Migrate voice features into the open-source LatinIME. This includes

the change to logging to remove any private dependencies and use
broadcast intents to VoiceSearch instead.

I have audited this code and it appears good to go for open-source,
but would appreciate a second pair of eyes.

Still to do after submitting this CL:

* Reintroduce Amith's memory leak fix (37557) which was the only CL
  added to LatinIME since the last merge over to the private copy.
* Make some changes to allow LatinIME to work without voice search
  installed. Currently I believe it will show the mic but fail if
  you press it. We need to base the visibility on the mic on the
  availability of the service.
* Fix this code to use the new Gservices framework, it's still trying
  to use the old one.
main
Mike LeBeau 2010-01-16 12:21:23 -08:00
parent 388ce92ab8
commit 466741d8a7
96 changed files with 3808 additions and 244 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 548 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 438 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

BIN
res/drawable-hdpi/mic_slash.png Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 681 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 398 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 309 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 483 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 859 B

BIN
res/drawable/cancel.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
res/drawable/caution.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
res/drawable/mic_slash.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

BIN
res/drawable/ok_cancel.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

BIN
res/drawable/working.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

View File

@ -0,0 +1,98 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
**
** Copyright 2009, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:background="@android:color/black"
android:paddingBottom="0dip"
android:paddingLeft="0dip"
android:paddingRight="0dip"
>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/main_image"
android:orientation="vertical"
android:background="@drawable/voice_ime_background"
android:scaleType="fitXY"
android:layout_width="match_parent"
android:layout_height="180dip"
android:paddingBottom="2dip"
android:paddingTop="2dip"
>
<TextView android:id="@+id/text"
android:text="@string/voice_initializing"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_marginTop="15dip"
android:textSize="28sp"
android:textColor="#ffffff"
android:layout_gravity="center_horizontal"
/>
<ImageView android:id="@+id/image"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_marginTop="20dip"
android:layout_gravity="center_horizontal"
android:src="@drawable/mic_slash"
/>
<ProgressBar android:id="@+id/progress"
android:layout_height="60dip"
android:layout_width="60dip"
android:layout_marginTop="20dip"
android:layout_gravity="center_horizontal"
android:visibility="gone"
android:indeterminate="true"
/>
</LinearLayout>
<LinearLayout android:id="@+id/button"
android:orientation="vertical"
android:background="@drawable/ok_cancel"
android:scaleType="fitXY"
android:layout_width="match_parent"
android:layout_height="42dip"
android:paddingLeft="1dip"
android:paddingRight="1dip"
>
<TextView android:id="@+id/button_text"
android:text="@string/cancel"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_marginTop="7dip"
android:textSize="19sp"
android:textColor="#ffffff"
android:layout_gravity="center_horizontal"
/>
</LinearLayout>
</LinearLayout>

View File

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
**
** Copyright 2009, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/keyboard_suggest_strip">
<!-- TODO: Use dark mic icon. -->
<ImageView android:id="@+id/image"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:paddingLeft="8dip"
android:paddingRight="8dip"
android:layout_gravity="center_horizontal"
android:src="@drawable/ic_suggest_strip_microphone"
/>
<TextView android:id="@+id/text"
android:text="@string/voice_punctuation_hint"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:paddingTop="2dip"
android:paddingRight="3dip"
android:textSize="13sp"
android:textColor="#888888"
android:layout_gravity="center_horizontal"
/>
</LinearLayout>

View File

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
**
** Copyright 2009, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/keyboard_suggest_strip"
android:gravity="center_horizontal"
android:paddingTop="2dip">
<TextView android:id="@+id/text"
android:text="@string/voice_swipe_hint"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:paddingTop="10dip"
android:paddingRight="6dip"
android:textSize="13sp"
android:textColor="#888888"
android:layout_gravity="center_horizontal"
/>
<ImageView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_gravity="center_horizontal"
android:src="@drawable/ic_suggest_strip_microphone"
/>
<ImageView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_gravity="center_horizontal"
android:src="@drawable/ic_suggest_strip_microphone_swipe"
/>
</LinearLayout>

View File

@ -47,12 +47,6 @@
<item msgid="1669461741568287396">"Základní"</item>
<item msgid="4894328801530136615">"Pokročilé"</item>
</string-array>
<string name="prediction_none" msgid="2472795101338047944">"0"</string>
<string name="prediction_basic" msgid="8407291081834155558">"1"</string>
<string name="prediction_full" msgid="3765102052052510268">"2"</string>
<!-- no translation found for prediction_modes_values:0 (579944677836100459) -->
<!-- no translation found for prediction_modes_values:1 (7214414132844804570) -->
<!-- no translation found for prediction_modes_values:2 (6678546276084314171) -->
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Uloženo"</string>
<string name="alternates_for_a" msgid="2566516493365324765">"áàâãäåæ"</string>
<string name="alternates_for_e" msgid="3900510936875547555">"éěèêë"</string>
@ -63,7 +57,6 @@
<string name="alternates_for_n" msgid="6257322556221886400">"ňñ"</string>
<string name="alternates_for_c" msgid="151699780720639892">"čç"</string>
<string name="alternates_for_y" msgid="1722776806607271199">"ýÿ"</string>
<string name="key_i" msgid="6483655742552255124">"i"</string>
<string name="tip_long_press" msgid="6101270866284343344">"Podržením klávesy zobrazíte diakritiku (ž, á atd.)"</string>
<string name="tip_dismiss" msgid="7585579046862204381">"Stisknutím klávesy Zpět ↶ můžete klávesnici kdykoli zavřít"</string>
<string name="tip_access_symbols" msgid="6344098517525531652">"Přístup k číslům a symbolům"</string>
@ -84,6 +77,30 @@
<string name="label_phone_key" msgid="4275497665515080551">"123"</string>
<string name="label_alpha_key" msgid="8864943487292437456">"ABC"</string>
<string name="label_alt_key" msgid="2846315350346694811">"Alt"</string>
<string name="voice_warning_title" msgid="4419354150908395008">"Hlasový vstup"</string>
<string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Pro váš jazyk aktuálně není hlasový vstup podporován, ale funguje v angličtině."</string>
<string name="voice_warning_may_not_understand" msgid="4611518823070986445">"Hlasový vstup je experimentální funkce, která využívá síťové rozpoznávání řeči společnosti Google."</string>
<string name="voice_warning_how_to_turn_off" msgid="5652369578498701761">"Chcete-li vypnout hlasový vstup, přejděte do nastavení klávesnice."</string>
<string name="voice_hint_dialog_message" msgid="6892342981545727994">"Chcete-li použít hlasový vstup, stiskněte tlačítko mikrofonu nebo přejeďte prstem přes klávesnici na obrazovce."</string>
<string name="voice_listening" msgid="467518160751321844">"Mluvte"</string>
<string name="voice_working" msgid="6666937792815731889">"Probíhá zpracování"</string>
<!-- no translation found for voice_initializing (661962047129906646) -->
<skip />
<string name="voice_error" msgid="5140896300312186162">"Chyba. Zkuste to prosím znovu."</string>
<string name="voice_network_error" msgid="6649556447401862563">"Připojení se nezdařilo."</string>
<string name="voice_too_much_speech" msgid="5746973620134227376">"Chyba, řeč je příliš dlouhá."</string>
<string name="voice_audio_error" msgid="5072707727016414454">"Problém se zvukem"</string>
<string name="voice_server_error" msgid="7807129913977261644">"Chyba serveru"</string>
<string name="voice_speech_timeout" msgid="8461817525075498795">"Nebyla detekována žádná řeč."</string>
<string name="voice_no_match" msgid="4285117547030179174">"Nebyly nalezeny žádné shody"</string>
<string name="voice_not_installed" msgid="5552450909753842415">"Hlasové vyhledávání není nainstalováno"</string>
<string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Nápověda:"</b>" Chcete-li aktivovat hlasový vstup, přejeďte prstem přes klávesnici."</string>
<string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Nápověda:"</b>" Příště zkuste vyslovit interpunkci, například „tečka“, „čárka“ nebo „otazník“."</string>
<string name="cancel" msgid="6830980399865683324">"Zrušit"</string>
<string name="ok" msgid="7898366843681727667">"OK"</string>
<string name="enable_voice" msgid="8299503298530853956">"Hlasový vstup"</string>
<string name="auto_submit" msgid="9151008027068358518">"Po hlasovém vstupu automaticky odeslat"</string>
<string name="auto_submit_summary" msgid="4961875269610384226">"Při vyhledávání nebo přechodu na další pole automaticky stisknout Enter."</string>
<string name="open_the_keyboard" msgid="2215920976029260466"><font size="17"><b>"Otevřete klávesnici"\n</b></font><font size="3">\n</font>"Dotkněte se jakéhokoli textového pole."</string>
<string name="close_the_keyboard" msgid="6251022259044940103"><font size="17"><b>"Zavřete klávesnici"\n</b></font><font size="3">\n</font>"Stiskněte klávesu Zpět."</string>
<string name="touch_and_hold" msgid="6154166367273010534"><font size="17"><b>"Přidržením klávesy zobrazte možnosti"\n</b></font><font size="3">\n</font>"Použijte interpunkční znaménka a diakritiku."</string>
@ -95,4 +112,5 @@
<string name="popular_domain_4" msgid="35359437471311470">".eu"</string>
<!-- no translation found for language_selection_title (530749890984542339) -->
<skip />
<string name="inputMethod" msgid="7854532062009028116">"Metoda zadávání dat"</string>
</resources>

View File

@ -47,12 +47,6 @@
<item msgid="1669461741568287396">"Grundlæggende"</item>
<item msgid="4894328801530136615">"Avanceret"</item>
</string-array>
<string name="prediction_none" msgid="2472795101338047944">"0"</string>
<string name="prediction_basic" msgid="8407291081834155558">"1"</string>
<string name="prediction_full" msgid="3765102052052510268">"2"</string>
<!-- no translation found for prediction_modes_values:0 (579944677836100459) -->
<!-- no translation found for prediction_modes_values:1 (7214414132844804570) -->
<!-- no translation found for prediction_modes_values:2 (6678546276084314171) -->
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: Gemt"</string>
<string name="alternates_for_a" msgid="2566516493365324765">"àáâãäåæ"</string>
<string name="alternates_for_e" msgid="3900510936875547555">"èéêë"</string>
@ -63,7 +57,6 @@
<string name="alternates_for_n" msgid="6257322556221886400">"ñ"</string>
<string name="alternates_for_c" msgid="151699780720639892">"ç"</string>
<string name="alternates_for_y" msgid="1722776806607271199">"ýÿ"</string>
<string name="key_i" msgid="6483655742552255124">"i"</string>
<string name="tip_long_press" msgid="6101270866284343344">"Hold en tast nede for at se accenter (ø, ö osv.)"</string>
<string name="tip_dismiss" msgid="7585579046862204381">"Tryk på tilbagetasten ↶ for når som helst at lukke for tastaturet"</string>
<string name="tip_access_symbols" msgid="6344098517525531652">"Få adgang til tal og symboler"</string>
@ -84,6 +77,30 @@
<string name="label_phone_key" msgid="4275497665515080551">"123"</string>
<string name="label_alpha_key" msgid="8864943487292437456">"ABC"</string>
<string name="label_alt_key" msgid="2846315350346694811">"ALT"</string>
<string name="voice_warning_title" msgid="4419354150908395008">"Stemmeinput"</string>
<string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Stemmeinput understøttes i øjeblikket ikke for dit sprog, men fungerer på engelsk."</string>
<string name="voice_warning_may_not_understand" msgid="4611518823070986445">"Stemme-input er en funktion på forsøgsbasis, som bruger Googles netværksstemmegenkendelse."</string>
<string name="voice_warning_how_to_turn_off" msgid="5652369578498701761">"Slå stemmeinput fra i indstillingerne for tastaturet."</string>
<string name="voice_hint_dialog_message" msgid="6892342981545727994">"For at bruge stemme-input skal du trykke på knappen mikrofon eller lade glide fingeren hen over skærmtastaturet."</string>
<string name="voice_listening" msgid="467518160751321844">"Tal nu"</string>
<string name="voice_working" msgid="6666937792815731889">"Arbejder"</string>
<!-- no translation found for voice_initializing (661962047129906646) -->
<skip />
<string name="voice_error" msgid="5140896300312186162">"Fejl. Prøv igen."</string>
<string name="voice_network_error" msgid="6649556447401862563">"Kunne ikke oprette forbindelse"</string>
<string name="voice_too_much_speech" msgid="5746973620134227376">"Fejl. For meget tale."</string>
<string name="voice_audio_error" msgid="5072707727016414454">"Lydproblem"</string>
<string name="voice_server_error" msgid="7807129913977261644">"Serverfejl"</string>
<string name="voice_speech_timeout" msgid="8461817525075498795">"Der høres ingen tale"</string>
<string name="voice_no_match" msgid="4285117547030179174">"Der blev ikke fundet nogen matches"</string>
<string name="voice_not_installed" msgid="5552450909753842415">"Stemmesøgning er ikke installeret"</string>
<string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Tip:"</b>" Glid hen over tastaturet for at tale"</string>
<string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Tip:"</b>" Næste gang kan du forsøge at sige tegnsætning, f.eks. \"punktum\", \"komma\" eller \"spørgsmålstegn\"."</string>
<string name="cancel" msgid="6830980399865683324">"Annuller"</string>
<string name="ok" msgid="7898366843681727667">"OK"</string>
<string name="enable_voice" msgid="8299503298530853956">"Stemmeinput"</string>
<string name="auto_submit" msgid="9151008027068358518">"Send automatisk efter stemme"</string>
<string name="auto_submit_summary" msgid="4961875269610384226">"Tryk automatisk på enter, når du søger eller går til det næste felt."</string>
<string name="open_the_keyboard" msgid="2215920976029260466"><font size="17"><b>"Åbn tastaturet"\n</b></font><font size="3">\n</font>"Tryk på et hvilket som helst tekstfelt."</string>
<string name="close_the_keyboard" msgid="6251022259044940103"><font size="17"><b>"Luk tastaturet"\n</b></font><font size="3">\n</font>"Tryk på Tilbagetasten."</string>
<string name="touch_and_hold" msgid="6154166367273010534"><font size="17"><b>"Tryk på og hold en tast nede for valgmuligheder"\n</b></font><font size="3">\n</font>"Få adgang til tegnsætning og accenter."</string>
@ -95,4 +112,5 @@
<string name="popular_domain_4" msgid="35359437471311470">".edu"</string>
<!-- no translation found for language_selection_title (530749890984542339) -->
<skip />
<string name="inputMethod" msgid="7854532062009028116">"Inputmetode"</string>
</resources>

View File

@ -47,12 +47,6 @@
<item msgid="1669461741568287396">"Standard"</item>
<item msgid="4894328801530136615">"Erweitert"</item>
</string-array>
<string name="prediction_none" msgid="2472795101338047944">"0"</string>
<string name="prediction_basic" msgid="8407291081834155558">"1"</string>
<string name="prediction_full" msgid="3765102052052510268">"2"</string>
<!-- no translation found for prediction_modes_values:0 (579944677836100459) -->
<!-- no translation found for prediction_modes_values:1 (7214414132844804570) -->
<!-- no translation found for prediction_modes_values:2 (6678546276084314171) -->
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Gespeichert"</string>
<string name="alternates_for_a" msgid="2566516493365324765">"ä"</string>
<string name="alternates_for_e" msgid="3900510936875547555">"èéêë"</string>
@ -63,7 +57,6 @@
<string name="alternates_for_n" msgid="6257322556221886400">"ñ"</string>
<string name="alternates_for_c" msgid="151699780720639892">"ç"</string>
<string name="alternates_for_y" msgid="1722776806607271199">"ýÿ"</string>
<string name="key_i" msgid="6483655742552255124">"i"</string>
<string name="tip_long_press" msgid="6101270866284343344">"Zur Anzeige von Umlauten (ä, ö usw.) Taste gedrückt halten"</string>
<string name="tip_dismiss" msgid="7585579046862204381">"Zum Schließen der Tastatur ↶ drücken"</string>
<string name="tip_access_symbols" msgid="6344098517525531652">"Auf Zahlen und Symbole zugreifen"</string>
@ -84,6 +77,30 @@
<string name="label_phone_key" msgid="4275497665515080551">"123"</string>
<string name="label_alpha_key" msgid="8864943487292437456">"ABC"</string>
<string name="label_alt_key" msgid="2846315350346694811">"ALT"</string>
<string name="voice_warning_title" msgid="4419354150908395008">"Spracheingabe"</string>
<string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Spracheingaben werden derzeit nicht für Ihre Sprache unterstützt, funktionieren jedoch in Englisch."</string>
<string name="voice_warning_may_not_understand" msgid="4611518823070986445">"Die Spracheingabe ist eine Funktion im Versuchsstadium, die die vernetzte Spracherkennung von Google verwendet."</string>
<string name="voice_warning_how_to_turn_off" msgid="5652369578498701761">"Wenn Sie die Spracheingabe deaktivieren möchten, rufen Sie die Tastatureinstellungen auf."</string>
<string name="voice_hint_dialog_message" msgid="6892342981545727994">"Um die Spracheingabe zu verwenden, drücken Sie den Mikrofonknopf oder ziehen Sie Ihren Finger über die Bildschirmtastatur."</string>
<string name="voice_listening" msgid="467518160751321844">"Jetzt sprechen"</string>
<string name="voice_working" msgid="6666937792815731889">"Vorgang läuft"</string>
<!-- no translation found for voice_initializing (661962047129906646) -->
<skip />
<string name="voice_error" msgid="5140896300312186162">"Fehler. Versuchen Sie es erneut.."</string>
<string name="voice_network_error" msgid="6649556447401862563">"Keine Verbindung"</string>
<string name="voice_too_much_speech" msgid="5746973620134227376">"Fehler Text zu lang"</string>
<string name="voice_audio_error" msgid="5072707727016414454">"Audio-Problem"</string>
<string name="voice_server_error" msgid="7807129913977261644">"Serverfehler"</string>
<string name="voice_speech_timeout" msgid="8461817525075498795">"Keine Sprache zu hören"</string>
<string name="voice_no_match" msgid="4285117547030179174">"Keine Übereinstimmungen gefunden"</string>
<string name="voice_not_installed" msgid="5552450909753842415">"Sprach-Suche nicht installiert"</string>
<string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Hinweis:"</b>" Ziehen Sie zum Sprechen den Finger über die Tastatur."</string>
<string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Hinweis:"</b>" Versuchen Sie beim nächsten Mal, Satzzeichen wie \"Punkt\", \"Komma\" oder \"Fragezeichen\" per Sprachbefehl einzugeben."</string>
<string name="cancel" msgid="6830980399865683324">"Abbrechen"</string>
<string name="ok" msgid="7898366843681727667">"OK"</string>
<string name="enable_voice" msgid="8299503298530853956">"Spracheingabe"</string>
<string name="auto_submit" msgid="9151008027068358518">"Nach Sprachaufnahme automatisch senden"</string>
<string name="auto_submit_summary" msgid="4961875269610384226">"Drücken Sie auf die Eingabetaste, wenn Sie einen Suchvorgang durchführen oder zum nächsten Feld wechseln."</string>
<string name="open_the_keyboard" msgid="2215920976029260466"><font size="17"><b>"Tastatur öffnen"\n</b></font><font size="3">\n</font>"Berühren Sie ein beliebiges Textfeld."</string>
<string name="close_the_keyboard" msgid="6251022259044940103"><font size="17"><b>"Tastatur schließen"\n</b></font><font size="3">\n</font>"Drücken Sie die Taste \"Zurück\"."</string>
<string name="touch_and_hold" msgid="6154166367273010534"><font size="17"><b>"Eine Taste für Optionen berühren und gedrückt halten"\n</b></font><font size="3">\n</font>"Greifen Sie auf Satzzeichen und Akzente zu."</string>
@ -95,4 +112,5 @@
<string name="popular_domain_4" msgid="35359437471311470">".edu"</string>
<!-- no translation found for language_selection_title (530749890984542339) -->
<skip />
<string name="inputMethod" msgid="7854532062009028116">"Eingabemethode"</string>
</resources>

View File

@ -47,12 +47,6 @@
<item msgid="1669461741568287396">"Βασική"</item>
<item msgid="4894328801530136615">"Σύνθετη"</item>
</string-array>
<string name="prediction_none" msgid="2472795101338047944">"0"</string>
<string name="prediction_basic" msgid="8407291081834155558">"1"</string>
<string name="prediction_full" msgid="3765102052052510268">"2"</string>
<!-- no translation found for prediction_modes_values:0 (579944677836100459) -->
<!-- no translation found for prediction_modes_values:1 (7214414132844804570) -->
<!-- no translation found for prediction_modes_values:2 (6678546276084314171) -->
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Αποθηκεύτηκε"</string>
<string name="alternates_for_a" msgid="2566516493365324765">"àáâãäåæ"</string>
<string name="alternates_for_e" msgid="3900510936875547555">"èéêë"</string>
@ -63,7 +57,6 @@
<string name="alternates_for_n" msgid="6257322556221886400">"ñ"</string>
<string name="alternates_for_c" msgid="151699780720639892">"ç"</string>
<string name="alternates_for_y" msgid="1722776806607271199">"ýÿ"</string>
<string name="key_i" msgid="6483655742552255124">"i"</string>
<string name="tip_long_press" msgid="6101270866284343344">"Κρατήστε πατημένο ένα πλήκτρο για να δείτε τους τονισμένους χαρακτήρες (ø, ö, κ.τ.λ.)"</string>
<string name="tip_dismiss" msgid="7585579046862204381">"Πατήστε το πλήκτρο Πίσω ↶ για να κλείσετε το πληκτρολόγιο ανά πάσα στιγμή"</string>
<string name="tip_access_symbols" msgid="6344098517525531652">"Πρόσβαση σε αριθμούς και σύμβολα"</string>
@ -84,6 +77,30 @@
<string name="label_phone_key" msgid="4275497665515080551">"123"</string>
<string name="label_alpha_key" msgid="8864943487292437456">"ΑΒΓ"</string>
<string name="label_alt_key" msgid="2846315350346694811">"ALT"</string>
<string name="voice_warning_title" msgid="4419354150908395008">"Φωνητική είσοδος"</string>
<string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Η φωνητική είσοδος δεν υποστηρίζεται αυτή τη στιγμή για τη γλώσσα σας, ωστόσο λειτουργεί στα Αγγλικά."</string>
<string name="voice_warning_may_not_understand" msgid="4611518823070986445">"Οι φωνητικές εντολές είναι μια πειραματική λειτουργία, η οποία χρησιμοποιεί τη δικτυακή αναγνώριση ομιλίας της Google."</string>
<string name="voice_warning_how_to_turn_off" msgid="5652369578498701761">"Για να απενεργοποιήσετε τη φωνητική είσοδο, μεταβείτε στις ρυθμίσεις πληκτρολογίου."</string>
<string name="voice_hint_dialog_message" msgid="6892342981545727994">"Για να χρησιμοποιήσετε τις φωνητικές εντολές, πιέστε το κουμπί μικροφώνου ή σύρετε το δάχτυλό σας κατά μήκος του πληκτρολογίου της οθόνης."</string>
<string name="voice_listening" msgid="467518160751321844">"Μιλήστε τώρα"</string>
<string name="voice_working" msgid="6666937792815731889">"Σε λειτουργία"</string>
<!-- no translation found for voice_initializing (661962047129906646) -->
<skip />
<string name="voice_error" msgid="5140896300312186162">"Σφάλμα. Δοκιμάστε ξανά."</string>
<string name="voice_network_error" msgid="6649556447401862563">"Δεν ήταν δυνατή η σύνδεση"</string>
<string name="voice_too_much_speech" msgid="5746973620134227376">"Σφάλμα, πολλές λέξεις."</string>
<string name="voice_audio_error" msgid="5072707727016414454">"Πρόβλημα ήχου"</string>
<string name="voice_server_error" msgid="7807129913977261644">"Σφάλμα διακομιστή"</string>
<string name="voice_speech_timeout" msgid="8461817525075498795">"Δεν ακούγεται ομιλία"</string>
<string name="voice_no_match" msgid="4285117547030179174">"Δεν βρέθηκε καμία αντιστοίχιση"</string>
<string name="voice_not_installed" msgid="5552450909753842415">"Η Αναζήτηση με φωνή δεν εγκαταστάθηκε"</string>
<string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Υπόδειξη:"</b>" Σύρετε κατά μήκος του πληκτρολογίου για να μιλήσετε"</string>
<string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Υπόδειξη:"</b>" Την επόμενη φορά, προσπαθήστε να προφέρετε σημεία στίξης, όπως \"τελεία\", \"κόμμα\" ή \"ερωτηματικό\"."</string>
<string name="cancel" msgid="6830980399865683324">"Ακύρωση"</string>
<string name="ok" msgid="7898366843681727667">"ΟΚ"</string>
<string name="enable_voice" msgid="8299503298530853956">"Φωνητική είσοδος"</string>
<string name="auto_submit" msgid="9151008027068358518">"Αυτόματη υποβολή μετά από ήχο"</string>
<string name="auto_submit_summary" msgid="4961875269610384226">"Πατήστε enter αυτόματα κατά την αναζήτηση ή τη μετάβαση στο επόμενο πεδίο."</string>
<string name="open_the_keyboard" msgid="2215920976029260466"><font size="17"><b>"Ανοίξτε το πληκτρολόγιο"\n</b></font><font size="3">\n</font>"Αγγίξτε οποιοδήποτε πεδίο κειμένου."</string>
<string name="close_the_keyboard" msgid="6251022259044940103"><font size="17"><b>"Κλείστε το πληκτρολόγιο"\n</b></font><font size="3">\n</font>"Πατήστε το πλήκτρο Πίσω."</string>
<string name="touch_and_hold" msgid="6154166367273010534"><font size="17"><b>"Αγγίξτε και κρατήστε ένα πλήκτρο για ορισμό επιλογών"\n</b></font><font size="3">\n</font>"Πρόσβαση στα σημεία στίξης και τονισμού."</string>
@ -95,4 +112,5 @@
<string name="popular_domain_4" msgid="35359437471311470">".edu"</string>
<!-- no translation found for language_selection_title (530749890984542339) -->
<skip />
<string name="inputMethod" msgid="7854532062009028116">"Μέθοδος εισόδου"</string>
</resources>

View File

@ -47,12 +47,6 @@
<item msgid="1669461741568287396">"Básico"</item>
<item msgid="4894328801530136615">"Avanzado"</item>
</string-array>
<string name="prediction_none" msgid="2472795101338047944">"0"</string>
<string name="prediction_basic" msgid="8407291081834155558">"1"</string>
<string name="prediction_full" msgid="3765102052052510268">"2"</string>
<!-- no translation found for prediction_modes_values:0 (579944677836100459) -->
<!-- no translation found for prediction_modes_values:1 (7214414132844804570) -->
<!-- no translation found for prediction_modes_values:2 (6678546276084314171) -->
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: guardada"</string>
<string name="alternates_for_a" msgid="2566516493365324765">"àáâãäåæ"</string>
<string name="alternates_for_e" msgid="3900510936875547555">"èéêë"</string>
@ -63,7 +57,6 @@
<string name="alternates_for_n" msgid="6257322556221886400">"ñ"</string>
<string name="alternates_for_c" msgid="151699780720639892">"ç"</string>
<string name="alternates_for_y" msgid="1722776806607271199">"ýÿ"</string>
<string name="key_i" msgid="6483655742552255124">"i"</string>
<string name="tip_long_press" msgid="6101270866284343344">"Mantén una tecla presionada para ver los acentos (ø, ö, etc.)"</string>
<string name="tip_dismiss" msgid="7585579046862204381">"Pulsa la tecla hacia atrás ↶ para cerrar el teclado en cualquier momento"</string>
<string name="tip_access_symbols" msgid="6344098517525531652">"Acceder a números y símbolos"</string>
@ -84,6 +77,30 @@
<string name="label_phone_key" msgid="4275497665515080551">"123"</string>
<string name="label_alpha_key" msgid="8864943487292437456">"ABC"</string>
<string name="label_alt_key" msgid="2846315350346694811">"ALT"</string>
<string name="voice_warning_title" msgid="4419354150908395008">"Entrada por voz"</string>
<string name="voice_warning_locale_not_supported" msgid="637923019716442333">"La entrada por voz no está admitida en tu idioma, pero sí funciona en inglés."</string>
<string name="voice_warning_may_not_understand" msgid="4611518823070986445">"La entrada por voz es una característica experimental que utiliza la red de reconocimiento de voz de Google."</string>
<string name="voice_warning_how_to_turn_off" msgid="5652369578498701761">"Para desactivar la entrada por voz, ve a configuración del teclado."</string>
<string name="voice_hint_dialog_message" msgid="6892342981545727994">"Para realizar entrada por voz, presiona el botón del micrófono o desliza tus dedos por el teclado en pantalla."</string>
<string name="voice_listening" msgid="467518160751321844">"Habla ahora"</string>
<string name="voice_working" msgid="6666937792815731889">"Procesando"</string>
<!-- no translation found for voice_initializing (661962047129906646) -->
<skip />
<string name="voice_error" msgid="5140896300312186162">"Error. Vuelve a intentarlo."</string>
<string name="voice_network_error" msgid="6649556447401862563">"No se pudo establecer la conexión."</string>
<string name="voice_too_much_speech" msgid="5746973620134227376">"Error, demasiado discurso."</string>
<string name="voice_audio_error" msgid="5072707727016414454">"Problema de audio"</string>
<string name="voice_server_error" msgid="7807129913977261644">"Error del servidor"</string>
<string name="voice_speech_timeout" msgid="8461817525075498795">"No se oyó la voz"</string>
<string name="voice_no_match" msgid="4285117547030179174">"No se encontraron coincidencias"</string>
<string name="voice_not_installed" msgid="5552450909753842415">"Búsqueda por voz no instalada"</string>
<string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Sugerencia:"</b>" Deslizar en el teclado para hablar"</string>
<string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Sugerencia:"</b>" La próxima vez intenta decir la puntuación como \"punto\", \"coma\" o \"signo de pregunta\"."</string>
<string name="cancel" msgid="6830980399865683324">"Cancelar"</string>
<string name="ok" msgid="7898366843681727667">"Aceptar"</string>
<string name="enable_voice" msgid="8299503298530853956">"Entrada por voz"</string>
<string name="auto_submit" msgid="9151008027068358518">"Enviar automáticamente después del audio"</string>
<string name="auto_submit_summary" msgid="4961875269610384226">"Presionar automáticamente Ingresar al buscar o ir al campo siguiente."</string>
<string name="open_the_keyboard" msgid="2215920976029260466"><font size="17"><b>"Abrir el teclado"\n</b></font><font size="3">\n</font>"Tocar cualquier campo de texto."</string>
<string name="close_the_keyboard" msgid="6251022259044940103"><font size="17"><b>"Cerrar el teclado"\n</b></font><font size="3">\n</font>"Presionar la tecla Atrás."</string>
<string name="touch_and_hold" msgid="6154166367273010534"><font size="17"><b>"Tocar &amp; y mantener presionada una tecla para las opciones"\n</b></font><font size="3">\n</font>"Acceder a puntuación y acentos."</string>
@ -95,4 +112,5 @@
<string name="popular_domain_4" msgid="35359437471311470">".edu"</string>
<!-- no translation found for language_selection_title (530749890984542339) -->
<skip />
<string name="inputMethod" msgid="7854532062009028116">"Método de entrada"</string>
</resources>

View File

@ -47,12 +47,6 @@
<item msgid="1669461741568287396">"Básico"</item>
<item msgid="4894328801530136615">"Avanzado"</item>
</string-array>
<string name="prediction_none" msgid="2472795101338047944">"0"</string>
<string name="prediction_basic" msgid="8407291081834155558">"1"</string>
<string name="prediction_full" msgid="3765102052052510268">"2"</string>
<!-- no translation found for prediction_modes_values:0 (579944677836100459) -->
<!-- no translation found for prediction_modes_values:1 (7214414132844804570) -->
<!-- no translation found for prediction_modes_values:2 (6678546276084314171) -->
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Guardada"</string>
<string name="alternates_for_a" msgid="2566516493365324765">"á"</string>
<string name="alternates_for_e" msgid="3900510936875547555">"é"</string>
@ -63,7 +57,6 @@
<string name="alternates_for_n" msgid="6257322556221886400">"ñ"</string>
<string name="alternates_for_c" msgid="151699780720639892">"ç"</string>
<string name="alternates_for_y" msgid="1722776806607271199">"ýÿ"</string>
<string name="key_i" msgid="6483655742552255124">"i"</string>
<string name="tip_long_press" msgid="6101270866284343344">"Mantén pulsada una tecla para ver los caracteres acentuados (ø, ö, etc.)."</string>
<string name="tip_dismiss" msgid="7585579046862204381">"Pulsa la tecla \"Atrás\" ↶ para cerrar el teclado en cualquier momento."</string>
<string name="tip_access_symbols" msgid="6344098517525531652">"Acceso a números y símbolos"</string>
@ -84,6 +77,30 @@
<string name="label_phone_key" msgid="4275497665515080551">"123"</string>
<string name="label_alpha_key" msgid="8864943487292437456">"ABC"</string>
<string name="label_alt_key" msgid="2846315350346694811">"ALT"</string>
<string name="voice_warning_title" msgid="4419354150908395008">"Introducción de voz"</string>
<string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Actualmente la introducción de voz no está disponible en tu idioma, pero se puede utilizar en inglés."</string>
<string name="voice_warning_may_not_understand" msgid="4611518823070986445">"La introducción de voz es una función en fase experimental que utiliza la tecnología de reconocimiento de voz en red de Google."</string>
<string name="voice_warning_how_to_turn_off" msgid="5652369578498701761">"Para desactivar la función de introducción de voz, accede a la configuración del teclado."</string>
<string name="voice_hint_dialog_message" msgid="6892342981545727994">"Para utilizar la función de introducción de voz, pulsa el botón de micrófono o desliza el dedo por el teclado en pantalla."</string>
<string name="voice_listening" msgid="467518160751321844">"Hablar ahora"</string>
<string name="voice_working" msgid="6666937792815731889">"Trabajando"</string>
<!-- no translation found for voice_initializing (661962047129906646) -->
<skip />
<string name="voice_error" msgid="5140896300312186162">"Se ha producido un error. Inténtalo de nuevo."</string>
<string name="voice_network_error" msgid="6649556447401862563">"No se ha podido establecer conexión."</string>
<string name="voice_too_much_speech" msgid="5746973620134227376">"Se ha producido un error debido a un exceso de introducción de datos de voz."</string>
<string name="voice_audio_error" msgid="5072707727016414454">"Problema de audio"</string>
<string name="voice_server_error" msgid="7807129913977261644">"Error del servidor"</string>
<string name="voice_speech_timeout" msgid="8461817525075498795">"Ninguna conversación escuchada"</string>
<string name="voice_no_match" msgid="4285117547030179174">"No se ha encontrado ninguna coincidencia."</string>
<string name="voice_not_installed" msgid="5552450909753842415">"La búsqueda por voz no está instalada."</string>
<string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Sugerencia:"</b>" muévete por el teclado para hablar."</string>
<string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Sugerencia:"</b>" la próxima vez, prueba a indicar signos de puntuación como, por ejemplo, \"punto\", \"coma\" o \"signo de interrogación\"."</string>
<string name="cancel" msgid="6830980399865683324">"Cancelar"</string>
<string name="ok" msgid="7898366843681727667">"Aceptar"</string>
<string name="enable_voice" msgid="8299503298530853956">"Introducción de voz"</string>
<string name="auto_submit" msgid="9151008027068358518">"Enviar automáticamente después de la introducción de voz"</string>
<string name="auto_submit_summary" msgid="4961875269610384226">"Pulsar Intro automáticamente al buscar o al pasar al siguiente campo"</string>
<string name="open_the_keyboard" msgid="2215920976029260466"><font size="17"><b>"Abrir el teclado"\n</b></font><font size="3">\n</font>"Pulsa cualquier campo de texto."</string>
<string name="close_the_keyboard" msgid="6251022259044940103"><font size="17"><b>"Cerrar el teclado"\n</b></font><font size="3">\n</font>"Pulsa la tecla \"Atrás\"."</string>
<string name="touch_and_hold" msgid="6154166367273010534"><font size="17"><b>"Mantén pulsada una tecla para acceder a las opciones."\n</b></font><font size="3">\n</font>"Accede a los signos de puntuación y a los acentos."</string>
@ -95,4 +112,5 @@
<string name="popular_domain_4" msgid="35359437471311470">".edu"</string>
<!-- no translation found for language_selection_title (530749890984542339) -->
<skip />
<string name="inputMethod" msgid="7854532062009028116">"Método de introducción de texto"</string>
</resources>

View File

@ -47,12 +47,6 @@
<item msgid="1669461741568287396">"Simple"</item>
<item msgid="4894328801530136615">"Avancé"</item>
</string-array>
<string name="prediction_none" msgid="2472795101338047944">"0"</string>
<string name="prediction_basic" msgid="8407291081834155558">"1"</string>
<string name="prediction_full" msgid="3765102052052510268">"2"</string>
<!-- no translation found for prediction_modes_values:0 (579944677836100459) -->
<!-- no translation found for prediction_modes_values:1 (7214414132844804570) -->
<!-- no translation found for prediction_modes_values:2 (6678546276084314171) -->
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : enregistré"</string>
<string name="alternates_for_a" msgid="2566516493365324765">"àáâãäåæ"</string>
<string name="alternates_for_e" msgid="3900510936875547555">"èéêë"</string>
@ -63,7 +57,6 @@
<string name="alternates_for_n" msgid="6257322556221886400">"ñ"</string>
<string name="alternates_for_c" msgid="151699780720639892">"ç"</string>
<string name="alternates_for_y" msgid="1722776806607271199">"ýÿ"</string>
<string name="key_i" msgid="6483655742552255124">"i"</string>
<string name="tip_long_press" msgid="6101270866284343344">"Maintenir une touche enfoncée pour afficher les accents (à, é, etc.)"</string>
<string name="tip_dismiss" msgid="7585579046862204381">"Appuyez sur la touche Retour ↶ pour fermer le clavier à tout moment."</string>
<string name="tip_access_symbols" msgid="6344098517525531652">"Accéder aux chiffres et symboles"</string>
@ -84,6 +77,30 @@
<string name="label_phone_key" msgid="4275497665515080551">"123"</string>
<string name="label_alpha_key" msgid="8864943487292437456">"ABC"</string>
<string name="label_alt_key" msgid="2846315350346694811">"ALT"</string>
<string name="voice_warning_title" msgid="4419354150908395008">"Saisie vocale"</string>
<string name="voice_warning_locale_not_supported" msgid="637923019716442333">"La saisie vocale n\'est pas encore prise en charge pour votre langue, mais elle fonctionne en anglais."</string>
<string name="voice_warning_may_not_understand" msgid="4611518823070986445">"La saisie vocale est une fonctionnalité expérimentale qui fait appel à la reconnaissance vocale en réseau de Google."</string>
<string name="voice_warning_how_to_turn_off" msgid="5652369578498701761">"Pour désactiver la saisie vocale, accédez aux paramètres du clavier."</string>
<string name="voice_hint_dialog_message" msgid="6892342981545727994">"Pour utiliser la saisie vocale, appuyez sur la touche du microphone ou faites glisser votre doigt sur le clavier à l\'écran."</string>
<string name="voice_listening" msgid="467518160751321844">"Parlez maintenant"</string>
<string name="voice_working" msgid="6666937792815731889">"Traitement en cours"</string>
<!-- no translation found for voice_initializing (661962047129906646) -->
<skip />
<string name="voice_error" msgid="5140896300312186162">"Erreur. Veuillez réessayer."</string>
<string name="voice_network_error" msgid="6649556447401862563">"Connexion impossible"</string>
<string name="voice_too_much_speech" msgid="5746973620134227376">"Erreur, discours trop long."</string>
<string name="voice_audio_error" msgid="5072707727016414454">"Problème audio"</string>
<string name="voice_server_error" msgid="7807129913977261644">"Erreur serveur"</string>
<string name="voice_speech_timeout" msgid="8461817525075498795">"Aucune requête vocale détectée"</string>
<string name="voice_no_match" msgid="4285117547030179174">"Aucune correspondance n\'a été trouvée."</string>
<string name="voice_not_installed" msgid="5552450909753842415">"Recherche vocale non installée"</string>
<string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Astuce :"</b>" Faites glisser votre doigt sur le clavier pour parler."</string>
<string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Astuce :"</b>" La prochaine fois, essayez de prononcer la ponctuation, en énonçant des termes tels que \"point\", \"virgule\" ou \"point d\'interrogation\"."</string>
<string name="cancel" msgid="6830980399865683324">"Annuler"</string>
<string name="ok" msgid="7898366843681727667">"OK"</string>
<string name="enable_voice" msgid="8299503298530853956">"Saisie vocale"</string>
<string name="auto_submit" msgid="9151008027068358518">"Envoi automatique après la saisie vocale"</string>
<string name="auto_submit_summary" msgid="4961875269610384226">"Appuyez automatiquement sur Entrée pour effectuer une recherche ou accéder au champ suivant."</string>
<string name="open_the_keyboard" msgid="2215920976029260466"><font size="17"><b>"Ouvrir le clavier"\n</b></font><font size="3">\n</font>"Appuyez sur un champ de texte."</string>
<string name="close_the_keyboard" msgid="6251022259044940103"><font size="17"><b>"Fermer le clavier"\n</b></font><font size="3">\n</font>"Appuyez sur la touche Retour."</string>
<string name="touch_and_hold" msgid="6154166367273010534"><font size="17"><b>"Appuyer sur une touche de manière prolongée pour accéder aux options"\n</b></font><font size="3">\n</font>"Accédez aux signes de ponctuation et aux accents."</string>
@ -95,4 +112,5 @@
<string name="popular_domain_4" msgid="35359437471311470">".edu"</string>
<!-- no translation found for language_selection_title (530749890984542339) -->
<skip />
<string name="inputMethod" msgid="7854532062009028116">"Mode de saisie"</string>
</resources>

View File

@ -47,12 +47,6 @@
<item msgid="1669461741568287396">"Base"</item>
<item msgid="4894328801530136615">"Avanzate"</item>
</string-array>
<string name="prediction_none" msgid="2472795101338047944">"0"</string>
<string name="prediction_basic" msgid="8407291081834155558">"1"</string>
<string name="prediction_full" msgid="3765102052052510268">"2"</string>
<!-- no translation found for prediction_modes_values:0 (579944677836100459) -->
<!-- no translation found for prediction_modes_values:1 (7214414132844804570) -->
<!-- no translation found for prediction_modes_values:2 (6678546276084314171) -->
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : parola salvata"</string>
<string name="alternates_for_a" msgid="2566516493365324765">"àá"</string>
<string name="alternates_for_e" msgid="3900510936875547555">"èé"</string>
@ -63,7 +57,6 @@
<string name="alternates_for_n" msgid="6257322556221886400">"ñ"</string>
<string name="alternates_for_c" msgid="151699780720639892">"ç"</string>
<string name="alternates_for_y" msgid="1722776806607271199">"ýÿ"</string>
<string name="key_i" msgid="6483655742552255124">"i"</string>
<string name="tip_long_press" msgid="6101270866284343344">"Tieni premuto un tasto per vedere le lettere con segni diacritici (ø, ö etc.)"</string>
<string name="tip_dismiss" msgid="7585579046862204381">"Premi il tasto Indietro ↶ per chiudere la tastiera"</string>
<string name="tip_access_symbols" msgid="6344098517525531652">"Accedi a numeri e simboli"</string>
@ -84,6 +77,30 @@
<string name="label_phone_key" msgid="4275497665515080551">"123"</string>
<string name="label_alpha_key" msgid="8864943487292437456">"ABC"</string>
<string name="label_alt_key" msgid="2846315350346694811">"ALT"</string>
<string name="voice_warning_title" msgid="4419354150908395008">"Comandi vocali"</string>
<string name="voice_warning_locale_not_supported" msgid="637923019716442333">"I comandi vocali non sono attualmente supportati per la tua lingua ma funzionano in inglese."</string>
<string name="voice_warning_may_not_understand" msgid="4611518823070986445">"I comandi vocali sono una funzione sperimentale che utilizza il riconoscimento vocale in rete di Google."</string>
<string name="voice_warning_how_to_turn_off" msgid="5652369578498701761">"Per disattivare i comandi vocali, vai alle impostazioni della tastiera."</string>
<string name="voice_hint_dialog_message" msgid="6892342981545727994">"Per utilizzare i comandi vocali, premi il pulsante del microfono o fai scorrere il dito sulla tastiera sullo schermo."</string>
<string name="voice_listening" msgid="467518160751321844">"Parla ora"</string>
<string name="voice_working" msgid="6666937792815731889">"Elaborazione in corso"</string>
<!-- no translation found for voice_initializing (661962047129906646) -->
<skip />
<string name="voice_error" msgid="5140896300312186162">"Errore. Riprova più tardi."</string>
<string name="voice_network_error" msgid="6649556447401862563">"Impossibile connettersi."</string>
<string name="voice_too_much_speech" msgid="5746973620134227376">"Errore: conversazione troppo lunga."</string>
<string name="voice_audio_error" msgid="5072707727016414454">"Problema audio"</string>
<string name="voice_server_error" msgid="7807129913977261644">"Errore del server"</string>
<string name="voice_speech_timeout" msgid="8461817525075498795">"Nessuna frase vocale rilevata"</string>
<string name="voice_no_match" msgid="4285117547030179174">"Nessuna corrispondenza trovata"</string>
<string name="voice_not_installed" msgid="5552450909753842415">"Ricerca vocale non installata"</string>
<string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Suggerimento."</b>" Fai scorrere il dito sulla tastiera per parlare"</string>
<string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Suggerimento."</b>" La prossima volta, prova a pronunciare termini relativi alla punteggiatura come \"punto\", \"virgola\" o \"punto di domanda\"."</string>
<string name="cancel" msgid="6830980399865683324">"Annulla"</string>
<string name="ok" msgid="7898366843681727667">"OK"</string>
<string name="enable_voice" msgid="8299503298530853956">"Comandi vocali"</string>
<string name="auto_submit" msgid="9151008027068358518">"Invia automaticamente dopo comando vocale"</string>
<string name="auto_submit_summary" msgid="4961875269610384226">"Premi automaticamente \"Invio\" durante una ricerca o un passaggio al campo successivo."</string>
<string name="open_the_keyboard" msgid="2215920976029260466"><font size="17"><b>"Apertura tastiera"\n</b></font><font size="3">\n</font>"Tocca qualsiasi campo di testo."</string>
<string name="close_the_keyboard" msgid="6251022259044940103"><font size="17"><b>"Chiusura tastiera"\n</b></font><font size="3">\n</font>"Premi il tasto Indietro."</string>
<string name="touch_and_hold" msgid="6154166367273010534"><font size="17"><b>"Tocca e tieni premuto un tasto per le opzioni"\n</b></font><font size="3">\n</font>"Accesso a punteggiatura e accenti."</string>
@ -95,4 +112,5 @@
<string name="popular_domain_4" msgid="35359437471311470">".edu"</string>
<!-- no translation found for language_selection_title (530749890984542339) -->
<skip />
<string name="inputMethod" msgid="7854532062009028116">"Metodo inserimento"</string>
</resources>

View File

@ -47,12 +47,6 @@
<item msgid="1669461741568287396">"基本"</item>
<item msgid="4894328801530136615">"高度"</item>
</string-array>
<string name="prediction_none" msgid="2472795101338047944">"0"</string>
<string name="prediction_basic" msgid="8407291081834155558">"1"</string>
<string name="prediction_full" msgid="3765102052052510268">"2"</string>
<!-- no translation found for prediction_modes_values:0 (579944677836100459) -->
<!-- no translation found for prediction_modes_values:1 (7214414132844804570) -->
<!-- no translation found for prediction_modes_values:2 (6678546276084314171) -->
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>:保存しました"</string>
<string name="alternates_for_a" msgid="2566516493365324765">"àáâãäåæ"</string>
<string name="alternates_for_e" msgid="3900510936875547555">"èéêë"</string>
@ -63,7 +57,6 @@
<string name="alternates_for_n" msgid="6257322556221886400">"ñ"</string>
<string name="alternates_for_c" msgid="151699780720639892">"ç"</string>
<string name="alternates_for_y" msgid="1722776806607271199">"ýÿ"</string>
<string name="key_i" msgid="6483655742552255124">"i"</string>
<string name="tip_long_press" msgid="6101270866284343344">"キー長押しでアクセント文字を表示(ø、öなど)"</string>
<string name="tip_dismiss" msgid="7585579046862204381">"戻るキーでキーボードを閉じます"</string>
<string name="tip_access_symbols" msgid="6344098517525531652">"数字と記号"</string>
@ -84,6 +77,30 @@
<string name="label_phone_key" msgid="4275497665515080551">"123"</string>
<string name="label_alpha_key" msgid="8864943487292437456">"ABC"</string>
<string name="label_alt_key" msgid="2846315350346694811">"ALT"</string>
<string name="voice_warning_title" msgid="4419354150908395008">"音声入力"</string>
<string name="voice_warning_locale_not_supported" msgid="637923019716442333">"音声入力は現在英語には対応していますが、日本語には対応していません。"</string>
<string name="voice_warning_may_not_understand" msgid="4611518823070986445">"音声入力はGoogleのネットワーク音声認識技術を利用した試験段階の機能です。"</string>
<string name="voice_warning_how_to_turn_off" msgid="5652369578498701761">"音声入力をOFFにするには、キーボードの設定を開きます。"</string>
<string name="voice_hint_dialog_message" msgid="6892342981545727994">"音声入力するには、マイクボタンを押すか画面キーボードをスワイプしてください。"</string>
<string name="voice_listening" msgid="467518160751321844">"お話しください"</string>
<string name="voice_working" msgid="6666937792815731889">"処理中"</string>
<!-- no translation found for voice_initializing (661962047129906646) -->
<skip />
<string name="voice_error" msgid="5140896300312186162">"エラーです。もう一度お試しください。"</string>
<string name="voice_network_error" msgid="6649556447401862563">"接続できませんでした"</string>
<string name="voice_too_much_speech" msgid="5746973620134227376">"音声が長すぎてエラーになりました。"</string>
<string name="voice_audio_error" msgid="5072707727016414454">"オーディオエラー"</string>
<string name="voice_server_error" msgid="7807129913977261644">"サーバーエラー"</string>
<string name="voice_speech_timeout" msgid="8461817525075498795">"音声が聞き取れません"</string>
<string name="voice_no_match" msgid="4285117547030179174">"該当なし"</string>
<string name="voice_not_installed" msgid="5552450909753842415">"Voice Searchはインストールされていません"</string>
<string name="voice_swipe_hint" msgid="6943546180310682021"><b>"ヒント:"</b>" 音声入力するにはキーボードをスワイプします"</string>
<string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"ヒント:"</b>" 次回は句読点として「period」、「comma」、「question mark」などの音声入力を試してみてください。"</string>
<string name="cancel" msgid="6830980399865683324">"キャンセル"</string>
<string name="ok" msgid="7898366843681727667">"OK"</string>
<string name="enable_voice" msgid="8299503298530853956">"音声入力"</string>
<string name="auto_submit" msgid="9151008027068358518">"入力後に自動送信する"</string>
<string name="auto_submit_summary" msgid="4961875269610384226">"検索または次のフィールドに進む際、Enterキーが自動的に押されます。"</string>
<string name="open_the_keyboard" msgid="2215920976029260466"><font size="17"><b>"キーボードを開く"\n</b></font><font size="3">\n</font>"テキストフィールドをタップします。"</string>
<string name="close_the_keyboard" msgid="6251022259044940103"><font size="17"><b>"キーボードを閉じる"\n</b></font><font size="3">\n</font>"[戻る]キーを押します。"</string>
<string name="touch_and_hold" msgid="6154166367273010534"><font size="17"><b>"キーを長押しして選択する"\n</b></font><font size="3">\n</font>"句読点キーとアクセント文字を表示します。"</string>
@ -95,4 +112,5 @@
<string name="popular_domain_4" msgid="35359437471311470">".edu"</string>
<!-- no translation found for language_selection_title (530749890984542339) -->
<skip />
<string name="inputMethod" msgid="7854532062009028116">"入力方法"</string>
</resources>

View File

@ -47,12 +47,6 @@
<item msgid="1669461741568287396">"기본"</item>
<item msgid="4894328801530136615">"고급"</item>
</string-array>
<string name="prediction_none" msgid="2472795101338047944">"0"</string>
<string name="prediction_basic" msgid="8407291081834155558">"1"</string>
<string name="prediction_full" msgid="3765102052052510268">"2"</string>
<!-- no translation found for prediction_modes_values:0 (579944677836100459) -->
<!-- no translation found for prediction_modes_values:1 (7214414132844804570) -->
<!-- no translation found for prediction_modes_values:2 (6678546276084314171) -->
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : 저장됨"</string>
<string name="alternates_for_a" msgid="2566516493365324765">"àáâãäåæ"</string>
<string name="alternates_for_e" msgid="3900510936875547555">"èéêë"</string>
@ -63,7 +57,6 @@
<string name="alternates_for_n" msgid="6257322556221886400">"ñ"</string>
<string name="alternates_for_c" msgid="151699780720639892">"ç"</string>
<string name="alternates_for_y" msgid="1722776806607271199">"ýÿ"</string>
<string name="key_i" msgid="6483655742552255124">"i"</string>
<string name="tip_long_press" msgid="6101270866284343344">"키를 길게 누르면 악센트(ø, ö 등)가 표시됩니다."</string>
<string name="tip_dismiss" msgid="7585579046862204381">"키보드를 닫으려면 언제든지 뒤로 키(↶)를 누르세요."</string>
<string name="tip_access_symbols" msgid="6344098517525531652">"숫자 및 기호 액세스"</string>
@ -84,6 +77,30 @@
<string name="label_phone_key" msgid="4275497665515080551">"123"</string>
<string name="label_alpha_key" msgid="8864943487292437456">"ABC"</string>
<string name="label_alt_key" msgid="2846315350346694811">"ALT"</string>
<string name="voice_warning_title" msgid="4419354150908395008">"음성 입력"</string>
<string name="voice_warning_locale_not_supported" msgid="637923019716442333">"음성 입력은 현재 자국어로 지원되지 않으며 영어로 작동됩니다."</string>
<string name="voice_warning_may_not_understand" msgid="4611518823070986445">"음성 입력은 Google의 네트워크화된 음성 인식을 사용하는 실험적 기능입니다."</string>
<string name="voice_warning_how_to_turn_off" msgid="5652369578498701761">"음성 입력을 사용하지 않으려면 키보드 설정으로 이동하세요."</string>
<string name="voice_hint_dialog_message" msgid="6892342981545727994">"음성 입력을 사용하려면 마이크 버튼을 누르거나 터치 키보드 위로 손가락을 미끄러지듯 움직이세요."</string>
<string name="voice_listening" msgid="467518160751321844">"지금 시작하세요."</string>
<string name="voice_working" msgid="6666937792815731889">"인식 중"</string>
<!-- no translation found for voice_initializing (661962047129906646) -->
<skip />
<string name="voice_error" msgid="5140896300312186162">"오류가 발생했습니다. 다시 시도해 보세요."</string>
<string name="voice_network_error" msgid="6649556447401862563">"연결할 수 없습니다."</string>
<string name="voice_too_much_speech" msgid="5746973620134227376">"음성을 너무 많이 입력했습니다."</string>
<string name="voice_audio_error" msgid="5072707727016414454">"오디오 문제"</string>
<string name="voice_server_error" msgid="7807129913977261644">"서버 오류"</string>
<string name="voice_speech_timeout" msgid="8461817525075498795">"음성이 인식되지 않았습니다."</string>
<string name="voice_no_match" msgid="4285117547030179174">"일치하는 항목 없음"</string>
<string name="voice_not_installed" msgid="5552450909753842415">"음성 검색이 설치되지 않았습니다."</string>
<string name="voice_swipe_hint" msgid="6943546180310682021"><b>"도움말:"</b>" 키보드를 스와이프하고 말하세요."</string>
<string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"도움말:"</b>" 다음 번에는 \'마침표\', \'쉼표\', \'물음표\'와 같은 구두점을 말해 보세요."</string>
<string name="cancel" msgid="6830980399865683324">"취소"</string>
<string name="ok" msgid="7898366843681727667">"확인"</string>
<string name="enable_voice" msgid="8299503298530853956">"음성 입력"</string>
<string name="auto_submit" msgid="9151008027068358518">"음성을 입력한 다음 자동 제출"</string>
<string name="auto_submit_summary" msgid="4961875269610384226">"검색하거나 다음 입력란으로 이동할 때 자동으로 Enter 키를 누릅니다."</string>
<string name="open_the_keyboard" msgid="2215920976029260466"><font size="17"><b>"키보드 열기"\n</b></font><font size="3">\n</font>"아무 텍스트 입력란이나 터치하세요."</string>
<string name="close_the_keyboard" msgid="6251022259044940103"><font size="17"><b>"키보드 닫기"\n</b></font><font size="3">\n</font>"\'뒤로\' 키를 누르세요."</string>
<string name="touch_and_hold" msgid="6154166367273010534"><font size="17"><b>"키를 길게 터치하여 옵션 보기"\n</b></font><font size="3">\n</font>"문장 부호 및 악센트 기호에 액세스하세요."</string>
@ -95,4 +112,5 @@
<string name="popular_domain_4" msgid="35359437471311470">".edu"</string>
<!-- no translation found for language_selection_title (530749890984542339) -->
<skip />
<string name="inputMethod" msgid="7854532062009028116">"입력 방법"</string>
</resources>

View File

@ -47,12 +47,6 @@
<item msgid="1669461741568287396">"Grunnleggende"</item>
<item msgid="4894328801530136615">"Avansert"</item>
</string-array>
<string name="prediction_none" msgid="2472795101338047944">"0"</string>
<string name="prediction_basic" msgid="8407291081834155558">"1"</string>
<string name="prediction_full" msgid="3765102052052510268">"2"</string>
<!-- no translation found for prediction_modes_values:0 (579944677836100459) -->
<!-- no translation found for prediction_modes_values:1 (7214414132844804570) -->
<!-- no translation found for prediction_modes_values:2 (6678546276084314171) -->
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: Lagret"</string>
<string name="alternates_for_a" msgid="2566516493365324765">"åæáàâãä"</string>
<string name="alternates_for_e" msgid="3900510936875547555">"éèêë"</string>
@ -63,7 +57,6 @@
<string name="alternates_for_n" msgid="6257322556221886400">"ñ"</string>
<string name="alternates_for_c" msgid="151699780720639892">"ç"</string>
<string name="alternates_for_y" msgid="1722776806607271199">"ýÿ"</string>
<string name="key_i" msgid="6483655742552255124">"i"</string>
<string name="tip_long_press" msgid="6101270866284343344">"Hold en tast nede for å se aksenterte tegn (ø, ö, osv.)"</string>
<string name="tip_dismiss" msgid="7585579046862204381">"Trykk tilbakeknappen, ↶, for å lukke tastaturet"</string>
<string name="tip_access_symbols" msgid="6344098517525531652">"Få tilgang til tall og symboler"</string>
@ -84,6 +77,30 @@
<string name="label_phone_key" msgid="4275497665515080551">"123"</string>
<string name="label_alpha_key" msgid="8864943487292437456">"ABC"</string>
<string name="label_alt_key" msgid="2846315350346694811">"ALT"</string>
<string name="voice_warning_title" msgid="4419354150908395008">"Stemmedata"</string>
<string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Stemmedata håndteres foreløpig ikke på ditt språk, men fungerer på engelsk."</string>
<string name="voice_warning_may_not_understand" msgid="4611518823070986445">"Talekommandoer er en eksperimentell funksjon som bruker Googles nettverksbaserte talegjenkjenning."</string>
<string name="voice_warning_how_to_turn_off" msgid="5652369578498701761">"Gå til innstillinger for tastatur for å slå av stemmedata."</string>
<string name="voice_hint_dialog_message" msgid="6892342981545727994">"Du bruker talekommandoer ved å trykke på mikrofonknappen eller skyve fingeren over tastaturet på skjermen."</string>
<string name="voice_listening" msgid="467518160751321844">"Snakk nå"</string>
<string name="voice_working" msgid="6666937792815731889">"Arbeider"</string>
<!-- no translation found for voice_initializing (661962047129906646) -->
<skip />
<string name="voice_error" msgid="5140896300312186162">"Feil. Prøv på nytt."</string>
<string name="voice_network_error" msgid="6649556447401862563">"Kunne ikke koble til"</string>
<string name="voice_too_much_speech" msgid="5746973620134227376">"Feil for mye tale"</string>
<string name="voice_audio_error" msgid="5072707727016414454">"Lydproblem"</string>
<string name="voice_server_error" msgid="7807129913977261644">"Tjenerfeil"</string>
<string name="voice_speech_timeout" msgid="8461817525075498795">"Ingen tale høres"</string>
<string name="voice_no_match" msgid="4285117547030179174">"Ingen treff"</string>
<string name="voice_not_installed" msgid="5552450909753842415">"Talesøk ikke installert"</string>
<string name="voice_swipe_hint" msgid="6943546180310682021">"Hint:"<b>" Sveip over tastaturet for å snakke"</b></string>
<string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Hint:"</b>" Neste gang kan du prøve å tale inn tegnsettingen ved for eksempel å si «punktum», «komma» eller «spørsmålstegn»."</string>
<string name="cancel" msgid="6830980399865683324">"Avbryt"</string>
<string name="ok" msgid="7898366843681727667">"OK"</string>
<string name="enable_voice" msgid="8299503298530853956">"Stemmedata"</string>
<string name="auto_submit" msgid="9151008027068358518">"Send inn automatisk etter tale"</string>
<string name="auto_submit_summary" msgid="4961875269610384226">"Trykk Enter automatisk ved søk eller flytting til neste felt."</string>
<string name="open_the_keyboard" msgid="2215920976029260466"><font size="17"><b>"Åpne tastaturet"\n</b></font><font size="3">\n</font>"Trykk på et tekstfelt."</string>
<string name="close_the_keyboard" msgid="6251022259044940103"><font size="17"><b>"Lukke tastaturet"\n</b></font><font size="3">\n</font>"Trykk på tilbaketasten."</string>
<string name="touch_and_hold" msgid="6154166367273010534"><font size="17"><b>"Trykk og hold nede en tast for flere valg"\n</b></font><font size="3">\n</font>"Få tilgang til skilletegn og aksenter."</string>
@ -95,4 +112,5 @@
<string name="popular_domain_4" msgid="35359437471311470">".info"</string>
<!-- no translation found for language_selection_title (530749890984542339) -->
<skip />
<string name="inputMethod" msgid="7854532062009028116">"Inndatametode"</string>
</resources>

View File

@ -47,12 +47,6 @@
<item msgid="1669461741568287396">"Basis"</item>
<item msgid="4894328801530136615">"Geavanceerd"</item>
</string-array>
<string name="prediction_none" msgid="2472795101338047944">"0"</string>
<string name="prediction_basic" msgid="8407291081834155558">"1"</string>
<string name="prediction_full" msgid="3765102052052510268">"2"</string>
<!-- no translation found for prediction_modes_values:0 (579944677836100459) -->
<!-- no translation found for prediction_modes_values:1 (7214414132844804570) -->
<!-- no translation found for prediction_modes_values:2 (6678546276084314171) -->
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Opgeslagen"</string>
<string name="alternates_for_a" msgid="2566516493365324765">"àáâãäåæ"</string>
<string name="alternates_for_e" msgid="3900510936875547555">"èéêë"</string>
@ -63,7 +57,6 @@
<string name="alternates_for_n" msgid="6257322556221886400">"ñ"</string>
<string name="alternates_for_c" msgid="151699780720639892">"ç"</string>
<string name="alternates_for_y" msgid="1722776806607271199">"ýÿ"</string>
<string name="key_i" msgid="6483655742552255124">"i"</string>
<string name="tip_long_press" msgid="6101270866284343344">"Houd een toets ingedrukt om diakritische tekens weer te geven (ø, ö, enzovoort)"</string>
<string name="tip_dismiss" msgid="7585579046862204381">"Druk op elk gewenst moment op de toets Terug ↶ om het toetsenbord te sluiten"</string>
<string name="tip_access_symbols" msgid="6344098517525531652">"Toegang tot cijfers en symbolen"</string>
@ -84,6 +77,30 @@
<string name="label_phone_key" msgid="4275497665515080551">"123"</string>
<string name="label_alpha_key" msgid="8864943487292437456">"ABC"</string>
<string name="label_alt_key" msgid="2846315350346694811">"Alt"</string>
<string name="voice_warning_title" msgid="4419354150908395008">"Spraakinvoer"</string>
<string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Spraakinvoer wordt momenteel niet ondersteund in uw taal, maar is wel beschikbaar in het Engels."</string>
<string name="voice_warning_may_not_understand" msgid="4611518823070986445">"Spraakinvoer is een experimentele functie met de spraakherkenning van het Google-netwerk."</string>
<string name="voice_warning_how_to_turn_off" msgid="5652369578498701761">"Als u spraakinvoer wilt uitschakelen, gaat u naar de toetsenbordinstellingen."</string>
<string name="voice_hint_dialog_message" msgid="6892342981545727994">"Als u spraakinvoer gebruikt, drukt u op de microfoonknop of schuift u uw vinger over het schermtoetsenbord."</string>
<string name="voice_listening" msgid="467518160751321844">"Nu spreken"</string>
<string name="voice_working" msgid="6666937792815731889">"Wordt uitgevoerd"</string>
<!-- no translation found for voice_initializing (661962047129906646) -->
<skip />
<string name="voice_error" msgid="5140896300312186162">"Fout. Probeer het opnieuw."</string>
<string name="voice_network_error" msgid="6649556447401862563">"Kan geen verbinding maken"</string>
<string name="voice_too_much_speech" msgid="5746973620134227376">"Fout, te lange spraakinvoer."</string>
<string name="voice_audio_error" msgid="5072707727016414454">"Audioprobleem"</string>
<string name="voice_server_error" msgid="7807129913977261644">"Serverfout"</string>
<string name="voice_speech_timeout" msgid="8461817525075498795">"Geen spraak te horen"</string>
<string name="voice_no_match" msgid="4285117547030179174">"Geen resultaten gevonden"</string>
<string name="voice_not_installed" msgid="5552450909753842415">"Voice Search is niet geïnstalleerd"</string>
<string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Hint:"</b>" schuif over het toetsenbord om te spreken"</string>
<string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Hint:"</b>" spreek de volgende keer interpunctie uit, zoals \'period\' (punt), \'comma\' (komma) of \'question mark\' (vraagteken)."</string>
<string name="cancel" msgid="6830980399865683324">"Annuleren"</string>
<string name="ok" msgid="7898366843681727667">"OK"</string>
<string name="enable_voice" msgid="8299503298530853956">"Spraakinvoer"</string>
<string name="auto_submit" msgid="9151008027068358518">"Automatisch verzenden na spraak"</string>
<string name="auto_submit_summary" msgid="4961875269610384226">"Drukt automatisch op Enter tijdens het zoeken of wanneer u naar het volgende veld wilt gaan."</string>
<string name="open_the_keyboard" msgid="2215920976029260466"><font size="17"><b>"Het toetsenbord openen"\n</b></font><font size="3">\n</font>"Raak een tekstveld aan."</string>
<string name="close_the_keyboard" msgid="6251022259044940103"><font size="17"><b>"Het toetsenbord sluiten"\n</b></font><font size="3">\n</font>"Druk op de terugtoets."</string>
<string name="touch_and_hold" msgid="6154166367273010534"><font size="17"><b>"Een toets blijven aanraken voor opties"\n</b></font><font size="3">\n</font>"Toegang tot interpunctie en diakritische tekens."</string>
@ -95,4 +112,5 @@
<string name="popular_domain_4" msgid="35359437471311470">".edu"</string>
<!-- no translation found for language_selection_title (530749890984542339) -->
<skip />
<string name="inputMethod" msgid="7854532062009028116">"Invoermethode"</string>
</resources>

View File

@ -47,12 +47,6 @@
<item msgid="1669461741568287396">"Podstawowy"</item>
<item msgid="4894328801530136615">"Zaawansowany"</item>
</string-array>
<string name="prediction_none" msgid="2472795101338047944">"0"</string>
<string name="prediction_basic" msgid="8407291081834155558">"1"</string>
<string name="prediction_full" msgid="3765102052052510268">"2"</string>
<!-- no translation found for prediction_modes_values:0 (579944677836100459) -->
<!-- no translation found for prediction_modes_values:1 (7214414132844804570) -->
<!-- no translation found for prediction_modes_values:2 (6678546276084314171) -->
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Zapisano"</string>
<string name="alternates_for_a" msgid="2566516493365324765">"ą"</string>
<string name="alternates_for_e" msgid="3900510936875547555">"ę"</string>
@ -63,7 +57,6 @@
<string name="alternates_for_n" msgid="6257322556221886400">"ń"</string>
<string name="alternates_for_c" msgid="151699780720639892">"ć"</string>
<string name="alternates_for_y" msgid="1722776806607271199">"ýÿ"</string>
<string name="key_i" msgid="6483655742552255124">"i"</string>
<string name="tip_long_press" msgid="6101270866284343344">"Przytrzymaj klawisz, aby wyświetlić znaki akcentowane (ą, ó itp.)"</string>
<string name="tip_dismiss" msgid="7585579046862204381">"Naciśnij klawisz cofania ↶, aby zamknąć klawiaturę w dowolnym momencie"</string>
<string name="tip_access_symbols" msgid="6344098517525531652">"Przejdź do cyfr i symboli"</string>
@ -84,6 +77,30 @@
<string name="label_phone_key" msgid="4275497665515080551">"123"</string>
<string name="label_alpha_key" msgid="8864943487292437456">"ABC"</string>
<string name="label_alt_key" msgid="2846315350346694811">"ALT"</string>
<string name="voice_warning_title" msgid="4419354150908395008">"Wprowadzanie głosowe"</string>
<string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Wprowadzanie głosowe obecnie nie jest obsługiwane w Twoim języku, ale działa w języku angielskim."</string>
<string name="voice_warning_may_not_understand" msgid="4611518823070986445">"Wprowadzanie głosowe to funkcja eksperymentalna wykorzystująca funkcję firmy Google umożliwiającą rozpoznawanie mowy przy użyciu sieci."</string>
<string name="voice_warning_how_to_turn_off" msgid="5652369578498701761">"Aby wyłączyć wprowadzanie głosowe, przejdź do ustawień klawiatury."</string>
<string name="voice_hint_dialog_message" msgid="6892342981545727994">"Aby skorzystać z wprowadzania głosowego, naciśnij przycisk mikrofonu lub przesuń palcem po klawiaturze ekranowej."</string>
<string name="voice_listening" msgid="467518160751321844">"Mów teraz"</string>
<string name="voice_working" msgid="6666937792815731889">"Działa"</string>
<!-- no translation found for voice_initializing (661962047129906646) -->
<skip />
<string name="voice_error" msgid="5140896300312186162">"Błąd. Spróbuj ponownie."</string>
<string name="voice_network_error" msgid="6649556447401862563">"Nie można nawiązać połączenia"</string>
<string name="voice_too_much_speech" msgid="5746973620134227376">"Błąd, zbyt długa wypowiedź."</string>
<string name="voice_audio_error" msgid="5072707727016414454">"Problem z dźwiękiem"</string>
<string name="voice_server_error" msgid="7807129913977261644">"Błąd serwera"</string>
<string name="voice_speech_timeout" msgid="8461817525075498795">"Nie wykryto mowy"</string>
<string name="voice_no_match" msgid="4285117547030179174">"Nie znaleziono żadnych wyników"</string>
<string name="voice_not_installed" msgid="5552450909753842415">"Wyszukiwanie głosowe nie jest zainstalowane"</string>
<string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Wskazówka:"</b>" przesuń palcem po klawiaturze, aby mówić."</string>
<string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Wskazówka:"</b>" następnym razem spróbuj wypowiadać nazwy znaków interpunkcyjnych: „kropka”, „przecinek” lub „pytajnik”."</string>
<string name="cancel" msgid="6830980399865683324">"Anuluj"</string>
<string name="ok" msgid="7898366843681727667">"OK"</string>
<string name="enable_voice" msgid="8299503298530853956">"Wprowadzanie głosowe"</string>
<string name="auto_submit" msgid="9151008027068358518">"Automatyczne przesyłanie uruchamiane głosem"</string>
<string name="auto_submit_summary" msgid="4961875269610384226">"Podczas wyszukiwania lub przechodzenia do następnego pola automatycznie naciśnij klawisz Enter."</string>
<string name="open_the_keyboard" msgid="2215920976029260466"><font size="17"><b>"Otwórz klawiaturę"\n</b></font><font size="3">\n</font>"Dotknij dowolnego pola tekstowego."</string>
<string name="close_the_keyboard" msgid="6251022259044940103"><font size="17"><b>"Zamknij klawiaturę"\n</b></font><font size="3">\n</font>"Naciśnij klawisz Wróć."</string>
<string name="touch_and_hold" msgid="6154166367273010534"><font size="17"><b>"Dotknij klawisza i przytrzymaj go, aby wyświetlić opcje"\n</b></font><font size="3">\n</font>"Dostęp do znaków przestankowych i akcentowanych."</string>
@ -95,4 +112,5 @@
<string name="popular_domain_4" msgid="35359437471311470">".edu"</string>
<!-- no translation found for language_selection_title (530749890984542339) -->
<skip />
<string name="inputMethod" msgid="7854532062009028116">"Metoda wprowadzania"</string>
</resources>

View File

@ -47,12 +47,6 @@
<item msgid="1669461741568287396">"Básico"</item>
<item msgid="4894328801530136615">"Avançados"</item>
</string-array>
<string name="prediction_none" msgid="2472795101338047944">"0"</string>
<string name="prediction_basic" msgid="8407291081834155558">"1"</string>
<string name="prediction_full" msgid="3765102052052510268">"2"</string>
<!-- no translation found for prediction_modes_values:0 (579944677836100459) -->
<!-- no translation found for prediction_modes_values:1 (7214414132844804570) -->
<!-- no translation found for prediction_modes_values:2 (6678546276084314171) -->
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: Guardada"</string>
<string name="alternates_for_a" msgid="2566516493365324765">"àáâãäåæ"</string>
<string name="alternates_for_e" msgid="3900510936875547555">"èéêë"</string>
@ -63,7 +57,6 @@
<string name="alternates_for_n" msgid="6257322556221886400">"ñ"</string>
<string name="alternates_for_c" msgid="151699780720639892">"ç"</string>
<string name="alternates_for_y" msgid="1722776806607271199">"ýÿ"</string>
<string name="key_i" msgid="6483655742552255124">"i"</string>
<string name="tip_long_press" msgid="6101270866284343344">"Mantenha uma tecla premida para ver os acentos (ø, ö, etc.)"</string>
<string name="tip_dismiss" msgid="7585579046862204381">"Prima a tecla de retrocesso ↶ para fechar o teclado a qualquer momento"</string>
<string name="tip_access_symbols" msgid="6344098517525531652">"Aceder a números e símbolos"</string>
@ -84,6 +77,30 @@
<string name="label_phone_key" msgid="4275497665515080551">"123"</string>
<string name="label_alpha_key" msgid="8864943487292437456">"ABC"</string>
<string name="label_alt_key" msgid="2846315350346694811">"ALT"</string>
<string name="voice_warning_title" msgid="4419354150908395008">"Entrada de voz"</string>
<string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Actualmente, a entrada de voz não é suportada para o seu idioma, mas funciona em inglês."</string>
<string name="voice_warning_may_not_understand" msgid="4611518823070986445">"A entrada de voz é uma funcionalidade experimental que utiliza o reconhecimento de voz em rede da Google."</string>
<string name="voice_warning_how_to_turn_off" msgid="5652369578498701761">"Para desactivar a entrada de voz, aceda às definições do teclado."</string>
<string name="voice_hint_dialog_message" msgid="6892342981545727994">"Para utilizar a entrada de voz, prima o botão do microfone ou deslize o dedo no teclado do ecrã."</string>
<string name="voice_listening" msgid="467518160751321844">"Falar agora"</string>
<string name="voice_working" msgid="6666937792815731889">"A executar"</string>
<!-- no translation found for voice_initializing (661962047129906646) -->
<skip />
<string name="voice_error" msgid="5140896300312186162">"Erro. Tente novamente."</string>
<string name="voice_network_error" msgid="6649556447401862563">"Não foi possível ligar"</string>
<string name="voice_too_much_speech" msgid="5746973620134227376">"Erro, discurso demasiado longo."</string>
<string name="voice_audio_error" msgid="5072707727016414454">"Problema de áudio"</string>
<string name="voice_server_error" msgid="7807129913977261644">"Erro no servidor"</string>
<string name="voice_speech_timeout" msgid="8461817525075498795">"Nenhuma voz ouvida"</string>
<string name="voice_no_match" msgid="4285117547030179174">"Não foram encontradas correspondências"</string>
<string name="voice_not_installed" msgid="5552450909753842415">"Pesquisa de voz não instalada"</string>
<string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Sugestão:"</b>" Deslize no teclado para falar"</string>
<string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Sugestão:"</b>" Da próxima vez, experimente dizer a pontuação como \"ponto final\", \"vírgula\" ou \"ponto de interrogação\"."</string>
<string name="cancel" msgid="6830980399865683324">"Cancelar"</string>
<string name="ok" msgid="7898366843681727667">"OK"</string>
<string name="enable_voice" msgid="8299503298530853956">"Entrada de voz"</string>
<string name="auto_submit" msgid="9151008027068358518">"Enviar automaticamente depois da voz"</string>
<string name="auto_submit_summary" msgid="4961875269610384226">"Premir automaticamente ENTER ao pesquisar ou avançar para o campo seguinte."</string>
<string name="open_the_keyboard" msgid="2215920976029260466"><font size="17"><b>"Abra o teclado"\n</b></font><font size="3">\n</font>"Toque em qualquer campo de texto."</string>
<string name="close_the_keyboard" msgid="6251022259044940103"><font size="17"><b>"Feche o teclado"\n</b></font><font size="3">\n</font>"Prima a tecla \"Anterior\"."</string>
<string name="touch_and_hold" msgid="6154166367273010534"><font size="17"><b>"Mantenha premida uma tecla para as opções"\n</b></font><font size="3">\n</font>"Aceder a pontuação e acentos."</string>
@ -93,6 +110,7 @@
<string name="popular_domain_2" msgid="3036812463748402878">".org"</string>
<string name="popular_domain_3" msgid="8718639560809452028">".gov"</string>
<string name="popular_domain_4" msgid="35359437471311470">".edu"</string>
<string name="inputMethod" msgid="1653630062304567879">"Método de entrada"</string>
<!-- no translation found for language_selection_title (530749890984542339) -->
<skip />
</resources>

View File

@ -47,12 +47,6 @@
<item msgid="1669461741568287396">"Básico"</item>
<item msgid="4894328801530136615">"Avançado"</item>
</string-array>
<string name="prediction_none" msgid="2472795101338047944">"0"</string>
<string name="prediction_basic" msgid="8407291081834155558">"1"</string>
<string name="prediction_full" msgid="3765102052052510268">"2"</string>
<!-- no translation found for prediction_modes_values:0 (579944677836100459) -->
<!-- no translation found for prediction_modes_values:1 (7214414132844804570) -->
<!-- no translation found for prediction_modes_values:2 (6678546276084314171) -->
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Salvo"</string>
<string name="alternates_for_a" msgid="2566516493365324765">"àáâãäåæ"</string>
<string name="alternates_for_e" msgid="3900510936875547555">"èéêë"</string>
@ -63,7 +57,6 @@
<string name="alternates_for_n" msgid="6257322556221886400">"ñ"</string>
<string name="alternates_for_c" msgid="151699780720639892">"ç"</string>
<string name="alternates_for_y" msgid="1722776806607271199">"ýÿ"</string>
<string name="key_i" msgid="6483655742552255124">"i"</string>
<string name="tip_long_press" msgid="6101270866284343344">"Segure uma tecla pressionada para ver os acentos (ø, ö, etc.)"</string>
<string name="tip_dismiss" msgid="7585579046862204381">"Apertar a tecla voltar ↶ para fechar o teclado, em qualquer ponto"</string>
<string name="tip_access_symbols" msgid="6344098517525531652">"Acessar números e símbolos"</string>
@ -84,6 +77,30 @@
<string name="label_phone_key" msgid="4275497665515080551">"123"</string>
<string name="label_alpha_key" msgid="8864943487292437456">"ABC"</string>
<string name="label_alt_key" msgid="2846315350346694811">"ALT"</string>
<string name="voice_warning_title" msgid="4419354150908395008">"Entrada de voz"</string>
<string name="voice_warning_locale_not_supported" msgid="637923019716442333">"A entrada de voz não é suportada no momento para o seu idioma, mas funciona em inglês."</string>
<string name="voice_warning_may_not_understand" msgid="4611518823070986445">"A entrada de voz é um recurso experimental que usa o reconhecimento de fala de rede do Google."</string>
<string name="voice_warning_how_to_turn_off" msgid="5652369578498701761">"Para desativar a entrada de voz, vá para as configurações do teclado."</string>
<string name="voice_hint_dialog_message" msgid="6892342981545727994">"Para usar a entrada de voz, pressione o botão com o microfone ou deslize o dedo sobre o teclado na tela."</string>
<string name="voice_listening" msgid="467518160751321844">"Fale agora"</string>
<string name="voice_working" msgid="6666937792815731889">"Trabalhando"</string>
<!-- no translation found for voice_initializing (661962047129906646) -->
<skip />
<string name="voice_error" msgid="5140896300312186162">"Erro. Tente novamente."</string>
<string name="voice_network_error" msgid="6649556447401862563">"Não foi possível conectar"</string>
<string name="voice_too_much_speech" msgid="5746973620134227376">"Erro, fala muito longa."</string>
<string name="voice_audio_error" msgid="5072707727016414454">"Problema com o áudio"</string>
<string name="voice_server_error" msgid="7807129913977261644">"Erro do servidor"</string>
<string name="voice_speech_timeout" msgid="8461817525075498795">"Nenhuma fala ouvida"</string>
<string name="voice_no_match" msgid="4285117547030179174">"Não há resultados compatíveis"</string>
<string name="voice_not_installed" msgid="5552450909753842415">"A pesquisa por voz não está instalada"</string>
<string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Dica:"</b>" Deslize sobre o teclado para falar"</string>
<string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Dica:"</b>" Da próxima vez, tente falar o nome da pontuação como \"ponto\", \"vírgula\" ou \"ponto de interrogação\"."</string>
<string name="cancel" msgid="6830980399865683324">"Cancelar"</string>
<string name="ok" msgid="7898366843681727667">"OK"</string>
<string name="enable_voice" msgid="8299503298530853956">"Entrada de voz"</string>
<string name="auto_submit" msgid="9151008027068358518">"Enviar automaticamente depois de falar"</string>
<string name="auto_submit_summary" msgid="4961875269610384226">"Pressione Enter automaticamente ao pesquisar ou ir para o próximo campo."</string>
<string name="open_the_keyboard" msgid="2215920976029260466"><font size="17"><b>"Abra o teclado"\n</b></font><font size="3">\n</font>"Toque em qualquer campo de texto."</string>
<string name="close_the_keyboard" msgid="6251022259044940103"><font size="17"><b>"Feche o teclado"\n</b></font><font size="3">\n</font>"Pressione a tecla Voltar."</string>
<string name="touch_and_hold" msgid="6154166367273010534"><font size="17"><b>"Toque e mantenha pressionada uma tecla para ver as opções"\n</b></font><font size="3">\n</font>"Acesse a pontuação e os acentos."</string>
@ -93,6 +110,7 @@
<string name="popular_domain_2" msgid="3036812463748402878">".org"</string>
<string name="popular_domain_3" msgid="8718639560809452028">".gov"</string>
<string name="popular_domain_4" msgid="35359437471311470">".edu"</string>
<string name="inputMethod" msgid="1653630062304567879">"Método de entrada"</string>
<!-- no translation found for language_selection_title (530749890984542339) -->
<skip />
</resources>

View File

@ -47,12 +47,6 @@
<item msgid="1669461741568287396">"Основной"</item>
<item msgid="4894328801530136615">"Расширенный"</item>
</string-array>
<string name="prediction_none" msgid="2472795101338047944">"0"</string>
<string name="prediction_basic" msgid="8407291081834155558">"1"</string>
<string name="prediction_full" msgid="3765102052052510268">"2"</string>
<!-- no translation found for prediction_modes_values:0 (579944677836100459) -->
<!-- no translation found for prediction_modes_values:1 (7214414132844804570) -->
<!-- no translation found for prediction_modes_values:2 (6678546276084314171) -->
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : сохранено"</string>
<string name="alternates_for_a" msgid="2566516493365324765">"àáâãäåæ"</string>
<string name="alternates_for_e" msgid="3900510936875547555">"èéêë"</string>
@ -63,7 +57,6 @@
<string name="alternates_for_n" msgid="6257322556221886400">"ñ"</string>
<string name="alternates_for_c" msgid="151699780720639892">"ç"</string>
<string name="alternates_for_y" msgid="1722776806607271199">"ýÿ"</string>
<string name="key_i" msgid="6483655742552255124">"i"</string>
<string name="tip_long_press" msgid="6101270866284343344">"Удерживайте клавишу, чтобы увидеть варианты с диакритическими знаками (ø, ö и т.д.)"</string>
<string name="tip_dismiss" msgid="7585579046862204381">"Нажмите клавишу \"Назад\" ↶, чтобы закрыть клавиатуру в любой момент"</string>
<string name="tip_access_symbols" msgid="6344098517525531652">"Открыть цифры и символы"</string>
@ -84,6 +77,30 @@
<string name="label_phone_key" msgid="4275497665515080551">"123"</string>
<string name="label_alpha_key" msgid="8864943487292437456">"АБВ"</string>
<string name="label_alt_key" msgid="2846315350346694811">"ALT"</string>
<string name="voice_warning_title" msgid="4419354150908395008">"Голосовой ввод"</string>
<string name="voice_warning_locale_not_supported" msgid="637923019716442333">"В настоящее время функция голосового ввода не поддерживает ваш язык, но вы можете пользоваться ей на английском."</string>
<string name="voice_warning_may_not_understand" msgid="4611518823070986445">"Голосовой ввод экспериментальная функция на основе технологии сетевого распознавания речи от Google."</string>
<string name="voice_warning_how_to_turn_off" msgid="5652369578498701761">"Функция голосового ввода отключается в настройках клавиатуры."</string>
<string name="voice_hint_dialog_message" msgid="6892342981545727994">"Чтобы использовать голосовой ввод, нажмите кнопку микрофона или проведите пальцем по экранной клавиатуре."</string>
<string name="voice_listening" msgid="467518160751321844">"Говорите"</string>
<string name="voice_working" msgid="6666937792815731889">"Выполняется обработка"</string>
<!-- no translation found for voice_initializing (661962047129906646) -->
<skip />
<string name="voice_error" msgid="5140896300312186162">"Ошибка. Повторите попытку."</string>
<string name="voice_network_error" msgid="6649556447401862563">"Ошибка подключения"</string>
<string name="voice_too_much_speech" msgid="5746973620134227376">"Слишком длинная фраза"</string>
<string name="voice_audio_error" msgid="5072707727016414454">"Неполадка со звуком"</string>
<string name="voice_server_error" msgid="7807129913977261644">"Ошибка сервера"</string>
<string name="voice_speech_timeout" msgid="8461817525075498795">"Речи не слышно"</string>
<string name="voice_no_match" msgid="4285117547030179174">"Соответствий не найдено"</string>
<string name="voice_not_installed" msgid="5552450909753842415">"Голосовой поиск не установлен"</string>
<string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Совет"</b>". Проведите пальцем по клавиатуре для голосового ввода."</string>
<string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Совет"</b>". В следующий раз проговаривайте знаки препинания, например \"точка\", \"запятая\", \"вопросительный знак\"."</string>
<string name="cancel" msgid="6830980399865683324">"Отмена"</string>
<string name="ok" msgid="7898366843681727667">"ОК"</string>
<string name="enable_voice" msgid="8299503298530853956">"Голосовой ввод"</string>
<string name="auto_submit" msgid="9151008027068358518">"Автоматически отправлять по окончании голосового ввода"</string>
<string name="auto_submit_summary" msgid="4961875269610384226">"Автоматически нажимать \"Ввод\" при поиске или переходе к следующему полю."</string>
<string name="open_the_keyboard" msgid="2215920976029260466"><font size="17"><b>"Откройте клавиатуру"\n</b></font><font size="3">\n</font>"Нажмите на любое текстовое поле."</string>
<string name="close_the_keyboard" msgid="6251022259044940103"><font size="17"><b>"Закрытие клавиатуры"\n</b></font><font size="3">\n</font>"Нажмите клавишу \"Назад\"."</string>
<string name="touch_and_hold" msgid="6154166367273010534"><font size="17"><b>"Нажмите и удерживайте клавишу для вызова параметров"\n</b></font><font size="3">\n</font>"Доступ к пунктуационным и диакритическим знакам."</string>
@ -95,4 +112,5 @@
<string name="popular_domain_4" msgid="35359437471311470">".edu"</string>
<!-- no translation found for language_selection_title (530749890984542339) -->
<skip />
<string name="inputMethod" msgid="7854532062009028116">"Способ ввода"</string>
</resources>

View File

@ -47,12 +47,6 @@
<item msgid="1669461741568287396">"Grundinställningar"</item>
<item msgid="4894328801530136615">"Avancerade"</item>
</string-array>
<string name="prediction_none" msgid="2472795101338047944">"0"</string>
<string name="prediction_basic" msgid="8407291081834155558">"1"</string>
<string name="prediction_full" msgid="3765102052052510268">"2"</string>
<!-- no translation found for prediction_modes_values:0 (579944677836100459) -->
<!-- no translation found for prediction_modes_values:1 (7214414132844804570) -->
<!-- no translation found for prediction_modes_values:2 (6678546276084314171) -->
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: sparat"</string>
<string name="alternates_for_a" msgid="2566516493365324765">"àáâãäåæ"</string>
<string name="alternates_for_e" msgid="3900510936875547555">"èéêë"</string>
@ -63,7 +57,6 @@
<string name="alternates_for_n" msgid="6257322556221886400">"ñ"</string>
<string name="alternates_for_c" msgid="151699780720639892">"ç"</string>
<string name="alternates_for_y" msgid="1722776806607271199">"ýÿ"</string>
<string name="key_i" msgid="6483655742552255124">"i"</string>
<string name="tip_long_press" msgid="6101270866284343344">"Håll nere en tangent om du vill visa accenter (ø, ö, etc.)"</string>
<string name="tip_dismiss" msgid="7585579046862204381">"Tryck på Tillbaka ↶ om du vill stänga tangentbordet"</string>
<string name="tip_access_symbols" msgid="6344098517525531652">"För siffror och symboler"</string>
@ -84,6 +77,30 @@
<string name="label_phone_key" msgid="4275497665515080551">"123"</string>
<string name="label_alpha_key" msgid="8864943487292437456">"ABC"</string>
<string name="label_alt_key" msgid="2846315350346694811">"ALT"</string>
<string name="voice_warning_title" msgid="4419354150908395008">"Röstindata"</string>
<string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Röstindata stöds inte på ditt språk än, men tjänsten fungerar på engelska."</string>
<string name="voice_warning_may_not_understand" msgid="4611518823070986445">"Röstinmatning är en funktion på experimentstadiet som använder Googles nätverks taligenkänning."</string>
<string name="voice_warning_how_to_turn_off" msgid="5652369578498701761">"Om du vill stänga av röstindata öppnar du inställningarna för tangentbordet."</string>
<string name="voice_hint_dialog_message" msgid="6892342981545727994">"Om du vill använda röstinmatning trycker du på mikrofonknappen eller drar fingret över tangentbordet på skärmen."</string>
<string name="voice_listening" msgid="467518160751321844">"Tala nu"</string>
<string name="voice_working" msgid="6666937792815731889">"Fungerar"</string>
<!-- no translation found for voice_initializing (661962047129906646) -->
<skip />
<string name="voice_error" msgid="5140896300312186162">"Fel. Försök igen."</string>
<string name="voice_network_error" msgid="6649556447401862563">"Det gick inte att ansluta"</string>
<string name="voice_too_much_speech" msgid="5746973620134227376">"Fel, för mycket tal."</string>
<string name="voice_audio_error" msgid="5072707727016414454">"Ljudproblem"</string>
<string name="voice_server_error" msgid="7807129913977261644">"Serverfel"</string>
<string name="voice_speech_timeout" msgid="8461817525075498795">"Hörde inget tal"</string>
<string name="voice_no_match" msgid="4285117547030179174">"Inga träffar hittades"</string>
<string name="voice_not_installed" msgid="5552450909753842415">"Voice Search är inte installerat"</string>
<string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Tips!"</b>" Dra över tangentbordet om du vill tala"</string>
<string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Tips!"</b>" Nästa gång testar du att säga skiljetecknen, som \"punkt\", \"komma\" eller \"frågetecken\"."</string>
<string name="cancel" msgid="6830980399865683324">"Avbryt"</string>
<string name="ok" msgid="7898366843681727667">"OK"</string>
<string name="enable_voice" msgid="8299503298530853956">"Röstindata"</string>
<string name="auto_submit" msgid="9151008027068358518">"Skicka automatiskt efter röst"</string>
<string name="auto_submit_summary" msgid="4961875269610384226">"Tryck automatiskt på retur vid sökning eller när du fortsätter till nästa fält."</string>
<string name="open_the_keyboard" msgid="2215920976029260466"><font size="17"><b>"Öppna tangentbordet"\n</b></font><font size="3">\n</font>"Tryck på ett textfält."</string>
<string name="close_the_keyboard" msgid="6251022259044940103"><font size="17"><b>"Stäng tangentbordet"\n</b></font><font size="3">\n</font>"Tryck på Tillbaka."</string>
<string name="touch_and_hold" msgid="6154166367273010534"><font size="17"><b>"Tryck länge på en tangent om du vill se alternativ"\n</b></font><font size="3">\n</font>"Använda skiljetecken och accenter."</string>
@ -95,4 +112,5 @@
<string name="popular_domain_4" msgid="35359437471311470">".edu"</string>
<!-- no translation found for language_selection_title (530749890984542339) -->
<skip />
<string name="inputMethod" msgid="7854532062009028116">"Indatametod"</string>
</resources>

View File

@ -20,4 +20,4 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- Accented characters related to "g" -->
<string name="alternates_for_g">ğ</string>
</resources>
</resources>

View File

@ -47,12 +47,6 @@
<item msgid="1669461741568287396">"Temel"</item>
<item msgid="4894328801530136615">"Gelişmiş"</item>
</string-array>
<string name="prediction_none" msgid="2472795101338047944">"0"</string>
<string name="prediction_basic" msgid="8407291081834155558">"1"</string>
<string name="prediction_full" msgid="3765102052052510268">"2"</string>
<!-- no translation found for prediction_modes_values:0 (579944677836100459) -->
<!-- no translation found for prediction_modes_values:1 (7214414132844804570) -->
<!-- no translation found for prediction_modes_values:2 (6678546276084314171) -->
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Kaydedildi"</string>
<string name="alternates_for_a" msgid="2566516493365324765">"àáâãäåæ"</string>
<string name="alternates_for_e" msgid="3900510936875547555">"èéêë"</string>
@ -63,7 +57,6 @@
<string name="alternates_for_n" msgid="6257322556221886400">"ñ"</string>
<string name="alternates_for_c" msgid="151699780720639892">"ç"</string>
<string name="alternates_for_y" msgid="1722776806607271199">"ýÿ"</string>
<string name="key_i" msgid="6483655742552255124">"i"</string>
<string name="tip_long_press" msgid="6101270866284343344">"Vurguları görmek için bir tuşu basılı tutun (ø, ö, v.b.)"</string>
<string name="tip_dismiss" msgid="7585579046862204381">"Klavyeyi herhangi bir anda kapatmak için geri tuşuna ↶ basın"</string>
<string name="tip_access_symbols" msgid="6344098517525531652">"Sayılara ve simgelere erişin"</string>
@ -84,6 +77,30 @@
<string name="label_phone_key" msgid="4275497665515080551">"123"</string>
<string name="label_alpha_key" msgid="8864943487292437456">"ABC"</string>
<string name="label_alt_key" msgid="2846315350346694811">"ALT"</string>
<string name="voice_warning_title" msgid="4419354150908395008">"Ses girişi"</string>
<string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Ses girişi, şu anda sizin diliniz için desteklenmiyor ama İngilizce dilinde kullanılabilir."</string>
<string name="voice_warning_may_not_understand" msgid="4611518823070986445">"Ses girişi, Google\'ın ağ bağlantılı ses tanıma işlevini kullanan deneysel bir özelliktir."</string>
<string name="voice_warning_how_to_turn_off" msgid="5652369578498701761">"Ses girişini kapatmak için klavye ayarlarına gidin."</string>
<string name="voice_hint_dialog_message" msgid="6892342981545727994">"Ses girişini kullanmak için mikrofon düğmesine basın veya parmağınızı dokunmatik klavye üzerinde kaydırın."</string>
<string name="voice_listening" msgid="467518160751321844">"Şimdi konuşun"</string>
<string name="voice_working" msgid="6666937792815731889">"Çalışıyor"</string>
<!-- no translation found for voice_initializing (661962047129906646) -->
<skip />
<string name="voice_error" msgid="5140896300312186162">"Hata. Lütfen tekrar deneyin."</string>
<string name="voice_network_error" msgid="6649556447401862563">"Bağlanamadı"</string>
<string name="voice_too_much_speech" msgid="5746973620134227376">"Hata, çok uzun konuşma."</string>
<string name="voice_audio_error" msgid="5072707727016414454">"Ses sorunu"</string>
<string name="voice_server_error" msgid="7807129913977261644">"Sunucu hatası"</string>
<string name="voice_speech_timeout" msgid="8461817525075498795">"Konuşma duyulmadı"</string>
<string name="voice_no_match" msgid="4285117547030179174">"Eşleşme bulunamadı"</string>
<string name="voice_not_installed" msgid="5552450909753842415">"Sesle arama yüklenmedi"</string>
<string name="voice_swipe_hint" msgid="6943546180310682021"><b>"İpucu:"</b>" Konuşmak için parmağınızı klavye üzerinde kaydırın"</string>
<string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"İpucu:"</b>" Sonraki sefer, \"nokta\", \"virgül\" veya \"soru işareti\" gibi noktalama işaretlerini telaffuz etmeyi deneyin."</string>
<string name="cancel" msgid="6830980399865683324">"İptal"</string>
<string name="ok" msgid="7898366843681727667">"Tamam"</string>
<string name="enable_voice" msgid="8299503298530853956">"Ses girişi"</string>
<string name="auto_submit" msgid="9151008027068358518">"Sesten sonra otomatik gönder"</string>
<string name="auto_submit_summary" msgid="4961875269610384226">"Arama yaparken veya bir sonraki alana giderken enter tuşuna otomatik olarak basın."</string>
<string name="open_the_keyboard" msgid="2215920976029260466"><font size="17"><b>"Klavyeyi açın"\n</b></font><font size="3">\n</font>"Herhangi bir metin alanına dokunun."</string>
<string name="close_the_keyboard" msgid="6251022259044940103"><font size="17"><b>"Klavyeyi kapatın"\n</b></font><font size="3">\n</font>"Geri tuşuna basın."</string>
<string name="touch_and_hold" msgid="6154166367273010534"><font size="17"><b>"Seçenekler için bir tuşa dokunun ve basılı tutun"\n</b></font><font size="3">\n</font>"Noktalama ve vurgulama işaretlerine erişin."</string>
@ -95,4 +112,5 @@
<string name="popular_domain_4" msgid="35359437471311470">".edu"</string>
<!-- no translation found for language_selection_title (530749890984542339) -->
<skip />
<string name="inputMethod" msgid="7854532062009028116">"Giriş yöntemi"</string>
</resources>

View File

@ -47,12 +47,6 @@
<item msgid="1669461741568287396">"基本模式"</item>
<item msgid="4894328801530136615">"高级模式"</item>
</string-array>
<string name="prediction_none" msgid="2472795101338047944">"0"</string>
<string name="prediction_basic" msgid="8407291081834155558">"1"</string>
<string name="prediction_full" msgid="3765102052052510268">"2"</string>
<!-- no translation found for prediction_modes_values:0 (579944677836100459) -->
<!-- no translation found for prediction_modes_values:1 (7214414132844804570) -->
<!-- no translation found for prediction_modes_values:2 (6678546276084314171) -->
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>:已保存"</string>
<string name="alternates_for_a" msgid="2566516493365324765">"àáâãäåæ"</string>
<string name="alternates_for_e" msgid="3900510936875547555">"èéêë"</string>
@ -84,6 +78,30 @@
<string name="label_phone_key" msgid="4275497665515080551">"123"</string>
<string name="label_alpha_key" msgid="8864943487292437456">"ABC"</string>
<string name="label_alt_key" msgid="2846315350346694811">"ALT"</string>
<string name="voice_warning_title" msgid="4419354150908395008">"语音输入"</string>
<string name="voice_warning_locale_not_supported" msgid="637923019716442333">"语音输入功能当前还不支持您的语言,您只能输入英语语音。"</string>
<string name="voice_warning_may_not_understand" msgid="4611518823070986445">"语音输入是一项试验性的功能,它采用了 Google 的网络语音识别功能。"</string>
<string name="voice_warning_how_to_turn_off" msgid="5652369578498701761">"要关闭语音输入功能,请转至键盘设置。"</string>
<string name="voice_hint_dialog_message" msgid="6892342981545727994">"要使用语音输入,请按麦克风按钮或者在屏幕键盘上滑动手指。"</string>
<string name="voice_listening" msgid="467518160751321844">"请开始说话"</string>
<string name="voice_working" msgid="6666937792815731889">"正在处理"</string>
<!-- no translation found for voice_initializing (661962047129906646) -->
<skip />
<string name="voice_error" msgid="5140896300312186162">"出错,请重试。"</string>
<string name="voice_network_error" msgid="6649556447401862563">"无法连接"</string>
<string name="voice_too_much_speech" msgid="5746973620134227376">"出错,语音过长。"</string>
<string name="voice_audio_error" msgid="5072707727016414454">"音频问题"</string>
<string name="voice_server_error" msgid="7807129913977261644">"服务器出错"</string>
<string name="voice_speech_timeout" msgid="8461817525075498795">"未听到语音"</string>
<string name="voice_no_match" msgid="4285117547030179174">"未找到匹配项"</string>
<string name="voice_not_installed" msgid="5552450909753842415">"未安装语音搜索"</string>
<string name="voice_swipe_hint" msgid="6943546180310682021"><b>"提示:"</b>"在键盘上滑动手指可激活语音功能"</string>
<string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"提示:"</b>"稍后,请尝试使用语音输入标点符号,如“句号”、“逗号”或“问号”。"</string>
<string name="cancel" msgid="6830980399865683324">"取消"</string>
<string name="ok" msgid="7898366843681727667">"确定"</string>
<string name="enable_voice" msgid="8299503298530853956">"语音输入"</string>
<string name="auto_submit" msgid="9151008027068358518">"语音结束后自动提交"</string>
<string name="auto_submit_summary" msgid="4961875269610384226">"搜索或转到下一字段时自动按 Enter。"</string>
<string name="open_the_keyboard" msgid="2215920976029260466"><font size="17"><b>"打开键盘"\n</b></font><font size="3">\n</font>"轻触任意文本字段。"</string>
<string name="close_the_keyboard" msgid="6251022259044940103"><font size="17"><b>"关闭键盘"\n</b></font><font size="3">\n</font>"按“返回”键。"</string>
<string name="touch_and_hold" msgid="6154166367273010534"><font size="17"><b>"按住某个键可开启其他字符选项"\n</b></font><font size="3">\n</font>"访问标点和重音符号。"</string>
@ -95,4 +113,5 @@
<string name="popular_domain_4" msgid="35359437471311470">".edu"</string>
<!-- no translation found for language_selection_title (530749890984542339) -->
<skip />
<string name="inputMethod" msgid="7854532062009028116">"输入法"</string>
</resources>

View File

@ -47,12 +47,6 @@
<item msgid="1669461741568287396">"基本模式"</item>
<item msgid="4894328801530136615">"進階模式"</item>
</string-array>
<string name="prediction_none" msgid="2472795101338047944">"0"</string>
<string name="prediction_basic" msgid="8407291081834155558">"1"</string>
<string name="prediction_full" msgid="3765102052052510268">"2"</string>
<!-- no translation found for prediction_modes_values:0 (579944677836100459) -->
<!-- no translation found for prediction_modes_values:1 (7214414132844804570) -->
<!-- no translation found for prediction_modes_values:2 (6678546276084314171) -->
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>:已儲存"</string>
<string name="alternates_for_a" msgid="2566516493365324765">"àáâãäåæ"</string>
<string name="alternates_for_e" msgid="3900510936875547555">"èéêë"</string>
@ -63,7 +57,6 @@
<string name="alternates_for_n" msgid="6257322556221886400">"ñ"</string>
<string name="alternates_for_c" msgid="151699780720639892">"ç"</string>
<string name="alternates_for_y" msgid="1722776806607271199">"ýÿ"</string>
<string name="key_i" msgid="6483655742552255124">"i"</string>
<string name="tip_long_press" msgid="6101270866284343344">"按住按鍵可查看重音符號 (ø、ö 等)"</string>
<string name="tip_dismiss" msgid="7585579046862204381">"隨時可以透過按後退鍵 ↶ 關閉鍵盤"</string>
<string name="tip_access_symbols" msgid="6344098517525531652">"使用數字和符號"</string>
@ -84,6 +77,30 @@
<string name="label_phone_key" msgid="4275497665515080551">"123"</string>
<string name="label_alpha_key" msgid="8864943487292437456">"ABC"</string>
<string name="label_alt_key" msgid="2846315350346694811">"ALT"</string>
<string name="voice_warning_title" msgid="4419354150908395008">"語音輸入"</string>
<string name="voice_warning_locale_not_supported" msgid="637923019716442333">"語音輸入目前不支援您的語言,但是可以辨識英文。"</string>
<string name="voice_warning_may_not_understand" msgid="4611518823070986445">"語音輸入這項實驗功能運用了 Google 的網路語音辨識系統。"</string>
<string name="voice_warning_how_to_turn_off" msgid="5652369578498701761">"請前往鍵盤設定來關閉語音輸入。"</string>
<string name="voice_hint_dialog_message" msgid="6892342981545727994">"如要使用語音輸入,按下 [麥克風] 按鈕,或將手指滑過螢幕小鍵盤即可。"</string>
<string name="voice_listening" msgid="467518160751321844">"請說話"</string>
<string name="voice_working" msgid="6666937792815731889">"辨識中"</string>
<!-- no translation found for voice_initializing (661962047129906646) -->
<skip />
<string name="voice_error" msgid="5140896300312186162">"發生錯誤,請再試一次。"</string>
<string name="voice_network_error" msgid="6649556447401862563">"無法連線"</string>
<string name="voice_too_much_speech" msgid="5746973620134227376">"錯誤:語音內容過長。"</string>
<string name="voice_audio_error" msgid="5072707727016414454">"音訊問題"</string>
<string name="voice_server_error" msgid="7807129913977261644">"伺服器錯誤"</string>
<string name="voice_speech_timeout" msgid="8461817525075498795">"沒有聽到任何聲音"</string>
<string name="voice_no_match" msgid="4285117547030179174">"找不到相符的項目"</string>
<string name="voice_not_installed" msgid="5552450909753842415">"未安裝語音搜尋"</string>
<string name="voice_swipe_hint" msgid="6943546180310682021"><b>"提示:"</b>"滑過鍵盤即可說話"</string>
<string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"提示:"</b>"下次可嘗試說出標點符號,例如「句號」、「逗號」或「問號」。"</string>
<string name="cancel" msgid="6830980399865683324">"取消"</string>
<string name="ok" msgid="7898366843681727667">"確定"</string>
<string name="enable_voice" msgid="8299503298530853956">"語音輸入"</string>
<string name="auto_submit" msgid="9151008027068358518">"說話後自動提交"</string>
<string name="auto_submit_summary" msgid="4961875269610384226">"搜尋或前往下一個欄位時自動按下輸入。"</string>
<string name="open_the_keyboard" msgid="2215920976029260466"><font size="17"><b>"開啟鍵盤"\n</b></font><font size="3">\n</font>"輕觸任何文字欄位。"</string>
<string name="close_the_keyboard" msgid="6251022259044940103"><font size="17"><b>"關閉鍵盤"\n</b></font><font size="3">\n</font>"按下 Back 鍵。"</string>
<string name="touch_and_hold" msgid="6154166367273010534"><font size="17"><b>\n"輕觸並按住按鍵開啟選項"</b></font><font size="3">\n</font>"輸入標點與輕重音。"</string>
@ -95,4 +112,5 @@
<string name="popular_domain_4" msgid="35359437471311470">".edu"</string>
<!-- no translation found for language_selection_title (530749890984542339) -->
<skip />
<string name="inputMethod" msgid="7854532062009028116">"輸入方式"</string>
</resources>

View File

@ -23,4 +23,6 @@
<!-- Whether this input method should be used as the default for a locale. Override it
for latin languages. -->
<bool name="im_is_default">false</bool>
<!-- Whether or not voice input is enabled by default. -->
<bool name="voice_input_default">true</bool>
</resources>

View File

@ -32,6 +32,4 @@
<string name="alternates_for_z"></string>
<!-- Accented characters related to "l" -->
<string name="alternates_for_l"></string>
<!-- Accented characters related to "g" -->
<string name="alternates_for_g"></string>
</resources>

View File

@ -20,5 +20,5 @@
<resources>
<!-- Keycode for F1 (function) key. This one switches between language switch & comma/.com -->
<integer name="key_f1">-102</integer>
<integer name="key_f1">-103</integer>
</resources>

View File

@ -93,13 +93,13 @@
</string-array>
<!-- Don't translate -->
<string name="prediction_none" >0</string>
<string name="prediction_none" translatable="false">0</string>
<!-- Don't translate -->
<string name="prediction_basic">1</string>
<string name="prediction_basic" translatable="false">1</string>
<!-- Don't translate -->
<string name="prediction_full" >2</string>
<string name="prediction_full" translatable="false">2</string>
<string-array name="prediction_modes_values">
<string-array name="prediction_modes_values" translatable="false">
<item>@string/prediction_none</item>
<item>@string/prediction_basic</item>
<item>@string/prediction_full</item>
@ -125,13 +125,7 @@
<string name="alternates_for_c">ç</string>
<!-- Accented forms of "y" -->
<string name="alternates_for_y">ýÿ</string>
<!-- Label to display on the lower "i" key.
Usually you don't need to modify this value, but if your locale requires some variant
for this character (e.g. \\u131 "Latin Small Letter Dotoless i"), please modify this
value. -->
<string name="key_i">i</string>
<!-- Tip to long press on keys -->
<string name="tip_long_press">Hold a key down to see accents (ø, ö, etc.)</string>
<!-- Tip to dismiss keyboard -->
@ -185,6 +179,85 @@
<!-- Label for ALT modifier key. Must be short to fit on key! -->
<string name="label_alt_key">ALT</string>
<!-- Voice related labels -->
<!-- Title of the warning dialog that shows when a user initiates voice input for
the first time. -->
<string name="voice_warning_title">Voice input</string>
<!-- Message that gets put at the top of the warning dialog if the user is attempting to use
voice input in a currently unsupported locale. Voice input will work for such a user,
but it will only recognize them in English. -->
<string name="voice_warning_locale_not_supported">Voice input is not currently supported for your language, but does work in English.</string>
<!-- Message of the warning dialog that shows when a user initiates voice input for
the first time, or turns it on in settings. -->
<string name="voice_warning_may_not_understand">Voice input is an experimental feature using Google\'s networked speech recognition.</string>
<!-- An additional part of the warning dialog for voice input that only shows when the user
actually initiates voice input, rather than just turning it on in settings. -->
<string name="voice_warning_how_to_turn_off">To turn off voice input, go to keyboard settings.</string>
<!-- Message to show when user clicks the swiping hint (which says
"Swipe across keyboard to speak"). Also shown when enabling settings. -->
<string name="voice_hint_dialog_message">To use voice input, press the microphone button or slide your finger across the on-screen keyboard.</string>
<!-- Short message to tell the user the system is ready for them to speak. -->
<string name="voice_listening">Speak now</string>
<!-- Short message shown after the user finishes speaking. -->
<string name="voice_working">Working</string>
<!-- Short message shown before the user should speak. -->
<string name="voice_initializing"></string>
<!-- Short message shown when a generic error occurs. -->
<string name="voice_error">Error. Please try again.</string>
<!-- Short message shown for a network error. -->
<string name="voice_network_error">Couldn\'t connect</string>
<!-- Short message shown for a network error where the utterance was really long,
in which case we should suggest that the user speak less. -->
<string name="voice_too_much_speech">Error, too much speech.</string>
<!-- Short message shown for an audio error. -->
<string name="voice_audio_error">Audio problem</string>
<!-- Short message shown for an error with the voice server. -->
<string name="voice_server_error">Server error</string>
<!-- Short message shown when no speech is heard. -->
<string name="voice_speech_timeout">No speech heard</string>
<!-- Short message shown when the server couldn't parse any speech. -->
<string name="voice_no_match">No matches found</string>
<!-- Short message shown when the user initiates voice and voice
search is not installed. -->
<string name="voice_not_installed">Voice search not installed</string>
<!-- Short hint shown in candidate view to explain voice input. -->
<string name="voice_swipe_hint"><b>Hint:</b> Swipe across keyboard to speak</string>
<!-- Short hint shown in candidate view to explain that user can speak punctuation. -->
<string name="voice_punctuation_hint"><b>Hint:</b> Next time, try speaking punctuation like \"period\", \"comma\", or \"question mark\".</string>
<!-- Label on button to stop recognition. Must be short to fit on button. -->
<string name="cancel">Cancel</string>
<!-- Label on button when an error occurs -->
<string name="ok">OK</string>
<!-- Preferences item for enabling speech input -->
<string name="enable_voice">Voice input</string>
<!-- Press the "enter" key after the user speaks. Option on settings.-->
<string name="auto_submit">Auto submit after voice</string>
<!-- Press the "enter" key after the user speaks. Summary of option in settings.-->
<string name="auto_submit_summary">Automatically press enter when searching or going to the next field.</string>
<!-- IME Tutorial screen (ROMAN) --><skip />
<!-- appears above image showing the user to click on a TextView to show the IME -->
<string name="open_the_keyboard"><font size="17"><b>Open the keyboard\n</b></font><font size="3">\n</font>Touch any text field.</string>
@ -197,7 +270,7 @@
<!-- appears above image showing how to access keyboard settings -->
<string name="keyboard_settings"><font size="17"><b>Keyboard settings\n</b></font><font size="3">\n</font>Touch \u0026 hold the <b>\?123\</b> key.</string>
<!-- popular web domains for the locale - most popular, displayed on the keyboard -->
<string name="popular_domain_0">".com"</string>
<!-- popular web domains for the locale - item 1, displayed in the popup -->
@ -208,6 +281,9 @@
<string name="popular_domain_3">".gov"</string>
<!-- popular web domains for the locale - item 4, displayed in the popup -->
<string name="popular_domain_4">".edu"</string>
<!-- Menu item for launching Input method switcher -->
<string name="inputMethod">Input method</string>
<!-- Title for input language selection screen -->
<string name="language_selection_title">Select input languages</string>

View File

@ -165,4 +165,81 @@
android:keyWidth="20%p" android:keyEdgeFlags="right"/>
</Row>
<Row android:keyboardMode="@+id/mode_normal_voice" android:rowEdgeFlags="bottom">
<Key android:codes="-2" android:keyLabel="@string/label_symbol_key"
android:popupKeyboard="@xml/kbd_popup_template"
android:popupCharacters="_"
android:keyWidth="20%p" android:keyEdgeFlags="left"/>
<Key android:codes="-102" android:keyIcon="@drawable/sym_keyboard_mic"
android:iconPreview="@drawable/sym_keyboard_feedback_mic"
android:keyWidth="10%p"/>
<Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space"
android:iconPreview="@drawable/sym_keyboard_feedback_space"
android:keyWidth="40%p" android:isRepeatable="true"/>
<Key android:codes="46" android:keyLabel="." android:popupKeyboard="@xml/popup_punctuation"
android:keyWidth="10%p"/>
<Key android:codes="10" android:keyIcon="@drawable/sym_keyboard_return"
android:iconPreview="@drawable/sym_keyboard_feedback_return"
android:keyWidth="20%p" android:keyEdgeFlags="right"/>
</Row>
<Row android:keyboardMode="@+id/mode_url_voice" android:rowEdgeFlags="bottom">
<Key android:codes="-2" android:keyLabel="@string/label_symbol_key"
android:popupKeyboard="@xml/kbd_popup_template"
android:popupCharacters="_"
android:keyWidth="20%p" android:keyEdgeFlags="left"/>
<Key android:keyLabel="@string/popular_domain_0"
android:keyOutputText="@string/popular_domain_0"
android:popupKeyboard="@xml/popup_domains"
android:keyWidth="15%p"/>
<Key android:keyLabel="/" android:keyWidth="15%p"/>
<Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space"
android:iconPreview="@drawable/sym_keyboard_feedback_space"
android:keyWidth="15%p" android:isRepeatable="true"/>
<Key android:keyLabel="." android:popupKeyboard="@xml/popup_punctuation"
android:keyWidth="15%p"/>
<Key android:codes="10" android:keyIcon="@drawable/sym_keyboard_return"
android:iconPreview="@drawable/sym_keyboard_feedback_return"
android:keyWidth="20%p" android:keyEdgeFlags="right"/>
</Row>
<Row android:keyboardMode="@+id/mode_email_voice" android:rowEdgeFlags="bottom">
<Key android:codes="-2" android:keyLabel="@string/label_symbol_key"
android:popupKeyboard="@xml/kbd_popup_template"
android:popupCharacters="_"
android:keyWidth="20%p" android:keyEdgeFlags="left"/>
<Key android:keyLabel="\@" android:keyWidth="15%p"/>
<Key android:keyLabel="@string/popular_domain_0"
android:keyOutputText="@string/popular_domain_0"
android:popupKeyboard="@xml/popup_domains"
android:keyWidth="15%p"/>
<Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space"
android:iconPreview="@drawable/sym_keyboard_feedback_space"
android:keyWidth="15%p" android:isRepeatable="true"/>
<Key android:keyLabel="." android:popupKeyboard="@xml/popup_punctuation"
android:keyWidth="15%p"/>
<Key android:codes="10" android:keyIcon="@drawable/sym_keyboard_return"
android:iconPreview="@drawable/sym_keyboard_feedback_return"
android:keyWidth="20%p" android:keyEdgeFlags="right"/>
</Row>
<Row android:keyboardMode="@+id/mode_im_voice" android:rowEdgeFlags="bottom">
<Key android:codes="-2" android:keyLabel="@string/label_symbol_key"
android:popupKeyboard="@xml/kbd_popup_template"
android:popupCharacters="_"
android:keyWidth="20%p" android:keyEdgeFlags="left"/>
<Key android:codes="-102" android:keyIcon="@drawable/sym_keyboard_mic"
android:iconPreview="@drawable/sym_keyboard_feedback_mic"
android:keyWidth="10%p"/>
<Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space"
android:iconPreview="@drawable/sym_keyboard_feedback_space"
android:keyWidth="40%p" android:isRepeatable="true"/>
<Key android:codes="46" android:keyLabel="." android:popupKeyboard="@xml/popup_punctuation"
android:keyWidth="10%p"/>
<Key android:keyLabel=":-)" android:keyOutputText=":-) "
android:popupKeyboard="@xml/popup_smileys"
android:keyWidth="20%p" android:keyEdgeFlags="right"/>
</Row>
</Keyboard>

View File

@ -166,5 +166,81 @@
android:popupKeyboard="@xml/popup_smileys"
android:keyWidth="20%p" android:keyEdgeFlags="right"/>
</Row>
<Row android:keyboardMode="@+id/mode_normal_voice" android:rowEdgeFlags="bottom">
<Key android:codes="-2" android:keyLabel="@string/label_symbol_key"
android:popupKeyboard="@xml/kbd_popup_template"
android:popupCharacters="_"
android:keyWidth="20%p" android:keyEdgeFlags="left"/>
<Key android:codes="-102" android:keyIcon="@drawable/sym_keyboard_mic"
android:iconPreview="@drawable/sym_keyboard_feedback_mic"
android:keyWidth="10%p"/>
<Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space"
android:iconPreview="@drawable/sym_keyboard_feedback_space"
android:keyWidth="40%p" android:isRepeatable="true"/>
<Key android:codes="46" android:keyLabel="." android:popupKeyboard="@xml/popup_punctuation"
android:keyWidth="10%p"/>
<Key android:codes="10" android:keyIcon="@drawable/sym_keyboard_return"
android:iconPreview="@drawable/sym_keyboard_feedback_return"
android:keyWidth="20%p" android:keyEdgeFlags="right"/>
</Row>
<Row android:keyboardMode="@+id/mode_url_voice" android:rowEdgeFlags="bottom">
<Key android:codes="-2" android:keyLabel="@string/label_symbol_key"
android:popupKeyboard="@xml/kbd_popup_template"
android:popupCharacters="_"
android:keyWidth="20%p" android:keyEdgeFlags="left"/>
<Key android:keyLabel="@string/popular_domain_0"
android:keyOutputText="@string/popular_domain_0"
android:popupKeyboard="@xml/popup_domains"
android:keyWidth="15%p"/>
<Key android:keyLabel="/" android:keyWidth="15%p"/>
<Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space"
android:iconPreview="@drawable/sym_keyboard_feedback_space"
android:keyWidth="15%p" android:isRepeatable="true"/>
<Key android:keyLabel="." android:popupKeyboard="@xml/popup_punctuation"
android:keyWidth="15%p"/>
<Key android:codes="10" android:keyIcon="@drawable/sym_keyboard_return"
android:iconPreview="@drawable/sym_keyboard_feedback_return"
android:keyWidth="20%p" android:keyEdgeFlags="right"/>
</Row>
<Row android:keyboardMode="@+id/mode_email_voice" android:rowEdgeFlags="bottom">
<Key android:codes="-2" android:keyLabel="@string/label_symbol_key"
android:popupKeyboard="@xml/kbd_popup_template"
android:popupCharacters="_"
android:keyWidth="20%p" android:keyEdgeFlags="left"/>
<Key android:keyLabel="\@" android:keyWidth="15%p"/>
<Key android:keyLabel="@string/popular_domain_0"
android:keyOutputText="@string/popular_domain_0"
android:popupKeyboard="@xml/popup_domains"
android:keyWidth="15%p"/>
<Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space"
android:iconPreview="@drawable/sym_keyboard_feedback_space"
android:keyWidth="15%p" android:isRepeatable="true"/>
<Key android:keyLabel="." android:popupKeyboard="@xml/popup_punctuation"
android:keyWidth="15%p"/>
<Key android:codes="10" android:keyIcon="@drawable/sym_keyboard_return"
android:iconPreview="@drawable/sym_keyboard_feedback_return"
android:keyWidth="20%p" android:keyEdgeFlags="right"/>
</Row>
<Row android:keyboardMode="@+id/mode_im_voice" android:rowEdgeFlags="bottom">
<Key android:codes="-2" android:keyLabel="@string/label_symbol_key"
android:popupKeyboard="@xml/kbd_popup_template"
android:popupCharacters="_"
android:keyWidth="20%p" android:keyEdgeFlags="left"/>
<Key android:codes="-102" android:keyIcon="@drawable/sym_keyboard_mic"
android:iconPreview="@drawable/sym_keyboard_feedback_mic"
android:keyWidth="10%p"/>
<Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space"
android:iconPreview="@drawable/sym_keyboard_feedback_space"
android:keyWidth="40%p" android:isRepeatable="true"/>
<Key android:codes="46" android:keyLabel="." android:popupKeyboard="@xml/popup_punctuation"
android:keyWidth="10%p"/>
<Key android:keyLabel=":-)" android:keyOutputText=":-) "
android:popupKeyboard="@xml/popup_smileys"
android:keyWidth="20%p" android:keyEdgeFlags="right"/>
</Row>
</Keyboard>

View File

@ -46,7 +46,7 @@
android:popupKeyboard="@xml/kbd_popup_template"
android:popupCharacters="@string/alternates_for_u"
/>
<Key android:keyLabel="@string/key_i"
<Key android:codes="105" android:keyLabel="i"
android:popupKeyboard="@xml/kbd_popup_template"
android:popupCharacters="@string/alternates_for_i"
/>
@ -70,14 +70,11 @@
android:popupKeyboard="@xml/kbd_popup_template"
android:popupCharacters="@string/alternates_for_d"/>
<Key android:codes="102" android:keyLabel="f"/>
<Key android:codes="103" android:keyLabel="g"
android:popupKeyboard="@xml/kbd_popup_template"
android:popupCharacters="@string/alternates_for_g"/>
/>
<Key android:codes="103" android:keyLabel="g"/>
<Key android:codes="104" android:keyLabel="h"/>
<Key android:codes="106" android:keyLabel="j"/>
<Key android:codes="107" android:keyLabel="k"/>
<Key android:codes="108" android:keyLabel="l"
<Key android:codes="108" android:keyLabel="l"
android:popupKeyboard="@xml/kbd_popup_template"
android:popupCharacters="@string/alternates_for_l"
android:keyEdgeFlags="right"/>
@ -126,6 +123,24 @@
android:keyWidth="20%p" android:keyEdgeFlags="right"/>
</Row>
<Row android:keyboardMode="@+id/mode_normal_voice" android:rowEdgeFlags="bottom">
<Key android:codes="-2" android:keyLabel="@string/label_symbol_key"
android:popupKeyboard="@xml/kbd_popup_template"
android:popupCharacters="_"
android:keyWidth="20%p" android:keyEdgeFlags="left"/>
<Key android:codes="-102" android:keyIcon="@drawable/sym_keyboard_mic"
android:iconPreview="@drawable/sym_keyboard_feedback_mic"
android:keyWidth="10%p"/>
<Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space"
android:iconPreview="@drawable/sym_keyboard_feedback_space"
android:keyWidth="40%p" android:isRepeatable="true"/>
<Key android:codes="46" android:keyLabel="." android:popupKeyboard="@xml/popup_punctuation"
android:keyWidth="10%p"/>
<Key android:codes="10" android:keyIcon="@drawable/sym_keyboard_return"
android:iconPreview="@drawable/sym_keyboard_feedback_return"
android:keyWidth="20%p" android:keyEdgeFlags="right"/>
</Row>
<Row android:keyboardMode="@+id/mode_url" android:rowEdgeFlags="bottom">
<Key android:codes="-2" android:keyLabel="@string/label_symbol_key"
android:popupKeyboard="@xml/kbd_popup_template"
@ -148,6 +163,26 @@
android:keyWidth="20%p" android:keyEdgeFlags="right"/>
</Row>
<Row android:keyboardMode="@+id/mode_url_voice" android:rowEdgeFlags="bottom">
<Key android:codes="-2" android:keyLabel="@string/label_symbol_key"
android:popupKeyboard="@xml/kbd_popup_template"
android:popupCharacters="_"
android:keyWidth="20%p" android:keyEdgeFlags="left"/>
<Key android:keyLabel="@string/popular_domain_0"
android:keyOutputText="@string/popular_domain_0"
android:popupKeyboard="@xml/popup_domains"
android:keyWidth="15%p"/>
<Key android:keyLabel="/" android:keyWidth="15%p"/>
<Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space"
android:iconPreview="@drawable/sym_keyboard_feedback_space"
android:keyWidth="15%p" android:isRepeatable="true"/>
<Key android:keyLabel="." android:popupKeyboard="@xml/popup_punctuation"
android:keyWidth="15%p"/>
<Key android:codes="10" android:keyIcon="@drawable/sym_keyboard_return"
android:iconPreview="@drawable/sym_keyboard_feedback_return"
android:keyWidth="20%p" android:keyEdgeFlags="right"/>
</Row>
<Row android:keyboardMode="@+id/mode_email" android:rowEdgeFlags="bottom">
<Key android:codes="-2" android:keyLabel="@string/label_symbol_key"
android:popupKeyboard="@xml/kbd_popup_template"
@ -170,6 +205,26 @@
android:keyWidth="20%p" android:keyEdgeFlags="right"/>
</Row>
<Row android:keyboardMode="@+id/mode_email_voice" android:rowEdgeFlags="bottom">
<Key android:codes="-2" android:keyLabel="@string/label_symbol_key"
android:popupKeyboard="@xml/kbd_popup_template"
android:popupCharacters="_"
android:keyWidth="20%p" android:keyEdgeFlags="left"/>
<Key android:keyLabel="\@" android:keyWidth="15%p"/>
<Key android:keyLabel="@string/popular_domain_0"
android:keyOutputText="@string/popular_domain_0"
android:popupKeyboard="@xml/popup_domains"
android:keyWidth="15%p"/>
<Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space"
android:iconPreview="@drawable/sym_keyboard_feedback_space"
android:keyWidth="15%p" android:isRepeatable="true"/>
<Key android:keyLabel="." android:popupKeyboard="@xml/popup_punctuation"
android:keyWidth="15%p"/>
<Key android:codes="10" android:keyIcon="@drawable/sym_keyboard_return"
android:iconPreview="@drawable/sym_keyboard_feedback_return"
android:keyWidth="20%p" android:keyEdgeFlags="right"/>
</Row>
<Row android:keyboardMode="@+id/mode_im" android:rowEdgeFlags="bottom">
<Key android:codes="-2" android:keyLabel="@string/label_symbol_key"
android:popupKeyboard="@xml/kbd_popup_template"
@ -186,5 +241,23 @@
android:popupKeyboard="@xml/popup_smileys"
android:keyWidth="20%p" android:keyEdgeFlags="right"/>
</Row>
<Row android:keyboardMode="@+id/mode_im_voice" android:rowEdgeFlags="bottom">
<Key android:codes="-2" android:keyLabel="@string/label_symbol_key"
android:popupKeyboard="@xml/kbd_popup_template"
android:popupCharacters="_"
android:keyWidth="20%p" android:keyEdgeFlags="left"/>
<Key android:codes="-102" android:keyIcon="@drawable/sym_keyboard_mic"
android:iconPreview="@drawable/sym_keyboard_feedback_mic"
android:keyWidth="10%p"/>
<Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space"
android:iconPreview="@drawable/sym_keyboard_feedback_space"
android:keyWidth="40%p" android:isRepeatable="true"/>
<Key android:codes="46" android:keyLabel="." android:popupKeyboard="@xml/popup_punctuation"
android:keyWidth="10%p"/>
<Key android:keyLabel=":-)" android:keyOutputText=":-) "
android:popupKeyboard="@xml/popup_smileys"
android:keyWidth="20%p" android:keyEdgeFlags="right"/>
</Row>
</Keyboard>

View File

@ -21,6 +21,6 @@
<!-- for the Input Method Manager. -->
<input-method xmlns:android="http://schemas.android.com/apk/res/android"
android:settingsActivity="com.android.inputmethod.latin.LatinIMESettings"
android:isDefault="@bool/im_is_default"
android:settingsActivity="com.google.android.voicesearch.LatinIMEWithVoiceSettings"
android:isDefault="true"
/>

View File

@ -37,6 +37,12 @@
android:defaultValue="true"
/>
<CheckBoxPreference
android:key="enable_voice_input"
android:title="@string/enable_voice"
android:persistent="false"
android:defaultValue="@bool/voice_input_default"
/>
<PreferenceScreen
android:title="@string/language_selection_title">
<intent

View File

@ -113,7 +113,7 @@ public class CandidateView extends View {
public CandidateView(Context context, AttributeSet attrs) {
super(context, attrs);
mSelectionHighlight = context.getResources().getDrawable(
com.android.internal.R.drawable.list_selector_background_pressed);
R.drawable.list_selector_background_pressed);
LayoutInflater inflate =
(LayoutInflater) context

View File

@ -0,0 +1,188 @@
/*
* Copyright (C) 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.android.inputmethod.latin;
import com.android.inputmethod.voice.GoogleSettingsUtil;
import android.content.ContentResolver;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.view.inputmethod.InputConnection;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
/**
* Logic to determine when to display hints on usage to the user.
*/
public class Hints {
public interface Display {
public void showHint(int viewResource);
}
private static final String TAG = "Hints";
private static final String PREF_VOICE_HINT_NUM_UNIQUE_DAYS_SHOWN =
"voice_hint_num_unique_days_shown";
private static final String PREF_VOICE_HINT_LAST_TIME_SHOWN =
"voice_hint_last_time_shown";
private static final String PREF_VOICE_INPUT_LAST_TIME_USED =
"voice_input_last_time_used";
private static final String PREF_VOICE_PUNCTUATION_HINT_VIEW_COUNT =
"voice_punctuation_hint_view_count";
private static final int DEFAULT_SWIPE_HINT_MAX_DAYS_TO_SHOW = 7;
private static final int DEFAULT_PUNCTUATION_HINT_MAX_DISPLAYS = 7;
private Context mContext;
private Display mDisplay;
private boolean mVoiceResultContainedPunctuation;
private int mSwipeHintMaxDaysToShow;
private int mPunctuationHintMaxDisplays;
// Only show punctuation hint if voice result did not contain punctuation.
static final Map<CharSequence, String> SPEAKABLE_PUNCTUATION
= new HashMap<CharSequence, String>();
static {
SPEAKABLE_PUNCTUATION.put(",", "comma");
SPEAKABLE_PUNCTUATION.put(".", "period");
SPEAKABLE_PUNCTUATION.put("?", "question mark");
}
public Hints(Context context, Display display) {
mContext = context;
mDisplay = display;
ContentResolver cr = mContext.getContentResolver();
mSwipeHintMaxDaysToShow = GoogleSettingsUtil.getGservicesInt(
cr,
GoogleSettingsUtil.LATIN_IME_VOICE_INPUT_SWIPE_HINT_MAX_DAYS,
DEFAULT_SWIPE_HINT_MAX_DAYS_TO_SHOW);
mPunctuationHintMaxDisplays = GoogleSettingsUtil.getGservicesInt(
cr,
GoogleSettingsUtil.LATIN_IME_VOICE_INPUT_PUNCTUATION_HINT_MAX_DISPLAYS,
DEFAULT_PUNCTUATION_HINT_MAX_DISPLAYS);
}
public boolean showSwipeHintIfNecessary(boolean fieldRecommended) {
if (fieldRecommended && shouldShowSwipeHint()) {
showHint(R.layout.voice_swipe_hint);
return true;
}
return false;
}
public boolean showPunctuationHintIfNecessary(InputConnection ic) {
if (!mVoiceResultContainedPunctuation
&& ic != null
&& getAndIncrementPref(PREF_VOICE_PUNCTUATION_HINT_VIEW_COUNT)
< mPunctuationHintMaxDisplays) {
CharSequence charBeforeCursor = ic.getTextBeforeCursor(1, 0);
if (SPEAKABLE_PUNCTUATION.containsKey(charBeforeCursor)) {
showHint(R.layout.voice_punctuation_hint);
return true;
}
}
return false;
}
public void registerVoiceResult(String text) {
// Update the current time as the last time voice input was used.
SharedPreferences.Editor editor =
PreferenceManager.getDefaultSharedPreferences(mContext).edit();
editor.putLong(PREF_VOICE_INPUT_LAST_TIME_USED, System.currentTimeMillis());
editor.commit();
mVoiceResultContainedPunctuation = false;
for (CharSequence s : SPEAKABLE_PUNCTUATION.keySet()) {
if (text.indexOf(s.toString()) >= 0) {
mVoiceResultContainedPunctuation = true;
break;
}
}
}
private boolean shouldShowSwipeHint() {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
int numUniqueDaysShown = sp.getInt(PREF_VOICE_HINT_NUM_UNIQUE_DAYS_SHOWN, 0);
// If we've already shown the hint for enough days, we'll return false.
if (numUniqueDaysShown < mSwipeHintMaxDaysToShow) {
long lastTimeVoiceWasUsed = sp.getLong(PREF_VOICE_INPUT_LAST_TIME_USED, 0);
// If the user has used voice today, we'll return false. (We don't show the hint on
// any day that the user has already used voice.)
if (!isFromToday(lastTimeVoiceWasUsed)) {
return true;
}
}
return false;
}
/**
* Determines whether the provided time is from some time today (i.e., this day, month,
* and year).
*/
private boolean isFromToday(long timeInMillis) {
if (timeInMillis == 0) return false;
Calendar today = Calendar.getInstance();
today.setTimeInMillis(System.currentTimeMillis());
Calendar timestamp = Calendar.getInstance();
timestamp.setTimeInMillis(timeInMillis);
return (today.get(Calendar.YEAR) == timestamp.get(Calendar.YEAR) &&
today.get(Calendar.DAY_OF_MONTH) == timestamp.get(Calendar.DAY_OF_MONTH) &&
today.get(Calendar.MONTH) == timestamp.get(Calendar.MONTH));
}
private void showHint(int hintViewResource) {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
int numUniqueDaysShown = sp.getInt(PREF_VOICE_HINT_NUM_UNIQUE_DAYS_SHOWN, 0);
long lastTimeHintWasShown = sp.getLong(PREF_VOICE_HINT_LAST_TIME_SHOWN, 0);
// If this is the first time the hint is being shown today, increase the saved values
// to represent that. We don't need to increase the last time the hint was shown unless
// it is a different day from the current value.
if (!isFromToday(lastTimeHintWasShown)) {
SharedPreferences.Editor editor = sp.edit();
editor.putInt(PREF_VOICE_HINT_NUM_UNIQUE_DAYS_SHOWN, numUniqueDaysShown + 1);
editor.putLong(PREF_VOICE_HINT_LAST_TIME_SHOWN, System.currentTimeMillis());
editor.commit();
}
if (mDisplay != null) {
mDisplay.showHint(hintViewResource);
}
}
private int getAndIncrementPref(String pref) {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
int value = sp.getInt(pref, 0);
SharedPreferences.Editor editor = sp.edit();
editor.putInt(pref, value + 1);
editor.commit();
return value;
}
}

View File

@ -48,6 +48,13 @@ public class KeyboardSwitcher {
private static final int SYMBOLS_MODE_STATE_SYMBOL = 2;
LatinKeyboardView mInputView;
private static final int[] ALPHABET_MODES = {
KEYBOARDMODE_NORMAL,
KEYBOARDMODE_URL,
KEYBOARDMODE_EMAIL,
KEYBOARDMODE_IM};
//LatinIME mContext;
Context mContext;
InputMethodService mInputMethodService;
@ -56,11 +63,17 @@ public class KeyboardSwitcher {
private KeyboardId mCurrentId;
private Map<KeyboardId, LatinKeyboard> mKeyboards;
private int mMode;
/**
* Maps keyboard mode to the equivalent mode with voice.
*/
private Map<Integer, Integer> mModeToVoice;
private int mMode; /** One of the MODE_XXX values */
private int mImeOptions;
private int mTextMode = MODE_TEXT_QWERTY;
private boolean mIsSymbols;
private boolean mHasVoice;
private boolean mPreferSymbols;
private int mSymbolsModeState = SYMBOLS_MODE_STATE_NONE;
@ -73,6 +86,11 @@ public class KeyboardSwitcher {
mKeyboards = new HashMap<KeyboardId, LatinKeyboard>();
mSymbolsId = new KeyboardId(R.xml.kbd_symbols);
mSymbolsShiftedId = new KeyboardId(R.xml.kbd_symbols_shift);
mModeToVoice = new HashMap<Integer, Integer>();
mModeToVoice.put(R.id.mode_normal, R.id.mode_normal_voice);
mModeToVoice.put(R.id.mode_url, R.id.mode_url_voice);
mModeToVoice.put(R.id.mode_email, R.id.mode_email_voice);
mModeToVoice.put(R.id.mode_im, R.id.mode_im_voice);
mInputMethodService = ims;
}
@ -110,12 +128,12 @@ public class KeyboardSwitcher {
*/
private static class KeyboardId {
public int mXml;
public int mMode;
public int mKeyboardMode; /** A KEYBOARDMODE_XXX value */
public boolean mEnableShiftLock;
public KeyboardId(int xml, int mode, boolean enableShiftLock) {
this.mXml = xml;
this.mMode = mode;
this.mKeyboardMode = mode;
this.mEnableShiftLock = enableShiftLock;
}
@ -128,27 +146,40 @@ public class KeyboardSwitcher {
}
public boolean equals(KeyboardId other) {
return other.mXml == this.mXml && other.mMode == this.mMode;
return other.mXml == this.mXml
&& other.mKeyboardMode == this.mKeyboardMode
&& other.mEnableShiftLock == this.mEnableShiftLock;
}
public int hashCode() {
return (mXml + 1) * (mMode + 1) * (mEnableShiftLock ? 2 : 1);
return (mXml + 1) * (mKeyboardMode + 1) * (mEnableShiftLock ? 2 : 1);
}
}
void setKeyboardMode(int mode, int imeOptions) {
void setVoiceMode(boolean enableVoice) {
setKeyboardMode(mMode, mImeOptions, enableVoice, mIsSymbols);
}
void setKeyboardMode(int mode, int imeOptions, boolean enableVoice) {
mSymbolsModeState = SYMBOLS_MODE_STATE_NONE;
mPreferSymbols = mode == MODE_SYMBOLS;
setKeyboardMode(mode == MODE_SYMBOLS ? MODE_TEXT : mode, imeOptions,
setKeyboardMode(mode == MODE_SYMBOLS ? MODE_TEXT : mode, imeOptions, enableVoice,
mPreferSymbols);
}
void setKeyboardMode(int mode, int imeOptions, boolean isSymbols) {
void setKeyboardMode(int mode, int imeOptions,
boolean enableVoice, boolean isSymbols) {
mMode = mode;
mImeOptions = imeOptions;
mHasVoice = enableVoice;
mIsSymbols = isSymbols;
mInputView.setPreviewEnabled(true);
KeyboardId id = getKeyboardId(mode, imeOptions, isSymbols);
if (enableVoice && mModeToVoice.containsKey(id.mKeyboardMode)) {
id.mKeyboardMode = mModeToVoice.get(id.mKeyboardMode);
}
LatinKeyboard keyboard = getKeyboard(id);
if (mode == MODE_PHONE) {
@ -166,7 +197,6 @@ public class KeyboardSwitcher {
keyboard.setShifted(false);
keyboard.setShiftLocked(keyboard.isShiftLocked());
keyboard.setImeOptions(mContext.getResources(), mMode, imeOptions);
}
private LatinKeyboard getKeyboard(KeyboardId id) {
@ -177,11 +207,16 @@ public class KeyboardSwitcher {
conf.locale = mInputLocale;
orig.updateConfiguration(conf, null);
LatinKeyboard keyboard = new LatinKeyboard(
mContext, id.mXml, id.mMode);
if (id.mMode == KEYBOARDMODE_NORMAL
|| id.mMode == KEYBOARDMODE_URL
|| id.mMode == KEYBOARDMODE_IM
|| id.mMode == KEYBOARDMODE_EMAIL) {
mContext, id.mXml, id.mKeyboardMode);
if (id.mKeyboardMode == KEYBOARDMODE_NORMAL
|| id.mKeyboardMode == KEYBOARDMODE_URL
|| id.mKeyboardMode == KEYBOARDMODE_IM
|| id.mKeyboardMode == KEYBOARDMODE_EMAIL
|| id.mKeyboardMode == R.id.mode_normal_voice
|| id.mKeyboardMode == R.id.mode_url_voice
|| id.mKeyboardMode == R.id.mode_im_voice
|| id.mKeyboardMode == R.id.mode_email_voice
) {
keyboard.setExtension(R.xml.kbd_extension);
}
@ -241,7 +276,7 @@ public class KeyboardSwitcher {
mTextMode = position;
}
if (isTextMode()) {
setKeyboardMode(MODE_TEXT, mImeOptions);
setKeyboardMode(MODE_TEXT, mImeOptions, mHasVoice);
}
}
@ -250,11 +285,13 @@ public class KeyboardSwitcher {
}
boolean isAlphabetMode() {
KeyboardId current = mCurrentId;
return current.mMode == KEYBOARDMODE_NORMAL
|| current.mMode == KEYBOARDMODE_URL
|| current.mMode == KEYBOARDMODE_EMAIL
|| current.mMode == KEYBOARDMODE_IM;
int currentMode = mCurrentId.mKeyboardMode;
for (Integer mode : ALPHABET_MODES) {
if (currentMode == mode || currentMode == mModeToVoice.get(mode)) {
return true;
}
}
return false;
}
void toggleShift() {
@ -278,7 +315,7 @@ public class KeyboardSwitcher {
}
void toggleSymbols() {
setKeyboardMode(mMode, mImeOptions, !mIsSymbols);
setKeyboardMode(mMode, mImeOptions, mHasVoice, !mIsSymbols);
if (mIsSymbols && !mPreferSymbols) {
mSymbolsModeState = SYMBOLS_MODE_STATE_BEGIN;
} else {

View File

@ -16,13 +16,7 @@
package com.android.inputmethod.latin;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import com.android.inputmethod.latin.UserDictionary;
import com.google.android.collect.Lists;
import android.app.AlertDialog;
import android.backup.BackupManager;
@ -53,23 +47,42 @@ import android.util.Log;
import android.util.PrintWriterPrinter;
import android.util.Printer;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.inputmethod.CompletionInfo;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.ExtractedText;
import android.view.inputmethod.ExtractedTextRequest;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;
import com.android.inputmethod.voice.EditingUtil;
import com.android.inputmethod.voice.FieldContext;
import com.android.inputmethod.voice.GoogleSettingsUtil;
import com.android.inputmethod.voice.VoiceInput;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
/**
* Input method implementation for Qwerty'ish keyboard.
*/
public class LatinIME extends InputMethodService
public class LatinIME extends InputMethodService
implements KeyboardView.OnKeyboardActionListener,
SharedPreferences.OnSharedPreferenceChangeListener {
VoiceInput.UiListener,
SharedPreferences.OnSharedPreferenceChangeListener {
private static final String TAG = "LatinIME";
static final boolean DEBUG = false;
static final boolean TRACE = false;
static final boolean VOICE_INSTALLED = true;
static final boolean ENABLE_VOICE_BUTTON = true;
private static final String PREF_VIBRATE_ON = "vibrate_on";
private static final String PREF_SOUND_ON = "sound_on";
@ -77,12 +90,53 @@ public class LatinIME extends InputMethodService
private static final String PREF_QUICK_FIXES = "quick_fixes";
private static final String PREF_SHOW_SUGGESTIONS = "show_suggestions";
private static final String PREF_AUTO_COMPLETE = "auto_complete";
private static final String PREF_ENABLE_VOICE = "enable_voice_input";
private static final String PREF_VOICE_SERVER_URL = "voice_server_url";
// Whether or not the user has used voice input before (and thus, whether to show the
// first-run warning dialog or not).
private static final String PREF_HAS_USED_VOICE_INPUT = "has_used_voice_input";
// Whether or not the user has used voice input from an unsupported locale UI before.
// For example, the user has a Chinese UI but activates voice input.
private static final String PREF_HAS_USED_VOICE_INPUT_UNSUPPORTED_LOCALE =
"has_used_voice_input_unsupported_locale";
// A list of locales which are supported by default for voice input, unless we get a
// different list from Gservices.
public static final String DEFAULT_VOICE_INPUT_SUPPORTED_LOCALES =
"en " +
"en_US " +
"en_GB " +
"en_AU " +
"en_CA " +
"en_IE " +
"en_IN " +
"en_NZ " +
"en_SG " +
"en_ZA ";
// 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.
private static final String IME_OPTION_NO_MICROPHONE = "nm";
public static final String PREF_SELECTED_LANGUAGES = "selected_languages";
public static final String PREF_INPUT_LANGUAGE = "input_language";
private static final int MSG_UPDATE_SUGGESTIONS = 0;
private static final int MSG_START_TUTORIAL = 1;
private static final int MSG_UPDATE_SHIFT_STATE = 2;
private static final int MSG_VOICE_RESULTS = 3;
private static final int MSG_START_LISTENING_AFTER_SWIPE = 4;
// If we detect a swipe gesture within N ms of typing, then swipe is
// ignored, since it may in fact be two key presses in quick succession.
private static final long MIN_MILLIS_AFTER_TYPING_BEFORE_SWIPE = 1000;
// If we detect a swipe gesture, and the user types N ms later, cancel the
// swipe since it was probably a false trigger.
private static final long MIN_MILLIS_AFTER_SWIPE_TO_WAIT_FOR_TYPING = 500;
// How many continuous deletes at which to start deleting at a higher speed.
private static final int DELETE_ACCELERATE_AT = 20;
@ -102,7 +156,7 @@ public class LatinIME extends InputMethodService
// Contextual menu positions
private static final int POS_SETTINGS = 0;
private static final int POS_METHOD = 1;
private LatinKeyboardView mInputView;
private CandidateViewContainer mCandidateViewContainer;
private CandidateView mCandidateView;
@ -110,6 +164,7 @@ public class LatinIME extends InputMethodService
private CompletionInfo[] mCompletions;
private AlertDialog mOptionsDialog;
private AlertDialog mVoiceWarningDialog;
KeyboardSwitcher mKeyboardSwitcher;
@ -117,6 +172,8 @@ public class LatinIME extends InputMethodService
private ContactsDictionary mContactsDictionary;
private ExpandableDictionary mAutoDictionary;
private Hints mHints;
Resources mResources;
private String mLocale;
@ -125,6 +182,13 @@ public class LatinIME extends InputMethodService
private WordComposer mWord = new WordComposer();
private int mCommittedLength;
private boolean mPredicting;
private boolean mRecognizing;
private boolean mAfterVoiceInput;
private boolean mImmediatelyAfterVoiceInput;
private boolean mShowingVoiceSuggestions;
private boolean mImmediatelyAfterVoiceSuggestions;
private boolean mVoiceInputHighlighted;
private boolean mEnableVoiceButton;
private CharSequence mBestWord;
private boolean mPredictionOn;
private boolean mCompletionOn;
@ -133,14 +197,22 @@ public class LatinIME extends InputMethodService
private boolean mAutoCorrectEnabled;
private boolean mAutoCorrectOn;
private boolean mCapsLock;
private boolean mPasswordText;
private boolean mEmailText;
private boolean mVibrateOn;
private boolean mSoundOn;
private boolean mAutoCap;
private boolean mQuickFixes;
private boolean mHasUsedVoiceInput;
private boolean mHasUsedVoiceInputUnsupportedLocale;
private boolean mLocaleSupportedForVoiceInput;
private boolean mShowSuggestions;
private boolean mSuggestionShouldReplaceCurrentWord;
private boolean mIsShowingHint;
private int mCorrectionMode;
private boolean mEnableVoice = true;
private int mOrientation;
// Indicates whether the suggestion strip is to be on in landscape
private boolean mJustAccepted;
private CharSequence mJustRevertedSeparator;
@ -159,6 +231,17 @@ public class LatinIME extends InputMethodService
private String mWordSeparators;
private String mSentenceSeparators;
private VoiceInput mVoiceInput;
private VoiceResults mVoiceResults = new VoiceResults();
private long mSwipeTriggerTimeMillis;
// For each word, a list of potential replacements, usually from voice.
private Map<String, List<CharSequence>> mWordToSuggestions = new HashMap();
private class VoiceResults {
List<String> candidates;
Map<String, List<CharSequence>> alternatives;
}
private int mCurrentInputLocale = 0;
private String mInputLanguage;
private String[] mSelectedLanguageArray;
@ -186,6 +269,13 @@ public class LatinIME extends InputMethodService
case MSG_UPDATE_SHIFT_STATE:
updateShiftKeyState(getCurrentInputEditorInfo());
break;
case MSG_VOICE_RESULTS:
handleVoiceResults();
break;
case MSG_START_LISTENING_AFTER_SWIPE:
if (mLastKeyTime < mSwipeTriggerTimeMillis) {
startListening(true);
}
}
}
};
@ -212,6 +302,19 @@ public class LatinIME extends InputMethodService
// register to receive ringer mode changes for silent mode
IntentFilter filter = new IntentFilter(AudioManager.RINGER_MODE_CHANGED_ACTION);
registerReceiver(mReceiver, filter);
if (VOICE_INSTALLED) {
mVoiceInput = new VoiceInput(this, this);
mHints = new Hints(this, new Hints.Display() {
public void showHint(int viewResource) {
LayoutInflater inflater = (LayoutInflater) getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(viewResource, null);
setCandidatesView(view);
setCandidatesViewShown(true);
mIsShowingHint = true;
}
});
}
PreferenceManager.getDefaultSharedPreferences(this)
.registerOnSharedPreferenceChangeListener(this);
}
@ -228,7 +331,6 @@ public class LatinIME extends InputMethodService
mSuggest.close();
}
mSuggest = new Suggest(this, R.raw.main);
if (mUserDictionary != null) mUserDictionary.close();
mUserDictionary = new UserDictionary(this);
if (mContactsDictionary == null) {
mContactsDictionary = new ContactsDictionary(this);
@ -248,10 +350,14 @@ public class LatinIME extends InputMethodService
orig.updateConfiguration(conf, orig.getDisplayMetrics());
}
@Override public void onDestroy() {
@Override
public void onDestroy() {
mUserDictionary.close();
mContactsDictionary.close();
unregisterReceiver(mReceiver);
if (VOICE_INSTALLED) {
mVoiceInput.destroy();
}
super.onDestroy();
}
@ -262,7 +368,9 @@ public class LatinIME extends InputMethodService
}
// If orientation changed while predicting, commit the change
if (conf.orientation != mOrientation) {
commitTyped(getCurrentInputConnection());
InputConnection ic = getCurrentInputConnection();
commitTyped(ic);
if (ic != null) ic.finishComposingText(); // For voice input
mOrientation = conf.orientation;
}
reloadKeyboards();
@ -276,10 +384,27 @@ public class LatinIME extends InputMethodService
mKeyboardSwitcher.setInputView(mInputView);
mKeyboardSwitcher.makeKeyboards(true);
mInputView.setOnKeyboardActionListener(this);
mKeyboardSwitcher.setKeyboardMode(KeyboardSwitcher.MODE_TEXT, 0);
mKeyboardSwitcher.setKeyboardMode(
KeyboardSwitcher.MODE_TEXT, 0,
shouldShowVoiceButton(makeFieldContext(), getCurrentInputEditorInfo()));
return mInputView;
}
@Override
public void onInitializeInterface() {
// Create a new view associated with voice input if the old
// view is stuck in another layout (e.g. if switching from
// portrait to landscape while speaking)
// NOTE: This must be done here because for some reason
// onCreateInputView isn't called after an orientation change while
// speech rec is in progress.
if (mVoiceInput != null && mVoiceInput.getView().getParent() != null) {
mVoiceInput.newView();
}
super.onInitializeInterface();
}
@Override
public View onCreateCandidatesView() {
mKeyboardSwitcher.makeKeyboards(true);
@ -308,32 +433,54 @@ public class LatinIME extends InputMethodService
TextEntryState.newSession(this);
// Most such things we decide below in the switch statement, but we need to know
// now whether this is a password text field, because we need to know now (before
// the switch statement) whether we want to enable the voice button.
mPasswordText = false;
int variation = attribute.inputType & EditorInfo.TYPE_MASK_VARIATION;
if (variation == EditorInfo.TYPE_TEXT_VARIATION_PASSWORD ||
variation == EditorInfo.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD) {
mPasswordText = true;
}
mEnableVoiceButton = shouldShowVoiceButton(makeFieldContext(), attribute);
mAfterVoiceInput = false;
mImmediatelyAfterVoiceInput = false;
mShowingVoiceSuggestions = false;
mImmediatelyAfterVoiceSuggestions = false;
mVoiceInputHighlighted = false;
boolean disableAutoCorrect = false;
mWordToSuggestions.clear();
mInputTypeNoAutoCorrect = false;
mPredictionOn = false;
mCompletionOn = false;
mCompletions = null;
mCapsLock = false;
switch (attribute.inputType&EditorInfo.TYPE_MASK_CLASS) {
mEmailText = false;
switch (attribute.inputType & EditorInfo.TYPE_MASK_CLASS) {
case EditorInfo.TYPE_CLASS_NUMBER:
case EditorInfo.TYPE_CLASS_DATETIME:
mKeyboardSwitcher.setKeyboardMode(KeyboardSwitcher.MODE_SYMBOLS,
attribute.imeOptions);
attribute.imeOptions, mEnableVoiceButton);
break;
case EditorInfo.TYPE_CLASS_PHONE:
mKeyboardSwitcher.setKeyboardMode(KeyboardSwitcher.MODE_PHONE,
attribute.imeOptions);
attribute.imeOptions, mEnableVoiceButton);
break;
case EditorInfo.TYPE_CLASS_TEXT:
mKeyboardSwitcher.setKeyboardMode(KeyboardSwitcher.MODE_TEXT,
attribute.imeOptions);
attribute.imeOptions, mEnableVoiceButton);
//startPrediction();
mPredictionOn = true;
// Make sure that passwords are not displayed in candidate view
int variation = attribute.inputType & EditorInfo.TYPE_MASK_VARIATION;
if (variation == EditorInfo.TYPE_TEXT_VARIATION_PASSWORD ||
variation == EditorInfo.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD ) {
mPredictionOn = false;
}
if (variation == EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS) {
mEmailText = true;
}
if (variation == EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS
|| variation == EditorInfo.TYPE_TEXT_VARIATION_PERSON_NAME) {
mAutoSpace = false;
@ -343,14 +490,14 @@ public class LatinIME extends InputMethodService
if (variation == EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS) {
mPredictionOn = false;
mKeyboardSwitcher.setKeyboardMode(KeyboardSwitcher.MODE_EMAIL,
attribute.imeOptions);
attribute.imeOptions, mEnableVoiceButton);
} else if (variation == EditorInfo.TYPE_TEXT_VARIATION_URI) {
mPredictionOn = false;
mKeyboardSwitcher.setKeyboardMode(KeyboardSwitcher.MODE_URL,
attribute.imeOptions);
attribute.imeOptions, mEnableVoiceButton);
} else if (variation == EditorInfo.TYPE_TEXT_VARIATION_SHORT_MESSAGE) {
mKeyboardSwitcher.setKeyboardMode(KeyboardSwitcher.MODE_IM,
attribute.imeOptions);
attribute.imeOptions, mEnableVoiceButton);
} else if (variation == EditorInfo.TYPE_TEXT_VARIATION_FILTER) {
mPredictionOn = false;
} else if (variation == EditorInfo.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT) {
@ -379,17 +526,25 @@ public class LatinIME extends InputMethodService
break;
default:
mKeyboardSwitcher.setKeyboardMode(KeyboardSwitcher.MODE_TEXT,
attribute.imeOptions);
attribute.imeOptions, mEnableVoiceButton);
updateShiftKeyState(attribute);
}
mInputView.closing();
mComposing.setLength(0);
mPredicting = false;
mDeleteCount = 0;
setCandidatesViewShown(false);
if (mCandidateView != null) mCandidateView.setSuggestions(null, false, false, false);
loadSettings();
setCandidatesViewShown(false);
setSuggestions(null, false, false, false);
// Override auto correct
if (disableAutoCorrect) {
mAutoCorrectOn = false;
if (mCorrectionMode == Suggest.CORRECTION_FULL) {
mCorrectionMode = Suggest.CORRECTION_BASIC;
}
}
// If the dictionary is not big enough, don't auto correct
mHasDictionary = mSuggest.hasMainDictionary();
@ -404,10 +559,31 @@ public class LatinIME extends InputMethodService
@Override
public void onFinishInput() {
super.onFinishInput();
if (mAfterVoiceInput) mVoiceInput.logInputEnded();
mVoiceInput.flushLogs();
if (mInputView != null) {
mInputView.closing();
}
if (VOICE_INSTALLED & mRecognizing) {
mVoiceInput.cancel();
}
}
@Override
public void onUpdateExtractedText(int token, ExtractedText text) {
super.onUpdateExtractedText(token, text);
InputConnection ic = getCurrentInputConnection();
if (!mImmediatelyAfterVoiceInput && mAfterVoiceInput && ic != null) {
mVoiceInput.logTextModified();
if (mHints.showPunctuationHintIfNecessary(ic)) {
mVoiceInput.logPunctuationHintDisplayed();
}
}
mImmediatelyAfterVoiceInput = false;
}
@Override
@ -416,10 +592,22 @@ public class LatinIME extends InputMethodService
int candidatesStart, int candidatesEnd) {
super.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd,
candidatesStart, candidatesEnd);
if (DEBUG) {
Log.i(TAG, "onUpdateSelection: oss=" + oldSelStart
+ ", ose=" + oldSelEnd
+ ", nss=" + newSelStart
+ ", nse=" + newSelEnd
+ ", cs=" + candidatesStart
+ ", ce=" + candidatesEnd);
}
mSuggestionShouldReplaceCurrentWord = false;
// If the current selection in the text view changes, we should
// clear whatever candidate text we have.
if (mComposing.length() > 0 && mPredicting && (newSelStart != candidatesEnd
|| newSelEnd != candidatesEnd)) {
if ((((mComposing.length() > 0 && mPredicting) || mVoiceInputHighlighted)
&& (newSelStart != candidatesEnd
|| newSelEnd != candidatesEnd))) {
mComposing.setLength(0);
mPredicting = false;
updateSuggestions();
@ -428,25 +616,58 @@ public class LatinIME extends InputMethodService
if (ic != null) {
ic.finishComposingText();
}
mVoiceInputHighlighted = false;
} else if (!mPredicting && !mJustAccepted
&& TextEntryState.getState() == TextEntryState.STATE_ACCEPTED_DEFAULT) {
TextEntryState.reset();
}
mJustAccepted = false;
postUpdateShiftKeyState();
if (VOICE_INSTALLED) {
if (mShowingVoiceSuggestions) {
if (mImmediatelyAfterVoiceSuggestions) {
mImmediatelyAfterVoiceSuggestions = false;
} else {
updateSuggestions();
mShowingVoiceSuggestions = false;
}
}
if (VoiceInput.ENABLE_WORD_CORRECTIONS) {
// If we have alternatives for the current word, then show them.
String word = EditingUtil.getWordAtCursor(
getCurrentInputConnection(), getWordSeparators());
if (word != null && mWordToSuggestions.containsKey(word.trim())) {
mSuggestionShouldReplaceCurrentWord = true;
final List<CharSequence> suggestions = mWordToSuggestions.get(word.trim());
setSuggestions(suggestions, false, true, true);
setCandidatesViewShown(true);
}
}
}
}
@Override
public void hideWindow() {
if (mAfterVoiceInput) mVoiceInput.logInputEnded();
if (TRACE) Debug.stopMethodTracing();
if (mOptionsDialog != null && mOptionsDialog.isShowing()) {
mOptionsDialog.dismiss();
mOptionsDialog = null;
}
if (mVoiceWarningDialog != null && mVoiceWarningDialog.isShowing()) {
mVoiceInput.logKeyboardWarningDialogDismissed();
mVoiceWarningDialog.dismiss();
mVoiceWarningDialog = null;
}
if (mTutorial != null) {
mTutorial.close();
mTutorial = null;
}
if (VOICE_INSTALLED & mRecognizing) {
mVoiceInput.cancel();
}
super.hideWindow();
TextEntryState.endSession();
}
@ -462,7 +683,7 @@ public class LatinIME extends InputMethodService
if (mCompletionOn) {
mCompletions = completions;
if (completions == null) {
mCandidateView.setSuggestions(null, false, false, false);
setSuggestions(null, false, false, false);
return;
}
@ -472,7 +693,7 @@ public class LatinIME extends InputMethodService
if (ci != null) stringList.add(ci.getText());
}
//CharSequence typedWord = mWord.getTypedWord();
mCandidateView.setSuggestions(stringList, true, true, true);
setSuggestions(stringList, true, true, true);
mBestWord = null;
setCandidatesViewShown(isCandidateStripVisible() || mCompletionOn);
}
@ -546,6 +767,20 @@ public class LatinIME extends InputMethodService
return super.onKeyUp(keyCode, event);
}
private void revertVoiceInput() {
InputConnection ic = getCurrentInputConnection();
if (ic != null) ic.commitText("", 1);
updateSuggestions();
mVoiceInputHighlighted = false;
}
private void commitVoiceInput() {
InputConnection ic = getCurrentInputConnection();
if (ic != null) ic.finishComposingText();
updateSuggestions();
mVoiceInputHighlighted = false;
}
private void reloadKeyboards() {
if (mKeyboardSwitcher == null) {
mKeyboardSwitcher = new KeyboardSwitcher(this, this);
@ -670,6 +905,11 @@ public class LatinIME extends InputMethodService
case Keyboard.KEYCODE_MODE_CHANGE:
changeKeyboardMode();
break;
case LatinKeyboardView.KEYCODE_VOICE:
if (VOICE_INSTALLED) {
startListening(false /* was a button press, was not a swipe */);
}
break;
default:
if (isWordSeparator(primaryCode)) {
handleSeparator(primaryCode);
@ -698,6 +938,10 @@ public class LatinIME extends InputMethodService
}
private void handleBackspace() {
if (VOICE_INSTALLED && mVoiceInputHighlighted) {
revertVoiceInput();
return;
}
boolean deleteChar = false;
InputConnection ic = getCurrentInputConnection();
if (ic == null) return;
@ -743,6 +987,9 @@ public class LatinIME extends InputMethodService
}
private void handleCharacter(int primaryCode, int[] keyCodes) {
if (VOICE_INSTALLED && mVoiceInputHighlighted) {
commitVoiceInput();
}
if (isAlphabet(primaryCode) && isPredictionOn() && !isCursorTouchingWord()) {
if (!mPredicting) {
mPredicting = true;
@ -778,6 +1025,9 @@ public class LatinIME extends InputMethodService
}
private void handleSeparator(int primaryCode) {
if (VOICE_INSTALLED && mVoiceInputHighlighted) {
commitVoiceInput();
}
boolean pickedDefault = false;
// Handle separator
InputConnection ic = getCurrentInputConnection();
@ -816,9 +1066,12 @@ public class LatinIME extends InputMethodService
ic.endBatchEdit();
}
}
private void handleClose() {
commitTyped(getCurrentInputConnection());
if (VOICE_INSTALLED & mRecognizing) {
mVoiceInput.cancel();
}
requestHideSelf(0);
mInputView.closing();
TextEntryState.endSession();
@ -852,14 +1105,205 @@ public class LatinIME extends InputMethodService
return isPredictionOn() && mShowSuggestions;
}
private void updateSuggestions() {
// Check if we have a suggestion engine attached.
if (mSuggest == null || !isPredictionOn()) {
return;
public void onCancelVoice() {
if (mRecognizing) {
switchToKeyboardView();
}
}
private void switchToKeyboardView() {
mHandler.post(new Runnable() {
public void run() {
mRecognizing = false;
if (mInputView != null) {
setInputView(mInputView);
}
updateInputViewShown();
}});
}
private void switchToRecognitionStatusView() {
mHandler.post(new Runnable() {
public void run() {
mRecognizing = true;
setInputView(mVoiceInput.getView());
updateInputViewShown();
}});
}
private void startListening(boolean swipe) {
if (!mHasUsedVoiceInput ||
(!mLocaleSupportedForVoiceInput && !mHasUsedVoiceInputUnsupportedLocale)) {
// Calls reallyStartListening if user clicks OK, does nothing if user clicks Cancel.
showVoiceWarningDialog(swipe);
} else {
reallyStartListening(swipe);
}
}
private void reallyStartListening(boolean swipe) {
if (!mHasUsedVoiceInput) {
// The user has started a voice input, so remember that in the
// future (so we don't show the warning dialog after the first run).
SharedPreferences.Editor editor =
PreferenceManager.getDefaultSharedPreferences(this).edit();
editor.putBoolean(PREF_HAS_USED_VOICE_INPUT, true);
editor.commit();
mHasUsedVoiceInput = true;
}
if (!mLocaleSupportedForVoiceInput && !mHasUsedVoiceInputUnsupportedLocale) {
// The user has started a voice input from an unsupported locale, so remember that
// in the future (so we don't show the warning dialog the next time they do this).
SharedPreferences.Editor editor =
PreferenceManager.getDefaultSharedPreferences(this).edit();
editor.putBoolean(PREF_HAS_USED_VOICE_INPUT_UNSUPPORTED_LOCALE, true);
editor.commit();
mHasUsedVoiceInputUnsupportedLocale = true;
}
// Clear N-best suggestions
setSuggestions(null, false, false, true);
FieldContext context = new FieldContext(
getCurrentInputConnection(), getCurrentInputEditorInfo());
mVoiceInput.startListening(context, swipe);
switchToRecognitionStatusView();
}
private void showVoiceWarningDialog(final boolean swipe) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setCancelable(true);
builder.setIcon(R.drawable.ic_mic_dialog);
builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
mVoiceInput.logKeyboardWarningDialogOk();
reallyStartListening(swipe);
}
});
builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
mVoiceInput.logKeyboardWarningDialogCancel();
}
});
if (mLocaleSupportedForVoiceInput) {
String message = getString(R.string.voice_warning_may_not_understand) + "\n\n" +
getString(R.string.voice_warning_how_to_turn_off);
builder.setMessage(message);
} else {
String message = getString(R.string.voice_warning_locale_not_supported) + "\n\n" +
getString(R.string.voice_warning_may_not_understand) + "\n\n" +
getString(R.string.voice_warning_how_to_turn_off);
builder.setMessage(message);
}
builder.setTitle(R.string.voice_warning_title);
mVoiceWarningDialog = builder.create();
Window window = mVoiceWarningDialog.getWindow();
WindowManager.LayoutParams lp = window.getAttributes();
lp.token = mInputView.getWindowToken();
lp.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
window.setAttributes(lp);
window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
mVoiceInput.logKeyboardWarningDialogShown();
mVoiceWarningDialog.show();
}
public void onVoiceResults(List<String> candidates,
Map<String, List<CharSequence>> alternatives) {
if (!mRecognizing) {
return;
}
mVoiceResults.candidates = candidates;
mVoiceResults.alternatives = alternatives;
mHandler.sendMessage(mHandler.obtainMessage(MSG_VOICE_RESULTS));
}
private void handleVoiceResults() {
mAfterVoiceInput = true;
mImmediatelyAfterVoiceInput = true;
InputConnection ic = getCurrentInputConnection();
if (!isFullscreenMode()) {
// Start listening for updates to the text from typing, etc.
if (ic != null) {
ExtractedTextRequest req = new ExtractedTextRequest();
ic.getExtractedText(req, InputConnection.GET_EXTRACTED_TEXT_MONITOR);
}
}
vibrate();
switchToKeyboardView();
final List<CharSequence> nBest = new ArrayList<CharSequence>();
boolean capitalizeFirstWord = preferCapitalization()
|| (mKeyboardSwitcher.isAlphabetMode() && mInputView.isShifted());
for (String c : mVoiceResults.candidates) {
if (capitalizeFirstWord) {
c = Character.toUpperCase(c.charAt(0)) + c.substring(1, c.length());
}
nBest.add(c);
}
if (nBest.size() == 0) {
return;
}
String bestResult = nBest.get(0).toString();
mVoiceInput.logVoiceInputDelivered();
mHints.registerVoiceResult(bestResult);
if (ic != null) ic.beginBatchEdit(); // To avoid extra updates on committing older text
commitTyped(ic);
EditingUtil.appendText(ic, bestResult);
if (ic != null) ic.endBatchEdit();
// Show N-Best alternates, if there is more than one choice.
if (nBest.size() > 1) {
mImmediatelyAfterVoiceSuggestions = true;
mShowingVoiceSuggestions = true;
setSuggestions(nBest.subList(1, nBest.size()), false, true, true);
setCandidatesViewShown(true);
}
mVoiceInputHighlighted = true;
mWordToSuggestions.putAll(mVoiceResults.alternatives);
}
private void setSuggestions(
List<CharSequence> suggestions,
boolean completions,
boolean typedWordValid,
boolean haveMinimalSuggestion) {
if (mIsShowingHint) {
setCandidatesView(mCandidateViewContainer);
mIsShowingHint = false;
}
if (mCandidateView != null) {
mCandidateView.setSuggestions(
suggestions, completions, typedWordValid, haveMinimalSuggestion);
}
}
private void updateSuggestions() {
mSuggestionShouldReplaceCurrentWord = false;
// Check if we have a suggestion engine attached.
if ((mSuggest == null || !isPredictionOn()) && !mVoiceInputHighlighted) {
return;
}
if (!mPredicting) {
mCandidateView.setSuggestions(null, false, false, false);
setSuggestions(null, false, false, false);
return;
}
@ -876,7 +1320,7 @@ public class LatinIME extends InputMethodService
// Don't auto-correct words with multiple capital letter
correctionAvailable &= !mWord.isMostlyCaps();
mCandidateView.setSuggestions(stringList, false, typedWordValid, correctionAvailable);
setSuggestions(stringList, false, typedWordValid, correctionAvailable);
if (stringList.size() > 0) {
if (correctionAvailable && !typedWordValid && stringList.size() > 1) {
mBestWord = stringList.get(1);
@ -903,6 +1347,8 @@ public class LatinIME extends InputMethodService
}
public void pickSuggestionManually(int index, CharSequence suggestion) {
if (mAfterVoiceInput && mShowingVoiceSuggestions) mVoiceInput.logNBestChoose(index);
if (mCompletionOn && mCompletions != null && index >= 0
&& index < mCompletions.length) {
CompletionInfo ci = mCompletions[index];
@ -937,7 +1383,12 @@ public class LatinIME extends InputMethodService
}
InputConnection ic = getCurrentInputConnection();
if (ic != null) {
ic.commitText(suggestion, 1);
if (mSuggestionShouldReplaceCurrentWord) {
EditingUtil.deleteWordAtCursor(ic, getWordSeparators());
}
if (!VoiceInput.DELETE_SYMBOL.equals(suggestion)) {
ic.commitText(suggestion, 1);
}
}
// Add the word to the auto dictionary if it's not a known word
if (mAutoDictionary.isValidWord(suggestion) || !mSuggest.isValidWord(suggestion)) {
@ -945,9 +1396,7 @@ public class LatinIME extends InputMethodService
}
mPredicting = false;
mCommittedLength = suggestion.length();
if (mCandidateView != null) {
mCandidateView.setSuggestions(null, false, false, false);
}
setSuggestions(null, false, false, false);
updateShiftKeyState(getCurrentInputEditorInfo());
}
@ -1016,6 +1465,11 @@ public class LatinIME extends InputMethodService
}
public void swipeRight() {
if (userHasNotTypedRecently() && VOICE_INSTALLED && mEnableVoice &&
fieldCanDoVoice(makeFieldContext())) {
startListening(true /* was a swipe */);
}
if (LatinKeyboardView.DEBUG_AUTO_PLAY) {
ClipboardManager cm = ((ClipboardManager)getSystemService(CLIPBOARD_SERVICE));
CharSequence text = cm.getText();
@ -1035,7 +1489,7 @@ public class LatinIME extends InputMethodService
int currentKeyboardMode = mKeyboardSwitcher.getKeyboardMode();
reloadKeyboards();
mKeyboardSwitcher.makeKeyboards(true);
mKeyboardSwitcher.setKeyboardMode(currentKeyboardMode, 0);
mKeyboardSwitcher.setKeyboardMode(currentKeyboardMode, 0, mEnableVoiceButton);
initSuggest(mInputLanguage);
persistInputLanguage(mInputLanguage);
updateShiftKeyState(getCurrentInputEditorInfo());
@ -1068,7 +1522,30 @@ public class LatinIME extends InputMethodService
public void onRelease(int primaryCode) {
//vibrate();
}
private FieldContext makeFieldContext() {
return new FieldContext(getCurrentInputConnection(), getCurrentInputEditorInfo());
}
private boolean fieldCanDoVoice(FieldContext fieldContext) {
return !mPasswordText
&& mVoiceInput != null
&& !mVoiceInput.isBlacklistedField(fieldContext);
}
private boolean fieldIsRecommendedForVoice(FieldContext fieldContext) {
// TODO: Move this logic into the VoiceInput method.
return !mPasswordText && !mEmailText && mVoiceInput.isRecommendedField(fieldContext);
}
private boolean shouldShowVoiceButton(FieldContext fieldContext, EditorInfo attribute) {
return ENABLE_VOICE_BUTTON
&& mEnableVoice
&& fieldCanDoVoice(fieldContext)
&& !(attribute != null && attribute.privateImeOptions != null
&& attribute.privateImeOptions.equals(IME_OPTION_NO_MICROPHONE));
}
// receive ringer mode changes to detect silent mode
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
@ -1087,6 +1564,26 @@ public class LatinIME extends InputMethodService
}
}
private boolean userHasNotTypedRecently() {
return (SystemClock.uptimeMillis() - mLastKeyTime)
> MIN_MILLIS_AFTER_TYPING_BEFORE_SWIPE;
}
/*
* Only trigger a swipe action if the user hasn't typed X millis before
* now, and if they don't type Y millis after the swipe is detected. This
* delays the onset of the swipe action by Y millis.
*/
private void conservativelyTriggerSwipeAction(final Runnable action) {
if (userHasNotTypedRecently()) {
mSwipeTriggerTimeMillis = System.currentTimeMillis();
mHandler.sendMessageDelayed(
mHandler.obtainMessage(MSG_START_LISTENING_AFTER_SWIPE),
MIN_MILLIS_AFTER_SWIPE_TO_WAIT_FOR_TYPING);
}
}
private void playKeyClick(int primaryCode) {
// if mAudioManager is null, we don't have the ringer state yet
// mAudioManager will be set by updateRingerMode
@ -1162,10 +1659,14 @@ public class LatinIME extends InputMethodService
}
}
private void launchSettings() {
protected void launchSettings() {
launchSettings(LatinIMESettings.class);
}
protected void launchSettings(Class settingsClass) {
handleClose();
Intent intent = new Intent();
intent.setClass(LatinIME.this, LatinIMESettings.class);
intent.setClass(LatinIME.this, settingsClass);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
@ -1177,10 +1678,37 @@ public class LatinIME extends InputMethodService
mSoundOn = sp.getBoolean(PREF_SOUND_ON, false);
mAutoCap = sp.getBoolean(PREF_AUTO_CAP, true);
mQuickFixes = sp.getBoolean(PREF_QUICK_FIXES, true);
mHasUsedVoiceInput = sp.getBoolean(PREF_HAS_USED_VOICE_INPUT, false);
mHasUsedVoiceInputUnsupportedLocale =
sp.getBoolean(PREF_HAS_USED_VOICE_INPUT_UNSUPPORTED_LOCALE, false);
// Get the current list of supported locales and check the current locale against that
// list. We cache this value so as not to check it every time the user starts a voice
// input. Because this method is called by onStartInputView, this should mean that as
// long as the locale doesn't change while the user is keeping the IME open, the
// value should never be stale.
String supportedLocalesString = GoogleSettingsUtil.getGservicesString(
getContentResolver(),
GoogleSettingsUtil.LATIN_IME_VOICE_INPUT_SUPPORTED_LOCALES,
DEFAULT_VOICE_INPUT_SUPPORTED_LOCALES);
ArrayList<String> voiceInputSupportedLocales =
Lists.newArrayList(supportedLocalesString.split("\\s+"));
mLocaleSupportedForVoiceInput = voiceInputSupportedLocales.contains(mLocale);
// If there is no auto text data, then quickfix is forced to "on", so that the other options
// will continue to work
if (AutoText.getSize(mInputView) < 1) mQuickFixes = true;
mShowSuggestions = sp.getBoolean(PREF_SHOW_SUGGESTIONS, true) & mQuickFixes;
if (VOICE_INSTALLED) {
boolean enableVoice = sp.getBoolean(PREF_ENABLE_VOICE, true);
if (enableVoice != mEnableVoice && mKeyboardSwitcher != null) {
mKeyboardSwitcher.setVoiceMode(enableVoice);
}
mEnableVoice = enableVoice;
}
mAutoCorrectEnabled = sp.getBoolean(PREF_AUTO_COMPLETE,
mResources.getBoolean(R.bool.enable_autocorrect)) & mShowSuggestions;
updateCorrectionMode();
@ -1219,7 +1747,7 @@ public class LatinIME extends InputMethodService
builder.setIcon(R.drawable.ic_dialog_keyboard);
builder.setNegativeButton(android.R.string.cancel, null);
CharSequence itemSettings = getString(R.string.english_ime_settings);
CharSequence itemInputMethod = getString(com.android.internal.R.string.inputMethod);
CharSequence itemInputMethod = getString(R.string.inputMethod);
builder.setItems(new CharSequence[] {
itemSettings, itemInputMethod},
new DialogInterface.OnClickListener() {
@ -1327,6 +1855,3 @@ public class LatinIME extends InputMethodService
}
}
}

View File

@ -26,6 +26,6 @@ public class LatinIMEBackupAgent extends BackupHelperAgent {
public void onCreate() {
addHelper("shared_pref", new SharedPreferencesBackupHelper(this,
"com.android.inputmethod.latin_preferences"));
getPackageName() + "_preferences"));
}
}

View File

@ -16,23 +16,53 @@
package com.android.inputmethod.latin;
import com.google.android.collect.Lists;
import android.app.AlertDialog;
import android.app.Dialog;
import android.backup.BackupManager;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceGroup;
import android.preference.Preference.OnPreferenceClickListener;
import android.text.AutoText;
import android.util.Log;
import com.android.inputmethod.voice.GoogleSettingsUtil;
import com.android.inputmethod.voice.VoiceInput;
import com.android.inputmethod.voice.VoiceInputLogger;
import java.util.ArrayList;
import java.util.Locale;
public class LatinIMESettings extends PreferenceActivity
implements SharedPreferences.OnSharedPreferenceChangeListener {
implements SharedPreferences.OnSharedPreferenceChangeListener,
OnPreferenceClickListener,
DialogInterface.OnDismissListener {
private static final String QUICK_FIXES_KEY = "quick_fixes";
private static final String SHOW_SUGGESTIONS_KEY = "show_suggestions";
private static final String PREDICTION_SETTINGS_KEY = "prediction_settings";
private static final String VOICE_SETTINGS_KEY = "enable_voice_input";
private static final String VOICE_SERVER_KEY = "voice_server_url";
private static final String TAG = "LatinIMESettings";
// Dialog ids
private static final int VOICE_INPUT_CONFIRM_DIALOG = 0;
private CheckBoxPreference mQuickFixes;
private CheckBoxPreference mShowSuggestions;
private CheckBoxPreference mVoicePreference;
private VoiceInputLogger mLogger;
private boolean mOkClicked = false;
@Override
protected void onCreate(Bundle icicle) {
@ -40,8 +70,16 @@ public class LatinIMESettings extends PreferenceActivity
addPreferencesFromResource(R.xml.prefs);
mQuickFixes = (CheckBoxPreference) findPreference(QUICK_FIXES_KEY);
mShowSuggestions = (CheckBoxPreference) findPreference(SHOW_SUGGESTIONS_KEY);
getPreferenceManager().getSharedPreferences().registerOnSharedPreferenceChangeListener(
this);
mVoicePreference = (CheckBoxPreference) findPreference(VOICE_SETTINGS_KEY);
SharedPreferences prefs = getPreferenceManager().getSharedPreferences();
prefs.registerOnSharedPreferenceChangeListener(this);
mVoicePreference.setOnPreferenceClickListener(this);
mVoicePreference.setChecked(prefs.getBoolean(
VOICE_SETTINGS_KEY, getResources().getBoolean(R.bool.voice_input_default)));
mLogger = VoiceInputLogger.getLogger(this);
}
@Override
@ -50,10 +88,17 @@ public class LatinIMESettings extends PreferenceActivity
int autoTextSize = AutoText.getSize(getListView());
if (autoTextSize < 1) {
((PreferenceGroup) findPreference(PREDICTION_SETTINGS_KEY))
.removePreference(mQuickFixes);
.removePreference(mQuickFixes);
} else {
mShowSuggestions.setDependency(QUICK_FIXES_KEY);
}
if (!LatinIME.VOICE_INSTALLED
|| !VoiceInput.voiceIsAvailable(this)) {
getPreferenceScreen().removePreference(mVoicePreference);
}
mVoicePreference.setChecked(
getPreferenceManager().getSharedPreferences().getBoolean(VOICE_SETTINGS_KEY, true));
}
@Override
@ -67,4 +112,91 @@ public class LatinIMESettings extends PreferenceActivity
String key) {
(new BackupManager(this)).dataChanged();
}
public boolean onPreferenceClick(Preference preference) {
if (preference == mVoicePreference) {
if (mVoicePreference.isChecked()) {
mOkClicked = false;
showDialog(VOICE_INPUT_CONFIRM_DIALOG);
} else {
updateVoicePreference();
}
}
return false;
}
@Override
protected Dialog onCreateDialog(int id) {
switch (id) {
case VOICE_INPUT_CONFIRM_DIALOG:
DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
if (whichButton == DialogInterface.BUTTON_NEGATIVE) {
mVoicePreference.setChecked(false);
mLogger.settingsWarningDialogCancel();
} else if (whichButton == DialogInterface.BUTTON_POSITIVE) {
mOkClicked = true;
mLogger.settingsWarningDialogOk();
}
updateVoicePreference();
}
};
AlertDialog.Builder builder = new AlertDialog.Builder(this)
.setTitle(R.string.voice_warning_title)
.setPositiveButton(android.R.string.ok, listener)
.setNegativeButton(android.R.string.cancel, listener);
// Get the current list of supported locales and check the current locale against
// that list, to decide whether to put a warning that voice input will not work in
// the current language as part of the pop-up confirmation dialog.
String supportedLocalesString = GoogleSettingsUtil.getGservicesString(
getContentResolver(),
GoogleSettingsUtil.LATIN_IME_VOICE_INPUT_SUPPORTED_LOCALES,
LatinIME.DEFAULT_VOICE_INPUT_SUPPORTED_LOCALES);
ArrayList<String> voiceInputSupportedLocales =
Lists.newArrayList(supportedLocalesString.split("\\s+"));
boolean localeSupported = voiceInputSupportedLocales.contains(
Locale.getDefault().toString());
if (localeSupported) {
String message = getString(R.string.voice_warning_may_not_understand) + "\n\n" +
getString(R.string.voice_hint_dialog_message);
builder.setMessage(message);
} else {
String message = getString(R.string.voice_warning_locale_not_supported) +
"\n\n" + getString(R.string.voice_warning_may_not_understand) + "\n\n" +
getString(R.string.voice_hint_dialog_message);
builder.setMessage(message);
}
AlertDialog dialog = builder.create();
dialog.setOnDismissListener(this);
mLogger.settingsWarningDialogShown();
return dialog;
default:
Log.e(TAG, "unknown dialog " + id);
return null;
}
}
public void onDismiss(DialogInterface dialog) {
mLogger.settingsWarningDialogDismissed();
if (!mOkClicked) {
// This assumes that onPreferenceClick gets called first, and this if the user
// agreed after the warning, we set the mOkClicked value to true.
mVoicePreference.setChecked(false);
}
}
private void updateVoicePreference() {
SharedPreferences.Editor editor = getPreferenceManager().getSharedPreferences().edit();
boolean isChecked = mVoicePreference.isChecked();
if (isChecked) {
mLogger.voiceInputSettingEnabled();
} else {
mLogger.voiceInputSettingDisabled();
}
editor.putBoolean(VOICE_SETTINGS_KEY, isChecked);
editor.commit();
}
}

View File

@ -35,8 +35,8 @@ public class LatinKeyboardView extends KeyboardView {
static final int KEYCODE_OPTIONS = -100;
static final int KEYCODE_SHIFT_LONGPRESS = -101;
static final int KEYCODE_F1 = -102;
static final int KEYCODE_VOICE = -102;
static final int KEYCODE_F1 = -103;
private Keyboard mPhoneKeyboard;
public LatinKeyboardView(Context context, AttributeSet attrs) {

View File

@ -0,0 +1,162 @@
/*
* Copyright (C) 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.android.inputmethod.voice;
import android.view.inputmethod.ExtractedText;
import android.view.inputmethod.ExtractedTextRequest;
import android.view.inputmethod.InputConnection;
/**
* Utility methods to deal with editing text through an InputConnection.
*/
public class EditingUtil {
private EditingUtil() {};
/**
* Append newText to the text field represented by connection.
* The new text becomes selected.
*/
public static void appendText(InputConnection connection, String newText) {
if (connection == null) {
return;
}
// Commit the composing text
connection.finishComposingText();
// Add a space if the field already has text.
CharSequence charBeforeCursor = connection.getTextBeforeCursor(1, 0);
if (charBeforeCursor != null
&& !charBeforeCursor.equals(" ")
&& (charBeforeCursor.length() > 0)) {
newText = " " + newText;
}
connection.setComposingText(newText, 1);
}
private static int getCursorPosition(InputConnection connection) {
ExtractedText extracted = connection.getExtractedText(
new ExtractedTextRequest(), 0);
if (extracted == null) {
return -1;
}
return extracted.startOffset + extracted.selectionStart;
}
private static int getSelectionEnd(InputConnection connection) {
ExtractedText extracted = connection.getExtractedText(
new ExtractedTextRequest(), 0);
if (extracted == null) {
return -1;
}
return extracted.startOffset + extracted.selectionEnd;
}
/**
* @param connection connection to the current text field.
* @param sep characters which may separate words
* @return the word that surrounds the cursor, including up to one trailing
* separator. For example, if the field contains "he|llo world", where |
* represents the cursor, then "hello " will be returned.
*/
public static String getWordAtCursor(
InputConnection connection, String separators) {
Range range = getWordRangeAtCursor(connection, separators);
return (range == null) ? null : range.word;
}
/**
* Removes the word surrounding the cursor. Parameters are identical to
* getWordAtCursor.
*/
public static void deleteWordAtCursor(
InputConnection connection, String separators) {
Range range = getWordRangeAtCursor(connection, separators);
if (range == null) return;
connection.finishComposingText();
// Move cursor to beginning of word, to avoid crash when cursor is outside
// of valid range after deleting text.
int newCursor = getCursorPosition(connection) - range.charsBefore;
connection.setSelection(newCursor, newCursor);
connection.deleteSurroundingText(0, range.charsBefore + range.charsAfter);
}
/**
* Represents a range of text, relative to the current cursor position.
*/
private static class Range {
/** Characters before selection start */
int charsBefore;
/**
* Characters after selection start, including one trailing word
* separator.
*/
int charsAfter;
/** The actual characters that make up a word */
String word;
public Range(int charsBefore, int charsAfter, String word) {
if (charsBefore < 0 || charsAfter < 0) {
throw new IndexOutOfBoundsException();
}
this.charsBefore = charsBefore;
this.charsAfter = charsAfter;
this.word = word;
}
}
private static Range getWordRangeAtCursor(
InputConnection connection, String sep) {
if (connection == null || sep == null) {
return null;
}
CharSequence before = connection.getTextBeforeCursor(1000, 0);
CharSequence after = connection.getTextAfterCursor(1000, 0);
if (before == null || after == null) {
return null;
}
// Find first word separator before the cursor
int start = before.length();
while (--start > 0 && !isWhitespace(before.charAt(start - 1), sep));
// Find last word separator after the cursor
int end = -1;
while (++end < after.length() && !isWhitespace(after.charAt(end), sep));
if (end < after.length() - 1) {
end++; // Include trailing space, if it exists, in word
}
int cursor = getCursorPosition(connection);
if (start >= 0 && cursor + end <= after.length() + before.length()) {
String word = before.toString().substring(start, before.length())
+ after.toString().substring(0, end);
return new Range(before.length() - start, end, word);
}
return null;
}
private static boolean isWhitespace(int code, String whitespace) {
return whitespace.contains(String.valueOf((char) code));
}
}

View File

@ -0,0 +1,91 @@
/*
* Copyright (C) 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.android.inputmethod.voice;
import android.os.Bundle;
import android.util.Log;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.ExtractedText;
import android.view.inputmethod.ExtractedTextRequest;
import android.view.inputmethod.InputConnection;
/**
* Represents information about a given text field, which can be passed
* to the speech recognizer as context information.
*/
public class FieldContext {
static final String LABEL = "label";
static final String HINT = "hint";
static final String PACKAGE_NAME = "packageName";
static final String FIELD_ID = "fieldId";
static final String FIELD_NAME = "fieldName";
static final String SINGLE_LINE = "singleLine";
static final String INPUT_TYPE = "inputType";
static final String IME_OPTIONS = "imeOptions";
Bundle mFieldInfo;
public FieldContext(InputConnection conn, EditorInfo info) {
this.mFieldInfo = new Bundle();
addEditorInfoToBundle(info, mFieldInfo);
addInputConnectionToBundle(conn, mFieldInfo);
Log.i("FieldContext", "Bundle = " + mFieldInfo.toString());
}
private static String safeToString(Object o) {
if (o == null) {
return "";
}
return o.toString();
}
private static void addEditorInfoToBundle(EditorInfo info, Bundle bundle) {
if (info == null) {
return;
}
bundle.putString(LABEL, safeToString(info.label));
bundle.putString(HINT, safeToString(info.hintText));
bundle.putString(PACKAGE_NAME, safeToString(info.packageName));
bundle.putInt(FIELD_ID, info.fieldId);
bundle.putString(FIELD_NAME, safeToString(info.fieldName));
bundle.putInt(INPUT_TYPE, info.inputType);
bundle.putInt(IME_OPTIONS, info.imeOptions);
}
private static void addInputConnectionToBundle(
InputConnection conn, Bundle bundle) {
if (conn == null) {
return;
}
ExtractedText et = conn.getExtractedText(new ExtractedTextRequest(), 0);
if (et == null) {
return;
}
bundle.putBoolean(SINGLE_LINE, (et.flags & et.FLAG_SINGLE_LINE) > 0);
}
public Bundle getBundle() {
return mFieldInfo;
}
public String toString() {
return mFieldInfo.toString();
}
}

View File

@ -0,0 +1,175 @@
/*
* Copyright (C) 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.android.inputmethod.voice;
import android.content.ContentResolver;
import android.database.Cursor;
import android.net.Uri;
import android.util.Log;
/**
* Utility for getting Google-specific settings from GoogleSettings.Partner or
* Gservices. Retrieving such settings may fail on a non-Google Experience
* Device (GED)
*/
public class GoogleSettingsUtil {
/**
* A whitespace-separated list of supported locales for voice input from the keyboard.
*/
public static final String LATIN_IME_VOICE_INPUT_SUPPORTED_LOCALES =
"latin_ime_voice_input_supported_locales";
/**
* A whitespace-separated list of recommended app packages for voice input from the
* keyboard.
*/
public static final String LATIN_IME_VOICE_INPUT_RECOMMENDED_PACKAGES =
"latin_ime_voice_input_recommended_packages";
/**
* The maximum number of unique days to show the swipe hint for voice input.
*/
public static final String LATIN_IME_VOICE_INPUT_SWIPE_HINT_MAX_DAYS =
"latin_ime_voice_input_swipe_hint_max_days";
/**
* The maximum number of times to show the punctuation hint for voice input.
*/
public static final String LATIN_IME_VOICE_INPUT_PUNCTUATION_HINT_MAX_DISPLAYS =
"latin_ime_voice_input_punctuation_hint_max_displays";
/**
* Endpointer parameters for voice input from the keyboard.
*/
public static final String LATIN_IME_SPEECH_MINIMUM_LENGTH_MILLIS =
"latin_ime_speech_minimum_length_millis";
public static final String LATIN_IME_SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS =
"latin_ime_speech_input_complete_silence_length_millis";
public static final String LATIN_IME_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS =
"latin_ime_speech_input_possibly_complete_silence_length_millis";
/**
* Min and max volume levels that can be displayed on the "speak now" screen.
*/
public static final String LATIN_IME_MIN_MICROPHONE_LEVEL =
"latin_ime_min_microphone_level";
public static final String LATIN_IME_MAX_MICROPHONE_LEVEL =
"latin_ime_max_microphone_level";
/**
* The number of sentence-level alternates to request of the server.
*/
public static final String LATIN_IME_MAX_VOICE_RESULTS = "latin_ime_max_voice_results";
/**
* Uri to use to access gservices settings
*/
private static final Uri GSERVICES_URI = Uri.parse("content://settings/gservices");
private static final String TAG = GoogleSettingsUtil.class.getSimpleName();
private static final boolean DBG = false;
/**
* Safely query for a Gservices string setting, which may not be available if this
* is not a Google Experience Device.
*
* @param cr The content resolver to use
* @param key The setting to look up
* @param defaultValue The default value to use if none can be found
* @return The value of the setting, or defaultValue if it couldn't be found
*/
public static String getGservicesString(ContentResolver cr, String key, String defaultValue) {
return getSettingString(GSERVICES_URI, cr, key, defaultValue);
}
/**
* Safely query for a Gservices int setting, which may not be available if this
* is not a Google Experience Device.
*
* @param cr The content resolver to use
* @param key The setting to look up
* @param defaultValue The default value to use if the setting couldn't be found or parsed
* @return The value of the setting, or defaultValue if it couldn't be found or parsed
*/
public static int getGservicesInt(ContentResolver cr, String key, int defaultValue) {
try {
return Integer.parseInt(getGservicesString(cr, key, String.valueOf(defaultValue)));
} catch (NumberFormatException e) {
return defaultValue;
}
}
/**
* Safely query for a Gservices float setting, which may not be available if this
* is not a Google Experience Device.
*
* @param cr The content resolver to use
* @param key The setting to look up
* @param defaultValue The default value to use if the setting couldn't be found or parsed
* @return The value of the setting, or defaultValue if it couldn't be found or parsed
*/
public static float getGservicesFloat(ContentResolver cr, String key, float defaultValue) {
try {
return Float.parseFloat(getGservicesString(cr, key, String.valueOf(defaultValue)));
} catch (NumberFormatException e) {
return defaultValue;
}
}
/**
* A safe way to query for a setting on both Google Experience and
* non-Google Experience devices, (code adapted from maps application
* examples)
*
* @param uri The uri to provide to the content resolver
* @param cr The content resolver to use
* @param key The setting to look up
* @param defaultValue The default value to use if none can be found
* @return The value of the setting, or defaultValue if it couldn't be found
*/
private static String getSettingString(Uri uri, ContentResolver cr, String key,
String defaultValue) {
String value = null;
Cursor cursor = null;
try {
cursor = cr.query(uri, new String[] {
"value"
}, "name='" + key + "'", null, null);
if ((cursor != null) && cursor.moveToFirst()) {
value = cursor.getString(cursor.getColumnIndexOrThrow("value"));
}
} catch (Throwable t) {
// This happens because we're probably running a non Type 1 aka
// Google Experience device which doesn't have the Google libraries.
if (DBG) {
Log.d(TAG, "Error getting setting from " + uri + " for key " + key + ": " + t);
}
} finally {
if (cursor != null) {
cursor.close();
}
}
if (DBG && value == null) {
Log.i(TAG, "no setting found from " + uri + " for key " + key + ", returning default");
}
return (value != null) ? value : defaultValue;
}
}

View File

@ -0,0 +1,28 @@
/*
* Copyright (C) 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.android.inputmethod.voice;
import android.content.Intent;
import com.android.inputmethod.latin.LatinIME;
public class LatinIMEWithVoice extends LatinIME {
@Override
protected void launchSettings() {
launchSettings(LatinIMEWithVoiceSettings.class);
}
}

View File

@ -0,0 +1,21 @@
/*
* Copyright (C) 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.android.inputmethod.voice;
import com.android.inputmethod.latin.LatinIMESettings;
public class LatinIMEWithVoiceSettings extends LatinIMESettings {}

View File

@ -0,0 +1,96 @@
/*
* Copyright (C) 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.android.inputmethod.voice;
/**
* Logging event constants used for Voice Search and VoiceIME. These are the keys and values of
* extras to be specified in logging broadcast intents to the {@link LoggingReceiver}.
*
* This class is duplicated between VoiceSearch and LatinIME. Please keep both versions
* in sync.
*/
public class LoggingEvents {
// The name of the broadcast intent for logging.
public static final String ACTION_LOG_EVENT = "com.google.android.voicesearch.LOG_EVENT";
// The extra key used for the name of the app being logged.
public static final String EXTRA_APP_NAME = "app_name";
// The extra key used for the event value. The possible event values depend on the
// app being logged for, and are defined in the subclasses below.
public static final String EXTRA_EVENT = "extra_event";
// The extra key used (with a boolean value of 'true') as a way to trigger a flush
// of the log events to the server.
public static final String EXTRA_FLUSH = "flush";
/**
* Logging event constants for VoiceIME. Below are the extra values for
* {@link LoggingEvents#EXTRA_EVENT}, clustered with keys to additional extras
* for some events that need to be included as additional fields in the event.
*/
public class VoiceIme {
// The app name to be used for logging VoiceIME events.
public static final String APP_NAME = "voiceime";
public static final int KEYBOARD_WARNING_DIALOG_SHOWN = 0;
public static final int KEYBOARD_WARNING_DIALOG_DISMISSED = 1;
public static final int KEYBOARD_WARNING_DIALOG_OK = 2;
public static final int KEYBOARD_WARNING_DIALOG_CANCEL = 3;
public static final int SETTINGS_WARNING_DIALOG_SHOWN = 4;
public static final int SETTINGS_WARNING_DIALOG_DISMISSED = 5;
public static final int SETTINGS_WARNING_DIALOG_OK = 6;
public static final int SETTINGS_WARNING_DIALOG_CANCEL = 7;
public static final int SWIPE_HINT_DISPLAYED = 8;
public static final int PUNCTUATION_HINT_DISPLAYED = 9;
public static final int CANCEL_DURING_LISTENING = 10;
public static final int CANCEL_DURING_WORKING = 11;
public static final int CANCEL_DURING_ERROR = 12;
public static final int ERROR = 13;
public static final String EXTRA_ERROR_CODE = "code"; // value should be int
public static final int START = 14;
public static final String EXTRA_START_LOCALE = "locale"; // value should be String
public static final String EXTRA_START_SWIPE = "swipe"; // value should be boolean
public static final int VOICE_INPUT_DELIVERED = 15;
public static final int N_BEST_CHOOSE = 16;
public static final String EXTRA_N_BEST_CHOOSE_INDEX = "index"; // value should be int
public static final int TEXT_MODIFIED = 17;
public static final int INPUT_ENDED = 18;
public static final int VOICE_INPUT_SETTING_ENABLED = 19;
public static final int VOICE_INPUT_SETTING_DISABLED = 20;
}
}

View File

@ -0,0 +1,321 @@
/*
* Copyright (C) 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.android.inputmethod.voice;
import android.content.ContentResolver;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.CornerPathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathEffect;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.MarginLayoutParams;
import android.widget.ImageView;
import android.widget.TextView;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.voice.GoogleSettingsUtil;
import java.io.ByteArrayOutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.ShortBuffer;
import java.util.ArrayList;
import java.util.List;
/**
* The user interface for the "Speak now" and "working" states.
* Displays a recognition dialog (with waveform, voice meter, etc.),
* plays beeps, shows errors, etc.
*/
public class RecognitionView {
private static final String TAG = "RecognitionView";
// If there's a significant delay between starting up voice search and the
// onset of audio recording, show the "initializing" screen first. If not,
// jump directly to the "speak now" screen to avoid flashing "initializing"
// quickly.
private static final boolean EXPECT_RECORDING_DELAY = true;
private Handler mUiHandler; // Reference to UI thread
private View mView;
private Context mContext;
private ImageView mImage;
private TextView mText;
private View mButton;
private TextView mButtonText;
private View mProgress;
private Drawable mInitializing;
private Drawable mError;
private List<Drawable> mSpeakNow;
private float mVolume = 0.0f;
private int mLevel = 0;
private enum State {LISTENING, WORKING, READY}
private State mState = State.READY;
private float mMinMicrophoneLevel;
private float mMaxMicrophoneLevel;
/** Updates the microphone icon to show user their volume.*/
private Runnable mUpdateVolumeRunnable = new Runnable() {
public void run() {
if (mState != State.LISTENING) {
return;
}
final float min = mMinMicrophoneLevel;
final float max = mMaxMicrophoneLevel;
final int maxLevel = mSpeakNow.size() - 1;
int index = (int) ((mVolume - min) / (max - min) * maxLevel);
final int level = Math.min(Math.max(0, index), maxLevel);
if (level != mLevel) {
mImage.setImageDrawable(mSpeakNow.get(level));
mLevel = level;
}
mUiHandler.postDelayed(mUpdateVolumeRunnable, 50);
}
};
public RecognitionView(Context context, OnClickListener clickListener) {
mUiHandler = new Handler();
LayoutInflater inflater = (LayoutInflater) context.getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
mView = inflater.inflate(R.layout.recognition_status, null);
ContentResolver cr = context.getContentResolver();
mMinMicrophoneLevel = GoogleSettingsUtil.getGservicesFloat(
cr, GoogleSettingsUtil.LATIN_IME_MIN_MICROPHONE_LEVEL, 15.f);
mMaxMicrophoneLevel = GoogleSettingsUtil.getGservicesFloat(
cr, GoogleSettingsUtil.LATIN_IME_MAX_MICROPHONE_LEVEL, 30.f);
// Pre-load volume level images
Resources r = context.getResources();
mSpeakNow = new ArrayList<Drawable>();
mSpeakNow.add(r.getDrawable(R.drawable.speak_now_level0));
mSpeakNow.add(r.getDrawable(R.drawable.speak_now_level1));
mSpeakNow.add(r.getDrawable(R.drawable.speak_now_level2));
mSpeakNow.add(r.getDrawable(R.drawable.speak_now_level3));
mSpeakNow.add(r.getDrawable(R.drawable.speak_now_level4));
mSpeakNow.add(r.getDrawable(R.drawable.speak_now_level5));
mSpeakNow.add(r.getDrawable(R.drawable.speak_now_level6));
mInitializing = r.getDrawable(R.drawable.mic_slash);
mError = r.getDrawable(R.drawable.caution);
mImage = (ImageView) mView.findViewById(R.id.image);
mButton = mView.findViewById(R.id.button);
mButton.setOnClickListener(clickListener);
mText = (TextView) mView.findViewById(R.id.text);
mButtonText = (TextView) mView.findViewById(R.id.button_text);
mProgress = mView.findViewById(R.id.progress);
mContext = context;
}
public View getView() {
return mView;
}
public void showInitializing() {
mUiHandler.post(new Runnable() {
public void run() {
mText.setText(R.string.voice_initializing);
mImage.setImageDrawable(mInitializing);
mButtonText.setText(mContext.getText(R.string.cancel));
}
});
}
public void showStartState() {
if (EXPECT_RECORDING_DELAY) {
showInitializing();
} else {
showListening();
}
}
public void showListening() {
mState = State.LISTENING;
mUiHandler.post(new Runnable() {
public void run() {
mText.setText(R.string.voice_listening);
mImage.setImageDrawable(mSpeakNow.get(0));
mButtonText.setText(mContext.getText(R.string.cancel));
}
});
mUiHandler.postDelayed(mUpdateVolumeRunnable, 50);
}
public void updateVoiceMeter(final float rmsdB) {
mVolume = rmsdB;
}
public void showError(final String message) {
mState = State.READY;
mUiHandler.post(new Runnable() {
public void run() {
exitWorking();
mText.setText(message);
mImage.setImageDrawable(mError);
mButtonText.setText(mContext.getText(R.string.ok));
}
});
}
public void showWorking(
final ByteArrayOutputStream waveBuffer,
final int speechStartPosition,
final int speechEndPosition) {
mState = State.WORKING;
mUiHandler.post(new Runnable() {
public void run() {
mText.setText(R.string.voice_working);
mImage.setVisibility(View.GONE);
mProgress.setVisibility(View.VISIBLE);
final ShortBuffer buf = ByteBuffer.wrap(waveBuffer.toByteArray())
.order(ByteOrder.nativeOrder()).asShortBuffer();
buf.position(0);
waveBuffer.reset();
showWave(buf, speechStartPosition / 2, speechEndPosition / 2);
}
});
}
/**
* @return an average abs of the specified buffer.
*/
private static int getAverageAbs(ShortBuffer buffer, int start, int i, int npw) {
int from = start + i * npw;
int end = from + npw;
int total = 0;
for (int x = from; x < end; x++) {
total += Math.abs(buffer.get(x));
}
return total / npw;
}
/**
* Shows waveform of input audio.
*
* Copied from version in VoiceSearch's RecognitionActivity.
*
* TODO: adjust stroke width based on the size of data.
* TODO: use dip rather than pixels.
*/
private void showWave(ShortBuffer waveBuffer, int startPosition, int endPosition) {
final int w = ((View) mImage.getParent()).getWidth();
final int h = mImage.getHeight();
if (w <= 0 || h <= 0) {
// view is not visible this time. Skip drawing.
return;
}
final Bitmap b = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
final Canvas c = new Canvas(b);
final Paint paint = new Paint();
paint.setColor(0xFFFFFFFF); // 0xAARRGGBB
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.STROKE);
paint.setAlpha(0x90);
final PathEffect effect = new CornerPathEffect(3);
paint.setPathEffect(effect);
final int numSamples = waveBuffer.remaining();
int endIndex;
if (endPosition == 0) {
endIndex = numSamples;
} else {
endIndex = Math.min(endPosition, numSamples);
}
int startIndex = startPosition - 2000; // include 250ms before speech
if (startIndex < 0) {
startIndex = 0;
}
final int numSamplePerWave = 200; // 8KHz 25ms = 200 samples
final float scale = 10.0f / 65536.0f;
final int count = (endIndex - startIndex) / numSamplePerWave;
final float deltaX = 1.0f * w / count;
int yMax = h / 2 - 10;
Path path = new Path();
c.translate(0, yMax);
float x = 0;
path.moveTo(x, 0);
yMax -= 10;
for (int i = 0; i < count; i++) {
final int avabs = getAverageAbs(waveBuffer, startIndex, i , numSamplePerWave);
int sign = ( (i & 01) == 0) ? -1 : 1;
final float y = Math.min(yMax, avabs * h * scale) * sign;
path.lineTo(x, y);
x += deltaX;
path.lineTo(x, y);
}
if (deltaX > 4) {
paint.setStrokeWidth(3);
} else {
paint.setStrokeWidth(Math.max(1, (int) (deltaX -.05)));
}
c.drawPath(path, paint);
mImage.setImageBitmap(b);
mImage.setVisibility(View.VISIBLE);
MarginLayoutParams mProgressParams = (MarginLayoutParams)mProgress.getLayoutParams();
mProgressParams.topMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
-h / 2 - 18, mContext.getResources().getDisplayMetrics());
// Tweak the padding manually to fill out the whole view horizontally.
// TODO: Do this in the xml layout instead.
((View) mImage.getParent()).setPadding(4, ((View) mImage.getParent()).getPaddingTop(), 3,
((View) mImage.getParent()).getPaddingBottom());
mProgress.setLayoutParams(mProgressParams);
}
public void finish() {
mState = State.READY;
mUiHandler.post(new Runnable() {
public void run() {
exitWorking();
}
});
showStartState();
}
private void exitWorking() {
mProgress.setVisibility(View.GONE);
mImage.setVisibility(View.VISIBLE);
}
}

View File

@ -0,0 +1,551 @@
/*
* Copyright (C) 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.android.inputmethod.voice;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.speech.IRecognitionListener;
import android.speech.RecognitionServiceUtil;
import android.speech.RecognizerIntent;
import android.speech.RecognitionResult;
import android.view.View;
import android.view.View.OnClickListener;
import com.android.inputmethod.latin.R;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* Speech recognition input, including both user interface and a background
* process to stream audio to the network recognizer. This class supplies a
* View (getView()), which it updates as recognition occurs. The user of this
* class is responsible for making the view visible to the user, as well as
* handling various events returned through UiListener.
*/
public class VoiceInput implements OnClickListener {
private static final String TAG = "VoiceInput";
private static final String EXTRA_RECOGNITION_CONTEXT =
"android.speech.extras.RECOGNITION_CONTEXT";
private static final String EXTRA_CALLING_PACKAGE = "calling_package";
private static final String DEFAULT_RECOMMENDED_PACKAGES =
"com.android.mms " +
"com.google.android.gm " +
"com.google.android.talk " +
"com.google.android.apps.googlevoice " +
"com.android.email " +
"com.android.browser ";
// WARNING! Before enabling this, fix the problem with calling getExtractedText() in
// landscape view. It causes Extracted text updates to be rejected due to a token mismatch
public static boolean ENABLE_WORD_CORRECTIONS = false;
private static Boolean sVoiceIsAvailable = null;
// Dummy word suggestion which means "delete current word"
public static final String DELETE_SYMBOL = " \u00D7 "; // times symbol
private Whitelist mRecommendedList;
private Whitelist mBlacklist;
private VoiceInputLogger mLogger;
// Names of a few intent extras defined in VoiceSearch's RecognitionService.
// These let us tweak the endpointer parameters.
private static final String EXTRA_SPEECH_MINIMUM_LENGTH_MILLIS =
"android.speech.extras.SPEECH_INPUT_MINIMUM_LENGTH_MILLIS";
private static final String EXTRA_SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS =
"android.speech.extras.SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS";
private static final String EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS =
"android.speech.extras.SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS";
// The usual endpointer default value for input complete silence length is 0.5 seconds,
// but that's used for things like voice search. For dictation-like voice input like this,
// we go with a more liberal value of 1 second. This value will only be used if a value
// is not provided from Gservices.
private static final String INPUT_COMPLETE_SILENCE_LENGTH_DEFAULT_VALUE_MILLIS = "1000";
// Used to record part of that state for logging purposes.
public static final int DEFAULT = 0;
public static final int LISTENING = 1;
public static final int WORKING = 2;
public static final int ERROR = 3;
private int mState = DEFAULT;
/**
* Events relating to the recognition UI. You must implement these.
*/
public interface UiListener {
/**
* @param recognitionResults a set of transcripts for what the user
* spoke, sorted by likelihood.
*/
public void onVoiceResults(
List<String> recognitionResults,
Map<String, List<CharSequence>> alternatives);
/**
* Called when the user cancels speech recognition.
*/
public void onCancelVoice();
}
private RecognitionServiceUtil.Connection mRecognitionConnection;
private IRecognitionListener mRecognitionListener;
private RecognitionView mRecognitionView;
private UiListener mUiListener;
private Context mContext;
private ScheduledThreadPoolExecutor mExecutor;
/**
* @param context the service or activity in which we're runing.
* @param uiHandler object to receive events from VoiceInput.
*/
public VoiceInput(Context context, UiListener uiHandler) {
mLogger = VoiceInputLogger.getLogger(context);
mRecognitionListener = new IMERecognitionListener();
mRecognitionConnection = new RecognitionServiceUtil.Connection() {
public synchronized void onServiceConnected(
ComponentName name, IBinder service) {
super.onServiceConnected(name, service);
}
};
mUiListener = uiHandler;
mContext = context;
newView();
String recommendedPackages = GoogleSettingsUtil.getGservicesString(
context.getContentResolver(),
GoogleSettingsUtil.LATIN_IME_VOICE_INPUT_RECOMMENDED_PACKAGES,
DEFAULT_RECOMMENDED_PACKAGES);
mRecommendedList = new Whitelist();
for (String recommendedPackage : recommendedPackages.split("\\s+")) {
mRecommendedList.addApp(recommendedPackage);
}
mBlacklist = new Whitelist();
mBlacklist.addApp("com.android.setupwizard");
mExecutor = new ScheduledThreadPoolExecutor(1);
bindIfNecessary();
}
/**
* @return true if field is blacklisted for voice
*/
public boolean isBlacklistedField(FieldContext context) {
return mBlacklist.matches(context);
}
/**
* Used to decide whether to show voice input hints for this field, etc.
*
* @return true if field is recommended for voice
*/
public boolean isRecommendedField(FieldContext context) {
return mRecommendedList.matches(context);
}
/**
* @return true if the speech service is available on the platform.
*/
public static boolean voiceIsAvailable(Context context) {
if (sVoiceIsAvailable != null) {
return sVoiceIsAvailable;
}
RecognitionServiceUtil.Connection recognitionConnection =
new RecognitionServiceUtil.Connection();
boolean bound = context.bindService(
makeIntent(), recognitionConnection, Context.BIND_AUTO_CREATE);
context.unbindService(recognitionConnection);
sVoiceIsAvailable = bound;
return bound;
}
/**
* Start listening for speech from the user. This will grab the microphone
* and start updating the view provided by getView(). It is the caller's
* responsibility to ensure that the view is visible to the user at this stage.
*
* @param context the same FieldContext supplied to voiceIsEnabled()
* @param swipe whether this voice input was started by swipe, for logging purposes
*/
public void startListening(FieldContext context, boolean swipe) {
mState = DEFAULT;
Locale locale = Locale.getDefault();
String localeString = locale.getLanguage() + "-" + locale.getCountry();
mLogger.start(localeString, swipe);
mState = LISTENING;
if (mRecognitionConnection.mService == null) {
mRecognitionView.showInitializing();
} else {
mRecognitionView.showStartState();
}
if (!bindIfNecessary()) {
mState = ERROR;
// We use CLIENT_ERROR to signify voice search is not available on the device.
onError(RecognitionResult.CLIENT_ERROR, false);
cancel();
}
if (mRecognitionConnection.mService != null) {
try {
Intent intent = makeIntent();
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, "");
intent.putExtra(EXTRA_RECOGNITION_CONTEXT, context.getBundle());
intent.putExtra(EXTRA_CALLING_PACKAGE, "VoiceIME");
intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS,
GoogleSettingsUtil.getGservicesInt(
mContext.getContentResolver(),
GoogleSettingsUtil.LATIN_IME_MAX_VOICE_RESULTS,
1));
// Get endpointer params from Gservices.
// TODO: Consider caching these values for improved performance on slower devices.
ContentResolver cr = mContext.getContentResolver();
putEndpointerExtra(
cr,
intent,
GoogleSettingsUtil.LATIN_IME_SPEECH_MINIMUM_LENGTH_MILLIS,
EXTRA_SPEECH_MINIMUM_LENGTH_MILLIS,
null /* rely on endpointer default */);
putEndpointerExtra(
cr,
intent,
GoogleSettingsUtil.LATIN_IME_SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS,
EXTRA_SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS,
INPUT_COMPLETE_SILENCE_LENGTH_DEFAULT_VALUE_MILLIS
/* our default value is different from the endpointer's */);
putEndpointerExtra(
cr,
intent,
GoogleSettingsUtil.
LATIN_IME_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS,
EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS,
null /* rely on endpointer default */);
mRecognitionConnection.mService.startListening(
intent, mRecognitionListener);
} catch (RemoteException e) {
Log.e(TAG, "Could not start listening", e);
onError(-1 /* no specific error, just show default error */, false);
}
}
}
/**
* Gets the value of the provided Gservices key, attempts to parse it into a long,
* and if successful, puts the long value as an extra in the provided intent.
*/
private void putEndpointerExtra(ContentResolver cr, Intent i,
String gservicesKey, String intentExtraKey, String defaultValue) {
long l = -1;
String s = GoogleSettingsUtil.getGservicesString(cr, gservicesKey, defaultValue);
if (s != null) {
try {
l = Long.valueOf(s);
} catch (NumberFormatException e) {
Log.e(TAG, "could not parse value for " + gservicesKey + ": " + s);
}
}
if (l != -1) i.putExtra(intentExtraKey, l);
}
public void destroy() {
if (mRecognitionConnection.mService != null) {
//mContext.unbindService(mRecognitionConnection);
}
}
/**
* Creates a new instance of the view that is returned by {@link #getView()}
* Clients should use this when a previously returned view is stuck in a
* layout that is being thrown away and a new one is need to show to the
* user.
*/
public void newView() {
mRecognitionView = new RecognitionView(mContext, this);
}
/**
* @return a view that shows the recognition flow--e.g., "Speak now" and
* "working" dialogs.
*/
public View getView() {
return mRecognitionView.getView();
}
/**
* Handle the cancel button.
*/
public void onClick(View view) {
switch(view.getId()) {
case R.id.button:
cancel();
break;
}
}
public void logTextModified() {
mLogger.textModified();
}
public void logKeyboardWarningDialogShown() {
mLogger.keyboardWarningDialogShown();
}
public void logKeyboardWarningDialogDismissed() {
mLogger.keyboardWarningDialogDismissed();
}
public void logKeyboardWarningDialogOk() {
mLogger.keyboardWarningDialogOk();
}
public void logKeyboardWarningDialogCancel() {
mLogger.keyboardWarningDialogCancel();
}
public void logSwipeHintDisplayed() {
mLogger.swipeHintDisplayed();
}
public void logPunctuationHintDisplayed() {
mLogger.punctuationHintDisplayed();
}
public void logVoiceInputDelivered() {
mLogger.voiceInputDelivered();
}
public void logNBestChoose(int index) {
mLogger.nBestChoose(index);
}
public void logInputEnded() {
mLogger.inputEnded();
}
public void flushLogs() {
mLogger.flush();
}
private static Intent makeIntent() {
Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
// On Cupcake, use VoiceIMEHelper since VoiceSearch doesn't support.
// On Donut, always use VoiceSearch, since VoiceIMEHelper and
// VoiceSearch may conflict.
if (Build.VERSION.RELEASE.equals("1.5")) {
intent = intent.setClassName(
"com.google.android.voiceservice",
"com.google.android.voiceservice.IMERecognitionService");
} else {
intent = intent.setClassName(
"com.google.android.voicesearch",
"com.google.android.voicesearch.RecognitionService");
}
return intent;
}
/**
* Bind to the recognition service if necessary.
* @return true if we are bound or binding to the service, false if
* the recognition service is unavailable.
*/
private boolean bindIfNecessary() {
if (mRecognitionConnection.mService != null) {
return true;
}
return mContext.bindService(
makeIntent(), mRecognitionConnection, Context.BIND_AUTO_CREATE);
}
/**
* Cancel in-progress speech recognition.
*/
public void cancel() {
switch (mState) {
case LISTENING:
mLogger.cancelDuringListening();
break;
case WORKING:
mLogger.cancelDuringWorking();
break;
case ERROR:
mLogger.cancelDuringError();
break;
}
mState = DEFAULT;
// Remove all pending tasks (e.g., timers to cancel voice input)
for (Runnable runnable : mExecutor.getQueue()) {
mExecutor.remove(runnable);
}
if (mRecognitionConnection.mService != null) {
try {
mRecognitionConnection.mService.cancel();
} catch (RemoteException e) {
Log.e(TAG, "Exception on cancel", e);
}
}
mUiListener.onCancelVoice();
mRecognitionView.finish();
}
private int getErrorStringId(int errorType, boolean endpointed) {
switch (errorType) {
// We use CLIENT_ERROR to signify that voice search is not available on the device.
case RecognitionResult.CLIENT_ERROR:
return R.string.voice_not_installed;
case RecognitionResult.NETWORK_ERROR:
return R.string.voice_network_error;
case RecognitionResult.NETWORK_TIMEOUT:
return endpointed ?
R.string.voice_network_error : R.string.voice_too_much_speech;
case RecognitionResult.AUDIO_ERROR:
return R.string.voice_audio_error;
case RecognitionResult.SERVER_ERROR:
return R.string.voice_server_error;
case RecognitionResult.SPEECH_TIMEOUT:
return R.string.voice_speech_timeout;
case RecognitionResult.NO_MATCH:
return R.string.voice_no_match;
default: return R.string.voice_error;
}
}
private void onError(int errorType, boolean endpointed) {
Log.i(TAG, "error " + errorType);
mLogger.error(errorType);
onError(mContext.getString(getErrorStringId(errorType, endpointed)));
}
private void onError(String error) {
mState = ERROR;
mRecognitionView.showError(error);
// Wait a couple seconds and then automatically dismiss message.
mExecutor.schedule(new Runnable() {
public void run() {
cancel();
}}, 2000, TimeUnit.MILLISECONDS);
}
private class IMERecognitionListener extends IRecognitionListener.Stub {
// Waveform data
final ByteArrayOutputStream mWaveBuffer = new ByteArrayOutputStream();
int mSpeechStart;
private boolean mEndpointed = false;
public void onReadyForSpeech(Bundle noiseParams) {
mRecognitionView.showListening();
}
public void onBeginningOfSpeech() {
mEndpointed = false;
mSpeechStart = mWaveBuffer.size();
}
public void onRmsChanged(float rmsdB) {
mRecognitionView.updateVoiceMeter(rmsdB);
}
public void onBufferReceived(byte[] buf) {
try {
mWaveBuffer.write(buf);
} catch (IOException e) {}
}
public void onEndOfSpeech() {
mEndpointed = true;
mState = WORKING;
mRecognitionView.showWorking(mWaveBuffer, mSpeechStart, mWaveBuffer.size());
}
public void onError(int errorType) {
mState = ERROR;
VoiceInput.this.onError(errorType, mEndpointed);
}
public void onResults(List<RecognitionResult> results, long token) {
mState = DEFAULT;
List<String> resultsAsText = new ArrayList<String>();
for (RecognitionResult result : results) {
resultsAsText.add(result.mText);
}
Map<String, List<CharSequence>> alternatives =
new HashMap<String, List<CharSequence>>();
if (resultsAsText.size() >= 2 && ENABLE_WORD_CORRECTIONS) {
String[][] words = new String[resultsAsText.size()][];
for (int i = 0; i < words.length; i++) {
words[i] = resultsAsText.get(i).split(" ");
}
for (int key = 0; key < words[0].length; key++) {
alternatives.put(words[0][key], new ArrayList<CharSequence>());
for (int alt = 1; alt < words.length; alt++) {
int keyBegin = key * words[alt].length / words[0].length;
int keyEnd = (key + 1) * words[alt].length / words[0].length;
for (int i = keyBegin; i < Math.min(words[alt].length, keyEnd); i++) {
List<CharSequence> altList = alternatives.get(words[0][key]);
if (!altList.contains(words[alt][i]) && altList.size() < 6) {
altList.add(words[alt][i]);
}
}
}
}
}
if (resultsAsText.size() > 5) {
resultsAsText = resultsAsText.subList(0, 5);
}
mUiListener.onVoiceResults(resultsAsText, alternatives);
mRecognitionView.finish();
destroy();
}
}
}

View File

@ -0,0 +1,174 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.android.inputmethod.voice;
import android.content.Context;
import android.content.Intent;
/**
* Provides the logging facility for voice input events. This fires broadcasts back to
* the voice search app which then logs on our behalf.
*
* Note that debug console logging does not occur in this class. If you want to
* see console output of these logging events, there is a boolean switch to turn
* on on the VoiceSearch side.
*/
public class VoiceInputLogger {
private static final String TAG = VoiceInputLogger.class.getSimpleName();
private static VoiceInputLogger sVoiceInputLogger;
private final Context mContext;
// The base intent used to form all broadcast intents to the logger
// in VoiceSearch.
private final Intent mBaseIntent;
/**
* Returns the singleton of the logger.
*
* @param contextHint a hint context used when creating the logger instance.
* Ignored if the singleton instance already exists.
*/
public static synchronized VoiceInputLogger getLogger(Context contextHint) {
if (sVoiceInputLogger == null) {
sVoiceInputLogger = new VoiceInputLogger(contextHint);
}
return sVoiceInputLogger;
}
public VoiceInputLogger(Context context) {
mContext = context;
mBaseIntent = new Intent(LoggingEvents.ACTION_LOG_EVENT);
mBaseIntent.putExtra(LoggingEvents.EXTRA_APP_NAME, LoggingEvents.VoiceIme.APP_NAME);
}
private Intent newLoggingBroadcast(int event) {
Intent i = new Intent(mBaseIntent);
i.putExtra(LoggingEvents.EXTRA_EVENT, event);
return i;
}
public void flush() {
Intent i = new Intent(mBaseIntent);
i.putExtra(LoggingEvents.EXTRA_FLUSH, true);
mContext.sendBroadcast(i);
}
public void keyboardWarningDialogShown() {
mContext.sendBroadcast(newLoggingBroadcast(
LoggingEvents.VoiceIme.KEYBOARD_WARNING_DIALOG_SHOWN));
}
public void keyboardWarningDialogDismissed() {
mContext.sendBroadcast(newLoggingBroadcast(
LoggingEvents.VoiceIme.KEYBOARD_WARNING_DIALOG_DISMISSED));
}
public void keyboardWarningDialogOk() {
mContext.sendBroadcast(newLoggingBroadcast(
LoggingEvents.VoiceIme.KEYBOARD_WARNING_DIALOG_OK));
}
public void keyboardWarningDialogCancel() {
mContext.sendBroadcast(newLoggingBroadcast(
LoggingEvents.VoiceIme.KEYBOARD_WARNING_DIALOG_CANCEL));
}
public void settingsWarningDialogShown() {
mContext.sendBroadcast(newLoggingBroadcast(
LoggingEvents.VoiceIme.SETTINGS_WARNING_DIALOG_SHOWN));
}
public void settingsWarningDialogDismissed() {
mContext.sendBroadcast(newLoggingBroadcast(
LoggingEvents.VoiceIme.SETTINGS_WARNING_DIALOG_DISMISSED));
}
public void settingsWarningDialogOk() {
mContext.sendBroadcast(newLoggingBroadcast(
LoggingEvents.VoiceIme.SETTINGS_WARNING_DIALOG_OK));
}
public void settingsWarningDialogCancel() {
mContext.sendBroadcast(newLoggingBroadcast(
LoggingEvents.VoiceIme.SETTINGS_WARNING_DIALOG_CANCEL));
}
public void swipeHintDisplayed() {
mContext.sendBroadcast(newLoggingBroadcast(LoggingEvents.VoiceIme.SWIPE_HINT_DISPLAYED));
}
public void cancelDuringListening() {
mContext.sendBroadcast(newLoggingBroadcast(LoggingEvents.VoiceIme.CANCEL_DURING_LISTENING));
}
public void cancelDuringWorking() {
mContext.sendBroadcast(newLoggingBroadcast(LoggingEvents.VoiceIme.CANCEL_DURING_WORKING));
}
public void cancelDuringError() {
mContext.sendBroadcast(newLoggingBroadcast(LoggingEvents.VoiceIme.CANCEL_DURING_ERROR));
}
public void punctuationHintDisplayed() {
mContext.sendBroadcast(newLoggingBroadcast(
LoggingEvents.VoiceIme.PUNCTUATION_HINT_DISPLAYED));
}
public void error(int code) {
Intent i = newLoggingBroadcast(LoggingEvents.VoiceIme.ERROR);
i.putExtra(LoggingEvents.VoiceIme.EXTRA_ERROR_CODE, code);
mContext.sendBroadcast(i);
}
public void start(String locale, boolean swipe) {
Intent i = newLoggingBroadcast(LoggingEvents.VoiceIme.START);
i.putExtra(LoggingEvents.VoiceIme.EXTRA_START_LOCALE, locale);
i.putExtra(LoggingEvents.VoiceIme.EXTRA_START_SWIPE, swipe);
mContext.sendBroadcast(i);
}
public void voiceInputDelivered() {
mContext.sendBroadcast(newLoggingBroadcast(LoggingEvents.VoiceIme.VOICE_INPUT_DELIVERED));
}
public void textModified() {
mContext.sendBroadcast(newLoggingBroadcast(LoggingEvents.VoiceIme.TEXT_MODIFIED));
}
public void nBestChoose(int index) {
Intent i = newLoggingBroadcast(LoggingEvents.VoiceIme.N_BEST_CHOOSE);
i.putExtra(LoggingEvents.VoiceIme.EXTRA_N_BEST_CHOOSE_INDEX, index);
mContext.sendBroadcast(i);
}
public void inputEnded() {
mContext.sendBroadcast(newLoggingBroadcast(LoggingEvents.VoiceIme.INPUT_ENDED));
}
public void voiceInputSettingEnabled() {
mContext.sendBroadcast(newLoggingBroadcast(
LoggingEvents.VoiceIme.VOICE_INPUT_SETTING_ENABLED));
}
public void voiceInputSettingDisabled() {
mContext.sendBroadcast(newLoggingBroadcast(
LoggingEvents.VoiceIme.VOICE_INPUT_SETTING_DISABLED));
}
}

View File

@ -0,0 +1,90 @@
/*
* Copyright (C) 2008-2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.android.inputmethod.voice;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import java.io.ByteArrayOutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.ShortBuffer;
/**
* Utility class to draw a waveform into a bitmap, given a byte array
* that represents the waveform as a sequence of 16-bit integers.
* Adapted from RecognitionActivity.java.
*/
public class WaveformImage {
private static final int SAMPLING_RATE = 8000;
private WaveformImage() {}
public static Bitmap drawWaveform(
ByteArrayOutputStream waveBuffer, int w, int h, int start, int end) {
final Bitmap b = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
final Canvas c = new Canvas(b);
final Paint paint = new Paint();
paint.setColor(0xFFFFFFFF); // 0xRRGGBBAA
paint.setAntiAlias(true);
paint.setStrokeWidth(0);
final ShortBuffer buf = ByteBuffer
.wrap(waveBuffer.toByteArray())
.order(ByteOrder.nativeOrder())
.asShortBuffer();
buf.position(0);
final int numSamples = waveBuffer.size() / 2;
final int delay = (SAMPLING_RATE * 100 / 1000);
int endIndex = end / 2 + delay;
if (end == 0 || endIndex >= numSamples) {
endIndex = numSamples;
}
int index = start / 2 - delay;
if (index < 0) {
index = 0;
}
final int size = endIndex - index;
int numSamplePerPixel = 32;
int delta = size / (numSamplePerPixel * w);
if (delta == 0) {
numSamplePerPixel = size / w;
delta = 1;
}
final float scale = 3.5f / 65536.0f;
// do one less column to make sure we won't read past
// the buffer.
try {
for (int i = 0; i < w - 1 ; i++) {
final float x = i;
for (int j = 0; j < numSamplePerPixel; j++) {
final short s = buf.get(index);
final float y = (h / 2) - (s * h * scale);
c.drawPoint(x, y, paint);
index += delta;
}
}
} catch (IndexOutOfBoundsException e) {
// this can happen, but we don't care
}
return b;
}
}

View File

@ -0,0 +1,67 @@
/*
* Copyright (C) 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.android.inputmethod.voice;
import android.os.Bundle;
import java.util.ArrayList;
import java.util.List;
/**
* A set of text fields where speech has been explicitly enabled.
*/
public class Whitelist {
private List<Bundle> mConditions;
public Whitelist() {
mConditions = new ArrayList<Bundle>();
}
public Whitelist(List<Bundle> conditions) {
this.mConditions = conditions;
}
public void addApp(String app) {
Bundle bundle = new Bundle();
bundle.putString("packageName", app);
mConditions.add(bundle);
}
/**
* @return true if the field is a member of the whitelist.
*/
public boolean matches(FieldContext context) {
for (Bundle condition : mConditions) {
if (matches(condition, context.getBundle())) {
return true;
}
}
return false;
}
/**
* @return true of all values in condition are matched by a value
* in target.
*/
private boolean matches(Bundle condition, Bundle target) {
for (String key : condition.keySet()) {
if (!condition.getString(key).equals(target.getString(key))) {
return false;
}
}
return true;
}
}

View File

@ -0,0 +1,29 @@
/*
*
* Copyright (C) 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.voicesearch;
import android.content.Intent;
import com.android.inputmethod.latin.LatinIME;
public class LatinIMEWithVoice extends LatinIME {
@Override
protected void launchSettings() {
launchSettings(LatinIMEWithVoiceSettings.class);
}
}

View File

@ -0,0 +1,5 @@
package com.google.android.voicesearch;
import com.android.inputmethod.latin.LatinIMESettings;
public class LatinIMEWithVoiceSettings extends LatinIMESettings {}