diff --git a/README.md b/README.md index ae62abc00..b1e6a3abe 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,6 @@ Does not use internet permission, and thus is 100% offline. * [Translations](#translations) * [To Community Creation](#to-community) * [Code Contribution](CONTRIBUTING.md) -- [To-do](#to-do) - [License](#license) - [Credits](#credits) @@ -41,7 +40,7 @@ Does not use internet permission, and thus is 100% offline.
  • Clipboard history
  • One-handed mode
  • -
  • Split keyboard (only available if the screen is large enough)
  • +
  • Split keyboard
  • Number pad
  • Backup and restore your settings and learned word / history data
  • @@ -88,26 +87,6 @@ You can share your themes, layouts and dictionaries with other people: ## Code Contribution See [Contribution Guidelines](CONTRIBUTING.md) -# To-do -__Planned features and improvements:__ -* Improve support for modifier keys (_alt_, _ctrl_, _meta_ and _fn_), some ideas: - * keep modifier keys on with long press - * keep modifier keys on until the next key press - * use sliding input -* Less complicated addition of new keyboard languages (e.g. #519) -* Additional and customizable key swipe functionality - * Some functionality will not be possible when using glide typing -* Add and enable emoji dictionaries by default (if available for language) -* Clearer / more intuitive arrangement of settings - * Maybe hide some less used settings by default (similar to color customization) -* Make use of the `.com` key in URL fields (currently only available for tablets) - * With language-dependent TLDs -* [Bug fixes](https://github.com/Helium314/HeliBoard/issues?q=is%3Aissue+is%3Aopen+label%3Abug) - -__What will _not_ be added:__ -* Dictionaries for more languages (you can still download them) -* Anything that requires additional permissions, unless there is a _very_ good reason - # License HeliBoard (as a fork of OpenBoard) is licensed under GNU General Public License v3.0. diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 30956503b..a2d08146f 100755 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,20 +1,19 @@ plugins { id("com.android.application") kotlin("android") - kotlin("plugin.serialization") version "2.0.21" + kotlin("plugin.serialization") version "2.1.21" kotlin("plugin.compose") version "2.0.0" } android { - compileSdk = 34 - buildToolsVersion = "34.0.0" + compileSdk = 35 defaultConfig { applicationId = "helium314.keyboard" minSdk = 21 - targetSdk = 34 - versionCode = 3000 - versionName = "3.0-alpha1" + targetSdk = 35 + versionCode = 3101 + versionName = "3.1" ndk { abiFilters.clear() abiFilters.addAll(listOf("armeabi-v7a", "arm64-v8a", "x86", "x86_64")) @@ -36,14 +35,23 @@ android { isJniDebuggable = false } debug { + // "normal" debug has minify for smaller APK to fit the GitHub 25 MB limit when zipped + // and for better performance in case users want to install a debug APK isMinifyEnabled = true isJniDebuggable = false applicationIdSuffix = ".debug" } create("runTests") { // build variant for running tests on CI that skips tests known to fail - isMinifyEnabled = true + isMinifyEnabled = false isJniDebuggable = false } + create("debugNoMinify") { // for faster builds in IDE + isDebuggable = true + isMinifyEnabled = false + isJniDebuggable = false + signingConfig = signingConfigs.getByName("debug") + applicationIdSuffix = ".debug" + } base.archivesBaseName = "HeliBoard_" + defaultConfig.versionName } @@ -58,9 +66,9 @@ android { path = File("src/main/jni/Android.mk") } } - ndkVersion = "26.2.11394342" + ndkVersion = "28.0.13004108" - packagingOptions { + packaging { jniLibs { // shrinks APK by 3 MB, zipped size unchanged useLegacyPackaging = true @@ -96,29 +104,29 @@ android { dependencies { // androidx - implementation("androidx.core:core-ktx:1.13.1") - implementation("androidx.appcompat:appcompat:1.7.0") - implementation("androidx.recyclerview:recyclerview:1.3.2") + implementation("androidx.core:core-ktx:1.16.0") + implementation("androidx.recyclerview:recyclerview:1.4.0") implementation("androidx.autofill:autofill:1.1.0") + implementation("androidx.viewpager2:viewpager2:1.1.0") // kotlin - implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.8.0") + implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.8.1") // compose coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.5") - implementation(platform("androidx.compose:compose-bom:2025.02.00")) + implementation(platform("androidx.compose:compose-bom:2025.05.00")) implementation("androidx.compose.material3:material3") implementation("androidx.compose.ui:ui-tooling-preview") debugImplementation("androidx.compose.ui:ui-tooling") - implementation("androidx.navigation:navigation-compose:2.8.8") + implementation("androidx.navigation:navigation-compose:2.9.0") implementation("sh.calvin.reorderable:reorderable:2.4.3") // for easier re-ordering implementation("com.github.skydoves:colorpicker-compose:1.1.2") // for user-defined colors // test testImplementation(kotlin("test")) testImplementation("junit:junit:4.13.2") - testImplementation("org.mockito:mockito-core:5.15.2") - testImplementation("org.robolectric:robolectric:4.12.1") + testImplementation("org.mockito:mockito-core:5.17.0") + testImplementation("org.robolectric:robolectric:4.14.1") testImplementation("androidx.test:runner:1.6.2") testImplementation("androidx.test:core:1.6.1") } diff --git a/app/src/debugNoMinify/res/values/strings.xml b/app/src/debugNoMinify/res/values/strings.xml new file mode 100644 index 000000000..73f1a95de --- /dev/null +++ b/app/src/debugNoMinify/res/values/strings.xml @@ -0,0 +1,9 @@ + + + + HeliBoard debug + HeliBoard debug Spell Checker + HeliBoard debug Settings + diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index cecae1976..a7dcab1e6 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -98,7 +98,15 @@ SPDX-License-Identifier: Apache-2.0 AND GPL-3.0-only - + + + + + + + + + diff --git a/app/src/main/assets/dictionaries_in_dict_repo.csv b/app/src/main/assets/dictionaries_in_dict_repo.csv index 4cfdd146f..5ceab4f16 100644 --- a/app/src/main/assets/dictionaries_in_dict_repo.csv +++ b/app/src/main/assets/dictionaries_in_dict_repo.csv @@ -1,114 +1,116 @@ +main,af,exp main,ar, +main,ar,exp main,hy, main,as, +main,bn_BD,exp main,bn, +main,bn,exp main,eu, main,be, main,bg, +main,bg,exp main,ca, +main,ca,exp main,hr, +main,hr,exp main,cs, +main,cs,exp main,da, +main,da,exp main,nl, +main,nl,exp main,en_AU, +main,en_CA,exp main,en_GB, +main,en_GB,exp main,en_US, +main,en_US,exp +symbols,en,exp emoji,en, main,eo, +main,eo,exp +main,et,exp main,fi, +main,fi,exp emoji,fr, +symbols,fr,exp main,fr, +main,fr,exp main,gl, +main,gl,exp main,ka, +main,de_AT,exp +main,de_CH, main,de, +main,de,exp main,gom, main,el, main,gu, main,he, main,iw, +main,he,exp main,hi, main,hi_ZZ, main,hu, +main,hu,exp +main,is,exp +main,id,exp main,it, +main,it,exp +main,kab,exp main,kn, main,ks, +main,kk,exp main,km, main,la, main,lv, +main,lv,exp main,lt, +main,lt,exp main,lb, main,mai, +addon,ml_ZZ,exp main,ml, main,mr, +main,ne,exp main,nb, +main,nb,exp main,or, +main,pms,exp main,pl, +main,pl,exp main,pt_BR, main,pt_PT, +main,pt_PT,exp main,pa, main,ro, +main,ro,exp emoji,ru, main,ru, +main,ru,exp main,sa, main,sat, main,sr_ZZ, main,sr, main,sd, +main,sk,exp main,sl, +main,sl,exp main,es, +main,es,exp main,zgh_ZZ, main,zgh, main,sv, +main,sv,exp main,ta, main,te, main,tok, main,tcy, main,tr, +main,tr,exp emoji,uk, main,uk, -main,ur, -main,af,exp -main,ar,exp -main,bn_BD,exp -main,bn,exp -main,bg,exp -main,ca,exp -main,hr,exp -main,cs,exp -main,da,exp -main,nl,exp -main,en_GB,exp -main,en_US,exp -symbols,en,exp -main,eo,exp -main,et,exp -main,fi,exp -symbols,fr,exp -main,fr,exp -main,gl,exp -main,de_AT,exp -main,de,exp -main,he,exp -main,hu,exp -main,is,exp -main,id,exp -main,it,exp -main,kab,exp -main,kk,exp -main,lv,exp -main,lt,exp -addon,ml_ZZ,exp -main,ne,exp -main,nb,exp -main,pms,exp -main,pl,exp -main,pt_PT,exp -main,ro,exp -main,ru,exp -main,sk,exp -main,sl,exp -main,es,exp -main,sv,exp -main,tr,exp main,uk,exp +main,ur, main,vi,exp diff --git a/app/src/main/assets/emoji/ACTIVITIES.txt b/app/src/main/assets/emoji/ACTIVITIES.txt new file mode 100644 index 000000000..416ac152e --- /dev/null +++ b/app/src/main/assets/emoji/ACTIVITIES.txt @@ -0,0 +1,85 @@ +🎃 +🎄 +🎆 +🎇 +🧨 +✨ +🎈 +🎉 +🎊 +🎋 +🎍 +🎎 +🎏 +🎐 +🎑 +🧧 +🎀 +🎁 +🎗️ +🎟️ +🎫 +🎖️ +🏆 +🏅 +🥇 +🥈 +🥉 +⚽ +⚾ +🥎 +🏀 +🏐 +🏈 +🏉 +🎾 +🥏 +🎳 +🏏 +🏑 +🏒 +🥍 +🏓 +🏸 +🥊 +🥋 +🥅 +⛳ +⛸️ +🎣 +🤿 +🎽 +🎿 +🛷 +🥌 +🎯 +🪀 +🪁 +🔫 +🎱 +🔮 +🪄 +🎮 +🕹️ +🎰 +🎲 +🧩 +🧸 +🪅 +🪩 +🪆 +♠️ +♥️ +♦️ +♣️ +♟️ +🃏 +🀄 +🎴 +🎭 +🖼️ +🎨 +🧵 +🪡 +🧶 +🪢 \ No newline at end of file diff --git a/app/src/main/assets/emoji/ANIMALS_AND_NATURE.txt b/app/src/main/assets/emoji/ANIMALS_AND_NATURE.txt new file mode 100644 index 000000000..04b714520 --- /dev/null +++ b/app/src/main/assets/emoji/ANIMALS_AND_NATURE.txt @@ -0,0 +1,159 @@ +🐵 +🐒 +🦍 +🦧 +🐶 +🐕 +🦮 +🐕‍🦺 +🐩 +🐺 +🦊 +🦝 +🐱 +🐈 +🐈‍⬛ +🦁 +🐯 +🐅 +🐆 +🐴 +🫎 +🫏 +🐎 +🦄 +🦓 +🦌 +🦬 +🐮 +🐂 +🐃 +🐄 +🐷 +🐖 +🐗 +🐽 +🐏 +🐑 +🐐 +🐪 +🐫 +🦙 +🦒 +🐘 +🦣 +🦏 +🦛 +🐭 +🐁 +🐀 +🐹 +🐰 +🐇 +🐿️ +🦫 +🦔 +🦇 +🐻 +🐻‍❄️ +🐨 +🐼 +🦥 +🦦 +🦨 +🦘 +🦡 +🐾 +🦃 +🐔 +🐓 +🐣 +🐤 +🐥 +🐦 +🐧 +🕊️ +🦅 +🦆 +🦢 +🦉 +🦤 +🪶 +🦩 +🦚 +🦜 +🪽 +🐦‍⬛ +🪿 +🐦‍🔥 +🐸 +🐊 +🐢 +🦎 +🐍 +🐲 +🐉 +🦕 +🦖 +🐳 +🐋 +🐬 +🦭 +🐟 +🐠 +🐡 +🦈 +🐙 +🐚 +🪸 +🪼 +🦀 +🦞 +🦐 +🦑 +🦪 +🐌 +🦋 +🐛 +🐜 +🐝 +🪲 +🐞 +🦗 +🪳 +🕷️ +🕸️ +🦂 +🦟 +🪰 +🪱 +🦠 +💐 +🌸 +💮 +🪷 +🏵️ +🌹 +🥀 +🌺 +🌻 +🌼 +🌷 +🪻 +🌱 +🪴 +🌲 +🌳 +🌴 +🌵 +🌾 +🌿 +☘️ +🍀 +🍁 +🍂 +🍃 +🪹 +🪺 +🍄 +🪾 \ No newline at end of file diff --git a/app/src/main/assets/emoji/EMOTICONS.txt b/app/src/main/assets/emoji/EMOTICONS.txt new file mode 100644 index 000000000..c2b3d9ddd --- /dev/null +++ b/app/src/main/assets/emoji/EMOTICONS.txt @@ -0,0 +1,25 @@ +:-) +;-) +:-( +:-! +:-$ +B-) +=-O +:-P +:O +:-* +:-D +:\'( +:-\\ +O:-) +:-[ +(╯° +□°) +╯︵ +┻━┻ +¯\\_ +(ツ) +_/¯ +┬─┬ +︵ /( +.□.\\ \ No newline at end of file diff --git a/app/src/main/assets/emoji/FLAGS.txt b/app/src/main/assets/emoji/FLAGS.txt new file mode 100644 index 000000000..c4bd83460 --- /dev/null +++ b/app/src/main/assets/emoji/FLAGS.txt @@ -0,0 +1,270 @@ +🏁 +🚩 +🎌 +🏴 +🏳️ +🏳️‍🌈 +🏳️‍⚧️ +🏴‍☠️ +🇦🇨 +🇦🇩 +🇦🇪 +🇦🇫 +🇦🇬 +🇦🇮 +🇦🇱 +🇦🇲 +🇦🇴 +🇦🇶 +🇦🇷 +🇦🇸 +🇦🇹 +🇦🇺 +🇦🇼 +🇦🇽 +🇦🇿 +🇧🇦 +🇧🇧 +🇧🇩 +🇧🇪 +🇧🇫 +🇧🇬 +🇧🇭 +🇧🇮 +🇧🇯 +🇧🇱 +🇧🇲 +🇧🇳 +🇧🇴 +🇧🇶 +🇧🇷 +🇧🇸 +🇧🇹 +🇧🇻 +🇧🇼 +🇧🇾 +🇧🇿 +🇨🇦 +🇨🇨 +🇨🇩 +🇨🇫 +🇨🇬 +🇨🇭 +🇨🇮 +🇨🇰 +🇨🇱 +🇨🇲 +🇨🇳 +🇨🇴 +🇨🇵 +🇨🇶 +🇨🇷 +🇨🇺 +🇨🇻 +🇨🇼 +🇨🇽 +🇨🇾 +🇨🇿 +🇩🇪 +🇩🇬 +🇩🇯 +🇩🇰 +🇩🇲 +🇩🇴 +🇩🇿 +🇪🇦 +🇪🇨 +🇪🇪 +🇪🇬 +🇪🇭 +🇪🇷 +🇪🇸 +🇪🇹 +🇪🇺 +🇫🇮 +🇫🇯 +🇫🇰 +🇫🇲 +🇫🇴 +🇫🇷 +🇬🇦 +🇬🇧 +🇬🇩 +🇬🇪 +🇬🇫 +🇬🇬 +🇬🇭 +🇬🇮 +🇬🇱 +🇬🇲 +🇬🇳 +🇬🇵 +🇬🇶 +🇬🇷 +🇬🇸 +🇬🇹 +🇬🇺 +🇬🇼 +🇬🇾 +🇭🇰 +🇭🇲 +🇭🇳 +🇭🇷 +🇭🇹 +🇭🇺 +🇮🇨 +🇮🇩 +🇮🇪 +🇮🇱 +🇮🇲 +🇮🇳 +🇮🇴 +🇮🇶 +🇮🇷 +🇮🇸 +🇮🇹 +🇯🇪 +🇯🇲 +🇯🇴 +🇯🇵 +🇰🇪 +🇰🇬 +🇰🇭 +🇰🇮 +🇰🇲 +🇰🇳 +🇰🇵 +🇰🇷 +🇰🇼 +🇰🇾 +🇰🇿 +🇱🇦 +🇱🇧 +🇱🇨 +🇱🇮 +🇱🇰 +🇱🇷 +🇱🇸 +🇱🇹 +🇱🇺 +🇱🇻 +🇱🇾 +🇲🇦 +🇲🇨 +🇲🇩 +🇲🇪 +🇲🇫 +🇲🇬 +🇲🇭 +🇲🇰 +🇲🇱 +🇲🇲 +🇲🇳 +🇲🇴 +🇲🇵 +🇲🇶 +🇲🇷 +🇲🇸 +🇲🇹 +🇲🇺 +🇲🇻 +🇲🇼 +🇲🇽 +🇲🇾 +🇲🇿 +🇳🇦 +🇳🇨 +🇳🇪 +🇳🇫 +🇳🇬 +🇳🇮 +🇳🇱 +🇳🇴 +🇳🇵 +🇳🇷 +🇳🇺 +🇳🇿 +🇴🇲 +🇵🇦 +🇵🇪 +🇵🇫 +🇵🇬 +🇵🇭 +🇵🇰 +🇵🇱 +🇵🇲 +🇵🇳 +🇵🇷 +🇵🇸 +🇵🇹 +🇵🇼 +🇵🇾 +🇶🇦 +🇷🇪 +🇷🇴 +🇷🇸 +🇷🇺 +🇷🇼 +🇸🇦 +🇸🇧 +🇸🇨 +🇸🇩 +🇸🇪 +🇸🇬 +🇸🇭 +🇸🇮 +🇸🇯 +🇸🇰 +🇸🇱 +🇸🇲 +🇸🇳 +🇸🇴 +🇸🇷 +🇸🇸 +🇸🇹 +🇸🇻 +🇸🇽 +🇸🇾 +🇸🇿 +🇹🇦 +🇹🇨 +🇹🇩 +🇹🇫 +🇹🇬 +🇹🇭 +🇹🇯 +🇹🇰 +🇹🇱 +🇹🇲 +🇹🇳 +🇹🇴 +🇹🇷 +🇹🇹 +🇹🇻 +🇹🇼 +🇹🇿 +🇺🇦 +🇺🇬 +🇺🇲 +🇺🇳 +🇺🇸 +🇺🇾 +🇺🇿 +🇻🇦 +🇻🇨 +🇻🇪 +🇻🇬 +🇻🇮 +🇻🇳 +🇻🇺 +🇼🇫 +🇼🇸 +🇽🇰 +🇾🇪 +🇾🇹 +🇿🇦 +🇿🇲 +🇿🇼 +🏴󠁧󠁢󠁥󠁮󠁧󠁿 +🏴󠁧󠁢󠁳󠁣󠁴󠁿 +🏴󠁧󠁢󠁷󠁬󠁳󠁿 \ No newline at end of file diff --git a/app/src/main/assets/emoji/FOOD_AND_DRINK.txt b/app/src/main/assets/emoji/FOOD_AND_DRINK.txt new file mode 100644 index 000000000..cb9b5dd54 --- /dev/null +++ b/app/src/main/assets/emoji/FOOD_AND_DRINK.txt @@ -0,0 +1,131 @@ +🍇 +🍈 +🍉 +🍊 +🍋 +🍋‍🟩 +🍌 +🍍 +🥭 +🍎 +🍏 +🍐 +🍑 +🍒 +🍓 +🫐 +🥝 +🍅 +🫒 +🥥 +🥑 +🍆 +🥔 +🥕 +🌽 +🌶️ +🫑 +🥒 +🥬 +🥦 +🧄 +🧅 +🥜 +🫘 +🌰 +🫚 +🫛 +🍄‍🟫 +🫜 +🍞 +🥐 +🥖 +🫓 +🥨 +🥯 +🥞 +🧇 +🧀 +🍖 +🍗 +🥩 +🥓 +🍔 +🍟 +🍕 +🌭 +🥪 +🌮 +🌯 +🫔 +🥙 +🧆 +🥚 +🍳 +🥘 +🍲 +🫕 +🥣 +🥗 +🍿 +🧈 +🧂 +🥫 +🍱 +🍘 +🍙 +🍚 +🍛 +🍜 +🍝 +🍠 +🍢 +🍣 +🍤 +🍥 +🥮 +🍡 +🥟 +🥠 +🥡 +🍦 +🍧 +🍨 +🍩 +🍪 +🎂 +🍰 +🧁 +🥧 +🍫 +🍬 +🍭 +🍮 +🍯 +🍼 +🥛 +☕ +🫖 +🍵 +🍶 +🍾 +🍷 +🍸 +🍹 +🍺 +🍻 +🥂 +🥃 +🫗 +🥤 +🧋 +🧃 +🧉 +🧊 +🥢 +🍽️ +🍴 +🥄 +🔪 +🫙 +🏺 \ No newline at end of file diff --git a/app/src/main/assets/emoji/OBJECTS.txt b/app/src/main/assets/emoji/OBJECTS.txt new file mode 100644 index 000000000..38b94b0b7 --- /dev/null +++ b/app/src/main/assets/emoji/OBJECTS.txt @@ -0,0 +1,264 @@ +👓 +🕶️ +🥽 +🥼 +🦺 +👔 +👕 +👖 +🧣 +🧤 +🧥 +🧦 +👗 +👘 +🥻 +🩱 +🩲 +🩳 +👙 +👚 +🪭 +👛 +👜 +👝 +🛍️ +🎒 +🩴 +👞 +👟 +🥾 +🥿 +👠 +👡 +🩰 +👢 +🪮 +👑 +👒 +🎩 +🎓 +🧢 +🪖 +⛑️ +📿 +💄 +💍 +💎 +🔇 +🔈 +🔉 +🔊 +📢 +📣 +📯 +🔔 +🔕 +🎼 +🎵 +🎶 +🎙️ +🎚️ +🎛️ +🎤 +🎧 +📻 +🎷 +🪗 +🎸 +🎹 +🎺 +🎻 +🪕 +🥁 +🪘 +🪇 +🪈 +🪉 +📱 +📲 +☎️ +📞 +📟 +📠 +🔋 +🪫 +🔌 +💻 +🖥️ +🖨️ +⌨️ +🖱️ +🖲️ +💽 +💾 +💿 +📀 +🧮 +🎥 +🎞️ +📽️ +🎬 +📺 +📷 +📸 +📹 +📼 +🔍 +🔎 +🕯️ +💡 +🔦 +🏮 +🪔 +📔 +📕 +📖 +📗 +📘 +📙 +📚 +📓 +📒 +📃 +📜 +📄 +📰 +🗞️ +📑 +🔖 +🏷️ +💰 +🪙 +💴 +💵 +💶 +💷 +💸 +💳 +🧾 +💹 +✉️ +📧 +📨 +📩 +📤 +📥 +📦 +📫 +📪 +📬 +📭 +📮 +🗳️ +✏️ +✒️ +🖋️ +🖊️ +🖌️ +🖍️ +📝 +💼 +📁 +📂 +🗂️ +📅 +📆 +🗒️ +🗓️ +📇 +📈 +📉 +📊 +📋 +📌 +📍 +📎 +🖇️ +📏 +📐 +✂️ +🗃️ +🗄️ +🗑️ +🔒 +🔓 +🔏 +🔐 +🔑 +🗝️ +🔨 +🪓 +⛏️ +⚒️ +🛠️ +🗡️ +⚔️ +💣 +🪃 +🏹 +🛡️ +🪚 +🔧 +🪛 +🔩 +⚙️ +🗜️ +⚖️ +🦯 +🔗 +⛓️‍💥 +⛓️ +🪝 +🧰 +🧲 +🪜 +🪏 +⚗️ +🧪 +🧫 +🧬 +🔬 +🔭 +📡 +💉 +🩸 +💊 +🩹 +🩼 +🩺 +🩻 +🚪 +🛗 +🪞 +🪟 +🛏️ +🛋️ +🪑 +🚽 +🪠 +🚿 +🛁 +🪤 +🪒 +🧴 +🧷 +🧹 +🧺 +🧻 +🪣 +🧼 +🫧 +🪥 +🧽 +🧯 +🛒 +🚬 +⚰️ +🪦 +⚱️ +🧿 +🪬 +🗿 +🪧 +🪪 \ No newline at end of file diff --git a/app/src/main/assets/emoji/PEOPLE_AND_BODY.txt b/app/src/main/assets/emoji/PEOPLE_AND_BODY.txt new file mode 100644 index 000000000..d7ceb5bb8 --- /dev/null +++ b/app/src/main/assets/emoji/PEOPLE_AND_BODY.txt @@ -0,0 +1,386 @@ +👋 👋🏻 👋🏼 👋🏽 👋🏾 👋🏿 +🤚 🤚🏻 🤚🏼 🤚🏽 🤚🏾 🤚🏿 +🖐️ 🖐🏻 🖐🏼 🖐🏽 🖐🏾 🖐🏿 +✋ ✋🏻 ✋🏼 ✋🏽 ✋🏾 ✋🏿 +🖖 🖖🏻 🖖🏼 🖖🏽 🖖🏾 🖖🏿 +🫱 🫱🏻 🫱🏼 🫱🏽 🫱🏾 🫱🏿 +🫲 🫲🏻 🫲🏼 🫲🏽 🫲🏾 🫲🏿 +🫳 🫳🏻 🫳🏼 🫳🏽 🫳🏾 🫳🏿 +🫴 🫴🏻 🫴🏼 🫴🏽 🫴🏾 🫴🏿 +🫷 🫷🏻 🫷🏼 🫷🏽 🫷🏾 🫷🏿 +🫸 🫸🏻 🫸🏼 🫸🏽 🫸🏾 🫸🏿 +👌 👌🏻 👌🏼 👌🏽 👌🏾 👌🏿 +🤌 🤌🏻 🤌🏼 🤌🏽 🤌🏾 🤌🏿 +🤏 🤏🏻 🤏🏼 🤏🏽 🤏🏾 🤏🏿 +✌️ ✌🏻 ✌🏼 ✌🏽 ✌🏾 ✌🏿 +🤞 🤞🏻 🤞🏼 🤞🏽 🤞🏾 🤞🏿 +🫰 🫰🏻 🫰🏼 🫰🏽 🫰🏾 🫰🏿 +🤟 🤟🏻 🤟🏼 🤟🏽 🤟🏾 🤟🏿 +🤘 🤘🏻 🤘🏼 🤘🏽 🤘🏾 🤘🏿 +🤙 🤙🏻 🤙🏼 🤙🏽 🤙🏾 🤙🏿 +👈 👈🏻 👈🏼 👈🏽 👈🏾 👈🏿 +👉 👉🏻 👉🏼 👉🏽 👉🏾 👉🏿 +👆 👆🏻 👆🏼 👆🏽 👆🏾 👆🏿 +🖕 🖕🏻 🖕🏼 🖕🏽 🖕🏾 🖕🏿 +👇 👇🏻 👇🏼 👇🏽 👇🏾 👇🏿 +☝️ ☝🏻 ☝🏼 ☝🏽 ☝🏾 ☝🏿 +🫵 🫵🏻 🫵🏼 🫵🏽 🫵🏾 🫵🏿 +👍 👍🏻 👍🏼 👍🏽 👍🏾 👍🏿 +👎 👎🏻 👎🏼 👎🏽 👎🏾 👎🏿 +✊ ✊🏻 ✊🏼 ✊🏽 ✊🏾 ✊🏿 +👊 👊🏻 👊🏼 👊🏽 👊🏾 👊🏿 +🤛 🤛🏻 🤛🏼 🤛🏽 🤛🏾 🤛🏿 +🤜 🤜🏻 🤜🏼 🤜🏽 🤜🏾 🤜🏿 +👏 👏🏻 👏🏼 👏🏽 👏🏾 👏🏿 +🙌 🙌🏻 🙌🏼 🙌🏽 🙌🏾 🙌🏿 +🫶 🫶🏻 🫶🏼 🫶🏽 🫶🏾 🫶🏿 +👐 👐🏻 👐🏼 👐🏽 👐🏾 👐🏿 +🤲 🤲🏻 🤲🏼 🤲🏽 🤲🏾 🤲🏿 +🤝 🤝🏻 🤝🏼 🤝🏽 🤝🏾 🤝🏿 +🙏 🙏🏻 🙏🏼 🙏🏽 🙏🏾 🙏🏿 +✍️ ✍🏻 ✍🏼 ✍🏽 ✍🏾 ✍🏿 +💅 💅🏻 💅🏼 💅🏽 💅🏾 💅🏿 +🤳 🤳🏻 🤳🏼 🤳🏽 🤳🏾 🤳🏿 +💪 💪🏻 💪🏼 💪🏽 💪🏾 💪🏿 +🦾 +🦿 +🦵 🦵🏻 🦵🏼 🦵🏽 🦵🏾 🦵🏿 +🦶 🦶🏻 🦶🏼 🦶🏽 🦶🏾 🦶🏿 +👂 👂🏻 👂🏼 👂🏽 👂🏾 👂🏿 +🦻 🦻🏻 🦻🏼 🦻🏽 🦻🏾 🦻🏿 +👃 👃🏻 👃🏼 👃🏽 👃🏾 👃🏿 +🧠 +🫀 +🫁 +🦷 +🦴 +👀 +👁️ +👅 +👄 +🫦 +👶 👶🏻 👶🏼 👶🏽 👶🏾 👶🏿 +🧒 🧒🏻 🧒🏼 🧒🏽 🧒🏾 🧒🏿 +👦 👦🏻 👦🏼 👦🏽 👦🏾 👦🏿 +👧 👧🏻 👧🏼 👧🏽 👧🏾 👧🏿 +🧑 🧑🏻 🧑🏼 🧑🏽 🧑🏾 🧑🏿 +👱 👱🏻 👱🏼 👱🏽 👱🏾 👱🏿 +👨 👨🏻 👨🏼 👨🏽 👨🏾 👨🏿 +🧔 🧔🏻 🧔🏼 🧔🏽 🧔🏾 🧔🏿 +🧔‍♂️ 🧔🏻‍♂️ 🧔🏼‍♂️ 🧔🏽‍♂️ 🧔🏾‍♂️ 🧔🏿‍♂️ +🧔‍♀️ 🧔🏻‍♀️ 🧔🏼‍♀️ 🧔🏽‍♀️ 🧔🏾‍♀️ 🧔🏿‍♀️ +👨‍🦰 👨🏻‍🦰 👨🏼‍🦰 👨🏽‍🦰 👨🏾‍🦰 👨🏿‍🦰 +👨‍🦱 👨🏻‍🦱 👨🏼‍🦱 👨🏽‍🦱 👨🏾‍🦱 👨🏿‍🦱 +👨‍🦳 👨🏻‍🦳 👨🏼‍🦳 👨🏽‍🦳 👨🏾‍🦳 👨🏿‍🦳 +👨‍🦲 👨🏻‍🦲 👨🏼‍🦲 👨🏽‍🦲 👨🏾‍🦲 👨🏿‍🦲 +👩 👩🏻 👩🏼 👩🏽 👩🏾 👩🏿 +👩‍🦰 👩🏻‍🦰 👩🏼‍🦰 👩🏽‍🦰 👩🏾‍🦰 👩🏿‍🦰 +🧑‍🦰 🧑🏻‍🦰 🧑🏼‍🦰 🧑🏽‍🦰 🧑🏾‍🦰 🧑🏿‍🦰 +👩‍🦱 👩🏻‍🦱 👩🏼‍🦱 👩🏽‍🦱 👩🏾‍🦱 👩🏿‍🦱 +🧑‍🦱 🧑🏻‍🦱 🧑🏼‍🦱 🧑🏽‍🦱 🧑🏾‍🦱 🧑🏿‍🦱 +👩‍🦳 👩🏻‍🦳 👩🏼‍🦳 👩🏽‍🦳 👩🏾‍🦳 👩🏿‍🦳 +🧑‍🦳 🧑🏻‍🦳 🧑🏼‍🦳 🧑🏽‍🦳 🧑🏾‍🦳 🧑🏿‍🦳 +👩‍🦲 👩🏻‍🦲 👩🏼‍🦲 👩🏽‍🦲 👩🏾‍🦲 👩🏿‍🦲 +🧑‍🦲 🧑🏻‍🦲 🧑🏼‍🦲 🧑🏽‍🦲 🧑🏾‍🦲 🧑🏿‍🦲 +👱‍♀️ 👱🏻‍♀️ 👱🏼‍♀️ 👱🏽‍♀️ 👱🏾‍♀️ 👱🏿‍♀️ +👱‍♂️ 👱🏻‍♂️ 👱🏼‍♂️ 👱🏽‍♂️ 👱🏾‍♂️ 👱🏿‍♂️ +🧓 🧓🏻 🧓🏼 🧓🏽 🧓🏾 🧓🏿 +👴 👴🏻 👴🏼 👴🏽 👴🏾 👴🏿 +👵 👵🏻 👵🏼 👵🏽 👵🏾 👵🏿 +🙍 🙍🏻 🙍🏼 🙍🏽 🙍🏾 🙍🏿 +🙍‍♂️ 🙍🏻‍♂️ 🙍🏼‍♂️ 🙍🏽‍♂️ 🙍🏾‍♂️ 🙍🏿‍♂️ +🙍‍♀️ 🙍🏻‍♀️ 🙍🏼‍♀️ 🙍🏽‍♀️ 🙍🏾‍♀️ 🙍🏿‍♀️ +🙎 🙎🏻 🙎🏼 🙎🏽 🙎🏾 🙎🏿 +🙎‍♂️ 🙎🏻‍♂️ 🙎🏼‍♂️ 🙎🏽‍♂️ 🙎🏾‍♂️ 🙎🏿‍♂️ +🙎‍♀️ 🙎🏻‍♀️ 🙎🏼‍♀️ 🙎🏽‍♀️ 🙎🏾‍♀️ 🙎🏿‍♀️ +🙅 🙅🏻 🙅🏼 🙅🏽 🙅🏾 🙅🏿 +🙅‍♂️ 🙅🏻‍♂️ 🙅🏼‍♂️ 🙅🏽‍♂️ 🙅🏾‍♂️ 🙅🏿‍♂️ +🙅‍♀️ 🙅🏻‍♀️ 🙅🏼‍♀️ 🙅🏽‍♀️ 🙅🏾‍♀️ 🙅🏿‍♀️ +🙆 🙆🏻 🙆🏼 🙆🏽 🙆🏾 🙆🏿 +🙆‍♂️ 🙆🏻‍♂️ 🙆🏼‍♂️ 🙆🏽‍♂️ 🙆🏾‍♂️ 🙆🏿‍♂️ +🙆‍♀️ 🙆🏻‍♀️ 🙆🏼‍♀️ 🙆🏽‍♀️ 🙆🏾‍♀️ 🙆🏿‍♀️ +💁 💁🏻 💁🏼 💁🏽 💁🏾 💁🏿 +💁‍♂️ 💁🏻‍♂️ 💁🏼‍♂️ 💁🏽‍♂️ 💁🏾‍♂️ 💁🏿‍♂️ +💁‍♀️ 💁🏻‍♀️ 💁🏼‍♀️ 💁🏽‍♀️ 💁🏾‍♀️ 💁🏿‍♀️ +🙋 🙋🏻 🙋🏼 🙋🏽 🙋🏾 🙋🏿 +🙋‍♂️ 🙋🏻‍♂️ 🙋🏼‍♂️ 🙋🏽‍♂️ 🙋🏾‍♂️ 🙋🏿‍♂️ +🙋‍♀️ 🙋🏻‍♀️ 🙋🏼‍♀️ 🙋🏽‍♀️ 🙋🏾‍♀️ 🙋🏿‍♀️ +🧏 🧏🏻 🧏🏼 🧏🏽 🧏🏾 🧏🏿 +🧏‍♂️ 🧏🏻‍♂️ 🧏🏼‍♂️ 🧏🏽‍♂️ 🧏🏾‍♂️ 🧏🏿‍♂️ +🧏‍♀️ 🧏🏻‍♀️ 🧏🏼‍♀️ 🧏🏽‍♀️ 🧏🏾‍♀️ 🧏🏿‍♀️ +🙇 🙇🏻 🙇🏼 🙇🏽 🙇🏾 🙇🏿 +🙇‍♂️ 🙇🏻‍♂️ 🙇🏼‍♂️ 🙇🏽‍♂️ 🙇🏾‍♂️ 🙇🏿‍♂️ +🙇‍♀️ 🙇🏻‍♀️ 🙇🏼‍♀️ 🙇🏽‍♀️ 🙇🏾‍♀️ 🙇🏿‍♀️ +🤦 🤦🏻 🤦🏼 🤦🏽 🤦🏾 🤦🏿 +🤦‍♂️ 🤦🏻‍♂️ 🤦🏼‍♂️ 🤦🏽‍♂️ 🤦🏾‍♂️ 🤦🏿‍♂️ +🤦‍♀️ 🤦🏻‍♀️ 🤦🏼‍♀️ 🤦🏽‍♀️ 🤦🏾‍♀️ 🤦🏿‍♀️ +🤷 🤷🏻 🤷🏼 🤷🏽 🤷🏾 🤷🏿 +🤷‍♂️ 🤷🏻‍♂️ 🤷🏼‍♂️ 🤷🏽‍♂️ 🤷🏾‍♂️ 🤷🏿‍♂️ +🤷‍♀️ 🤷🏻‍♀️ 🤷🏼‍♀️ 🤷🏽‍♀️ 🤷🏾‍♀️ 🤷🏿‍♀️ +🧑‍⚕️ 🧑🏻‍⚕️ 🧑🏼‍⚕️ 🧑🏽‍⚕️ 🧑🏾‍⚕️ 🧑🏿‍⚕️ +👨‍⚕️ 👨🏻‍⚕️ 👨🏼‍⚕️ 👨🏽‍⚕️ 👨🏾‍⚕️ 👨🏿‍⚕️ +👩‍⚕️ 👩🏻‍⚕️ 👩🏼‍⚕️ 👩🏽‍⚕️ 👩🏾‍⚕️ 👩🏿‍⚕️ +🧑‍🎓 🧑🏻‍🎓 🧑🏼‍🎓 🧑🏽‍🎓 🧑🏾‍🎓 🧑🏿‍🎓 +👨‍🎓 👨🏻‍🎓 👨🏼‍🎓 👨🏽‍🎓 👨🏾‍🎓 👨🏿‍🎓 +👩‍🎓 👩🏻‍🎓 👩🏼‍🎓 👩🏽‍🎓 👩🏾‍🎓 👩🏿‍🎓 +🧑‍🏫 🧑🏻‍🏫 🧑🏼‍🏫 🧑🏽‍🏫 🧑🏾‍🏫 🧑🏿‍🏫 +👨‍🏫 👨🏻‍🏫 👨🏼‍🏫 👨🏽‍🏫 👨🏾‍🏫 👨🏿‍🏫 +👩‍🏫 👩🏻‍🏫 👩🏼‍🏫 👩🏽‍🏫 👩🏾‍🏫 👩🏿‍🏫 +🧑‍⚖️ 🧑🏻‍⚖️ 🧑🏼‍⚖️ 🧑🏽‍⚖️ 🧑🏾‍⚖️ 🧑🏿‍⚖️ +👨‍⚖️ 👨🏻‍⚖️ 👨🏼‍⚖️ 👨🏽‍⚖️ 👨🏾‍⚖️ 👨🏿‍⚖️ +👩‍⚖️ 👩🏻‍⚖️ 👩🏼‍⚖️ 👩🏽‍⚖️ 👩🏾‍⚖️ 👩🏿‍⚖️ +🧑‍🌾 🧑🏻‍🌾 🧑🏼‍🌾 🧑🏽‍🌾 🧑🏾‍🌾 🧑🏿‍🌾 +👨‍🌾 👨🏻‍🌾 👨🏼‍🌾 👨🏽‍🌾 👨🏾‍🌾 👨🏿‍🌾 +👩‍🌾 👩🏻‍🌾 👩🏼‍🌾 👩🏽‍🌾 👩🏾‍🌾 👩🏿‍🌾 +🧑‍🍳 🧑🏻‍🍳 🧑🏼‍🍳 🧑🏽‍🍳 🧑🏾‍🍳 🧑🏿‍🍳 +👨‍🍳 👨🏻‍🍳 👨🏼‍🍳 👨🏽‍🍳 👨🏾‍🍳 👨🏿‍🍳 +👩‍🍳 👩🏻‍🍳 👩🏼‍🍳 👩🏽‍🍳 👩🏾‍🍳 👩🏿‍🍳 +🧑‍🔧 🧑🏻‍🔧 🧑🏼‍🔧 🧑🏽‍🔧 🧑🏾‍🔧 🧑🏿‍🔧 +👨‍🔧 👨🏻‍🔧 👨🏼‍🔧 👨🏽‍🔧 👨🏾‍🔧 👨🏿‍🔧 +👩‍🔧 👩🏻‍🔧 👩🏼‍🔧 👩🏽‍🔧 👩🏾‍🔧 👩🏿‍🔧 +🧑‍🏭 🧑🏻‍🏭 🧑🏼‍🏭 🧑🏽‍🏭 🧑🏾‍🏭 🧑🏿‍🏭 +👨‍🏭 👨🏻‍🏭 👨🏼‍🏭 👨🏽‍🏭 👨🏾‍🏭 👨🏿‍🏭 +👩‍🏭 👩🏻‍🏭 👩🏼‍🏭 👩🏽‍🏭 👩🏾‍🏭 👩🏿‍🏭 +🧑‍💼 🧑🏻‍💼 🧑🏼‍💼 🧑🏽‍💼 🧑🏾‍💼 🧑🏿‍💼 +👨‍💼 👨🏻‍💼 👨🏼‍💼 👨🏽‍💼 👨🏾‍💼 👨🏿‍💼 +👩‍💼 👩🏻‍💼 👩🏼‍💼 👩🏽‍💼 👩🏾‍💼 👩🏿‍💼 +🧑‍🔬 🧑🏻‍🔬 🧑🏼‍🔬 🧑🏽‍🔬 🧑🏾‍🔬 🧑🏿‍🔬 +👨‍🔬 👨🏻‍🔬 👨🏼‍🔬 👨🏽‍🔬 👨🏾‍🔬 👨🏿‍🔬 +👩‍🔬 👩🏻‍🔬 👩🏼‍🔬 👩🏽‍🔬 👩🏾‍🔬 👩🏿‍🔬 +🧑‍💻 🧑🏻‍💻 🧑🏼‍💻 🧑🏽‍💻 🧑🏾‍💻 🧑🏿‍💻 +👨‍💻 👨🏻‍💻 👨🏼‍💻 👨🏽‍💻 👨🏾‍💻 👨🏿‍💻 +👩‍💻 👩🏻‍💻 👩🏼‍💻 👩🏽‍💻 👩🏾‍💻 👩🏿‍💻 +🧑‍🎤 🧑🏻‍🎤 🧑🏼‍🎤 🧑🏽‍🎤 🧑🏾‍🎤 🧑🏿‍🎤 +👨‍🎤 👨🏻‍🎤 👨🏼‍🎤 👨🏽‍🎤 👨🏾‍🎤 👨🏿‍🎤 +👩‍🎤 👩🏻‍🎤 👩🏼‍🎤 👩🏽‍🎤 👩🏾‍🎤 👩🏿‍🎤 +🧑‍🎨 🧑🏻‍🎨 🧑🏼‍🎨 🧑🏽‍🎨 🧑🏾‍🎨 🧑🏿‍🎨 +👨‍🎨 👨🏻‍🎨 👨🏼‍🎨 👨🏽‍🎨 👨🏾‍🎨 👨🏿‍🎨 +👩‍🎨 👩🏻‍🎨 👩🏼‍🎨 👩🏽‍🎨 👩🏾‍🎨 👩🏿‍🎨 +🧑‍✈️ 🧑🏻‍✈️ 🧑🏼‍✈️ 🧑🏽‍✈️ 🧑🏾‍✈️ 🧑🏿‍✈️ +👨‍✈️ 👨🏻‍✈️ 👨🏼‍✈️ 👨🏽‍✈️ 👨🏾‍✈️ 👨🏿‍✈️ +👩‍✈️ 👩🏻‍✈️ 👩🏼‍✈️ 👩🏽‍✈️ 👩🏾‍✈️ 👩🏿‍✈️ +🧑‍🚀 🧑🏻‍🚀 🧑🏼‍🚀 🧑🏽‍🚀 🧑🏾‍🚀 🧑🏿‍🚀 +👨‍🚀 👨🏻‍🚀 👨🏼‍🚀 👨🏽‍🚀 👨🏾‍🚀 👨🏿‍🚀 +👩‍🚀 👩🏻‍🚀 👩🏼‍🚀 👩🏽‍🚀 👩🏾‍🚀 👩🏿‍🚀 +🧑‍🚒 🧑🏻‍🚒 🧑🏼‍🚒 🧑🏽‍🚒 🧑🏾‍🚒 🧑🏿‍🚒 +👨‍🚒 👨🏻‍🚒 👨🏼‍🚒 👨🏽‍🚒 👨🏾‍🚒 👨🏿‍🚒 +👩‍🚒 👩🏻‍🚒 👩🏼‍🚒 👩🏽‍🚒 👩🏾‍🚒 👩🏿‍🚒 +👮 👮🏻 👮🏼 👮🏽 👮🏾 👮🏿 +👮‍♂️ 👮🏻‍♂️ 👮🏼‍♂️ 👮🏽‍♂️ 👮🏾‍♂️ 👮🏿‍♂️ +👮‍♀️ 👮🏻‍♀️ 👮🏼‍♀️ 👮🏽‍♀️ 👮🏾‍♀️ 👮🏿‍♀️ +🕵️ 🕵🏻 🕵🏼 🕵🏽 🕵🏾 🕵🏿 +🕵️‍♂️ 🕵🏻‍♂️ 🕵🏼‍♂️ 🕵🏽‍♂️ 🕵🏾‍♂️ 🕵🏿‍♂️ +🕵️‍♀️ 🕵🏻‍♀️ 🕵🏼‍♀️ 🕵🏽‍♀️ 🕵🏾‍♀️ 🕵🏿‍♀️ +💂 💂🏻 💂🏼 💂🏽 💂🏾 💂🏿 +💂‍♂️ 💂🏻‍♂️ 💂🏼‍♂️ 💂🏽‍♂️ 💂🏾‍♂️ 💂🏿‍♂️ +💂‍♀️ 💂🏻‍♀️ 💂🏼‍♀️ 💂🏽‍♀️ 💂🏾‍♀️ 💂🏿‍♀️ +🥷 🥷🏻 🥷🏼 🥷🏽 🥷🏾 🥷🏿 +👷 👷🏻 👷🏼 👷🏽 👷🏾 👷🏿 +👷‍♂️ 👷🏻‍♂️ 👷🏼‍♂️ 👷🏽‍♂️ 👷🏾‍♂️ 👷🏿‍♂️ +👷‍♀️ 👷🏻‍♀️ 👷🏼‍♀️ 👷🏽‍♀️ 👷🏾‍♀️ 👷🏿‍♀️ +🫅 🫅🏻 🫅🏼 🫅🏽 🫅🏾 🫅🏿 +🤴 🤴🏻 🤴🏼 🤴🏽 🤴🏾 🤴🏿 +👸 👸🏻 👸🏼 👸🏽 👸🏾 👸🏿 +👳 👳🏻 👳🏼 👳🏽 👳🏾 👳🏿 +👳‍♂️ 👳🏻‍♂️ 👳🏼‍♂️ 👳🏽‍♂️ 👳🏾‍♂️ 👳🏿‍♂️ +👳‍♀️ 👳🏻‍♀️ 👳🏼‍♀️ 👳🏽‍♀️ 👳🏾‍♀️ 👳🏿‍♀️ +👲 👲🏻 👲🏼 👲🏽 👲🏾 👲🏿 +🧕 🧕🏻 🧕🏼 🧕🏽 🧕🏾 🧕🏿 +🤵 🤵🏻 🤵🏼 🤵🏽 🤵🏾 🤵🏿 +🤵‍♂️ 🤵🏻‍♂️ 🤵🏼‍♂️ 🤵🏽‍♂️ 🤵🏾‍♂️ 🤵🏿‍♂️ +🤵‍♀️ 🤵🏻‍♀️ 🤵🏼‍♀️ 🤵🏽‍♀️ 🤵🏾‍♀️ 🤵🏿‍♀️ +👰 👰🏻 👰🏼 👰🏽 👰🏾 👰🏿 +👰‍♂️ 👰🏻‍♂️ 👰🏼‍♂️ 👰🏽‍♂️ 👰🏾‍♂️ 👰🏿‍♂️ +👰‍♀️ 👰🏻‍♀️ 👰🏼‍♀️ 👰🏽‍♀️ 👰🏾‍♀️ 👰🏿‍♀️ +🤰 🤰🏻 🤰🏼 🤰🏽 🤰🏾 🤰🏿 +🫃 🫃🏻 🫃🏼 🫃🏽 🫃🏾 🫃🏿 +🫄 🫄🏻 🫄🏼 🫄🏽 🫄🏾 🫄🏿 +🤱 🤱🏻 🤱🏼 🤱🏽 🤱🏾 🤱🏿 +👩‍🍼 👩🏻‍🍼 👩🏼‍🍼 👩🏽‍🍼 👩🏾‍🍼 👩🏿‍🍼 +👨‍🍼 👨🏻‍🍼 👨🏼‍🍼 👨🏽‍🍼 👨🏾‍🍼 👨🏿‍🍼 +🧑‍🍼 🧑🏻‍🍼 🧑🏼‍🍼 🧑🏽‍🍼 🧑🏾‍🍼 🧑🏿‍🍼 +👼 👼🏻 👼🏼 👼🏽 👼🏾 👼🏿 +🎅 🎅🏻 🎅🏼 🎅🏽 🎅🏾 🎅🏿 +🤶 🤶🏻 🤶🏼 🤶🏽 🤶🏾 🤶🏿 +🧑‍🎄 🧑🏻‍🎄 🧑🏼‍🎄 🧑🏽‍🎄 🧑🏾‍🎄 🧑🏿‍🎄 +🦸 🦸🏻 🦸🏼 🦸🏽 🦸🏾 🦸🏿 +🦸‍♂️ 🦸🏻‍♂️ 🦸🏼‍♂️ 🦸🏽‍♂️ 🦸🏾‍♂️ 🦸🏿‍♂️ +🦸‍♀️ 🦸🏻‍♀️ 🦸🏼‍♀️ 🦸🏽‍♀️ 🦸🏾‍♀️ 🦸🏿‍♀️ +🦹 🦹🏻 🦹🏼 🦹🏽 🦹🏾 🦹🏿 +🦹‍♂️ 🦹🏻‍♂️ 🦹🏼‍♂️ 🦹🏽‍♂️ 🦹🏾‍♂️ 🦹🏿‍♂️ +🦹‍♀️ 🦹🏻‍♀️ 🦹🏼‍♀️ 🦹🏽‍♀️ 🦹🏾‍♀️ 🦹🏿‍♀️ +🧙 🧙🏻 🧙🏼 🧙🏽 🧙🏾 🧙🏿 +🧙‍♂️ 🧙🏻‍♂️ 🧙🏼‍♂️ 🧙🏽‍♂️ 🧙🏾‍♂️ 🧙🏿‍♂️ +🧙‍♀️ 🧙🏻‍♀️ 🧙🏼‍♀️ 🧙🏽‍♀️ 🧙🏾‍♀️ 🧙🏿‍♀️ +🧚 🧚🏻 🧚🏼 🧚🏽 🧚🏾 🧚🏿 +🧚‍♂️ 🧚🏻‍♂️ 🧚🏼‍♂️ 🧚🏽‍♂️ 🧚🏾‍♂️ 🧚🏿‍♂️ +🧚‍♀️ 🧚🏻‍♀️ 🧚🏼‍♀️ 🧚🏽‍♀️ 🧚🏾‍♀️ 🧚🏿‍♀️ +🧛 🧛🏻 🧛🏼 🧛🏽 🧛🏾 🧛🏿 +🧛‍♂️ 🧛🏻‍♂️ 🧛🏼‍♂️ 🧛🏽‍♂️ 🧛🏾‍♂️ 🧛🏿‍♂️ +🧛‍♀️ 🧛🏻‍♀️ 🧛🏼‍♀️ 🧛🏽‍♀️ 🧛🏾‍♀️ 🧛🏿‍♀️ +🧜 🧜🏻 🧜🏼 🧜🏽 🧜🏾 🧜🏿 +🧜‍♂️ 🧜🏻‍♂️ 🧜🏼‍♂️ 🧜🏽‍♂️ 🧜🏾‍♂️ 🧜🏿‍♂️ +🧜‍♀️ 🧜🏻‍♀️ 🧜🏼‍♀️ 🧜🏽‍♀️ 🧜🏾‍♀️ 🧜🏿‍♀️ +🧝 🧝🏻 🧝🏼 🧝🏽 🧝🏾 🧝🏿 +🧝‍♂️ 🧝🏻‍♂️ 🧝🏼‍♂️ 🧝🏽‍♂️ 🧝🏾‍♂️ 🧝🏿‍♂️ +🧝‍♀️ 🧝🏻‍♀️ 🧝🏼‍♀️ 🧝🏽‍♀️ 🧝🏾‍♀️ 🧝🏿‍♀️ +🧞 +🧞‍♂️ +🧞‍♀️ +🧟 +🧟‍♂️ +🧟‍♀️ +🧌 +💆 💆🏻 💆🏼 💆🏽 💆🏾 💆🏿 +💆‍♂️ 💆🏻‍♂️ 💆🏼‍♂️ 💆🏽‍♂️ 💆🏾‍♂️ 💆🏿‍♂️ +💆‍♀️ 💆🏻‍♀️ 💆🏼‍♀️ 💆🏽‍♀️ 💆🏾‍♀️ 💆🏿‍♀️ +💇 💇🏻 💇🏼 💇🏽 💇🏾 💇🏿 +💇‍♂️ 💇🏻‍♂️ 💇🏼‍♂️ 💇🏽‍♂️ 💇🏾‍♂️ 💇🏿‍♂️ +💇‍♀️ 💇🏻‍♀️ 💇🏼‍♀️ 💇🏽‍♀️ 💇🏾‍♀️ 💇🏿‍♀️ +🚶 🚶🏻 🚶🏼 🚶🏽 🚶🏾 🚶🏿 +🚶‍♂️ 🚶🏻‍♂️ 🚶🏼‍♂️ 🚶🏽‍♂️ 🚶🏾‍♂️ 🚶🏿‍♂️ +🚶‍♀️ 🚶🏻‍♀️ 🚶🏼‍♀️ 🚶🏽‍♀️ 🚶🏾‍♀️ 🚶🏿‍♀️ +🚶‍➡️ 🚶🏻‍➡️ 🚶🏼‍➡️ 🚶🏽‍➡️ 🚶🏾‍➡️ 🚶🏿‍➡️ +🚶‍♀️‍➡️ 🚶🏻‍♀️‍➡️ 🚶🏼‍♀️‍➡️ 🚶🏽‍♀️‍➡️ 🚶🏾‍♀️‍➡️ 🚶🏿‍♀️‍➡️ +🚶‍♂️‍➡️ 🚶🏻‍♂️‍➡️ 🚶🏼‍♂️‍➡️ 🚶🏽‍♂️‍➡️ 🚶🏾‍♂️‍➡️ 🚶🏿‍♂️‍➡️ +🧍 🧍🏻 🧍🏼 🧍🏽 🧍🏾 🧍🏿 +🧍‍♂️ 🧍🏻‍♂️ 🧍🏼‍♂️ 🧍🏽‍♂️ 🧍🏾‍♂️ 🧍🏿‍♂️ +🧍‍♀️ 🧍🏻‍♀️ 🧍🏼‍♀️ 🧍🏽‍♀️ 🧍🏾‍♀️ 🧍🏿‍♀️ +🧎 🧎🏻 🧎🏼 🧎🏽 🧎🏾 🧎🏿 +🧎‍♂️ 🧎🏻‍♂️ 🧎🏼‍♂️ 🧎🏽‍♂️ 🧎🏾‍♂️ 🧎🏿‍♂️ +🧎‍♀️ 🧎🏻‍♀️ 🧎🏼‍♀️ 🧎🏽‍♀️ 🧎🏾‍♀️ 🧎🏿‍♀️ +🧎‍➡️ 🧎🏻‍➡️ 🧎🏼‍➡️ 🧎🏽‍➡️ 🧎🏾‍➡️ 🧎🏿‍➡️ +🧎‍♀️‍➡️ 🧎🏻‍♀️‍➡️ 🧎🏼‍♀️‍➡️ 🧎🏽‍♀️‍➡️ 🧎🏾‍♀️‍➡️ 🧎🏿‍♀️‍➡️ +🧎‍♂️‍➡️ 🧎🏻‍♂️‍➡️ 🧎🏼‍♂️‍➡️ 🧎🏽‍♂️‍➡️ 🧎🏾‍♂️‍➡️ 🧎🏿‍♂️‍➡️ +🧑‍🦯 🧑🏻‍🦯 🧑🏼‍🦯 🧑🏽‍🦯 🧑🏾‍🦯 🧑🏿‍🦯 +🧑‍🦯‍➡️ 🧑🏻‍🦯‍➡️ 🧑🏼‍🦯‍➡️ 🧑🏽‍🦯‍➡️ 🧑🏾‍🦯‍➡️ 🧑🏿‍🦯‍➡️ +👨‍🦯 👨🏻‍🦯 👨🏼‍🦯 👨🏽‍🦯 👨🏾‍🦯 👨🏿‍🦯 +👨‍🦯‍➡️ 👨🏻‍🦯‍➡️ 👨🏼‍🦯‍➡️ 👨🏽‍🦯‍➡️ 👨🏾‍🦯‍➡️ 👨🏿‍🦯‍➡️ +👩‍🦯 👩🏻‍🦯 👩🏼‍🦯 👩🏽‍🦯 👩🏾‍🦯 👩🏿‍🦯 +👩‍🦯‍➡️ 👩🏻‍🦯‍➡️ 👩🏼‍🦯‍➡️ 👩🏽‍🦯‍➡️ 👩🏾‍🦯‍➡️ 👩🏿‍🦯‍➡️ +🧑‍🦼 🧑🏻‍🦼 🧑🏼‍🦼 🧑🏽‍🦼 🧑🏾‍🦼 🧑🏿‍🦼 +🧑‍🦼‍➡️ 🧑🏻‍🦼‍➡️ 🧑🏼‍🦼‍➡️ 🧑🏽‍🦼‍➡️ 🧑🏾‍🦼‍➡️ 🧑🏿‍🦼‍➡️ +👨‍🦼 👨🏻‍🦼 👨🏼‍🦼 👨🏽‍🦼 👨🏾‍🦼 👨🏿‍🦼 +👨‍🦼‍➡️ 👨🏻‍🦼‍➡️ 👨🏼‍🦼‍➡️ 👨🏽‍🦼‍➡️ 👨🏾‍🦼‍➡️ 👨🏿‍🦼‍➡️ +👩‍🦼 👩🏻‍🦼 👩🏼‍🦼 👩🏽‍🦼 👩🏾‍🦼 👩🏿‍🦼 +👩‍🦼‍➡️ 👩🏻‍🦼‍➡️ 👩🏼‍🦼‍➡️ 👩🏽‍🦼‍➡️ 👩🏾‍🦼‍➡️ 👩🏿‍🦼‍➡️ +🧑‍🦽 🧑🏻‍🦽 🧑🏼‍🦽 🧑🏽‍🦽 🧑🏾‍🦽 🧑🏿‍🦽 +🧑‍🦽‍➡️ 🧑🏻‍🦽‍➡️ 🧑🏼‍🦽‍➡️ 🧑🏽‍🦽‍➡️ 🧑🏾‍🦽‍➡️ 🧑🏿‍🦽‍➡️ +👨‍🦽 👨🏻‍🦽 👨🏼‍🦽 👨🏽‍🦽 👨🏾‍🦽 👨🏿‍🦽 +👨‍🦽‍➡️ 👨🏻‍🦽‍➡️ 👨🏼‍🦽‍➡️ 👨🏽‍🦽‍➡️ 👨🏾‍🦽‍➡️ 👨🏿‍🦽‍➡️ +👩‍🦽 👩🏻‍🦽 👩🏼‍🦽 👩🏽‍🦽 👩🏾‍🦽 👩🏿‍🦽 +👩‍🦽‍➡️ 👩🏻‍🦽‍➡️ 👩🏼‍🦽‍➡️ 👩🏽‍🦽‍➡️ 👩🏾‍🦽‍➡️ 👩🏿‍🦽‍➡️ +🏃 🏃🏻 🏃🏼 🏃🏽 🏃🏾 🏃🏿 +🏃‍♂️ 🏃🏻‍♂️ 🏃🏼‍♂️ 🏃🏽‍♂️ 🏃🏾‍♂️ 🏃🏿‍♂️ +🏃‍♀️ 🏃🏻‍♀️ 🏃🏼‍♀️ 🏃🏽‍♀️ 🏃🏾‍♀️ 🏃🏿‍♀️ +🏃‍➡️ 🏃🏻‍➡️ 🏃🏼‍➡️ 🏃🏽‍➡️ 🏃🏾‍➡️ 🏃🏿‍➡️ +🏃‍♀️‍➡️ 🏃🏻‍♀️‍➡️ 🏃🏼‍♀️‍➡️ 🏃🏽‍♀️‍➡️ 🏃🏾‍♀️‍➡️ 🏃🏿‍♀️‍➡️ +🏃‍♂️‍➡️ 🏃🏻‍♂️‍➡️ 🏃🏼‍♂️‍➡️ 🏃🏽‍♂️‍➡️ 🏃🏾‍♂️‍➡️ 🏃🏿‍♂️‍➡️ +💃 💃🏻 💃🏼 💃🏽 💃🏾 💃🏿 +🕺 🕺🏻 🕺🏼 🕺🏽 🕺🏾 🕺🏿 +🕴️ 🕴🏻 🕴🏼 🕴🏽 🕴🏾 🕴🏿 +👯 +👯‍♂️ +👯‍♀️ +🧖 🧖🏻 🧖🏼 🧖🏽 🧖🏾 🧖🏿 +🧖‍♂️ 🧖🏻‍♂️ 🧖🏼‍♂️ 🧖🏽‍♂️ 🧖🏾‍♂️ 🧖🏿‍♂️ +🧖‍♀️ 🧖🏻‍♀️ 🧖🏼‍♀️ 🧖🏽‍♀️ 🧖🏾‍♀️ 🧖🏿‍♀️ +🧗 🧗🏻 🧗🏼 🧗🏽 🧗🏾 🧗🏿 +🧗‍♂️ 🧗🏻‍♂️ 🧗🏼‍♂️ 🧗🏽‍♂️ 🧗🏾‍♂️ 🧗🏿‍♂️ +🧗‍♀️ 🧗🏻‍♀️ 🧗🏼‍♀️ 🧗🏽‍♀️ 🧗🏾‍♀️ 🧗🏿‍♀️ +🤺 +🏇 🏇🏻 🏇🏼 🏇🏽 🏇🏾 🏇🏿 +⛷️ +🏂 🏂🏻 🏂🏼 🏂🏽 🏂🏾 🏂🏿 +🏌️ 🏌🏻 🏌🏼 🏌🏽 🏌🏾 🏌🏿 +🏌️‍♂️ 🏌🏻‍♂️ 🏌🏼‍♂️ 🏌🏽‍♂️ 🏌🏾‍♂️ 🏌🏿‍♂️ +🏌️‍♀️ 🏌🏻‍♀️ 🏌🏼‍♀️ 🏌🏽‍♀️ 🏌🏾‍♀️ 🏌🏿‍♀️ +🏄 🏄🏻 🏄🏼 🏄🏽 🏄🏾 🏄🏿 +🏄‍♂️ 🏄🏻‍♂️ 🏄🏼‍♂️ 🏄🏽‍♂️ 🏄🏾‍♂️ 🏄🏿‍♂️ +🏄‍♀️ 🏄🏻‍♀️ 🏄🏼‍♀️ 🏄🏽‍♀️ 🏄🏾‍♀️ 🏄🏿‍♀️ +🚣 🚣🏻 🚣🏼 🚣🏽 🚣🏾 🚣🏿 +🚣‍♂️ 🚣🏻‍♂️ 🚣🏼‍♂️ 🚣🏽‍♂️ 🚣🏾‍♂️ 🚣🏿‍♂️ +🚣‍♀️ 🚣🏻‍♀️ 🚣🏼‍♀️ 🚣🏽‍♀️ 🚣🏾‍♀️ 🚣🏿‍♀️ +🏊 🏊🏻 🏊🏼 🏊🏽 🏊🏾 🏊🏿 +🏊‍♂️ 🏊🏻‍♂️ 🏊🏼‍♂️ 🏊🏽‍♂️ 🏊🏾‍♂️ 🏊🏿‍♂️ +🏊‍♀️ 🏊🏻‍♀️ 🏊🏼‍♀️ 🏊🏽‍♀️ 🏊🏾‍♀️ 🏊🏿‍♀️ +⛹️ ⛹🏻 ⛹🏼 ⛹🏽 ⛹🏾 ⛹🏿 +⛹️‍♂️ ⛹🏻‍♂️ ⛹🏼‍♂️ ⛹🏽‍♂️ ⛹🏾‍♂️ ⛹🏿‍♂️ +⛹️‍♀️ ⛹🏻‍♀️ ⛹🏼‍♀️ ⛹🏽‍♀️ ⛹🏾‍♀️ ⛹🏿‍♀️ +🏋️ 🏋🏻 🏋🏼 🏋🏽 🏋🏾 🏋🏿 +🏋️‍♂️ 🏋🏻‍♂️ 🏋🏼‍♂️ 🏋🏽‍♂️ 🏋🏾‍♂️ 🏋🏿‍♂️ +🏋️‍♀️ 🏋🏻‍♀️ 🏋🏼‍♀️ 🏋🏽‍♀️ 🏋🏾‍♀️ 🏋🏿‍♀️ +🚴 🚴🏻 🚴🏼 🚴🏽 🚴🏾 🚴🏿 +🚴‍♂️ 🚴🏻‍♂️ 🚴🏼‍♂️ 🚴🏽‍♂️ 🚴🏾‍♂️ 🚴🏿‍♂️ +🚴‍♀️ 🚴🏻‍♀️ 🚴🏼‍♀️ 🚴🏽‍♀️ 🚴🏾‍♀️ 🚴🏿‍♀️ +🚵 🚵🏻 🚵🏼 🚵🏽 🚵🏾 🚵🏿 +🚵‍♂️ 🚵🏻‍♂️ 🚵🏼‍♂️ 🚵🏽‍♂️ 🚵🏾‍♂️ 🚵🏿‍♂️ +🚵‍♀️ 🚵🏻‍♀️ 🚵🏼‍♀️ 🚵🏽‍♀️ 🚵🏾‍♀️ 🚵🏿‍♀️ +🤸 🤸🏻 🤸🏼 🤸🏽 🤸🏾 🤸🏿 +🤸‍♂️ 🤸🏻‍♂️ 🤸🏼‍♂️ 🤸🏽‍♂️ 🤸🏾‍♂️ 🤸🏿‍♂️ +🤸‍♀️ 🤸🏻‍♀️ 🤸🏼‍♀️ 🤸🏽‍♀️ 🤸🏾‍♀️ 🤸🏿‍♀️ +🤼 +🤼‍♂️ +🤼‍♀️ +🤽 🤽🏻 🤽🏼 🤽🏽 🤽🏾 🤽🏿 +🤽‍♂️ 🤽🏻‍♂️ 🤽🏼‍♂️ 🤽🏽‍♂️ 🤽🏾‍♂️ 🤽🏿‍♂️ +🤽‍♀️ 🤽🏻‍♀️ 🤽🏼‍♀️ 🤽🏽‍♀️ 🤽🏾‍♀️ 🤽🏿‍♀️ +🤾 🤾🏻 🤾🏼 🤾🏽 🤾🏾 🤾🏿 +🤾‍♂️ 🤾🏻‍♂️ 🤾🏼‍♂️ 🤾🏽‍♂️ 🤾🏾‍♂️ 🤾🏿‍♂️ +🤾‍♀️ 🤾🏻‍♀️ 🤾🏼‍♀️ 🤾🏽‍♀️ 🤾🏾‍♀️ 🤾🏿‍♀️ +🤹 🤹🏻 🤹🏼 🤹🏽 🤹🏾 🤹🏿 +🤹‍♂️ 🤹🏻‍♂️ 🤹🏼‍♂️ 🤹🏽‍♂️ 🤹🏾‍♂️ 🤹🏿‍♂️ +🤹‍♀️ 🤹🏻‍♀️ 🤹🏼‍♀️ 🤹🏽‍♀️ 🤹🏾‍♀️ 🤹🏿‍♀️ +🧘 🧘🏻 🧘🏼 🧘🏽 🧘🏾 🧘🏿 +🧘‍♂️ 🧘🏻‍♂️ 🧘🏼‍♂️ 🧘🏽‍♂️ 🧘🏾‍♂️ 🧘🏿‍♂️ +🧘‍♀️ 🧘🏻‍♀️ 🧘🏼‍♀️ 🧘🏽‍♀️ 🧘🏾‍♀️ 🧘🏿‍♀️ +🛀 🛀🏻 🛀🏼 🛀🏽 🛀🏾 🛀🏿 +🛌 🛌🏻 🛌🏼 🛌🏽 🛌🏾 🛌🏿 +🧑‍🤝‍🧑 🧑🏻‍🤝‍🧑🏻 🧑🏻‍🤝‍🧑🏼 🧑🏻‍🤝‍🧑🏽 🧑🏻‍🤝‍🧑🏾 🧑🏻‍🤝‍🧑🏿 🧑🏼‍🤝‍🧑🏻 🧑🏼‍🤝‍🧑🏼 🧑🏼‍🤝‍🧑🏽 🧑🏼‍🤝‍🧑🏾 🧑🏼‍🤝‍🧑🏿 🧑🏽‍🤝‍🧑🏻 🧑🏽‍🤝‍🧑🏼 🧑🏽‍🤝‍🧑🏽 🧑🏽‍🤝‍🧑🏾 🧑🏽‍🤝‍🧑🏿 🧑🏾‍🤝‍🧑🏻 🧑🏾‍🤝‍🧑🏼 🧑🏾‍🤝‍🧑🏽 🧑🏾‍🤝‍🧑🏾 🧑🏾‍🤝‍🧑🏿 🧑🏿‍🤝‍🧑🏻 🧑🏿‍🤝‍🧑🏼 🧑🏿‍🤝‍🧑🏽 🧑🏿‍🤝‍🧑🏾 🧑🏿‍🤝‍🧑🏿 +👭 👭🏻 👭🏼 👭🏽 👭🏾 👭🏿 +👫 👫🏻 👫🏼 👫🏽 👫🏾 👫🏿 +👬 👬🏻 👬🏼 👬🏽 👬🏾 👬🏿 +💏 💏🏻 💏🏼 💏🏽 💏🏾 💏🏿 +👩‍❤️‍💋‍👨 👩🏻‍❤️‍💋‍👨🏻 👩🏻‍❤️‍💋‍👨🏼 👩🏻‍❤️‍💋‍👨🏽 👩🏻‍❤️‍💋‍👨🏾 👩🏻‍❤️‍💋‍👨🏿 👩🏼‍❤️‍💋‍👨🏻 👩🏼‍❤️‍💋‍👨🏼 👩🏼‍❤️‍💋‍👨🏽 👩🏼‍❤️‍💋‍👨🏾 👩🏼‍❤️‍💋‍👨🏿 👩🏽‍❤️‍💋‍👨🏻 👩🏽‍❤️‍💋‍👨🏼 👩🏽‍❤️‍💋‍👨🏽 👩🏽‍❤️‍💋‍👨🏾 👩🏽‍❤️‍💋‍👨🏿 👩🏾‍❤️‍💋‍👨🏻 👩🏾‍❤️‍💋‍👨🏼 👩🏾‍❤️‍💋‍👨🏽 👩🏾‍❤️‍💋‍👨🏾 👩🏾‍❤️‍💋‍👨🏿 👩🏿‍❤️‍💋‍👨🏻 👩🏿‍❤️‍💋‍👨🏼 👩🏿‍❤️‍💋‍👨🏽 👩🏿‍❤️‍💋‍👨🏾 👩🏿‍❤️‍💋‍👨🏿 +👨‍❤️‍💋‍👨 👨🏻‍❤️‍💋‍👨🏻 👨🏻‍❤️‍💋‍👨🏼 👨🏻‍❤️‍💋‍👨🏽 👨🏻‍❤️‍💋‍👨🏾 👨🏻‍❤️‍💋‍👨🏿 👨🏼‍❤️‍💋‍👨🏻 👨🏼‍❤️‍💋‍👨🏼 👨🏼‍❤️‍💋‍👨🏽 👨🏼‍❤️‍💋‍👨🏾 👨🏼‍❤️‍💋‍👨🏿 👨🏽‍❤️‍💋‍👨🏻 👨🏽‍❤️‍💋‍👨🏼 👨🏽‍❤️‍💋‍👨🏽 👨🏽‍❤️‍💋‍👨🏾 👨🏽‍❤️‍💋‍👨🏿 👨🏾‍❤️‍💋‍👨🏻 👨🏾‍❤️‍💋‍👨🏼 👨🏾‍❤️‍💋‍👨🏽 👨🏾‍❤️‍💋‍👨🏾 👨🏾‍❤️‍💋‍👨🏿 👨🏿‍❤️‍💋‍👨🏻 👨🏿‍❤️‍💋‍👨🏼 👨🏿‍❤️‍💋‍👨🏽 👨🏿‍❤️‍💋‍👨🏾 👨🏿‍❤️‍💋‍👨🏿 +👩‍❤️‍💋‍👩 👩🏻‍❤️‍💋‍👩🏻 👩🏻‍❤️‍💋‍👩🏼 👩🏻‍❤️‍💋‍👩🏽 👩🏻‍❤️‍💋‍👩🏾 👩🏻‍❤️‍💋‍👩🏿 👩🏼‍❤️‍💋‍👩🏻 👩🏼‍❤️‍💋‍👩🏼 👩🏼‍❤️‍💋‍👩🏽 👩🏼‍❤️‍💋‍👩🏾 👩🏼‍❤️‍💋‍👩🏿 👩🏽‍❤️‍💋‍👩🏻 👩🏽‍❤️‍💋‍👩🏼 👩🏽‍❤️‍💋‍👩🏽 👩🏽‍❤️‍💋‍👩🏾 👩🏽‍❤️‍💋‍👩🏿 👩🏾‍❤️‍💋‍👩🏻 👩🏾‍❤️‍💋‍👩🏼 👩🏾‍❤️‍💋‍👩🏽 👩🏾‍❤️‍💋‍👩🏾 👩🏾‍❤️‍💋‍👩🏿 👩🏿‍❤️‍💋‍👩🏻 👩🏿‍❤️‍💋‍👩🏼 👩🏿‍❤️‍💋‍👩🏽 👩🏿‍❤️‍💋‍👩🏾 👩🏿‍❤️‍💋‍👩🏿 +💑 💑🏻 💑🏼 💑🏽 💑🏾 💑🏿 +👩‍❤️‍👨 👩🏻‍❤️‍👨🏻 👩🏻‍❤️‍👨🏼 👩🏻‍❤️‍👨🏽 👩🏻‍❤️‍👨🏾 👩🏻‍❤️‍👨🏿 👩🏼‍❤️‍👨🏻 👩🏼‍❤️‍👨🏼 👩🏼‍❤️‍👨🏽 👩🏼‍❤️‍👨🏾 👩🏼‍❤️‍👨🏿 👩🏽‍❤️‍👨🏻 👩🏽‍❤️‍👨🏼 👩🏽‍❤️‍👨🏽 👩🏽‍❤️‍👨🏾 👩🏽‍❤️‍👨🏿 👩🏾‍❤️‍👨🏻 👩🏾‍❤️‍👨🏼 👩🏾‍❤️‍👨🏽 👩🏾‍❤️‍👨🏾 👩🏾‍❤️‍👨🏿 👩🏿‍❤️‍👨🏻 👩🏿‍❤️‍👨🏼 👩🏿‍❤️‍👨🏽 👩🏿‍❤️‍👨🏾 👩🏿‍❤️‍👨🏿 +👨‍❤️‍👨 👨🏻‍❤️‍👨🏻 👨🏻‍❤️‍👨🏼 👨🏻‍❤️‍👨🏽 👨🏻‍❤️‍👨🏾 👨🏻‍❤️‍👨🏿 👨🏼‍❤️‍👨🏻 👨🏼‍❤️‍👨🏼 👨🏼‍❤️‍👨🏽 👨🏼‍❤️‍👨🏾 👨🏼‍❤️‍👨🏿 👨🏽‍❤️‍👨🏻 👨🏽‍❤️‍👨🏼 👨🏽‍❤️‍👨🏽 👨🏽‍❤️‍👨🏾 👨🏽‍❤️‍👨🏿 👨🏾‍❤️‍👨🏻 👨🏾‍❤️‍👨🏼 👨🏾‍❤️‍👨🏽 👨🏾‍❤️‍👨🏾 👨🏾‍❤️‍👨🏿 👨🏿‍❤️‍👨🏻 👨🏿‍❤️‍👨🏼 👨🏿‍❤️‍👨🏽 👨🏿‍❤️‍👨🏾 👨🏿‍❤️‍👨🏿 +👩‍❤️‍👩 👩🏻‍❤️‍👩🏻 👩🏻‍❤️‍👩🏼 👩🏻‍❤️‍👩🏽 👩🏻‍❤️‍👩🏾 👩🏻‍❤️‍👩🏿 👩🏼‍❤️‍👩🏻 👩🏼‍❤️‍👩🏼 👩🏼‍❤️‍👩🏽 👩🏼‍❤️‍👩🏾 👩🏼‍❤️‍👩🏿 👩🏽‍❤️‍👩🏻 👩🏽‍❤️‍👩🏼 👩🏽‍❤️‍👩🏽 👩🏽‍❤️‍👩🏾 👩🏽‍❤️‍👩🏿 👩🏾‍❤️‍👩🏻 👩🏾‍❤️‍👩🏼 👩🏾‍❤️‍👩🏽 👩🏾‍❤️‍👩🏾 👩🏾‍❤️‍👩🏿 👩🏿‍❤️‍👩🏻 👩🏿‍❤️‍👩🏼 👩🏿‍❤️‍👩🏽 👩🏿‍❤️‍👩🏾 👩🏿‍❤️‍👩🏿 +👨‍👩‍👦 +👨‍👩‍👧 +👨‍👩‍👧‍👦 +👨‍👩‍👦‍👦 +👨‍👩‍👧‍👧 +👨‍👨‍👦 +👨‍👨‍👧 +👨‍👨‍👧‍👦 +👨‍👨‍👦‍👦 +👨‍👨‍👧‍👧 +👩‍👩‍👦 +👩‍👩‍👧 +👩‍👩‍👧‍👦 +👩‍👩‍👦‍👦 +👩‍👩‍👧‍👧 +👨‍👦 +👨‍👦‍👦 +👨‍👧 +👨‍👧‍👦 +👨‍👧‍👧 +👩‍👦 +👩‍👦‍👦 +👩‍👧 +👩‍👧‍👦 +👩‍👧‍👧 +🗣️ +👤 +👥 +🫂 +👪 +🧑‍🧑‍🧒 +🧑‍🧑‍🧒‍🧒 +🧑‍🧒 +🧑‍🧒‍🧒 +👣 +🫆 \ No newline at end of file diff --git a/app/src/main/assets/emoji/SMILEYS_AND_EMOTION.txt b/app/src/main/assets/emoji/SMILEYS_AND_EMOTION.txt new file mode 100644 index 000000000..73218d6fe --- /dev/null +++ b/app/src/main/assets/emoji/SMILEYS_AND_EMOTION.txt @@ -0,0 +1,169 @@ +😀 +😃 +😄 +😁 +😆 +😅 +🤣 +😂 +🙂 +🙃 +🫠 +😉 +😊 +😇 +🥰 +😍 +🤩 +😘 +😗 +☺️ +😚 +😙 +🥲 +😋 +😛 +😜 +🤪 +😝 +🤑 +🤗 +🤭 +🫢 +🫣 +🤫 +🤔 +🫡 +🤐 +🤨 +😐 +😑 +😶 +🫥 +😶‍🌫️ +😏 +😒 +🙄 +😬 +😮‍💨 +🤥 +🫨 +🙂‍↔️ +🙂‍↕️ +😌 +😔 +😪 +🤤 +😴 +🫩 +😷 +🤒 +🤕 +🤢 +🤮 +🤧 +🥵 +🥶 +🥴 +😵 +😵‍💫 +🤯 +🤠 +🥳 +🥸 +😎 +🤓 +🧐 +😕 +🫤 +😟 +🙁 +☹️ +😮 +😯 +😲 +😳 +🥺 +🥹 +😦 +😧 +😨 +😰 +😥 +😢 +😭 +😱 +😖 +😣 +😞 +😓 +😩 +😫 +🥱 +😤 +😡 +😠 +🤬 +😈 +👿 +💀 +☠️ +💩 +🤡 +👹 +👺 +👻 +👽 +👾 +🤖 +😺 +😸 +😹 +😻 +😼 +😽 +🙀 +😿 +😾 +🙈 +🙉 +🙊 +💌 +💘 +💝 +💖 +💗 +💓 +💞 +💕 +💟 +❣️ +💔 +❤️‍🔥 +❤️‍🩹 +❤️ +🩷 +🧡 +💛 +💚 +💙 +🩵 +💜 +🤎 +🖤 +🩶 +🤍 +💋 +💯 +💢 +💥 +💫 +💦 +💨 +🕳️ +💬 +👁️‍🗨️ +🗨️ +🗯️ +💭 +💤 \ No newline at end of file diff --git a/app/src/main/assets/emoji/SYMBOLS.txt b/app/src/main/assets/emoji/SYMBOLS.txt new file mode 100644 index 000000000..f85cc13bb --- /dev/null +++ b/app/src/main/assets/emoji/SYMBOLS.txt @@ -0,0 +1,250 @@ +🏧 +🚮 +🚰 +♿ +🚹 +🚺 +🚻 +🚼 +🚾 +🛂 +🛃 +🛄 +🛅 +⚠️ +🚸 +⛔ +🚫 +🚳 +🚭 +🚯 +🚱 +🚷 +📵 +🔞 +☢️ +☣️ +⬆️ +↗️ +➡️ +↘️ +⬇️ +↙️ +⬅️ +↖️ +↕️ +↔️ +↩️ +↪️ +⤴️ +⤵️ +🔃 +🔄 +🔙 +🔚 +🔛 +🔜 +🔝 +🛐 +⚛️ +🕉️ +✡️ +☸️ +☯️ +✝️ +☦️ +☪️ +☮️ +🕎 +🔯 +🪯 +♈ +♉ +♊ +♋ +♌ +♍ +♎ +♏ +♐ +♑ +♒ +♓ +⛎ +🔀 +🔁 +🔂 +▶️ +⏩ +⏭️ +⏯️ +◀️ +⏪ +⏮️ +🔼 +⏫ +🔽 +⏬ +⏸️ +⏹️ +⏺️ +⏏️ +🎦 +🔅 +🔆 +📶 +🛜 +📳 +📴 +♀️ +♂️ +⚧️ +✖️ +➕ +➖ +➗ +🟰 +♾️ +‼️ +⁉️ +❓ +❔ +❕ +❗ +〰️ +💱 +💲 +⚕️ +♻️ +⚜️ +🔱 +📛 +🔰 +⭕ +✅ +☑️ +✔️ +❌ +❎ +➰ +➿ +〽️ +✳️ +✴️ +❇️ +©️ +®️ +™️ +🫟 +🇦 +🇧 +🇨 +🇩 +🇪 +🇫 +🇬 +🇭 +🇮 +🇯 +🇰 +🇱 +🇲 +🇳 +🇴 +🇵 +🇶 +🇷 +🇸 +🇹 +🇺 +🇻 +🇼 +🇽 +🇾 +🇿 +#️⃣ +*️⃣ +0️⃣ +1️⃣ +2️⃣ +3️⃣ +4️⃣ +5️⃣ +6️⃣ +7️⃣ +8️⃣ +9️⃣ +🔟 +🔠 +🔡 +🔢 +🔣 +🔤 +🅰️ +🆎 +🅱️ +🆑 +🆒 +🆓 +ℹ️ +🆔 +Ⓜ️ +🆕 +🆖 +🅾️ +🆗 +🅿️ +🆘 +🆙 +🆚 +🈁 +🈂️ +🈷️ +🈶 +🈯 +🉐 +🈹 +🈚 +🈲 +🉑 +🈸 +🈴 +🈳 +㊗️ +㊙️ +🈺 +🈵 +🔴 +🟠 +🟡 +🟢 +🔵 +🟣 +🟤 +⚫ +⚪ +🟥 +🟧 +🟨 +🟩 +🟦 +🟪 +🟫 +⬛ +⬜ +◼️ +◻️ +◾ +◽ +▪️ +▫️ +🔶 +🔷 +🔸 +🔹 +🔺 +🔻 +💠 +🔘 +🔳 +🔲 \ No newline at end of file diff --git a/app/src/main/assets/emoji/TRAVEL_AND_PLACES.txt b/app/src/main/assets/emoji/TRAVEL_AND_PLACES.txt new file mode 100644 index 000000000..ff1f0ad4a --- /dev/null +++ b/app/src/main/assets/emoji/TRAVEL_AND_PLACES.txt @@ -0,0 +1,218 @@ +🌍 +🌎 +🌏 +🌐 +🗺️ +🗾 +🧭 +🏔️ +⛰️ +🌋 +🗻 +🏕️ +🏖️ +🏜️ +🏝️ +🏞️ +🏟️ +🏛️ +🏗️ +🧱 +🪨 +🪵 +🛖 +🏘️ +🏚️ +🏠 +🏡 +🏢 +🏣 +🏤 +🏥 +🏦 +🏨 +🏩 +🏪 +🏫 +🏬 +🏭 +🏯 +🏰 +💒 +🗼 +🗽 +⛪ +🕌 +🛕 +🕍 +⛩️ +🕋 +⛲ +⛺ +🌁 +🌃 +🏙️ +🌄 +🌅 +🌆 +🌇 +🌉 +♨️ +🎠 +🛝 +🎡 +🎢 +💈 +🎪 +🚂 +🚃 +🚄 +🚅 +🚆 +🚇 +🚈 +🚉 +🚊 +🚝 +🚞 +🚋 +🚌 +🚍 +🚎 +🚐 +🚑 +🚒 +🚓 +🚔 +🚕 +🚖 +🚗 +🚘 +🚙 +🛻 +🚚 +🚛 +🚜 +🏎️ +🏍️ +🛵 +🦽 +🦼 +🛺 +🚲 +🛴 +🛹 +🛼 +🚏 +🛣️ +🛤️ +🛢️ +⛽ +🛞 +🚨 +🚥 +🚦 +🛑 +🚧 +⚓ +🛟 +⛵ +🛶 +🚤 +🛳️ +⛴️ +🛥️ +🚢 +✈️ +🛩️ +🛫 +🛬 +🪂 +💺 +🚁 +🚟 +🚠 +🚡 +🛰️ +🚀 +🛸 +🛎️ +🧳 +⌛ +⏳ +⌚ +⏰ +⏱️ +⏲️ +🕰️ +🕛 +🕧 +🕐 +🕜 +🕑 +🕝 +🕒 +🕞 +🕓 +🕟 +🕔 +🕠 +🕕 +🕡 +🕖 +🕢 +🕗 +🕣 +🕘 +🕤 +🕙 +🕥 +🕚 +🕦 +🌑 +🌒 +🌓 +🌔 +🌕 +🌖 +🌗 +🌘 +🌙 +🌚 +🌛 +🌜 +🌡️ +☀️ +🌝 +🌞 +🪐 +⭐ +🌟 +🌠 +🌌 +☁️ +⛅ +⛈️ +🌤️ +🌥️ +🌦️ +🌧️ +🌨️ +🌩️ +🌪️ +🌫️ +🌬️ +🌀 +🌈 +🌂 +☂️ +☔ +⛱️ +⚡ +❄️ +☃️ +⛄ +☄️ +🔥 +💧 +🌊 \ No newline at end of file diff --git a/app/src/main/assets/emoji/minApi.txt b/app/src/main/assets/emoji/minApi.txt new file mode 100644 index 000000000..842da2d6b --- /dev/null +++ b/app/src/main/assets/emoji/minApi.txt @@ -0,0 +1,12 @@ +23 🙂 🙃 🤑 🤗 🤔 🤐 🙄 🤒 🤕 🤓 🙁 ☹️ ☠️ 🤖 ❣️ 🕳️ 👁️‍🗨️ 🗨️ 🗯️ 🖐️ 🖖 🤘 🖕 ✍️ 👁️ 🕵️ 🕴️ ⛷️ 🏌️ ⛹️ 🏋️ 🛌 👨‍❤️‍💋‍👨 👩‍❤️‍💋‍👩 👨‍❤️‍👨 👩‍❤️‍👩 👨‍👩‍👧 👨‍👩‍👧‍👦 👨‍👩‍👦‍👦 👨‍👩‍👧‍👧 👨‍👨‍👦 👨‍👨‍👧 👨‍👨‍👧‍👦 👨‍👨‍👦‍👦 👨‍👨‍👧‍👧 👩‍👩‍👦 👩‍👩‍👧 👩‍👩‍👧‍👦 👩‍👩‍👦‍👦 👩‍👩‍👧‍👧 🗣️ 🦁 🦄 🐿️ 🦃 🕊️ 🦀 🕷️ 🕸️ 🦂 🏵️ ☘️ 🌶️ 🧀 🌭 🌮 🌯 🍿 🍾 🍽️ 🏺 🗺️ 🏔️ ⛰️ 🏕️ 🏖️ 🏜️ 🏝️ 🏞️ 🏟️ 🏛️ 🏗️ 🏘️ 🏚️ 🕌 🕍 ⛩️ 🕋 🏙️ 🏎️ 🏍️ 🛣️ 🛤️ 🛢️ 🛳️ ⛴️ 🛥️ 🛩️ 🛫 🛬 🛰️ 🛎️ ⏱️ ⏲️ 🕰️ 🌡️ ⛈️ 🌤️ 🌥️ 🌦️ 🌧️ 🌨️ 🌩️ 🌪️ 🌫️ 🌬️ ☂️ ⛱️ ☃️ ☄️ 🎗️ 🎟️ 🎖️ 🏅 🏐 🏏 🏑 🏒 🏓 🏸 ⛸️ 🕹️ 🖼️ 🕶️ 🛍️ ⛑️ 📿 🎙️ 🎚️ 🎛️ 🖥️ 🖨️ ⌨️ 🖱️ 🖲️ 🎞️ 📽️ 📸 🕯️ 🗞️ 🏷️ 🗳️ 🖋️ 🖊️ 🖌️ 🖍️ 🗂️ 🗒️ 🗓️ 🖇️ 🗃️ 🗄️ 🗑️ 🗝️ ⛏️ ⚒️ 🛠️ 🗡️ ⚔️ 🏹 🛡️ ⚙️ 🗜️ ⚖️ ⛓️ ⚗️ 🛏️ 🛋️ ⚰️ ⚱️ ☢️ ☣️ 🛐 ⚛️ 🕉️ ✡️ ☸️ ☯️ ✝️ ☦️ ☪️ ☮️ 🕎 ⏭️ ⏯️ ⏮️ ⏸️ ⏹️ ⏺️ ⏏️ ⚜️ *️⃣ 🏴 🏳️ +24 🤣 🤥 🤤 🤢 🤧 🤠 🤡 🖤 👋🏻 👋🏼 👋🏽 👋🏾 👋🏿 🤚 🤚🏻 🤚🏼 🤚🏽 🤚🏾 🤚🏿 🖐🏻 🖐🏼 🖐🏽 🖐🏾 🖐🏿 ✋🏻 ✋🏼 ✋🏽 ✋🏾 ✋🏿 🖖🏻 🖖🏼 🖖🏽 🖖🏾 🖖🏿 👌🏻 👌🏼 👌🏽 👌🏾 👌🏿 ✌🏻 ✌🏼 ✌🏽 ✌🏾 ✌🏿 🤞 🤞🏻 🤞🏼 🤞🏽 🤞🏾 🤞🏿 🤘🏻 🤘🏼 🤘🏽 🤘🏾 🤘🏿 🤙 🤙🏻 🤙🏼 🤙🏽 🤙🏾 🤙🏿 👈🏻 👈🏼 👈🏽 👈🏾 👈🏿 👉🏻 👉🏼 👉🏽 👉🏾 👉🏿 👆🏻 👆🏼 👆🏽 👆🏾 👆🏿 🖕🏻 🖕🏼 🖕🏽 🖕🏾 🖕🏿 👇🏻 👇🏼 👇🏽 👇🏾 👇🏿 ☝🏻 ☝🏼 ☝🏽 ☝🏾 ☝🏿 👍🏻 👍🏼 👍🏽 👍🏾 👍🏿 👎🏻 👎🏼 👎🏽 👎🏾 👎🏿 ✊🏻 ✊🏼 ✊🏽 ✊🏾 ✊🏿 👊🏻 👊🏼 👊🏽 👊🏾 👊🏿 🤛 🤛🏻 🤛🏼 🤛🏽 🤛🏾 🤛🏿 🤜 🤜🏻 🤜🏼 🤜🏽 🤜🏾 🤜🏿 👏🏻 👏🏼 👏🏽 👏🏾 👏🏿 🙌🏻 🙌🏼 🙌🏽 🙌🏾 🙌🏿 👐🏻 👐🏼 👐🏽 👐🏾 👐🏿 🤝 🙏🏻 🙏🏼 🙏🏽 🙏🏾 🙏🏿 ✍🏻 ✍🏼 ✍🏽 ✍🏾 ✍🏿 💅🏻 💅🏼 💅🏽 💅🏾 💅🏿 🤳 🤳🏻 🤳🏼 🤳🏽 🤳🏾 🤳🏿 💪🏻 💪🏼 💪🏽 💪🏾 💪🏿 👂🏻 👂🏼 👂🏽 👂🏾 👂🏿 👃🏻 👃🏼 👃🏽 👃🏾 👃🏿 👶🏻 👶🏼 👶🏽 👶🏾 👶🏿 👦🏻 👦🏼 👦🏽 👦🏾 👦🏿 👧🏻 👧🏼 👧🏽 👧🏾 👧🏿 👱🏻 👱🏼 👱🏽 👱🏾 👱🏿 👨🏻 👨🏼 👨🏽 👨🏾 👨🏿 👩🏻 👩🏼 👩🏽 👩🏾 👩🏿 👴🏻 👴🏼 👴🏽 👴🏾 👴🏿 👵🏻 👵🏼 👵🏽 👵🏾 👵🏿 🙍🏻 🙍🏼 🙍🏽 🙍🏾 🙍🏿 🙎🏻 🙎🏼 🙎🏽 🙎🏾 🙎🏿 🙅🏻 🙅🏼 🙅🏽 🙅🏾 🙅🏿 🙆🏻 🙆🏼 🙆🏽 🙆🏾 🙆🏿 💁🏻 💁🏼 💁🏽 💁🏾 💁🏿 🙋🏻 🙋🏼 🙋🏽 🙋🏾 🙋🏿 🙇🏻 🙇🏼 🙇🏽 🙇🏾 🙇🏿 🤦 🤦🏻 🤦🏼 🤦🏽 🤦🏾 🤦🏿 🤷 🤷🏻 🤷🏼 🤷🏽 🤷🏾 🤷🏿 👮🏻 👮🏼 👮🏽 👮🏾 👮🏿 🕵🏻 🕵🏼 🕵🏽 🕵🏾 🕵🏿 💂🏻 💂🏼 💂🏽 💂🏾 💂🏿 👷🏻 👷🏼 👷🏽 👷🏾 👷🏿 🤴 🤴🏻 🤴🏼 🤴🏽 🤴🏾 🤴🏿 👸🏻 👸🏼 👸🏽 👸🏾 👸🏿 👳🏻 👳🏼 👳🏽 👳🏾 👳🏿 👲🏻 👲🏼 👲🏽 👲🏾 👲🏿 🤵 🤵🏻 🤵🏼 🤵🏽 🤵🏾 🤵🏿 👰🏻 👰🏼 👰🏽 👰🏾 👰🏿 🤰 🤰🏻 🤰🏼 🤰🏽 🤰🏾 🤰🏿 👼🏻 👼🏼 👼🏽 👼🏾 👼🏿 🎅🏻 🎅🏼 🎅🏽 🎅🏾 🎅🏿 🤶 🤶🏻 🤶🏼 🤶🏽 🤶🏾 🤶🏿 💆🏻 💆🏼 💆🏽 💆🏾 💆🏿 💇🏻 💇🏼 💇🏽 💇🏾 💇🏿 🚶🏻 🚶🏼 🚶🏽 🚶🏾 🚶🏿 🏃🏻 🏃🏼 🏃🏽 🏃🏾 🏃🏿 💃🏻 💃🏼 💃🏽 💃🏾 💃🏿 🕺 🕺🏻 🕺🏼 🕺🏽 🕺🏾 🕺🏿 🤺 🏄🏻 🏄🏼 🏄🏽 🏄🏾 🏄🏿 🚣🏻 🚣🏼 🚣🏽 🚣🏾 🚣🏿 🏊🏻 🏊🏼 🏊🏽 🏊🏾 🏊🏿 ⛹🏻 ⛹🏼 ⛹🏽 ⛹🏾 ⛹🏿 🏋🏻 🏋🏼 🏋🏽 🏋🏾 🏋🏿 🚴🏻 🚴🏼 🚴🏽 🚴🏾 🚴🏿 🚵🏻 🚵🏼 🚵🏽 🚵🏾 🚵🏿 🤸 🤸🏻 🤸🏼 🤸🏽 🤸🏾 🤸🏿 🤼 🤽 🤽🏻 🤽🏼 🤽🏽 🤽🏾 🤽🏿 🤾 🤾🏻 🤾🏼 🤾🏽 🤾🏾 🤾🏿 🤹 🤹🏻 🤹🏼 🤹🏽 🤹🏾 🤹🏿 🛀🏻 🛀🏼 🛀🏽 🛀🏾 🛀🏿 🦍 🦊 🦌 🦏 🦇 🦅 🦆 🦉 🦎 🦈 🦐 🦑 🦋 🥀 🥝 🥑 🥔 🥕 🥒 🥜 🥐 🥖 🥞 🥓 🥙 🥚 🥘 🥗 🥛 🥂 🥃 🥄 🛵 🛴 🛑 🛶 🥇 🥈 🥉 🥊 🥋 🥅 🥁 🛒 🇦🇨 🇦🇶 🇧🇻 🇨🇵 🇭🇲 🇮🇨 🇸🇭 🇸🇯 🇹🇦 🇺🇲 +25 🤝🏻 🤝🏼 🤝🏽 🤝🏾 🤝🏿 👱‍♀️ 👱🏻‍♀️ 👱🏼‍♀️ 👱🏽‍♀️ 👱🏾‍♀️ 👱🏿‍♀️ 👱‍♂️ 👱🏻‍♂️ 👱🏼‍♂️ 👱🏽‍♂️ 👱🏾‍♂️ 👱🏿‍♂️ 🙍‍♂️ 🙍🏻‍♂️ 🙍🏼‍♂️ 🙍🏽‍♂️ 🙍🏾‍♂️ 🙍🏿‍♂️ 🙍‍♀️ 🙍🏻‍♀️ 🙍🏼‍♀️ 🙍🏽‍♀️ 🙍🏾‍♀️ 🙍🏿‍♀️ 🙎‍♂️ 🙎🏻‍♂️ 🙎🏼‍♂️ 🙎🏽‍♂️ 🙎🏾‍♂️ 🙎🏿‍♂️ 🙎‍♀️ 🙎🏻‍♀️ 🙎🏼‍♀️ 🙎🏽‍♀️ 🙎🏾‍♀️ 🙎🏿‍♀️ 🙅‍♂️ 🙅🏻‍♂️ 🙅🏼‍♂️ 🙅🏽‍♂️ 🙅🏾‍♂️ 🙅🏿‍♂️ 🙅‍♀️ 🙅🏻‍♀️ 🙅🏼‍♀️ 🙅🏽‍♀️ 🙅🏾‍♀️ 🙅🏿‍♀️ 🙆‍♂️ 🙆🏻‍♂️ 🙆🏼‍♂️ 🙆🏽‍♂️ 🙆🏾‍♂️ 🙆🏿‍♂️ 🙆‍♀️ 🙆🏻‍♀️ 🙆🏼‍♀️ 🙆🏽‍♀️ 🙆🏾‍♀️ 🙆🏿‍♀️ 💁‍♂️ 💁🏻‍♂️ 💁🏼‍♂️ 💁🏽‍♂️ 💁🏾‍♂️ 💁🏿‍♂️ 💁‍♀️ 💁🏻‍♀️ 💁🏼‍♀️ 💁🏽‍♀️ 💁🏾‍♀️ 💁🏿‍♀️ 🙋‍♂️ 🙋🏻‍♂️ 🙋🏼‍♂️ 🙋🏽‍♂️ 🙋🏾‍♂️ 🙋🏿‍♂️ 🙋‍♀️ 🙋🏻‍♀️ 🙋🏼‍♀️ 🙋🏽‍♀️ 🙋🏾‍♀️ 🙋🏿‍♀️ 🙇‍♂️ 🙇🏻‍♂️ 🙇🏼‍♂️ 🙇🏽‍♂️ 🙇🏾‍♂️ 🙇🏿‍♂️ 🙇‍♀️ 🙇🏻‍♀️ 🙇🏼‍♀️ 🙇🏽‍♀️ 🙇🏾‍♀️ 🙇🏿‍♀️ 🤦‍♂️ 🤦🏻‍♂️ 🤦🏼‍♂️ 🤦🏽‍♂️ 🤦🏾‍♂️ 🤦🏿‍♂️ 🤦‍♀️ 🤦🏻‍♀️ 🤦🏼‍♀️ 🤦🏽‍♀️ 🤦🏾‍♀️ 🤦🏿‍♀️ 🤷‍♂️ 🤷🏻‍♂️ 🤷🏼‍♂️ 🤷🏽‍♂️ 🤷🏾‍♂️ 🤷🏿‍♂️ 🤷‍♀️ 🤷🏻‍♀️ 🤷🏼‍♀️ 🤷🏽‍♀️ 🤷🏾‍♀️ 🤷🏿‍♀️ 👨‍⚕️ 👨🏻‍⚕️ 👨🏼‍⚕️ 👨🏽‍⚕️ 👨🏾‍⚕️ 👨🏿‍⚕️ 👩‍⚕️ 👩🏻‍⚕️ 👩🏼‍⚕️ 👩🏽‍⚕️ 👩🏾‍⚕️ 👩🏿‍⚕️ 👨‍🎓 👨🏻‍🎓 👨🏼‍🎓 👨🏽‍🎓 👨🏾‍🎓 👨🏿‍🎓 👩‍🎓 👩🏻‍🎓 👩🏼‍🎓 👩🏽‍🎓 👩🏾‍🎓 👩🏿‍🎓 👨‍🏫 👨🏻‍🏫 👨🏼‍🏫 👨🏽‍🏫 👨🏾‍🏫 👨🏿‍🏫 👩‍🏫 👩🏻‍🏫 👩🏼‍🏫 👩🏽‍🏫 👩🏾‍🏫 👩🏿‍🏫 👨‍⚖️ 👨🏻‍⚖️ 👨🏼‍⚖️ 👨🏽‍⚖️ 👨🏾‍⚖️ 👨🏿‍⚖️ 👩‍⚖️ 👩🏻‍⚖️ 👩🏼‍⚖️ 👩🏽‍⚖️ 👩🏾‍⚖️ 👩🏿‍⚖️ 👨‍🌾 👨🏻‍🌾 👨🏼‍🌾 👨🏽‍🌾 👨🏾‍🌾 👨🏿‍🌾 👩‍🌾 👩🏻‍🌾 👩🏼‍🌾 👩🏽‍🌾 👩🏾‍🌾 👩🏿‍🌾 👨‍🍳 👨🏻‍🍳 👨🏼‍🍳 👨🏽‍🍳 👨🏾‍🍳 👨🏿‍🍳 👩‍🍳 👩🏻‍🍳 👩🏼‍🍳 👩🏽‍🍳 👩🏾‍🍳 👩🏿‍🍳 👨‍🔧 👨🏻‍🔧 👨🏼‍🔧 👨🏽‍🔧 👨🏾‍🔧 👨🏿‍🔧 👩‍🔧 👩🏻‍🔧 👩🏼‍🔧 👩🏽‍🔧 👩🏾‍🔧 👩🏿‍🔧 👨‍🏭 👨🏻‍🏭 👨🏼‍🏭 👨🏽‍🏭 👨🏾‍🏭 👨🏿‍🏭 👩‍🏭 👩🏻‍🏭 👩🏼‍🏭 👩🏽‍🏭 👩🏾‍🏭 👩🏿‍🏭 👨‍💼 👨🏻‍💼 👨🏼‍💼 👨🏽‍💼 👨🏾‍💼 👨🏿‍💼 👩‍💼 👩🏻‍💼 👩🏼‍💼 👩🏽‍💼 👩🏾‍💼 👩🏿‍💼 👨‍🔬 👨🏻‍🔬 👨🏼‍🔬 👨🏽‍🔬 👨🏾‍🔬 👨🏿‍🔬 👩‍🔬 👩🏻‍🔬 👩🏼‍🔬 👩🏽‍🔬 👩🏾‍🔬 👩🏿‍🔬 👨‍💻 👨🏻‍💻 👨🏼‍💻 👨🏽‍💻 👨🏾‍💻 👨🏿‍💻 👩‍💻 👩🏻‍💻 👩🏼‍💻 👩🏽‍💻 👩🏾‍💻 👩🏿‍💻 👨‍🎤 👨🏻‍🎤 👨🏼‍🎤 👨🏽‍🎤 👨🏾‍🎤 👨🏿‍🎤 👩‍🎤 👩🏻‍🎤 👩🏼‍🎤 👩🏽‍🎤 👩🏾‍🎤 👩🏿‍🎤 👨‍🎨 👨🏻‍🎨 👨🏼‍🎨 👨🏽‍🎨 👨🏾‍🎨 👨🏿‍🎨 👩‍🎨 👩🏻‍🎨 👩🏼‍🎨 👩🏽‍🎨 👩🏾‍🎨 👩🏿‍🎨 👨‍✈️ 👨🏻‍✈️ 👨🏼‍✈️ 👨🏽‍✈️ 👨🏾‍✈️ 👨🏿‍✈️ 👩‍✈️ 👩🏻‍✈️ 👩🏼‍✈️ 👩🏽‍✈️ 👩🏾‍✈️ 👩🏿‍✈️ 👨‍🚀 👨🏻‍🚀 👨🏼‍🚀 👨🏽‍🚀 👨🏾‍🚀 👨🏿‍🚀 👩‍🚀 👩🏻‍🚀 👩🏼‍🚀 👩🏽‍🚀 👩🏾‍🚀 👩🏿‍🚀 👨‍🚒 👨🏻‍🚒 👨🏼‍🚒 👨🏽‍🚒 👨🏾‍🚒 👨🏿‍🚒 👩‍🚒 👩🏻‍🚒 👩🏼‍🚒 👩🏽‍🚒 👩🏾‍🚒 👩🏿‍🚒 👮‍♂️ 👮🏻‍♂️ 👮🏼‍♂️ 👮🏽‍♂️ 👮🏾‍♂️ 👮🏿‍♂️ 👮‍♀️ 👮🏻‍♀️ 👮🏼‍♀️ 👮🏽‍♀️ 👮🏾‍♀️ 👮🏿‍♀️ 🕵️‍♂️ 🕵🏻‍♂️ 🕵🏼‍♂️ 🕵🏽‍♂️ 🕵🏾‍♂️ 🕵🏿‍♂️ 🕵️‍♀️ 🕵🏻‍♀️ 🕵🏼‍♀️ 🕵🏽‍♀️ 🕵🏾‍♀️ 🕵🏿‍♀️ 💂‍♂️ 💂🏻‍♂️ 💂🏼‍♂️ 💂🏽‍♂️ 💂🏾‍♂️ 💂🏿‍♂️ 💂‍♀️ 💂🏻‍♀️ 💂🏼‍♀️ 💂🏽‍♀️ 💂🏾‍♀️ 💂🏿‍♀️ 👷‍♂️ 👷🏻‍♂️ 👷🏼‍♂️ 👷🏽‍♂️ 👷🏾‍♂️ 👷🏿‍♂️ 👷‍♀️ 👷🏻‍♀️ 👷🏼‍♀️ 👷🏽‍♀️ 👷🏾‍♀️ 👷🏿‍♀️ 👳‍♂️ 👳🏻‍♂️ 👳🏼‍♂️ 👳🏽‍♂️ 👳🏾‍♂️ 👳🏿‍♂️ 👳‍♀️ 👳🏻‍♀️ 👳🏼‍♀️ 👳🏽‍♀️ 👳🏾‍♀️ 👳🏿‍♀️ 💆‍♂️ 💆🏻‍♂️ 💆🏼‍♂️ 💆🏽‍♂️ 💆🏾‍♂️ 💆🏿‍♂️ 💆‍♀️ 💆🏻‍♀️ 💆🏼‍♀️ 💆🏽‍♀️ 💆🏾‍♀️ 💆🏿‍♀️ 💇‍♂️ 💇🏻‍♂️ 💇🏼‍♂️ 💇🏽‍♂️ 💇🏾‍♂️ 💇🏿‍♂️ 💇‍♀️ 💇🏻‍♀️ 💇🏼‍♀️ 💇🏽‍♀️ 💇🏾‍♀️ 💇🏿‍♀️ 🚶‍♂️ 🚶🏻‍♂️ 🚶🏼‍♂️ 🚶🏽‍♂️ 🚶🏾‍♂️ 🚶🏿‍♂️ 🚶‍♀️ 🚶🏻‍♀️ 🚶🏼‍♀️ 🚶🏽‍♀️ 🚶🏾‍♀️ 🚶🏿‍♀️ 🏃‍♂️ 🏃🏻‍♂️ 🏃🏼‍♂️ 🏃🏽‍♂️ 🏃🏾‍♂️ 🏃🏿‍♂️ 🏃‍♀️ 🏃🏻‍♀️ 🏃🏼‍♀️ 🏃🏽‍♀️ 🏃🏾‍♀️ 🏃🏿‍♀️ 👯‍♂️ 👯‍♀️ 🏌️‍♂️ 🏌️‍♀️ 🏄‍♂️ 🏄🏻‍♂️ 🏄🏼‍♂️ 🏄🏽‍♂️ 🏄🏾‍♂️ 🏄🏿‍♂️ 🏄‍♀️ 🏄🏻‍♀️ 🏄🏼‍♀️ 🏄🏽‍♀️ 🏄🏾‍♀️ 🏄🏿‍♀️ 🚣‍♂️ 🚣🏻‍♂️ 🚣🏼‍♂️ 🚣🏽‍♂️ 🚣🏾‍♂️ 🚣🏿‍♂️ 🚣‍♀️ 🚣🏻‍♀️ 🚣🏼‍♀️ 🚣🏽‍♀️ 🚣🏾‍♀️ 🚣🏿‍♀️ 🏊‍♂️ 🏊🏻‍♂️ 🏊🏼‍♂️ 🏊🏽‍♂️ 🏊🏾‍♂️ 🏊🏿‍♂️ 🏊‍♀️ 🏊🏻‍♀️ 🏊🏼‍♀️ 🏊🏽‍♀️ 🏊🏾‍♀️ 🏊🏿‍♀️ ⛹️‍♂️ ⛹🏻‍♂️ ⛹🏼‍♂️ ⛹🏽‍♂️ ⛹🏾‍♂️ ⛹🏿‍♂️ ⛹️‍♀️ ⛹🏻‍♀️ ⛹🏼‍♀️ ⛹🏽‍♀️ ⛹🏾‍♀️ ⛹🏿‍♀️ 🏋️‍♂️ 🏋🏻‍♂️ 🏋🏼‍♂️ 🏋🏽‍♂️ 🏋🏾‍♂️ 🏋🏿‍♂️ 🏋️‍♀️ 🏋🏻‍♀️ 🏋🏼‍♀️ 🏋🏽‍♀️ 🏋🏾‍♀️ 🏋🏿‍♀️ 🚴‍♂️ 🚴🏻‍♂️ 🚴🏼‍♂️ 🚴🏽‍♂️ 🚴🏾‍♂️ 🚴🏿‍♂️ 🚴‍♀️ 🚴🏻‍♀️ 🚴🏼‍♀️ 🚴🏽‍♀️ 🚴🏾‍♀️ 🚴🏿‍♀️ 🚵‍♂️ 🚵🏻‍♂️ 🚵🏼‍♂️ 🚵🏽‍♂️ 🚵🏾‍♂️ 🚵🏿‍♂️ 🚵‍♀️ 🚵🏻‍♀️ 🚵🏼‍♀️ 🚵🏽‍♀️ 🚵🏾‍♀️ 🚵🏿‍♀️ 🤸‍♂️ 🤸🏻‍♂️ 🤸🏼‍♂️ 🤸🏽‍♂️ 🤸🏾‍♂️ 🤸🏿‍♂️ 🤸‍♀️ 🤸🏻‍♀️ 🤸🏼‍♀️ 🤸🏽‍♀️ 🤸🏾‍♀️ 🤸🏿‍♀️ 🤼‍♂️ 🤼‍♀️ 🤽‍♂️ 🤽🏻‍♂️ 🤽🏼‍♂️ 🤽🏽‍♂️ 🤽🏾‍♂️ 🤽🏿‍♂️ 🤽‍♀️ 🤽🏻‍♀️ 🤽🏼‍♀️ 🤽🏽‍♀️ 🤽🏾‍♀️ 🤽🏿‍♀️ 🤾‍♂️ 🤾🏻‍♂️ 🤾🏼‍♂️ 🤾🏽‍♂️ 🤾🏾‍♂️ 🤾🏿‍♂️ 🤾‍♀️ 🤾🏻‍♀️ 🤾🏼‍♀️ 🤾🏽‍♀️ 🤾🏾‍♀️ 🤾🏿‍♀️ 🤹‍♂️ 🤹🏻‍♂️ 🤹🏼‍♂️ 🤹🏽‍♂️ 🤹🏾‍♂️ 🤹🏿‍♂️ 🤹‍♀️ 🤹🏻‍♀️ 🤹🏼‍♀️ 🤹🏽‍♀️ 🤹🏾‍♀️ 🤹🏿‍♀️ 👨‍👩‍👦 👨‍👦 👨‍👦‍👦 👨‍👧 👨‍👧‍👦 👨‍👧‍👧 👩‍👦 👩‍👦‍👦 👩‍👧 👩‍👧‍👦 👩‍👧‍👧 ♀️ ♂️ ⚕️ 🏳️‍🌈 +26 🤩 🤪 🤭 🤫 🤨 🤮 🤯 🧐 🤬 🧡 🤟 🤟🏻 🤟🏼 🤟🏽 🤟🏾 🤟🏿 🤲 🤲🏻 🤲🏼 🤲🏽 🤲🏾 🤲🏿 🧠 🧒 🧒🏻 🧒🏼 🧒🏽 🧒🏾 🧒🏿 🧑 🧑🏻 🧑🏼 🧑🏽 🧑🏾 🧑🏿 🧔 🧔🏻 🧔🏼 🧔🏽 🧔🏾 🧔🏿 🧓 🧓🏻 🧓🏼 🧓🏽 🧓🏾 🧓🏿 🧕 🧕🏻 🧕🏼 🧕🏽 🧕🏾 🧕🏿 🤱 🤱🏻 🤱🏼 🤱🏽 🤱🏾 🤱🏿 🧙 🧙🏻 🧙🏼 🧙🏽 🧙🏾 🧙🏿 🧙‍♂️ 🧙🏻‍♂️ 🧙🏼‍♂️ 🧙🏽‍♂️ 🧙🏾‍♂️ 🧙🏿‍♂️ 🧙‍♀️ 🧙🏻‍♀️ 🧙🏼‍♀️ 🧙🏽‍♀️ 🧙🏾‍♀️ 🧙🏿‍♀️ 🧚 🧚🏻 🧚🏼 🧚🏽 🧚🏾 🧚🏿 🧚‍♂️ 🧚🏻‍♂️ 🧚🏼‍♂️ 🧚🏽‍♂️ 🧚🏾‍♂️ 🧚🏿‍♂️ 🧚‍♀️ 🧚🏻‍♀️ 🧚🏼‍♀️ 🧚🏽‍♀️ 🧚🏾‍♀️ 🧚🏿‍♀️ 🧛 🧛🏻 🧛🏼 🧛🏽 🧛🏾 🧛🏿 🧛‍♂️ 🧛🏻‍♂️ 🧛🏼‍♂️ 🧛🏽‍♂️ 🧛🏾‍♂️ 🧛🏿‍♂️ 🧛‍♀️ 🧛🏻‍♀️ 🧛🏼‍♀️ 🧛🏽‍♀️ 🧛🏾‍♀️ 🧛🏿‍♀️ 🧜 🧜🏻 🧜🏼 🧜🏽 🧜🏾 🧜🏿 🧜‍♂️ 🧜🏻‍♂️ 🧜🏼‍♂️ 🧜🏽‍♂️ 🧜🏾‍♂️ 🧜🏿‍♂️ 🧜‍♀️ 🧜🏻‍♀️ 🧜🏼‍♀️ 🧜🏽‍♀️ 🧜🏾‍♀️ 🧜🏿‍♀️ 🧝 🧝🏻 🧝🏼 🧝🏽 🧝🏾 🧝🏿 🧝‍♂️ 🧝🏻‍♂️ 🧝🏼‍♂️ 🧝🏽‍♂️ 🧝🏾‍♂️ 🧝🏿‍♂️ 🧝‍♀️ 🧝🏻‍♀️ 🧝🏼‍♀️ 🧝🏽‍♀️ 🧝🏾‍♀️ 🧝🏿‍♀️ 🧞 🧞‍♂️ 🧞‍♀️ 🧟 🧟‍♂️ 🧟‍♀️ 🕴🏻 🕴🏼 🕴🏽 🕴🏾 🕴🏿 🧖 🧖🏻 🧖🏼 🧖🏽 🧖🏾 🧖🏿 🧖‍♂️ 🧖🏻‍♂️ 🧖🏼‍♂️ 🧖🏽‍♂️ 🧖🏾‍♂️ 🧖🏿‍♂️ 🧖‍♀️ 🧖🏻‍♀️ 🧖🏼‍♀️ 🧖🏽‍♀️ 🧖🏾‍♀️ 🧖🏿‍♀️ 🧗 🧗🏻 🧗🏼 🧗🏽 🧗🏾 🧗🏿 🧗‍♂️ 🧗🏻‍♂️ 🧗🏼‍♂️ 🧗🏽‍♂️ 🧗🏾‍♂️ 🧗🏿‍♂️ 🧗‍♀️ 🧗🏻‍♀️ 🧗🏼‍♀️ 🧗🏽‍♀️ 🧗🏾‍♀️ 🧗🏿‍♀️ 🏇🏻 🏇🏼 🏇🏽 🏇🏾 🏇🏿 🏂🏻 🏂🏼 🏂🏽 🏂🏾 🏂🏿 🏌🏻 🏌🏼 🏌🏽 🏌🏾 🏌🏿 🏌🏻‍♂️ 🏌🏼‍♂️ 🏌🏽‍♂️ 🏌🏾‍♂️ 🏌🏿‍♂️ 🏌🏻‍♀️ 🏌🏼‍♀️ 🏌🏽‍♀️ 🏌🏾‍♀️ 🏌🏿‍♀️ 🧘 🧘🏻 🧘🏼 🧘🏽 🧘🏾 🧘🏿 🧘‍♂️ 🧘🏻‍♂️ 🧘🏼‍♂️ 🧘🏽‍♂️ 🧘🏾‍♂️ 🧘🏿‍♂️ 🧘‍♀️ 🧘🏻‍♀️ 🧘🏼‍♀️ 🧘🏽‍♀️ 🧘🏾‍♀️ 🧘🏿‍♀️ 🛌🏻 🛌🏼 🛌🏽 🛌🏾 🛌🏿 👩‍❤️‍💋‍👨 👩‍❤️‍👨 🦓 🦒 🦔 🦕 🦖 🦗 🥥 🥦 🥨 🥩 🥪 🥣 🥫 🥟 🥠 🥡 🥧 🥤 🥢 🛸 🛷 🥌 🧣 🧤 🧥 🧦 🧢 🇺🇳 🏴󠁧󠁢󠁥󠁮󠁧󠁿 🏴󠁧󠁢󠁳󠁣󠁴󠁿 🏴󠁧󠁢󠁷󠁬󠁳󠁿 +28 🥰 🥵 🥶 🥴 🥳 🥺 🦵 🦵🏻 🦵🏼 🦵🏽 🦵🏾 🦵🏿 🦶 🦶🏻 🦶🏼 🦶🏽 🦶🏾 🦶🏿 🦷 🦴 👨‍🦰 👨🏻‍🦰 👨🏼‍🦰 👨🏽‍🦰 👨🏾‍🦰 👨🏿‍🦰 👨‍🦱 👨🏻‍🦱 👨🏼‍🦱 👨🏽‍🦱 👨🏾‍🦱 👨🏿‍🦱 👨‍🦳 👨🏻‍🦳 👨🏼‍🦳 👨🏽‍🦳 👨🏾‍🦳 👨🏿‍🦳 👨‍🦲 👨🏻‍🦲 👨🏼‍🦲 👨🏽‍🦲 👨🏾‍🦲 👨🏿‍🦲 👩‍🦰 👩🏻‍🦰 👩🏼‍🦰 👩🏽‍🦰 👩🏾‍🦰 👩🏿‍🦰 👩‍🦱 👩🏻‍🦱 👩🏼‍🦱 👩🏽‍🦱 👩🏾‍🦱 👩🏿‍🦱 👩‍🦳 👩🏻‍🦳 👩🏼‍🦳 👩🏽‍🦳 👩🏾‍🦳 👩🏿‍🦳 👩‍🦲 👩🏻‍🦲 👩🏼‍🦲 👩🏽‍🦲 👩🏾‍🦲 👩🏿‍🦲 🦸 🦸🏻 🦸🏼 🦸🏽 🦸🏾 🦸🏿 🦸‍♂️ 🦸🏻‍♂️ 🦸🏼‍♂️ 🦸🏽‍♂️ 🦸🏾‍♂️ 🦸🏿‍♂️ 🦸‍♀️ 🦸🏻‍♀️ 🦸🏼‍♀️ 🦸🏽‍♀️ 🦸🏾‍♀️ 🦸🏿‍♀️ 🦹 🦹🏻 🦹🏼 🦹🏽 🦹🏾 🦹🏿 🦹‍♂️ 🦹🏻‍♂️ 🦹🏼‍♂️ 🦹🏽‍♂️ 🦹🏾‍♂️ 🦹🏿‍♂️ 🦹‍♀️ 🦹🏻‍♀️ 🦹🏼‍♀️ 🦹🏽‍♀️ 🦹🏾‍♀️ 🦹🏿‍♀️ 🦝 🦙 🦛 🦘 🦡 🦢 🦚 🦜 🦞 🦟 🦠 🥭 🥬 🥯 🧂 🥮 🧁 🧭 🧱 🛹 🧳 🧨 🧧 🥎 🥏 🥍 🧩 🧸 ♟️ 🧵 🧶 🥽 🥼 🥾 🥿 🧮 🧾 🧰 🧲 🧪 🧫 🧬 🧴 🧷 🧹 🧺 🧻 🧼 🧽 🧯 🧿 ♾️ 🏴‍☠️ +29 🥱 🤎 🤍 🤏 🤏🏻 🤏🏼 🤏🏽 🤏🏾 🤏🏿 🦾 🦿 🦻 🦻🏻 🦻🏼 🦻🏽 🦻🏾 🦻🏿 🧏 🧏🏻 🧏🏼 🧏🏽 🧏🏾 🧏🏿 🧏‍♂️ 🧏🏻‍♂️ 🧏🏼‍♂️ 🧏🏽‍♂️ 🧏🏾‍♂️ 🧏🏿‍♂️ 🧏‍♀️ 🧏🏻‍♀️ 🧏🏼‍♀️ 🧏🏽‍♀️ 🧏🏾‍♀️ 🧏🏿‍♀️ 🧍 🧍🏻 🧍🏼 🧍🏽 🧍🏾 🧍🏿 🧍‍♂️ 🧍🏻‍♂️ 🧍🏼‍♂️ 🧍🏽‍♂️ 🧍🏾‍♂️ 🧍🏿‍♂️ 🧍‍♀️ 🧍🏻‍♀️ 🧍🏼‍♀️ 🧍🏽‍♀️ 🧍🏾‍♀️ 🧍🏿‍♀️ 🧎 🧎🏻 🧎🏼 🧎🏽 🧎🏾 🧎🏿 🧎‍♂️ 🧎🏻‍♂️ 🧎🏼‍♂️ 🧎🏽‍♂️ 🧎🏾‍♂️ 🧎🏿‍♂️ 🧎‍♀️ 🧎🏻‍♀️ 🧎🏼‍♀️ 🧎🏽‍♀️ 🧎🏾‍♀️ 🧎🏿‍♀️ 👨‍🦯 👨🏻‍🦯 👨🏼‍🦯 👨🏽‍🦯 👨🏾‍🦯 👨🏿‍🦯 👩‍🦯 👩🏻‍🦯 👩🏼‍🦯 👩🏽‍🦯 👩🏾‍🦯 👩🏿‍🦯 👨‍🦼 👨🏻‍🦼 👨🏼‍🦼 👨🏽‍🦼 👨🏾‍🦼 👨🏿‍🦼 👩‍🦼 👩🏻‍🦼 👩🏼‍🦼 👩🏽‍🦼 👩🏾‍🦼 👩🏿‍🦼 👨‍🦽 👨🏻‍🦽 👨🏼‍🦽 👨🏽‍🦽 👨🏾‍🦽 👨🏿‍🦽 👩‍🦽 👩🏻‍🦽 👩🏼‍🦽 👩🏽‍🦽 👩🏾‍🦽 👩🏿‍🦽 🧑‍🤝‍🧑 🧑🏻‍🤝‍🧑🏻 🧑🏼‍🤝‍🧑🏻 🧑🏼‍🤝‍🧑🏼 🧑🏽‍🤝‍🧑🏻 🧑🏽‍🤝‍🧑🏼 🧑🏽‍🤝‍🧑🏽 🧑🏾‍🤝‍🧑🏻 🧑🏾‍🤝‍🧑🏼 🧑🏾‍🤝‍🧑🏽 🧑🏾‍🤝‍🧑🏾 🧑🏿‍🤝‍🧑🏻 🧑🏿‍🤝‍🧑🏼 🧑🏿‍🤝‍🧑🏽 🧑🏿‍🤝‍🧑🏾 🧑🏿‍🤝‍🧑🏿 👭🏻 👭🏼 👭🏽 👭🏾 👭🏿 👫🏻 👫🏼 👫🏽 👫🏾 👫🏿 👬🏻 👬🏼 👬🏽 👬🏾 👬🏿 🦧 🦮 🐕‍🦺 🦥 🦦 🦨 🦩 🦪 🧄 🧅 🧇 🧆 🧈 🧃 🧉 🧊 🛕 🦽 🦼 🛺 🪂 🪐 🤿 🪀 🪁 🦺 🥻 🩱 🩲 🩳 🩰 🪕 🪔 🪓 🦯 🩸 🩹 🩺 🪑 🪒 🟠 🟡 🟢 🟣 🟤 🟥 🟧 🟨 🟩 🟦 🟪 🟫 🇧🇱 🇧🇶 🇲🇶 🇷🇪 🇹🇫 🇽🇰 +30 🥲 🥸 🤌 🤌🏻 🤌🏼 🤌🏽 🤌🏾 🤌🏿 🫀 🫁 🧑‍🦰 🧑🏻‍🦰 🧑🏼‍🦰 🧑🏽‍🦰 🧑🏾‍🦰 🧑🏿‍🦰 🧑‍🦱 🧑🏻‍🦱 🧑🏼‍🦱 🧑🏽‍🦱 🧑🏾‍🦱 🧑🏿‍🦱 🧑‍🦳 🧑🏻‍🦳 🧑🏼‍🦳 🧑🏽‍🦳 🧑🏾‍🦳 🧑🏿‍🦳 🧑‍🦲 🧑🏻‍🦲 🧑🏼‍🦲 🧑🏽‍🦲 🧑🏾‍🦲 🧑🏿‍🦲 🧑‍⚕️ 🧑🏻‍⚕️ 🧑🏼‍⚕️ 🧑🏽‍⚕️ 🧑🏾‍⚕️ 🧑🏿‍⚕️ 🧑‍🎓 🧑🏻‍🎓 🧑🏼‍🎓 🧑🏽‍🎓 🧑🏾‍🎓 🧑🏿‍🎓 🧑‍🏫 🧑🏻‍🏫 🧑🏼‍🏫 🧑🏽‍🏫 🧑🏾‍🏫 🧑🏿‍🏫 🧑‍⚖️ 🧑🏻‍⚖️ 🧑🏼‍⚖️ 🧑🏽‍⚖️ 🧑🏾‍⚖️ 🧑🏿‍⚖️ 🧑‍🌾 🧑🏻‍🌾 🧑🏼‍🌾 🧑🏽‍🌾 🧑🏾‍🌾 🧑🏿‍🌾 🧑‍🍳 🧑🏻‍🍳 🧑🏼‍🍳 🧑🏽‍🍳 🧑🏾‍🍳 🧑🏿‍🍳 🧑‍🔧 🧑🏻‍🔧 🧑🏼‍🔧 🧑🏽‍🔧 🧑🏾‍🔧 🧑🏿‍🔧 🧑‍🏭 🧑🏻‍🏭 🧑🏼‍🏭 🧑🏽‍🏭 🧑🏾‍🏭 🧑🏿‍🏭 🧑‍💼 🧑🏻‍💼 🧑🏼‍💼 🧑🏽‍💼 🧑🏾‍💼 🧑🏿‍💼 🧑‍🔬 🧑🏻‍🔬 🧑🏼‍🔬 🧑🏽‍🔬 🧑🏾‍🔬 🧑🏿‍🔬 🧑‍💻 🧑🏻‍💻 🧑🏼‍💻 🧑🏽‍💻 🧑🏾‍💻 🧑🏿‍💻 🧑‍🎤 🧑🏻‍🎤 🧑🏼‍🎤 🧑🏽‍🎤 🧑🏾‍🎤 🧑🏿‍🎤 🧑‍🎨 🧑🏻‍🎨 🧑🏼‍🎨 🧑🏽‍🎨 🧑🏾‍🎨 🧑🏿‍🎨 🧑‍✈️ 🧑🏻‍✈️ 🧑🏼‍✈️ 🧑🏽‍✈️ 🧑🏾‍✈️ 🧑🏿‍✈️ 🧑‍🚀 🧑🏻‍🚀 🧑🏼‍🚀 🧑🏽‍🚀 🧑🏾‍🚀 🧑🏿‍🚀 🧑‍🚒 🧑🏻‍🚒 🧑🏼‍🚒 🧑🏽‍🚒 🧑🏾‍🚒 🧑🏿‍🚒 🥷 🥷🏻 🥷🏼 🥷🏽 🥷🏾 🥷🏿 🤵‍♂️ 🤵🏻‍♂️ 🤵🏼‍♂️ 🤵🏽‍♂️ 🤵🏾‍♂️ 🤵🏿‍♂️ 🤵‍♀️ 🤵🏻‍♀️ 🤵🏼‍♀️ 🤵🏽‍♀️ 🤵🏾‍♀️ 🤵🏿‍♀️ 👰‍♂️ 👰🏻‍♂️ 👰🏼‍♂️ 👰🏽‍♂️ 👰🏾‍♂️ 👰🏿‍♂️ 👰‍♀️ 👰🏻‍♀️ 👰🏼‍♀️ 👰🏽‍♀️ 👰🏾‍♀️ 👰🏿‍♀️ 👩‍🍼 👩🏻‍🍼 👩🏼‍🍼 👩🏽‍🍼 👩🏾‍🍼 👩🏿‍🍼 👨‍🍼 👨🏻‍🍼 👨🏼‍🍼 👨🏽‍🍼 👨🏾‍🍼 👨🏿‍🍼 🧑‍🍼 🧑🏻‍🍼 🧑🏼‍🍼 🧑🏽‍🍼 🧑🏾‍🍼 🧑🏿‍🍼 🧑‍🎄 🧑🏻‍🎄 🧑🏼‍🎄 🧑🏽‍🎄 🧑🏾‍🎄 🧑🏿‍🎄 🧑‍🦯 🧑🏻‍🦯 🧑🏼‍🦯 🧑🏽‍🦯 🧑🏾‍🦯 🧑🏿‍🦯 🧑‍🦼 🧑🏻‍🦼 🧑🏼‍🦼 🧑🏽‍🦼 🧑🏾‍🦼 🧑🏿‍🦼 🧑‍🦽 🧑🏻‍🦽 🧑🏼‍🦽 🧑🏽‍🦽 🧑🏾‍🦽 🧑🏿‍🦽 🧑🏻‍🤝‍🧑🏼 🧑🏻‍🤝‍🧑🏽 🧑🏻‍🤝‍🧑🏾 🧑🏻‍🤝‍🧑🏿 🧑🏼‍🤝‍🧑🏽 🧑🏼‍🤝‍🧑🏾 🧑🏼‍🤝‍🧑🏿 🧑🏽‍🤝‍🧑🏾 🧑🏽‍🤝‍🧑🏿 🧑🏾‍🤝‍🧑🏿 🫂 🐈‍⬛ 🦬 🦣 🦫 🐻‍❄️ 🦤 🪶 🦭 🪲 🪳 🪰 🪱 🪴 🫐 🫒 🫑 🫓 🫔 🫕 🫖 🧋 🪨 🪵 🛖 🛻 🛼 🪄 🪅 🪆 🪡 🪢 🩴 🪖 🪗 🪘 🪙 🪃 🪚 🪛 🪝 🪜 🛗 🪞 🪟 🪠 🪤 🪣 🪥 🪦 🪧 ⚧️ 🏳️‍⚧️ 🇩🇬 🇪🇦 🇪🇭 🇫🇰 🇬🇫 🇬🇵 🇬🇸 🇲🇫 🇳🇨 🇵🇲 🇼🇫 🇾🇹 +31 😶‍🌫️ 😮‍💨 😵‍💫 ❤️‍🔥 ❤️‍🩹 🧔‍♂️ 🧔🏻‍♂️ 🧔🏼‍♂️ 🧔🏽‍♂️ 🧔🏾‍♂️ 🧔🏿‍♂️ 🧔‍♀️ 🧔🏻‍♀️ 🧔🏼‍♀️ 🧔🏽‍♀️ 🧔🏾‍♀️ 🧔🏿‍♀️ 💏🏻 💏🏼 💏🏽 💏🏾 💏🏿 👩🏻‍❤️‍💋‍👨🏻 👩🏻‍❤️‍💋‍👨🏼 👩🏻‍❤️‍💋‍👨🏽 👩🏻‍❤️‍💋‍👨🏾 👩🏻‍❤️‍💋‍👨🏿 👩🏼‍❤️‍💋‍👨🏻 👩🏼‍❤️‍💋‍👨🏼 👩🏼‍❤️‍💋‍👨🏽 👩🏼‍❤️‍💋‍👨🏾 👩🏼‍❤️‍💋‍👨🏿 👩🏽‍❤️‍💋‍👨🏻 👩🏽‍❤️‍💋‍👨🏼 👩🏽‍❤️‍💋‍👨🏽 👩🏽‍❤️‍💋‍👨🏾 👩🏽‍❤️‍💋‍👨🏿 👩🏾‍❤️‍💋‍👨🏻 👩🏾‍❤️‍💋‍👨🏼 👩🏾‍❤️‍💋‍👨🏽 👩🏾‍❤️‍💋‍👨🏾 👩🏾‍❤️‍💋‍👨🏿 👩🏿‍❤️‍💋‍👨🏻 👩🏿‍❤️‍💋‍👨🏼 👩🏿‍❤️‍💋‍👨🏽 👩🏿‍❤️‍💋‍👨🏾 👩🏿‍❤️‍💋‍👨🏿 👨🏻‍❤️‍💋‍👨🏻 👨🏻‍❤️‍💋‍👨🏼 👨🏻‍❤️‍💋‍👨🏽 👨🏻‍❤️‍💋‍👨🏾 👨🏻‍❤️‍💋‍👨🏿 👨🏼‍❤️‍💋‍👨🏻 👨🏼‍❤️‍💋‍👨🏼 👨🏼‍❤️‍💋‍👨🏽 👨🏼‍❤️‍💋‍👨🏾 👨🏼‍❤️‍💋‍👨🏿 👨🏽‍❤️‍💋‍👨🏻 👨🏽‍❤️‍💋‍👨🏼 👨🏽‍❤️‍💋‍👨🏽 👨🏽‍❤️‍💋‍👨🏾 👨🏽‍❤️‍💋‍👨🏿 👨🏾‍❤️‍💋‍👨🏻 👨🏾‍❤️‍💋‍👨🏼 👨🏾‍❤️‍💋‍👨🏽 👨🏾‍❤️‍💋‍👨🏾 👨🏾‍❤️‍💋‍👨🏿 👨🏿‍❤️‍💋‍👨🏻 👨🏿‍❤️‍💋‍👨🏼 👨🏿‍❤️‍💋‍👨🏽 👨🏿‍❤️‍💋‍👨🏾 👨🏿‍❤️‍💋‍👨🏿 👩🏻‍❤️‍💋‍👩🏻 👩🏻‍❤️‍💋‍👩🏼 👩🏻‍❤️‍💋‍👩🏽 👩🏻‍❤️‍💋‍👩🏾 👩🏻‍❤️‍💋‍👩🏿 👩🏼‍❤️‍💋‍👩🏻 👩🏼‍❤️‍💋‍👩🏼 👩🏼‍❤️‍💋‍👩🏽 👩🏼‍❤️‍💋‍👩🏾 👩🏼‍❤️‍💋‍👩🏿 👩🏽‍❤️‍💋‍👩🏻 👩🏽‍❤️‍💋‍👩🏼 👩🏽‍❤️‍💋‍👩🏽 👩🏽‍❤️‍💋‍👩🏾 👩🏽‍❤️‍💋‍👩🏿 👩🏾‍❤️‍💋‍👩🏻 👩🏾‍❤️‍💋‍👩🏼 👩🏾‍❤️‍💋‍👩🏽 👩🏾‍❤️‍💋‍👩🏾 👩🏾‍❤️‍💋‍👩🏿 👩🏿‍❤️‍💋‍👩🏻 👩🏿‍❤️‍💋‍👩🏼 👩🏿‍❤️‍💋‍👩🏽 👩🏿‍❤️‍💋‍👩🏾 👩🏿‍❤️‍💋‍👩🏿 💑🏻 💑🏼 💑🏽 💑🏾 💑🏿 👩🏻‍❤️‍👨🏻 👩🏻‍❤️‍👨🏼 👩🏻‍❤️‍👨🏽 👩🏻‍❤️‍👨🏾 👩🏻‍❤️‍👨🏿 👩🏼‍❤️‍👨🏻 👩🏼‍❤️‍👨🏼 👩🏼‍❤️‍👨🏽 👩🏼‍❤️‍👨🏾 👩🏼‍❤️‍👨🏿 👩🏽‍❤️‍👨🏻 👩🏽‍❤️‍👨🏼 👩🏽‍❤️‍👨🏽 👩🏽‍❤️‍👨🏾 👩🏽‍❤️‍👨🏿 👩🏾‍❤️‍👨🏻 👩🏾‍❤️‍👨🏼 👩🏾‍❤️‍👨🏽 👩🏾‍❤️‍👨🏾 👩🏾‍❤️‍👨🏿 👩🏿‍❤️‍👨🏻 👩🏿‍❤️‍👨🏼 👩🏿‍❤️‍👨🏽 👩🏿‍❤️‍👨🏾 👩🏿‍❤️‍👨🏿 👨🏻‍❤️‍👨🏻 👨🏻‍❤️‍👨🏼 👨🏻‍❤️‍👨🏽 👨🏻‍❤️‍👨🏾 👨🏻‍❤️‍👨🏿 👨🏼‍❤️‍👨🏻 👨🏼‍❤️‍👨🏼 👨🏼‍❤️‍👨🏽 👨🏼‍❤️‍👨🏾 👨🏼‍❤️‍👨🏿 👨🏽‍❤️‍👨🏻 👨🏽‍❤️‍👨🏼 👨🏽‍❤️‍👨🏽 👨🏽‍❤️‍👨🏾 👨🏽‍❤️‍👨🏿 👨🏾‍❤️‍👨🏻 👨🏾‍❤️‍👨🏼 👨🏾‍❤️‍👨🏽 👨🏾‍❤️‍👨🏾 👨🏾‍❤️‍👨🏿 👨🏿‍❤️‍👨🏻 👨🏿‍❤️‍👨🏼 👨🏿‍❤️‍👨🏽 👨🏿‍❤️‍👨🏾 👨🏿‍❤️‍👨🏿 👩🏻‍❤️‍👩🏻 👩🏻‍❤️‍👩🏼 👩🏻‍❤️‍👩🏽 👩🏻‍❤️‍👩🏾 👩🏻‍❤️‍👩🏿 👩🏼‍❤️‍👩🏻 👩🏼‍❤️‍👩🏼 👩🏼‍❤️‍👩🏽 👩🏼‍❤️‍👩🏾 👩🏼‍❤️‍👩🏿 👩🏽‍❤️‍👩🏻 👩🏽‍❤️‍👩🏼 👩🏽‍❤️‍👩🏽 👩🏽‍❤️‍👩🏾 👩🏽‍❤️‍👩🏿 👩🏾‍❤️‍👩🏻 👩🏾‍❤️‍👩🏼 👩🏾‍❤️‍👩🏽 👩🏾‍❤️‍👩🏾 👩🏾‍❤️‍👩🏿 👩🏿‍❤️‍👩🏻 👩🏿‍❤️‍👩🏼 👩🏿‍❤️‍👩🏽 👩🏿‍❤️‍👩🏾 👩🏿‍❤️‍👩🏿 +32 🫠 🫢 🫣 🫡 🫥 🫤 🥹 🫱 🫱🏻 🫱🏼 🫱🏽 🫱🏾 🫱🏿 🫲 🫲🏻 🫲🏼 🫲🏽 🫲🏾 🫲🏿 🫳 🫳🏻 🫳🏼 🫳🏽 🫳🏾 🫳🏿 🫴 🫴🏻 🫴🏼 🫴🏽 🫴🏾 🫴🏿 🫰 🫰🏻 🫰🏼 🫰🏽 🫰🏾 🫰🏿 🫵 🫵🏻 🫵🏼 🫵🏽 🫵🏾 🫵🏿 🫶 🫶🏻 🫶🏼 🫶🏽 🫶🏾 🫶🏿 🫦 🫅 🫅🏻 🫅🏼 🫅🏽 🫅🏾 🫅🏿 🫃 🫃🏻 🫃🏼 🫃🏽 🫃🏾 🫃🏿 🫄 🫄🏻 🫄🏼 🫄🏽 🫄🏾 🫄🏿 🧌 🪸 🪷 🪹 🪺 🫘 🫗 🫙 🛝 🛞 🛟 🪩 🪫 🩼 🩻 🫧 🪬 🪪 🟰 +33 🫨 🩷 🩵 🩶 🫷 🫷🏻 🫷🏼 🫷🏽 🫷🏾 🫷🏿 🫸 🫸🏻 🫸🏼 🫸🏽 🫸🏾 🫸🏿 🫎 🫏 🪽 🐦‍⬛ 🪿 🪼 🪻 🫚 🫛 🪭 🪮 🪇 🪈 🪯 🛜 +34 🙂‍↔️ 🙂‍↕️ 🚶‍➡️ 🚶🏻‍➡️ 🚶🏼‍➡️ 🚶🏽‍➡️ 🚶🏾‍➡️ 🚶🏿‍➡️ 🚶‍♀️‍➡️ 🚶🏻‍♀️‍➡️ 🚶🏼‍♀️‍➡️ 🚶🏽‍♀️‍➡️ 🚶🏾‍♀️‍➡️ 🚶🏿‍♀️‍➡️ 🚶‍♂️‍➡️ 🚶🏻‍♂️‍➡️ 🚶🏼‍♂️‍➡️ 🚶🏽‍♂️‍➡️ 🚶🏾‍♂️‍➡️ 🚶🏿‍♂️‍➡️ 🧎‍➡️ 🧎🏻‍➡️ 🧎🏼‍➡️ 🧎🏽‍➡️ 🧎🏾‍➡️ 🧎🏿‍➡️ 🧎‍♀️‍➡️ 🧎🏻‍♀️‍➡️ 🧎🏼‍♀️‍➡️ 🧎🏽‍♀️‍➡️ 🧎🏾‍♀️‍➡️ 🧎🏿‍♀️‍➡️ 🧎‍♂️‍➡️ 🧎🏻‍♂️‍➡️ 🧎🏼‍♂️‍➡️ 🧎🏽‍♂️‍➡️ 🧎🏾‍♂️‍➡️ 🧎🏿‍♂️‍➡️ 🧑‍🦯‍➡️ 🧑🏻‍🦯‍➡️ 🧑🏼‍🦯‍➡️ 🧑🏽‍🦯‍➡️ 🧑🏾‍🦯‍➡️ 🧑🏿‍🦯‍➡️ 👨‍🦯‍➡️ 👨🏻‍🦯‍➡️ 👨🏼‍🦯‍➡️ 👨🏽‍🦯‍➡️ 👨🏾‍🦯‍➡️ 👨🏿‍🦯‍➡️ 👩‍🦯‍➡️ 👩🏻‍🦯‍➡️ 👩🏼‍🦯‍➡️ 👩🏽‍🦯‍➡️ 👩🏾‍🦯‍➡️ 👩🏿‍🦯‍➡️ 🧑‍🦼‍➡️ 🧑🏻‍🦼‍➡️ 🧑🏼‍🦼‍➡️ 🧑🏽‍🦼‍➡️ 🧑🏾‍🦼‍➡️ 🧑🏿‍🦼‍➡️ 👨‍🦼‍➡️ 👨🏻‍🦼‍➡️ 👨🏼‍🦼‍➡️ 👨🏽‍🦼‍➡️ 👨🏾‍🦼‍➡️ 👨🏿‍🦼‍➡️ 👩‍🦼‍➡️ 👩🏻‍🦼‍➡️ 👩🏼‍🦼‍➡️ 👩🏽‍🦼‍➡️ 👩🏾‍🦼‍➡️ 👩🏿‍🦼‍➡️ 🧑‍🦽‍➡️ 🧑🏻‍🦽‍➡️ 🧑🏼‍🦽‍➡️ 🧑🏽‍🦽‍➡️ 🧑🏾‍🦽‍➡️ 🧑🏿‍🦽‍➡️ 👨‍🦽‍➡️ 👨🏻‍🦽‍➡️ 👨🏼‍🦽‍➡️ 👨🏽‍🦽‍➡️ 👨🏾‍🦽‍➡️ 👨🏿‍🦽‍➡️ 👩‍🦽‍➡️ 👩🏻‍🦽‍➡️ 👩🏼‍🦽‍➡️ 👩🏽‍🦽‍➡️ 👩🏾‍🦽‍➡️ 👩🏿‍🦽‍➡️ 🏃‍➡️ 🏃🏻‍➡️ 🏃🏼‍➡️ 🏃🏽‍➡️ 🏃🏾‍➡️ 🏃🏿‍➡️ 🏃‍♀️‍➡️ 🏃🏻‍♀️‍➡️ 🏃🏼‍♀️‍➡️ 🏃🏽‍♀️‍➡️ 🏃🏾‍♀️‍➡️ 🏃🏿‍♀️‍➡️ 🏃‍♂️‍➡️ 🏃🏻‍♂️‍➡️ 🏃🏼‍♂️‍➡️ 🏃🏽‍♂️‍➡️ 🏃🏾‍♂️‍➡️ 🏃🏿‍♂️‍➡️ 🧑‍🧑‍🧒 🧑‍🧑‍🧒‍🧒 🧑‍🧒 🧑‍🧒‍🧒 🐦‍🔥 🍋‍🟩 🍄‍🟫 ⛓️‍💥 +35 🫩 🫆 🪾 🫜 🪉 🪏 🫟 🇨🇶 \ No newline at end of file diff --git a/app/src/main/assets/layouts/main/akan.txt b/app/src/main/assets/layouts/main/akan.txt new file mode 100644 index 000000000..1f139b582 --- /dev/null +++ b/app/src/main/assets/layouts/main/akan.txt @@ -0,0 +1,28 @@ +ɛ q +w +e +r +t +y +u +i +o +p + +a +s +d +f +g +h +j +k +l + +z +ɔ x +c ¢ +v +b +n +m diff --git a/app/src/main/assets/layouts/main/bemba.txt b/app/src/main/assets/layouts/main/bemba.txt new file mode 100644 index 000000000..5253b2885 --- /dev/null +++ b/app/src/main/assets/layouts/main/bemba.txt @@ -0,0 +1,29 @@ +q +w +e +r +t +y +u +i +o +p +ŋ + +a +s +d +f +g +h +j +k +l + +z +x +c +v +b +n +m diff --git a/app/src/main/assets/layouts/main/central_kurdish.txt b/app/src/main/assets/layouts/main/central_kurdish.txt new file mode 100644 index 000000000..eec1593e8 --- /dev/null +++ b/app/src/main/assets/layouts/main/central_kurdish.txt @@ -0,0 +1,31 @@ +ق +و +ە +ر +ت +ی +ێ +ئ +ۆ +پ + +ا +س +ش +د +ف +ھ|ه +ژ +ل +ک +گ + +ز +ع +ح +ج +چ +خ +ب +ن +م diff --git a/app/src/main/assets/layouts/main/dagbani.txt b/app/src/main/assets/layouts/main/dagbani.txt new file mode 100644 index 000000000..588ff0513 --- /dev/null +++ b/app/src/main/assets/layouts/main/dagbani.txt @@ -0,0 +1,28 @@ +q +w +ɛ e +r ¢ +t +y +u +i +ɔ o +p + +a +s +d +f +ɣ g +h +j +k +l + +ʒ z +x x +c +v +b +ŋ n +m diff --git a/app/src/main/assets/layouts/main/ewe.txt b/app/src/main/assets/layouts/main/ewe.txt new file mode 100644 index 000000000..bb307f1a3 --- /dev/null +++ b/app/src/main/assets/layouts/main/ewe.txt @@ -0,0 +1,28 @@ +ɛ q +w +e +r +t +ɣ y +u +i +o +p + +a +s +d +f +g +h +j +k +l + +z +ɔ x +c ¢ +v +b +n +m diff --git a/app/src/main/assets/layouts/main/ga.txt b/app/src/main/assets/layouts/main/ga.txt new file mode 100644 index 000000000..03d1fe66e --- /dev/null +++ b/app/src/main/assets/layouts/main/ga.txt @@ -0,0 +1,28 @@ +ɛ q +w +e +r +t +y +u +i +o +p + +a +s +d +f +g +h +j +k +l + +z +ɔ x +ŋ c ¢ +v +b +n +m diff --git a/app/src/main/assets/layouts/main/hausa.txt b/app/src/main/assets/layouts/main/hausa.txt new file mode 100644 index 000000000..3138eb991 --- /dev/null +++ b/app/src/main/assets/layouts/main/hausa.txt @@ -0,0 +1,28 @@ +ẹ q +w +e +r +t +y +u +i +o +p + +a +s +d +f +g +h +j +k +l + +z +ọ x +c +v +b +n ₦ +m diff --git a/app/src/main/assets/layouts/main/igbo.txt b/app/src/main/assets/layouts/main/igbo.txt new file mode 100644 index 000000000..9cf50d780 --- /dev/null +++ b/app/src/main/assets/layouts/main/igbo.txt @@ -0,0 +1,28 @@ +ṅ q +w +e +r +t +y +u +i +o +p + +a +s +d +f +g +h +j +k +l + +z +ọ x +c +ụ v +b +n ₦ +m diff --git a/app/src/main/assets/layouts/main/kikuyu.txt b/app/src/main/assets/layouts/main/kikuyu.txt new file mode 100644 index 000000000..0fdbdd8d2 --- /dev/null +++ b/app/src/main/assets/layouts/main/kikuyu.txt @@ -0,0 +1,28 @@ +ĩ q +w +e +r +t +y +u +i +o +p + +a +s +d +f +g +h +j +k +l + +z +ũ x +c +v +b +n +m diff --git a/app/src/main/assets/layouts/main/korean_phonetic.json b/app/src/main/assets/layouts/main/korean_phonetic.json new file mode 100644 index 000000000..b2c2a6bb2 --- /dev/null +++ b/app/src/main/assets/layouts/main/korean_phonetic.json @@ -0,0 +1,55 @@ +[ + [ + { "label": "\u3147" }, + { "label": "\u3161" }, + { "$": "shift_state_selector", + "manualOrLocked": { "label": "\u3156" }, + "default": { "label": "\u3154", "popup": { "main": { "label": "\u3156" } } } + }, + { "label": "\u3139" }, + { "label": "\u314c" }, + { "$": "shift_state_selector", + "manualOrLocked": { "label": "\u3152" }, + "default": { "label": "\u3150", "popup": { "main": { "label": "\u3152" } } } + }, + { "label": "\u315c" }, + { "label": "\u3163" }, + { "label": "\u3157" }, + { "label": "\u314d" } + ], + [ + { "label": "\u314f" }, + { "$": "shift_state_selector", + "manualOrLocked": { "label": "\u3146" }, + "default": { "label": "\u3145", "popup": { "main": { "label": "\u3146" } } } + }, + { "$": "shift_state_selector", + "manualOrLocked": { "label": "\u3138" }, + "default": { "label": "\u3137", "popup": { "main": { "label": "\u3138" } } } + }, + { "label": "\u3151" }, + { "$": "shift_state_selector", + "manualOrLocked": { "label": "\u3132" }, + "default": { "label": "\u3131", "popup": { "main": { "label": "\u3132" } } } + }, + { "label": "\u314e" }, + { "$": "shift_state_selector", + "manualOrLocked": { "label": "\u3149" }, + "default": { "label": "\u3148", "popup": { "main": { "label": "\u3149" } } } + }, + { "label": "\u314b" }, + { "label": "\u315b" } + ], + [ + { "label": "\u3155" }, + { "label": "\u3160" }, + { "label": "\u314a" }, + { "label": "\u3153" }, + { "$": "shift_state_selector", + "manualOrLocked": { "label": "\u3143" }, + "default": { "label": "\u3142", "popup": { "main": { "label": "\u3143" } } } + }, + { "label": "\u3134" }, + { "label": "\u3141" } + ] +] diff --git a/app/src/main/assets/layouts/main/lingala.txt b/app/src/main/assets/layouts/main/lingala.txt new file mode 100644 index 000000000..830109805 --- /dev/null +++ b/app/src/main/assets/layouts/main/lingala.txt @@ -0,0 +1,28 @@ +q +w +ɛ e +r +t +y +u +i +ɔ o +p + +a +s +d +f +g +h +j +k +l + +z +x +c +̌ v +b +n +m diff --git a/app/src/main/assets/layouts/main/luganda.txt b/app/src/main/assets/layouts/main/luganda.txt new file mode 100644 index 000000000..5253b2885 --- /dev/null +++ b/app/src/main/assets/layouts/main/luganda.txt @@ -0,0 +1,29 @@ +q +w +e +r +t +y +u +i +o +p +ŋ + +a +s +d +f +g +h +j +k +l + +z +x +c +v +b +n +m diff --git a/app/src/main/assets/layouts/main/russian.txt b/app/src/main/assets/layouts/main/russian.txt index 7ceb2435d..7da99f64e 100644 --- a/app/src/main/assets/layouts/main/russian.txt +++ b/app/src/main/assets/layouts/main/russian.txt @@ -8,7 +8,7 @@ ш щ з -х +х ъ [ { ф ы @@ -20,7 +20,7 @@ л д ж -э +э э́ ] } я ч diff --git a/app/src/main/assets/layouts/main/russian_extended.txt b/app/src/main/assets/layouts/main/russian_extended.txt new file mode 100644 index 000000000..8b3249fee --- /dev/null +++ b/app/src/main/assets/layouts/main/russian_extended.txt @@ -0,0 +1,34 @@ +й +ц +у +к +е +н +г +ш +щ +з +х [ { +ъ ] } + +ф +ы +в +а +п +р +о +л +д +ж +э э́ + +я +ч +с +м +и +т +ь +б < +ю > diff --git a/app/src/main/assets/layouts/main/sesotho.txt b/app/src/main/assets/layouts/main/sesotho.txt new file mode 100644 index 000000000..b0796b3b5 --- /dev/null +++ b/app/src/main/assets/layouts/main/sesotho.txt @@ -0,0 +1,28 @@ +q +w +e +r +t +y +u +i +o +p + +a +š s +d +f +g +h +j +k +l + +z +x +c +v +b +n +m diff --git a/app/src/main/assets/layouts/main/ukrainian.txt b/app/src/main/assets/layouts/main/ukrainian.txt index 7e01cde38..ff1ed643a 100644 --- a/app/src/main/assets/layouts/main/ukrainian.txt +++ b/app/src/main/assets/layouts/main/ukrainian.txt @@ -8,7 +8,8 @@ ш щ з -х +х [ { +ї ] } ф і @@ -20,7 +21,7 @@ л д ж -є +є ' " я ч @@ -30,4 +31,4 @@ т ь б < -ю > +ю > ґ diff --git a/app/src/main/assets/layouts/main/ukrainian_extended.txt b/app/src/main/assets/layouts/main/ukrainian_extended.txt new file mode 100644 index 000000000..7e37e93cc --- /dev/null +++ b/app/src/main/assets/layouts/main/ukrainian_extended.txt @@ -0,0 +1,35 @@ +й +ц +у +к +е +н +г +ш +щ +з +х [ { +ї ] } + +ф +і +в +а +п +р +о +л +д +ж +є ' " +' " + +я +ч +с +м +и +т +ь +б < +ю > ґ diff --git a/app/src/main/assets/layouts/main/yoruba.txt b/app/src/main/assets/layouts/main/yoruba.txt new file mode 100644 index 000000000..3ee1696dd --- /dev/null +++ b/app/src/main/assets/layouts/main/yoruba.txt @@ -0,0 +1,28 @@ +ẹ q +w +e +r +t +y +u +i +o +p + +a +s +d +f +g +h +j +k +l + +z +ọ x +c +ṣ v +b +n ₦ +m diff --git a/app/src/main/assets/layouts/number_row/number_row.json b/app/src/main/assets/layouts/number_row/number_row.json new file mode 100644 index 000000000..3ad11861a --- /dev/null +++ b/app/src/main/assets/layouts/number_row/number_row.json @@ -0,0 +1,44 @@ +[ + [ + { "$": "shift_state_selector", + "manualOrLocked": { "label": "!" }, + "default": { "label": "1", "popup": { "relevant": [{ "label": "¹" }, { "label": "½" }, { "label": "⅓" }, { "label": "¼" }, { "label": "⅛" }] } } + }, + { "$": "shift_state_selector", + "manualOrLocked": { "label": "@" }, + "default": { "label": "2", "popup": { "relevant": [{ "label": "²" }, { "label": "⅔" }] } } + }, + { "$": "shift_state_selector", + "manualOrLocked": { "label": "#" }, + "default": { "label": "3", "popup": { "relevant": [{ "label": "³" }, { "label": "¾" }, { "label": "⅜" }] } } + }, + { "$": "shift_state_selector", + "manualOrLocked": { "label": "$" }, + "default": { "label": "4", "popup": { "relevant": [{ "label": "⁴" }] } } + }, + { "$": "shift_state_selector", + "manualOrLocked": { "label": "%" }, + "default": { "label": "5", "popup": { "relevant": [{ "label": "⁵" }, { "label": "⅝" }] } } + }, + { "$": "shift_state_selector", + "manualOrLocked": { "label": "^" }, + "default": { "label": "6", "popup": { "relevant": [{ "label": "⁶" }] } } + }, + { "$": "shift_state_selector", + "manualOrLocked": { "label": "&" }, + "default": { "label": "7", "popup": { "relevant": [{ "label": "⁷" }, { "label": "⅞" }] } } + }, + { "$": "shift_state_selector", + "manualOrLocked": { "label": "*" }, + "default": { "label": "8", "popup": { "relevant": [{ "label": "⁸" }] } } + }, + { "$": "shift_state_selector", + "manualOrLocked": { "label": "(" }, + "default": { "label": "9", "popup": { "relevant": [{ "label": "⁹" }] } } + }, + { "$": "shift_state_selector", + "manualOrLocked": { "label": ")" }, + "default": { "label": "0", "popup": { "relevant": [{ "label": "⁰" }, { "label": "ⁿ" }, { "label": "∅" }] } } + } + ] + ] \ No newline at end of file diff --git a/app/src/main/assets/layouts/number_row/number_row.txt b/app/src/main/assets/layouts/number_row/number_row_basic.txt similarity index 85% rename from app/src/main/assets/layouts/number_row/number_row.txt rename to app/src/main/assets/layouts/number_row/number_row_basic.txt index a7fed81c6..709c30a8b 100644 --- a/app/src/main/assets/layouts/number_row/number_row.txt +++ b/app/src/main/assets/layouts/number_row/number_row_basic.txt @@ -7,4 +7,4 @@ 7 ⁷ ⅞ 8 ⁸ 9 ⁹ -0 ⁰ ⁿ ∅ +0 ⁰ ⁿ ∅ \ No newline at end of file diff --git a/app/src/main/assets/locale_key_texts/ckb.txt b/app/src/main/assets/locale_key_texts/ckb.txt new file mode 100644 index 000000000..5e13897b8 --- /dev/null +++ b/app/src/main/assets/locale_key_texts/ckb.txt @@ -0,0 +1,39 @@ +[popup_keys] +ق ٯ +و وو +ە ة ﻪ ـہ +ر ڕ ڒ ࢪ +ت ط +ی ي ې ۍ +ێ ؽ +ئ ء ﺋ +ۆ ؤ ۏ ۊ ۋ ۉ ۇ +پ ث +ا أ إ آ ٱ +س ص +ش ض +د ۮ ڌ ﮆ +ف ڤ ڡ +ھ ھ +ژ ━|ـ +ل ڵ +ک ك ڪ +گ غ +ز ظ +ع ؏ +ب ى +punctuation !autoColumnOrder!8 \؟ ! ، ٫ ؍ : ؛ ; : | - @ _ # * ٪ & ^ +« „ “ ” +» ‚ ‘ ’ ‹ › + +[labels] +alphabet: ئ‌پ‌گ +symbol: ٣٢١؟ +comma: ، +question: ؟ + +[number_row] +١ ٢ ٣ ٤ ٥ ٦ ٧ ٨ ٩ ٠ + +[tlds] +iq krd diff --git a/app/src/main/assets/locale_key_texts/ru.txt b/app/src/main/assets/locale_key_texts/ru.txt index bbb9a2478..59583da42 100644 --- a/app/src/main/assets/locale_key_texts/ru.txt +++ b/app/src/main/assets/locale_key_texts/ru.txt @@ -1,9 +1,19 @@ [popup_keys] -е ё -ь ъ +е ё е́ ѣ +ф ѳ +ы ы́ +а а́ +о о́ +я я́ +и и́ +ь ъ ы +ю ю́ ' ’ ‚ ‘ › ‹ " ” „ “ » « +і ы +є э э́ + [labels] alphabet: АБВ diff --git a/app/src/main/assets/locale_key_texts/uk.txt b/app/src/main/assets/locale_key_texts/uk.txt index 9ee926c94..080bf826b 100644 --- a/app/src/main/assets/locale_key_texts/uk.txt +++ b/app/src/main/assets/locale_key_texts/uk.txt @@ -1,9 +1,19 @@ [popup_keys] +е е́ г ґ -ь +ф ѳ і ї -' ’ ‚ ‘ -" ” „ “ +а а́ +о о́ +я я́ +и и́ і ї +г ґ +ю ю́ +' ’ ‚ ‘ › ‹ +" ” „ “ » « + +ы і ї +э є [labels] alphabet: АБВ diff --git a/app/src/main/java/helium314/keyboard/accessibility/MainKeyboardAccessibilityDelegate.kt b/app/src/main/java/helium314/keyboard/accessibility/MainKeyboardAccessibilityDelegate.kt index 0be99c7c0..6a4283494 100644 --- a/app/src/main/java/helium314/keyboard/accessibility/MainKeyboardAccessibilityDelegate.kt +++ b/app/src/main/java/helium314/keyboard/accessibility/MainKeyboardAccessibilityDelegate.kt @@ -14,7 +14,7 @@ import android.view.MotionEvent import helium314.keyboard.accessibility.AccessibilityLongPressTimer.LongPressTimerCallback import helium314.keyboard.keyboard.* import helium314.keyboard.latin.R -import helium314.keyboard.latin.utils.SubtypeLocaleUtils +import helium314.keyboard.latin.utils.SubtypeLocaleUtils.displayName /** * This class represents a delegate that can be registered in [MainKeyboardView] to enhance @@ -86,9 +86,7 @@ class MainKeyboardAccessibilityDelegate( * @param keyboard The new keyboard. */ private fun announceKeyboardLanguage(keyboard: Keyboard) { - val languageText = SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale( - keyboard.mId.mSubtype.rawSubtype) - sendWindowStateChanged(languageText) + sendWindowStateChanged(keyboard.mId.mSubtype.rawSubtype.displayName()) } /** diff --git a/app/src/main/java/helium314/keyboard/keyboard/Key.java b/app/src/main/java/helium314/keyboard/keyboard/Key.java index 3d0917976..c80c1eb3b 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/Key.java +++ b/app/src/main/java/helium314/keyboard/keyboard/Key.java @@ -24,6 +24,7 @@ import helium314.keyboard.latin.common.StringUtils; import helium314.keyboard.latin.utils.PopupKeysUtilsKt; import helium314.keyboard.latin.utils.ToolbarKey; import helium314.keyboard.latin.utils.ToolbarUtilsKt; +import kotlin.collections.ArraysKt; import java.util.Arrays; import java.util.Locale; @@ -919,7 +920,7 @@ public class Key implements Comparable { @NonNull final Drawable spacebarBackground, @NonNull final Drawable actionKeyBackground) { final Drawable background; - if (isAccentColored()) { + if (hasActionKeyBackground()) { background = actionKeyBackground; } else if (hasFunctionalBackground()) { background = functionalKeyBackground; @@ -933,17 +934,10 @@ public class Key implements Comparable { return background; } - public final boolean isAccentColored() { - if (hasActionKeyBackground()) return true; - final String iconName = getIconName(); - if (iconName == null) return false; - // todo: other way of identifying the color? - // this should be done differently, as users can set any icon now - // how is the background drawable selected? can we use the same way? - return iconName.equals(KeyboardIconsSet.NAME_NEXT_KEY) - || iconName.equals(KeyboardIconsSet.NAME_PREVIOUS_KEY) - || iconName.equals("clipboard_action_key") - || iconName.equals("emoji_action_key"); + public final boolean hasActionKeyPopups() { + if (!hasActionKeyBackground()) return false; + // only use the special action key popups for action colored keys, and only for icon popups + return ArraysKt.none(getPopupKeys(), (key) -> key.mIconName == null); } public boolean hasFunctionalBackground() { diff --git a/app/src/main/java/helium314/keyboard/keyboard/KeyboardActionListenerImpl.kt b/app/src/main/java/helium314/keyboard/keyboard/KeyboardActionListenerImpl.kt index 89fdcecb4..9df3a9682 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/KeyboardActionListenerImpl.kt +++ b/app/src/main/java/helium314/keyboard/keyboard/KeyboardActionListenerImpl.kt @@ -1,5 +1,6 @@ package helium314.keyboard.keyboard +import android.text.InputType import android.view.KeyEvent import android.view.inputmethod.InputMethodSubtype import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode @@ -13,9 +14,12 @@ import helium314.keyboard.latin.common.loopOverCodePointsBackwards import helium314.keyboard.latin.inputlogic.InputLogic import helium314.keyboard.latin.settings.Settings import kotlin.math.abs +import kotlin.math.min class KeyboardActionListenerImpl(private val latinIME: LatinIME, private val inputLogic: InputLogic) : KeyboardActionListener { + private val connection = inputLogic.mConnection + private val keyboardSwitcher = KeyboardSwitcher.getInstance() private val settings = Settings.getInstance() private var metaState = 0 // is this enough, or are there threading issues with the different PointerTrackers? @@ -28,9 +32,15 @@ class KeyboardActionListenerImpl(private val latinIME: LatinIME, private val inp private fun adjustMetaState(code: Int, remove: Boolean) { val metaCode = when (code) { KeyCode.CTRL -> KeyEvent.META_CTRL_ON + KeyCode.CTRL_LEFT -> KeyEvent.META_CTRL_LEFT_ON + KeyCode.CTRL_RIGHT -> KeyEvent.META_CTRL_RIGHT_ON KeyCode.ALT -> KeyEvent.META_ALT_ON + KeyCode.ALT_LEFT -> KeyEvent.META_ALT_LEFT_ON + KeyCode.ALT_RIGHT -> KeyEvent.META_ALT_RIGHT_ON KeyCode.FN -> KeyEvent.META_FUNCTION_ON KeyCode.META -> KeyEvent.META_META_ON + KeyCode.META_LEFT -> KeyEvent.META_META_LEFT_ON + KeyCode.META_RIGHT -> KeyEvent.META_META_RIGHT_ON else -> return } metaState = if (remove) metaState and metaCode.inv() @@ -70,8 +80,9 @@ class KeyboardActionListenerImpl(private val latinIME: LatinIME, private val inp keyboardSwitcher.onFinishSlidingInput(latinIME.currentAutoCapsState, latinIME.currentRecapitalizeState) override fun onCustomRequest(requestCode: Int): Boolean { - if (requestCode == Constants.CUSTOM_CODE_SHOW_INPUT_METHOD_PICKER) + if (requestCode == Constants.CUSTOM_CODE_SHOW_INPUT_METHOD_PICKER) { return latinIME.showInputPickerDialog() + } return false } @@ -101,30 +112,34 @@ class KeyboardActionListenerImpl(private val latinIME: LatinIME, private val inp override fun onMoveDeletePointer(steps: Int) { inputLogic.finishInput() - val end = inputLogic.mConnection.expectedSelectionEnd - var actualSteps = 0 // corrected steps to avoid splitting chars belonging to the same codepoint + val end = connection.expectedSelectionEnd + val actualSteps = actualSteps(steps) + val start = connection.expectedSelectionStart + actualSteps + if (start > end) return + connection.setSelection(start, end) + } + + private fun actualSteps(steps: Int): Int { + var actualSteps = 0 + // corrected steps to avoid splitting chars belonging to the same codepoint if (steps > 0) { - val text = inputLogic.mConnection.getSelectedText(0) - if (text == null) actualSteps = steps - else loopOverCodePoints(text) { - actualSteps += Character.charCount(it) + val text = connection.getSelectedText(0) ?: return steps + loopOverCodePoints(text) { cp, charCount -> + actualSteps += charCount actualSteps >= steps } } else { - val text = inputLogic.mConnection.getTextBeforeCursor(-steps * 4, 0) - if (text == null) actualSteps = steps - else loopOverCodePointsBackwards(text) { - actualSteps -= Character.charCount(it) + val text = connection.getTextBeforeCursor(-steps * 4, 0) ?: return steps + loopOverCodePointsBackwards(text) { cp, charCount -> + actualSteps -= charCount actualSteps <= steps } } - val start = inputLogic.mConnection.expectedSelectionStart + actualSteps - if (start > end) return - inputLogic.mConnection.setSelection(start, end) + return actualSteps } override fun onUpWithDeletePointerActive() { - if (!inputLogic.mConnection.hasSelection()) return + if (!connection.hasSelection()) return inputLogic.finishInput() onCodeInput(KeyCode.DELETE, Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE, false) } @@ -143,16 +158,17 @@ class KeyboardActionListenerImpl(private val latinIME: LatinIME, private val inp val current = RichInputMethodManager.getInstance().currentSubtype.rawSubtype var wantedIndex = subtypes.indexOf(current) + if (steps > 0) 1 else -1 wantedIndex %= subtypes.size - if (wantedIndex < 0) + if (wantedIndex < 0) { wantedIndex += subtypes.size + } val newSubtype = subtypes[wantedIndex] // do not switch if we would switch to the initial subtype after cycling all other subtypes - if (initialSubtype == null) - initialSubtype = current + if (initialSubtype == null) initialSubtype = current if (initialSubtype == newSubtype) { - if ((subtypeSwitchCount > 0 && steps > 0) || ((subtypeSwitchCount < 0 && steps < 0))) + if ((subtypeSwitchCount > 0 && steps > 0) || (subtypeSwitchCount < 0 && steps < 0)) { return true + } } if (steps > 0) subtypeSwitchCount++ else subtypeSwitchCount-- @@ -173,17 +189,8 @@ class KeyboardActionListenerImpl(private val latinIME: LatinIME, private val inp val steps = if (RichInputMethodManager.getInstance().currentSubtype.isRtlSubtype) -rawSteps else rawSteps val moveSteps: Int if (steps < 0) { - var actualSteps = 0 // corrected steps to avoid splitting chars belonging to the same codepoint - val text = inputLogic.mConnection.getTextBeforeCursor(-steps * 4, 0) ?: return false - loopOverCodePointsBackwards(text) { - if (StringUtils.mightBeEmoji(it)) { - actualSteps = 0 - return@loopOverCodePointsBackwards true - } - actualSteps -= Character.charCount(it) - actualSteps <= steps - } - moveSteps = -text.length.coerceAtMost(abs(actualSteps)) + val text = connection.getTextBeforeCursor(-steps * 4, 0) ?: return false + moveSteps = negativeMoveSteps(text, steps) if (moveSteps == 0) { // some apps don't return any text via input connection, and the cursor can't be moved // we fall back to virtually pressing the left/right key one or more times instead @@ -193,36 +200,61 @@ class KeyboardActionListenerImpl(private val latinIME: LatinIME, private val inp return true } } else { - var actualSteps = 0 // corrected steps to avoid splitting chars belonging to the same codepoint - val text = inputLogic.mConnection.getTextAfterCursor(steps * 4, 0) ?: return false - loopOverCodePoints(text) { - if (StringUtils.mightBeEmoji(it)) { - actualSteps = 0 - return@loopOverCodePoints true - } - actualSteps += Character.charCount(it) - actualSteps >= steps - } - moveSteps = text.length.coerceAtMost(actualSteps) + val text = connection.getTextAfterCursor(steps * 4, 0) ?: return false + moveSteps = positiveMoveSteps(text, steps) if (moveSteps == 0) { + // some apps don't return any text via input connection, and the cursor can't be moved + // we fall back to virtually pressing the left/right key one or more times instead repeat(steps) { onCodeInput(KeyCode.ARROW_RIGHT, Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE, false) } return true } } - if (inputLogic.moveCursorByAndReturnIfInsideComposingWord(moveSteps)) { + + // the shortcut below causes issues due to horrible handling of text fields by Firefox and forks + // issues: + // * setSelection "will cause the editor to call onUpdateSelection", see: https://developer.android.com/reference/android/view/inputmethod/InputConnection#setSelection(int,%20int) + // but Firefox is simply not doing this within the same word... WTF? + // https://github.com/Helium314/HeliBoard/issues/1139#issuecomment-2588169384 + // * inputType is NOT if variant InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT (variant appears to always be 0) + // so we can't even only do it for browsers (identifying by app name will break for forks) + // best "solution" is not doing this for InputType variation 0 but this applies to the majority of text fields... + val variation = InputType.TYPE_MASK_VARIATION and Settings.getValues().mInputAttributes.mInputType + if (variation != 0 && inputLogic.moveCursorByAndReturnIfInsideComposingWord(moveSteps)) { // no need to finish input and restart suggestions if we're still in the word - // this is a noticeable performance improvement - val newPosition = inputLogic.mConnection.expectedSelectionStart + moveSteps - inputLogic.mConnection.setSelection(newPosition, newPosition) + // this is a noticeable performance improvement when moving through long words + val newPosition = connection.expectedSelectionStart + moveSteps + connection.setSelection(newPosition, newPosition) return true } + inputLogic.finishInput() - val newPosition = inputLogic.mConnection.expectedSelectionStart + moveSteps - inputLogic.mConnection.setSelection(newPosition, newPosition) + val newPosition = connection.expectedSelectionStart + moveSteps + connection.setSelection(newPosition, newPosition) inputLogic.restartSuggestionsOnWordTouchedByCursor(settings.current, keyboardSwitcher.currentKeyboardScript) return true } + private fun positiveMoveSteps(text: CharSequence, steps: Int): Int { + var actualSteps = 0 + // corrected steps to avoid splitting chars belonging to the same codepoint + loopOverCodePoints(text) { cp, charCount -> + if (StringUtils.mightBeEmoji(cp)) return 0 + actualSteps += charCount + actualSteps >= steps + } + return min(actualSteps, text.length) + } + + private fun negativeMoveSteps(text: CharSequence, steps: Int): Int { + var actualSteps = 0 + // corrected steps to avoid splitting chars belonging to the same codepoint + loopOverCodePointsBackwards(text) { cp, charCount -> + if (StringUtils.mightBeEmoji(cp)) return 0 + actualSteps -= charCount + actualSteps <= steps + } + return -min(-actualSteps, text.length) + } } diff --git a/app/src/main/java/helium314/keyboard/keyboard/KeyboardLayoutSet.java b/app/src/main/java/helium314/keyboard/keyboard/KeyboardLayoutSet.java index 3344aa6eb..2bdbbdc97 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/KeyboardLayoutSet.java +++ b/app/src/main/java/helium314/keyboard/keyboard/KeyboardLayoutSet.java @@ -96,7 +96,7 @@ public final class KeyboardLayoutSet { public static void onSystemLocaleChanged() { clearKeyboardCache(); LocaleKeyboardInfosKt.clearCache(); - SubtypeLocaleUtils.clearDisplayNameCache(); + SubtypeLocaleUtils.clearSubtypeDisplayNameCache(); } public static void onKeyboardThemeChanged() { diff --git a/app/src/main/java/helium314/keyboard/keyboard/KeyboardSwitcher.java b/app/src/main/java/helium314/keyboard/keyboard/KeyboardSwitcher.java index aeb07b9e3..2b679dd26 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/KeyboardSwitcher.java +++ b/app/src/main/java/helium314/keyboard/keyboard/KeyboardSwitcher.java @@ -157,10 +157,9 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions { } catch (KeyboardLayoutSetException e) { Log.e(TAG, "loading keyboard failed: " + e.mKeyboardId, e.getCause()); try { - final InputMethodSubtype qwerty = SubtypeUtilsAdditional.INSTANCE - .createEmojiCapableAdditionalSubtype(mRichImm.getCurrentSubtypeLocale(), SubtypeLocaleUtils.QWERTY, true); + final InputMethodSubtype defaults = SubtypeUtilsAdditional.INSTANCE.createDefaultSubtype(mRichImm.getCurrentSubtypeLocale()); mKeyboardLayoutSet = builder.setKeyboardGeometry(keyboardWidth, keyboardHeight) - .setSubtype(RichInputMethodSubtype.Companion.get(qwerty)) + .setSubtype(RichInputMethodSubtype.Companion.get(defaults)) .setVoiceInputKeyEnabled(settingsValues.mShowsVoiceInputKey) .setNumberRowEnabled(settingsValues.mShowsNumberRow) .setLanguageSwitchKeyEnabled(settingsValues.isLanguageSwitchKeyEnabled()) @@ -169,9 +168,9 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions { .setOneHandedModeEnabled(oneHandedModeEnabled) .build(); mState.onLoadKeyboard(currentAutoCapsState, currentRecapitalizeState, oneHandedModeEnabled); - showToast("error loading the keyboard, falling back to qwerty", false); + showToast("error loading the keyboard, falling back to defaults", false); } catch (KeyboardLayoutSetException e2) { - Log.e(TAG, "even fallback to qwerty failed: " + e2.mKeyboardId, e2.getCause()); + Log.e(TAG, "even fallback to defaults failed: " + e2.mKeyboardId, e2.getCause()); } } } @@ -480,7 +479,6 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions { if (mKeyboardViewWrapper.getOneHandedModeEnabled() == enabled) { return; } - mEmojiPalettesView.clearKeyboardCache(); final Settings settings = Settings.getInstance(); mKeyboardViewWrapper.setOneHandedModeEnabled(enabled); mKeyboardViewWrapper.setOneHandedGravity(settings.getCurrent().mOneHandedModeGravity); @@ -515,9 +513,11 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions { } public void reloadKeyboard() { - if (mCurrentInputView != null) - loadKeyboard(mLatinIME.getCurrentInputEditorInfo(), Settings.getValues(), - mLatinIME.getCurrentAutoCapsState(), mLatinIME.getCurrentRecapitalizeState()); + if (mCurrentInputView == null) + return; + mEmojiPalettesView.clearKeyboardCache(); + loadKeyboard(mLatinIME.getCurrentInputEditorInfo(), Settings.getValues(), + mLatinIME.getCurrentAutoCapsState(), mLatinIME.getCurrentRecapitalizeState()); } /** @@ -644,6 +644,12 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions { } } + public void trimMemory() { + if (mEmojiPalettesView != null) { + mEmojiPalettesView.clearKeyboardCache(); + } + } + @SuppressLint("InflateParams") public View onCreateInputView(@NonNull Context displayContext, final boolean isHardwareAcceleratedDrawingEnabled) { if (mKeyboardView != null) { diff --git a/app/src/main/java/helium314/keyboard/keyboard/KeyboardTheme.kt b/app/src/main/java/helium314/keyboard/keyboard/KeyboardTheme.kt index 9a51bafa6..73d03ef00 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/KeyboardTheme.kt +++ b/app/src/main/java/helium314/keyboard/keyboard/KeyboardTheme.kt @@ -405,14 +405,7 @@ private constructor(val themeId: Int, @JvmField val mStyleId: Int) { } fun getUnusedThemeName(initialName: String, prefs: SharedPreferences): String { - val existingNames = prefs.all.keys.mapNotNull { - when { - it.startsWith(Settings.PREF_USER_COLORS_PREFIX) -> it.substringAfter(Settings.PREF_USER_COLORS_PREFIX) - it.startsWith(Settings.PREF_USER_ALL_COLORS_PREFIX) -> it.substringAfter(Settings.PREF_USER_ALL_COLORS_PREFIX) - it.startsWith(Settings.PREF_USER_MORE_COLORS_PREFIX) -> it.substringAfter(Settings.PREF_USER_MORE_COLORS_PREFIX) - else -> null - } - }.toSortedSet() + val existingNames = getExistingThemeNames(prefs) if (initialName !in existingNames) return initialName var i = 1 while ("$initialName$i" in existingNames) @@ -420,11 +413,8 @@ private constructor(val themeId: Int, @JvmField val mStyleId: Int) { return "$initialName$i" } - // returns false if not renamed due to invalid name or collision - fun renameUserColors(from: String, to: String, prefs: SharedPreferences): Boolean { - if (to.isBlank()) return false // don't want that - if (to == from) return true // nothing to do - val existingNames = prefs.all.keys.mapNotNull { + private fun getExistingThemeNames(prefs: SharedPreferences) = + prefs.all.keys.mapNotNull { when { it.startsWith(Settings.PREF_USER_COLORS_PREFIX) -> it.substringAfter(Settings.PREF_USER_COLORS_PREFIX) it.startsWith(Settings.PREF_USER_ALL_COLORS_PREFIX) -> it.substringAfter(Settings.PREF_USER_ALL_COLORS_PREFIX) @@ -432,6 +422,12 @@ private constructor(val themeId: Int, @JvmField val mStyleId: Int) { else -> null } }.toSortedSet() + + // returns false if not renamed due to invalid name or collision + fun renameUserColors(from: String, to: String, prefs: SharedPreferences): Boolean { + if (to.isBlank()) return false // don't want that + if (to == from) return true // nothing to do + val existingNames = getExistingThemeNames(prefs) if (to in existingNames) return false // all good, now rename prefs.edit { diff --git a/app/src/main/java/helium314/keyboard/keyboard/KeyboardView.java b/app/src/main/java/helium314/keyboard/keyboard/KeyboardView.java index 1c484dfbb..2df204403 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/KeyboardView.java +++ b/app/src/main/java/helium314/keyboard/keyboard/KeyboardView.java @@ -27,6 +27,7 @@ import android.view.View; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import helium314.keyboard.keyboard.emoji.EmojiPageKeyboardView; import helium314.keyboard.keyboard.internal.KeyDrawParams; import helium314.keyboard.keyboard.internal.KeyVisualAttributes; import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode; @@ -34,7 +35,7 @@ import helium314.keyboard.latin.R; import helium314.keyboard.latin.common.ColorType; import helium314.keyboard.latin.common.Colors; import helium314.keyboard.latin.common.Constants; -import helium314.keyboard.latin.common.StringUtils; +import helium314.keyboard.latin.common.StringUtilsKt; import helium314.keyboard.latin.settings.Settings; import helium314.keyboard.latin.suggestions.MoreSuggestions; import helium314.keyboard.latin.suggestions.PopupSuggestionsView; @@ -147,6 +148,7 @@ public class KeyboardView extends View { mPaint.setAntiAlias(true); mTypeface = Settings.getInstance().getCustomTypeface(); + setFitsSystemWindows(true); } @Nullable @@ -191,7 +193,8 @@ public class KeyboardView extends View { invalidateAllKeys(); requestLayout(); mFontSizeMultiplier = mKeyboard.mId.isEmojiKeyboard() - ? Settings.getValues().mFontSizeMultiplierEmoji + // In the case of EmojiKeyFit, the size of emojis is taken care of by the size of the keys + ? (Settings.getValues().mEmojiKeyFit? 1 : Settings.getValues().mFontSizeMultiplierEmoji) : Settings.getValues().mFontSizeMultiplier; } @@ -423,10 +426,14 @@ public class KeyboardView extends View { } if (key.isEnabled()) { - if (StringUtils.mightBeEmoji(label)) + if (StringUtilsKt.isEmoji(label)) paint.setColor(key.selectTextColor(params) | 0xFF000000); // ignore alpha for emojis (though actually color isn't applied anyway and we could just set white) else if (key.hasActionKeyBackground()) paint.setColor(mColors.get(ColorType.ACTION_KEY_ICON)); + else if (this instanceof EmojiPageKeyboardView) + paint.setColor(mColors.get(ColorType.EMOJI_KEY_TEXT)); + else if (this instanceof PopupKeysKeyboardView) + paint.setColor(mColors.get(ColorType.POPUP_KEY_TEXT)); else paint.setColor(key.selectTextColor(params)); // Set a drop shadow for the text if the shadow radius is positive value. @@ -610,7 +617,7 @@ public class KeyboardView extends View { } private void setKeyIconColor(Key key, Drawable icon, Keyboard keyboard) { - if (key.isAccentColored()) { + if (key.hasActionKeyBackground()) { mColors.setColor(icon, ColorType.ACTION_KEY_ICON); } else if (key.isShift() && keyboard != null) { if (keyboard.mId.mElementId == KeyboardId.ELEMENT_ALPHABET_MANUAL_SHIFTED @@ -624,8 +631,7 @@ public class KeyboardView extends View { } else if (key.getBackgroundType() != Key.BACKGROUND_TYPE_NORMAL) { mColors.setColor(icon, ColorType.KEY_ICON); } else if (this instanceof PopupKeysKeyboardView) { - // set color filter for long press comma key, should not trigger anywhere else - mColors.setColor(icon, ColorType.KEY_ICON); + mColors.setColor(icon, ColorType.POPUP_KEY_ICON); } else if (key.getCode() == Constants.CODE_SPACE || key.getCode() == KeyCode.ZWNJ) { // set color of default number pad space bar icon for Holo style, or for zero-width non-joiner (zwnj) on some layouts like nepal mColors.setColor(icon, ColorType.KEY_ICON); diff --git a/app/src/main/java/helium314/keyboard/keyboard/MainKeyboardView.java b/app/src/main/java/helium314/keyboard/keyboard/MainKeyboardView.java index 9239f5ea1..3a3fa3e16 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/MainKeyboardView.java +++ b/app/src/main/java/helium314/keyboard/keyboard/MainKeyboardView.java @@ -18,6 +18,7 @@ import android.graphics.Paint; import android.graphics.Paint.Align; import android.graphics.Typeface; import android.util.AttributeSet; +import android.view.ContextThemeWrapper; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; @@ -25,7 +26,6 @@ import android.view.ViewGroup; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.appcompat.view.ContextThemeWrapper; import helium314.keyboard.accessibility.AccessibilityUtils; import helium314.keyboard.accessibility.MainKeyboardAccessibilityDelegate; @@ -57,6 +57,7 @@ import helium314.keyboard.latin.settings.Settings; import helium314.keyboard.latin.utils.KtxKt; import helium314.keyboard.latin.utils.LanguageOnSpacebarUtils; import helium314.keyboard.latin.utils.Log; +import helium314.keyboard.latin.utils.SubtypeLocaleUtils; import helium314.keyboard.latin.utils.TypefaceUtils; import java.util.ArrayList; @@ -505,7 +506,7 @@ public final class MainKeyboardView extends KeyboardView implements DrawingProxy mPopupKeysKeyboardCache.put(key, popupKeysKeyboard); } - final View container = key.hasActionKeyBackground() ? mPopupKeysKeyboardForActionContainer + final View container = key.hasActionKeyPopups() ? mPopupKeysKeyboardForActionContainer : mPopupKeysKeyboardContainer; final PopupKeysKeyboardView popupKeysKeyboardView = container.findViewById(R.id.popup_keys_keyboard_view); diff --git a/app/src/main/java/helium314/keyboard/keyboard/PopupKeysKeyboard.java b/app/src/main/java/helium314/keyboard/keyboard/PopupKeysKeyboard.java index 113404375..645e420bb 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/PopupKeysKeyboard.java +++ b/app/src/main/java/helium314/keyboard/keyboard/PopupKeysKeyboard.java @@ -328,12 +328,13 @@ public final class PopupKeysKeyboard extends Keyboard { final PopupKeysKeyboardParams params = mParams; final int popupKeyFlags = mParentKey.getPopupKeyLabelFlags(); final PopupKeySpec[] popupKeys = mParentKey.getPopupKeys(); + final int background = mParentKey.hasActionKeyPopups() ? Key.BACKGROUND_TYPE_ACTION : Key.BACKGROUND_TYPE_NORMAL; for (int n = 0; n < popupKeys.length; n++) { final PopupKeySpec popupKeySpec = popupKeys[n]; final int row = n / params.mNumColumns; final int x = params.getX(n, row); final int y = params.getY(row); - final Key key = popupKeySpec.buildKey(x, y, popupKeyFlags, params); + final Key key = popupKeySpec.buildKey(x, y, popupKeyFlags, background, params); params.markAsEdgeKey(key, row); params.onAddKey(key); diff --git a/app/src/main/java/helium314/keyboard/keyboard/clipboard/ClipboardHistoryView.kt b/app/src/main/java/helium314/keyboard/keyboard/clipboard/ClipboardHistoryView.kt index 284616b44..0f0cb756f 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/clipboard/ClipboardHistoryView.kt +++ b/app/src/main/java/helium314/keyboard/keyboard/clipboard/ClipboardHistoryView.kt @@ -71,6 +71,7 @@ class ClipboardHistoryView @JvmOverloads constructor( getEnabledClipboardToolbarKeys(context.prefs()) .forEach { toolbarKeys.add(createToolbarKey(context, KeyboardIconsSet.instance, it)) } keyboardAttr.recycle() + fitsSystemWindows = true } override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { diff --git a/app/src/main/java/helium314/keyboard/keyboard/clipboard/ClipboardLayoutParams.kt b/app/src/main/java/helium314/keyboard/keyboard/clipboard/ClipboardLayoutParams.kt index 1eada9c2c..c5edd6ab5 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/clipboard/ClipboardLayoutParams.kt +++ b/app/src/main/java/helium314/keyboard/keyboard/clipboard/ClipboardLayoutParams.kt @@ -64,4 +64,4 @@ class ClipboardLayoutParams(ctx: Context) { view.layoutParams = this } } -} \ No newline at end of file +} diff --git a/app/src/main/java/helium314/keyboard/keyboard/emoji/DynamicGridKeyboard.java b/app/src/main/java/helium314/keyboard/keyboard/emoji/DynamicGridKeyboard.java index 599895a6c..6e9c4a36c 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/emoji/DynamicGridKeyboard.java +++ b/app/src/main/java/helium314/keyboard/keyboard/emoji/DynamicGridKeyboard.java @@ -11,6 +11,7 @@ import static helium314.keyboard.keyboard.internal.keyboard_parser.EmojiParserKt import android.content.SharedPreferences; import android.text.TextUtils; +import helium314.keyboard.latin.common.Constants; import helium314.keyboard.latin.settings.Defaults; import helium314.keyboard.latin.utils.Log; @@ -34,8 +35,6 @@ import java.util.List; */ final class DynamicGridKeyboard extends Keyboard { private static final String TAG = DynamicGridKeyboard.class.getSimpleName(); - private static final int TEMPLATE_KEY_CODE_0 = 0x30; - private static final int TEMPLATE_KEY_CODE_1 = 0x31; private final Object mLock = new Object(); private final SharedPreferences mPrefs; @@ -60,8 +59,8 @@ final class DynamicGridKeyboard extends Keyboard { mBaseWidth = width - paddingWidth; mOccupiedWidth = width; final float spacerWidth = Settings.getValues().mSplitKeyboardSpacerRelativeWidth * mBaseWidth; - final Key key0 = getTemplateKey(TEMPLATE_KEY_CODE_0); - final Key key1 = getTemplateKey(TEMPLATE_KEY_CODE_1); + final Key key0 = getTemplateKey(Constants.RECENTS_TEMPLATE_KEY_CODE_0); + final Key key1 = getTemplateKey(Constants.RECENTS_TEMPLATE_KEY_CODE_1); final int horizontalGap = Math.abs(key1.getX() - key0.getX()) - key0.getWidth(); final float widthScale = determineWidthScale(key0.getWidth() + horizontalGap); mHorizontalGap = (int) (horizontalGap * widthScale); @@ -213,7 +212,7 @@ final class DynamicGridKeyboard extends Keyboard { } // fall back to creating the key - return new Key(getTemplateKey(TEMPLATE_KEY_CODE_0), null, null, Key.BACKGROUND_TYPE_EMPTY, code, null); + return new Key(getTemplateKey(Constants.RECENTS_TEMPLATE_KEY_CODE_0), null, null, Key.BACKGROUND_TYPE_EMPTY, code, null); } private Key getKeyByOutputText(final Collection keyboards, @@ -227,7 +226,7 @@ final class DynamicGridKeyboard extends Keyboard { } // fall back to creating the key - return new Key(getTemplateKey(TEMPLATE_KEY_CODE_0), null, null, Key.BACKGROUND_TYPE_EMPTY, 0, outputText); + return new Key(getTemplateKey(Constants.RECENTS_TEMPLATE_KEY_CODE_0), null, null, Key.BACKGROUND_TYPE_EMPTY, 0, outputText); } public void loadRecentKeys(final Collection keyboards) { diff --git a/app/src/main/java/helium314/keyboard/keyboard/emoji/EmojiCategory.java b/app/src/main/java/helium314/keyboard/keyboard/emoji/EmojiCategory.java index 910fcb38a..d2a7213fd 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/emoji/EmojiCategory.java +++ b/app/src/main/java/helium314/keyboard/keyboard/emoji/EmojiCategory.java @@ -261,20 +261,6 @@ final class EmojiCategory { return 0; } - // Returns the view pager's page position for the categoryId - public int getPagerPageIdFromCategoryAndPageId(final int categoryId, final int categoryPageId) { - int sum = 0; - for (int i = 0; i < mShownCategories.size(); ++i) { - final CategoryProperties props = mShownCategories.get(i); - if (props.mCategoryId == categoryId) { - return sum + categoryPageId; - } - sum += props.getPageCount(); - } - Log.w(TAG, "categoryId not found: " + categoryId); - return 0; - } - public int getRecentTabId() { return getTabIdFromCategoryId(EmojiCategory.ID_RECENTS); } @@ -285,11 +271,11 @@ final class EmojiCategory { } // Returns a keyboard from the recycler view's adapter position. - public DynamicGridKeyboard getKeyboardFromAdapterPosition(final int position) { - if (position >= 0 && position < getCurrentCategoryPageCount()) { - return getKeyboard(mCurrentCategoryId, position); + public DynamicGridKeyboard getKeyboardFromAdapterPosition(int categoryId, final int position) { + if (position >= 0 && position < getCategoryPageCount(categoryId)) { + return getKeyboard(categoryId, position); } - Log.w(TAG, "invalid position for categoryId : " + mCurrentCategoryId); + Log.w(TAG, "invalid position for categoryId : " + categoryId); return null; } diff --git a/app/src/main/java/helium314/keyboard/keyboard/emoji/EmojiLayoutParams.kt b/app/src/main/java/helium314/keyboard/keyboard/emoji/EmojiLayoutParams.kt index 3444c8aad..b423ca44c 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/emoji/EmojiLayoutParams.kt +++ b/app/src/main/java/helium314/keyboard/keyboard/emoji/EmojiLayoutParams.kt @@ -8,7 +8,7 @@ package helium314.keyboard.keyboard.emoji import android.content.res.Resources import android.view.View import android.widget.LinearLayout -import androidx.recyclerview.widget.RecyclerView +import androidx.viewpager2.widget.ViewPager2 import helium314.keyboard.keyboard.internal.KeyboardParams import helium314.keyboard.latin.R import helium314.keyboard.latin.settings.Settings @@ -47,7 +47,7 @@ internal class EmojiLayoutParams(res: Resources) { emojiKeyboardHeight = emojiListHeight - emojiCategoryPageIdViewHeight - emojiListBottomMargin } - fun setEmojiListProperties(vp: RecyclerView) { + fun setEmojiListProperties(vp: ViewPager2) { val lp = vp.layoutParams as LinearLayout.LayoutParams lp.height = emojiKeyboardHeight lp.bottomMargin = emojiListBottomMargin diff --git a/app/src/main/java/helium314/keyboard/keyboard/emoji/EmojiPalettesAdapter.java b/app/src/main/java/helium314/keyboard/keyboard/emoji/EmojiPalettesAdapter.java index 7b3e02914..7f7b63614 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/emoji/EmojiPalettesAdapter.java +++ b/app/src/main/java/helium314/keyboard/keyboard/emoji/EmojiPalettesAdapter.java @@ -12,156 +12,32 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import helium314.keyboard.keyboard.Key; import helium314.keyboard.keyboard.Keyboard; -import helium314.keyboard.keyboard.KeyboardView; import helium314.keyboard.latin.R; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; -import helium314.keyboard.latin.settings.Settings; final class EmojiPalettesAdapter extends RecyclerView.Adapter{ private static final String TAG = EmojiPalettesAdapter.class.getSimpleName(); private static final boolean DEBUG_PAGER = false; + private final int mCategoryId; private final OnKeyEventListener mListener; - private final DynamicGridKeyboard mRecentsKeyboard; - private final SparseArray mActiveKeyboardViews = new SparseArray<>(); private final EmojiCategory mEmojiCategory; - private int mActivePosition = 0; - public EmojiPalettesAdapter(final EmojiCategory emojiCategory, - final OnKeyEventListener listener) { + public EmojiPalettesAdapter(final EmojiCategory emojiCategory, int categoryId, final OnKeyEventListener listener) { mEmojiCategory = emojiCategory; + mCategoryId = categoryId; mListener = listener; - mRecentsKeyboard = mEmojiCategory.getKeyboard(EmojiCategory.ID_RECENTS, 0); } - public void flushPendingRecentKeys() { - mRecentsKeyboard.flushPendingRecentKeys(); - final KeyboardView recentKeyboardView = - mActiveKeyboardViews.get(mEmojiCategory.getRecentTabId()); - if (recentKeyboardView != null) { - recentKeyboardView.invalidateAllKeys(); - } - } - - public void addRecentKey(final Key key) { - if (Settings.getValues().mIncognitoModeEnabled) { - // We do not want to log recent keys while being in incognito - return; - } - if (mEmojiCategory.isInRecentTab()) { - mRecentsKeyboard.addPendingKey(key); - return; - } - mRecentsKeyboard.addKeyFirst(key); - final KeyboardView recentKeyboardView = - mActiveKeyboardViews.get(mEmojiCategory.getRecentTabId()); - if (recentKeyboardView != null) { - recentKeyboardView.invalidateAllKeys(); - } - } - - public void onPageScrolled() { - releaseCurrentKey(false /* withKeyRegistering */); - } - - public void releaseCurrentKey(final boolean withKeyRegistering) { - // Make sure the delayed key-down event (highlight effect and haptic feedback) will be - // canceled. - final EmojiPageKeyboardView currentKeyboardView = - mActiveKeyboardViews.get(mActivePosition); - if (currentKeyboardView == null) { - return; - } - currentKeyboardView.releaseCurrentKey(withKeyRegistering); - } - -/* - @Override - public Object instantiateItem(final ViewGroup container, final int position) { - if (DEBUG_PAGER) { - Log.d(TAG, "instantiate item: " + position); - } - final EmojiPageKeyboardView oldKeyboardView = mActiveKeyboardViews.get(position); - if (oldKeyboardView != null) { - oldKeyboardView.deallocateMemory(); - // This may be redundant but wanted to be safer.. - mActiveKeyboardViews.remove(position); - } - final Keyboard keyboard = - mEmojiCategory.getKeyboardFromPagePosition(position); - final LayoutInflater inflater = LayoutInflater.from(container.getContext()); - final EmojiPageKeyboardView keyboardView = (EmojiPageKeyboardView) inflater.inflate( - R.layout.emoji_keyboard_page, container, false); - keyboardView.setKeyboard(keyboard); - keyboardView.setOnKeyEventListener(mListener); - container.addView(keyboardView); - mActiveKeyboardViews.put(position, keyboardView); - return keyboardView; - } - - @Override - public void setPrimaryItem(final ViewGroup container, final int position, - final Object object) { - if (mActivePosition == position) { - return; - } - final EmojiPageKeyboardView oldKeyboardView = mActiveKeyboardViews.get(mActivePosition); - if (oldKeyboardView != null) { - oldKeyboardView.releaseCurrentKey(false); - oldKeyboardView.deallocateMemory(); - } - mActivePosition = position; - } - - @Override - public boolean isViewFromObject(final View view, final Object object) { - return view == object; - } - - @Override - public void destroyItem(final ViewGroup container, final int position, - final Object object) { - if (DEBUG_PAGER) { - Log.d(TAG, "destroy item: " + position + ", " + object.getClass().getSimpleName()); - } - final EmojiPageKeyboardView keyboardView = mActiveKeyboardViews.get(position); - if (keyboardView != null) { - keyboardView.deallocateMemory(); - mActiveKeyboardViews.remove(position); - } - if (object instanceof View) { - container.removeView((View)object); - } else { - Log.w(TAG, "Warning!!! Emoji palette may be leaking. " + object); - } - } -*/ - @NonNull @Override public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - /*if (DEBUG_PAGER) { - Log.d(TAG, "instantiate item: " + viewType); - } - final EmojiPageKeyboardView oldKeyboardView = mActiveKeyboardViews.get(viewType); - if (oldKeyboardView != null) { - oldKeyboardView.deallocateMemory(); - // This may be redundant but wanted to be safer.. - mActiveKeyboardViews.remove(viewType); - } - final Keyboard keyboard = - mEmojiCategory.getKeyboardFromPagePosition(parent.getVerticalScrollbarPosition());*/ final LayoutInflater inflater = LayoutInflater.from(parent.getContext()); final EmojiPageKeyboardView keyboardView = (EmojiPageKeyboardView)inflater.inflate( R.layout.emoji_keyboard_page, parent, false); - /*keyboardView.setKeyboard(keyboard); - keyboardView.setOnKeyEventListener(mListener); - parent.addView(keyboardView); - mActiveKeyboardViews.put(parent.getVerticalScrollbarPosition(), keyboardView);*/ return new ViewHolder(keyboardView); } @@ -170,33 +46,22 @@ final class EmojiPalettesAdapter extends RecyclerView.Adapter { + private boolean mInitialized; + private Map mViews = new HashMap<>(mEmojiCategory.getShownCategories().size()); + + private PagerAdapter(ViewPager2 pager) { + setHasStableIds(true); + pager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() { + @Override + public void onPageSelected(int position) { + var categoryId = (int) getItemId(position); + setCurrentCategoryId(categoryId, false); + var recyclerView = mViews.get(position); + if (recyclerView != null) { + updateState(recyclerView, categoryId); + } + } + }); + } + + @Override + public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) { + recyclerView.setItemViewCacheSize(mEmojiCategory.getShownCategories().size()); + } + + @NonNull + @Override + public PagerViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + var view = LayoutInflater.from(parent.getContext()).inflate(R.layout.emoji_category_view, parent, false); + var viewHolder = new PagerViewHolder(view); + var emojiRecyclerView = getRecyclerView(view); + + emojiRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) { + super.onScrollStateChanged(recyclerView, newState); + // Ignore this message. Only want the actual page selected. + } + + @Override + public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { + updateState(recyclerView, viewHolder.mCategoryId); + } + }); + + emojiRecyclerView.setPersistentDrawingCache(PERSISTENT_NO_CACHE); + return viewHolder; + } + + @Override + public void onBindViewHolder(PagerViewHolder holder, int position) { + holder.mCategoryId = getItemId(position); + var recyclerView = getRecyclerView(holder.itemView); + mViews.put(position, recyclerView); + recyclerView.setAdapter(new EmojiPalettesAdapter(mEmojiCategory, (int) holder.mCategoryId, + EmojiPalettesView.this)); + + if (! mInitialized) { + recyclerView.scrollToPosition(mEmojiCategory.getCurrentCategoryPageId()); + mInitialized = true; + } + } + + @Override + public int getItemCount() { + return mEmojiCategory.getShownCategories().size(); + } + + @Override + public void onViewDetachedFromWindow(PagerViewHolder holder) { + if (holder.mCategoryId == EmojiCategory.ID_RECENTS) { + // Needs to save pending updates for recent keys when we get out of the recents + // category because we don't want to move the recent emojis around while the user + // is in the recents category. + getRecentsKeyboard().flushPendingRecentKeys(); + getRecyclerView(holder.itemView).getAdapter().notifyDataSetChanged(); + } + } + + @Override + public long getItemId(int position) { + return mEmojiCategory.getShownCategories().get(position).mCategoryId; + } + + private static RecyclerView getRecyclerView(View view) { + return view.findViewById(R.id.emoji_keyboard_list); + } + + private void updateState(@NonNull RecyclerView recyclerView, long categoryId) { + if (categoryId != mEmojiCategory.getCurrentCategoryId()) { + return; + } + + final int offset = recyclerView.computeVerticalScrollOffset(); + final int extent = recyclerView.computeVerticalScrollExtent(); + final int range = recyclerView.computeVerticalScrollRange(); + final float percentage = offset / (float) (range - extent); + + final int currentCategorySize = mEmojiCategory.getCurrentCategoryPageCount(); + final int a = (int) (percentage * currentCategorySize); + final float b = percentage * currentCategorySize - a; + mEmojiCategoryPageIndicatorView.setCategoryPageId(currentCategorySize, a, b); + + LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager(); + final int firstCompleteVisibleBoard = layoutManager.findFirstCompletelyVisibleItemPosition(); + final int firstVisibleBoard = layoutManager.findFirstVisibleItemPosition(); + mEmojiCategory.setCurrentCategoryPageId( + firstCompleteVisibleBoard > 0 ? firstCompleteVisibleBoard : firstVisibleBoard); + } + } + private boolean initialized = false; - // keep the indicator in case emoji view is changed to tabs / viewpager - private final boolean mCategoryIndicatorEnabled; - private final int mCategoryIndicatorDrawableResId; - private final int mCategoryIndicatorBackgroundResId; - private final int mCategoryPageIndicatorColor; private final Colors mColors; - private EmojiPalettesAdapter mEmojiPalettesAdapter; private final EmojiLayoutParams mEmojiLayoutParams; - private final LinearLayoutManager mEmojiLayoutManager; private LinearLayout mTabStrip; - private RecyclerView mEmojiRecyclerView; private EmojiCategoryPageIndicatorView mEmojiCategoryPageIndicatorView; private KeyboardActionListener mKeyboardActionListener = KeyboardActionListener.EMPTY_LISTENER; private final EmojiCategory mEmojiCategory; - - private ImageView mCurrentTab = null; + private ViewPager2 mPager; public EmojiPalettesView(final Context context, final AttributeSet attrs) { this(context, attrs, R.attr.emojiPalettesViewStyle); @@ -96,16 +208,8 @@ public final class EmojiPalettesView extends LinearLayout final TypedArray emojiPalettesViewAttr = context.obtainStyledAttributes(attrs, R.styleable.EmojiPalettesView, defStyle, R.style.EmojiPalettesView); mEmojiCategory = new EmojiCategory(context, layoutSet, emojiPalettesViewAttr); - mCategoryIndicatorEnabled = emojiPalettesViewAttr.getBoolean( - R.styleable.EmojiPalettesView_categoryIndicatorEnabled, false); - mCategoryIndicatorDrawableResId = emojiPalettesViewAttr.getResourceId( - R.styleable.EmojiPalettesView_categoryIndicatorDrawable, 0); - mCategoryIndicatorBackgroundResId = emojiPalettesViewAttr.getResourceId( - R.styleable.EmojiPalettesView_categoryIndicatorBackground, 0); - mCategoryPageIndicatorColor = emojiPalettesViewAttr.getColor( // todo: remove this and related attr - R.styleable.EmojiPalettesView_categoryPageIndicatorColor, 0); emojiPalettesViewAttr.recycle(); - mEmojiLayoutManager = new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false); + setFitsSystemWindows(true); } @Override @@ -121,13 +225,6 @@ public final class EmojiPalettesView extends LinearLayout setMeasuredDimension(width, height); } - // todo (maybe): bring back the holo indicator thing? - // just some 2 dp high strip - // would probably need a vertical linear layout - // better not, would complicate stuff again - // when decided to definitely not bring it back: - // remove mCategoryIndicatorEnabled, mCategoryIndicatorDrawableResId, mCategoryIndicatorBackgroundResId - // and the attrs categoryIndicatorDrawable, categoryIndicatorEnabled, categoryIndicatorBackground (and the connected drawables) private void addTab(final LinearLayout host, final int categoryId) { final ImageView iconView = new ImageView(getContext()); mColors.setBackground(iconView, ColorType.STRIP_BACKGROUND); @@ -149,59 +246,14 @@ public final class EmojiPalettesView extends LinearLayout for (final EmojiCategory.CategoryProperties properties : mEmojiCategory.getShownCategories()) { addTab(mTabStrip, properties.mCategoryId); } -// mTabStrip.setOnTabChangedListener(this); // now onClickListener -/* final TabWidget tabWidget = mTabStrip.getTabWidget(); - tabWidget.setStripEnabled(mCategoryIndicatorEnabled); - if (mCategoryIndicatorEnabled) { - // On TabWidget's strip, what looks like an indicator is actually a background. - // And what looks like a background are actually left and right drawables. - tabWidget.setBackgroundResource(mCategoryIndicatorDrawableResId); - tabWidget.setLeftStripDrawable(mCategoryIndicatorBackgroundResId); - tabWidget.setRightStripDrawable(mCategoryIndicatorBackgroundResId); - tabWidget.setBackgroundColor(mColors.get(ColorType.EMOJI_CATEGORY_SELECTED)); - } -*/ - mEmojiPalettesAdapter = new EmojiPalettesAdapter(mEmojiCategory, this); - - mEmojiRecyclerView = findViewById(R.id.emoji_keyboard_list); - mEmojiRecyclerView.setLayoutManager(mEmojiLayoutManager); - mEmojiRecyclerView.setAdapter(mEmojiPalettesAdapter); - mEmojiRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { - @Override - public void onScrollStateChanged(@NonNull @NotNull RecyclerView recyclerView, int newState) { - super.onScrollStateChanged(recyclerView, newState); - // Ignore this message. Only want the actual page selected. - } - - @Override - public void onScrolled(@NonNull @NotNull RecyclerView recyclerView, int dx, int dy) { - super.onScrolled(recyclerView, dx, dy); - mEmojiPalettesAdapter.onPageScrolled(); - - final int offset = recyclerView.computeVerticalScrollOffset(); - final int extent = recyclerView.computeVerticalScrollExtent(); - final int range = recyclerView.computeVerticalScrollRange(); - final float percentage = offset / (float) (range - extent); - - final int currentCategorySize = mEmojiCategory.getCurrentCategoryPageCount(); - final int a = (int) (percentage * currentCategorySize); - final float b = percentage * currentCategorySize - a; - mEmojiCategoryPageIndicatorView.setCategoryPageId(currentCategorySize, a, b); - - final int firstCompleteVisibleBoard = mEmojiLayoutManager.findFirstCompletelyVisibleItemPosition(); - final int firstVisibleBoard = mEmojiLayoutManager.findFirstVisibleItemPosition(); - mEmojiCategory.setCurrentCategoryPageId( - firstCompleteVisibleBoard > 0 ? firstCompleteVisibleBoard : firstVisibleBoard); - } - }); - - mEmojiRecyclerView.setPersistentDrawingCache(PERSISTENT_NO_CACHE); - mEmojiLayoutParams.setEmojiListProperties(mEmojiRecyclerView); + mPager = findViewById(R.id.emoji_pager); + mPager.setAdapter(new PagerAdapter(mPager)); + mEmojiLayoutParams.setEmojiListProperties(mPager); mEmojiCategoryPageIndicatorView = findViewById(R.id.emoji_category_page_id_view); mEmojiLayoutParams.setCategoryPageIdViewProperties(mEmojiCategoryPageIndicatorView); - setCurrentCategoryAndPageId(mEmojiCategory.getCurrentCategoryId(), mEmojiCategory.getCurrentCategoryPageId(), true); + setCurrentCategoryId(mEmojiCategory.getCurrentCategoryId(), true); mEmojiCategoryPageIndicatorView.setColors(mColors.get(ColorType.EMOJI_CATEGORY_SELECTED), mColors.get(ColorType.STRIP_BACKGROUND)); initialized = true; @@ -219,7 +271,7 @@ public final class EmojiPalettesView extends LinearLayout AudioAndHapticFeedbackManager.getInstance().performHapticAndAudioFeedback(KeyCode.NOT_SPECIFIED, this); final int categoryId = ((Long) tag).intValue(); if (categoryId != mEmojiCategory.getCurrentCategoryId()) { - setCurrentCategoryAndPageId(categoryId, 0, false); + setCurrentCategoryId(categoryId, false); updateEmojiCategoryPageIdView(); } } @@ -244,7 +296,7 @@ public final class EmojiPalettesView extends LinearLayout */ @Override public void onReleaseKey(final Key key) { - mEmojiPalettesAdapter.addRecentKey(key); + addRecentKey(key); final int code = key.getCode(); if (code == KeyCode.MULTIPLE_CODE_POINTS) { mKeyboardActionListener.onTextInput(key.getOutputText()); @@ -269,13 +321,22 @@ public final class EmojiPalettesView extends LinearLayout setupBottomRowKeyboard(editorInfo, keyboardActionListener); final KeyDrawParams params = new KeyDrawParams(); params.updateParams(mEmojiLayoutParams.getBottomRowKeyboardHeight(), keyVisualAttr); - if (mEmojiRecyclerView.getAdapter() == null) { - mEmojiRecyclerView.setAdapter(mEmojiPalettesAdapter); - setCurrentCategoryAndPageId(mEmojiCategory.getCurrentCategoryId(), mEmojiCategory.getCurrentCategoryPageId(), true); - } setupSidePadding(); } + private void addRecentKey(final Key key) { + if (Settings.getValues().mIncognitoModeEnabled) { + // We do not want to log recent keys while being in incognito + return; + } + if (mEmojiCategory.isInRecentTab()) { + getRecentsKeyboard().addPendingKey(key); + return; + } + getRecentsKeyboard().addKeyFirst(key); + mPager.getAdapter().notifyItemChanged(mEmojiCategory.getRecentTabId()); + } + private void setupBottomRowKeyboard(final EditorInfo editorInfo, final KeyboardActionListener keyboardActionListener) { MainKeyboardView keyboardView = findViewById(R.id.bottom_row_keyboard); keyboardView.setKeyboardActionListener(keyboardActionListener); @@ -295,11 +356,11 @@ public final class EmojiPalettesView extends LinearLayout final float rightPadding = keyboardAttr.getFraction(R.styleable.Keyboard_keyboardRightPadding, keyboardWidth, keyboardWidth, 0f) * sv.mSidePaddingScale; keyboardAttr.recycle(); - mEmojiRecyclerView.setPadding( + mPager.setPadding( (int) leftPadding, - mEmojiRecyclerView.getPaddingTop(), + mPager.getPaddingTop(), (int) rightPadding, - mEmojiRecyclerView.getPaddingBottom() + mPager.getPaddingBottom() ); mEmojiCategoryPageIndicatorView.setPadding( (int) leftPadding, @@ -312,9 +373,11 @@ public final class EmojiPalettesView extends LinearLayout public void stopEmojiPalettes() { if (!initialized) return; - mEmojiPalettesAdapter.releaseCurrentKey(true); - mEmojiPalettesAdapter.flushPendingRecentKeys(); - mEmojiRecyclerView.setAdapter(null); + getRecentsKeyboard().flushPendingRecentKeys(); + } + + private DynamicGridKeyboard getRecentsKeyboard() { + return mEmojiCategory.getKeyboard(EmojiCategory.ID_RECENTS, 0); } public void setKeyboardActionListener(final KeyboardActionListener listener) { @@ -330,34 +393,33 @@ public final class EmojiPalettesView extends LinearLayout mEmojiCategory.getCurrentCategoryPageId(), 0.0f); } - private void setCurrentCategoryAndPageId(final int categoryId, final int categoryPageId, final boolean force) { + private void setCurrentCategoryId(final int categoryId, final boolean initial) { final int oldCategoryId = mEmojiCategory.getCurrentCategoryId(); - final int oldCategoryPageId = mEmojiCategory.getCurrentCategoryPageId(); - - if (oldCategoryId == EmojiCategory.ID_RECENTS && categoryId != EmojiCategory.ID_RECENTS) { - // Needs to save pending updates for recent keys when we get out of the recents - // category because we don't want to move the recent emojis around while the user - // is in the recents category. - mEmojiPalettesAdapter.flushPendingRecentKeys(); - } - - if (force || oldCategoryId != categoryId || oldCategoryPageId != categoryPageId) { + if (initial || oldCategoryId != categoryId) { mEmojiCategory.setCurrentCategoryId(categoryId); - mEmojiCategory.setCurrentCategoryPageId(categoryPageId); - mEmojiPalettesAdapter.notifyDataSetChanged(); - mEmojiRecyclerView.scrollToPosition(categoryPageId); + + if (mPager.getScrollState() != ViewPager2.SCROLL_STATE_DRAGGING) { + // Not swiping + mPager.setCurrentItem(mEmojiCategory.getTabIdFromCategoryId( + mEmojiCategory.getCurrentCategoryId()), ! initial); + } + + final View old = mTabStrip.findViewWithTag((long) oldCategoryId); + final View current = mTabStrip.findViewWithTag((long) categoryId); + + if (old instanceof ImageView) + Settings.getValues().mColors.setColor((ImageView) old, ColorType.EMOJI_CATEGORY); + if (current instanceof ImageView) + Settings.getValues().mColors.setColor((ImageView) current, ColorType.EMOJI_CATEGORY_SELECTED); } - - final View old = mTabStrip.findViewWithTag((long) oldCategoryId); - final View current = mTabStrip.findViewWithTag((long) categoryId); - - if (old instanceof ImageView) - Settings.getValues().mColors.setColor((ImageView) old, ColorType.EMOJI_CATEGORY); - if (current instanceof ImageView) - Settings.getValues().mColors.setColor((ImageView) current, ColorType.EMOJI_CATEGORY_SELECTED); } public void clearKeyboardCache() { + if (!initialized) { + return; + } + mEmojiCategory.clearKeyboardCache(); + mPager.getAdapter().notifyDataSetChanged(); } -} \ No newline at end of file +} diff --git a/app/src/main/java/helium314/keyboard/keyboard/emoji/SupportedEmojis.kt b/app/src/main/java/helium314/keyboard/keyboard/emoji/SupportedEmojis.kt new file mode 100644 index 000000000..831017267 --- /dev/null +++ b/app/src/main/java/helium314/keyboard/keyboard/emoji/SupportedEmojis.kt @@ -0,0 +1,24 @@ +package helium314.keyboard.keyboard.emoji + +import android.content.Context +import helium314.keyboard.latin.settings.Defaults +import helium314.keyboard.latin.settings.Settings +import helium314.keyboard.latin.utils.Log +import helium314.keyboard.latin.utils.prefs + +object SupportedEmojis { + private val unsupportedEmojis = hashSetOf() + + fun load(context: Context) { + val maxSdk = context.prefs().getInt(Settings.PREF_EMOJI_MAX_SDK, Defaults.PREF_EMOJI_MAX_SDK) + unsupportedEmojis.clear() + context.assets.open("emoji/minApi.txt").reader().readLines().forEach { + val s = it.split(" ") + val minApi = s.first().toInt() + if (minApi > maxSdk) + unsupportedEmojis.addAll(s.drop(1)) + } + } + + fun isUnsupported(emoji: String) = emoji in unsupportedEmojis +} diff --git a/app/src/main/java/helium314/keyboard/keyboard/internal/KeyPreviewChoreographer.java b/app/src/main/java/helium314/keyboard/keyboard/internal/KeyPreviewChoreographer.java index 718d1f8c4..6dcfef34c 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/internal/KeyPreviewChoreographer.java +++ b/app/src/main/java/helium314/keyboard/keyboard/internal/KeyPreviewChoreographer.java @@ -108,7 +108,7 @@ public final class KeyPreviewChoreographer { final boolean hasPopupKeys = (key.getPopupKeys() != null); keyPreviewView.setPreviewBackground(hasPopupKeys, keyPreviewPosition); final Colors colors = Settings.getValues().mColors; - colors.setBackground(keyPreviewView, ColorType.KEY_PREVIEW); + colors.setBackground(keyPreviewView, ColorType.KEY_PREVIEW_BACKGROUND); // The key preview is placed vertically above the top edge of the parent key with an // arbitrary offset. diff --git a/app/src/main/java/helium314/keyboard/keyboard/internal/KeyPreviewView.java b/app/src/main/java/helium314/keyboard/keyboard/internal/KeyPreviewView.java index c7069ec0f..64ef4bfea 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/internal/KeyPreviewView.java +++ b/app/src/main/java/helium314/keyboard/keyboard/internal/KeyPreviewView.java @@ -15,8 +15,7 @@ import android.text.TextUtils; import android.util.AttributeSet; import android.util.TypedValue; import android.view.Gravity; - -import androidx.appcompat.widget.AppCompatTextView; +import android.widget.TextView; import helium314.keyboard.keyboard.Key; import helium314.keyboard.latin.R; @@ -25,10 +24,9 @@ import helium314.keyboard.latin.settings.Settings; import java.util.HashSet; -/** - * The pop up key preview view. - */ -public class KeyPreviewView extends AppCompatTextView { +/** The pop up key preview view. */ +// Android Studio complains about TextView, but we're not using tint or auto-size that should be the relevant differences +public class KeyPreviewView extends TextView { public static final int POSITION_MIDDLE = 0; public static final int POSITION_LEFT = 1; public static final int POSITION_RIGHT = 2; diff --git a/app/src/main/java/helium314/keyboard/keyboard/internal/KeyVisualAttributes.java b/app/src/main/java/helium314/keyboard/keyboard/internal/KeyVisualAttributes.java index ee76f94ee..2e8b172cd 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/internal/KeyVisualAttributes.java +++ b/app/src/main/java/helium314/keyboard/keyboard/internal/KeyVisualAttributes.java @@ -129,7 +129,7 @@ public final class KeyVisualAttributes { // when? -> hasShiftedLetterHint and isShiftedLetterActivated -> both are label flags mShiftedLetterHintActivatedColor = keyAttr.getColor( R.styleable.Keyboard_Key_keyShiftedLetterHintActivatedColor, 0); - mPreviewTextColor = colors.get(ColorType.KEY_TEXT); + mPreviewTextColor = colors.get(ColorType.KEY_PREVIEW_TEXT); mHintLabelVerticalAdjustment = ResourceUtils.getFraction(keyAttr, R.styleable.Keyboard_Key_keyHintLabelVerticalAdjustment, 0.0f); diff --git a/app/src/main/java/helium314/keyboard/keyboard/internal/KeyboardBuilder.kt b/app/src/main/java/helium314/keyboard/keyboard/internal/KeyboardBuilder.kt index f28aaecfb..a8e43f294 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/internal/KeyboardBuilder.kt +++ b/app/src/main/java/helium314/keyboard/keyboard/internal/KeyboardBuilder.kt @@ -48,7 +48,7 @@ open class KeyboardBuilder(protected val mContext: Context, if (id.isEmojiKeyboard) { mParams.mAllowRedundantPopupKeys = true readAttributes(R.xml.kbd_emoji) - keysInRows = EmojiParser(mParams, mContext, Settings.getValues().mEmojiMaxSdk).parse() + keysInRows = EmojiParser(mParams, mContext).parse() } else { try { setupParams() @@ -176,7 +176,7 @@ open class KeyboardBuilder(protected val mContext: Context, val relativeWidthSumNew = row.sumOf { it.mWidth } val widthFactor = relativeWidthSum / relativeWidthSumNew // re-calculate absolute sizes and positions - var currentX = 0f + var currentX = mParams.mLeftPadding.toFloat() row.forEach { it.mWidth *= widthFactor it.setAbsoluteDimensions(currentX, y) diff --git a/app/src/main/java/helium314/keyboard/keyboard/internal/KeyboardState.java b/app/src/main/java/helium314/keyboard/keyboard/internal/KeyboardState.java index 51dc98b0d..07639d3fa 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/internal/KeyboardState.java +++ b/app/src/main/java/helium314/keyboard/keyboard/internal/KeyboardState.java @@ -80,6 +80,7 @@ public final class KeyboardState { private static final int SWITCH_STATE_SYMBOL_BEGIN = 1; private static final int SWITCH_STATE_SYMBOL = 2; private static final int SWITCH_STATE_NUMPAD = 3; + private static final int SWITCH_STATE_NUMPAD_BEGIN = 9; private static final int SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL = 4; private static final int SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE = 5; private static final int SWITCH_STATE_MOMENTARY_ALPHA_SHIFT = 6; @@ -403,7 +404,7 @@ public final class KeyboardState { mMode = MODE_NUMPAD; mRecapitalizeMode = RecapitalizeStatus.NOT_A_RECAPITALIZE_MODE; mSwitchActions.setNumpadKeyboard(); - mSwitchState = withSliding ? SWITCH_STATE_MOMENTARY_TO_NUMPAD : SWITCH_STATE_NUMPAD; + mSwitchState = withSliding ? SWITCH_STATE_MOMENTARY_TO_NUMPAD : SWITCH_STATE_NUMPAD_BEGIN; } public void toggleNumpad(final boolean withSliding, final int autoCapsFlags, final int recapitalizeMode, @@ -789,6 +790,17 @@ public final class KeyboardState { mPrevSymbolsKeyboardWasShifted = false; } break; + case SWITCH_STATE_NUMPAD: + // Switch back to alpha keyboard mode if user types one or more non-space/enter + // characters followed by a space/enter. + if (isSpaceOrEnter(code) && Settings.getValues().mAlphaAfterNumpadAndSpace) { + toggleNumpad(false, autoCapsFlags, recapitalizeMode, true, false); + } + break; + case SWITCH_STATE_NUMPAD_BEGIN: + if (!isSpaceOrEnter(code)) + mSwitchState = SWITCH_STATE_NUMPAD; + break; } // If the code is a letter, update keyboard shift state. @@ -833,6 +845,7 @@ public final class KeyboardState { case SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE -> "MOMENTARY-SYMBOL-MORE"; case SWITCH_STATE_MOMENTARY_ALPHA_SHIFT -> "MOMENTARY-ALPHA_SHIFT"; case SWITCH_STATE_NUMPAD -> "NUMPAD"; + case SWITCH_STATE_NUMPAD_BEGIN -> "NUMPAD-BEGIN"; case SWITCH_STATE_MOMENTARY_TO_NUMPAD -> "MOMENTARY-TO-NUMPAD"; case SWITCH_STATE_MOMENTARY_FROM_NUMPAD -> "MOMENTARY-FROM-NUMPAD"; default -> null; diff --git a/app/src/main/java/helium314/keyboard/keyboard/internal/PopupKeySpec.java b/app/src/main/java/helium314/keyboard/keyboard/internal/PopupKeySpec.java index a1b41b79c..695a660af 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/internal/PopupKeySpec.java +++ b/app/src/main/java/helium314/keyboard/keyboard/internal/PopupKeySpec.java @@ -68,11 +68,9 @@ public final class PopupKeySpec { } @NonNull - public Key buildKey(final int x, final int y, final int labelFlags, - @NonNull final KeyboardParams params) { - return new Key(mLabel, mIconName, mCode, mOutputText, null /* hintLabel */, labelFlags, - Key.BACKGROUND_TYPE_NORMAL, x, y, params.mDefaultAbsoluteKeyWidth, params.mDefaultAbsoluteRowHeight, - params.mHorizontalGap, params.mVerticalGap); + public Key buildKey(final int x, final int y, final int labelFlags, final int background, @NonNull final KeyboardParams params) { + return new Key(mLabel, mIconName, mCode, mOutputText, null, labelFlags, background, x, y, + params.mDefaultAbsoluteKeyWidth, params.mDefaultAbsoluteRowHeight, params.mHorizontalGap, params.mVerticalGap); } @Override diff --git a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/EmojiParser.kt b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/EmojiParser.kt index 165b506fb..35ab32dfe 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/EmojiParser.kt +++ b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/EmojiParser.kt @@ -5,38 +5,63 @@ import android.content.Context import helium314.keyboard.keyboard.Key import helium314.keyboard.keyboard.Key.KeyParams import helium314.keyboard.keyboard.KeyboardId +import helium314.keyboard.keyboard.emoji.SupportedEmojis import helium314.keyboard.keyboard.internal.KeyboardParams import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode import helium314.keyboard.latin.R +import helium314.keyboard.latin.common.Constants import helium314.keyboard.latin.common.StringUtils +import helium314.keyboard.latin.common.splitOnWhitespace +import helium314.keyboard.latin.settings.Defaults import helium314.keyboard.latin.settings.Settings import helium314.keyboard.latin.utils.ResourceUtils +import helium314.keyboard.latin.utils.prefs +import java.util.Collections import kotlin.math.sqrt -class EmojiParser(private val params: KeyboardParams, private val context: Context, private val maxSdk: Int) { +class EmojiParser(private val params: KeyboardParams, private val context: Context) { fun parse(): ArrayList> { - val emojiArrayId = when (params.mId.mElementId) { - KeyboardId.ELEMENT_EMOJI_RECENTS -> R.array.emoji_recents - KeyboardId.ELEMENT_EMOJI_CATEGORY1 -> R.array.emoji_smileys_emotion - KeyboardId.ELEMENT_EMOJI_CATEGORY2 -> R.array.emoji_people_body - KeyboardId.ELEMENT_EMOJI_CATEGORY3 -> R.array.emoji_animals_nature - KeyboardId.ELEMENT_EMOJI_CATEGORY4 -> R.array.emoji_food_drink - KeyboardId.ELEMENT_EMOJI_CATEGORY5 -> R.array.emoji_travel_places - KeyboardId.ELEMENT_EMOJI_CATEGORY6 -> R.array.emoji_activities - KeyboardId.ELEMENT_EMOJI_CATEGORY7 -> R.array.emoji_objects - KeyboardId.ELEMENT_EMOJI_CATEGORY8 -> R.array.emoji_symbols - KeyboardId.ELEMENT_EMOJI_CATEGORY9 -> R.array.emoji_flags - KeyboardId.ELEMENT_EMOJI_CATEGORY10 -> R.array.emoji_emoticons - else -> throw(IllegalStateException("can only parse emoji categories where an array exists")) + val emojiFileName = when (params.mId.mElementId) { + KeyboardId.ELEMENT_EMOJI_CATEGORY1 -> "SMILEYS_AND_EMOTION.txt" + KeyboardId.ELEMENT_EMOJI_CATEGORY2 -> "PEOPLE_AND_BODY.txt" + KeyboardId.ELEMENT_EMOJI_CATEGORY3 -> "ANIMALS_AND_NATURE.txt" + KeyboardId.ELEMENT_EMOJI_CATEGORY4 -> "FOOD_AND_DRINK.txt" + KeyboardId.ELEMENT_EMOJI_CATEGORY5 -> "TRAVEL_AND_PLACES.txt" + KeyboardId.ELEMENT_EMOJI_CATEGORY6 -> "ACTIVITIES.txt" + KeyboardId.ELEMENT_EMOJI_CATEGORY7 -> "OBJECTS.txt" + KeyboardId.ELEMENT_EMOJI_CATEGORY8 -> "SYMBOLS.txt" + KeyboardId.ELEMENT_EMOJI_CATEGORY9 -> "FLAGS.txt" + KeyboardId.ELEMENT_EMOJI_CATEGORY10 -> "EMOTICONS.txt" + else -> null } - val emojiArray = context.resources.getStringArray(emojiArrayId) - val popupEmojisArray = if (params.mId.mElementId != KeyboardId.ELEMENT_EMOJI_CATEGORY2) null - else context.resources.getStringArray(R.array.emoji_people_body_more) - if (popupEmojisArray != null && emojiArray.size != popupEmojisArray.size) - throw(IllegalStateException("Inconsistent array size between codesArray and popupKeysArray")) + val emojiLines = if (emojiFileName == null) { + listOf( // special template keys for recents category + StringUtils.newSingleCodePointString(Constants.RECENTS_TEMPLATE_KEY_CODE_0), + StringUtils.newSingleCodePointString(Constants.RECENTS_TEMPLATE_KEY_CODE_1), + ) + } else { + context.assets.open("emoji/$emojiFileName").reader().use { it.readLines() } + } + val defaultSkinTone = context.prefs().getString(Settings.PREF_EMOJI_SKIN_TONE, Defaults.PREF_EMOJI_SKIN_TONE)!! + if (params.mId.mElementId == KeyboardId.ELEMENT_EMOJI_CATEGORY2 && defaultSkinTone != "") { + // adjust PEOPLE_AND_BODY if we have a non-yellow default skin tone + val modifiedLines = emojiLines.map { + val split = it.splitOnWhitespace().toMutableList() + // find the line containing the skin tone, and swap with first + val foundIndex = split.indexOfFirst { it.contains(defaultSkinTone) } + if (foundIndex > 0) { + Collections.swap(split, 0, foundIndex) + } + split.joinToString(" ") + } + return parseLines(modifiedLines) + } + return parseLines(emojiLines) + } - val row = ArrayList(emojiArray.size) + private fun parseLines(lines: List): ArrayList> { + val row = ArrayList(lines.size) var currentX = params.mLeftPadding.toFloat() val currentY = params.mTopPadding.toFloat() // no need to ever change, assignment to rows into rows is done in DynamicGridKeyboard @@ -44,14 +69,20 @@ class EmojiParser(private val params: KeyboardParams, private val context: Conte // this is a bit long, but ensures that emoji size stays the same, independent of these settings // we also ignore side padding for key width, and prefer fewer keys per row over narrower keys val defaultKeyWidth = ResourceUtils.getDefaultKeyboardWidth(context) * params.mDefaultKeyWidth - val keyWidth = defaultKeyWidth * sqrt(Settings.getValues().mKeyboardHeightScale) + var keyWidth = defaultKeyWidth * sqrt(Settings.getValues().mKeyboardHeightScale) val defaultKeyboardHeight = ResourceUtils.getDefaultKeyboardHeight(context.resources, false) val defaultBottomPadding = context.resources.getFraction(R.fraction.config_keyboard_bottom_padding_holo, defaultKeyboardHeight, defaultKeyboardHeight) val emojiKeyboardHeight = ResourceUtils.getDefaultKeyboardHeight(context.resources, false) * 0.75f + params.mVerticalGap - defaultBottomPadding - context.resources.getDimensionPixelSize(R.dimen.config_emoji_category_page_id_height) - val keyHeight = emojiKeyboardHeight * params.mDefaultRowHeight * Settings.getValues().mKeyboardHeightScale // still apply height scale to key + var keyHeight = emojiKeyboardHeight * params.mDefaultRowHeight * Settings.getValues().mKeyboardHeightScale // still apply height scale to key - emojiArray.forEachIndexed { i, codeArraySpec -> - val keyParams = parseEmojiKey(codeArraySpec, popupEmojisArray?.get(i)?.takeIf { it.isNotEmpty() }) ?: return@forEachIndexed + if (Settings.getValues().mEmojiKeyFit) { + keyWidth *= Settings.getValues().mFontSizeMultiplierEmoji + keyHeight *= Settings.getValues().mFontSizeMultiplierEmoji + } + + + lines.forEach { line -> + val keyParams = parseEmojiKeyNew(line) ?: return@forEach keyParams.xPos = currentX keyParams.yPos = currentY keyParams.mAbsoluteWidth = keyWidth @@ -62,44 +93,30 @@ class EmojiParser(private val params: KeyboardParams, private val context: Conte return arrayListOf(row) } - private fun getLabelAndCode(spec: String): Pair? { - val specAndSdk = spec.split("||") - if (specAndSdk.getOrNull(1)?.toIntOrNull()?.let { it > maxSdk } == true) return null - if ("," !in specAndSdk.first()) { - val code = specAndSdk.first().toIntOrNull(16) ?: return specAndSdk.first() to KeyCode.MULTIPLE_CODE_POINTS // text emojis - val label = StringUtils.newSingleCodePointString(code) - return label to code + private fun parseEmojiKeyNew(line: String): KeyParams? { + if (!line.contains(" ") || params.mId.mElementId == KeyboardId.ELEMENT_EMOJI_CATEGORY10) { + // single emoji without popups, or emoticons (there is one that contains space...) + return if (SupportedEmojis.isUnsupported(line)) null + else KeyParams(line, line.getCode(), null, null, Key.LABEL_FLAGS_FONT_NORMAL, params) } - val labelBuilder = StringBuilder() - for (codePointString in specAndSdk.first().split(",")) { - val cp = codePointString.toInt(16) - labelBuilder.appendCodePoint(cp) - } - return labelBuilder.toString() to KeyCode.MULTIPLE_CODE_POINTS - } - - private fun parseEmojiKey(spec: String, popupKeysString: String? = null): KeyParams? { - val (label, code) = getLabelAndCode(spec) ?: return null - val sb = StringBuilder() - popupKeysString?.split(";")?.let { popupKeys -> - popupKeys.forEach { - val (mkLabel, _) = getLabelAndCode(it) ?: return@forEach - sb.append(mkLabel).append(",") - } - } - val popupKeysSpec = if (sb.isNotEmpty()) { - sb.deleteCharAt(sb.length - 1) - sb.toString() - } else null + val split = line.split(" ") + val label = split.first() + if (SupportedEmojis.isUnsupported(label)) return null + val popupKeysSpec = split.drop(1).filterNot { SupportedEmojis.isUnsupported(it) } + .takeIf { it.isNotEmpty() }?.joinToString(",") return KeyParams( label, - code, + label.getCode(), if (popupKeysSpec != null) EMOJI_HINT_LABEL else null, popupKeysSpec, Key.LABEL_FLAGS_FONT_NORMAL, params ) } + + private fun String.getCode(): Int = + if (StringUtils.codePointCount(this) != 1) KeyCode.MULTIPLE_CODE_POINTS + else Character.codePointAt(this, 0) } -const val EMOJI_HINT_LABEL = "◥" \ No newline at end of file +const val EMOJI_HINT_LABEL = "◥" diff --git a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/KeyboardParser.kt b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/KeyboardParser.kt index 999716ac6..4cea8ac1e 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/KeyboardParser.kt +++ b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/KeyboardParser.kt @@ -237,7 +237,7 @@ class KeyboardParser(private val params: KeyboardParams, private val context: Co { it.label == KeyLabel.PERIOD || it.groupId == KeyData.GROUP_PERIOD}, { baseKeys.last()[1].copy(newGroupId = 2, newType = baseKeys.last()[1].type ?: it.type) } ) - baseKeys.removeLast() + baseKeys.removeAt(baseKeys.lastIndex) } // add zwnj key next to space if necessary val spaceIndex = functionalKeysBottom.indexOfFirst { it.label == KeyLabel.SPACE && it.width <= 0 } // width could be 0 or -1 diff --git a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/LayoutParser.kt b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/LayoutParser.kt index 3164cc698..d2b51fb92 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/LayoutParser.kt +++ b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/LayoutParser.kt @@ -59,8 +59,7 @@ object LayoutParser { /** Parse simple layouts, defined only as rows of (normal) keys with popup keys. */ fun parseSimpleString(layoutText: String): List> { - val rowStrings = layoutText.replace("\r\n", "\n").split("\\n\\s*\\n".toRegex()).filter { it.isNotBlank() } - return rowStrings.map { row -> + return LayoutUtils.getSimpleRowStrings(layoutText).map { row -> row.split("\n").mapNotNull { parseKey(it) } } } diff --git a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/LocaleKeyboardInfos.kt b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/LocaleKeyboardInfos.kt index 260eb9571..93c51b981 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/LocaleKeyboardInfos.kt +++ b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/LocaleKeyboardInfos.kt @@ -11,6 +11,7 @@ import helium314.keyboard.latin.R import helium314.keyboard.latin.common.splitOnFirstSpacesOnly import helium314.keyboard.latin.common.splitOnWhitespace import helium314.keyboard.latin.settings.Settings +import helium314.keyboard.latin.utils.SpacedTokens import helium314.keyboard.latin.utils.SubtypeLocaleUtils import java.io.InputStream import java.util.Locale @@ -44,7 +45,7 @@ class LocaleKeyboardInfos(dataStream: InputStream?, locale: Locale) { "mns" -> Key.LABEL_FLAGS_FOLLOW_KEY_LETTER_RATIO else -> 0 } - val tlds = getLocaleTlds(locale) // todo: USE IT + val tlds = getLocaleTlds(locale) init { readStream(dataStream, false, true) @@ -83,18 +84,12 @@ class LocaleKeyboardInfos(dataStream: InputStream?, locale: Locale) { READER_MODE_EXTRA_KEYS -> if (!onlyPopupKeys) addExtraKey(line.split(colonSpaceRegex, 2)) READER_MODE_LABELS -> if (!onlyPopupKeys) addLabel(line.split(colonSpaceRegex, 2)) READER_MODE_NUMBER_ROW -> localizedNumberKeys = line.splitOnWhitespace() - READER_MODE_TLD -> line.splitOnWhitespace().forEach { tlds.add(".$it") } + READER_MODE_TLD -> SpacedTokens(line).forEach { tlds.add(".$it") } } } } } - fun addDefaultTlds(locale: Locale) { - if ((locale.language != "en" && euroLocales.matches(locale.language)) || euroCountries.matches(locale.country)) - tlds.add(".eu") - tlds.addAll(defaultTlds.splitOnWhitespace()) - } - /** Pair(extraKeysLeft, extraKeysRight) */ fun getTabletExtraKeys(elementId: Int): Pair, List> { val flags = Key.LABEL_FLAGS_FONT_DEFAULT @@ -205,7 +200,6 @@ private fun createLocaleKeyTexts(context: Context, params: KeyboardParams, popup if (locale == params.mId.locale) return@forEach lkt.addFile(getStreamForLocale(locale, context), true) } - lkt.addDefaultTlds(params.mId.locale) when (popupKeysSetting) { POPUP_KEYS_MAIN -> lkt.addFile(context.assets.open("$LOCALE_TEXTS_FOLDER/more_popups_main.txt"), false) POPUP_KEYS_MORE -> lkt.addFile(context.assets.open("$LOCALE_TEXTS_FOLDER/more_popups_more.txt"), false) @@ -227,19 +221,27 @@ private fun getStreamForLocale(locale: Locale, context: Context) = } private fun getLocaleTlds(locale: Locale): LinkedHashSet { + val tlds = getDefaultTlds(locale) val ccLower = locale.country.lowercase() - val tlds = LinkedHashSet() if (ccLower.isEmpty() || locale.language == SubtypeLocaleUtils.NO_LANGUAGE) return tlds specialCountryTlds.forEach { if (ccLower != it.first) return@forEach - tlds.addAll(it.second.splitOnWhitespace()) - return tlds + tlds.addAll(SpacedTokens(it.second)) + return@getLocaleTlds tlds } tlds.add(".$ccLower") return tlds } +private fun getDefaultTlds(locale: Locale): LinkedHashSet { + val tlds = linkedSetOf() + tlds.addAll(SpacedTokens(defaultTlds)) + if ((locale.language != "en" && euroLocales.matches(locale.language)) || euroCountries.matches(locale.country)) + tlds.add(".eu") + return tlds +} + fun clearCache() = localeKeyboardInfosCache.clear() // cache the texts, so they don't need to be read over and over @@ -263,9 +265,9 @@ private fun getCurrencyKey(locale: Locale): Pair> { return euro if (locale.toString().matches(euroLocales)) return euro - if (locale.language.matches("ca|eu|lb|mt".toRegex())) + if (locale.language.matches("ca|eu|lb|mt|pms".toRegex())) return euro - if (locale.language.matches("fa|iw|ko|lo|mn|ne|si|th|uk|vi|km".toRegex())) + if (locale.language.matches("ak|dag|ee|fa|gaa|ha|he|ig|iw|lo|ko|km|mn|ne|si|th|uk|vi|yo".toRegex())) return genericCurrencyKey(getCurrency(locale)) if (locale.language == "hy") return dram @@ -291,17 +293,24 @@ private fun getCurrency(locale: Locale): String { if (locale.country == "BD") return "৳" if (locale.country == "LK") return "රු" return when (locale.language) { + "ak" -> "¢" + "dag" -> "¢" + "ee" -> "¢" "fa" -> "﷼" - "iw" -> "₪" - "ko" -> "₩" + "gaa" -> "¢" + "ha" -> "₦" + "ig" -> "₦" + "iw", "he" -> "₪" "lo" -> "₭" + "km" -> "៛" + "ko" -> "₩" "mn" -> "₮" "ne" -> "रु." "si" -> "රු" "th" -> "฿" "uk" -> "₴" "vi" -> "₫" - "km" -> "៛" + "yo" -> "₦" else -> "$" } } diff --git a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/KeyCode.kt b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/KeyCode.kt index bf5c65f04..4e2ccebe2 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/KeyCode.kt +++ b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/KeyCode.kt @@ -24,15 +24,15 @@ object KeyCode { const val UNSPECIFIED = 0 const val CTRL = -1 - const val CTRL_LOCK = -2 + //const val CTRL_LOCK = -2 const val ALT = -3 - const val ALT_LOCK = -4 + //const val ALT_LOCK = -4 const val FN = -5 - const val FN_LOCK = -6 + //const val FN_LOCK = -6 const val DELETE = -7 - const val DELETE_WORD = -8 - const val FORWARD_DELETE = -9 - const val FORWARD_DELETE_WORD = -10 + //const val DELETE_WORD = -8 + //const val FORWARD_DELETE = -9 + //const val FORWARD_DELETE_WORD = -10 const val SHIFT = -11 const val CAPS_LOCK = -13 @@ -51,21 +51,21 @@ object KeyCode { const val CLIPBOARD_SELECT_WORD = -34 // CLIPBOARD_SELECT const val CLIPBOARD_SELECT_ALL = -35 const val CLIPBOARD_CLEAR_HISTORY = -36 - const val CLIPBOARD_CLEAR_FULL_HISTORY = -37 - const val CLIPBOARD_CLEAR_PRIMARY_CLIP = -38 + //const val CLIPBOARD_CLEAR_FULL_HISTORY = -37 + //const val CLIPBOARD_CLEAR_PRIMARY_CLIP = -38 - const val COMPACT_LAYOUT_TO_LEFT = -111 - const val COMPACT_LAYOUT_TO_RIGHT = -112 + //const val COMPACT_LAYOUT_TO_LEFT = -111 + //const val COMPACT_LAYOUT_TO_RIGHT = -112 const val SPLIT_LAYOUT = -113 - const val MERGE_LAYOUT = -114 + //const val MERGE_LAYOUT = -114 const val UNDO = -131 const val REDO = -132 const val ALPHA = -201 // VIEW_CHARACTERS const val SYMBOL = -202 // VIEW_SYMBOLS - const val VIEW_SYMBOLS2 = -203 - const val VIEW_NUMERIC = -204 + //const val VIEW_SYMBOLS2 = -203 + //const val VIEW_NUMERIC = -204 const val NUMPAD = -205 // VIEW_NUMERIC_ADVANCED const val VIEW_PHONE = -206 const val VIEW_PHONE2 = -207 @@ -74,21 +74,21 @@ object KeyCode { const val EMOJI = -212 // IME_UI_MODE_MEDIA const val CLIPBOARD = -213 // IME_UI_MODE_CLIPBOARD - const val SYSTEM_INPUT_METHOD_PICKER = -221 - const val SYSTEM_PREV_INPUT_METHOD = -222 - const val SYSTEM_NEXT_INPUT_METHOD = -223 - const val IME_SUBTYPE_PICKER = -224 - const val IME_PREV_SUBTYPE = -225 - const val IME_NEXT_SUBTYPE = -226 + //const val SYSTEM_INPUT_METHOD_PICKER = -221 + //const val SYSTEM_PREV_INPUT_METHOD = -222 + //const val SYSTEM_NEXT_INPUT_METHOD = -223 + //const val IME_SUBTYPE_PICKER = -224 + //const val IME_PREV_SUBTYPE = -225 + //const val IME_NEXT_SUBTYPE = -226 const val LANGUAGE_SWITCH = -227 - const val IME_SHOW_UI = -231 - const val IME_HIDE_UI = -232 + //const val IME_SHOW_UI = -231 + //const val IME_HIDE_UI = -232 const val VOICE_INPUT = -233 - const val TOGGLE_SMARTBAR_VISIBILITY = -241 - const val TOGGLE_ACTIONS_OVERFLOW = -242 - const val TOGGLE_ACTIONS_EDITOR = -243 + //const val TOGGLE_SMARTBAR_VISIBILITY = -241 + //const val TOGGLE_ACTIONS_OVERFLOW = -242 + //const val TOGGLE_ACTIONS_EDITOR = -243 const val TOGGLE_INCOGNITO_MODE = -244 const val TOGGLE_AUTOCORRECT = -245 @@ -104,18 +104,18 @@ object KeyCode { const val CURRENCY_SLOT_6 = -806 const val MULTIPLE_CODE_POINTS = -902 - const val DRAG_MARKER = -991 - const val NOOP = -999 + //const val DRAG_MARKER = -991 + //const val NOOP = -999 - const val CHAR_WIDTH_SWITCHER = -9701 - const val CHAR_WIDTH_FULL = -9702 - const val CHAR_WIDTH_HALF = -9703 + //const val CHAR_WIDTH_SWITCHER = -9701 + //const val CHAR_WIDTH_FULL = -9702 + //const val CHAR_WIDTH_HALF = -9703 - const val KANA_SMALL = 12307 - const val KANA_SWITCHER = -9710 - const val KANA_HIRA = -9711 - const val KANA_KATA = -9712 - const val KANA_HALF_KATA = -9713 + //const val KANA_SMALL = 12307 + //const val KANA_SWITCHER = -9710 + //const val KANA_HIRA = -9711 + //const val KANA_KATA = -9712 + //const val KANA_HALF_KATA = -9713 const val KESHIDA = 1600 const val ZWNJ = 8204 // 0x200C, named HALF_SPACE in FlorisBoard @@ -137,7 +137,7 @@ object KeyCode { const val PAGE_UP = -10010 const val PAGE_DOWN = -10011 const val META = -10012 - const val META_LOCK = -10013 // to be consistent with the CTRL/ALT/FN LOCK codes, not sure whether this will be used + //const val META_LOCK = -10013 // to be consistent with the CTRL/ALT/FN LOCK codes, not sure whether this will be used const val TAB = -10014 const val WORD_LEFT = -10015 const val WORD_RIGHT = -10016 @@ -165,8 +165,15 @@ object KeyCode { const val F11 = -10038 const val F12 = -10039 const val BACK = -10040 - const val SELECT_LEFT = -10041 - const val SELECT_RIGHT = -10042 + //const val SELECT_LEFT = -10041 + //const val SELECT_RIGHT = -10042 + const val TIMESTAMP = -10043 + const val CTRL_LEFT = -10044 + const val CTRL_RIGHT = -10045 + const val ALT_LEFT = -10046 + const val ALT_RIGHT = -10047 + const val META_LEFT = -10048 + const val META_RIGHT = -10049 /** to make sure a FlorisBoard code works when reading a JSON layout */ fun Int.checkAndConvertCode(): Int = if (this > 0) this else when (this) { @@ -182,7 +189,8 @@ object KeyCode { SYMBOL_ALPHA, TOGGLE_ONE_HANDED_MODE, SWITCH_ONE_HANDED_MODE, SPLIT_LAYOUT, SHIFT_ENTER, ACTION_NEXT, ACTION_PREVIOUS, NOT_SPECIFIED, CLIPBOARD_COPY_ALL, WORD_LEFT, WORD_RIGHT, PAGE_UP, PAGE_DOWN, META, TAB, ESCAPE, INSERT, SLEEP, MEDIA_PLAY, MEDIA_PAUSE, MEDIA_PLAY_PAUSE, MEDIA_NEXT, - MEDIA_PREVIOUS, VOL_UP, VOL_DOWN, MUTE, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, BACK + MEDIA_PREVIOUS, VOL_UP, VOL_DOWN, MUTE, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, BACK, + TIMESTAMP, CTRL_LEFT, CTRL_RIGHT, ALT_LEFT, ALT_RIGHT, META_LEFT, META_RIGHT -> this // conversion @@ -194,8 +202,12 @@ object KeyCode { else -> throw IllegalStateException("key code $this not yet supported") } - // todo: three are many more keys, see near https://developer.android.com/reference/android/view/KeyEvent#KEYCODE_0 - /** convert a keyCode / codePoint to a KeyEvent.KEYCODE_, fallback to KeyEvent.KEYCODE_UNKNOWN */ + // todo: there are many more keys, see near https://developer.android.com/reference/android/view/KeyEvent#KEYCODE_0 + /** + * Convert a keyCode / codePoint to a KeyEvent.KEYCODE_. + * Fallback to KeyEvent.KEYCODE_UNKNOWN. + * To be uses for fake hardware key press. + * */ fun Int.toKeyEventCode(): Int = if (this > 0) when (this.toChar().uppercaseChar()) { '/' -> KeyEvent.KEYCODE_SLASH diff --git a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/KeyLabel.kt b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/KeyLabel.kt index 221bb432a..01c73c2d7 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/KeyLabel.kt +++ b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/KeyLabel.kt @@ -31,6 +31,7 @@ object KeyLabel { const val META = "meta" const val TAB = "tab" const val ESCAPE = "esc" + const val TIMESTAMP = "timestamp" /** to make sure a FlorisBoard label works when reading a JSON layout */ // resulting special labels should be names of FunctionalKey enum, case insensitive diff --git a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/PopupSet.kt b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/PopupSet.kt index f0cb2cb40..8d696ddaf 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/PopupSet.kt +++ b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/PopupSet.kt @@ -49,6 +49,6 @@ open class PopupSet( } class SimplePopups(val popupKeys: Collection?) : PopupSet() { - override fun getPopupKeyLabels(params: KeyboardParams) = popupKeys + override fun getPopupKeyLabels(params: KeyboardParams) = popupKeys?.map { KeyData.processLabel(it, params) } override fun isEmpty(): Boolean = popupKeys.isNullOrEmpty() } diff --git a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/TextKeyData.kt b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/TextKeyData.kt index eff715490..d98f3b956 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/TextKeyData.kt +++ b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/TextKeyData.kt @@ -12,6 +12,7 @@ import kotlinx.serialization.Transient import helium314.keyboard.keyboard.Key import helium314.keyboard.keyboard.KeyboardId import helium314.keyboard.keyboard.KeyboardTheme +import helium314.keyboard.keyboard.internal.KeyboardCodesSet import helium314.keyboard.keyboard.internal.KeyboardIconsSet import helium314.keyboard.keyboard.internal.KeyboardParams import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode.checkAndConvertCode @@ -24,6 +25,7 @@ import helium314.keyboard.latin.common.StringUtils import helium314.keyboard.latin.settings.Settings import helium314.keyboard.latin.spellcheck.AndroidSpellCheckerService import helium314.keyboard.latin.utils.InputTypeUtils +import helium314.keyboard.latin.utils.LayoutType import helium314.keyboard.latin.utils.Log import helium314.keyboard.latin.utils.ToolbarKey import helium314.keyboard.latin.utils.getCodeForToolbarKey @@ -130,6 +132,9 @@ sealed interface KeyData : AbstractKeyData { keys.add("!icon/start_onehanded_mode_key|!code/key_toggle_onehanded") if (!params.mId.mDeviceLocked) keys.add("!icon/settings_key|!code/key_settings") + if (shouldShowTldPopups(params)) { + keys.add(",") + } return keys } @@ -284,6 +289,40 @@ sealed interface KeyData : AbstractKeyData { return getStringInLocale(id, params) } + fun processLabel(label: String, params: KeyboardParams): String = when (label) { + KeyLabel.SYMBOL_ALPHA -> if (params.mId.isAlphabetKeyboard) params.mLocaleKeyboardInfos.labelSymbol else params.mLocaleKeyboardInfos.labelAlphabet + KeyLabel.SYMBOL -> params.mLocaleKeyboardInfos.labelSymbol + KeyLabel.ALPHA -> params.mLocaleKeyboardInfos.labelAlphabet + KeyLabel.COMMA -> params.mLocaleKeyboardInfos.labelComma + KeyLabel.PERIOD -> getPeriodLabel(params) + KeyLabel.SPACE -> getSpaceLabel(params) + KeyLabel.ACTION -> "${getActionKeyLabel(params)}|${getActionKeyCode(params)}" + KeyLabel.DELETE -> "!icon/delete_key|!code/key_delete" + KeyLabel.SHIFT -> "${getShiftLabel(params)}|!code/key_shift" + KeyLabel.COM -> params.mLocaleKeyboardInfos.tlds.first() + KeyLabel.LANGUAGE_SWITCH -> "!icon/language_switch_key|!code/key_language_switch" + KeyLabel.ZWNJ -> "!icon/zwnj_key|\u200C" + KeyLabel.CURRENCY -> params.mLocaleKeyboardInfos.currencyKey.first + KeyLabel.CURRENCY1 -> params.mLocaleKeyboardInfos.currencyKey.second[0] + KeyLabel.CURRENCY2 -> params.mLocaleKeyboardInfos.currencyKey.second[1] + KeyLabel.CURRENCY3 -> params.mLocaleKeyboardInfos.currencyKey.second[2] + KeyLabel.CURRENCY4 -> params.mLocaleKeyboardInfos.currencyKey.second[3] + KeyLabel.CURRENCY5 -> params.mLocaleKeyboardInfos.currencyKey.second[4] + KeyLabel.CTRL, KeyLabel.ALT, KeyLabel.FN, KeyLabel.META , KeyLabel.ESCAPE -> label.uppercase(Locale.US) + KeyLabel.TAB -> "!icon/tab_key|!code/${KeyCode.TAB}" + KeyLabel.TIMESTAMP -> "⌚|!code/${KeyCode.TIMESTAMP}" + else -> { + if (label in toolbarKeyStrings.values) { + "!icon/$label|!code/${getCodeForToolbarKey(ToolbarKey.valueOf(label.uppercase(Locale.US)))}" + } else label + } + } + + private fun shouldShowTldPopups(params: KeyboardParams): Boolean = + (Settings.getInstance().current.mShowTldPopupKeys + && params.mId.mSubtype.layouts[LayoutType.FUNCTIONAL] != "functional_keys_tablet" + && params.mId.mMode in setOf(KeyboardId.MODE_URL, KeyboardId.MODE_EMAIL)) + // could make arrays right away, but they need to be copied anyway as popupKeys arrays are modified when creating KeyParams private const val POPUP_EYS_NAVIGATE_PREVIOUS = "!icon/previous_key|!code/key_action_previous,!icon/clipboard_action_key|!code/key_clipboard" private const val POPUP_EYS_NAVIGATE_NEXT = "!icon/clipboard_action_key|!code/key_clipboard,!icon/next_key|!code/key_action_next" @@ -300,12 +339,13 @@ sealed interface KeyData : AbstractKeyData { // so better only do it in case the popup stuff needs more improvements // idea: directly create PopupKeySpec, but need to deal with needsToUpcase and popupKeysColumnAndFlags fun getPopupLabel(params: KeyboardParams): String { - val newLabel = processLabel(params) + val newLabel = processLabel(label, params) if (code == KeyCode.UNSPECIFIED) { - if (newLabel == label) return label + if (newLabel == label || newLabel.contains(KeyboardCodesSet.PREFIX_CODE)) + return newLabel val newCode = processCode() - if (newLabel.endsWith("|")) return "${newLabel}!code/$newCode" // for toolbar keys - return if (newCode == code) newLabel else "${newLabel}|!code/$newCode" + if (newLabel.endsWith("|")) return "${newLabel}${KeyboardCodesSet.PREFIX_CODE}$newCode" // maybe not used any more + return if (newCode == code) newLabel else "${newLabel}|${KeyboardCodesSet.PREFIX_CODE}$newCode" } if (code >= 32) { if (newLabel.startsWith(KeyboardIconsSet.PREFIX_ICON)) { @@ -323,12 +363,12 @@ sealed interface KeyData : AbstractKeyData { val outputText = String(codePoints, 0, codePoints.size) return "${newLabel}|$outputText" } - return if (newLabel.endsWith("|")) "$newLabel!code/${processCode()}" // for toolbar keys - else "$newLabel|!code/${processCode()}" + return if (newLabel.endsWith("|")) "$newLabel${KeyboardCodesSet.PREFIX_CODE}${processCode()}" // for toolbar keys + else "$newLabel|${KeyboardCodesSet.PREFIX_CODE}${processCode()}" } fun getCurrencyLabel(params: KeyboardParams): String { - val newLabel = processLabel(params) + val newLabel = processLabel(label, params) return when (code) { // consider currency codes for label KeyCode.CURRENCY_SLOT_1 -> "$newLabel|${params.mLocaleKeyboardInfos.currencyKey.first}" @@ -387,9 +427,9 @@ sealed interface KeyData : AbstractKeyData { newLabel = getCurrencyLabel(params) } else { newCode = processCode() - newLabel = processLabel(params) + newLabel = processLabel(label, params) } - val newLabelFlags = labelFlags or additionalLabelFlags or getAdditionalLabelFlags(params) + var newLabelFlags = labelFlags or additionalLabelFlags or getAdditionalLabelFlags(params) val newPopupKeys = popup.merge(getAdditionalPopupKeys(params)) val background = when (type) { @@ -401,6 +441,9 @@ sealed interface KeyData : AbstractKeyData { KeyType.LOCK -> getShiftBackground(params) null -> getDefaultBackground(params) } + if (background == Key.BACKGROUND_TYPE_FUNCTIONAL + || background == Key.BACKGROUND_TYPE_STICKY_ON || background == Key.BACKGROUND_TYPE_STICKY_OFF) + newLabelFlags = newLabelFlags or Key.LABEL_FLAGS_FOLLOW_FUNCTIONAL_TEXT_COLOR return if (newCode == KeyCode.UNSPECIFIED || newCode == KeyCode.MULTIPLE_CODE_POINTS) { // code will be determined from label if possible (i.e. label is single code point) @@ -470,37 +513,6 @@ sealed interface KeyData : AbstractKeyData { else params.mDefaultKeyWidth } - // todo (later): encoding the code in the label should be avoided, because we know it already - private fun processLabel(params: KeyboardParams): String = when (label) { - KeyLabel.SYMBOL_ALPHA -> if (params.mId.isAlphabetKeyboard) params.mLocaleKeyboardInfos.labelSymbol else params.mLocaleKeyboardInfos.labelAlphabet - KeyLabel.SYMBOL -> params.mLocaleKeyboardInfos.labelSymbol - KeyLabel.ALPHA -> params.mLocaleKeyboardInfos.labelAlphabet - KeyLabel.COMMA -> params.mLocaleKeyboardInfos.labelComma - KeyLabel.PERIOD -> getPeriodLabel(params) - KeyLabel.SPACE -> getSpaceLabel(params) - KeyLabel.ACTION -> "${getActionKeyLabel(params)}|${getActionKeyCode(params)}" - KeyLabel.DELETE -> "!icon/delete_key|!code/key_delete" - KeyLabel.SHIFT -> "${getShiftLabel(params)}|!code/key_shift" -// KeyLabel.EMOJI -> "!icon/emoji_normal_key|!code/key_emoji" - // todo (later): label and popupKeys for .com should be in localeKeyTexts, handled similar to currency key - KeyLabel.COM -> ".com" - KeyLabel.LANGUAGE_SWITCH -> "!icon/language_switch_key|!code/key_language_switch" - KeyLabel.ZWNJ -> "!icon/zwnj_key|\u200C" - KeyLabel.CURRENCY -> params.mLocaleKeyboardInfos.currencyKey.first - KeyLabel.CURRENCY1 -> params.mLocaleKeyboardInfos.currencyKey.second[0] - KeyLabel.CURRENCY2 -> params.mLocaleKeyboardInfos.currencyKey.second[1] - KeyLabel.CURRENCY3 -> params.mLocaleKeyboardInfos.currencyKey.second[2] - KeyLabel.CURRENCY4 -> params.mLocaleKeyboardInfos.currencyKey.second[3] - KeyLabel.CURRENCY5 -> params.mLocaleKeyboardInfos.currencyKey.second[4] - KeyLabel.CTRL, KeyLabel.ALT, KeyLabel.FN, KeyLabel.META , KeyLabel.ESCAPE -> label.uppercase(Locale.US) - KeyLabel.TAB -> "!icon/tab_key|" - else -> { - if (label in toolbarKeyStrings.values) { - "!icon/$label|" - } else label - } - } - private fun processCode(): Int { if (code != KeyCode.UNSPECIFIED) return code return when (label) { @@ -513,6 +525,7 @@ sealed interface KeyData : AbstractKeyData { KeyLabel.META -> KeyCode.META KeyLabel.TAB -> KeyCode.TAB KeyLabel.ESCAPE -> KeyCode.ESCAPE + KeyLabel.TIMESTAMP -> KeyCode.TIMESTAMP else -> { if (label in toolbarKeyStrings.values) { getCodeForToolbarKey(ToolbarKey.valueOf(label.uppercase(Locale.US))) @@ -524,17 +537,20 @@ sealed interface KeyData : AbstractKeyData { // todo (later): add explanations / reasoning, often this is just taken from conversion from OpenBoard / AOSP layouts private fun getAdditionalLabelFlags(params: KeyboardParams): Int { return when (label) { - KeyLabel.ALPHA, KeyLabel.SYMBOL_ALPHA, KeyLabel.SYMBOL -> Key.LABEL_FLAGS_PRESERVE_CASE or Key.LABEL_FLAGS_FOLLOW_FUNCTIONAL_TEXT_COLOR + KeyLabel.ALPHA, KeyLabel.SYMBOL_ALPHA, KeyLabel.SYMBOL -> Key.LABEL_FLAGS_PRESERVE_CASE KeyLabel.COMMA -> Key.LABEL_FLAGS_HAS_POPUP_HINT - // essentially this only changes the appearance of the armenian period key in holo theme - KeyLabel.PERIOD -> Key.LABEL_FLAGS_HAS_POPUP_HINT and if (params.mId.isAlphabetKeyboard) params.mLocaleKeyboardInfos.labelFlags else 0 + // essentially the first term only changes the appearance of the armenian period key in holo theme + KeyLabel.PERIOD -> (Key.LABEL_FLAGS_HAS_POPUP_HINT and + if (params.mId.isAlphabetKeyboard) params.mLocaleKeyboardInfos.labelFlags else 0) or + Key.LABEL_FLAGS_PRESERVE_CASE or + // in functional_keys.json the label flag is already defined, let's not override it in case it's removed by the user + if (!params.mId.isAlphaOrSymbolKeyboard && shouldShowTldPopups(params)) Key.LABEL_FLAGS_DISABLE_HINT_LABEL else 0 KeyLabel.ACTION -> { - Key.LABEL_FLAGS_PRESERVE_CASE or Key.LABEL_FLAGS_AUTO_X_SCALE or - Key.LABEL_FLAGS_FOLLOW_KEY_LABEL_RATIO or Key.LABEL_FLAGS_FOLLOW_FUNCTIONAL_TEXT_COLOR or + Key.LABEL_FLAGS_PRESERVE_CASE or Key.LABEL_FLAGS_AUTO_X_SCALE or Key.LABEL_FLAGS_FOLLOW_KEY_LABEL_RATIO or Key.LABEL_FLAGS_HAS_POPUP_HINT or KeyboardTheme.getThemeActionAndEmojiKeyLabelFlags(params.mThemeId) } KeyLabel.SPACE -> if (params.mId.isNumberLayout) Key.LABEL_FLAGS_ALIGN_ICON_TO_BOTTOM else 0 - KeyLabel.SHIFT -> Key.LABEL_FLAGS_PRESERVE_CASE or if (!params.mId.isAlphabetKeyboard) Key.LABEL_FLAGS_FOLLOW_FUNCTIONAL_TEXT_COLOR else 0 + KeyLabel.SHIFT -> Key.LABEL_FLAGS_PRESERVE_CASE toolbarKeyStrings[ToolbarKey.EMOJI] -> KeyboardTheme.getThemeActionAndEmojiKeyLabelFlags(params.mThemeId) KeyLabel.COM -> Key.LABEL_FLAGS_AUTO_X_SCALE or Key.LABEL_FLAGS_FONT_NORMAL or Key.LABEL_FLAGS_HAS_POPUP_HINT or Key.LABEL_FLAGS_PRESERVE_CASE KeyLabel.ZWNJ -> Key.LABEL_FLAGS_HAS_POPUP_HINT @@ -546,12 +562,12 @@ sealed interface KeyData : AbstractKeyData { private fun getAdditionalPopupKeys(params: KeyboardParams): PopupSet? { if (groupId == GROUP_COMMA) return SimplePopups(getCommaPopupKeys(params)) - if (groupId == GROUP_PERIOD) return SimplePopups(getPunctuationPopupKeys(params)) + if (groupId == GROUP_PERIOD) return getPeriodPopups(params) if (groupId == GROUP_ENTER) return getActionKeyPopupKeys(params) if (groupId == GROUP_NO_DEFAULT_POPUP) return null return when (label) { KeyLabel.COMMA -> SimplePopups(getCommaPopupKeys(params)) - KeyLabel.PERIOD -> SimplePopups(getPunctuationPopupKeys(params)) + KeyLabel.PERIOD -> getPeriodPopups(params) KeyLabel.ACTION -> getActionKeyPopupKeys(params) KeyLabel.SHIFT -> { if (params.mId.isAlphabetKeyboard) SimplePopups( @@ -561,13 +577,22 @@ sealed interface KeyData : AbstractKeyData { ) ) else null // why the alphabet popup keys actually? } - KeyLabel.COM -> SimplePopups(listOf(Key.POPUP_KEYS_HAS_LABELS, ".net", ".org", ".gov", ".edu")) + KeyLabel.COM -> SimplePopups( + listOf(Key.POPUP_KEYS_HAS_LABELS).plus(params.mLocaleKeyboardInfos.tlds.drop(1)) + ) + KeyLabel.ZWNJ -> SimplePopups(listOf("!icon/zwj_key|\u200D")) // only add currency popups if there are none defined on the key KeyLabel.CURRENCY -> if (popup.isEmpty()) SimplePopups(params.mLocaleKeyboardInfos.currencyKey.second) else null else -> null } } + + private fun getPeriodPopups(params: KeyboardParams): SimplePopups = + SimplePopups( + if (shouldShowTldPopups(params)) params.mLocaleKeyboardInfos.tlds + else getPunctuationPopupKeys(params) + ) } /** diff --git a/app/src/main/java/helium314/keyboard/latin/App.kt b/app/src/main/java/helium314/keyboard/latin/App.kt index 23308a14a..47ee42fea 100644 --- a/app/src/main/java/helium314/keyboard/latin/App.kt +++ b/app/src/main/java/helium314/keyboard/latin/App.kt @@ -6,6 +6,7 @@ import android.content.Context import androidx.core.content.edit import helium314.keyboard.keyboard.ColorSetting import helium314.keyboard.keyboard.KeyboardTheme +import helium314.keyboard.keyboard.emoji.SupportedEmojis import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode.checkAndConvertCode import helium314.keyboard.latin.common.ColorType import helium314.keyboard.latin.common.Constants.Separators @@ -23,6 +24,7 @@ import helium314.keyboard.latin.utils.DictionaryInfoUtils.USER_DICTIONARY_SUFFIX import helium314.keyboard.latin.utils.LayoutType import helium314.keyboard.latin.utils.LayoutType.Companion.folder import helium314.keyboard.latin.utils.LayoutUtilsCustom +import helium314.keyboard.latin.utils.Log import helium314.keyboard.latin.utils.ScriptUtils.SCRIPT_LATIN import helium314.keyboard.latin.utils.ScriptUtils.script import helium314.keyboard.latin.utils.SubtypeSettings @@ -32,8 +34,8 @@ import helium314.keyboard.latin.utils.defaultPinnedToolbarPref import helium314.keyboard.latin.utils.getResourceSubtypes import helium314.keyboard.latin.utils.locale import helium314.keyboard.latin.utils.mainLayoutName +import helium314.keyboard.latin.utils.mainLayoutNameOrQwerty import helium314.keyboard.latin.utils.prefs -import helium314.keyboard.latin.utils.protectedPrefs import helium314.keyboard.latin.utils.upgradeToolbarPrefs import helium314.keyboard.latin.utils.writeCustomKeyCodes import helium314.keyboard.settings.screens.colorPrefsAndResIds @@ -51,6 +53,16 @@ class App : Application() { checkVersionUpgrade(this) app = this Defaults.initDynamicDefaults(this) + LayoutUtilsCustom.removeMissingLayouts(this) // only after version upgrade + SupportedEmojis.load(this) + + val packageInfo = packageManager.getPackageInfo(packageName, 0) + @Suppress("DEPRECATION") + Log.i( + "startup", "Starting ${applicationInfo.processName} version ${packageInfo.versionName} (${ + packageInfo.versionCode + }) on Android ${android.os.Build.VERSION.RELEASE} (SDK ${android.os.Build.VERSION.SDK_INT})" + ) } companion object { @@ -74,16 +86,13 @@ fun checkVersionUpgrade(context: Context) { if (oldVersion == BuildConfig.VERSION_CODE) return // clear extracted dictionaries, in case updated version contains newer ones - DictionaryInfoUtils.getCachedDirectoryList(context)?.forEach { - if (!it.isDirectory) return@forEach + DictionaryInfoUtils.getCacheDirectories(context).forEach { val files = it.listFiles() ?: return@forEach for (file in files) { if (!file.name.endsWith(USER_DICTIONARY_SUFFIX)) file.delete() } } - if (oldVersion == 0) // new install or restoring settings from old app name - upgradesWhenComingFromOldAppName(context) if (oldVersion <= 1000) { // upgrade old custom layouts name val oldShiftSymbolsFile = getCustomLayoutFile("custom.shift_symbols", context) if (oldShiftSymbolsFile.exists()) { @@ -161,7 +170,7 @@ fun checkVersionUpgrade(context: Context) { split[1] = newName split.joinToString(":") } - Settings.writePrefAdditionalSubtypes(prefs, newSubtypeStrings.joinToString(";")) + prefs.edit().putString(Settings.PREF_ADDITIONAL_SUBTYPES, newSubtypeStrings.joinToString(";")).apply() } // rename other custom layouts LayoutUtilsCustom.onLayoutFileChanged() @@ -232,7 +241,7 @@ fun checkVersionUpgrade(context: Context) { KeyboardTheme.writeUserMoreColors(prefs, themeNameNight, moreColorsNight) } if (prefs.contains("theme_dark_color_all_colors")) { - val allColorsNight = readAllColorsMap(false) + val allColorsNight = readAllColorsMap(true) prefs.edit().remove("theme_dark_color_all_colors").apply() KeyboardTheme.writeUserAllColors(prefs, themeNameNight, allColorsNight) } @@ -437,19 +446,19 @@ fun checkVersionUpgrade(context: Context) { val mainLayoutName = oldSplit[1] // we now need more information than just locale and main layout name, get it from existing subtypes val filtered = additionalSubtypes.filter { - it.locale().toLanguageTag() == languageTag && (it.mainLayoutName() ?: "qwerty") == mainLayoutName + it.locale().toLanguageTag() == languageTag && (it.mainLayoutNameOrQwerty()) == mainLayoutName } if (filtered.isNotEmpty()) return@joinToString filtered.first().toSettingsSubtype().toPref() // find best matching resource subtype val goodMatch = resourceSubtypes.filter { - it.locale().toLanguageTag() == languageTag && (it.mainLayoutName() ?: "qwerty") == mainLayoutName + it.locale().toLanguageTag() == languageTag && (it.mainLayoutNameOrQwerty()) == mainLayoutName } if (goodMatch.isNotEmpty()) return@joinToString goodMatch.first().toSettingsSubtype().toPref() // not sure how we can get here, but better deal with it val okMatch = resourceSubtypes.filter { - it.locale().language == languageTag.constructLocale().language && (it.mainLayoutName() ?: "qwerty") == mainLayoutName + it.locale().language == languageTag.constructLocale().language && (it.mainLayoutNameOrQwerty()) == mainLayoutName } if (okMatch.isNotEmpty()) okMatch.first().toSettingsSubtype().toPref() @@ -530,115 +539,30 @@ fun checkVersionUpgrade(context: Context) { prefs.edit().remove("auto_correction_confidence").putFloat(Settings.PREF_AUTO_CORRECT_THRESHOLD, value).apply() } } - if (oldVersion <= 2310) { - listOf( - Settings.PREF_ENABLED_SUBTYPES, - Settings.PREF_SELECTED_SUBTYPE, - Settings.PREF_ADDITIONAL_SUBTYPES - ).forEach { key -> - val value = prefs.getString(key, "")!! - if ("bengali," in value) { - prefs.edit().putString(key, value.replace("bengali,", "bengali_inscript,")).apply() + if (oldVersion <= 2310) { + listOf( + Settings.PREF_ENABLED_SUBTYPES, + Settings.PREF_SELECTED_SUBTYPE, + Settings.PREF_ADDITIONAL_SUBTYPES + ).forEach { key -> + val value = prefs.getString(key, "")!! + if ("bengali," in value) { + prefs.edit().putString(key, value.replace("bengali,", "bengali_inscript,")).apply() + } + } + } + if (oldVersion <= 3001 && prefs.getInt(Settings.PREF_CLIPBOARD_HISTORY_RETENTION_TIME, Defaults.PREF_CLIPBOARD_HISTORY_RETENTION_TIME) <= 0) { + prefs.edit().putInt(Settings.PREF_CLIPBOARD_HISTORY_RETENTION_TIME, 121).apply() + } + if (oldVersion <= 3002) { + prefs.all.filterKeys { it.startsWith(Settings.PREF_USER_ALL_COLORS_PREFIX) }.forEach { + val oldValue = prefs.getString(it.key, "")!! + if ("KEY_PREVIEW" !in oldValue) return@forEach + val newValue = oldValue.replace("KEY_PREVIEW", "KEY_PREVIEW_BACKGROUND") + prefs.edit().putString(it.key, newValue).apply() } } -} upgradeToolbarPrefs(prefs) LayoutUtilsCustom.onLayoutFileChanged() // just to be sure prefs.edit { putInt(Settings.PREF_VERSION_CODE, BuildConfig.VERSION_CODE) } } - -// todo (later): remove it when most users probably have upgraded -private fun upgradesWhenComingFromOldAppName(context: Context) { - // move layout files - try { - File(context.filesDir, "layouts").listFiles()?.forEach { - it.copyTo(getCustomLayoutFile(it.name, context), true) - it.delete() - } - } catch (_: Exception) {} - // move background images - try { - val bgDay = File(context.filesDir, "custom_background_image") - if (bgDay.isFile) { - bgDay.copyTo(Settings.getCustomBackgroundFile(context, false, false), true) - bgDay.delete() - } - val bgNight = File(context.filesDir, "custom_background_image_night") - if (bgNight.isFile) { - bgNight.copyTo(Settings.getCustomBackgroundFile(context, true, false), true) - bgNight.delete() - } - } catch (_: Exception) {} - // upgrade prefs - val prefs = context.prefs() - if (prefs.all.containsKey("theme_variant")) { - prefs.edit().putString(Settings.PREF_THEME_COLORS, prefs.getString("theme_variant", "")).apply() - prefs.edit().remove("theme_variant").apply() - } - if (prefs.all.containsKey("theme_variant_night")) { - prefs.edit().putString(Settings.PREF_THEME_COLORS_NIGHT, prefs.getString("theme_variant_night", "")).apply() - prefs.edit().remove("theme_variant_night").apply() - } - prefs.all.toMap().forEach { - if (it.key.startsWith("pref_key_") && it.key != "pref_key_longpress_timeout") { - var remove = true - when (val value = it.value) { - is Boolean -> prefs.edit().putBoolean(it.key.substringAfter("pref_key_"), value).apply() - is Int -> prefs.edit().putInt(it.key.substringAfter("pref_key_"), value).apply() - is Long -> prefs.edit().putLong(it.key.substringAfter("pref_key_"), value).apply() - is String -> prefs.edit().putString(it.key.substringAfter("pref_key_"), value).apply() - is Float -> prefs.edit().putFloat(it.key.substringAfter("pref_key_"), value).apply() - else -> remove = false - } - if (remove) - prefs.edit().remove(it.key).apply() - } else if (it.key.startsWith("pref_")) { - var remove = true - when (val value = it.value) { - is Boolean -> prefs.edit().putBoolean(it.key.substringAfter("pref_"), value).apply() - is Int -> prefs.edit().putInt(it.key.substringAfter("pref_"), value).apply() - is Long -> prefs.edit().putLong(it.key.substringAfter("pref_"), value).apply() - is String -> prefs.edit().putString(it.key.substringAfter("pref_"), value).apply() - is Float -> prefs.edit().putFloat(it.key.substringAfter("pref_"), value).apply() - else -> remove = false - } - if (remove) - prefs.edit().remove(it.key).apply() - } - } - // change more_keys to popup_keys - if (prefs.contains("more_keys_order")) { - prefs.edit().putString(Settings.PREF_POPUP_KEYS_ORDER, prefs.getString("more_keys_order", "")?.replace("more_", "popup_")).apply() - prefs.edit().remove("more_keys_order").apply() - } - if (prefs.contains("more_keys_labels_order")) { - prefs.edit().putString(Settings.PREF_POPUP_KEYS_LABELS_ORDER, prefs.getString("more_keys_labels_order", "")?.replace("more_", "popup_")).apply() - prefs.edit().remove("more_keys_labels_order").apply() - } - if (prefs.contains("more_more_keys")) { - prefs.edit().putString(Settings.PREF_MORE_POPUP_KEYS, prefs.getString("more_more_keys", "")).apply() - prefs.edit().remove("more_more_keys").apply() - } - if (prefs.contains("spellcheck_use_contacts")) { - prefs.edit().putBoolean(Settings.PREF_USE_CONTACTS, prefs.getBoolean("spellcheck_use_contacts", false)).apply() - prefs.edit().remove("spellcheck_use_contacts").apply() - } - // upgrade additional subtype locale strings - if (prefs.contains(Settings.PREF_ADDITIONAL_SUBTYPES)) { - val additionalSubtypes = mutableListOf() - prefs.getString(Settings.PREF_ADDITIONAL_SUBTYPES, "")!!.split(";").forEach { - val localeString = it.substringBefore(":") - additionalSubtypes.add(it.replace(localeString, localeString.constructLocale().toLanguageTag())) - } - Settings.writePrefAdditionalSubtypes(prefs, additionalSubtypes.joinToString(";")) - } - // move pinned clips to credential protected storage if device is not locked (should never happen) - if (!prefs.contains(Settings.PREF_PINNED_CLIPS)) return - try { - val defaultProtectedPrefs = context.protectedPrefs() - defaultProtectedPrefs.edit { putString(Settings.PREF_PINNED_CLIPS, prefs.getString(Settings.PREF_PINNED_CLIPS, "")) } - prefs.edit { remove(Settings.PREF_PINNED_CLIPS) } - } catch (_: IllegalStateException) { - // SharedPreferences in credential encrypted storage are not available until after user is unlocked - } -} diff --git a/app/src/main/java/helium314/keyboard/latin/AppsBinaryDictionary.java b/app/src/main/java/helium314/keyboard/latin/AppsBinaryDictionary.java new file mode 100644 index 000000000..fce77fd3f --- /dev/null +++ b/app/src/main/java/helium314/keyboard/latin/AppsBinaryDictionary.java @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: GPL-3.0-only + +package helium314.keyboard.latin; + +import android.content.Context; + +import com.android.inputmethod.latin.BinaryDictionary; + +import java.io.File; +import java.util.Locale; + +import helium314.keyboard.latin.common.StringUtils; +import helium314.keyboard.latin.utils.Log; +import helium314.keyboard.latin.utils.SpacedTokens; + +public class AppsBinaryDictionary extends ExpandableBinaryDictionary { + private static final String TAG = AppsBinaryDictionary.class.getSimpleName(); + private static final String NAME = "apps"; + + private static final int FREQUENCY_FOR_APPS = 100; + private static final int FREQUENCY_FOR_APPS_BIGRAM = 200; + + private static final boolean DEBUG = false; + private static final boolean DEBUG_DUMP = false; + + private final AppsManager mAppsManager; + + protected AppsBinaryDictionary(final Context ctx, final Locale locale, + final File dictFile, final String name) { + super(ctx, getDictName(name, locale, dictFile), locale, Dictionary.TYPE_APPS, dictFile); + mAppsManager = new AppsManager(ctx); + reloadDictionaryIfRequired(); + } + + public static AppsBinaryDictionary getDictionary(final Context context, final Locale locale, + final File dictFile, final String dictNamePrefix) { + return new AppsBinaryDictionary(context, locale, dictFile, dictNamePrefix + NAME); + } + + /** + * Typically called whenever the dictionary is created for the first time or recreated when we + * think that there are updates to the dictionary. This is called asynchronously. + */ + @Override + public void loadInitialContentsLocked() { + loadDictionaryLocked(); + } + + /** + * Loads app names to the dictionary. + */ + private void loadDictionaryLocked() { + for (final String name : mAppsManager.getNames()) { + addNameLocked(name); + } + } + + /** + * Adds the words in an app label to the binary dictionary along with their n-grams. + */ + private void addNameLocked(final String appLabel) { + NgramContext ngramContext = NgramContext.getEmptyPrevWordsContext( + BinaryDictionary.MAX_PREV_WORD_COUNT_FOR_N_GRAM); + // TODO: Better tokenization for non-Latin writing systems + for (final String word : new SpacedTokens(appLabel)) { + if (DEBUG_DUMP) { + Log.d(TAG, "addName word = " + word); + } + final int wordLen = StringUtils.codePointCount(word); + // Don't add single letter words, possibly confuses capitalization of i. + if (1 < wordLen && wordLen <= MAX_WORD_LENGTH) { + if (DEBUG) { + Log.d(TAG, "addName " + appLabel + ", " + word + ", " + ngramContext); + } + runGCIfRequiredLocked(true /* mindsBlockByGC */); + addUnigramLocked(word, FREQUENCY_FOR_APPS, + null /* shortcut */, 0 /* shortcutFreq */, false /* isNotAWord */, + false /* isPossiblyOffensive */, + BinaryDictionary.NOT_A_VALID_TIMESTAMP); + if (ngramContext.isValid()) { + runGCIfRequiredLocked(true /* mindsBlockByGC */); + addNgramEntryLocked(ngramContext, + word, + FREQUENCY_FOR_APPS_BIGRAM, + BinaryDictionary.NOT_A_VALID_TIMESTAMP); + } + ngramContext = ngramContext.getNextNgramContext( + new NgramContext.WordInfo(word)); + } + } + } +} diff --git a/app/src/main/java/helium314/keyboard/latin/AppsManager.kt b/app/src/main/java/helium314/keyboard/latin/AppsManager.kt new file mode 100644 index 000000000..3c918563b --- /dev/null +++ b/app/src/main/java/helium314/keyboard/latin/AppsManager.kt @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: GPL-3.0-only + +package helium314.keyboard.latin + +import android.content.Context +import android.content.Intent +import android.content.pm.PackageManager +import android.content.pm.ResolveInfo +import java.util.HashSet + +class AppsManager(context: Context) { + private val mPackageManager: PackageManager = context.packageManager + + /** + * Returns all app labels associated with a launcher icon, sorted arbitrarily. + */ + fun getNames(): HashSet { + val filter = Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_LAUNCHER) + // activities with an entry/icon for the launcher + val launcherApps: List = mPackageManager.queryIntentActivities(filter, 0) + + val names = HashSet(launcherApps.size) + for (info in launcherApps) { + val name = info.activityInfo.loadLabel(mPackageManager).toString() + names.add(name) + } + + return names + } +} diff --git a/app/src/main/java/helium314/keyboard/latin/ClipboardHistoryEntry.kt b/app/src/main/java/helium314/keyboard/latin/ClipboardHistoryEntry.kt index bb6cf5bf0..1990ee929 100644 --- a/app/src/main/java/helium314/keyboard/latin/ClipboardHistoryEntry.kt +++ b/app/src/main/java/helium314/keyboard/latin/ClipboardHistoryEntry.kt @@ -2,18 +2,12 @@ package helium314.keyboard.latin -import kotlinx.serialization.KSerializer import kotlinx.serialization.Serializable -import kotlinx.serialization.descriptors.PrimitiveKind -import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor -import kotlinx.serialization.encoding.Decoder -import kotlinx.serialization.encoding.Encoder @Serializable data class ClipboardHistoryEntry ( var timeStamp: Long, - @Serializable(with = CharSequenceStringSerializer::class) - val content: CharSequence, + val content: String, var isPinned: Boolean = false ) : Comparable { override fun compareTo(other: ClipboardHistoryEntry): Int { @@ -21,13 +15,3 @@ data class ClipboardHistoryEntry ( return if (result != 0) result else other.timeStamp.compareTo(timeStamp) } } - -class CharSequenceStringSerializer : KSerializer { - override val descriptor = PrimitiveSerialDescriptor("CharSequence", PrimitiveKind.STRING) - - override fun serialize(encoder: Encoder, value: CharSequence) { - encoder.encodeString(value.toString()) - } - - override fun deserialize(decoder: Decoder) = decoder.decodeString() -} \ No newline at end of file diff --git a/app/src/main/java/helium314/keyboard/latin/ClipboardHistoryManager.kt b/app/src/main/java/helium314/keyboard/latin/ClipboardHistoryManager.kt index 3a279046a..8d41cfb70 100644 --- a/app/src/main/java/helium314/keyboard/latin/ClipboardHistoryManager.kt +++ b/app/src/main/java/helium314/keyboard/latin/ClipboardHistoryManager.kt @@ -61,7 +61,7 @@ class ClipboardHistoryManager( val content = clipItem.coerceToText(latinIME) if (TextUtils.isEmpty(content)) return - val duplicateEntryIndex = historyEntries.indexOfFirst { it.content.toString() == content.toString() } + val duplicateEntryIndex = historyEntries.indexOfFirst { it.content == content.toString() } if (duplicateEntryIndex != -1) { val existingEntry = historyEntries[duplicateEntryIndex] if (existingEntry.timeStamp == timeStamp) return // nothing to change (may occur frequently starting with API 30) @@ -74,9 +74,9 @@ class ClipboardHistoryManager( onHistoryChangeListener?.onClipboardHistoryEntryMoved(duplicateEntryIndex, newIndex) return } - if (historyEntries.any { it.content.toString() == content.toString() }) return + if (historyEntries.any { it.content == content.toString() }) return - val entry = ClipboardHistoryEntry(timeStamp, content) + val entry = ClipboardHistoryEntry(timeStamp, content.toString()) historyEntries.add(entry) sortHistoryEntries() val at = historyEntries.indexOf(entry) @@ -120,7 +120,7 @@ class ClipboardHistoryManager( private fun checkClipRetentionElapsed() { val mins = latinIME.mSettings.current.mClipboardHistoryRetentionTime - if (mins <= 0) return // No retention limit + if (mins > 120) return // No retention limit, changed from <= 0 because we want it to be larger than all other choices val maxClipRetentionTime = mins * 60 * 1000L val now = System.currentTimeMillis() historyEntries.removeAll { !it.isPinned && (now - it.timeStamp) > maxClipRetentionTime } diff --git a/app/src/main/java/helium314/keyboard/latin/ContactsBinaryDictionary.java b/app/src/main/java/helium314/keyboard/latin/ContactsBinaryDictionary.java index 2a82a0f0b..c8e953dab 100644 --- a/app/src/main/java/helium314/keyboard/latin/ContactsBinaryDictionary.java +++ b/app/src/main/java/helium314/keyboard/latin/ContactsBinaryDictionary.java @@ -14,7 +14,6 @@ import android.provider.ContactsContract.Contacts; import helium314.keyboard.latin.utils.Log; import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import com.android.inputmethod.latin.BinaryDictionary; @@ -51,7 +50,7 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary } public static ContactsBinaryDictionary getDictionary(final Context context, @NonNull final Locale locale, - final File dictFile, final String dictNamePrefix, @Nullable final String account) { + final File dictFile, final String dictNamePrefix) { return new ContactsBinaryDictionary(context, locale, dictFile, dictNamePrefix + NAME); } diff --git a/app/src/main/java/helium314/keyboard/latin/ContactsDictionaryConstants.java b/app/src/main/java/helium314/keyboard/latin/ContactsDictionaryConstants.java index 23c3eaf39..dd0ff0e80 100644 --- a/app/src/main/java/helium314/keyboard/latin/ContactsDictionaryConstants.java +++ b/app/src/main/java/helium314/keyboard/latin/ContactsDictionaryConstants.java @@ -20,8 +20,8 @@ public class ContactsDictionaryConstants { /** * Frequency for contacts information into the dictionary */ - public static final int FREQUENCY_FOR_CONTACTS = 40; - public static final int FREQUENCY_FOR_CONTACTS_BIGRAM = 90; + public static final int FREQUENCY_FOR_CONTACTS = 100; // much increased from original frequency because contacts were barely suggested + public static final int FREQUENCY_FOR_CONTACTS_BIGRAM = 200; // todo: seems broken, how to actually get bigrams? /** * Do not attempt to query contacts if there are more than this many entries. diff --git a/app/src/main/java/helium314/keyboard/latin/Dictionary.java b/app/src/main/java/helium314/keyboard/latin/Dictionary.java index 4c26703ed..2a9c3d190 100644 --- a/app/src/main/java/helium314/keyboard/latin/Dictionary.java +++ b/app/src/main/java/helium314/keyboard/latin/Dictionary.java @@ -6,15 +6,15 @@ package helium314.keyboard.latin; +import androidx.annotation.NonNull; + +import java.util.ArrayList; +import java.util.Locale; + import helium314.keyboard.latin.SuggestedWords.SuggestedWordInfo; import helium314.keyboard.latin.common.ComposedData; import helium314.keyboard.latin.settings.SettingsValuesForSuggestion; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Locale; - /** * Abstract base class for a dictionary that can do a fuzzy search for words based on a set of key * strokes. @@ -48,6 +48,7 @@ public abstract class Dictionary { // phony dictionary instances for them. public static final String TYPE_MAIN = "main"; public static final String TYPE_CONTACTS = "contacts"; + public static final String TYPE_APPS = "apps"; // User dictionary, the system-managed one. public static final String TYPE_USER = "user"; // User history dictionary internal to LatinIME. @@ -56,16 +57,6 @@ public abstract class Dictionary { // The locale for this dictionary. May be null if unknown (phony dictionary for example). public final Locale mLocale; - /** - * Set out of the dictionary types listed above that are based on data specific to the user, - * e.g., the user's contacts. - */ - private static final HashSet sUserSpecificDictionaryTypes = new HashSet<>(Arrays.asList( - TYPE_USER_TYPED, - TYPE_USER, - TYPE_CONTACTS, - TYPE_USER_HISTORY)); - public Dictionary(final String dictType, final Locale locale) { mDictType = dictType; mLocale = locale; @@ -178,7 +169,14 @@ public abstract class Dictionary { * @return Whether this dictionary is specific to the user. */ public boolean isUserSpecific() { - return sUserSpecificDictionaryTypes.contains(mDictType); + return switch (mDictType) { + case TYPE_USER_TYPED, + TYPE_USER, + TYPE_CONTACTS, + TYPE_APPS, + TYPE_USER_HISTORY -> true; + default -> false; + }; } /** diff --git a/app/src/main/java/helium314/keyboard/latin/DictionaryCollection.java b/app/src/main/java/helium314/keyboard/latin/DictionaryCollection.java index 7496f86f1..35d4bc034 100644 --- a/app/src/main/java/helium314/keyboard/latin/DictionaryCollection.java +++ b/app/src/main/java/helium314/keyboard/latin/DictionaryCollection.java @@ -6,30 +6,35 @@ package helium314.keyboard.latin; -import helium314.keyboard.latin.utils.Log; - import helium314.keyboard.latin.SuggestedWords.SuggestedWordInfo; import helium314.keyboard.latin.common.ComposedData; import helium314.keyboard.latin.settings.SettingsValuesForSuggestion; +import helium314.keyboard.latin.utils.Log; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Locale; -import java.util.concurrent.CopyOnWriteArrayList; /** * Class for a collection of dictionaries that behave like one dictionary. */ public final class DictionaryCollection extends Dictionary { private final String TAG = DictionaryCollection.class.getSimpleName(); - private final CopyOnWriteArrayList mDictionaries; + private final ArrayList mDictionaries; + private final float[] mWeights; public DictionaryCollection(final String dictType, final Locale locale, - final Collection dictionaries) { + final Collection dictionaries, final float[] weights) { super(dictType, locale); - mDictionaries = new CopyOnWriteArrayList<>(dictionaries); + mDictionaries = new ArrayList<>(dictionaries); mDictionaries.removeAll(Collections.singleton(null)); + if (mDictionaries.size() > weights.length) { + mWeights = new float[mDictionaries.size()]; + Arrays.fill(mWeights, 1f); + Log.w(TAG, "got weights array of length " + weights.length + ", expected "+mDictionaries.size()); + } else mWeights = weights; } @Override @@ -38,19 +43,19 @@ public final class DictionaryCollection extends Dictionary { final SettingsValuesForSuggestion settingsValuesForSuggestion, final int sessionId, final float weightForLocale, final float[] inOutWeightOfLangModelVsSpatialModel) { - final CopyOnWriteArrayList dictionaries = mDictionaries; + final ArrayList dictionaries = mDictionaries; if (dictionaries.isEmpty()) return null; // To avoid creating unnecessary objects, we get the list out of the first // dictionary and add the rest to it if not null, hence the get(0) ArrayList suggestions = dictionaries.get(0).getSuggestions(composedData, ngramContext, proximityInfoHandle, settingsValuesForSuggestion, sessionId, - weightForLocale, inOutWeightOfLangModelVsSpatialModel); + weightForLocale * mWeights[0], inOutWeightOfLangModelVsSpatialModel); if (null == suggestions) suggestions = new ArrayList<>(); final int length = dictionaries.size(); for (int i = 1; i < length; ++ i) { final ArrayList sugg = dictionaries.get(i).getSuggestions( composedData, ngramContext, proximityInfoHandle, settingsValuesForSuggestion, - sessionId, weightForLocale, inOutWeightOfLangModelVsSpatialModel); + sessionId, weightForLocale * mWeights[i], inOutWeightOfLangModelVsSpatialModel); if (null != sugg) suggestions.addAll(sugg); } return suggestions; @@ -93,22 +98,4 @@ public final class DictionaryCollection extends Dictionary { for (final Dictionary dict : mDictionaries) dict.close(); } - - // Warning: this is not thread-safe. Take necessary precaution when calling. - public void addDictionary(final Dictionary newDict) { - if (null == newDict) return; - if (mDictionaries.contains(newDict)) { - Log.w(TAG, "This collection already contains this dictionary: " + newDict); - } - mDictionaries.add(newDict); - } - - // Warning: this is not thread-safe. Take necessary precaution when calling. - public void removeDictionary(final Dictionary dict) { - if (mDictionaries.contains(dict)) { - mDictionaries.remove(dict); - } else { - Log.w(TAG, "This collection does not contain this dictionary: " + dict); - } - } } diff --git a/app/src/main/java/helium314/keyboard/latin/DictionaryFacilitator.java b/app/src/main/java/helium314/keyboard/latin/DictionaryFacilitator.java index 4d8ca5f6f..eba0932f6 100644 --- a/app/src/main/java/helium314/keyboard/latin/DictionaryFacilitator.java +++ b/app/src/main/java/helium314/keyboard/latin/DictionaryFacilitator.java @@ -23,7 +23,7 @@ import java.util.concurrent.TimeUnit; /** * Interface that facilitates interaction with different kinds of dictionaries. Provides APIs to - * instantiate and select the correct dictionaries (based on language or account), update entries + * instantiate and select the correct dictionaries (based on language and settings), update entries * and fetch suggestions. Currently AndroidSpellCheckerService and LatinIME both use * DictionaryFacilitator as a client for interacting with dictionaries. */ @@ -32,22 +32,20 @@ public interface DictionaryFacilitator { String[] ALL_DICTIONARY_TYPES = new String[] { Dictionary.TYPE_MAIN, Dictionary.TYPE_CONTACTS, + Dictionary.TYPE_APPS, Dictionary.TYPE_USER_HISTORY, Dictionary.TYPE_USER}; String[] DYNAMIC_DICTIONARY_TYPES = new String[] { Dictionary.TYPE_CONTACTS, + Dictionary.TYPE_APPS, Dictionary.TYPE_USER_HISTORY, Dictionary.TYPE_USER}; - /** - * The facilitator will put words into the cache whenever it decodes them. - */ + /** The facilitator will put words into the cache whenever it decodes them. */ void setValidSpellingWordReadCache(final LruCache cache); - /** - * The facilitator will get words from the cache whenever it needs to check their spelling. - */ + /** The facilitator will get words from the cache whenever it needs to check their spelling. */ void setValidSpellingWordWriteCache(final LruCache cache); /** @@ -77,56 +75,64 @@ public interface DictionaryFacilitator { */ void onFinishInput(Context context); + /** whether a dictionary is set */ boolean isActive(); + /** the locale provided in resetDictionaries */ @NonNull Locale getMainLocale(); - // useful for multilingual typing - Locale getCurrentLocale(); + /** the most "trusted" locale, differs from getMainLocale only if multilingual typing is used */ + @NonNull Locale getCurrentLocale(); boolean usesSameSettings( @NonNull final List locales, final boolean contacts, - final boolean personalization, - @Nullable final String account + final boolean apps, + final boolean personalization ); - String getAccount(); - + /** switches to newLocale, gets secondary locales from current settings, and sets secondary dictionaries */ void resetDictionaries( final Context context, final Locale newLocale, final boolean useContactsDict, + final boolean useAppsDict, final boolean usePersonalizedDicts, final boolean forceReloadMainDictionary, - @Nullable final String account, final String dictNamePrefix, @Nullable final DictionaryInitializationListener listener); + /** removes the word from all editable dictionaries, and adds it to a blacklist in case it's in a read-only dictionary */ void removeWord(String word); void closeDictionaries(); - // The main dictionaries are loaded asynchronously. Don't cache the return value - // of these methods. + /** main dictionaries are loaded asynchronously after resetDictionaries */ boolean hasAtLeastOneInitializedMainDictionary(); + /** main dictionaries are loaded asynchronously after resetDictionaries */ boolean hasAtLeastOneUninitializedMainDictionary(); + /** main dictionaries are loaded asynchronously after resetDictionaries */ void waitForLoadingMainDictionaries(final long timeout, final TimeUnit unit) throws InterruptedException; + /** adds the word to user history dictionary, calls adjustConfindences, and might add it to personal dictionary if the setting is enabled */ void addToUserHistory(final String suggestion, final boolean wasAutoCapitalized, @NonNull final NgramContext ngramContext, final long timeStampInSeconds, final boolean blockPotentiallyOffensive); + /** adjust confidences for multilingual typing */ void adjustConfidences(final String word, final boolean wasAutoCapitalized); + /** a string with all used locales and their current confidences, null if multilingual typing is not used */ + @Nullable String localesAndConfidences(); + + /** completely removes the word from user history (currently not if event is a backspace event) */ void unlearnFromUserHistory(final String word, @NonNull final NgramContext ngramContext, final long timeStampInSeconds, final int eventType); - // TODO: Revise the way to fusion suggestion results. @NonNull SuggestionResults getSuggestionResults(final ComposedData composedData, final NgramContext ngramContext, @NonNull final Keyboard keyboard, final SettingsValuesForSuggestion settingsValuesForSuggestion, final int sessionId, @@ -136,12 +142,10 @@ public interface DictionaryFacilitator { boolean isValidSuggestionWord(final String word); - boolean clearUserHistoryDictionary(final Context context); + void clearUserHistoryDictionary(final Context context); String dump(final Context context); - String localesAndConfidences(); - void dumpDictionaryForDebug(final String dictName); @NonNull List getDictionaryStats(final Context context); diff --git a/app/src/main/java/helium314/keyboard/latin/DictionaryFacilitatorImpl.java b/app/src/main/java/helium314/keyboard/latin/DictionaryFacilitatorImpl.java deleted file mode 100644 index e075b1290..000000000 --- a/app/src/main/java/helium314/keyboard/latin/DictionaryFacilitatorImpl.java +++ /dev/null @@ -1,1085 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * modified - * SPDX-License-Identifier: Apache-2.0 AND GPL-3.0-only - */ - -package helium314.keyboard.latin; - -import android.Manifest; -import android.content.Context; -import android.provider.UserDictionary; -import android.text.TextUtils; -import android.util.LruCache; -import android.view.inputmethod.InputMethodSubtype; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import helium314.keyboard.keyboard.Keyboard; -import helium314.keyboard.latin.NgramContext.WordInfo; -import helium314.keyboard.latin.SuggestedWords.SuggestedWordInfo; -import helium314.keyboard.latin.common.ComposedData; -import helium314.keyboard.latin.common.Constants; -import helium314.keyboard.latin.common.StringUtils; -import helium314.keyboard.latin.common.StringUtilsKt; -import helium314.keyboard.latin.permissions.PermissionsUtil; -import helium314.keyboard.latin.personalization.UserHistoryDictionary; -import helium314.keyboard.latin.settings.Settings; -import helium314.keyboard.latin.settings.SettingsValues; -import helium314.keyboard.latin.settings.SettingsValuesForSuggestion; -import helium314.keyboard.latin.utils.ExecutorUtils; -import helium314.keyboard.latin.utils.KtxKt; -import helium314.keyboard.latin.utils.Log; -import helium314.keyboard.latin.utils.SubtypeSettings; -import helium314.keyboard.latin.utils.SubtypeUtilsKt; -import helium314.keyboard.latin.utils.SuggestionResults; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Scanner; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -/** - * Facilitates interaction with different kinds of dictionaries. Provides APIs - * to instantiate and select the correct dictionaries (based on language or account), - * update entries and fetch suggestions. - *

    - * Currently AndroidSpellCheckerService and LatinIME both use DictionaryFacilitator as - * a client for interacting with dictionaries. - */ -public class DictionaryFacilitatorImpl implements DictionaryFacilitator { - public static final String TAG = DictionaryFacilitatorImpl.class.getSimpleName(); - - // HACK: This threshold is being used when adding a capitalized entry in the User History - // dictionary. - private static final int CAPITALIZED_FORM_MAX_PROBABILITY_FOR_INSERT = 140; - - private ArrayList mDictionaryGroups = new ArrayList<>() {{ add(new DictionaryGroup()); }}; - private volatile CountDownLatch mLatchForWaitingLoadingMainDictionaries = new CountDownLatch(0); - // To synchronize assigning mDictionaryGroup to ensure closing dictionaries. - private final Object mLock = new Object(); - // library does not deal well with ngram history for auto-capitalized words, so we adjust the ngram - // context to store next word suggestions for such cases - private boolean mTryChangingWords = false; - private String mChangeFrom = ""; - private String mChangeTo = ""; - - // todo: write cache never set, and never read (only written) - // tried to use read cache for a while, but small performance improvements are not worth the work (https://github.com/Helium314/HeliBoard/issues/307) - private LruCache mValidSpellingWordReadCache; - private LruCache mValidSpellingWordWriteCache; - - @Override - public void setValidSpellingWordReadCache(final LruCache cache) { - mValidSpellingWordReadCache = cache; - } - - @Override - public void setValidSpellingWordWriteCache(final LruCache cache) { - mValidSpellingWordWriteCache = cache; - } - - // judging by usage, this should check primary locale only - @Override - public boolean isForLocale(final Locale locale) { - return locale != null && locale.equals(mDictionaryGroups.get(0).mLocale); - } - - private boolean hasLocale(final Locale locale) { - if (locale == null) return false; - for (DictionaryGroup dictionaryGroup : mDictionaryGroups) { - if (locale.equals(dictionaryGroup.mLocale)) return true; - } - return false; - } - - /** - * A group of dictionaries that work together for a single language. - */ - private static class DictionaryGroup { - private static final int MAX_CONFIDENCE = 2; - - /** - * The locale associated with the dictionary group. - */ - @NonNull public final Locale mLocale; - - /** - * The user account associated with the dictionary group. - */ - @Nullable public final String mAccount; - - @Nullable private Dictionary mMainDict; - // Confidence that the most probable language is actually the language the user is - // typing in. For now, this is simply the number of times a word from this language - // has been committed in a row, with an exception when typing a single word not contained - // in this language. - private int mConfidence = 1; - - // words cannot be removed from main dictionary, so we use a blacklist instead - public String blacklistFileName = null; - public Set blacklist = new HashSet<>(); - - // allow to go above max confidence, for better determination of currently preferred language - // when decreasing confidence or getting weight factor, limit to maximum - public void increaseConfidence() { - mConfidence += 1; - } - - // If confidence is above max, drop to max confidence. This does not change weights and - // allows conveniently typing single words from the other language without affecting suggestions - public void decreaseConfidence() { - if (mConfidence > MAX_CONFIDENCE) - mConfidence = MAX_CONFIDENCE; - else if (mConfidence > 0) { - mConfidence -= 1; - } - } - - public float getWeightForTypingInLocale(List groups) { - return getWeightForLocale(groups, 0.15f); - } - - public float getWeightForGesturingInLocale(List groups) { - return getWeightForLocale(groups, 0.05f); - } - - // might need some more tuning - private float getWeightForLocale(final List groups, final float step) { - if (groups.size() == 1) return 1f; - if (mConfidence < 2) return 1f - step * (MAX_CONFIDENCE - mConfidence); - for (DictionaryGroup group : groups) { - if (group != this && group.mConfidence >= mConfidence) return 1f - step / 2f; - } - return 1f; - } - public final ConcurrentHashMap mSubDictMap = - new ConcurrentHashMap<>(); - - public DictionaryGroup() { - this(new Locale(""), null, null, Collections.emptyMap()); - } - - public DictionaryGroup(@NonNull final Locale locale, - @Nullable final Dictionary mainDict, - @Nullable final String account, - @NonNull final Map subDicts) { - mLocale = locale; - mAccount = account; - // The main dictionary can be asynchronously loaded. - setMainDict(mainDict); - for (final Map.Entry entry : subDicts.entrySet()) { - setSubDict(entry.getKey(), entry.getValue()); - } - } - - private void setSubDict(@NonNull final String dictType, @NonNull final ExpandableBinaryDictionary dict) { - mSubDictMap.put(dictType, dict); - } - - public void setMainDict(@Nullable final Dictionary mainDict) { - // Close old dictionary if exists. Main dictionary can be assigned multiple times. - final Dictionary oldDict = mMainDict; - mMainDict = mainDict; - if (oldDict != null && mainDict != oldDict) { - oldDict.close(); - } - } - - public @Nullable Dictionary getDict(@NonNull final String dictType) { - if (Dictionary.TYPE_MAIN.equals(dictType)) { - return mMainDict; - } - return getSubDict(dictType); - } - - public @Nullable ExpandableBinaryDictionary getSubDict(@NonNull final String dictType) { - return mSubDictMap.get(dictType); - } - - public boolean hasDict(@NonNull final String dictType, @Nullable final String account) { - if (Dictionary.TYPE_MAIN.equals(dictType)) { - return mMainDict != null; - } - if (Dictionary.TYPE_USER_HISTORY.equals(dictType) && - !TextUtils.equals(account, mAccount)) { - // If the dictionary type is user history, & if the account doesn't match, - // return immediately. If the account matches, continue looking it up in the - // sub dictionary map. - return false; - } - return mSubDictMap.containsKey(dictType); - } - - public void closeDict(@NonNull final String dictType) { - final Dictionary dict; - if (Dictionary.TYPE_MAIN.equals(dictType)) { - dict = mMainDict; - } else { - dict = mSubDictMap.remove(dictType); - } - if (dict != null) { - dict.close(); - } - } - } - - public DictionaryFacilitatorImpl() { - } - - @Override - public void onStartInput() { - } - - @Override - public void onFinishInput(Context context) { - for (DictionaryGroup dictionaryGroup : mDictionaryGroups) { - for (final String dictType : ALL_DICTIONARY_TYPES) { - Dictionary dict = dictionaryGroup.getDict(dictType); - if (dict != null) dict.onFinishInput(); - } - } - } - - @Override - public boolean isActive() { - return !mDictionaryGroups.get(0).mLocale.getLanguage().isEmpty(); - } - - @Override - @NonNull - public Locale getMainLocale() { - return mDictionaryGroups.get(0).mLocale; - } - - @Override - public Locale getCurrentLocale() { - return getCurrentlyPreferredDictionaryGroup().mLocale; - } - - public boolean usesContacts() { - return mDictionaryGroups.get(0).getSubDict(Dictionary.TYPE_CONTACTS) != null; - } - - public boolean usesPersonalization() { - return mDictionaryGroups.get(0).getSubDict(Dictionary.TYPE_USER_HISTORY) != null; - } - - @Override - public String getAccount() { - return null; - } - - @Override - public boolean usesSameSettings(@NonNull final List locales, final boolean contacts, - final boolean personalization, @Nullable final String account) { - final boolean first = usesContacts() == contacts && usesPersonalization() == personalization - && TextUtils.equals(mDictionaryGroups.get(0).mAccount, account) - && locales.size() == mDictionaryGroups.size(); - if (!first) return false; - for (int i = 0; i < locales.size(); i++) { - if (locales.get(i) != mDictionaryGroups.get(i).mLocale) return false; - } - return true; - } - - @Nullable - private static ExpandableBinaryDictionary getSubDict(final String dictType, - final Context context, final Locale locale, final File dictFile, - final String dictNamePrefix, @Nullable final String account) { - ExpandableBinaryDictionary dict = null; - try { - dict = switch (dictType) { - case Dictionary.TYPE_USER_HISTORY -> UserHistoryDictionary.getDictionary(context, locale, dictFile, dictNamePrefix, account); - case Dictionary.TYPE_USER -> UserBinaryDictionary.getDictionary(context, locale, dictFile, dictNamePrefix, account); - case Dictionary.TYPE_CONTACTS -> ContactsBinaryDictionary.getDictionary(context, locale, dictFile, dictNamePrefix, account); - default -> null; - }; - } catch (final SecurityException | IllegalArgumentException e) { - Log.e(TAG, "Cannot create dictionary: " + dictType, e); - } - if (dict == null) - Log.e(TAG, "Cannot create dictionary for " + dictType); - return dict; - } - - @Nullable - static DictionaryGroup findDictionaryGroupWithLocale(final List dictionaryGroups, - @NonNull final Locale locale) { - if (dictionaryGroups == null) return null; - for (DictionaryGroup dictionaryGroup : dictionaryGroups) { - if (locale.equals(dictionaryGroup.mLocale)) - return dictionaryGroup; - } - return null; - } - - // original - public void resetDictionaries( - final Context context, - @NonNull final Locale newLocale, - final boolean useContactsDict, - final boolean usePersonalizedDicts, - final boolean forceReloadMainDictionary, - @Nullable final String account, - final String dictNamePrefix, - @Nullable final DictionaryInitializationListener listener) { - final HashMap> existingDictionariesToCleanup = new HashMap<>(); - final HashSet subDictTypesToUse = new HashSet<>(); - subDictTypesToUse.add(Dictionary.TYPE_USER); - Log.i(TAG, "resetDictionaries, force reloading main dictionary: " + forceReloadMainDictionary); - final List allLocales = new ArrayList<>() {{ - add(newLocale); - - // adding secondary locales is a bit tricky since they depend on the subtype - // but usually this is called with the selected subtype locale - final InputMethodSubtype selected = SubtypeSettings.INSTANCE.getSelectedSubtype(KtxKt.prefs(context)); - if (SubtypeUtilsKt.locale(selected).equals(newLocale)) { - addAll(SubtypeUtilsKt.getSecondaryLocales(selected.getExtraValue())); - } else { - // probably we're called from the spell checker when using a different app as keyboard - final List enabled = SubtypeSettings.INSTANCE.getEnabledSubtypes(false); - for (InputMethodSubtype subtype : enabled) { - if (SubtypeUtilsKt.locale(subtype).equals(newLocale)) - addAll(SubtypeUtilsKt.getSecondaryLocales(subtype.getExtraValue())); - } - } - }}; - - // Do not use contacts dictionary if we do not have permissions to read contacts. - if (useContactsDict - && PermissionsUtil.checkAllPermissionsGranted(context, Manifest.permission.READ_CONTACTS)) { - subDictTypesToUse.add(Dictionary.TYPE_CONTACTS); - } - if (usePersonalizedDicts) { - subDictTypesToUse.add(Dictionary.TYPE_USER_HISTORY); - } - - // Gather all dictionaries by locale. We may remove some from the list to clean up later. - for (DictionaryGroup dictionaryGroup : mDictionaryGroups) { - final ArrayList dictTypeForLocale = new ArrayList<>(); - existingDictionariesToCleanup.put(dictionaryGroup.mLocale, dictTypeForLocale); - - for (final String dictType : DYNAMIC_DICTIONARY_TYPES) { - if (dictionaryGroup.hasDict(dictType, account)) { - dictTypeForLocale.add(dictType); - } - } - if (dictionaryGroup.hasDict(Dictionary.TYPE_MAIN, account)) { - dictTypeForLocale.add(Dictionary.TYPE_MAIN); - } - } - - // create new dictionary groups and remove dictionaries to re-use from existingDictionariesToCleanup - final ArrayList newDictionaryGroups = new ArrayList<>(allLocales.size()); - for (Locale locale : allLocales) { - // get existing dictionary group for new locale - final DictionaryGroup oldDictionaryGroupForLocale = findDictionaryGroupWithLocale(mDictionaryGroups, locale); - final ArrayList dictTypesToCleanupForLocale = existingDictionariesToCleanup.get(locale); - final boolean noExistingDictsForThisLocale = (null == oldDictionaryGroupForLocale); - - // create new or re-use already loaded main dict - final Dictionary mainDict; - if (forceReloadMainDictionary || noExistingDictsForThisLocale - || !oldDictionaryGroupForLocale.hasDict(Dictionary.TYPE_MAIN, account)) { - mainDict = null; - } else { - mainDict = oldDictionaryGroupForLocale.getDict(Dictionary.TYPE_MAIN); - dictTypesToCleanupForLocale.remove(Dictionary.TYPE_MAIN); - } - - // create new or re-use already loaded sub-dicts - final Map subDicts = new HashMap<>(); - for (final String subDictType : subDictTypesToUse) { - final ExpandableBinaryDictionary subDict; - if (noExistingDictsForThisLocale || forceReloadMainDictionary - || !oldDictionaryGroupForLocale.hasDict(subDictType, account)) { - // Create a new dictionary. - subDict = getSubDict(subDictType, context, locale, null, dictNamePrefix, account); - if (subDict == null) continue; // https://github.com/Helium314/HeliBoard/issues/293 - } else { - // Reuse the existing dictionary, and don't close it at the end - subDict = oldDictionaryGroupForLocale.getSubDict(subDictType); - dictTypesToCleanupForLocale.remove(subDictType); - } - subDicts.put(subDictType, subDict); - } - DictionaryGroup newDictGroup = new DictionaryGroup(locale, mainDict, account, subDicts); - newDictionaryGroups.add(newDictGroup); - - // load blacklist - if (noExistingDictsForThisLocale) { - newDictGroup.blacklistFileName = context.getFilesDir().getAbsolutePath() + File.separator + "blacklists" + File.separator + locale.toLanguageTag() + ".txt"; - if (!new File(newDictGroup.blacklistFileName).exists()) - new File(context.getFilesDir().getAbsolutePath() + File.separator + "blacklists").mkdirs(); - newDictGroup.blacklist.addAll(readBlacklistFile(newDictGroup.blacklistFileName)); - } else { - // re-use if possible - newDictGroup.blacklistFileName = oldDictionaryGroupForLocale.blacklistFileName; - newDictGroup.blacklist.addAll(oldDictionaryGroupForLocale.blacklist); - } - } - - - // Replace Dictionaries. - final List oldDictionaryGroups; - synchronized (mLock) { - oldDictionaryGroups = mDictionaryGroups; - mDictionaryGroups = newDictionaryGroups; - if (hasAtLeastOneUninitializedMainDictionary()) { - asyncReloadUninitializedMainDictionaries(context, allLocales, listener); - } - } - - if (listener != null) { - listener.onUpdateMainDictionaryAvailability(hasAtLeastOneInitializedMainDictionary()); - } - - // Clean up old dictionaries. - for (final Locale localeToCleanUp : existingDictionariesToCleanup.keySet()) { - final ArrayList dictTypesToCleanUp = existingDictionariesToCleanup.get(localeToCleanUp); - final DictionaryGroup dictionarySetToCleanup = findDictionaryGroupWithLocale(oldDictionaryGroups, localeToCleanUp); - for (final String dictType : dictTypesToCleanUp) { - dictionarySetToCleanup.closeDict(dictType); - } - } - - if (mValidSpellingWordWriteCache != null) { - mValidSpellingWordWriteCache.evictAll(); - } - if (mValidSpellingWordReadCache != null) { - mValidSpellingWordReadCache.evictAll(); - } - } - - private void asyncReloadUninitializedMainDictionaries(final Context context, - final List locales, final DictionaryInitializationListener listener) { - final CountDownLatch latchForWaitingLoadingMainDictionary = new CountDownLatch(1); - mLatchForWaitingLoadingMainDictionaries = latchForWaitingLoadingMainDictionary; - ExecutorUtils.getBackgroundExecutor(ExecutorUtils.KEYBOARD).execute(() -> - doReloadUninitializedMainDictionaries(context, locales, listener, latchForWaitingLoadingMainDictionary)); - } - - void doReloadUninitializedMainDictionaries(final Context context, final List locales, - final DictionaryInitializationListener listener, - final CountDownLatch latchForWaitingLoadingMainDictionary) { - final Dictionary[] mainDicts = new Dictionary[locales.size()]; - final ArrayList dictionaryGroups = new ArrayList<>(); - for (int i = 0; i < locales.size(); i++) { - Locale locale = locales.get(i); - DictionaryGroup dictionaryGroup = findDictionaryGroupWithLocale(mDictionaryGroups, locale); - if (null == dictionaryGroup) { - // This should never happen, but better safe than crashy - Log.w(TAG, "Expected a dictionary group for " + locale + " but none found"); - return; - } - dictionaryGroups.add(dictionaryGroup); - // do nothing if main dict already initialized - if (dictionaryGroup.mMainDict != null && dictionaryGroup.mMainDict.isInitialized()) { - mainDicts[i] = null; - continue; - } - mainDicts[i] = DictionaryFactoryKt.createMainDictionary(context, dictionaryGroup.mLocale); - } - - synchronized (mLock) { - for (int i = 0; i < locales.size(); i++) { - final Locale locale = locales.get(i); - if (mainDicts[i] == null) - continue; - if (locale.equals(dictionaryGroups.get(i).mLocale)) { - dictionaryGroups.get(i).setMainDict(mainDicts[i]); - } else { - // Dictionary facilitator has been reset for another locale. - mainDicts[i].close(); - } - } - } - if (listener != null) { - listener.onUpdateMainDictionaryAvailability(hasAtLeastOneInitializedMainDictionary()); - } - latchForWaitingLoadingMainDictionary.countDown(); - } - - public void closeDictionaries() { - final ArrayList dictionaryGroupsToClose; - synchronized (mLock) { - dictionaryGroupsToClose = new ArrayList<>(mDictionaryGroups); - mDictionaryGroups.clear(); - mDictionaryGroups.add(new DictionaryGroup()); - } - for (DictionaryGroup dictionaryGroup : dictionaryGroupsToClose) { - for (final String dictType : ALL_DICTIONARY_TYPES) { - dictionaryGroup.closeDict(dictType); - } - } - } - - // The main dictionaries are loaded asynchronously. Don't cache the return value - // of these methods. - public boolean hasAtLeastOneInitializedMainDictionary() { - for (DictionaryGroup dictionaryGroup : mDictionaryGroups) { - final Dictionary mainDict = dictionaryGroup.getDict(Dictionary.TYPE_MAIN); - if (mainDict != null && mainDict.isInitialized()) return true; - } - return false; - } - - public boolean hasAtLeastOneUninitializedMainDictionary() { - for (DictionaryGroup dictionaryGroup : mDictionaryGroups) { - final Dictionary mainDict = dictionaryGroup.getDict(Dictionary.TYPE_MAIN); - if (mainDict == null || !mainDict.isInitialized()) return true; - } - return false; - } - - public void waitForLoadingMainDictionaries(final long timeout, final TimeUnit unit) - throws InterruptedException { - mLatchForWaitingLoadingMainDictionaries.await(timeout, unit); - } - - public void addToUserHistory(final String suggestion, final boolean wasAutoCapitalized, - @NonNull final NgramContext ngramContext, final long timeStampInSeconds, - final boolean blockPotentiallyOffensive) { - // Update the spelling cache before learning. Words that are not yet added to user history - // and appear in no other language model are not considered valid. - putWordIntoValidSpellingWordCache("addToUserHistory", suggestion); - - final String[] words = suggestion.split(Constants.WORD_SEPARATOR); - - // increase / decrease confidence if we have more than one dictionary group - boolean[] validWordForDictionary; // store results to avoid unnecessary duplicate lookups - if (mDictionaryGroups.size() > 1 && words.length == 1) { // ignore if more than a single word, this only happens with (badly working) spaceAwareGesture - validWordForDictionary = adjustConfidencesInternal(suggestion, wasAutoCapitalized); - } else - validWordForDictionary = null; - - // add word to user dictionary if it is in no other dictionary except user history dictionary, - // reasoning: typing the same word again -> we probably want it in some dictionary permanently - final SettingsValues sv = Settings.getValues(); - if (sv.mAddToPersonalDictionary // require the setting - && sv.mAutoCorrectEnabled == sv.mAutoCorrectionEnabledPerUserSettings // don't add if user wants autocorrect but input field does not, see https://github.com/Helium314/HeliBoard/issues/427#issuecomment-1905438000 - && mDictionaryGroups.get(0).hasDict(Dictionary.TYPE_USER_HISTORY, mDictionaryGroups.get(0).mAccount) // require personalized suggestions - && !wasAutoCapitalized // we can't be 100% sure about what the user intended to type, so better don't add it - && words.length == 1) { // ignore if more than a single word, this only happens with (badly working) spaceAwareGesture - addToPersonalDictionaryIfInvalidButInHistory(suggestion, validWordForDictionary); - } - - NgramContext ngramContextForCurrentWord = ngramContext; - for (int i = 0; i < words.length; i++) { - final String currentWord = words[i]; - final boolean wasCurrentWordAutoCapitalized = (i == 0) && wasAutoCapitalized; - // add to history for preferred dictionary group, to avoid mixing languages in history - addWordToUserHistory(getCurrentlyPreferredDictionaryGroup(), ngramContextForCurrentWord, currentWord, - wasCurrentWordAutoCapitalized, (int) timeStampInSeconds, - blockPotentiallyOffensive); - ngramContextForCurrentWord = - ngramContextForCurrentWord.getNextNgramContext(new WordInfo(currentWord)); - - // remove manually entered blacklisted words from blacklist - for (DictionaryGroup dictionaryGroup : mDictionaryGroups) { - if (dictionaryGroup.blacklist.remove(currentWord)) - removeWordFromBlacklistFile(currentWord, dictionaryGroup.blacklistFileName); - } - } - } - - @Override public void adjustConfidences(final String word, final boolean wasAutoCapitalized) { - if (mDictionaryGroups.size() > 1 && !word.contains(Constants.WORD_SEPARATOR)) - adjustConfidencesInternal(word, wasAutoCapitalized); - } - - private boolean[] adjustConfidencesInternal(final String word, final boolean wasAutoCapitalized) { - final boolean[] validWordForDictionary = new boolean[mDictionaryGroups.size()]; - // if suggestion was auto-capitalized, check against both the suggestion and the de-capitalized suggestion - final String decapitalizedSuggestion; - if (wasAutoCapitalized) - decapitalizedSuggestion = StringUtilsKt.decapitalize(word, getCurrentLocale()); - else - decapitalizedSuggestion = word; - for (int i = 0; i < mDictionaryGroups.size(); i ++) { - final DictionaryGroup dictionaryGroup = mDictionaryGroups.get(i); - final boolean isValidWord = isValidWord(word, ALL_DICTIONARY_TYPES, dictionaryGroup); - if (isValidWord || (wasAutoCapitalized && isValidWord(decapitalizedSuggestion, ALL_DICTIONARY_TYPES, dictionaryGroup))) - dictionaryGroup.increaseConfidence(); - else dictionaryGroup.decreaseConfidence(); - validWordForDictionary[i] = isValidWord; - } - return validWordForDictionary; - } - - // main and secondary isValid provided to avoid duplicate lookups - private void addToPersonalDictionaryIfInvalidButInHistory(String word, boolean[] validWordForDictionary) { - final DictionaryGroup dictionaryGroup = getClearlyPreferredDictionaryGroupOrNull(); - if (dictionaryGroup == null) return; - if (validWordForDictionary == null - ? isValidWord(word, ALL_DICTIONARY_TYPES, dictionaryGroup) - : validWordForDictionary[mDictionaryGroups.indexOf(dictionaryGroup)] - ) - return; - - final ExpandableBinaryDictionary userDict = dictionaryGroup.getSubDict(Dictionary.TYPE_USER); - final Dictionary userHistoryDict = dictionaryGroup.getSubDict(Dictionary.TYPE_USER_HISTORY); - if (userDict == null || userHistoryDict == null) return; - - // user history always reports words as invalid, so here we need to check isInDictionary instead - // update: now getFrequency returns the correct value instead of -1, so better use that - // a little testing shows that after 2 times adding, the frequency is 111, and then rises slowly with usage - // 120 is after 3 uses of the word, so we simply require more than that. - // also maybe a problem: words added to dictionaries (user and history) are apparently found - // only after some delay. but this is not too bad, it just delays adding - if (userHistoryDict.getFrequency(word) > 120) { - if (userDict.isInDictionary(word)) // is this check necessary? - return; - ExecutorUtils.getBackgroundExecutor(ExecutorUtils.KEYBOARD).execute(() -> - UserDictionary.Words.addWord(userDict.mContext, word, - 250 /*FREQUENCY_FOR_USER_DICTIONARY_ADDS*/, null, dictionaryGroup.mLocale)); - } - } - - private void putWordIntoValidSpellingWordCache( - @NonNull final String caller, - @NonNull final String originalWord) { - if (mValidSpellingWordWriteCache == null) { - return; - } - - final String lowerCaseWord = originalWord.toLowerCase(getCurrentLocale()); - final boolean lowerCaseValid = isValidSpellingWord(lowerCaseWord); - mValidSpellingWordWriteCache.put(lowerCaseWord, lowerCaseValid); - - final String capitalWord = - StringUtils.capitalizeFirstAndDowncaseRest(originalWord, getCurrentLocale()); - final boolean capitalValid; - if (lowerCaseValid) { - // The lower case form of the word is valid, so the upper case must be valid. - capitalValid = true; - } else { - capitalValid = isValidSpellingWord(capitalWord); - } - mValidSpellingWordWriteCache.put(capitalWord, capitalValid); - } - - private void addWordToUserHistory(final DictionaryGroup dictionaryGroup, - final NgramContext ngramContext, final String word, final boolean wasAutoCapitalized, - final int timeStampInSeconds, final boolean blockPotentiallyOffensive) { - final ExpandableBinaryDictionary userHistoryDictionary = - dictionaryGroup.getSubDict(Dictionary.TYPE_USER_HISTORY); - if (userHistoryDictionary == null || !hasLocale(userHistoryDictionary.mLocale)) { - return; - } - final int mainFreq = dictionaryGroup.hasDict(Dictionary.TYPE_MAIN, null) - ? dictionaryGroup.getDict(Dictionary.TYPE_MAIN).getFrequency(word) - : Dictionary.NOT_A_PROBABILITY; - if (mainFreq == 0 && blockPotentiallyOffensive) { - return; - } - if (mTryChangingWords) - mTryChangingWords = ngramContext.changeWordIfAfterBeginningOfSentence(mChangeFrom, mChangeTo); - final String secondWord; - // check for isBeginningOfSentenceContext too, because not all text fields auto-capitalize in this case - // and even if the user capitalizes manually, they most likely don't want the capitalized form suggested - if (wasAutoCapitalized || ngramContext.isBeginningOfSentenceContext()) { - // used word with lower-case first letter instead of all lower-case, as auto-capitalize - // does not affect the other letters - final String decapitalizedWord = StringUtilsKt.decapitalize(word, dictionaryGroup.mLocale); - if (isValidWord(word, ALL_DICTIONARY_TYPES, dictionaryGroup) && !isValidWord(decapitalizedWord, ALL_DICTIONARY_TYPES, dictionaryGroup)) { - // If the word was auto-capitalized and exists only as a capitalized word in the - // dictionary, then we must not downcase it before registering it. For example, - // the name of the contacts in start-of-sentence position would come here with the - // wasAutoCapitalized flag: if we downcase it, we'd register a lower-case version - // of that contact's name which would end up popping in suggestions. - secondWord = word; - } else { - // If however the word is not in the dictionary, or exists as a de-capitalized word - // only, then we consider that was a lower-case word that had been auto-capitalized. - secondWord = decapitalizedWord; - mTryChangingWords = true; - mChangeFrom = word; - mChangeTo = secondWord; - } - } else { - // HACK: We'd like to avoid adding the capitalized form of common words to the User - // History dictionary in order to avoid suggesting them until the dictionary - // consolidation is done. - // TODO: Remove this hack when ready. - final String lowerCasedWord = word.toLowerCase(dictionaryGroup.mLocale); - final int lowerCaseFreqInMainDict = dictionaryGroup.hasDict(Dictionary.TYPE_MAIN, null) - ? dictionaryGroup.getDict(Dictionary.TYPE_MAIN).getFrequency(lowerCasedWord) - : Dictionary.NOT_A_PROBABILITY; - if (mainFreq < lowerCaseFreqInMainDict - && lowerCaseFreqInMainDict >= CAPITALIZED_FORM_MAX_PROBABILITY_FOR_INSERT) { - // Use lower cased word as the word can be a distracter of the popular word. - secondWord = lowerCasedWord; - } else { - secondWord = word; - } - } - // We demote unrecognized words (frequency < 0, below) by specifying them as "invalid". - // We don't add words with 0-frequency (assuming they would be profanity etc.). - // comment: so this means words not in main dict are always invalid... weird (but still works) - final boolean isValid = mainFreq > 0; - UserHistoryDictionary.addToDictionary(userHistoryDictionary, ngramContext, secondWord, - isValid, timeStampInSeconds); - } - - /** returns the dictionaryGroup with most confidence, first group when tied */ - private DictionaryGroup getCurrentlyPreferredDictionaryGroup() { - DictionaryGroup dictGroup = null; - int highestConfidence = -1; - for (DictionaryGroup dictionaryGroup : mDictionaryGroups) { - if (dictionaryGroup.mConfidence > highestConfidence) { - dictGroup = dictionaryGroup; - highestConfidence = dictGroup.mConfidence; - } - } - return dictGroup; - } - - private DictionaryGroup getClearlyPreferredDictionaryGroupOrNull() { - // we want one clearly preferred group and return null otherwise - if (mDictionaryGroups.size() == 1) - return mDictionaryGroups.get(0); - // that preferred group should have at least MAX_CONFIDENCE, and all others should have 0 (we want to be really sure!) - int preferredGroup = -1; - for (int i = 0; i < mDictionaryGroups.size(); i ++) { - final DictionaryGroup dictionaryGroup = mDictionaryGroups.get(i); - if (dictionaryGroup.mConfidence == 0) continue; - if (dictionaryGroup.mConfidence >= DictionaryGroup.MAX_CONFIDENCE && preferredGroup == -1) { - preferredGroup = i; - continue; - } - // either we have 2 groups with high confidence, or a group with low but non-0 confidence - // in either case, we're not sure enough and return null - return null; - } - if (preferredGroup == -1) return null; - return mDictionaryGroups.get(preferredGroup); - } - - private void removeWord(final String dictName, final String word) { - final ExpandableBinaryDictionary dictionary = getCurrentlyPreferredDictionaryGroup().getSubDict(dictName); - if (dictionary != null) { - dictionary.removeUnigramEntryDynamically(word); - } - } - - @Override - public void unlearnFromUserHistory(final String word, - @NonNull final NgramContext ngramContext, final long timeStampInSeconds, - final int eventType) { - // TODO: Decide whether or not to remove the word on EVENT_BACKSPACE. - if (eventType != Constants.EVENT_BACKSPACE) { - removeWord(Dictionary.TYPE_USER_HISTORY, word); - } - - // Update the spelling cache after unlearning. Words that are removed from user history - // and appear in no other language model are not considered valid. - putWordIntoValidSpellingWordCache("unlearnFromUserHistory", word.toLowerCase()); - } - - // TODO: Revise the way to fusion suggestion results. - @Override - @SuppressWarnings("unchecked") - @NonNull public SuggestionResults getSuggestionResults(ComposedData composedData, - NgramContext ngramContext, @NonNull final Keyboard keyboard, - SettingsValuesForSuggestion settingsValuesForSuggestion, int sessionId, - int inputStyle) { - long proximityInfoHandle = keyboard.getProximityInfo().getNativeProximityInfo(); - final SuggestionResults suggestionResults = new SuggestionResults( - SuggestedWords.MAX_SUGGESTIONS, ngramContext.isBeginningOfSentenceContext(), - false /* firstSuggestionExceedsConfidenceThreshold */); - final float[] weightOfLangModelVsSpatialModel = - new float[] { Dictionary.NOT_A_WEIGHT_OF_LANG_MODEL_VS_SPATIAL_MODEL }; - - // start getting suggestions for non-main locales first, but in background - final ArrayList[] otherDictionarySuggestions = (ArrayList[]) new ArrayList[mDictionaryGroups.size() - 1]; - final CountDownLatch waitForOtherDictionaries; - if (mDictionaryGroups.size() > 1) { - waitForOtherDictionaries = new CountDownLatch(mDictionaryGroups.size() - 1); - for (int i = 1; i < mDictionaryGroups.size(); i ++) { - final DictionaryGroup dictionaryGroup = mDictionaryGroups.get(i); - final int index = i - 1; - ExecutorUtils.getBackgroundExecutor(ExecutorUtils.KEYBOARD).execute(() -> { - otherDictionarySuggestions[index] = getSuggestions(composedData, - ngramContext, settingsValuesForSuggestion, sessionId, proximityInfoHandle, - weightOfLangModelVsSpatialModel, dictionaryGroup); - waitForOtherDictionaries.countDown(); - }); - } - } else - waitForOtherDictionaries = null; - - // get main locale suggestions - final ArrayList dictionarySuggestions = getSuggestions(composedData, - ngramContext, settingsValuesForSuggestion, sessionId, proximityInfoHandle, - weightOfLangModelVsSpatialModel, mDictionaryGroups.get(0)); - suggestionResults.addAll(dictionarySuggestions); - if (null != suggestionResults.mRawSuggestions) { - suggestionResults.mRawSuggestions.addAll(dictionarySuggestions); - } - - // wait for other locale suggestions - if (waitForOtherDictionaries != null) { - try { waitForOtherDictionaries.await(); } - catch (InterruptedException e) { - Log.w(TAG, "Interrupted while trying to get secondary locale suggestions", e); - } - for (int i = 1; i < mDictionaryGroups.size(); i ++) { - suggestionResults.addAll(otherDictionarySuggestions[i - 1]); - if (null != suggestionResults.mRawSuggestions) { - suggestionResults.mRawSuggestions.addAll(otherDictionarySuggestions[i - 1]); - } - } - } - - return suggestionResults; - } - - private ArrayList getSuggestions(ComposedData composedData, - NgramContext ngramContext, SettingsValuesForSuggestion settingsValuesForSuggestion, - int sessionId, long proximityInfoHandle, float[] weightOfLangModelVsSpatialModel, - DictionaryGroup dictGroup) { - final ArrayList suggestions = new ArrayList<>(); - float weightForLocale = composedData.mIsBatchMode - ? dictGroup.getWeightForGesturingInLocale(mDictionaryGroups) - : dictGroup.getWeightForTypingInLocale(mDictionaryGroups); - for (final String dictType : ALL_DICTIONARY_TYPES) { - final Dictionary dictionary = dictGroup.getDict(dictType); - if (null == dictionary) continue; - final ArrayList dictionarySuggestions = - dictionary.getSuggestions(composedData, ngramContext, - proximityInfoHandle, settingsValuesForSuggestion, sessionId, - weightForLocale, weightOfLangModelVsSpatialModel); - if (null == dictionarySuggestions) continue; - - // for some reason, garbage words are produced when glide typing - // for user history and main dictionary we can filter them out by checking whether the - // dictionary actually contains the word - // but personal dictionary and addon dictionaries may contain shortcuts, which do not - // pass an isInDictionary check (e.g. emojis) - // (if the main dict contains shortcuts to non-words, this will break) - final boolean checkForGarbage = composedData.mIsBatchMode && (dictType.equals(Dictionary.TYPE_USER_HISTORY) || dictType.equals(Dictionary.TYPE_MAIN)); - for (SuggestedWordInfo info : dictionarySuggestions) { - final String word = info.getWord(); - if (!isBlacklisted(word)) { // don't add blacklisted words - if (checkForGarbage - // only check history and "main main dictionary" - // consider the user might use custom main dictionary containing shortcuts - // assume this is unlikely to happen, and take care about common shortcuts that are not actual words (emoji, symbols) - && word.length() > 2 // should exclude most symbol shortcuts - && info.mSourceDict.mDictType.equals(dictType) // dictType is always main, but info.mSourceDict.mDictType contains the actual dict (main dict is a dictionary group) - && !StringUtils.mightBeEmoji(word) // emojis often have more than 2 chars; simplified check for performance reasons - && !dictionary.isInDictionary(word)) - continue; - suggestions.add(info); - } - } - } - return suggestions; - } - - // Spell checker is using this, and has its own instance of DictionaryFacilitatorImpl, - // meaning that it always has default mConfidence. So we cannot choose to only check preferred - // locale, and instead simply return true if word is in any of the available dictionaries - public boolean isValidSpellingWord(final String word) { - if (mValidSpellingWordReadCache != null) { - final Boolean cachedValue = mValidSpellingWordReadCache.get(word); - if (cachedValue != null) { - return cachedValue; - } - } - boolean result = false; - for (DictionaryGroup dictionaryGroup : mDictionaryGroups) { - if (isValidWord(word, ALL_DICTIONARY_TYPES, dictionaryGroup)) { - result = true; - break; - } - } - if (mValidSpellingWordReadCache != null) - mValidSpellingWordReadCache.put(word, result); - return result; - } - - // this is unused, so leave it for now (redirecting to isValidWord seems to defeat the purpose...) - public boolean isValidSuggestionWord(final String word) { - return isValidWord(word, ALL_DICTIONARY_TYPES, mDictionaryGroups.get(0)); - } - - private boolean isValidWord(final String word, final String[] dictionariesToCheck, final DictionaryGroup dictionaryGroup) { - if (TextUtils.isEmpty(word)) { - return false; - } - if (isBlacklisted(word)) return false; - for (final String dictType : dictionariesToCheck) { - final Dictionary dictionary = dictionaryGroup.getDict(dictType); - // Ideally the passed map would come out of a {@link java.util.concurrent.Future} and - // would be immutable once it's finished initializing, but concretely a null test is - // probably good enough for the time being. - if (null == dictionary) continue; - if (dictionary.isValidWord(word)) { - return true; - } - } - return false; - } - - private boolean isBlacklisted(final String word) { - for (DictionaryGroup dictionaryGroup : mDictionaryGroups) { - if (dictionaryGroup.blacklist.contains(word)) - return true; - } - return false; - } - - @Override - public void removeWord(String word) { - for (DictionaryGroup dictionaryGroup : mDictionaryGroups) { - removeWordFromGroup(word, dictionaryGroup); - } - } - - private void removeWordFromGroup(String word, DictionaryGroup group) { - // remove from user history - final ExpandableBinaryDictionary historyDict = group.getSubDict(Dictionary.TYPE_USER_HISTORY); - if (historyDict != null) { - historyDict.removeUnigramEntryDynamically(word); - } - // and from personal dictionary - final ExpandableBinaryDictionary userDict = group.getSubDict(Dictionary.TYPE_USER); - if (userDict != null) { - userDict.removeUnigramEntryDynamically(word); - } - - final ExpandableBinaryDictionary contactsDict = group.getSubDict(Dictionary.TYPE_CONTACTS); - if (contactsDict != null) { - if (contactsDict.isInDictionary(word)) { - contactsDict.removeUnigramEntryDynamically(word); // will be gone until next reload of dict - addToBlacklist(word, group); - return; - } - } - if (!group.hasDict(Dictionary.TYPE_MAIN, null)) - return; - if (group.getDict(Dictionary.TYPE_MAIN).isValidWord(word)) { - addToBlacklist(word, group); - return; - } - final String lowercase = word.toLowerCase(group.mLocale); - if (group.getDict(Dictionary.TYPE_MAIN).isValidWord(lowercase)) { - addToBlacklist(lowercase, group); - } - } - - private void addToBlacklist(final String word, final DictionaryGroup group) { - if (!group.blacklist.add(word)) - return; - ExecutorUtils.getBackgroundExecutor(ExecutorUtils.KEYBOARD).execute(() -> { - try { - FileOutputStream fos = new FileOutputStream(group.blacklistFileName, true); - fos.write((word + "\n").getBytes(StandardCharsets.UTF_8)); - fos.close(); - } catch (IOException e) { - Log.e(TAG, "Exception while trying to write blacklist", e); - } - }); - } - - private ArrayList readBlacklistFile(final String filename) { - final ArrayList blacklist = new ArrayList<>(); - if (filename == null) return blacklist; - File blacklistFile = new File(filename); - if (!blacklistFile.exists()) return blacklist; - try { - final Scanner scanner = new Scanner(blacklistFile, StandardCharsets.UTF_8.name()).useDelimiter("\n"); - while (scanner.hasNext()) { - blacklist.add(scanner.next()); - } - } catch (IOException e) { - Log.e(TAG, "Exception while reading blacklist", e); - } - return blacklist; - } - - private void removeWordFromBlacklistFile(String word, String filename) { - ExecutorUtils.getBackgroundExecutor(ExecutorUtils.KEYBOARD).execute(() -> { - try { - ArrayList blacklist = readBlacklistFile(filename); - blacklist.remove(word); - FileOutputStream fos = new FileOutputStream(filename); - for (String entry : blacklist) { - fos.write((entry + "\n").getBytes(StandardCharsets.UTF_8)); - } - fos.close(); - } catch (IOException e) { - Log.e(TAG, "Exception while trying to write blacklist" + filename, e); - } - }); - - } - - @Override - public boolean clearUserHistoryDictionary(final Context context) { - for (DictionaryGroup dictionaryGroup : mDictionaryGroups) { - final ExpandableBinaryDictionary dictionary = dictionaryGroup.getSubDict(Dictionary.TYPE_USER_HISTORY); - if (dictionary == null) { - return false; // should only ever happen for primary dictionary, so this is safe - } - dictionary.clear(); - } - return true; - } - - @Override - public String localesAndConfidences() { - if (mDictionaryGroups.size() < 2) return null; - final StringBuilder sb = new StringBuilder(); - for (final DictionaryGroup dictGroup : mDictionaryGroups) { - if (sb.length() > 0) - sb.append(", "); - sb.append(dictGroup.mLocale).append(" ").append(dictGroup.mConfidence); - } - return sb.toString(); - } - - @Override - public void dumpDictionaryForDebug(final String dictName) { - final ExpandableBinaryDictionary dictToDump = mDictionaryGroups.get(0).getSubDict(dictName); - if (dictToDump == null) { - Log.e(TAG, "Cannot dump " + dictName + ". " - + "The dictionary is not being used for suggestion or cannot be dumped."); - return; - } - dictToDump.dumpAllWordsForDebug(); - } - - @Override - // this is unused, so leave it for now - @NonNull public List getDictionaryStats(final Context context) { - final ArrayList statsOfEnabledSubDicts = new ArrayList<>(); - for (final String dictType : DYNAMIC_DICTIONARY_TYPES) { - final ExpandableBinaryDictionary dictionary = mDictionaryGroups.get(0).getSubDict(dictType); - if (dictionary == null) continue; - statsOfEnabledSubDicts.add(dictionary.getDictionaryStats()); - } - return statsOfEnabledSubDicts; - } - - @Override - public String dump(final Context context) { - return ""; - } -} diff --git a/app/src/main/java/helium314/keyboard/latin/DictionaryFacilitatorImpl.kt b/app/src/main/java/helium314/keyboard/latin/DictionaryFacilitatorImpl.kt new file mode 100644 index 000000000..3de4df001 --- /dev/null +++ b/app/src/main/java/helium314/keyboard/latin/DictionaryFacilitatorImpl.kt @@ -0,0 +1,820 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * modified + * SPDX-License-Identifier: Apache-2.0 AND GPL-3.0-only + */ +package helium314.keyboard.latin + +import android.Manifest +import android.content.Context +import android.provider.UserDictionary +import android.util.LruCache +import helium314.keyboard.keyboard.Keyboard +import helium314.keyboard.keyboard.emoji.SupportedEmojis +import helium314.keyboard.latin.DictionaryFacilitator.DictionaryInitializationListener +import helium314.keyboard.latin.NgramContext.WordInfo +import helium314.keyboard.latin.SuggestedWords.SuggestedWordInfo +import helium314.keyboard.latin.common.ComposedData +import helium314.keyboard.latin.common.Constants +import helium314.keyboard.latin.common.StringUtils +import helium314.keyboard.latin.common.decapitalize +import helium314.keyboard.latin.common.splitOnWhitespace +import helium314.keyboard.latin.permissions.PermissionsUtil +import helium314.keyboard.latin.personalization.UserHistoryDictionary +import helium314.keyboard.latin.settings.Settings +import helium314.keyboard.latin.settings.SettingsValuesForSuggestion +import helium314.keyboard.latin.utils.Log +import helium314.keyboard.latin.utils.SubtypeSettings +import helium314.keyboard.latin.utils.SuggestionResults +import helium314.keyboard.latin.utils.getSecondaryLocales +import helium314.keyboard.latin.utils.locale +import helium314.keyboard.latin.utils.prefs +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.async +import kotlinx.coroutines.awaitAll +import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking +import java.io.File +import java.io.IOException +import java.util.Locale +import java.util.concurrent.ConcurrentHashMap +import java.util.concurrent.CountDownLatch +import java.util.concurrent.TimeUnit + +/** + * Facilitates interaction with different kinds of dictionaries. Provides APIs + * to instantiate and select the correct dictionaries (based on language and settings), + * update entries and fetch suggestions. + * + * + * Currently AndroidSpellCheckerService and LatinIME both use DictionaryFacilitator as + * a client for interacting with dictionaries. + */ +class DictionaryFacilitatorImpl : DictionaryFacilitator { + private var dictionaryGroups = listOf(DictionaryGroup()) + + @Volatile + private var mLatchForWaitingLoadingMainDictionaries = CountDownLatch(0) + + // The library does not deal well with ngram history for auto-capitalized words, so we adjust + // the ngram context to store next word suggestions for such cases. + // todo: this is awful, find a better solution / workaround + // or remove completely? not sure if it's actually an improvement + // should be fixed in the library, but that's not feasible with current user-provides-library approach + // added in 12cbd43bda7d0f0cd73925e9cf836de751c32ed0 / https://github.com/Helium314/HeliBoard/issues/135 + private var tryChangingWords = false + private var changeFrom = "" + private var changeTo = "" + + // todo: write cache never set, and never read (only written) + // tried to use read cache for a while, but small performance improvements are not worth the work, + // see https://github.com/Helium314/HeliBoard/issues/307 + private var mValidSpellingWordReadCache: LruCache? = null + private var mValidSpellingWordWriteCache: LruCache? = null + + private val scope = CoroutineScope(Dispatchers.Default) + + override fun setValidSpellingWordReadCache(cache: LruCache) { + mValidSpellingWordReadCache = cache + } + + override fun setValidSpellingWordWriteCache(cache: LruCache) { + mValidSpellingWordWriteCache = cache + } + + // judging by usage before adding multilingual typing, this should check primary group locale only + override fun isForLocale(locale: Locale?): Boolean { + return locale != null && locale == dictionaryGroups[0].locale + } + + override fun onStartInput() { + } + + override fun onFinishInput(context: Context) { + for (dictGroup in dictionaryGroups) { + DictionaryFacilitator.ALL_DICTIONARY_TYPES.forEach { dictGroup.getDict(it)?.onFinishInput() } + } + } + + override fun isActive(): Boolean { + return dictionaryGroups[0].locale.language.isNotEmpty() + } + + override fun getMainLocale(): Locale { + return dictionaryGroups[0].locale + } + + override fun getCurrentLocale(): Locale { + return currentlyPreferredDictionaryGroup.locale + } + + override fun usesSameSettings(locales: List, contacts: Boolean, apps: Boolean, personalization: Boolean): Boolean { + val dictGroup = dictionaryGroups[0] // settings are the same for all groups + return contacts == dictGroup.hasDict(Dictionary.TYPE_CONTACTS) + && apps == dictGroup.hasDict(Dictionary.TYPE_APPS) + && personalization == dictGroup.hasDict(Dictionary.TYPE_USER_HISTORY) + && locales.size == dictionaryGroups.size + && locales.none { findDictionaryGroupWithLocale(dictionaryGroups, it) == null } + } + + // -------------- managing (loading & closing) dictionaries ------------ + + override fun resetDictionaries( + context: Context, + newLocale: Locale, + useContactsDict: Boolean, + useAppsDict: Boolean, + usePersonalizedDicts: Boolean, + forceReloadMainDictionary: Boolean, + dictNamePrefix: String, + listener: DictionaryInitializationListener? + ) { + Log.i(TAG, "resetDictionaries, force reloading main dictionary: $forceReloadMainDictionary") + + val locales = getUsedLocales(newLocale, context) + + val subDictTypesToUse = listOfNotNull( + Dictionary.TYPE_USER, + if (useAppsDict) Dictionary.TYPE_APPS else null, + if (usePersonalizedDicts) Dictionary.TYPE_USER_HISTORY else null, + if (useContactsDict && PermissionsUtil.checkAllPermissionsGranted(context, Manifest.permission.READ_CONTACTS)) + Dictionary.TYPE_CONTACTS else null + ) + + val (newDictionaryGroups, existingDictsToCleanup) = + getNewDictGroupsAndDictsToCleanup(locales, subDictTypesToUse, forceReloadMainDictionary, dictNamePrefix, context) + + // Replace Dictionaries. + val oldDictionaryGroups: List + synchronized(this) { + oldDictionaryGroups = dictionaryGroups + dictionaryGroups = newDictionaryGroups + if (hasAtLeastOneUninitializedMainDictionary()) { + asyncReloadUninitializedMainDictionaries(context, locales, listener) + } + } + + listener?.onUpdateMainDictionaryAvailability(hasAtLeastOneInitializedMainDictionary()) + + // Clean up old dictionaries. + existingDictsToCleanup.forEach { (locale, dictTypes) -> + val dictGroupToCleanup = findDictionaryGroupWithLocale(oldDictionaryGroups, locale) ?: return@forEach + for (dictType in dictTypes) { + dictGroupToCleanup.closeDict(dictType) + } + } + + mValidSpellingWordWriteCache?.evictAll() + mValidSpellingWordReadCache?.evictAll() + } + + /** creates dictionaryGroups for [newLocales] with given [newSubDictTypes], trying to re-use existing dictionaries. + * returns the new dictionaryGroups and unused dictionary types by locale */ + private fun getNewDictGroupsAndDictsToCleanup( + newLocales: Collection, + newSubDictTypes: Collection, + forceReload: Boolean, + dictNamePrefix: String, + context: Context + ): Pair, Map>> { + // Gather all dictionaries by locale. We may remove some from the list later. + val existingDictsToCleanup = HashMap>() + for (dictGroup in dictionaryGroups) { + existingDictsToCleanup[dictGroup.locale] = DictionaryFacilitator.ALL_DICTIONARY_TYPES + .filterTo(mutableListOf()) { dictGroup.hasDict(it) } + } + + // create new dictionary groups and remove dictionaries to re-use from existingDictsToCleanup + val newDictionaryGroups = mutableListOf() + for (locale in newLocales) { + // get existing dictionary group for new locale + val oldDictGroupForLocale = findDictionaryGroupWithLocale(dictionaryGroups, locale) + val dictTypesToCleanupForLocale = existingDictsToCleanup[locale] + + // create new or re-use already loaded main dict + val mainDict: Dictionary? + if (forceReload || oldDictGroupForLocale == null + || !oldDictGroupForLocale.hasDict(Dictionary.TYPE_MAIN) + ) { + mainDict = null // null main dicts will be loaded later in asyncReloadUninitializedMainDictionaries + } else { + mainDict = oldDictGroupForLocale.getDict(Dictionary.TYPE_MAIN) + dictTypesToCleanupForLocale?.remove(Dictionary.TYPE_MAIN) + } + + // create new or re-use already loaded sub-dicts + val subDicts: MutableMap = HashMap() + for (subDictType in newSubDictTypes) { + val subDict: ExpandableBinaryDictionary + if (forceReload || oldDictGroupForLocale == null + || !oldDictGroupForLocale.hasDict(subDictType) + ) { + // Create a new dictionary. + subDict = createSubDict(subDictType, context, locale, null, dictNamePrefix) ?: continue + } else { + // Reuse the existing dictionary. + subDict = oldDictGroupForLocale.getSubDict(subDictType) ?: continue + dictTypesToCleanupForLocale?.remove(subDictType) + } + subDicts[subDictType] = subDict + } + val newDictGroup = DictionaryGroup(locale, mainDict, subDicts, context) + newDictionaryGroups.add(newDictGroup) + } + return newDictionaryGroups to existingDictsToCleanup + } + + private fun asyncReloadUninitializedMainDictionaries( + context: Context, locales: Collection, listener: DictionaryInitializationListener? + ) { + val latchForWaitingLoadingMainDictionary = CountDownLatch(1) + mLatchForWaitingLoadingMainDictionaries = latchForWaitingLoadingMainDictionary + scope.launch { + val dictGroupsWithNewMainDict = locales.mapNotNull { + val dictionaryGroup = findDictionaryGroupWithLocale(dictionaryGroups, it) + if (dictionaryGroup == null) { + Log.w(TAG, "Expected a dictionary group for $it but none found") + return@mapNotNull null // This should never happen + } + if (dictionaryGroup.getDict(Dictionary.TYPE_MAIN)?.isInitialized == true) null + else dictionaryGroup to DictionaryFactory.createMainDictionaryCollection(context, it) + } + synchronized(this) { + dictGroupsWithNewMainDict.forEach { (dictGroup, mainDict) -> + dictGroup.setMainDict(mainDict) + } + } + + listener?.onUpdateMainDictionaryAvailability(hasAtLeastOneInitializedMainDictionary()) + latchForWaitingLoadingMainDictionary.countDown() + } + } + + override fun closeDictionaries() { + val dictionaryGroupsToClose: List + synchronized(this) { + dictionaryGroupsToClose = dictionaryGroups + dictionaryGroups = listOf(DictionaryGroup()) + } + for (dictionaryGroup in dictionaryGroupsToClose) { + for (dictType in DictionaryFacilitator.ALL_DICTIONARY_TYPES) { + dictionaryGroup.closeDict(dictType) + } + } + } + + // The main dictionaries are loaded asynchronously. Don't cache the return value of these methods. + override fun hasAtLeastOneInitializedMainDictionary(): Boolean = + dictionaryGroups.any { it.getDict(Dictionary.TYPE_MAIN)?.isInitialized == true } + + override fun hasAtLeastOneUninitializedMainDictionary(): Boolean = + dictionaryGroups.any { it.getDict(Dictionary.TYPE_MAIN)?.isInitialized != true } + + @Throws(InterruptedException::class) + override fun waitForLoadingMainDictionaries(timeout: Long, unit: TimeUnit) { + mLatchForWaitingLoadingMainDictionaries.await(timeout, unit) + } + + // -------------- actual dictionary stuff like getting suggestions ------------ + + override fun addToUserHistory( + suggestion: String, wasAutoCapitalized: Boolean, ngramContext: NgramContext, + timeStampInSeconds: Long, blockPotentiallyOffensive: Boolean + ) { + // Update the spelling cache before learning. Words that are not yet added to user history + // and appear in no other language model are not considered valid. + putWordIntoValidSpellingWordCache("addToUserHistory", suggestion) + + val words = suggestion.splitOnWhitespace().dropLastWhile { it.isEmpty() } + + // increase / decrease confidence + if (words.size == 1) // ignore if more than a single word, which only happens with (badly working) spaceAwareGesture + adjustConfidences(suggestion, wasAutoCapitalized) + + // Add word to user dictionary if it is in no other dictionary except user history dictionary (i.e. typed again). + val sv = Settings.getValues() + if (sv.mAddToPersonalDictionary // require the opt-in + && sv.mAutoCorrectEnabled == sv.mAutoCorrectionEnabledPerUserSettings // don't add if user wants autocorrect but input field does not, see https://github.com/Helium314/HeliBoard/issues/427#issuecomment-1905438000 + && dictionaryGroups[0].hasDict(Dictionary.TYPE_USER_HISTORY) // require personalized suggestions + && !wasAutoCapitalized // we can't be 100% sure about what the user intended to type, so better don't add it + && words.size == 1 // only single words + ) { + addToPersonalDictionaryIfInvalidButInHistory(suggestion) + } + + var ngramContextForCurrentWord = ngramContext + val preferredGroup = currentlyPreferredDictionaryGroup + for (i in words.indices) { + val currentWord = words[i] + val wasCurrentWordAutoCapitalized = (i == 0) && wasAutoCapitalized + // add to history for preferred dictionary group, to avoid mixing languages in history + addWordToUserHistory( + preferredGroup, ngramContextForCurrentWord, currentWord, + wasCurrentWordAutoCapitalized, timeStampInSeconds.toInt(), blockPotentiallyOffensive + ) + ngramContextForCurrentWord = ngramContextForCurrentWord.getNextNgramContext(WordInfo(currentWord)) + + // remove manually entered blacklisted words from blacklist for likely matching languages + dictionaryGroups.filter { it.confidence == preferredGroup.confidence }.forEach { + it.removeFromBlacklist(currentWord) + } + } + } + + private fun addWordToUserHistory( + dictionaryGroup: DictionaryGroup, ngramContext: NgramContext, word: String, wasAutoCapitalized: Boolean, + timeStampInSeconds: Int, blockPotentiallyOffensive: Boolean + ) { + val userHistoryDictionary = dictionaryGroup.getSubDict(Dictionary.TYPE_USER_HISTORY) ?: return + + val mainFreq = dictionaryGroup.getDict(Dictionary.TYPE_MAIN)?.getFrequency(word) ?: Dictionary.NOT_A_PROBABILITY + if (mainFreq == 0 && blockPotentiallyOffensive) + return + if (tryChangingWords) + tryChangingWords = ngramContext.changeWordIfAfterBeginningOfSentence(changeFrom, changeTo) + + val wordToUse: String + // Check for isBeginningOfSentenceContext too, because not all text fields auto-capitalize in this case. + // Even if the user capitalizes manually, they most likely don't want the capitalized form suggested. + if (wasAutoCapitalized || ngramContext.isBeginningOfSentenceContext) { + val decapitalizedWord = word.decapitalize(dictionaryGroup.locale) // try undoing auto-capitalization + if (isValidWord(word, DictionaryFacilitator.ALL_DICTIONARY_TYPES, dictionaryGroup) + && !isValidWord(decapitalizedWord, DictionaryFacilitator.ALL_DICTIONARY_TYPES, dictionaryGroup) + ) { + // If the word was auto-capitalized and exists only as a capitalized word in the + // dictionary, then we must not downcase it before registering it. For example, + // the name of the contacts in start-of-sentence position would come here with the + // wasAutoCapitalized flag: if we downcase it, we'd register a lower-case version + // of that contact's name which would end up popping in suggestions. + wordToUse = word + } else { + // If however the word is not in the dictionary, or exists as a de-capitalized word + // only, then we consider that was a lower-case word that had been auto-capitalized. + wordToUse = decapitalizedWord + tryChangingWords = true + changeFrom = word + changeTo = wordToUse + } + } else { + // HACK: We'd like to avoid adding the capitalized form of common words to the User + // History dictionary in order to avoid suggesting them until the dictionary + // consolidation is done. + // TODO: Remove this hack when ready. + val lowerCasedWord = word.lowercase(dictionaryGroup.locale) + val lowerCaseFreqInMainDict = dictionaryGroup.getDict(Dictionary.TYPE_MAIN)?.getFrequency(lowerCasedWord) + ?: Dictionary.NOT_A_PROBABILITY + wordToUse = if (mainFreq < lowerCaseFreqInMainDict + && lowerCaseFreqInMainDict >= CAPITALIZED_FORM_MAX_PROBABILITY_FOR_INSERT + ) { + // Use lower cased word as the word can be a distracter of the popular word. + lowerCasedWord + } else { + word + } + } + // We demote unrecognized words (frequency <= 0) by specifying them as "invalid". + // We don't add words with 0-frequency (assuming they would be profanity etc.). + val isValid = mainFreq > 0 + UserHistoryDictionary.addToDictionary(userHistoryDictionary, ngramContext, wordToUse, isValid, timeStampInSeconds) + } + + private fun addToPersonalDictionaryIfInvalidButInHistory(word: String) { + val dictionaryGroup = clearlyPreferredDictionaryGroup ?: return + val userDict = dictionaryGroup.getSubDict(Dictionary.TYPE_USER) ?: return + val userHistoryDict = dictionaryGroup.getSubDict(Dictionary.TYPE_USER_HISTORY) ?: return + if (isValidWord(word, DictionaryFacilitator.ALL_DICTIONARY_TYPES, dictionaryGroup)) + return // valid word, no reason to auto-add it to personal dict + if (userDict.isInDictionary(word)) + return // should never happen, but better be safe + + // User history always reports words as invalid, so we check the frequency instead. + // Testing shows that after 2 times adding, the frequency is 111, and then rises slowly with usage (values vary slightly). + // 120 is after 3 uses of the word, so we simply require more than that. todo: Could be made configurable. + // Words added to dictionaries (user and history) seem to be found only after some delay. + // This is not too bad, but it delays adding in case a user wants to fill a dictionary using this functionality + if (userHistoryDict.getFrequency(word) > 120) { + scope.launch { + UserDictionary.Words.addWord(userDict.mContext, word, 250, null, dictionaryGroup.locale) + } + } + } + + private fun putWordIntoValidSpellingWordCache(caller: String, originalWord: String) { + if (mValidSpellingWordWriteCache == null) + return + + val lowerCaseWord = originalWord.lowercase(currentLocale) + val lowerCaseValid = isValidSpellingWord(lowerCaseWord) + mValidSpellingWordWriteCache?.put(lowerCaseWord, lowerCaseValid) + + val capitalWord = StringUtils.capitalizeFirstAndDowncaseRest(originalWord, currentLocale) + val capitalValid = if (lowerCaseValid) { + true // The lower case form of the word is valid, so the upper case must be valid. + } else { + isValidSpellingWord(capitalWord) + } + mValidSpellingWordWriteCache?.put(capitalWord, capitalValid) + } + + override fun adjustConfidences(word: String, wasAutoCapitalized: Boolean) { + if (dictionaryGroups.size == 1 || word.contains(Constants.WORD_SEPARATOR)) + return + + // if suggestion was auto-capitalized, check against both the suggestion and the de-capitalized suggestion + val decapitalizedSuggestion = if (wasAutoCapitalized) word.decapitalize(currentLocale) else word + dictionaryGroups.forEach { + if (isValidWord(word, DictionaryFacilitator.ALL_DICTIONARY_TYPES, it)) { + it.increaseConfidence() + return@forEach + } + // also increase confidence if suggestion was auto-capitalized and the lowercase variant it valid + if (wasAutoCapitalized && isValidWord(decapitalizedSuggestion, DictionaryFacilitator.ALL_DICTIONARY_TYPES, it)) + it.increaseConfidence() + else it.decreaseConfidence() + } + } + + /** the dictionaryGroup with most confidence, first group when tied */ + private val currentlyPreferredDictionaryGroup: DictionaryGroup get() = dictionaryGroups.maxBy { it.confidence } + + /** the only dictionary group, or the dictionaryGroup confidence >= DictionaryGroup.MAX_CONFIDENCE if all others have 0 */ + private val clearlyPreferredDictionaryGroup: DictionaryGroup? get() { + if (dictionaryGroups.size == 1) return dictionaryGroups.first() // confidence not used if we only have a single group + + val preferred = currentlyPreferredDictionaryGroup + if (preferred.confidence < DictionaryGroup.MAX_CONFIDENCE) return null + if (dictionaryGroups.any { it.confidence > 0 && it !== preferred }) + return null + return preferred + } + + override fun unlearnFromUserHistory(word: String, ngramContext: NgramContext, timeStampInSeconds: Long, eventType: Int) { + // TODO: Decide whether or not to remove the word on EVENT_BACKSPACE. + if (eventType != Constants.EVENT_BACKSPACE) { + currentlyPreferredDictionaryGroup.getSubDict(Dictionary.TYPE_USER_HISTORY)?.removeUnigramEntryDynamically(word) + } + + // Update the spelling cache after unlearning. Words that are removed from user history + // and appear in no other language model are not considered valid. + putWordIntoValidSpellingWordCache("unlearnFromUserHistory", word.lowercase(Locale.getDefault())) + } + + // TODO: Revise the way to fusion suggestion results. + override fun getSuggestionResults( + composedData: ComposedData, ngramContext: NgramContext, keyboard: Keyboard, + settingsValuesForSuggestion: SettingsValuesForSuggestion, sessionId: Int, inputStyle: Int + ): SuggestionResults { + val proximityInfoHandle = keyboard.proximityInfo.nativeProximityInfo + val weightOfLangModelVsSpatialModel = floatArrayOf(Dictionary.NOT_A_WEIGHT_OF_LANG_MODEL_VS_SPATIAL_MODEL) + + val waitForOtherDicts = if (dictionaryGroups.size == 1) null else CountDownLatch(dictionaryGroups.size - 1) + val suggestionsArray = Array?>(dictionaryGroups.size) { null } + for (i in 1..dictionaryGroups.lastIndex) { + scope.launch { + suggestionsArray[i] = getSuggestions(composedData, ngramContext, settingsValuesForSuggestion, sessionId, + proximityInfoHandle, weightOfLangModelVsSpatialModel, dictionaryGroups[i]) + waitForOtherDicts?.countDown() + } + } + suggestionsArray[0] = getSuggestions(composedData, ngramContext, settingsValuesForSuggestion, sessionId, + proximityInfoHandle, weightOfLangModelVsSpatialModel, dictionaryGroups[0]) + val suggestionResults = SuggestionResults( + SuggestedWords.MAX_SUGGESTIONS, ngramContext.isBeginningOfSentenceContext, false + ) + waitForOtherDicts?.await() + + suggestionsArray.forEach { + if (it == null) return@forEach + suggestionResults.addAll(it) + suggestionResults.mRawSuggestions?.addAll(it) + } + + return suggestionResults + } + + private fun getSuggestions( + composedData: ComposedData, ngramContext: NgramContext, + settingsValuesForSuggestion: SettingsValuesForSuggestion, sessionId: Int, + proximityInfoHandle: Long, weightOfLangModelVsSpatialModel: FloatArray, dictGroup: DictionaryGroup + ): List { + val suggestions = ArrayList() + val weightForLocale = dictGroup.getWeightForLocale(dictionaryGroups, composedData.mIsBatchMode) + for (dictType in DictionaryFacilitator.ALL_DICTIONARY_TYPES) { + val dictionary = dictGroup.getDict(dictType) ?: continue + val dictionarySuggestions = dictionary.getSuggestions(composedData, ngramContext, proximityInfoHandle, + settingsValuesForSuggestion, sessionId, weightForLocale, weightOfLangModelVsSpatialModel + ) ?: continue + + // For some reason "garbage" words are produced when glide typing. For user history + // and main dictionaries we can filter them out by checking whether the dictionary + // actually contains the word. But personal and addon dictionaries may contain shortcuts, + // which do not pass an isInDictionary check (e.g. emojis). + // (if the main dict contains shortcuts to non-words, this will break!) + val checkForGarbage = composedData.mIsBatchMode && (dictType == Dictionary.TYPE_USER_HISTORY || dictType == Dictionary.TYPE_MAIN) + + for (info in dictionarySuggestions) { + val word = info.word + if (isBlacklisted(word) || SupportedEmojis.isUnsupported(word)) // don't add blacklisted words and unsupported emojis + continue + if (checkForGarbage + // consider the user might use custom main dictionary containing shortcuts + // assume this is unlikely to happen, and take care about common shortcuts that are not actual words (emoji, symbols) + && word.length > 2 // should exclude most symbol shortcuts + && info.mSourceDict.mDictType == dictType // dictType is always main, but info.mSourceDict.mDictType contains the actual dict (main dict is a dictionary group) + && !StringUtils.mightBeEmoji(word) // simplified check for performance reasons + && !dictionary.isInDictionary(word) + ) + continue + + if (word.length == 1 && info.mSourceDict.mDictType == "emoji" && !StringUtils.mightBeEmoji(word[0].code)) + continue + + suggestions.add(info) + } + } + return suggestions + } + + // Spell checker is using this, and has its own instance of DictionaryFacilitatorImpl, + // meaning that it always has default mConfidence. So we cannot choose to only check preferred + // locale, and instead simply return true if word is in any of the available dictionaries + override fun isValidSpellingWord(word: String): Boolean { + mValidSpellingWordReadCache?.get(word)?.let { return it } + val result = dictionaryGroups.any { isValidWord(word, DictionaryFacilitator.ALL_DICTIONARY_TYPES, it) } + mValidSpellingWordReadCache?.put(word, result) + return result + } + + // this is unused, so leave it for now (redirecting to isValidWord seems to defeat the purpose...) + override fun isValidSuggestionWord(word: String): Boolean { + return isValidWord(word, DictionaryFacilitator.ALL_DICTIONARY_TYPES, dictionaryGroups[0]) + } + + // todo: move into dictionaryGroup? + private fun isValidWord(word: String, dictionariesToCheck: Array, dictionaryGroup: DictionaryGroup): Boolean { + if (word.isEmpty() || dictionaryGroup.isBlacklisted(word)) return false + return dictionariesToCheck.any { dictionaryGroup.getDict(it)?.isValidWord(word) == true } + } + + private fun isBlacklisted(word: String): Boolean = dictionaryGroups.any { it.isBlacklisted(word) } + + override fun removeWord(word: String) { + for (dictionaryGroup in dictionaryGroups) { + dictionaryGroup.removeWord(word) + } + } + + override fun clearUserHistoryDictionary(context: Context) { + for (dictionaryGroup in dictionaryGroups) { + dictionaryGroup.getSubDict(Dictionary.TYPE_USER_HISTORY)?.clear() + } + } + + override fun localesAndConfidences(): String? { + if (dictionaryGroups.size < 2) return null + return dictionaryGroups.joinToString(", ") { "${it.locale} ${it.confidence}" } + } + + override fun dumpDictionaryForDebug(dictName: String) { + val dictToDump = dictionaryGroups[0].getSubDict(dictName) + if (dictToDump == null) { + Log.e(TAG, ("Cannot dump $dictName. The dictionary is not being used for suggestion or cannot be dumped.")) + return + } + dictToDump.dumpAllWordsForDebug() + } + + override fun getDictionaryStats(context: Context): List = + DictionaryFacilitator.DYNAMIC_DICTIONARY_TYPES.flatMap { dictType -> + dictionaryGroups.mapNotNull { it.getSubDict(dictType)?.dictionaryStats } + } + + override fun dump(context: Context) = getDictionaryStats(context).joinToString("\n") + + companion object { + private val TAG = DictionaryFacilitatorImpl::class.java.simpleName + + // HACK: This threshold is being used when adding a capitalized entry in the User History dictionary. + private const val CAPITALIZED_FORM_MAX_PROBABILITY_FOR_INSERT = 140 + + private fun createSubDict( + dictType: String, context: Context, locale: Locale, dictFile: File?, dictNamePrefix: String + ): ExpandableBinaryDictionary? { + try { + return when (dictType) { + Dictionary.TYPE_USER_HISTORY -> UserHistoryDictionary.getDictionary(context, locale, dictFile, dictNamePrefix) + Dictionary.TYPE_USER -> UserBinaryDictionary.getDictionary(context, locale, dictFile, dictNamePrefix) + Dictionary.TYPE_CONTACTS -> ContactsBinaryDictionary.getDictionary(context, locale, dictFile, dictNamePrefix) + Dictionary.TYPE_APPS -> AppsBinaryDictionary.getDictionary(context, locale, dictFile, dictNamePrefix) + else -> throw IllegalArgumentException("unknown dictionary type $dictType") + } + } catch (e: SecurityException) { + Log.e(TAG, "Cannot create dictionary: $dictType", e) + } catch (e: IllegalArgumentException) { + Log.e(TAG, "Cannot create dictionary: $dictType", e) + } + return null + } + + private fun findDictionaryGroupWithLocale(dictGroups: List?, locale: Locale): DictionaryGroup? { + return dictGroups?.firstOrNull { it.locale == locale } + } + + private fun getUsedLocales(mainLocale: Locale, context: Context): Collection { + val locales = hashSetOf(mainLocale) + // adding secondary locales is a bit tricky since they depend on the subtype + // but usually this is called with the selected subtype locale + val selectedSubtype = SubtypeSettings.getSelectedSubtype(context.prefs()) + if (selectedSubtype.locale() == mainLocale) { + locales.addAll(getSecondaryLocales(selectedSubtype.extraValue)) + } else { + // probably we're called from the spell checker when using a different app as keyboard + // so best bet is adding all secondary locales for matching main locale + SubtypeSettings.getEnabledSubtypes(false).forEach { + if (it.locale() == mainLocale) + locales.addAll(getSecondaryLocales(it.extraValue)) + } + } + return locales + } + } +} + +/** A group of dictionaries that work together for a single language. */ +private class DictionaryGroup( + val locale: Locale = Locale(""), + private var mainDict: Dictionary? = null, + subDicts: Map = emptyMap(), + context: Context? = null +) { + private val subDicts: ConcurrentHashMap = ConcurrentHashMap(subDicts) + + /** Removes a word from all dictionaries in this group. If the word is in a read-only dictionary, it is blacklisted. */ + fun removeWord(word: String) { + // remove from user history + getSubDict(Dictionary.TYPE_USER_HISTORY)?.removeUnigramEntryDynamically(word) + + // and from personal dictionary + getSubDict(Dictionary.TYPE_USER)?.removeUnigramEntryDynamically(word) + + val contactsDict = getSubDict(Dictionary.TYPE_CONTACTS) + if (contactsDict != null && contactsDict.isInDictionary(word)) { + contactsDict.removeUnigramEntryDynamically(word) // will be gone until next reload of dict + addToBlacklist(word) + return + } + + val appsDict = getSubDict(Dictionary.TYPE_APPS) + if (appsDict != null && appsDict.isInDictionary(word)) { + appsDict.removeUnigramEntryDynamically(word) // will be gone until next reload of dict + addToBlacklist(word) + return + } + + val mainDict = mainDict ?: return + if (mainDict.isValidWord(word)) { + addToBlacklist(word) + return + } + + val lowercase = word.lowercase(locale) + if (getDict(Dictionary.TYPE_MAIN)!!.isValidWord(lowercase)) { + addToBlacklist(lowercase) + } + } + + // --------------- Confidence for multilingual typing ------------------- + + // Confidence that the most probable language is actually the language the user is + // typing in. For now, this is simply the number of times a word from this language + // has been committed in a row, with an exception when typing a single word not contained + // in this language. + var confidence = 1 + + // allow to go above max confidence, for better determination of currently preferred language + // when decreasing confidence or getting weight factor, limit to maximum + fun increaseConfidence() { + confidence += 1 + } + + // If confidence is above max, drop to max confidence. This does not change weights and + // allows conveniently typing single words from the other language without affecting suggestions + fun decreaseConfidence() { + if (confidence > MAX_CONFIDENCE) confidence = MAX_CONFIDENCE + else if (confidence > 0) { + confidence -= 1 + } + } + + fun getWeightForLocale(groups: List, isGesturing: Boolean) = + getWeightForLocale(groups, if (isGesturing) 0.05f else 0.15f) + + // might need some more tuning + fun getWeightForLocale(groups: List, step: Float): Float { + if (groups.size == 1) return 1f + if (confidence < 2) return 1f - step * (MAX_CONFIDENCE - confidence) + for (group in groups) { + if (group !== this && group.confidence >= confidence) return 1f - step / 2f + } + return 1f + } + + // --------------- Blacklist ------------------- + + private val scope = CoroutineScope(Dispatchers.IO) + + // words cannot be (permanently) removed from some dictionaries, so we use a blacklist for "removing" words + private val blacklistFile = if (context?.filesDir == null) null + else { + val file = File(context.filesDir.absolutePath + File.separator + "blacklists" + File.separator + locale.toLanguageTag() + ".txt") + if (file.isDirectory) file.delete() // this apparently was an issue in some versions + if (file.mkdirs()) file + else null + } + + private val blacklist = hashSetOf().apply { + if (blacklistFile?.exists() != true) return@apply + scope.launch { + synchronized(this) { + try { + addAll(blacklistFile.readLines()) + } catch (e: IOException) { + Log.e(TAG, "Exception while trying to read blacklist from ${blacklistFile.name}", e) + } + } + } + } + + fun isBlacklisted(word: String) = blacklist.contains(word) + + fun addToBlacklist(word: String) { + if (!blacklist.add(word) || blacklistFile == null) return + scope.launch { + synchronized(this) { + try { + if (blacklistFile.isDirectory) blacklistFile.delete() + blacklistFile.appendText("$word\n") + } catch (e: IOException) { + Log.e(TAG, "Exception while trying to add word \"$word\" to blacklist ${blacklistFile.name}", e) + } + } + } + } + + fun removeFromBlacklist(word: String) { + if (!blacklist.remove(word) || blacklistFile == null) return + scope.launch { + synchronized(this) { + try { + val newLines = blacklistFile.readLines().filterNot { it == word } + blacklistFile.writeText(newLines.joinToString("\n")) + } catch (e: IOException) { + Log.e(TAG, "Exception while trying to remove word \"$word\" to blacklist ${blacklistFile.name}", e) + } + } + } + } + + // --------------- Dictionary handling ------------------- + + fun setMainDict(newMainDict: Dictionary?) { + // Close old dictionary if exists. Main dictionary can be assigned multiple times. + val oldDict = mainDict + mainDict = newMainDict + if (oldDict != null && newMainDict !== oldDict) + oldDict.close() + } + + fun getDict(dictType: String): Dictionary? { + if (dictType == Dictionary.TYPE_MAIN) { + return mainDict + } + return getSubDict(dictType) + } + + fun getSubDict(dictType: String): ExpandableBinaryDictionary? { + return subDicts[dictType] + } + + fun hasDict(dictType: String): Boolean { + if (dictType == Dictionary.TYPE_MAIN) { + return mainDict != null + } + return subDicts.containsKey(dictType) + } + + fun closeDict(dictType: String) { + val dict = if (Dictionary.TYPE_MAIN == dictType) { + mainDict + } else { + subDicts.remove(dictType) + } + dict?.close() + } + + companion object { + private val TAG = DictionaryGroup::class.java.simpleName + const val MAX_CONFIDENCE = 2 + } +} diff --git a/app/src/main/java/helium314/keyboard/latin/DictionaryFacilitatorLruCache.java b/app/src/main/java/helium314/keyboard/latin/DictionaryFacilitatorLruCache.java index 08096413c..2e98d0064 100644 --- a/app/src/main/java/helium314/keyboard/latin/DictionaryFacilitatorLruCache.java +++ b/app/src/main/java/helium314/keyboard/latin/DictionaryFacilitatorLruCache.java @@ -26,6 +26,7 @@ public class DictionaryFacilitatorLruCache { private final Object mLock = new Object(); private final DictionaryFacilitator mDictionaryFacilitator; private boolean mUseContactsDictionary; + private boolean mUseAppsDictionary; private Locale mLocale; public DictionaryFacilitatorLruCache(final Context context, final String dictionaryNamePrefix) { @@ -58,10 +59,8 @@ public class DictionaryFacilitatorLruCache { // Nothing to do if the locale is null. This would be the case before any get() calls. if (mLocale != null) { // Note: Given that personalized dictionaries are not used here; we can pass null account. - mDictionaryFacilitator.resetDictionaries(mContext, mLocale, - mUseContactsDictionary, false /* usePersonalizedDicts */, - false /* forceReloadMainDictionary */, null /* account */, - mDictionaryNamePrefix, null /* listener */); + mDictionaryFacilitator.resetDictionaries(mContext, mLocale, mUseContactsDictionary, + mUseAppsDictionary, false, false, mDictionaryNamePrefix, null); } } @@ -77,6 +76,18 @@ public class DictionaryFacilitatorLruCache { } } + public void setUseAppsDictionary(final boolean useAppsDictionary) { + synchronized (mLock) { + if (mUseAppsDictionary == useAppsDictionary) { + // The value has not been changed. + return; + } + mUseAppsDictionary = useAppsDictionary; + resetDictionariesForLocaleLocked(); + waitForLoadingMainDictionary(mDictionaryFacilitator); + } + } + public DictionaryFacilitator get(final Locale locale) { synchronized (mLock) { if (!mDictionaryFacilitator.isForLocale(locale)) { diff --git a/app/src/main/java/helium314/keyboard/latin/DictionaryFactory.kt b/app/src/main/java/helium314/keyboard/latin/DictionaryFactory.kt index 29b416a5d..bd86960b3 100644 --- a/app/src/main/java/helium314/keyboard/latin/DictionaryFactory.kt +++ b/app/src/main/java/helium314/keyboard/latin/DictionaryFactory.kt @@ -6,88 +6,87 @@ package helium314.keyboard.latin import android.content.Context -import helium314.keyboard.latin.common.FileUtils import helium314.keyboard.latin.common.LocaleUtils -import helium314.keyboard.latin.common.LocaleUtils.constructLocale import helium314.keyboard.latin.utils.DictionaryInfoUtils import helium314.keyboard.latin.utils.Log import java.io.File import java.util.LinkedList import java.util.Locale -/** - * Initializes a main dictionary collection from a dictionary pack, with explicit flags. - * - * - * This searches for a content provider providing a dictionary pack for the specified - * locale. If none is found, it falls back to the built-in dictionary - if any. - * @param context application context for reading resources - * @param locale the locale for which to create the dictionary - * @return an initialized instance of DictionaryCollection - */ -fun createMainDictionary(context: Context, locale: Locale): DictionaryCollection { - val cacheDir = DictionaryInfoUtils.getAndCreateCacheDirectoryForLocale(locale, context) - val dictList = LinkedList() - // get cached dict files - val (userDicts, extractedDicts) = DictionaryInfoUtils.getCachedDictsForLocale(locale, context) - .partition { it.name.endsWith(DictionaryInfoUtils.USER_DICTIONARY_SUFFIX) } - // add user dicts to list - userDicts.forEach { checkAndAddDictionaryToListIfNotExisting(it, dictList, locale) } - // add extracted dicts to list (after userDicts, to skip extracted dicts of same type) - extractedDicts.forEach { checkAndAddDictionaryToListIfNotExisting(it, dictList, locale) } - if (dictList.any { it.mDictType == Dictionary.TYPE_MAIN }) - return DictionaryCollection(Dictionary.TYPE_MAIN, locale, dictList) - - // no main dict found -> check assets - val assetsDicts = DictionaryInfoUtils.getAssetsDictionaryList(context) - // file name is _.dict - val dictsByType = assetsDicts?.groupBy { it.substringBefore("_") } - // for each type find the best match - dictsByType?.forEach { (dictType, dicts) -> - val bestMatch = LocaleUtils.getBestMatch(locale, dicts) { it.substringAfter("_") - .substringBefore(".").constructLocale() } ?: return@forEach - // extract dict and add extracted file - val targetFile = File(cacheDir, "$dictType.dict") - FileUtils.copyStreamToNewFile( - context.assets.open(DictionaryInfoUtils.ASSETS_DICTIONARY_FOLDER + File.separator + bestMatch), - targetFile - ) - checkAndAddDictionaryToListIfNotExisting(targetFile, dictList, locale) - } - // If the list is empty, that means we should not use any dictionary (for example, the user - // explicitly disabled the main dictionary), so the following is okay. dictList is never - // null, but if for some reason it is, DictionaryCollection handles it gracefully. - return DictionaryCollection(Dictionary.TYPE_MAIN, locale, dictList) -} - -/** - * add dictionary created from [file] to [dicts] - * if [file] cannot be loaded it is deleted - * if the dictionary type already exists in [dicts], the [file] is skipped - */ -private fun checkAndAddDictionaryToListIfNotExisting(file: File, dicts: MutableList, locale: Locale) { - if (!file.isFile) return - val header = DictionaryInfoUtils.getDictionaryFileHeaderOrNull(file) ?: return killDictionary(file) - val dictType = header.mIdString.split(":").first() - if (dicts.any { it.mDictType == dictType }) return - val readOnlyBinaryDictionary = ReadOnlyBinaryDictionary( - file.absolutePath, 0, file.length(), false, locale, dictType - ) - - if (readOnlyBinaryDictionary.isValidDictionary) { - if (locale.language == "ko") { - // Use KoreanDictionary for Korean locale - dicts.add(KoreanDictionary(readOnlyBinaryDictionary)) - } else { - dicts.add(readOnlyBinaryDictionary) +object DictionaryFactory { + /** + * Initializes a main dictionary collection for a locale. + * Uses all dictionaries in cache folder for locale, and adds built-in + * dictionaries of matching locales if type is not already in cache folder. + * + * @return an initialized instance of DictionaryCollection + */ + // todo: + // expose the weight so users can adjust dictionary "importance" (useful for addons like emoji dict) + // allow users to block certain dictionaries (not sure how this should work exactly) + fun createMainDictionaryCollection(context: Context, locale: Locale): DictionaryCollection { + val dictList = LinkedList() + val (extracted, nonExtracted) = getAvailableDictsForLocale(locale, context) + extracted.sortedBy { !it.name.endsWith(DictionaryInfoUtils.USER_DICTIONARY_SUFFIX) }.forEach { + // we sort to have user dicts first, so they have priority over internal dicts of the same type + checkAndAddDictionaryToListNewType(it, dictList, locale) } - } else { - readOnlyBinaryDictionary.close() - killDictionary(file) + nonExtracted.forEach { filename -> + val type = filename.substringBefore("_") + if (dictList.any { it.mDictType == type }) return@forEach + val extractedFile = DictionaryInfoUtils.extractAssetsDictionary(filename, locale, context) ?: return@forEach + checkAndAddDictionaryToListNewType(extractedFile, dictList, locale) + } + return DictionaryCollection(Dictionary.TYPE_MAIN, locale, dictList, FloatArray(dictList.size) { 1f }) + } + + fun getAvailableDictsForLocale(locale: Locale, context: Context): Pair, List> { + val cachedDicts = DictionaryInfoUtils.getCachedDictsForLocale(locale, context) + + val nonExtractedDicts = mutableListOf() + DictionaryInfoUtils.getAssetsDictionaryList(context) + // file name is _.dict + ?.groupBy { it.substringBefore("_") } + ?.forEach { (dictType, dicts) -> + if (cachedDicts.any { it.name == "$dictType.dict" }) + return@forEach // dictionary is already extracted (can't be old because of cleanup on upgrade) + val bestMatch = LocaleUtils.getBestMatch(locale, dicts) { + DictionaryInfoUtils.extractLocaleFromAssetsDictionaryFile(it) + } ?: return@forEach + nonExtractedDicts.add(bestMatch) + } + return cachedDicts to nonExtractedDicts + } + + /** + * add dictionary created from [file] to [dicts] + * if [file] cannot be loaded it is deleted + * if the dictionary type already exists in [dicts], the [file] is skipped + */ + private fun checkAndAddDictionaryToListNewType(file: File, dicts: MutableList, locale: Locale) { + if (!file.isFile) return + val header = DictionaryInfoUtils.getDictionaryFileHeaderOrNull(file) ?: return killDictionary(file) + val dictType = header.mIdString.split(":").first() + if (dicts.any { it.mDictType == dictType }) return + val readOnlyBinaryDictionary = ReadOnlyBinaryDictionary( + file.absolutePath, 0, file.length(), false, locale, dictType + ) + + if (readOnlyBinaryDictionary.isValidDictionary) { + if (locale.language == "ko") { + // Use KoreanDictionary for Korean locale + dicts.add(KoreanDictionary(readOnlyBinaryDictionary)) + } else { + dicts.add(readOnlyBinaryDictionary) + } + } else { + readOnlyBinaryDictionary.close() + killDictionary(file) + } + } + + private fun killDictionary(file: File) { + Log.e("DictionaryFactory", "could not load dictionary ${file.parentFile?.name}/${file.name}, deleting") + file.delete() } } - -private fun killDictionary(file: File) { - Log.e("DictionaryFactory", "could not load dictionary ${file.parentFile?.name}/${file.name}, deleting") - file.delete() -} diff --git a/app/src/main/java/helium314/keyboard/latin/InputView.java b/app/src/main/java/helium314/keyboard/latin/InputView.java index 8125edc09..fe2645766 100644 --- a/app/src/main/java/helium314/keyboard/latin/InputView.java +++ b/app/src/main/java/helium314/keyboard/latin/InputView.java @@ -21,6 +21,8 @@ import helium314.keyboard.latin.common.ColorType; import helium314.keyboard.latin.settings.Settings; import helium314.keyboard.latin.suggestions.PopupSuggestionsView; import helium314.keyboard.latin.suggestions.SuggestionStripView; +import kotlin.Unit; + public final class InputView extends FrameLayout { private final Rect mInputViewRect = new Rect(); @@ -43,10 +45,7 @@ public final class InputView extends FrameLayout { mMainKeyboardView, suggestionStripView); mMoreSuggestionsViewCanceler = new MoreSuggestionsViewCanceler( mMainKeyboardView, suggestionStripView); - ViewKt.doOnNextLayout(this, v -> { - Settings.getValues().mColors.setBackground(findViewById(R.id.main_keyboard_frame), ColorType.MAIN_BACKGROUND); - return null; - }); + ViewKt.doOnNextLayout(this, this::onNextLayout); } public void setKeyboardTopPadding(final int keyboardTopPadding) { @@ -104,6 +103,14 @@ public final class InputView extends FrameLayout { return mActiveForwarder.onTouchEvent(x, y, me); } + private Unit onNextLayout(View v) { + Settings.getValues().mColors.setBackground(findViewById(R.id.main_keyboard_frame), ColorType.MAIN_BACKGROUND); + + // Work around inset application being unreliable + requestApplyInsets(); + return null; + } + /** * This class forwards series of {@link MotionEvent}s from SenderView to * ReceiverView. diff --git a/app/src/main/java/helium314/keyboard/latin/KeyboardWrapperView.kt b/app/src/main/java/helium314/keyboard/latin/KeyboardWrapperView.kt index 5fb5a122d..35a689740 100644 --- a/app/src/main/java/helium314/keyboard/latin/KeyboardWrapperView.kt +++ b/app/src/main/java/helium314/keyboard/latin/KeyboardWrapperView.kt @@ -78,7 +78,7 @@ class KeyboardWrapperView @JvmOverloads constructor( val changePercent = 2 * sign * (x - motionEvent.rawX) / context.resources.displayMetrics.density if (abs(changePercent) < 1) return@setOnTouchListener true x = motionEvent.rawX - val oldScale = Settings.readOneHandedModeScale(context.prefs(), Settings.getValues().mDisplayOrientation == Configuration.ORIENTATION_PORTRAIT) + val oldScale = Settings.readOneHandedModeScale(context.prefs(), Settings.getValues().mDisplayOrientation == Configuration.ORIENTATION_LANDSCAPE) val newScale = (oldScale + changePercent / 100f).coerceAtMost(2.5f).coerceAtLeast(0.5f) if (newScale == oldScale) return@setOnTouchListener true Settings.getInstance().writeOneHandedModeScale(newScale) diff --git a/app/src/main/java/helium314/keyboard/latin/LatinIME.java b/app/src/main/java/helium314/keyboard/latin/LatinIME.java index d2e75a457..d58c7609d 100644 --- a/app/src/main/java/helium314/keyboard/latin/LatinIME.java +++ b/app/src/main/java/helium314/keyboard/latin/LatinIME.java @@ -7,6 +7,7 @@ package helium314.keyboard.latin; import android.annotation.SuppressLint; +import android.app.AlertDialog; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -100,7 +101,6 @@ import java.util.concurrent.TimeUnit; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; -import androidx.appcompat.app.AlertDialog; import androidx.core.content.ContextCompat; /** @@ -523,6 +523,11 @@ public class LatinIME extends InputMethodService implements } final class SubtypeState { + // When HintLocales causes a subtype override, we store + // the overridden subtype here in order to restore it when + // we switch to another input context that has no HintLocales. + private InputMethodSubtype mOverriddenByLocale; + private InputMethodSubtype mLastActiveSubtype; private boolean mCurrentSubtypeHasBeenUsed = true; // starting with true avoids immediate switch @@ -530,6 +535,70 @@ public class LatinIME extends InputMethodService implements mCurrentSubtypeHasBeenUsed = true; } + // TextFields can provide locale/language hints that the IME should use via 'hintLocales'. + // If a matching subtype is found, we temporarily switch to that subtype until + // we return to a context that does not provide any hints, or until the user + // explicitly changes the language/subtype in use. + public InputMethodSubtype getSubtypeForLocales(final RichInputMethodManager richImm, final Iterable locales) { + final InputMethodSubtype overriddenByLocale = mOverriddenByLocale; + if (locales == null) { + if (overriddenByLocale != null) { + // no locales provided, so switch back to + // whatever subtype was used last time. + mOverriddenByLocale = null; + + return overriddenByLocale; + } + + return null; + } + + final InputMethodSubtype currentSubtype = richImm.getCurrentSubtype().getRawSubtype(); + final Locale currentSubtypeLocale = richImm.getCurrentSubtypeLocale(); + final int minimumMatchLevel = 3; // LocaleUtils.LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER; + + // Try finding a subtype matching the hint language. + for (final Locale hintLocale : locales) { + if (LocaleUtils.INSTANCE.getMatchLevel(hintLocale, currentSubtypeLocale) >= minimumMatchLevel + || CollectionsKt.any(mSettings.getCurrent().mSecondaryLocales, + (secLocale) -> LocaleUtils.INSTANCE.getMatchLevel(hintLocale, secLocale) >= minimumMatchLevel)) { + // current locales are already a good match, and we want to avoid unnecessary layout switches. + return null; + } + + final InputMethodSubtype subtypeForHintLocale = richImm.findSubtypeForHintLocale(hintLocale); + if (subtypeForHintLocale == null) { + continue; + } + + if (subtypeForHintLocale.equals(currentSubtype)) { + // no need to switch, we already use the correct locale. + return null; + } + + if (overriddenByLocale == null) { + // auto-switching based on hint locale, so store + // whatever subtype was in use so we can switch back + // to it later when there are no hint locales. + mOverriddenByLocale = currentSubtype; + } + + return subtypeForHintLocale; + } + + return null; + } + + public void onSubtypeChanged(final InputMethodSubtype oldSubtype, + final InputMethodSubtype newSubtype) { + if (oldSubtype != mOverriddenByLocale) { + // Whenever the subtype is changed, clear tracking + // the subtype that is overridden by a HintLocale as + // we no longer have a subtype to automatically switch back to. + mOverriddenByLocale = null; + } + } + public void switchSubtype(final RichInputMethodManager richImm) { final InputMethodSubtype currentSubtype = richImm.getCurrentSubtype().getRawSubtype(); final InputMethodSubtype lastActiveSubtype = mLastActiveSubtype; @@ -668,8 +737,8 @@ public class LatinIME extends InputMethodService implements if (mDictionaryFacilitator.usesSameSettings( locales, mSettings.getCurrent().mUseContactsDictionary, - mSettings.getCurrent().mUsePersonalizedDicts, - mSettings.getCurrent().mAccount + mSettings.getCurrent().mUseAppsDictionary, + mSettings.getCurrent().mUsePersonalizedDicts )) { return; } @@ -686,8 +755,8 @@ public class LatinIME extends InputMethodService implements private void resetDictionaryFacilitator(@NonNull final Locale locale) { final SettingsValues settingsValues = mSettings.getCurrent(); mDictionaryFacilitator.resetDictionaries(this, locale, - settingsValues.mUseContactsDictionary, settingsValues.mUsePersonalizedDicts, - false, settingsValues.mAccount, "", this); + settingsValues.mUseContactsDictionary, settingsValues.mUseAppsDictionary, + settingsValues.mUsePersonalizedDicts, false, "", this); mInputLogic.mSuggest.setAutoCorrectionThreshold(settingsValues.mAutoCorrectionThreshold); } @@ -696,12 +765,9 @@ public class LatinIME extends InputMethodService implements */ /* package private */ void resetSuggestMainDict() { final SettingsValues settingsValues = mSettings.getCurrent(); - mDictionaryFacilitator.resetDictionaries(this /* context */, - mDictionaryFacilitator.getMainLocale(), settingsValues.mUseContactsDictionary, - settingsValues.mUsePersonalizedDicts, - true /* forceReloadMainDictionary */, - settingsValues.mAccount, "" /* dictNamePrefix */, - this /* DictionaryInitializationListener */); + mDictionaryFacilitator.resetDictionaries(this, mDictionaryFacilitator.getMainLocale(), + settingsValues.mUseContactsDictionary, settingsValues.mUseAppsDictionary, + settingsValues.mUsePersonalizedDicts, true, "", this); } // used for debug @@ -858,6 +924,8 @@ public class LatinIME extends InputMethodService implements return; } InputMethodSubtype oldSubtype = mRichImm.getCurrentSubtype().getRawSubtype(); + + mSubtypeState.onSubtypeChanged(oldSubtype, subtype); StatsUtils.onSubtypeChanged(oldSubtype, subtype); mRichImm.onSubtypeChanged(subtype); mInputLogic.onSubtypeChanged(SubtypeLocaleUtils.getCombiningRulesExtraValue(subtype), @@ -876,20 +944,10 @@ public class LatinIME extends InputMethodService implements super.onStartInput(editorInfo, restarting); final List hintLocales = EditorInfoCompatUtils.getHintLocales(editorInfo); - if (hintLocales == null) { - return; - } - // Try switching to a subtype matching the hint language. - for (final Locale hintLocale : hintLocales) { - if (LocaleUtils.INSTANCE.getMatchLevel(hintLocale, mRichImm.getCurrentSubtypeLocale()) >= 3 - || CollectionsKt.any(mSettings.getCurrent().mSecondaryLocales, (secLocale) -> LocaleUtils.INSTANCE.getMatchLevel(hintLocale, secLocale) >= 3)) - return; // current locales are already a good match, and we want to avoid unnecessary layout switches - final InputMethodSubtype newSubtype = mRichImm.findSubtypeForHintLocale(hintLocale); - if (newSubtype == null) continue; - if (newSubtype.equals(mRichImm.getCurrentSubtype().getRawSubtype())) - return; // no need to switch, we already use the correct locale - mHandler.postSwitchLanguage(newSubtype); - break; + final InputMethodSubtype subtypeForLocales = mSubtypeState.getSubtypeForLocales(mRichImm, hintLocales); + if (subtypeForLocales != null) { + // found a better subtype using hint locales that we should switch to. + mHandler.postSwitchLanguage(subtypeForLocales); } } @@ -1403,7 +1461,7 @@ public class LatinIME extends InputMethodService implements // switch IME if wanted and possible if (switchIme && !switchSubtype && switchInputMethod()) return; - final boolean hasMoreThanOneSubtype = mRichImm.getMyEnabledInputMethodSubtypeList(false).size() > 1; + final boolean hasMoreThanOneSubtype = mRichImm.getMyEnabledInputMethodSubtypeList(true).size() > 1; // switch subtype if wanted, do nothing if no other subtype is available if (switchSubtype && !switchIme) { if (hasMoreThanOneSubtype) @@ -1960,8 +2018,10 @@ public class LatinIME extends InputMethodService implements public void onTrimMemory(int level) { super.onTrimMemory(level); switch (level) { - case TRIM_MEMORY_RUNNING_LOW, TRIM_MEMORY_RUNNING_CRITICAL, TRIM_MEMORY_COMPLETE -> - KeyboardLayoutSet.onSystemLocaleChanged(); // clears caches, nothing else + case TRIM_MEMORY_RUNNING_LOW, TRIM_MEMORY_RUNNING_CRITICAL, TRIM_MEMORY_COMPLETE -> { + KeyboardLayoutSet.onSystemLocaleChanged(); // clears caches, nothing else + mKeyboardSwitcher.trimMemory(); + } // deallocateMemory always called on hiding, and should not be called when showing } } diff --git a/app/src/main/java/helium314/keyboard/latin/RichInputMethodManager.java b/app/src/main/java/helium314/keyboard/latin/RichInputMethodManager.java index 607e30a92..d5e19d334 100644 --- a/app/src/main/java/helium314/keyboard/latin/RichInputMethodManager.java +++ b/app/src/main/java/helium314/keyboard/latin/RichInputMethodManager.java @@ -25,6 +25,7 @@ import helium314.keyboard.latin.utils.ScriptUtils; import helium314.keyboard.latin.utils.SubtypeLocaleUtils; import helium314.keyboard.latin.utils.SubtypeSettings; import helium314.keyboard.latin.utils.SubtypeUtilsKt; +import kotlin.collections.CollectionsKt; import java.util.Collections; import java.util.HashMap; @@ -91,9 +92,6 @@ public class RichInputMethodManager { mContext = context; mInputMethodInfoCache = new InputMethodInfoCache(mImm, context.getPackageName()); - // Initialize subtype utils. - SubtypeLocaleUtils.init(context); - // Initialize the current input method subtype and the shortcut IME. refreshSubtypeCaches(); } @@ -148,13 +146,15 @@ public class RichInputMethodManager { if (mCachedThisImeInfo != null) { return mCachedThisImeInfo; } - for (final InputMethodInfo imi : mImm.getInputMethodList()) { + final var inputMethods = mImm.getInputMethodList(); + for (final InputMethodInfo imi : inputMethods) { if (imi.getPackageName().equals(mImePackageName)) { mCachedThisImeInfo = imi; return imi; } } - throw new RuntimeException("Input method id for " + mImePackageName + " not found."); + throw new RuntimeException("Input method id for " + mImePackageName + " not found, only found" + + CollectionsKt.map(inputMethods, InputMethodInfo::getPackageName)); } public synchronized List getEnabledInputMethodSubtypeList( @@ -302,9 +302,8 @@ public class RichInputMethodManager { final int count = myImi.getSubtypeCount(); for (int i = 0; i < count; i++) { final InputMethodSubtype subtype = myImi.getSubtypeAt(i); - final String layoutName = SubtypeLocaleUtils.getMainLayoutName(subtype); - if (locale.equals(SubtypeUtilsKt.locale(subtype)) - && keyboardLayoutSetName.equals(layoutName)) { + final String layoutName = SubtypeUtilsKt.mainLayoutNameOrQwerty(subtype); + if (locale.equals(SubtypeUtilsKt.locale(subtype)) && keyboardLayoutSetName.equals(layoutName)) { return subtype; } } diff --git a/app/src/main/java/helium314/keyboard/latin/RichInputMethodSubtype.kt b/app/src/main/java/helium314/keyboard/latin/RichInputMethodSubtype.kt index 5764bd2d5..d79fc4133 100644 --- a/app/src/main/java/helium314/keyboard/latin/RichInputMethodSubtype.kt +++ b/app/src/main/java/helium314/keyboard/latin/RichInputMethodSubtype.kt @@ -10,10 +10,11 @@ import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder import helium314.keyboard.latin.common.Constants import helium314.keyboard.latin.common.Constants.Subtype.ExtraValue.KEYBOARD_LAYOUT_SET import helium314.keyboard.latin.common.LocaleUtils.constructLocale -import helium314.keyboard.latin.common.LocaleUtils.isRtlLanguage import helium314.keyboard.latin.utils.LayoutType import helium314.keyboard.latin.utils.LayoutUtilsCustom import helium314.keyboard.latin.utils.Log +import helium314.keyboard.latin.utils.ScriptUtils +import helium314.keyboard.latin.utils.ScriptUtils.script import helium314.keyboard.latin.utils.SubtypeLocaleUtils import helium314.keyboard.latin.utils.locale import java.util.Locale @@ -25,7 +26,7 @@ class RichInputMethodSubtype private constructor(val rawSubtype: InputMethodSubt val locale: Locale = rawSubtype.locale() // The subtype is considered RTL if the language of the main subtype is RTL. - val isRtlSubtype: Boolean = isRtlLanguage(locale) + val isRtlSubtype: Boolean = ScriptUtils.isScriptRtl(locale.script()) fun getExtraValueOf(key: String): String? = rawSubtype.getExtraValueOf(key) @@ -40,21 +41,9 @@ class RichInputMethodSubtype private constructor(val rawSubtype: InputMethodSubt val isCustom: Boolean get() = LayoutUtilsCustom.isCustomLayout(mainLayoutName) - val fullDisplayName: String get() { - if (isNoLanguage) { - return SubtypeLocaleUtils.getMainLayoutDisplayName(rawSubtype)!! - } - return SubtypeLocaleUtils.getSubtypeLocaleDisplayName(locale) - } + val fullDisplayName: String get() = SubtypeLocaleUtils.getSubtypeLocaleDisplayName(locale) - val middleDisplayName: String - // Get the RichInputMethodSubtype's middle display name in its locale. - get() { - if (isNoLanguage) { - return SubtypeLocaleUtils.getMainLayoutDisplayName(rawSubtype)!! - } - return SubtypeLocaleUtils.getSubtypeLanguageDisplayName(locale) - } + val middleDisplayName: String get() = SubtypeLocaleUtils.getSubtypeLanguageDisplayName(locale) override fun equals(other: Any?): Boolean { if (other !is RichInputMethodSubtype) return false @@ -81,7 +70,7 @@ class RichInputMethodSubtype private constructor(val rawSubtype: InputMethodSubt + "," + Constants.Subtype.ExtraValue.EMOJI_CAPABLE) private val DUMMY_NO_LANGUAGE_SUBTYPE = RichInputMethodSubtype( InputMethodSubtypeBuilder() - .setSubtypeNameResId(R.string.subtype_no_language_qwerty) + .setSubtypeNameResId(R.string.subtype_no_language) .setSubtypeIconResId(R.drawable.ic_ime_switcher) .setSubtypeLocale(SubtypeLocaleUtils.NO_LANGUAGE) .setSubtypeMode(Constants.Subtype.KEYBOARD_MODE) @@ -132,4 +121,4 @@ class RichInputMethodSubtype private constructor(val rawSubtype: InputMethodSubt return DUMMY_NO_LANGUAGE_SUBTYPE } } -} \ No newline at end of file +} diff --git a/app/src/main/java/helium314/keyboard/latin/SingleDictionaryFacilitator.kt b/app/src/main/java/helium314/keyboard/latin/SingleDictionaryFacilitator.kt new file mode 100644 index 000000000..e8941c459 --- /dev/null +++ b/app/src/main/java/helium314/keyboard/latin/SingleDictionaryFacilitator.kt @@ -0,0 +1,121 @@ +// SPDX-License-Identifier: GPL-3.0-only +package helium314.keyboard.latin + +import android.content.Context +import android.util.LruCache +import helium314.keyboard.keyboard.Keyboard +import helium314.keyboard.keyboard.KeyboardSwitcher +import helium314.keyboard.latin.DictionaryFacilitator.DictionaryInitializationListener +import helium314.keyboard.latin.common.ComposedData +import helium314.keyboard.latin.settings.SettingsValuesForSuggestion +import helium314.keyboard.latin.utils.SuggestionResults +import java.util.Locale +import java.util.concurrent.TimeUnit + +/** Simple DictionaryFacilitator for a single Dictionary. Has some optional special purpose functionality. */ +class SingleDictionaryFacilitator(private val dict: Dictionary) : DictionaryFacilitator { + var suggestionLogger: SuggestionLogger? = null + + // this will not work from spell checker if used together with a different keyboard app + fun getSuggestions(word: String): SuggestionResults { + val suggestionResults = getSuggestionResults( + ComposedData.createForWord(word), + NgramContext.getEmptyPrevWordsContext(0), + KeyboardSwitcher.getInstance().keyboard, // looks like actual keyboard doesn't matter (composed data doesn't contain coordinates) + SettingsValuesForSuggestion(false, false), + Suggest.SESSION_ID_TYPING, SuggestedWords.INPUT_STYLE_TYPING + ) + return suggestionResults + } + + override fun getSuggestionResults( + composedData: ComposedData, ngramContext: NgramContext, keyboard: Keyboard, + settingsValuesForSuggestion: SettingsValuesForSuggestion, sessionId: Int, inputStyle: Int + ): SuggestionResults { + val suggestionResults = SuggestionResults( + SuggestedWords.MAX_SUGGESTIONS, ngramContext.isBeginningOfSentenceContext, + false + ) + suggestionResults.addAll( + dict.getSuggestions(composedData, ngramContext, keyboard.proximityInfo.nativeProximityInfo, + settingsValuesForSuggestion, sessionId, 1f, + floatArrayOf(Dictionary.NOT_A_WEIGHT_OF_LANG_MODEL_VS_SPATIAL_MODEL) + ) + ) + suggestionLogger?.onNewSuggestions(suggestionResults, composedData, ngramContext, keyboard, inputStyle) + + return suggestionResults + } + + // ------------ dummy functionality ---------------- + + override fun setValidSpellingWordReadCache(cache: LruCache) {} + + override fun setValidSpellingWordWriteCache(cache: LruCache) {} + + override fun isForLocale(locale: Locale?): Boolean = locale == dict.mLocale + + override fun onStartInput() {} + + override fun onFinishInput(context: Context) { + dict.onFinishInput() + } + + override fun closeDictionaries() { + dict.close() + } + + override fun isActive(): Boolean = true + + override fun getMainLocale(): Locale = dict.mLocale + + override fun getCurrentLocale(): Locale = mainLocale + + override fun usesSameSettings(locales: List, contacts: Boolean, apps: Boolean, personalization: Boolean): Boolean { + return locales.singleOrNull() == mainLocale + } + + override fun resetDictionaries(context: Context, newLocale: Locale, useContactsDict: Boolean, useAppsDict: Boolean, + usePersonalizedDicts: Boolean, forceReloadMainDictionary: Boolean, dictNamePrefix: String, listener: DictionaryInitializationListener? + ) { } + + override fun hasAtLeastOneInitializedMainDictionary(): Boolean = dict.isInitialized + + override fun hasAtLeastOneUninitializedMainDictionary(): Boolean = !dict.isInitialized + + override fun waitForLoadingMainDictionaries(timeout: Long, unit: TimeUnit) { + } + + override fun addToUserHistory( + suggestion: String, wasAutoCapitalized: Boolean, ngramContext: NgramContext, + timeStampInSeconds: Long, blockPotentiallyOffensive: Boolean + ) {} + + override fun adjustConfidences(word: String, wasAutoCapitalized: Boolean) {} + + override fun unlearnFromUserHistory(word: String, ngramContext: NgramContext, timeStampInSeconds: Long, eventType: Int) {} + + override fun isValidSpellingWord(word: String): Boolean = dict.isValidWord(word) + + override fun isValidSuggestionWord(word: String) = isValidSpellingWord(word) + + override fun removeWord(word: String) {} + + override fun clearUserHistoryDictionary(context: Context) {} + + override fun localesAndConfidences(): String? = null + + override fun dumpDictionaryForDebug(dictName: String) {} + + override fun getDictionaryStats(context: Context): List = emptyList() + + override fun dump(context: Context) = getDictionaryStats(context).joinToString("\n") + + companion object { + interface SuggestionLogger { + /** provides input data and suggestions returned by the library */ + fun onNewSuggestions(suggestions: SuggestionResults, composedData: ComposedData, + ngramContext: NgramContext, keyboard: Keyboard, inputStyle: Int) + } + } +} diff --git a/app/src/main/java/helium314/keyboard/latin/UserBinaryDictionary.java b/app/src/main/java/helium314/keyboard/latin/UserBinaryDictionary.java index 0ff78fd6e..91d963cf8 100644 --- a/app/src/main/java/helium314/keyboard/latin/UserBinaryDictionary.java +++ b/app/src/main/java/helium314/keyboard/latin/UserBinaryDictionary.java @@ -82,8 +82,7 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary { } public static UserBinaryDictionary getDictionary( - final Context context, final Locale locale, final File dictFile, - final String dictNamePrefix, @Nullable final String account) { + final Context context, final Locale locale, final File dictFile, final String dictNamePrefix) { return new UserBinaryDictionary(context, locale, false, dictFile, dictNamePrefix + NAME); } diff --git a/app/src/main/java/helium314/keyboard/latin/WordComposer.java b/app/src/main/java/helium314/keyboard/latin/WordComposer.java index d67f50d7e..a5b50f353 100644 --- a/app/src/main/java/helium314/keyboard/latin/WordComposer.java +++ b/app/src/main/java/helium314/keyboard/latin/WordComposer.java @@ -218,6 +218,11 @@ public final class WordComposer { // TODO: compute where that puts us inside the events } + public void resetInvalidCursorPosition() { + if (mCursorPositionWithinWord > mCodePointSize) + mCursorPositionWithinWord = 0; + } + public boolean isCursorFrontOrMiddleOfComposingWord() { if (DebugFlags.DEBUG_ENABLED && mCursorPositionWithinWord > mCodePointSize) { throw new RuntimeException("Wrong cursor position : " + mCursorPositionWithinWord @@ -474,6 +479,10 @@ public final class WordComposer { return mIsBatchMode; } + public void unsetBatchMode() { + mIsBatchMode = false; + } + public void setRejectedBatchModeSuggestion(final String rejectedSuggestion) { mRejectedBatchModeSuggestion = rejectedSuggestion; } diff --git a/app/src/main/java/helium314/keyboard/latin/common/Colors.kt b/app/src/main/java/helium314/keyboard/latin/common/Colors.kt index ffbc13d62..708122828 100644 --- a/app/src/main/java/helium314/keyboard/latin/common/Colors.kt +++ b/app/src/main/java/helium314/keyboard/latin/common/Colors.kt @@ -274,11 +274,11 @@ class DynamicColors(context: Context, override val themeStyle: String, override override fun get(color: ColorType): Int = when (color) { TOOL_BAR_KEY_ENABLED_BACKGROUND, EMOJI_CATEGORY_SELECTED, ACTION_KEY_BACKGROUND, CLIPBOARD_PIN, SHIFT_KEY_ICON -> accent - AUTOFILL_BACKGROUND_CHIP, GESTURE_PREVIEW, POPUP_KEYS_BACKGROUND, MORE_SUGGESTIONS_BACKGROUND, KEY_PREVIEW -> adjustedBackground + AUTOFILL_BACKGROUND_CHIP, GESTURE_PREVIEW, POPUP_KEYS_BACKGROUND, MORE_SUGGESTIONS_BACKGROUND, KEY_PREVIEW_BACKGROUND -> adjustedBackground TOOL_BAR_EXPAND_KEY_BACKGROUND -> if (!isNight) accent else doubleAdjustedBackground GESTURE_TRAIL -> gesture - KEY_TEXT, SUGGESTION_AUTO_CORRECT, REMOVE_SUGGESTION_ICON, - KEY_ICON, ONE_HANDED_MODE_BUTTON, EMOJI_CATEGORY, TOOL_BAR_KEY, FUNCTIONAL_KEY_TEXT -> keyText + KEY_TEXT, SUGGESTION_AUTO_CORRECT, REMOVE_SUGGESTION_ICON, EMOJI_KEY_TEXT, KEY_PREVIEW_TEXT, POPUP_KEY_TEXT, + KEY_ICON, POPUP_KEY_ICON, ONE_HANDED_MODE_BUTTON, EMOJI_CATEGORY, TOOL_BAR_KEY, FUNCTIONAL_KEY_TEXT -> keyText KEY_HINT_TEXT -> keyHintText SPACE_BAR_TEXT -> spaceBarText FUNCTIONAL_KEY_BACKGROUND -> functionalKey @@ -327,7 +327,7 @@ class DynamicColors(context: Context, override val themeStyle: String, override EMOJI_CATEGORY_SELECTED, CLIPBOARD_PIN, SHIFT_KEY_ICON -> accentColorFilter REMOVE_SUGGESTION_ICON, EMOJI_CATEGORY, KEY_TEXT, KEY_ICON, ONE_HANDED_MODE_BUTTON, TOOL_BAR_KEY, TOOL_BAR_EXPAND_KEY -> keyTextFilter - KEY_PREVIEW -> adjustedBackgroundFilter + KEY_PREVIEW_BACKGROUND -> adjustedBackgroundFilter ACTION_KEY_ICON -> actionKeyIconColorFilter else -> colorFilter(get(color)) } @@ -336,7 +336,7 @@ class DynamicColors(context: Context, override val themeStyle: String, override if (view.background == null) view.setBackgroundColor(Color.WHITE) // set white to make the color filters work when (color) { - KEY_PREVIEW -> view.background.colorFilter = adjustedBackgroundFilter + KEY_PREVIEW_BACKGROUND -> view.background.colorFilter = adjustedBackgroundFilter FUNCTIONAL_KEY_BACKGROUND, KEY_BACKGROUND, MORE_SUGGESTIONS_WORD_BACKGROUND, SPACE_BAR_BACKGROUND, STRIP_BACKGROUND -> setColor(view.background, color) ONE_HANDED_MODE_BUTTON -> setColor(view.background, if (keyboardBackground == null) MAIN_BACKGROUND else STRIP_BACKGROUND) MORE_SUGGESTIONS_BACKGROUND -> view.background.colorFilter = backgroundFilter @@ -472,10 +472,11 @@ class DefaultColors ( TOOL_BAR_KEY_ENABLED_BACKGROUND, EMOJI_CATEGORY_SELECTED, ACTION_KEY_BACKGROUND, CLIPBOARD_PIN, SHIFT_KEY_ICON -> accent AUTOFILL_BACKGROUND_CHIP -> if (themeStyle == STYLE_MATERIAL && !hasKeyBorders) background else adjustedBackground - GESTURE_PREVIEW, POPUP_KEYS_BACKGROUND, MORE_SUGGESTIONS_BACKGROUND, KEY_PREVIEW -> adjustedBackground + GESTURE_PREVIEW, POPUP_KEYS_BACKGROUND, MORE_SUGGESTIONS_BACKGROUND, KEY_PREVIEW_BACKGROUND -> adjustedBackground TOOL_BAR_EXPAND_KEY_BACKGROUND, CLIPBOARD_SUGGESTION_BACKGROUND -> doubleAdjustedBackground GESTURE_TRAIL -> gesture - KEY_TEXT, REMOVE_SUGGESTION_ICON, FUNCTIONAL_KEY_TEXT, KEY_ICON -> keyText + KEY_TEXT, REMOVE_SUGGESTION_ICON, FUNCTIONAL_KEY_TEXT, KEY_ICON, EMOJI_KEY_TEXT, + POPUP_KEY_TEXT, POPUP_KEY_ICON, KEY_PREVIEW_TEXT -> keyText KEY_HINT_TEXT -> keyHintText SPACE_BAR_TEXT -> spaceBarText FUNCTIONAL_KEY_BACKGROUND -> functionalKey @@ -524,7 +525,7 @@ class DefaultColors ( if (view.background == null) view.setBackgroundColor(Color.WHITE) // set white to make the color filters work when (color) { - KEY_PREVIEW, POPUP_KEYS_BACKGROUND -> view.background.colorFilter = adjustedBackgroundFilter + KEY_PREVIEW_BACKGROUND, POPUP_KEYS_BACKGROUND -> view.background.colorFilter = adjustedBackgroundFilter FUNCTIONAL_KEY_BACKGROUND, KEY_BACKGROUND, MORE_SUGGESTIONS_WORD_BACKGROUND, SPACE_BAR_BACKGROUND, STRIP_BACKGROUND, CLIPBOARD_SUGGESTION_BACKGROUND -> setColor(view.background, color) ONE_HANDED_MODE_BUTTON -> setColor(view.background, if (keyboardBackground == null) MAIN_BACKGROUND else STRIP_BACKGROUND) MORE_SUGGESTIONS_BACKGROUND -> view.background.colorFilter = backgroundFilter @@ -547,7 +548,7 @@ class DefaultColors ( EMOJI_CATEGORY_SELECTED, CLIPBOARD_PIN, SHIFT_KEY_ICON -> accentColorFilter KEY_TEXT, KEY_ICON -> keyTextFilter REMOVE_SUGGESTION_ICON, EMOJI_CATEGORY, ONE_HANDED_MODE_BUTTON, TOOL_BAR_KEY, TOOL_BAR_EXPAND_KEY -> suggestionTextFilter - KEY_PREVIEW -> adjustedBackgroundFilter + KEY_PREVIEW_BACKGROUND -> adjustedBackgroundFilter ACTION_KEY_ICON -> actionKeyIconColorFilter else -> colorFilter(get(color)) // create color filter (not great for performance, so the frequently used filters should be stored) } @@ -620,6 +621,7 @@ enum class ColorType { CLIPBOARD_PIN, EMOJI_CATEGORY, EMOJI_CATEGORY_SELECTED, + EMOJI_KEY_TEXT, FUNCTIONAL_KEY_TEXT, FUNCTIONAL_KEY_BACKGROUND, GESTURE_TRAIL, @@ -628,11 +630,14 @@ enum class ColorType { KEY_ICON, KEY_TEXT, KEY_HINT_TEXT, - KEY_PREVIEW, + KEY_PREVIEW_BACKGROUND, + KEY_PREVIEW_TEXT, MORE_SUGGESTIONS_HINT, MORE_SUGGESTIONS_BACKGROUND, MORE_SUGGESTIONS_WORD_BACKGROUND, POPUP_KEYS_BACKGROUND, + POPUP_KEY_TEXT, + POPUP_KEY_ICON, NAVIGATION_BAR, SHIFT_KEY_ICON, SPACE_BAR_BACKGROUND, diff --git a/app/src/main/java/helium314/keyboard/latin/common/ComposedData.java b/app/src/main/java/helium314/keyboard/latin/common/ComposedData.java deleted file mode 100644 index 7e42f380a..000000000 --- a/app/src/main/java/helium314/keyboard/latin/common/ComposedData.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * modified - * SPDX-License-Identifier: Apache-2.0 AND GPL-3.0-only - */ - -package helium314.keyboard.latin.common; - -import androidx.annotation.NonNull; - -/** - * An immutable class that encapsulates a snapshot of word composition data. - */ -public class ComposedData { - @NonNull - public final InputPointers mInputPointers; - public final boolean mIsBatchMode; - @NonNull - public final String mTypedWord; - - public ComposedData(@NonNull final InputPointers inputPointers, final boolean isBatchMode, - @NonNull final String typedWord) { - mInputPointers = inputPointers; - mIsBatchMode = isBatchMode; - mTypedWord = typedWord; - } - - /** - * Copy the code points in the typed word to a destination array of ints. - * - * If the array is too small to hold the code points in the typed word, nothing is copied and - * -1 is returned. - * - * @param destination the array of ints. - * @return the number of copied code points. - */ - public int copyCodePointsExceptTrailingSingleQuotesAndReturnCodePointCount( - @NonNull final int[] destination) { - // lastIndex is exclusive - final int lastIndex = mTypedWord.length() - - StringUtils.getTrailingSingleQuotesCount(mTypedWord); - if (lastIndex <= 0) { - // The string is empty or contains only single quotes. - return 0; - } - - // The following function counts the number of code points in the text range which begins - // at index 0 and extends to the character at lastIndex. - final int codePointSize = Character.codePointCount(mTypedWord, 0, lastIndex); - if (codePointSize > destination.length) { - return -1; - } - return StringUtils.copyCodePointsAndReturnCodePointCount(destination, mTypedWord, 0, - lastIndex, true /* downCase */); - } -} diff --git a/app/src/main/java/helium314/keyboard/latin/common/ComposedData.kt b/app/src/main/java/helium314/keyboard/latin/common/ComposedData.kt new file mode 100644 index 000000000..091c41920 --- /dev/null +++ b/app/src/main/java/helium314/keyboard/latin/common/ComposedData.kt @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * modified + * SPDX-License-Identifier: Apache-2.0 AND GPL-3.0-only + */ +package helium314.keyboard.latin.common + +import helium314.keyboard.latin.WordComposer +import kotlin.random.Random + +/** An immutable class that encapsulates a snapshot of word composition data. */ +class ComposedData( + @JvmField val mInputPointers: InputPointers, + @JvmField val mIsBatchMode: Boolean, + @JvmField val mTypedWord: String +) { + /** + * Copy the code points in the typed word to a destination array of ints. + * + * If the array is too small to hold the code points in the typed word, nothing is copied and + * -1 is returned. + * + * @param destination the array of ints. + * @return the number of copied code points. + */ + fun copyCodePointsExceptTrailingSingleQuotesAndReturnCodePointCount( + destination: IntArray + ): Int { + // lastIndex is exclusive + val lastIndex = (mTypedWord.length - StringUtils.getTrailingSingleQuotesCount(mTypedWord)) + if (lastIndex <= 0) { + return 0 // The string is empty or contains only single quotes. + } + + // The following function counts the number of code points in the text range which begins + // at index 0 and extends to the character at lastIndex. + val codePointSize = Character.codePointCount(mTypedWord, 0, lastIndex) + if (codePointSize > destination.size) { + return -1 + } + return StringUtils.copyCodePointsAndReturnCodePointCount( + destination, mTypedWord, 0, lastIndex, true + ) + } + + companion object { + fun createForWord(word: String): ComposedData { + val codePoints = StringUtils.toCodePointArray(word) + val coordinates = CoordinateUtils.newCoordinateArray(codePoints.size) + for (i in codePoints.indices) { + CoordinateUtils.setXYInArray(coordinates, i, Random.nextBits(2), Random.nextBits(2)) + } + return WordComposer().apply { setComposingWord(codePoints, coordinates) }.composedDataSnapshot + } + } +} diff --git a/app/src/main/java/helium314/keyboard/latin/common/Constants.java b/app/src/main/java/helium314/keyboard/latin/common/Constants.java index 4dedec0ec..65df85cec 100644 --- a/app/src/main/java/helium314/keyboard/latin/common/Constants.java +++ b/app/src/main/java/helium314/keyboard/latin/common/Constants.java @@ -197,6 +197,8 @@ public final class Constants { public static final int CODE_GRAVE_ACCENT = '`'; public static final int CODE_CIRCUMFLEX_ACCENT = '^'; public static final int CODE_TILDE = '~'; + public static final int RECENTS_TEMPLATE_KEY_CODE_0 = 0x30; + public static final int RECENTS_TEMPLATE_KEY_CODE_1 = 0x31; public static final String REGEXP_PERIOD = "\\."; public static final String STRING_SPACE = " "; diff --git a/app/src/main/java/helium314/keyboard/latin/common/LocaleUtils.kt b/app/src/main/java/helium314/keyboard/latin/common/LocaleUtils.kt index 377d0c08d..f06ca7332 100644 --- a/app/src/main/java/helium314/keyboard/latin/common/LocaleUtils.kt +++ b/app/src/main/java/helium314/keyboard/latin/common/LocaleUtils.kt @@ -8,10 +8,10 @@ package helium314.keyboard.latin.common import android.content.Context import android.content.res.Resources import helium314.keyboard.compat.locale -import helium314.keyboard.latin.BuildConfig import helium314.keyboard.latin.R import helium314.keyboard.latin.utils.ScriptUtils.script import helium314.keyboard.latin.utils.SubtypeLocaleUtils +import helium314.keyboard.latin.utils.runInLocale import java.util.Locale /** @@ -171,34 +171,32 @@ object LocaleUtils { } } - @JvmStatic - fun isRtlLanguage(locale: Locale): Boolean { - val displayName = locale.getDisplayName(locale) - if (displayName.isEmpty()) return false - return when (Character.getDirectionality(displayName.codePointAt(0))) { - Character.DIRECTIONALITY_RIGHT_TO_LEFT, Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC -> true - else -> false - } - } + fun Locale.localizedDisplayName(resources: Resources, displayLocale: Locale? = null): String { + val languageTag = toLanguageTag() + if (languageTag == SubtypeLocaleUtils.NO_LANGUAGE) + return resources.getString(R.string.subtype_no_language) - fun Locale.localizedDisplayName(context: Context) = - getLocaleDisplayNameInLocale(this, context.resources, context.resources.configuration.locale()) - - @JvmStatic - fun getLocaleDisplayNameInLocale(locale: Locale, resources: Resources, displayLocale: Locale): String { - val languageTag = locale.toLanguageTag() - if (languageTag == SubtypeLocaleUtils.NO_LANGUAGE) return resources.getString(R.string.subtype_no_language) - if (locale.script() != locale.language.constructLocale().script() || locale.language == "mns" || locale.language == "xdq" || locale.language=="dru") { - val resId = resources.getIdentifier( - "subtype_${languageTag.replace("-", "_")}", - "string", - BuildConfig.APPLICATION_ID // replaces context.packageName, see https://stackoverflow.com/a/24525379 - ) - if (resId != 0) return resources.getString(resId) + val overrideResId = when (languageTag) { + "en-US" -> R.string.subtype_en_US + "en-GB" -> R.string.subtype_en_GB + "es-US" -> R.string.subtype_es_US + "hi-Latn" -> R.string.subtype_hi_Latn + "sr-Latn" -> R.string.subtype_sr_Latn + "mns" -> R.string.subtype_mns + "xdq" -> R.string.subtype_xdq + "dru" -> R.string.subtype_xdq + "st" -> R.string.subtype_st + "dag" -> R.string.subtype_dag + else -> 0 } - val localeDisplayName = locale.getDisplayName(displayLocale) + if (overrideResId != 0) { + return if (displayLocale == null) resources.getString(overrideResId) + else runInLocale(resources, displayLocale) { it.getString(overrideResId) } + } + + val localeDisplayName = getDisplayName(displayLocale ?: resources.configuration.locale()) return if (localeDisplayName == languageTag) { - locale.getDisplayName(Locale.US) // try fallback to English name, relevant e.g. fpr pms, see https://github.com/Helium314/HeliBoard/pull/748 + getDisplayName(Locale.US) // try fallback to English name, relevant e.g. fpr pms, see https://github.com/Helium314/HeliBoard/pull/748 } else { localeDisplayName } diff --git a/app/src/main/java/helium314/keyboard/latin/common/StringUtils.kt b/app/src/main/java/helium314/keyboard/latin/common/StringUtils.kt index 5b8af87c3..982be6919 100644 --- a/app/src/main/java/helium314/keyboard/latin/common/StringUtils.kt +++ b/app/src/main/java/helium314/keyboard/latin/common/StringUtils.kt @@ -6,67 +6,66 @@ import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode import helium314.keyboard.latin.common.StringUtils.mightBeEmoji import helium314.keyboard.latin.common.StringUtils.newSingleCodePointString import helium314.keyboard.latin.settings.SpacingAndPunctuations +import helium314.keyboard.latin.utils.SpacedTokens import java.math.BigInteger import java.util.Locale -fun loopOverCodePoints(s: CharSequence, run: (Int) -> Boolean) { - val text = if (s is String) s else s.toString() +fun CharSequence.codePointAt(offset: Int) = Character.codePointAt(this, offset) +fun CharSequence.codePointBefore(offset: Int) = Character.codePointBefore(this, offset) + +inline fun loopOverCodePoints(text: CharSequence, loop: (cp: Int, charCount: Int) -> Boolean) { var offset = 0 while (offset < text.length) { - val codepoint = text.codePointAt(offset) - if (run(codepoint)) return - offset += Character.charCount(codepoint) + val cp = text.codePointAt(offset) + val charCount = Character.charCount(cp) + if (loop(cp, charCount)) return + offset += charCount } } -fun loopOverCodePointsBackwards(s: CharSequence, run: (Int) -> Boolean) { - val text = if (s is String) s else s.toString() +inline fun loopOverCodePointsBackwards(text: CharSequence, loop: (cp: Int, charCount: Int) -> Boolean) { var offset = text.length while (offset > 0) { - val codepoint = text.codePointBefore(offset) - if (run(codepoint)) return - offset -= Character.charCount(codepoint) + val cp = text.codePointBefore(offset) + val charCount = Character.charCount(cp) + if (loop(cp, charCount)) return + offset -= charCount } } -fun nonWordCodePointAndNoSpaceBeforeCursor(s: CharSequence, spacingAndPunctuations: SpacingAndPunctuations): Boolean { +fun nonWordCodePointAndNoSpaceBeforeCursor(text: CharSequence, spacingAndPunctuations: SpacingAndPunctuations): Boolean { var space = false var nonWordCodePoint = false - loopOverCodePointsBackwards(s) { - if (!space && Character.isWhitespace(it)) - space = true - // treat double quote like a word codepoint for the purpose of this function (not great, maybe clarify name, or extend list of chars?) - if (!nonWordCodePoint && !spacingAndPunctuations.isWordCodePoint(it) && it != '"'.code) + loopOverCodePointsBackwards(text) { cp, _ -> + if (!space && Character.isWhitespace(cp)) space = true + // treat double quote like a word codepoint for this function (not great, maybe clarify name or extend list of chars?) + if (!nonWordCodePoint && !spacingAndPunctuations.isWordCodePoint(cp) && cp != '"'.code) { nonWordCodePoint = true + } space && nonWordCodePoint // stop if both are found } - return nonWordCodePoint && !space // return true if an non-word codepoint and no space was found + return nonWordCodePoint && !space // return true if a non-word codepoint and no space was found } -fun hasLetterBeforeLastSpaceBeforeCursor(s: CharSequence): Boolean { - var letter = false - loopOverCodePointsBackwards(s) { - if (Character.isWhitespace(it)) true - else if (Character.isLetter(it)) { - letter = true - true - } - else false +fun hasLetterBeforeLastSpaceBeforeCursor(text: CharSequence): Boolean { + loopOverCodePointsBackwards(text) { cp, _ -> + if (Character.isWhitespace(cp)) return false + else if (Character.isLetter(cp)) return true + false // continue } - return letter + return false } -/** get the complete emoji at end of [s], considering that emojis can be joined with ZWJ resulting in different emojis */ -fun getFullEmojiAtEnd(s: CharSequence): String { - val text = if (s is String) s else s.toString() - var offset = text.length +/** get the complete emoji at end of [text], considering that emojis can be joined with ZWJ resulting in different emojis */ +fun getFullEmojiAtEnd(text: CharSequence): String { + val s = text.toString() + var offset = s.length while (offset > 0) { - val codepoint = text.codePointBefore(offset) + val codepoint = s.codePointBefore(offset) // stop if codepoint can't be emoji - if (!mightBeEmoji(codepoint)) - return text.substring(offset) + if (!mightBeEmoji(codepoint)) return text.substring(offset) offset -= Character.charCount(codepoint) - if (offset > 0 && text[offset - 1].code == KeyCode.ZWJ) { + if (offset > 0 && s[offset - 1].code == KeyCode.ZWJ) { // todo: this appends ZWJ in weird cases like text, ZWJ, emoji // and detects single ZWJ as emoji (at least irrelevant for current use of getFullEmojiAtEnd) offset -= 1 @@ -76,19 +75,17 @@ fun getFullEmojiAtEnd(s: CharSequence): String { if (codepoint in 0x1F3FB..0x1F3FF) { // Skin tones are not added with ZWJ, but just appended. This is not nice as they can be emojis on their own, // but that's how it is done. Assume that an emoji before the skin tone will get merged (usually correct in practice) - val codepointBefore = text.codePointBefore(offset) + val codepointBefore = s.codePointBefore(offset) if (isEmoji(codepointBefore)) { offset -= Character.charCount(codepointBefore) continue } } // check the whole text after offset - val textToCheck = text.substring(offset) - if (isEmoji(textToCheck)) { - return textToCheck - } + val textToCheck = s.substring(offset) + if (isEmoji(textToCheck)) return textToCheck } - return text.substring(offset) + return s.substring(offset) } /** split the string on the first of consecutive space only, further consecutive spaces are added to the next split */ @@ -110,8 +107,7 @@ fun String.splitOnFirstSpacesOnly(): List { sb.append(c) } } - if (sb.isNotBlank()) - out.add(sb.toString()) + if (sb.isNotBlank()) out.add(sb.toString()) return out } @@ -120,8 +116,7 @@ fun CharSequence.isValidNumber(): Boolean { } fun String.decapitalize(locale: Locale): String { - if (isEmpty() || !this[0].isUpperCase()) - return this + if (isEmpty() || !this[0].isUpperCase()) return this return replaceFirstChar { it.lowercase(locale) } } @@ -136,11 +131,9 @@ fun containsValueWhenSplit(string: String?, value: String, split: String): Boole fun isEmoji(c: Int): Boolean = mightBeEmoji(c) && isEmoji(newSingleCodePointString(c)) -fun isEmoji(s: CharSequence): Boolean = mightBeEmoji(s) && s.matches(emoRegex) +fun isEmoji(text: CharSequence): Boolean = mightBeEmoji(text) && text.matches(emoRegex) -fun String.splitOnWhitespace() = split(whitespaceSplitRegex) - -private val whitespaceSplitRegex = "\\s+".toRegex() +fun String.splitOnWhitespace() = SpacedTokens(this).toList() // from https://github.com/mathiasbynens/emoji-test-regex-pattern, MIT license // matches single emojis only diff --git a/app/src/main/java/helium314/keyboard/latin/define/DebugFlags.kt b/app/src/main/java/helium314/keyboard/latin/define/DebugFlags.kt index 6829f71e3..08f54c4f0 100644 --- a/app/src/main/java/helium314/keyboard/latin/define/DebugFlags.kt +++ b/app/src/main/java/helium314/keyboard/latin/define/DebugFlags.kt @@ -11,6 +11,7 @@ import android.os.Build import helium314.keyboard.latin.BuildConfig import helium314.keyboard.latin.settings.DebugSettings import helium314.keyboard.latin.settings.Defaults +import helium314.keyboard.latin.utils.DeviceProtectedUtils import helium314.keyboard.latin.utils.Log import helium314.keyboard.latin.utils.prefs import java.io.File @@ -64,11 +65,17 @@ ${Log.getLog(100).joinToString("\n")} private fun writeCrashReportToFile(text: String) { try { - val dir = appContext.getExternalFilesDir(null) ?: return + val dir = appContext.getExternalFilesDir(null) val date = SimpleDateFormat("yyyy-MM-dd_HH-mm-ss").format(Calendar.getInstance().time) val crashReportFile = File(dir, "crash_report_$date.txt") - crashReportFile.writeText(text) - } catch (ignored: IOException) { + crashReportFile.appendText(text) + } catch (_: Exception) { + // can't write in external files dir, maybe device just booted and is still locked + // in this case there shouldn't be any sensitive data and we can put crash logs in unprotected files dir + val dir = DeviceProtectedUtils.getFilesDir(appContext) ?: return + val date = SimpleDateFormat("yyyy-MM-dd_HH-mm-ss").format(Calendar.getInstance().time) + val crashReportFile = File(dir, "crash_report_unprotected_$date.txt") + crashReportFile.appendText(text) } } } diff --git a/app/src/main/java/helium314/keyboard/latin/inputlogic/InputLogic.java b/app/src/main/java/helium314/keyboard/latin/inputlogic/InputLogic.java index 83d008642..e2ef27e6a 100644 --- a/app/src/main/java/helium314/keyboard/latin/inputlogic/InputLogic.java +++ b/app/src/main/java/helium314/keyboard/latin/inputlogic/InputLogic.java @@ -54,6 +54,7 @@ import helium314.keyboard.latin.utils.RecapitalizeStatus; import helium314.keyboard.latin.utils.ScriptUtils; import helium314.keyboard.latin.utils.StatsUtils; import helium314.keyboard.latin.utils.TextRange; +import helium314.keyboard.latin.utils.TimestampKt; import java.util.ArrayList; import java.util.Locale; @@ -323,7 +324,8 @@ public final class InputLogic { // Don't allow cancellation of manual pick mLastComposedWord.deactivate(); // Space state must be updated before calling updateShiftState - mSpaceState = SpaceState.PHANTOM; + if (settingsValues.mAutospaceAfterSuggestion) + mSpaceState = SpaceState.PHANTOM; inputTransaction.requireShiftUpdate(InputTransaction.SHIFT_UPDATE_NOW); // If we're not showing the "Touch again to save", then update the suggestion strip. @@ -438,19 +440,30 @@ public final class InputLogic { mWordBeingCorrectedByCursor = null; mJustRevertedACommit = false; final Event processedEvent; - if (currentKeyboardScript.equals(ScriptUtils.SCRIPT_HANGUL) - // only use the Hangul chain if codepoint may actually be Hangul - // todo: this whole hangul-related logic should probably be somewhere else - // need to use hangul combiner for whitespace, because otherwise the current word - // seems to get deleted / replaced by space during mConnection.endBatchEdit() - // similar for functional keys (codePoint -1) - && (event.getMCodePoint() >= 0x1100 || Character.isWhitespace(event.getMCodePoint()) || event.getMCodePoint() == -1)) { - mWordComposer.setHangul(true); - final Event hangulDecodedEvent = HangulEventDecoder.decodeSoftwareKeyEvent(event); - // todo: here hangul combiner does already consume the event, and appends typed codepoint - // to the current word instead of considering the cursor position - // position is actually not visible to the combiner, how to fix? - processedEvent = mWordComposer.processEvent(hangulDecodedEvent); + if (currentKeyboardScript.equals(ScriptUtils.SCRIPT_HANGUL)) { + // only use the Hangul chain if codepoint may actually be Hangul + // todo: this whole hangul-related logic should probably be somewhere else + // need to use hangul combiner for functional keys (codePoint -1), because otherwise the current word + // seems to get deleted / replaced by space during mConnection.endBatchEdit() + if (event.getMCodePoint() >= 0x1100 || event.getMCodePoint() == -1) { + mWordComposer.setHangul(true); + final Event hangulDecodedEvent = HangulEventDecoder.decodeSoftwareKeyEvent(event); + // todo: here hangul combiner does already consume the event, and appends typed codepoint + // to the current word instead of considering the cursor position + // position is actually not visible to the combiner, how to fix? + processedEvent = mWordComposer.processEvent(hangulDecodedEvent); + if (event.getMKeyCode() == KeyCode.DELETE) + mWordComposer.resetInvalidCursorPosition(); + } else { + mWordComposer.setHangul(false); + final boolean wasComposingWord = mWordComposer.isComposingWord(); + processedEvent = mWordComposer.processEvent(event); + // workaround for space and some other separators deleting / replacing the word + if (wasComposingWord && !mWordComposer.isComposingWord()) { + mWordComposer.resetInvalidCursorPosition(); + mConnection.finishComposingText(); + } + } } else { mWordComposer.setHangul(false); processedEvent = mWordComposer.processEvent(event); @@ -546,7 +559,8 @@ public final class InputLogic { || settingsValues.isUsuallyFollowedBySpace(codePointBeforeCursor)) { final boolean autoShiftHasBeenOverriden = keyboardSwitcher.getKeyboardShiftMode() != getCurrentAutoCapsState(settingsValues); - mSpaceState = SpaceState.PHANTOM; + if (settingsValues.mAutospaceBeforeGestureTyping) + mSpaceState = SpaceState.PHANTOM; if (!autoShiftHasBeenOverriden) { // When we change the space state, we need to update the shift state of the // keyboard unless it has been overridden manually. This is happening for example @@ -686,10 +700,7 @@ public final class InputLogic { if (mSuggestedWords.isPrediction()) { inputTransaction.setRequiresUpdateSuggestions(); } - // undo phantom space if it's because after punctuation - // users who want to start a sentence with a lowercase letter may not like it - if (mSpaceState == SpaceState.PHANTOM - && inputTransaction.getMSettingsValues().isUsuallyFollowedBySpace(mConnection.getCodePointBeforeCursor())) + if (mSpaceState == SpaceState.PHANTOM && inputTransaction.getMSettingsValues().mShiftRemovesAutospace) mSpaceState = SpaceState.NONE; break; case KeyCode.SETTINGS: @@ -756,16 +767,35 @@ public final class InputLogic { } break; case KeyCode.WORD_LEFT: - sendDownUpKeyEventWithMetaState(KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.META_CTRL_ON); + sendDownUpKeyEventWithMetaState(ScriptUtils.isScriptRtl(currentKeyboardScript)? + KeyEvent.KEYCODE_DPAD_RIGHT : KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.META_CTRL_ON); break; case KeyCode.WORD_RIGHT: - sendDownUpKeyEventWithMetaState(KeyEvent.KEYCODE_DPAD_RIGHT, KeyEvent.META_CTRL_ON); + sendDownUpKeyEventWithMetaState(ScriptUtils.isScriptRtl(currentKeyboardScript)? + KeyEvent.KEYCODE_DPAD_LEFT : KeyEvent.KEYCODE_DPAD_RIGHT, KeyEvent.META_CTRL_ON); break; case KeyCode.MOVE_START_OF_PAGE: + final int selectionEnd = mConnection.getExpectedSelectionEnd(); sendDownUpKeyEventWithMetaState(KeyEvent.KEYCODE_MOVE_HOME, KeyEvent.META_CTRL_ON); + if (mConnection.getExpectedSelectionStart() > 0 && mConnection.getExpectedSelectionEnd() == selectionEnd) { + // unchanged, and we're not at the top -> try a different method (necessary for compose fields) + mConnection.setSelection(0, 0); + } break; case KeyCode.MOVE_END_OF_PAGE: + final int selectionStart = mConnection.getExpectedSelectionEnd(); sendDownUpKeyEventWithMetaState(KeyEvent.KEYCODE_MOVE_END, KeyEvent.META_CTRL_ON); + if (mConnection.getExpectedSelectionStart() == selectionStart) { + // unchanged, try fallback e.g. for compose fields that don't care about ctrl + end + // we just move to a very large index, and hope the field is prepared to deal with this + // getting the actual length of the text for setting the correct position can be tricky for some apps... + try { + mConnection.setSelection(Integer.MAX_VALUE, Integer.MAX_VALUE); + } catch (Exception e) { + // better catch potential errors and just do nothing in this case + Log.i(TAG, "error when trying to move cursor to last position: " + e); + } + } break; case KeyCode.UNDO: sendDownUpKeyEventWithMetaState(KeyEvent.KEYCODE_Z, KeyEvent.META_CTRL_ON); @@ -776,14 +806,18 @@ public final class InputLogic { case KeyCode.SPLIT_LAYOUT: KeyboardSwitcher.getInstance().toggleSplitKeyboardMode(); break; + case KeyCode.TIMESTAMP: + mLatinIME.onTextInput(TimestampKt.getTimestamp(mLatinIME)); + break; case KeyCode.VOICE_INPUT: // switching to shortcut IME, shift state, keyboard,... is handled by LatinIME, // {@link KeyboardSwitcher#onEvent(Event)}, or {@link #onPressKey(int,int,boolean)} and {@link #onReleaseKey(int,boolean)}. // We need to switch to the shortcut IME. This is handled by LatinIME since the // input logic has no business with IME switching. case KeyCode.CAPS_LOCK, KeyCode.SYMBOL_ALPHA, KeyCode.ALPHA, KeyCode.SYMBOL, KeyCode.NUMPAD, KeyCode.EMOJI, - KeyCode.TOGGLE_ONE_HANDED_MODE, KeyCode.SWITCH_ONE_HANDED_MODE, - KeyCode.CTRL, KeyCode.ALT, KeyCode.FN, KeyCode.META: + KeyCode.TOGGLE_ONE_HANDED_MODE, KeyCode.SWITCH_ONE_HANDED_MODE, KeyCode.FN, + KeyCode.CTRL, KeyCode.CTRL_LEFT, KeyCode.CTRL_RIGHT, KeyCode.ALT, KeyCode.ALT_LEFT, KeyCode.ALT_RIGHT, + KeyCode.META, KeyCode.META_LEFT, KeyCode.META_RIGHT: break; default: if (event.getMMetaState() != 0) { @@ -930,6 +964,7 @@ public final class InputLogic { // handleNonSpecialCharacterEvent which has the same name as other handle* methods but is // not the same. boolean isComposingWord = mWordComposer.isComposingWord(); + mWordComposer.unsetBatchMode(); // relevant in case we continue a batch word with normal typing // if we continue directly after a sometimesWordConnector, restart suggestions for the whole word // (only with URL detection and suggestions enabled) @@ -949,7 +984,9 @@ public final class InputLogic { // TODO: remove isWordConnector() and use isUsuallyFollowedBySpace() instead. // See onStartBatchInput() to see how to do it. if (SpaceState.PHANTOM == inputTransaction.getMSpaceState() - && !settingsValues.isWordConnector(codePoint)) { + && !settingsValues.isWordConnector(codePoint) + && !settingsValues.isUsuallyFollowedBySpace(codePoint) // only relevant in rare cases + ) { if (isComposingWord) { // Sanity check throw new RuntimeException("Should not be composing here"); @@ -1127,7 +1164,7 @@ public final class InputLogic { // A double quote behaves like it's usually followed by space if we're inside // a double quote. if (wasComposingWord - && settingsValues.mAutospaceAfterPunctuationEnabled + && settingsValues.mAutospaceAfterPunctuation && (settingsValues.isUsuallyFollowedBySpace(codePoint) || isInsideDoubleQuoteOrAfterDigit)) { mSpaceState = SpaceState.PHANTOM; } @@ -1196,7 +1233,7 @@ public final class InputLogic { } inputTransaction.setRequiresUpdateSuggestions(); } else { - if (mLastComposedWord.canRevertCommit()) { + if (mLastComposedWord.canRevertCommit() && inputTransaction.getMSettingsValues().mBackspaceRevertsAutocorrect) { final String lastComposedWord = mLastComposedWord.mTypedWord; revertCommit(inputTransaction); StatsUtils.onRevertAutoCorrect(); @@ -2168,6 +2205,7 @@ public final class InputLogic { && !(mConnection.getCodePointBeforeCursor() == Constants.CODE_PERIOD && mConnection.wordBeforeCursorMayBeEmail()) ) { mConnection.commitCodePoint(Constants.CODE_SPACE); + // todo: why not remove phantom space state? } } @@ -2202,12 +2240,14 @@ public final class InputLogic { mConnection.beginBatchEdit(); if (SpaceState.PHANTOM == mSpaceState) { insertAutomaticSpaceIfOptionsAndTextAllow(settingsValues); + mSpaceState = SpaceState.NONE; } mWordComposer.setBatchInputWord(batchInputText); setComposingTextInternal(batchInputText, 1); mConnection.endBatchEdit(); // Space state must be updated before calling updateShiftState - mSpaceState = SpaceState.PHANTOM; + if (settingsValues.mAutospaceAfterGestureTyping) + mSpaceState = SpaceState.PHANTOM; keyboardSwitcher.requestUpdatingShiftState(getCurrentAutoCapsState(settingsValues), getCurrentRecapitalizeState()); } diff --git a/app/src/main/java/helium314/keyboard/latin/personalization/PersonalizationHelper.java b/app/src/main/java/helium314/keyboard/latin/personalization/PersonalizationHelper.java index 93f7f76cb..dc8692c6a 100644 --- a/app/src/main/java/helium314/keyboard/latin/personalization/PersonalizationHelper.java +++ b/app/src/main/java/helium314/keyboard/latin/personalization/PersonalizationHelper.java @@ -10,7 +10,6 @@ import android.content.Context; import helium314.keyboard.latin.utils.Log; import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import helium314.keyboard.latin.common.FileUtils; @@ -31,12 +30,8 @@ public class PersonalizationHelper { sLangUserHistoryDictCache = new ConcurrentHashMap<>(); @NonNull - public static UserHistoryDictionary getUserHistoryDictionary( - final Context context, final Locale locale, @Nullable final String accountName) { + public static UserHistoryDictionary getUserHistoryDictionary(final Context context, final Locale locale) { String lookupStr = locale.toString(); - if (accountName != null) { - lookupStr += "." + accountName; - } synchronized (sLangUserHistoryDictCache) { if (sLangUserHistoryDictCache.containsKey(lookupStr)) { final SoftReference ref = @@ -50,8 +45,7 @@ public class PersonalizationHelper { return dict; } } - final UserHistoryDictionary dict = new UserHistoryDictionary( - context, locale, accountName); + final UserHistoryDictionary dict = new UserHistoryDictionary(context, locale); sLangUserHistoryDictCache.put(lookupStr, new SoftReference<>(dict)); return dict; } diff --git a/app/src/main/java/helium314/keyboard/latin/personalization/UserHistoryDictionary.java b/app/src/main/java/helium314/keyboard/latin/personalization/UserHistoryDictionary.java index b860b1c96..98645080e 100644 --- a/app/src/main/java/helium314/keyboard/latin/personalization/UserHistoryDictionary.java +++ b/app/src/main/java/helium314/keyboard/latin/personalization/UserHistoryDictionary.java @@ -30,9 +30,8 @@ public class UserHistoryDictionary extends ExpandableBinaryDictionary { static final String NAME = UserHistoryDictionary.class.getSimpleName(); // TODO: Make this constructor private - UserHistoryDictionary(final Context context, final Locale locale, - @Nullable final String account) { - super(context, getUserHistoryDictName(NAME, locale, null /* dictFile */, account), locale, Dictionary.TYPE_USER_HISTORY, null); + UserHistoryDictionary(final Context context, final Locale locale) { + super(context, getUserHistoryDictName(NAME, locale, null), locale, Dictionary.TYPE_USER_HISTORY, null); if (mLocale != null && mLocale.toString().length() > 1) { reloadDictionaryIfRequired(); } @@ -41,14 +40,13 @@ public class UserHistoryDictionary extends ExpandableBinaryDictionary { /** * @returns the name of the {@link UserHistoryDictionary}. */ - static String getUserHistoryDictName(final String name, final Locale locale, - @Nullable final File dictFile, @Nullable final String account) { + static String getUserHistoryDictName(final String name, final Locale locale, @Nullable final File dictFile) { return getDictName(name, locale, dictFile); } public static UserHistoryDictionary getDictionary(final Context context, final Locale locale, - final File dictFile, final String dictNamePrefix, @Nullable final String account) { - return PersonalizationHelper.getUserHistoryDictionary(context, locale, account); + final File dictFile, final String dictNamePrefix) { + return PersonalizationHelper.getUserHistoryDictionary(context, locale); } /** diff --git a/app/src/main/java/helium314/keyboard/latin/settings/Defaults.kt b/app/src/main/java/helium314/keyboard/latin/settings/Defaults.kt index 0301409ba..0dff54197 100644 --- a/app/src/main/java/helium314/keyboard/latin/settings/Defaults.kt +++ b/app/src/main/java/helium314/keyboard/latin/settings/Defaults.kt @@ -9,7 +9,6 @@ import helium314.keyboard.keyboard.KeyboardTheme import helium314.keyboard.latin.BuildConfig import helium314.keyboard.latin.common.Constants.Separators import helium314.keyboard.latin.common.Constants.Subtype.ExtraValue -import helium314.keyboard.latin.utils.JniUtils import helium314.keyboard.latin.utils.LayoutType import helium314.keyboard.latin.utils.POPUP_KEYS_LABEL_DEFAULT import helium314.keyboard.latin.utils.POPUP_KEYS_ORDER_DEFAULT @@ -64,9 +63,11 @@ object Defaults { const val PREF_MORE_AUTO_CORRECTION = false const val PREF_AUTO_CORRECT_THRESHOLD = 0.185f const val PREF_AUTOCORRECT_SHORTCUTS = true + const val PREF_BACKSPACE_REVERTS_AUTOCORRECT = true const val PREF_CENTER_SUGGESTION_TEXT_TO_ENTER = false const val PREF_SHOW_SUGGESTIONS = true const val PREF_ALWAYS_SHOW_SUGGESTIONS = false + const val PREF_ALWAYS_SHOW_SUGGESTIONS_EXCEPT_WEB_TEXT = true const val PREF_KEY_USE_PERSONALIZED_DICTS = true const val PREF_KEY_USE_DOUBLE_SPACE_PERIOD = true const val PREF_BLOCK_POTENTIALLY_OFFENSIVE = true @@ -74,9 +75,9 @@ object Defaults { const val PREF_LANGUAGE_SWITCH_KEY = "internal" const val PREF_SHOW_EMOJI_KEY = false const val PREF_VARIABLE_TOOLBAR_DIRECTION = true - const val PREF_ADDITIONAL_SUBTYPES = "de${Separators.SET}${ExtraValue.KEYBOARD_LAYOUT_SET}=qwerty${Separators.SETS}" + - "fr${Separators.SET}${ExtraValue.KEYBOARD_LAYOUT_SET}=qwertz${Separators.SETS}" + - "hu${Separators.SET}${ExtraValue.KEYBOARD_LAYOUT_SET}=qwerty" + const val PREF_ADDITIONAL_SUBTYPES = "de${Separators.SET}${ExtraValue.KEYBOARD_LAYOUT_SET}=MAIN:qwerty${Separators.SETS}" + + "fr${Separators.SET}${ExtraValue.KEYBOARD_LAYOUT_SET}=MAIN:qwertz${Separators.SETS}" + + "hu${Separators.SET}${ExtraValue.KEYBOARD_LAYOUT_SET}=MAIN:qwerty" const val PREF_ENABLE_SPLIT_KEYBOARD = false const val PREF_ENABLE_SPLIT_KEYBOARD_LANDSCAPE = false const val PREF_SPLIT_SPACER_SCALE = SettingsValues.DEFAULT_SIZE_SCALE @@ -88,10 +89,16 @@ object Defaults { const val PREF_SIDE_PADDING_SCALE_LANDSCAPE = 0f const val PREF_FONT_SCALE = SettingsValues.DEFAULT_SIZE_SCALE const val PREF_EMOJI_FONT_SCALE = SettingsValues.DEFAULT_SIZE_SCALE + const val PREF_EMOJI_KEY_FIT = true + const val PREF_EMOJI_SKIN_TONE = "" const val PREF_SPACE_HORIZONTAL_SWIPE = "move_cursor" const val PREF_SPACE_VERTICAL_SWIPE = "none" const val PREF_DELETE_SWIPE = true const val PREF_AUTOSPACE_AFTER_PUNCTUATION = false + const val PREF_AUTOSPACE_AFTER_SUGGESTION = true + const val PREF_AUTOSPACE_AFTER_GESTURE_TYPING = true + const val PREF_AUTOSPACE_BEFORE_GESTURE_TYPING = true + const val PREF_SHIFT_REMOVES_AUTOSPACE = false const val PREF_ALWAYS_INCOGNITO_MODE = false const val PREF_BIGRAM_PREDICTIONS = true const val PREF_SUGGEST_CLIPBOARD_CONTENT = true @@ -110,6 +117,7 @@ object Defaults { const val PREF_GESTURE_TRAIL_FADEOUT_DURATION = 800 const val PREF_SHOW_SETUP_WIZARD_ICON = true const val PREF_USE_CONTACTS = false + const val PREF_USE_APPS = false const val PREFS_LONG_PRESS_SYMBOLS_FOR_NUMPAD = false const val PREF_ONE_HANDED_MODE = false @SuppressLint("RtlHardcoded") @@ -123,6 +131,7 @@ object Defaults { const val PREF_POPUP_KEYS_ORDER = POPUP_KEYS_ORDER_DEFAULT const val PREF_POPUP_KEYS_LABELS_ORDER = POPUP_KEYS_LABEL_DEFAULT const val PREF_SHOW_POPUP_HINTS = false + const val PREF_SHOW_TLD_POPUP_KEYS = true const val PREF_MORE_POPUP_KEYS = "main" const val PREF_SPACE_TO_CHANGE_LANG = true const val PREF_LANGUAGE_SWIPE_DISTANCE = 5 @@ -145,15 +154,14 @@ object Defaults { const val PREF_ABC_AFTER_EMOJI = false const val PREF_ABC_AFTER_CLIP = false const val PREF_ABC_AFTER_SYMBOL_SPACE = true + const val PREF_ABC_AFTER_NUMPAD_SPACE = false const val PREF_REMOVE_REDUNDANT_POPUPS = false const val PREF_SPACE_BAR_TEXT = "" - @JvmField + const val PREF_TIMESTAMP_FORMAT = "yyyy-MM-dd HH:mm:ss" val PREF_EMOJI_MAX_SDK = Build.VERSION.SDK_INT const val PREF_EMOJI_RECENT_KEYS = "" const val PREF_LAST_SHOWN_EMOJI_CATEGORY_PAGE_ID = 0 const val PREF_PINNED_CLIPS = "" - @JvmField - val PREF_LIBRARY_CHECKSUM: String = JniUtils.expectedDefaultChecksum() const val PREF_SHOW_DEBUG_SETTINGS = false val PREF_DEBUG_MODE = BuildConfig.DEBUG const val PREF_SHOW_SUGGESTION_INFOS = false diff --git a/app/src/main/java/helium314/keyboard/latin/settings/Settings.java b/app/src/main/java/helium314/keyboard/latin/settings/Settings.java index 89e93e8dd..6b6c5ddf4 100644 --- a/app/src/main/java/helium314/keyboard/latin/settings/Settings.java +++ b/app/src/main/java/helium314/keyboard/latin/settings/Settings.java @@ -71,9 +71,11 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang public static final String PREF_MORE_AUTO_CORRECTION = "more_auto_correction"; public static final String PREF_AUTO_CORRECT_THRESHOLD = "auto_correct_threshold"; public static final String PREF_AUTOCORRECT_SHORTCUTS = "autocorrect_shortcuts"; + public static final String PREF_BACKSPACE_REVERTS_AUTOCORRECT = "backspace_reverts_autocorrect"; public static final String PREF_CENTER_SUGGESTION_TEXT_TO_ENTER = "center_suggestion_text_to_enter"; public static final String PREF_SHOW_SUGGESTIONS = "show_suggestions"; public static final String PREF_ALWAYS_SHOW_SUGGESTIONS = "always_show_suggestions"; + public static final String PREF_ALWAYS_SHOW_SUGGESTIONS_EXCEPT_WEB_TEXT = "always_show_suggestions_except_web_text"; public static final String PREF_KEY_USE_PERSONALIZED_DICTS = "use_personalized_dicts"; public static final String PREF_KEY_USE_DOUBLE_SPACE_PERIOD = "use_double_space_period"; public static final String PREF_BLOCK_POTENTIALLY_OFFENSIVE = "block_potentially_offensive"; @@ -93,10 +95,16 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang public static final String PREF_SIDE_PADDING_SCALE_LANDSCAPE = "side_padding_scale_landscape"; public static final String PREF_FONT_SCALE = "font_scale"; public static final String PREF_EMOJI_FONT_SCALE = "emoji_font_scale"; + public static final String PREF_EMOJI_KEY_FIT = "emoji_key_fit"; + public static final String PREF_EMOJI_SKIN_TONE = "emoji_skin_tone"; public static final String PREF_SPACE_HORIZONTAL_SWIPE = "horizontal_space_swipe"; public static final String PREF_SPACE_VERTICAL_SWIPE = "vertical_space_swipe"; public static final String PREF_DELETE_SWIPE = "delete_swipe"; public static final String PREF_AUTOSPACE_AFTER_PUNCTUATION = "autospace_after_punctuation"; + public static final String PREF_AUTOSPACE_AFTER_SUGGESTION = "autospace_after_suggestion"; + public static final String PREF_AUTOSPACE_AFTER_GESTURE_TYPING = "autospace_after_gesture_typing"; + public static final String PREF_AUTOSPACE_BEFORE_GESTURE_TYPING = "autospace_before_gesture_typing"; + public static final String PREF_SHIFT_REMOVES_AUTOSPACE = "shift_removes_autospace"; public static final String PREF_ALWAYS_INCOGNITO_MODE = "always_incognito_mode"; public static final String PREF_BIGRAM_PREDICTIONS = "next_word_prediction"; public static final String PREF_SUGGEST_CLIPBOARD_CONTENT = "suggest_clipboard_content"; @@ -114,6 +122,7 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang public static final String PREF_GESTURE_TRAIL_FADEOUT_DURATION = "gesture_trail_fadeout_duration"; public static final String PREF_SHOW_SETUP_WIZARD_ICON = "show_setup_wizard_icon"; public static final String PREF_USE_CONTACTS = "use_contacts"; + public static final String PREF_USE_APPS = "use_apps"; public static final String PREFS_LONG_PRESS_SYMBOLS_FOR_NUMPAD = "long_press_symbols_for_numpad"; // one-handed mode gravity, enablement and scale, stored separately per orientation @@ -131,6 +140,7 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang public static final String PREF_POPUP_KEYS_LABELS_ORDER = "popup_keys_labels_order"; public static final String PREF_SHOW_POPUP_HINTS = "show_popup_hints"; public static final String PREF_MORE_POPUP_KEYS = "more_popup_keys"; + public static final String PREF_SHOW_TLD_POPUP_KEYS = "show_tld_popup_keys"; public static final String PREF_SPACE_TO_CHANGE_LANG = "prefs_long_press_keyboard_to_change_lang"; public static final String PREF_LANGUAGE_SWIPE_DISTANCE = "language_swipe_distance"; @@ -154,8 +164,10 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang public static final String PREF_ABC_AFTER_EMOJI = "abc_after_emoji"; public static final String PREF_ABC_AFTER_CLIP = "abc_after_clip"; public static final String PREF_ABC_AFTER_SYMBOL_SPACE = "abc_after_symbol_space"; + public static final String PREF_ABC_AFTER_NUMPAD_SPACE = "abc_after_numpad_space"; public static final String PREF_REMOVE_REDUNDANT_POPUPS = "remove_redundant_popups"; public static final String PREF_SPACE_BAR_TEXT = "space_bar_text"; + public static final String PREF_TIMESTAMP_FORMAT = "timestamp_format"; // Emoji public static final String PREF_EMOJI_MAX_SDK = "emoji_max_sdk"; @@ -312,10 +324,6 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang mPrefs.edit().putBoolean(Settings.PREF_ALWAYS_INCOGNITO_MODE, !oldValue).apply(); } - public static void writePrefAdditionalSubtypes(final SharedPreferences prefs, final String prefSubtypes) { - prefs.edit().putString(PREF_ADDITIONAL_SUBTYPES, prefSubtypes).apply(); - } - public static int readHorizontalSpaceSwipe(final SharedPreferences prefs) { return switch (prefs.getString(PREF_SPACE_HORIZONTAL_SWIPE, Defaults.PREF_SPACE_HORIZONTAL_SWIPE)) { case "move_cursor" -> KeyboardActionListener.SWIPE_MOVE_CURSOR; @@ -356,7 +364,7 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang public void writeOneHandedModeEnabled(final boolean enabled) { mPrefs.edit().putBoolean(PREF_ONE_HANDED_MODE_PREFIX + - (mSettingsValues.mDisplayOrientation == Configuration.ORIENTATION_PORTRAIT), enabled).apply(); + (mSettingsValues.mDisplayOrientation != Configuration.ORIENTATION_LANDSCAPE), enabled).apply(); } public static float readOneHandedModeScale(final SharedPreferences prefs, final boolean isLandscape) { @@ -365,7 +373,7 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang public void writeOneHandedModeScale(final Float scale) { mPrefs.edit().putFloat(PREF_ONE_HANDED_SCALE_PREFIX + - (mSettingsValues.mDisplayOrientation == Configuration.ORIENTATION_PORTRAIT), scale).apply(); + (mSettingsValues.mDisplayOrientation != Configuration.ORIENTATION_LANDSCAPE), scale).apply(); } public static int readOneHandedModeGravity(final SharedPreferences prefs, final boolean isLandscape) { @@ -374,7 +382,7 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang public void writeOneHandedModeGravity(final int gravity) { mPrefs.edit().putInt(PREF_ONE_HANDED_GRAVITY_PREFIX + - (mSettingsValues.mDisplayOrientation == Configuration.ORIENTATION_PORTRAIT), gravity).apply(); + (mSettingsValues.mDisplayOrientation != Configuration.ORIENTATION_LANDSCAPE), gravity).apply(); } public void writeSplitKeyboardEnabled(final boolean enabled, final boolean isLandscape) { diff --git a/app/src/main/java/helium314/keyboard/latin/settings/SettingsSubtype.kt b/app/src/main/java/helium314/keyboard/latin/settings/SettingsSubtype.kt index a5745295b..b966d92d8 100644 --- a/app/src/main/java/helium314/keyboard/latin/settings/SettingsSubtype.kt +++ b/app/src/main/java/helium314/keyboard/latin/settings/SettingsSubtype.kt @@ -11,39 +11,25 @@ import helium314.keyboard.latin.common.LocaleUtils.constructLocale import helium314.keyboard.latin.define.DebugFlags import helium314.keyboard.latin.utils.LayoutType import helium314.keyboard.latin.utils.LayoutType.Companion.toExtraValue -import helium314.keyboard.latin.utils.LayoutUtilsCustom import helium314.keyboard.latin.utils.Log import helium314.keyboard.latin.utils.ScriptUtils import helium314.keyboard.latin.utils.ScriptUtils.script -import helium314.keyboard.latin.utils.SubtypeLocaleUtils +import helium314.keyboard.latin.utils.SubtypeSettings import helium314.keyboard.latin.utils.SubtypeUtilsAdditional import helium314.keyboard.latin.utils.locale import java.util.Locale // some kind of intermediate between the string stored in preferences and an InputMethodSubtype +// todo: consider using a hashMap or sortedMap instead of a string if we run into comparison issues once again data class SettingsSubtype(val locale: Locale, val extraValues: String) { fun toPref() = locale.toLanguageTag() + Separators.SET + extraValues /** Creates an additional subtype from the SettingsSubtype. * Resulting InputMethodSubtypes are equal if SettingsSubtypes are equal */ - fun toAdditionalSubtype(): InputMethodSubtype? { + fun toAdditionalSubtype(): InputMethodSubtype { val asciiCapable = locale.script() == ScriptUtils.SCRIPT_LATIN - val subtype = SubtypeUtilsAdditional.createAdditionalSubtype(locale, extraValues, asciiCapable, true) - - // todo: this is returns null for all non-latin layouts - // either fix it, or remove the check - // if removed, removing a layout will result in fallback qwerty even for non-ascii, but this is better than the current alternative -/* if (subtype.nameResId == SubtypeLocaleUtils.UNKNOWN_KEYBOARD_LAYOUT - && mainLayoutName()?.endsWith("+") != true // "+" layouts and custom layouts are always "unknown" - && !LayoutUtilsCustom.isCustomLayout(mainLayoutName() ?: SubtypeLocaleUtils.QWERTY) - ) { - // Skip unknown keyboard layout subtype. This may happen when predefined keyboard - // layout has been removed. - Log.w(SettingsSubtype::class.simpleName, "unknown additional subtype $this") - return null - }*/ - return subtype + return SubtypeUtilsAdditional.createAdditionalSubtype(locale, extraValues, asciiCapable, true) } fun mainLayoutName() = LayoutType.getMainLayoutFromExtraValue(extraValues) @@ -54,7 +40,7 @@ data class SettingsSubtype(val locale: Locale, val extraValues: String) { val newList = extraValues.split(",") .filterNot { it.isBlank() || it.startsWith("$extraValueKey=") || it == extraValueKey } val newValue = if (extraValue == null) extraValueKey else "$extraValueKey=$extraValue" - val newValues = (newList + newValue).joinToString(",") + val newValues = (newList + newValue).sorted().joinToString(",") return copy(extraValues = newValues) } @@ -86,6 +72,8 @@ data class SettingsSubtype(val locale: Locale, val extraValues: String) { prefs.getString(Settings.PREF_ADDITIONAL_SUBTYPES, Defaults.PREF_ADDITIONAL_SUBTYPES)!! .split(Separators.SETS).contains(toPref()) + fun isSameAsDefault() = SubtypeSettings.getResourceSubtypesForLocale(locale).any { it.toSettingsSubtype() == this.toPref().toSettingsSubtype() } + companion object { fun String.toSettingsSubtype(): SettingsSubtype = SettingsSubtype( diff --git a/app/src/main/java/helium314/keyboard/latin/settings/SettingsValues.java b/app/src/main/java/helium314/keyboard/latin/settings/SettingsValues.java index 8576bc1d2..9c0b66f23 100644 --- a/app/src/main/java/helium314/keyboard/latin/settings/SettingsValues.java +++ b/app/src/main/java/helium314/keyboard/latin/settings/SettingsValues.java @@ -11,11 +11,11 @@ import android.content.Context; import android.content.SharedPreferences; import android.content.res.Configuration; import android.content.res.Resources; +import android.text.InputType; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodSubtype; import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import androidx.core.util.TypedValueCompat; import helium314.keyboard.compat.ConfigurationCompatKt; @@ -65,6 +65,7 @@ public class SettingsValues { public final boolean mShowNumberRowHints; public final boolean mShowsHints; public final boolean mShowsPopupHints; + public final boolean mShowTldPopupKeys; public final boolean mSpaceForLangChange; public final boolean mShowsEmojiKey; public final boolean mVarToolbarDirection; @@ -75,7 +76,11 @@ public class SettingsValues { public final int mSpaceSwipeVertical; public final int mLanguageSwipeDistance; public final boolean mDeleteSwipeEnabled; - public final boolean mAutospaceAfterPunctuationEnabled; + public final boolean mAutospaceAfterPunctuation; + public final boolean mAutospaceAfterSuggestion; + public final boolean mAutospaceAfterGestureTyping; + public final boolean mAutospaceBeforeGestureTyping; + public final boolean mShiftRemovesAutospace; public final boolean mClipboardHistoryEnabled; public final long mClipboardHistoryRetentionTime; public final boolean mOneHandedModeEnabled; @@ -103,6 +108,7 @@ public class SettingsValues { public final int mScreenMetrics; public final boolean mAddToPersonalDictionary; public final boolean mUseContactsDictionary; + public final boolean mUseAppsDictionary; public final boolean mCustomNavBarColor; public final float mKeyboardHeightScale; public final boolean mUrlDetectionEnabled; @@ -113,10 +119,12 @@ public class SettingsValues { public final boolean mAlphaAfterEmojiInEmojiView; public final boolean mAlphaAfterClipHistoryEntry; public final boolean mAlphaAfterSymbolAndSpace; + public final boolean mAlphaAfterNumpadAndSpace; public final boolean mRemoveRedundantPopups; public final String mSpaceBarText; public final float mFontSizeMultiplier; public final float mFontSizeMultiplierEmoji; + public final boolean mEmojiKeyFit; // From the input box @NonNull @@ -128,6 +136,7 @@ public class SettingsValues { public final boolean mAutoCorrectionEnabledPerUserSettings; public final boolean mAutoCorrectEnabled; public final float mAutoCorrectionThreshold; + public final boolean mBackspaceRevertsAutocorrect; public final int mScoreLimitForAutocorrect; public final boolean mAutoCorrectShortcuts; private final boolean mSuggestionsEnabledPerUserSettings; @@ -136,14 +145,10 @@ public class SettingsValues { public final SettingsValuesForSuggestion mSettingsValuesForSuggestion; public final boolean mIncognitoModeEnabled; public final boolean mLongPressSymbolsForNumpad; - public final int mEmojiMaxSdk; // User-defined colors public final Colors mColors; - @Nullable - public final String mAccount; // todo: always null, remove? - // creation of Colors and SpacingAndPunctuations are the slowest parts in here, but still ok public SettingsValues(final Context context, final SharedPreferences prefs, final Resources res, @NonNull final InputAttributes inputAttributes) { @@ -172,6 +177,7 @@ public class SettingsValues { mShowNumberRowHints = prefs.getBoolean(Settings.PREF_SHOW_NUMBER_ROW_HINTS, Defaults.PREF_SHOW_NUMBER_ROW_HINTS); mShowsHints = prefs.getBoolean(Settings.PREF_SHOW_HINTS, Defaults.PREF_SHOW_HINTS); mShowsPopupHints = prefs.getBoolean(Settings.PREF_SHOW_POPUP_HINTS, Defaults.PREF_SHOW_POPUP_HINTS); + mShowTldPopupKeys = prefs.getBoolean(Settings.PREF_SHOW_TLD_POPUP_KEYS, Defaults.PREF_SHOW_TLD_POPUP_KEYS); mSpaceForLangChange = prefs.getBoolean(Settings.PREF_SPACE_TO_CHANGE_LANG, Defaults.PREF_SPACE_TO_CHANGE_LANG); mShowsEmojiKey = prefs.getBoolean(Settings.PREF_SHOW_EMOJI_KEY, Defaults.PREF_SHOW_EMOJI_KEY); mVarToolbarDirection = prefs.getBoolean(Settings.PREF_VARIABLE_TOOLBAR_DIRECTION, Defaults.PREF_VARIABLE_TOOLBAR_DIRECTION); @@ -191,6 +197,7 @@ public class SettingsValues { mScoreLimitForAutocorrect = (mAutoCorrectionThreshold < 0) ? 600000 // very aggressive : (mAutoCorrectionThreshold < 0.07 ? 800000 : 950000); // aggressive or modest mAutoCorrectShortcuts = prefs.getBoolean(Settings.PREF_AUTOCORRECT_SHORTCUTS, Defaults.PREF_AUTOCORRECT_SHORTCUTS); + mBackspaceRevertsAutocorrect = prefs.getBoolean(Settings.PREF_BACKSPACE_REVERTS_AUTOCORRECT, Defaults.PREF_BACKSPACE_REVERTS_AUTOCORRECT); mBigramPredictionEnabled = prefs.getBoolean(Settings.PREF_BIGRAM_PREDICTIONS, Defaults.PREF_BIGRAM_PREDICTIONS); mSuggestClipboardContent = prefs.getBoolean(Settings.PREF_SUGGEST_CLIPBOARD_CONTENT, Defaults.PREF_SUGGEST_CLIPBOARD_CONTENT); mDoubleSpacePeriodTimeout = 1100; // ms @@ -217,8 +224,10 @@ public class SettingsValues { mGestureFloatingPreviewDynamicEnabled = Settings.readGestureDynamicPreviewEnabled(prefs); mGestureFastTypingCooldown = prefs.getInt(Settings.PREF_GESTURE_FAST_TYPING_COOLDOWN, Defaults.PREF_GESTURE_FAST_TYPING_COOLDOWN); mGestureTrailFadeoutDuration = prefs.getInt(Settings.PREF_GESTURE_TRAIL_FADEOUT_DURATION, Defaults.PREF_GESTURE_TRAIL_FADEOUT_DURATION); - mAccount = null; // remove? or can it be useful somewhere? - mOverrideShowingSuggestions = mInputAttributes.mMayOverrideShowingSuggestions && prefs.getBoolean(Settings.PREF_ALWAYS_SHOW_SUGGESTIONS, Defaults.PREF_ALWAYS_SHOW_SUGGESTIONS); + mOverrideShowingSuggestions = mInputAttributes.mMayOverrideShowingSuggestions + && prefs.getBoolean(Settings.PREF_ALWAYS_SHOW_SUGGESTIONS, Defaults.PREF_ALWAYS_SHOW_SUGGESTIONS) + && ((inputAttributes.mInputType & InputType.TYPE_MASK_VARIATION) != InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT + || !prefs.getBoolean(Settings.PREF_ALWAYS_SHOW_SUGGESTIONS_EXCEPT_WEB_TEXT, Defaults.PREF_ALWAYS_SHOW_SUGGESTIONS_EXCEPT_WEB_TEXT)); final boolean suggestionsEnabled = prefs.getBoolean(Settings.PREF_SHOW_SUGGESTIONS, Defaults.PREF_SHOW_SUGGESTIONS); mSuggestionsEnabledPerUserSettings = (mInputAttributes.mShouldShowSuggestions && suggestionsEnabled) || mOverrideShowingSuggestions; @@ -229,7 +238,11 @@ public class SettingsValues { mSpaceSwipeVertical = Settings.readVerticalSpaceSwipe(prefs); mLanguageSwipeDistance = prefs.getInt(Settings.PREF_LANGUAGE_SWIPE_DISTANCE, Defaults.PREF_LANGUAGE_SWIPE_DISTANCE); mDeleteSwipeEnabled = prefs.getBoolean(Settings.PREF_DELETE_SWIPE, Defaults.PREF_DELETE_SWIPE); - mAutospaceAfterPunctuationEnabled = prefs.getBoolean(Settings.PREF_AUTOSPACE_AFTER_PUNCTUATION, Defaults.PREF_AUTOSPACE_AFTER_PUNCTUATION); + mAutospaceAfterPunctuation = prefs.getBoolean(Settings.PREF_AUTOSPACE_AFTER_PUNCTUATION, Defaults.PREF_AUTOSPACE_AFTER_PUNCTUATION); + mAutospaceAfterSuggestion = prefs.getBoolean(Settings.PREF_AUTOSPACE_AFTER_SUGGESTION, Defaults.PREF_AUTOSPACE_AFTER_SUGGESTION); + mAutospaceAfterGestureTyping = prefs.getBoolean(Settings.PREF_AUTOSPACE_AFTER_GESTURE_TYPING, Defaults.PREF_AUTOSPACE_AFTER_GESTURE_TYPING); + mAutospaceBeforeGestureTyping = prefs.getBoolean(Settings.PREF_AUTOSPACE_BEFORE_GESTURE_TYPING, Defaults.PREF_AUTOSPACE_BEFORE_GESTURE_TYPING); + mShiftRemovesAutospace = prefs.getBoolean(Settings.PREF_SHIFT_REMOVES_AUTOSPACE, Defaults.PREF_SHIFT_REMOVES_AUTOSPACE); mClipboardHistoryEnabled = prefs.getBoolean(Settings.PREF_ENABLE_CLIPBOARD_HISTORY, Defaults.PREF_ENABLE_CLIPBOARD_HISTORY); mClipboardHistoryRetentionTime = prefs.getInt(Settings.PREF_CLIPBOARD_HISTORY_RETENTION_TIME, Defaults.PREF_CLIPBOARD_HISTORY_RETENTION_TIME); @@ -251,6 +264,7 @@ public class SettingsValues { mPopupKeyLabelSources = SubtypeUtilsKt.getPopupKeyLabelSources(selectedSubtype, prefs); mAddToPersonalDictionary = prefs.getBoolean(Settings.PREF_ADD_TO_PERSONAL_DICTIONARY, Defaults.PREF_ADD_TO_PERSONAL_DICTIONARY); mUseContactsDictionary = SettingsValues.readUseContactsEnabled(prefs, context); + mUseAppsDictionary = prefs.getBoolean(Settings.PREF_USE_APPS, Defaults.PREF_USE_APPS); mCustomNavBarColor = prefs.getBoolean(Settings.PREF_NAVBAR_COLOR, Defaults.PREF_NAVBAR_COLOR); mNarrowKeyGaps = prefs.getBoolean(Settings.PREF_NARROW_KEY_GAPS, Defaults.PREF_NARROW_KEY_GAPS); mSettingsValuesForSuggestion = new SettingsValuesForSuggestion( @@ -266,11 +280,12 @@ public class SettingsValues { mAlphaAfterEmojiInEmojiView = prefs.getBoolean(Settings.PREF_ABC_AFTER_EMOJI, Defaults.PREF_ABC_AFTER_EMOJI); mAlphaAfterClipHistoryEntry = prefs.getBoolean(Settings.PREF_ABC_AFTER_CLIP, Defaults.PREF_ABC_AFTER_CLIP); mAlphaAfterSymbolAndSpace = prefs.getBoolean(Settings.PREF_ABC_AFTER_SYMBOL_SPACE, Defaults.PREF_ABC_AFTER_SYMBOL_SPACE); + mAlphaAfterNumpadAndSpace = prefs.getBoolean(Settings.PREF_ABC_AFTER_NUMPAD_SPACE, Defaults.PREF_ABC_AFTER_NUMPAD_SPACE); mRemoveRedundantPopups = prefs.getBoolean(Settings.PREF_REMOVE_REDUNDANT_POPUPS, Defaults.PREF_REMOVE_REDUNDANT_POPUPS); mSpaceBarText = prefs.getString(Settings.PREF_SPACE_BAR_TEXT, Defaults.PREF_SPACE_BAR_TEXT); - mEmojiMaxSdk = prefs.getInt(Settings.PREF_EMOJI_MAX_SDK, Defaults.PREF_EMOJI_MAX_SDK); mFontSizeMultiplier = prefs.getFloat(Settings.PREF_FONT_SCALE, Defaults.PREF_FONT_SCALE); mFontSizeMultiplierEmoji = prefs.getFloat(Settings.PREF_EMOJI_FONT_SCALE, Defaults.PREF_EMOJI_FONT_SCALE); + mEmojiKeyFit = prefs.getBoolean(Settings.PREF_EMOJI_KEY_FIT, Defaults.PREF_EMOJI_KEY_FIT); } public boolean isApplicationSpecifiedCompletionsOn() { @@ -334,11 +349,12 @@ public class SettingsValues { return mDisplayOrientation == configuration.orientation; } - private static boolean readUseContactsEnabled(final SharedPreferences prefs, final Context context) { + private static boolean readUseContactsEnabled(final SharedPreferences prefs, final Context ctx) { final boolean setting = prefs.getBoolean(Settings.PREF_USE_CONTACTS, Defaults.PREF_USE_CONTACTS); if (!setting) return false; - if (PermissionsUtil.checkAllPermissionsGranted(context, Manifest.permission.READ_CONTACTS)) + if (PermissionsUtil.checkAllPermissionsGranted(ctx, Manifest.permission.READ_CONTACTS)) { return true; + } // disable if permission not granted prefs.edit().putBoolean(Settings.PREF_USE_CONTACTS, false).apply(); return false; diff --git a/app/src/main/java/helium314/keyboard/latin/spellcheck/AndroidSpellCheckerService.java b/app/src/main/java/helium314/keyboard/latin/spellcheck/AndroidSpellCheckerService.java index 807561799..73d66ad30 100644 --- a/app/src/main/java/helium314/keyboard/latin/spellcheck/AndroidSpellCheckerService.java +++ b/app/src/main/java/helium314/keyboard/latin/spellcheck/AndroidSpellCheckerService.java @@ -83,6 +83,7 @@ public final class AndroidSpellCheckerService extends SpellCheckerService final SharedPreferences prefs = KtxKt.prefs(this); prefs.registerOnSharedPreferenceChangeListener(this); onSharedPreferenceChanged(prefs, Settings.PREF_USE_CONTACTS); + onSharedPreferenceChanged(prefs, Settings.PREF_USE_APPS); final boolean blockOffensive = prefs.getBoolean(Settings.PREF_BLOCK_POTENTIALLY_OFFENSIVE, Defaults.PREF_BLOCK_POTENTIALLY_OFFENSIVE); mSettingsValuesForSuggestion = new SettingsValuesForSuggestion(blockOffensive, false); } @@ -93,13 +94,19 @@ public final class AndroidSpellCheckerService extends SpellCheckerService @Override public void onSharedPreferenceChanged(final SharedPreferences prefs, final String key) { - if (Settings.PREF_USE_CONTACTS.equals(key)) { + if (key != null) switch (key) { + case Settings.PREF_USE_CONTACTS -> { final boolean useContactsDictionary = prefs.getBoolean(Settings.PREF_USE_CONTACTS, Defaults.PREF_USE_CONTACTS); mDictionaryFacilitatorCache.setUseContactsDictionary(useContactsDictionary); - } else if (Settings.PREF_BLOCK_POTENTIALLY_OFFENSIVE.equals(key)) { + } + case Settings.PREF_USE_APPS -> { + final boolean useAppsDictionary = prefs.getBoolean(Settings.PREF_USE_APPS, Defaults.PREF_USE_APPS); + mDictionaryFacilitatorCache.setUseAppsDictionary(useAppsDictionary); + } + case Settings.PREF_BLOCK_POTENTIALLY_OFFENSIVE -> { final boolean blockOffensive = prefs.getBoolean(Settings.PREF_BLOCK_POTENTIALLY_OFFENSIVE, Defaults.PREF_BLOCK_POTENTIALLY_OFFENSIVE); mSettingsValuesForSuggestion = new SettingsValuesForSuggestion(blockOffensive, false); - } + }} } @Override diff --git a/app/src/main/java/helium314/keyboard/latin/suggestions/SuggestionStripLayoutHelper.java b/app/src/main/java/helium314/keyboard/latin/suggestions/SuggestionStripLayoutHelper.java index 07535c641..e7cf2ed56 100644 --- a/app/src/main/java/helium314/keyboard/latin/suggestions/SuggestionStripLayoutHelper.java +++ b/app/src/main/java/helium314/keyboard/latin/suggestions/SuggestionStripLayoutHelper.java @@ -373,7 +373,7 @@ final class SuggestionStripLayoutHelper { x += wordView.getMeasuredWidth(); if (SuggestionStripView.DEBUG_SUGGESTIONS) { - layoutDebugInfo(positionInStrip, placerView, x); + layoutDebugInfo(positionInStrip, placerView, (int) stripView.getX() + x); } } return startIndexOfMoreSuggestions; @@ -436,8 +436,7 @@ final class SuggestionStripLayoutHelper { placerView.addView(debugInfoView); debugInfoView.measure(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); final int infoWidth = debugInfoView.getMeasuredWidth(); - final int y = debugInfoView.getMeasuredHeight(); - ViewLayoutUtils.placeViewAt(debugInfoView, x - infoWidth, y, infoWidth, debugInfoView.getMeasuredHeight()); + ViewLayoutUtils.placeViewAt(debugInfoView, x - infoWidth, 0, infoWidth, debugInfoView.getMeasuredHeight()); } private int getSuggestionWidth(final int positionInStrip, final int maxWidth) { diff --git a/app/src/main/java/helium314/keyboard/latin/suggestions/SuggestionStripView.java b/app/src/main/java/helium314/keyboard/latin/suggestions/SuggestionStripView.java index 860759831..9a8e49f36 100644 --- a/app/src/main/java/helium314/keyboard/latin/suggestions/SuggestionStripView.java +++ b/app/src/main/java/helium314/keyboard/latin/suggestions/SuggestionStripView.java @@ -14,12 +14,9 @@ import android.content.Context; import android.content.SharedPreferences; import android.content.res.Resources; import android.graphics.Color; -import android.graphics.PorterDuff; import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; -import android.graphics.drawable.ShapeDrawable; -import android.graphics.drawable.shapes.OvalShape; import android.os.Build; import android.text.TextUtils; import android.util.AttributeSet; @@ -214,10 +211,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick mToolbarExpandKey.setOnClickListener(this); mToolbarExpandKey.setImageDrawable(Settings.getValues().mIncognitoModeEnabled ? mIncognitoIcon : mToolbarArrowIcon); colors.setColor(mToolbarExpandKey, ColorType.TOOL_BAR_EXPAND_KEY); - mToolbarExpandKey.setBackground(new ShapeDrawable(new OvalShape())); // ShapeDrawable color is black, need src_atop filter - mToolbarExpandKey.getBackground().setColorFilter(colors.get(ColorType.TOOL_BAR_EXPAND_KEY_BACKGROUND), PorterDuff.Mode.SRC_ATOP); - mToolbarExpandKey.getLayoutParams().height *= 0.82; // shrink the whole key a little (drawable not affected) - mToolbarExpandKey.getLayoutParams().width *= 0.82; + colors.setColor(mToolbarExpandKey.getBackground(), ColorType.TOOL_BAR_EXPAND_KEY_BACKGROUND); for (final ToolbarKey pinnedKey : ToolbarUtilsKt.getPinnedToolbarKeys(prefs)) { final ImageButton button = createToolbarKey(context, iconsSet, pinnedKey); @@ -488,7 +482,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick mSuggestedWords.mIsObsoleteSuggestions, mSuggestedWords.mInputStyle, mSuggestedWords.mSequenceNumber); mStartIndexOfMoreSuggestions = mLayoutHelper.layoutAndReturnStartIndexOfMoreSuggestions( - getContext(), mSuggestedWords, mSuggestionsStrip, SuggestionStripView.this); + getContext(), mSuggestedWords, mSuggestionsStrip, this); mStripVisibilityGroup.showSuggestionsStrip(); // Show the toolbar if no suggestions are left and the "Auto show toolbar" setting is enabled if (mSuggestedWords.isEmpty() && Settings.getValues().mAutoShowToolbar){ @@ -707,6 +701,13 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick mSuggestionsStrip.setVisibility(VISIBLE); mPinnedKeys.setVisibility(VISIBLE); } + + if (DEBUG_SUGGESTIONS) { + for (var view : mDebugInfoViews) { + view.setVisibility(mSuggestionsStrip.getVisibility()); + } + } + mToolbarExpandKey.setScaleX((visible && !locked ? -1f : 1f) * mRtl); } diff --git a/app/src/main/java/helium314/keyboard/latin/utils/DialogUtils.kt b/app/src/main/java/helium314/keyboard/latin/utils/DialogUtils.kt index 470743bbb..e13f2f101 100644 --- a/app/src/main/java/helium314/keyboard/latin/utils/DialogUtils.kt +++ b/app/src/main/java/helium314/keyboard/latin/utils/DialogUtils.kt @@ -1,7 +1,7 @@ package helium314.keyboard.latin.utils import android.content.Context -import androidx.appcompat.view.ContextThemeWrapper +import android.view.ContextThemeWrapper import helium314.keyboard.latin.R // todo: ideally the custom InputMethodPicker would be removed / replaced with compose dialog, then this can be removed diff --git a/app/src/main/java/helium314/keyboard/latin/utils/DictionaryInfoUtils.java b/app/src/main/java/helium314/keyboard/latin/utils/DictionaryInfoUtils.java deleted file mode 100644 index b27de7655..000000000 --- a/app/src/main/java/helium314/keyboard/latin/utils/DictionaryInfoUtils.java +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * modified - * SPDX-License-Identifier: Apache-2.0 AND GPL-3.0-only - */ - -package helium314.keyboard.latin.utils; - -import android.content.Context; -import android.text.TextUtils; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import com.android.inputmethod.latin.utils.BinaryDictionaryUtils; - -import helium314.keyboard.latin.define.DecoderSpecificConstants; -import helium314.keyboard.latin.makedict.DictionaryHeader; -import helium314.keyboard.latin.makedict.UnsupportedFormatException; -import helium314.keyboard.latin.settings.SpacingAndPunctuations; - -import java.io.File; -import java.io.IOException; -import java.util.Locale; - -/** - * This class encapsulates the logic for the Latin-IME side of dictionary information management. - */ -public class DictionaryInfoUtils { - private static final String TAG = DictionaryInfoUtils.class.getSimpleName(); - public static final String DEFAULT_MAIN_DICT = "main"; - public static final String USER_DICTIONARY_SUFFIX = "user.dict"; - public static final String MAIN_DICT_PREFIX = DEFAULT_MAIN_DICT + "_"; - // 6 digits - unicode is limited to 21 bits - private static final int MAX_HEX_DIGITS_FOR_CODEPOINT = 6; - public static final String ASSETS_DICTIONARY_FOLDER = "dicts"; - public static final String ID_CATEGORY_SEPARATOR = ":"; - private static final String DICTIONARY_CATEGORY_SEPARATOR_EXPRESSION = "[" + ID_CATEGORY_SEPARATOR + "_]"; - - private DictionaryInfoUtils() { - // Private constructor to forbid instantation of this helper class. - } - - /** - * Returns whether we may want to use this character as part of a file name. - *

    - * This basically only accepts ascii letters and numbers, and rejects everything else. - */ - private static boolean isFileNameCharacter(int codePoint) { - if (codePoint >= 0x30 && codePoint <= 0x39) return true; // Digit - if (codePoint >= 0x41 && codePoint <= 0x5A) return true; // Uppercase - if (codePoint >= 0x61 && codePoint <= 0x7A) return true; // Lowercase - return codePoint == '_' || codePoint == '-'; - } - - /** - * Escapes a string for any characters that may be suspicious for a file or directory name. - *

    - * Concretely this does a sort of URL-encoding except it will encode everything that's not - * alphanumeric or underscore. (true URL-encoding leaves alone characters like '*', which - * we cannot allow here) - */ - // TODO: create a unit test for this method - public static String replaceFileNameDangerousCharacters(final String name) { - // This assumes '%' is fully available as a non-separator, normal - // character in a file name. This is probably true for all file systems. - final StringBuilder sb = new StringBuilder(); - final int nameLength = name.length(); - for (int i = 0; i < nameLength; i = name.offsetByCodePoints(i, 1)) { - final int codePoint = name.codePointAt(i); - if (DictionaryInfoUtils.isFileNameCharacter(codePoint)) { - sb.appendCodePoint(codePoint); - } else { - sb.append(String.format(Locale.US, "%%%1$0" + MAX_HEX_DIGITS_FOR_CODEPOINT + "x", codePoint)); - } - } - return sb.toString(); - } - - /** - * Helper method to get the top level cache directory. - */ - public static String getWordListCacheDirectory(final Context context) { - return context.getFilesDir() + File.separator + "dicts"; - } - - /** - * Reverse escaping done by {@link #replaceFileNameDangerousCharacters(String)}. - */ - @NonNull - public static String getWordListIdFromFileName(@NonNull final String fname) { - final StringBuilder sb = new StringBuilder(); - final int fnameLength = fname.length(); - for (int i = 0; i < fnameLength; i = fname.offsetByCodePoints(i, 1)) { - final int codePoint = fname.codePointAt(i); - if ('%' != codePoint) { - sb.appendCodePoint(codePoint); - } else { - // + 1 to pass the % sign - final int encodedCodePoint = - Integer.parseInt(fname.substring(i + 1, i + 1 + MAX_HEX_DIGITS_FOR_CODEPOINT), 16); - i += MAX_HEX_DIGITS_FOR_CODEPOINT; - sb.appendCodePoint(encodedCodePoint); - } - } - return sb.toString(); - } - - /** - * Helper method to the list of cache directories, one for each distinct locale. - */ - @Nullable public static File[] getCachedDirectoryList(final Context context) { - return new File(DictionaryInfoUtils.getWordListCacheDirectory(context)).listFiles(); - } - - /** - * Find out the cache directory associated with a specific locale. - */ - public static String getAndCreateCacheDirectoryForLocale(final Locale locale, final Context context) { - final String absoluteDirectoryName = getCacheDirectoryForLocale(locale, context); - final File directory = new File(absoluteDirectoryName); - if (!directory.exists()) { - if (!directory.mkdirs()) { - Log.e(TAG, "Could not create the directory for locale" + locale); - } - } - return absoluteDirectoryName; - } - - public static String getCacheDirectoryForLocale(final Locale locale, final Context context) { - final String relativeDirectoryName = replaceFileNameDangerousCharacters(locale.toLanguageTag()); - return getWordListCacheDirectory(context) + File.separator + relativeDirectoryName; - } - - public static File[] getCachedDictsForLocale(final Locale locale, final Context context) { - final File cachedDir = new File(getAndCreateCacheDirectoryForLocale(locale, context)); - if (!cachedDir.isDirectory()) - return new File[]{}; - return cachedDir.listFiles(); - } - - public static String getExtractedMainDictFilename() { - return DEFAULT_MAIN_DICT + ".dict"; - } - - @Nullable - public static DictionaryHeader getDictionaryFileHeaderOrNull(final File file, - final long offset, final long length) { - try { - return BinaryDictionaryUtils.getHeaderWithOffsetAndLength(file, offset, length); - } catch (UnsupportedFormatException | IOException e) { - return null; - } - } - - @Nullable - public static DictionaryHeader getDictionaryFileHeaderOrNull(final File file) { - try { - return BinaryDictionaryUtils.getHeader(file); - } catch (UnsupportedFormatException | IOException e) { - return null; - } - } - - /** - * Returns the locale for a dictionary file name stored in assets. - *

    - * Assumes file name main_[locale].dict - *

    - * Returns the locale, or null if file name does not match the pattern - */ - @Nullable public static String extractLocaleFromAssetsDictionaryFile(final String dictionaryFileName) { - if (dictionaryFileName.startsWith(DictionaryInfoUtils.MAIN_DICT_PREFIX) - && dictionaryFileName.endsWith(".dict")) { - return dictionaryFileName.substring( - DictionaryInfoUtils.MAIN_DICT_PREFIX.length(), - dictionaryFileName.lastIndexOf('.') - ); - } - return null; - } - - @Nullable public static String[] getAssetsDictionaryList(final Context context) { - final String[] dictionaryList; - try { - dictionaryList = context.getAssets().list(ASSETS_DICTIONARY_FOLDER); - } catch (IOException e) { - return null; - } - return dictionaryList; - } - - public static boolean looksValidForDictionaryInsertion(final CharSequence text, - final SpacingAndPunctuations spacingAndPunctuations) { - if (TextUtils.isEmpty(text)) { - return false; - } - final int length = text.length(); - if (length > DecoderSpecificConstants.DICTIONARY_MAX_WORD_LENGTH) { - return false; - } - int i = 0; - int digitCount = 0; - while (i < length) { - final int codePoint = Character.codePointAt(text, i); - final int charCount = Character.charCount(codePoint); - i += charCount; - if (Character.isDigit(codePoint)) { - // Count digits: see below - digitCount += charCount; - continue; - } - if (!spacingAndPunctuations.isWordCodePoint(codePoint)) { - return false; - } - } - // We reject strings entirely comprised of digits to avoid using PIN codes or credit - // card numbers. It would come in handy for word prediction though; a good example is - // when writing one's address where the street number is usually quite discriminative, - // as well as the postal code. - return digitCount < length; - } -} diff --git a/app/src/main/java/helium314/keyboard/latin/utils/DictionaryInfoUtils.kt b/app/src/main/java/helium314/keyboard/latin/utils/DictionaryInfoUtils.kt new file mode 100644 index 000000000..8715d2d4c --- /dev/null +++ b/app/src/main/java/helium314/keyboard/latin/utils/DictionaryInfoUtils.kt @@ -0,0 +1,187 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * modified + * SPDX-License-Identifier: Apache-2.0 AND GPL-3.0-only + */ +package helium314.keyboard.latin.utils + +import android.content.Context +import android.text.TextUtils +import com.android.inputmethod.latin.utils.BinaryDictionaryUtils +import helium314.keyboard.latin.common.FileUtils +import helium314.keyboard.latin.common.LocaleUtils.constructLocale +import helium314.keyboard.latin.common.loopOverCodePoints +import helium314.keyboard.latin.define.DecoderSpecificConstants +import helium314.keyboard.latin.makedict.DictionaryHeader +import helium314.keyboard.latin.makedict.UnsupportedFormatException +import helium314.keyboard.latin.settings.SpacingAndPunctuations +import java.io.File +import java.io.IOException +import java.util.Locale + +/** encapsulates the logic for the Latin-IME side of dictionary information management */ +object DictionaryInfoUtils { + private val TAG = DictionaryInfoUtils::class.java.simpleName + const val DEFAULT_MAIN_DICT = "main" + const val USER_DICTIONARY_SUFFIX = "user.dict" + const val MAIN_DICT_PREFIX = DEFAULT_MAIN_DICT + "_" + const val ASSETS_DICTIONARY_FOLDER = "dicts" + const val MAIN_DICT_FILE_NAME = DEFAULT_MAIN_DICT + ".dict" + private const val MAX_HEX_DIGITS_FOR_CODEPOINT = 6 // unicode is limited to 21 bits + + /** + * Returns whether we may want to use this character as part of a file name. + * This basically only accepts ascii letters and numbers, and rejects everything else. + */ + private fun isFileNameCharacter(codePoint: Int): Boolean { + if (codePoint in 0x30..0x39) return true // Digit + if (codePoint in 0x41..0x5A) return true // Uppercase + if (codePoint in 0x61..0x7A) return true // Lowercase + return codePoint == '_'.code || codePoint == '-'.code + } + + /** + * Escapes a string for any characters that may be suspicious for a file or directory name. + * + * Concretely this does a sort of URL-encoding except it will encode everything that's not + * alphanumeric or underscore. (true URL-encoding leaves alone characters like '*', which + * we cannot allow here) + */ + private fun replaceFileNameDangerousCharacters(name: String): String { + // This assumes '%' is fully available as a non-separator, normal + // character in a file name. This is probably true for all file systems. + val sb = StringBuilder() + loopOverCodePoints(name) { codePoint, _ -> + if (isFileNameCharacter(codePoint)) { + sb.appendCodePoint(codePoint) + } else { + sb.append(String.format(Locale.US, "%%%1$0" + MAX_HEX_DIGITS_FOR_CODEPOINT + "x", codePoint)) + } + false + } + return sb.toString() + } + + // we cache the extracted dictionaries in filesDir, because actual cache might be cleared at + // any time, and we can't permanently check whether the dictionary still exists + fun getWordListCacheDirectory(context: Context): String = context.filesDir.toString() + File.separator + "dicts" + + /** Reverse escaping done by replaceFileNameDangerousCharacters. */ + fun getWordListIdFromFileName(fname: String): String { + val sb = StringBuilder() + val fnameLength = fname.length + var i = 0 + while (i < fnameLength) { + val codePoint = fname.codePointAt(i) + if ('%'.code != codePoint) { + sb.appendCodePoint(codePoint) + } else { + // + 1 to pass the % sign + val encodedCodePoint = fname.substring(i + 1, i + 1 + MAX_HEX_DIGITS_FOR_CODEPOINT).toInt(16) + i += MAX_HEX_DIGITS_FOR_CODEPOINT + sb.appendCodePoint(encodedCodePoint) + } + i = fname.offsetByCodePoints(i, 1) + } + return sb.toString() + } + + /** Helper method to the list of cache directories, one for each distinct locale. */ + fun getCacheDirectories(context: Context) = File(getWordListCacheDirectory(context)).listFiles().orEmpty() + + /** Find out the cache directory associated with a specific locale. */ + fun getCacheDirectoryForLocale(locale: Locale, context: Context): String? { + val relativeDirectoryName = replaceFileNameDangerousCharacters(locale.toLanguageTag()) + val absoluteDirectoryName = getWordListCacheDirectory(context) + File.separator + relativeDirectoryName + val directory = File(absoluteDirectoryName) + if (!directory.exists() && !directory.mkdirs()) { + Log.e(TAG, "Could not create the directory for locale $locale") + return null + } + return absoluteDirectoryName + } + + fun getCachedDictsForLocale(locale: Locale, context: Context) = + getCacheDirectoryForLocale(locale, context)?.let { File(it).listFiles() }.orEmpty() + + fun getDictionaryFileHeaderOrNull(file: File, offset: Long, length: Long): DictionaryHeader? { + return try { + BinaryDictionaryUtils.getHeaderWithOffsetAndLength(file, offset, length) + } catch (e: UnsupportedFormatException) { + null + } catch (e: IOException) { + null + } + } + + fun getDictionaryFileHeaderOrNull(file: File): DictionaryHeader? { + return try { + BinaryDictionaryUtils.getHeader(file) + } catch (e: UnsupportedFormatException) { + null + } catch (e: IOException) { + null + } + } + + /** + * Returns the locale for a dictionary file name stored in assets. + * + * Assumes file name main_[locale].dict + * Returns the locale, or null if file name does not match the pattern + */ + fun extractLocaleFromAssetsDictionaryFile(dictionaryFileName: String): Locale { + if (dictionaryFileName.contains('_') && !dictionaryFileName.contains('.')) + throw IllegalStateException("invalid asset dictionary name $dictionaryFileName") + return dictionaryFileName.substringAfter("_").substringBefore(".").constructLocale() + } + + // actually we could extract assets dicts to unprotected storage + fun extractAssetsDictionary(dictionaryFileName: String, locale: Locale, context: Context): File? { + val cacheDir = getCacheDirectoryForLocale(locale, context) ?: return null + val targetFile = File(cacheDir, "${dictionaryFileName.substringBefore("_")}.dict") + try { + FileUtils.copyStreamToNewFile( + context.assets.open(ASSETS_DICTIONARY_FOLDER + File.separator + dictionaryFileName), + targetFile + ) + } catch (e: IOException) { + Log.e(TAG, "Could not extract assets dictionary $dictionaryFileName") + return null + } + return targetFile + } + + fun getAssetsDictionaryList(context: Context): Array? = try { + context.assets.list(ASSETS_DICTIONARY_FOLDER) + } catch (e: IOException) { + null + } + + @JvmStatic + fun looksValidForDictionaryInsertion(text: CharSequence, spacingAndPunctuations: SpacingAndPunctuations): Boolean { + if (TextUtils.isEmpty(text)) { + return false + } + if (text.length > DecoderSpecificConstants.DICTIONARY_MAX_WORD_LENGTH) { + return false + } + var digitCount = 0 + loopOverCodePoints(text) { codePoint, charCount -> + if (Character.isDigit(codePoint)) { + // Count digits: see below + digitCount += charCount + return@loopOverCodePoints false + } + if (!spacingAndPunctuations.isWordCodePoint(codePoint)) { + return false + } + false + } + // We reject strings entirely comprised of digits to avoid using PIN codes or credit + // card numbers. It would come in handy for word prediction though; a good example is + // when writing one's address where the street number is usually quite discriminative, + // as well as the postal code. + return digitCount < text.length + } +} diff --git a/app/src/main/java/helium314/keyboard/latin/utils/DictionaryUtils.kt b/app/src/main/java/helium314/keyboard/latin/utils/DictionaryUtils.kt index 3bbb310c4..e4f119d8b 100644 --- a/app/src/main/java/helium314/keyboard/latin/utils/DictionaryUtils.kt +++ b/app/src/main/java/helium314/keyboard/latin/utils/DictionaryUtils.kt @@ -25,7 +25,7 @@ fun getDictionaryLocales(context: Context): MutableSet { val locales = HashSet() // get cached dictionaries: extracted or user-added dictionaries - DictionaryInfoUtils.getCachedDirectoryList(context)?.forEach { directory -> + DictionaryInfoUtils.getCacheDirectories(context).forEach { directory -> if (!directory.isDirectory) return@forEach if (!hasAnythingOtherThanExtractedMainDictionary(directory)) return@forEach val locale = DictionaryInfoUtils.getWordListIdFromFileName(directory.name).constructLocale() @@ -35,8 +35,7 @@ fun getDictionaryLocales(context: Context): MutableSet { val assetsDictionaryList = DictionaryInfoUtils.getAssetsDictionaryList(context) if (assetsDictionaryList != null) { for (dictionary in assetsDictionaryList) { - val locale = DictionaryInfoUtils.extractLocaleFromAssetsDictionaryFile(dictionary)?.constructLocale() ?: continue - locales.add(locale) + locales.add(DictionaryInfoUtils.extractLocaleFromAssetsDictionaryFile(dictionary)) } } return locales @@ -135,4 +134,4 @@ fun cleanUnusedMainDicts(context: Context) { } private fun hasAnythingOtherThanExtractedMainDictionary(dir: File) = - dir.listFiles()?.any { it.name != DictionaryInfoUtils.getExtractedMainDictFilename() } != false + dir.listFiles()?.any { it.name != DictionaryInfoUtils.MAIN_DICT_FILE_NAME } != false diff --git a/app/src/main/java/helium314/keyboard/latin/utils/InputMethodPicker.kt b/app/src/main/java/helium314/keyboard/latin/utils/InputMethodPicker.kt index 33ac3d5d5..9879af717 100644 --- a/app/src/main/java/helium314/keyboard/latin/utils/InputMethodPicker.kt +++ b/app/src/main/java/helium314/keyboard/latin/utils/InputMethodPicker.kt @@ -2,6 +2,7 @@ package helium314.keyboard.latin.utils +import android.app.AlertDialog import android.os.IBinder import android.text.Spannable import android.text.SpannableString @@ -10,10 +11,10 @@ import android.text.style.RelativeSizeSpan import android.view.WindowManager import android.view.inputmethod.InputMethodInfo import android.view.inputmethod.InputMethodSubtype -import androidx.appcompat.app.AlertDialog import helium314.keyboard.latin.LatinIME import helium314.keyboard.latin.R import helium314.keyboard.latin.RichInputMethodManager +import helium314.keyboard.latin.utils.SubtypeLocaleUtils.displayName // similar to what showSubtypePicker does in https://github.com/rkkr/simple-keyboard/blob/master/app/src/main/java/rkr/simplekeyboard/inputmethod/latin/RichInputMethodManager.java fun createInputMethodPickerDialog(latinIme: LatinIME, richImm: RichInputMethodManager, windowToken: IBinder): AlertDialog { @@ -26,7 +27,7 @@ fun createInputMethodPickerDialog(latinIme: LatinIME, richImm: RichInputMethodMa var currentSubtypeIndex = 0 enabledImis.forEach { imi -> val subtypes = if (imi != thisImi) richImm.getEnabledInputMethodSubtypeList(imi, true) - else richImm.getEnabledInputMethodSubtypeList(imi, true).sortedBy { it.displayName(latinIme).toString() } + else richImm.getEnabledInputMethodSubtypeList(imi, true).sortedBy { it.displayName() } if (subtypes.isEmpty()) { enabledSubtypes.add(imi to null) } else { @@ -44,7 +45,7 @@ fun createInputMethodPickerDialog(latinIme: LatinIME, richImm: RichInputMethodMa for (imiAndSubtype in enabledSubtypes) { val (imi, subtype) = imiAndSubtype - val subtypeName = if (imi == thisImi) subtype?.displayName(latinIme) + val subtypeName = if (imi == thisImi) subtype?.displayName() else subtype?.getDisplayName(latinIme, imi.packageName, imi.serviceInfo.applicationInfo) val title = SpannableString(subtypeName?.ifBlank { imi.loadLabel(pm) } ?: imi.loadLabel(pm)) val subtitle = SpannableString(if (subtype == null) "" else "\n${imi.loadLabel(pm)}") diff --git a/app/src/main/java/helium314/keyboard/latin/utils/JniUtils.java b/app/src/main/java/helium314/keyboard/latin/utils/JniUtils.java index 603e32ab6..9998d7e26 100644 --- a/app/src/main/java/helium314/keyboard/latin/utils/JniUtils.java +++ b/app/src/main/java/helium314/keyboard/latin/utils/JniUtils.java @@ -13,7 +13,6 @@ import android.text.TextUtils; import helium314.keyboard.latin.App; import helium314.keyboard.latin.BuildConfig; -import helium314.keyboard.latin.settings.Defaults; import helium314.keyboard.latin.settings.Settings; import java.io.File; @@ -63,7 +62,7 @@ public final class JniUtils { // we want the default preferences, because storing the checksum in device protected storage is discouraged // see https://developer.android.com/reference/android/content/Context#createDeviceProtectedStorageContext() // if device is locked, this will throw an IllegalStateException - wantedChecksum = KtxKt.protectedPrefs(app).getString(Settings.PREF_LIBRARY_CHECKSUM, Defaults.PREF_LIBRARY_CHECKSUM); + wantedChecksum = KtxKt.protectedPrefs(app).getString(Settings.PREF_LIBRARY_CHECKSUM, expectedDefaultChecksum()); } final FileInputStream libStream = new FileInputStream(userSuppliedLibrary); final String checksum = ChecksumCalculator.INSTANCE.checksum(libStream); @@ -91,7 +90,7 @@ public final class JniUtils { System.loadLibrary(JNI_LIB_NAME_GOOGLE); sHaveGestureLib = true; } catch (UnsatisfiedLinkError ul) { - Log.w(TAG, "Could not load system glide typing library " + JNI_LIB_NAME_GOOGLE, ul); + Log.w(TAG, "Could not load system glide typing library " + JNI_LIB_NAME_GOOGLE + ": " + ul.getMessage()); } } if (!sHaveGestureLib) { diff --git a/app/src/main/java/helium314/keyboard/latin/utils/LanguageOnSpacebarUtils.java b/app/src/main/java/helium314/keyboard/latin/utils/LanguageOnSpacebarUtils.java index f942157ca..f7c400da2 100644 --- a/app/src/main/java/helium314/keyboard/latin/utils/LanguageOnSpacebarUtils.java +++ b/app/src/main/java/helium314/keyboard/latin/utils/LanguageOnSpacebarUtils.java @@ -43,16 +43,12 @@ public final class LanguageOnSpacebarUtils { return FORMAT_TYPE_NONE; } final Locale locale = subtype.getLocale(); - if (locale == null) { - return FORMAT_TYPE_NONE; - } final String keyboardLanguage = locale.getLanguage(); final String keyboardLayout = subtype.getMainLayoutName(); int sameLanguageAndLayoutCount = 0; for (final InputMethodSubtype ims : sEnabledSubtypes) { final String language = SubtypeUtilsKt.locale(ims).getLanguage(); - if (keyboardLanguage.equals(language) && keyboardLayout.equals( - SubtypeLocaleUtils.getMainLayoutName(ims))) { + if (keyboardLanguage.equals(language) && keyboardLayout.equals(SubtypeUtilsKt.mainLayoutNameOrQwerty(ims))) { sameLanguageAndLayoutCount++; } } diff --git a/app/src/main/java/helium314/keyboard/latin/utils/LayoutType.kt b/app/src/main/java/helium314/keyboard/latin/utils/LayoutType.kt index 412bb158c..00db72c87 100644 --- a/app/src/main/java/helium314/keyboard/latin/utils/LayoutType.kt +++ b/app/src/main/java/helium314/keyboard/latin/utils/LayoutType.kt @@ -13,9 +13,9 @@ enum class LayoutType { companion object { fun EnumMap.toExtraValue() = map { it.key.name + Separators.KV + it.value }.joinToString(Separators.ENTRY) - fun getLayoutMap(string: String): EnumMap { + fun getLayoutMap(string: String?): EnumMap { val map = EnumMap(LayoutType::class.java) - string.split(Separators.ENTRY).forEach { + string?.split(Separators.ENTRY)?.forEach { val s = it.split(Separators.KV) runCatching { map[LayoutType.valueOf(s[0])] = s[1] } } diff --git a/app/src/main/java/helium314/keyboard/latin/utils/LayoutUtils.kt b/app/src/main/java/helium314/keyboard/latin/utils/LayoutUtils.kt index 56afe9ce9..13bcb24c0 100644 --- a/app/src/main/java/helium314/keyboard/latin/utils/LayoutUtils.kt +++ b/app/src/main/java/helium314/keyboard/latin/utils/LayoutUtils.kt @@ -1,6 +1,8 @@ package helium314.keyboard.latin.utils import android.content.Context +import helium314.keyboard.keyboard.internal.keyboard_parser.floris.SimplePopups +import helium314.keyboard.keyboard.internal.keyboard_parser.getOrCreate import helium314.keyboard.latin.R import helium314.keyboard.latin.settings.Defaults.default import helium314.keyboard.latin.utils.LayoutType.Companion.folder @@ -15,7 +17,7 @@ object LayoutUtils { return context.assets.list(layoutType.folder)?.map { it.substringBefore(".") }.orEmpty() if (locale == null) return SubtypeSettings.getAllAvailableSubtypes() - .mapTo(HashSet()) { it.mainLayoutName()?.substringBefore("+") ?: "qwerty" } + .mapTo(HashSet()) { it.mainLayoutNameOrQwerty().substringBefore("+") } .apply { addAll(context.resources.getStringArray(R.array.predefined_layouts)) } val layouts = SubtypeSettings.getResourceSubtypesForLocale(locale).mapNotNullTo(mutableSetOf()) { it.mainLayoutName() } if (locale.script() == ScriptUtils.SCRIPT_LATIN) @@ -26,6 +28,7 @@ object LayoutUtils { fun getLMainLayoutsForLocales(locales: List, context: Context): Collection = locales.flatMapTo(HashSet()) { getAvailableLayouts(LayoutType.MAIN, context, it) }.sorted() + /** gets content for built-in (non-custom) layout [layoutName], with fallback to qwerty */ fun getContent(layoutType: LayoutType, layoutName: String, context: Context): String { val layouts = context.assets.list(layoutType.folder)!! layouts.firstOrNull { it.startsWith("$layoutName.") } @@ -33,4 +36,27 @@ object LayoutUtils { val fallback = layouts.first { it.startsWith(layoutType.default) } // must exist! return context.assets.open(layoutType.folder + File.separator + fallback).reader().readText() } + + fun getContentWithPlus(mainLayoutName: String, locale: Locale, context: Context): String { + val content = getContent(LayoutType.MAIN, mainLayoutName, context) + if (!mainLayoutName.endsWith("+")) + return content + // the stuff below will not work if we add "+" layouts in json format + // ideally we should serialize keyData to json to solve this + val rows = getSimpleRowStrings(content) + val localeKeyboardInfos = getOrCreate(context, locale) + return rows.mapIndexed { i, row -> + val extraKeys = localeKeyboardInfos.getExtraKeys(i + 1) ?: return@mapIndexed row + val rowList = row.split("\n").filterNot { it.isEmpty() }.toMutableList() + extraKeys.forEach { key -> + val popups = (key.popup as? SimplePopups)?.popupKeys?.joinToString(" ") + ?.takeIf { it.isNotEmpty() }?.let { " $it" } ?: "" + rowList.add(key.label + popups) + } + rowList.joinToString("\n") + }.joinToString("\n\n") + } + + fun getSimpleRowStrings(layoutContent: String): List = + layoutContent.replace("\r\n", "\n").split("\\n\\s*\\n".toRegex()).filter { it.isNotBlank() } } diff --git a/app/src/main/java/helium314/keyboard/latin/utils/LayoutUtilsCustom.kt b/app/src/main/java/helium314/keyboard/latin/utils/LayoutUtilsCustom.kt index bc40baed5..4f8686442 100644 --- a/app/src/main/java/helium314/keyboard/latin/utils/LayoutUtilsCustom.kt +++ b/app/src/main/java/helium314/keyboard/latin/utils/LayoutUtilsCustom.kt @@ -2,6 +2,7 @@ package helium314.keyboard.latin.utils import android.content.Context +import android.widget.Toast import helium314.keyboard.keyboard.Key import helium314.keyboard.keyboard.KeyboardId import helium314.keyboard.keyboard.KeyboardLayoutSet @@ -10,9 +11,14 @@ import helium314.keyboard.keyboard.internal.KeyboardParams import helium314.keyboard.keyboard.internal.keyboard_parser.LayoutParser import helium314.keyboard.keyboard.internal.keyboard_parser.POPUP_KEYS_NORMAL import helium314.keyboard.keyboard.internal.keyboard_parser.addLocaleKeyTextsToParams +import helium314.keyboard.latin.common.Constants.Separators +import helium314.keyboard.latin.common.Constants.Subtype.ExtraValue.KEYBOARD_LAYOUT_SET import helium314.keyboard.latin.common.decodeBase36 import helium314.keyboard.latin.common.encodeBase36 +import helium314.keyboard.latin.define.DebugFlags +import helium314.keyboard.latin.settings.Defaults import helium314.keyboard.latin.settings.Settings +import helium314.keyboard.latin.settings.SettingsSubtype.Companion.toSettingsSubtype import helium314.keyboard.latin.utils.LayoutType.Companion.folder import helium314.keyboard.latin.utils.ScriptUtils.script import kotlinx.serialization.SerializationException @@ -30,11 +36,13 @@ object LayoutUtilsCustom { params.mPopupKeyTypes.add(POPUP_KEYS_LAYOUT) addLocaleKeyTextsToParams(context, params, POPUP_KEYS_NORMAL) try { - val keys = LayoutParser.parseJsonString(layoutContent).map { row -> row.mapNotNull { it.compute(params)?.toKeyParams(params) } } - return checkKeys(keys) + if (layoutContent.trimStart().startsWith("[") || layoutContent.trimStart().startsWith("//")) { + val keys = LayoutParser.parseJsonString(layoutContent).map { row -> row.mapNotNull { it.compute(params)?.toKeyParams(params) } } + return checkKeys(keys) + } } catch (e: SerializationException) { Log.w(TAG, "json parsing error", e) - if (layoutContent.trimStart().startsWith("[") && layoutContent.trimEnd().endsWith("]") && layoutContent.contains("},")) + if (layoutContent.trimEnd().endsWith("]") && layoutContent.contains("},")) return false // we're sure enough it's a json } catch (e: Exception) { Log.w(TAG, "json layout parsed, but considered invalid", e) @@ -124,7 +132,6 @@ object LayoutUtilsCustom { layoutName } - /** @return layoutName for given [displayName]. If [layoutType ]is MAIN, non-null [locale] must be supplied */ fun getLayoutName(displayName: String, layoutType: LayoutType, locale: Locale? = null): String { if (layoutType != LayoutType.MAIN) @@ -143,6 +150,37 @@ object LayoutUtilsCustom { return file } + // remove layouts without a layout file from custom subtypes and settings + // should not be necessary, but better fall back to default instead of crashing when encountering a bug + fun removeMissingLayouts(context: Context) { + val prefs = context.prefs() + fun remove(type: LayoutType, name: String) { + val message = "removing custom layout ${getDisplayName(name)} / $name without file" + if (DebugFlags.DEBUG_ENABLED) + Toast.makeText(context, message, Toast.LENGTH_LONG).show() + Log.w(TAG, message) + SubtypeSettings.onRenameLayout(type, name, null, context) + } + LayoutType.entries.forEach { type -> + val name = Settings.readDefaultLayoutName(type, prefs) + if (!isCustomLayout(name) || getLayoutFiles(type, context).any { it.name.startsWith(name) }) + return@forEach + remove(type, name) + } + prefs.getString(Settings.PREF_ADDITIONAL_SUBTYPES, Defaults.PREF_ADDITIONAL_SUBTYPES)!! + .split(Separators.SETS).forEach outer@{ + val subtype = it.toSettingsSubtype() + LayoutType.getLayoutMap(subtype.getExtraValueOf(KEYBOARD_LAYOUT_SET) ?: "").forEach { (type, name) -> + if (!isCustomLayout(name) || getLayoutFiles(type, context).any { it.name.startsWith(name) }) + return@forEach + remove(type, name) + // recursive call: additional subtypes must have changed, so we repeat until nothing needs to be deleted + removeMissingLayouts(context) + return + } + } + } + // this goes into prefs and file names, so do not change! const val CUSTOM_LAYOUT_PREFIX = "custom." private const val TAG = "LayoutUtilsCustom" diff --git a/app/src/main/java/helium314/keyboard/latin/utils/PopupKeysUtils.kt b/app/src/main/java/helium314/keyboard/latin/utils/PopupKeysUtils.kt index 5d47d27b8..6bd810d05 100644 --- a/app/src/main/java/helium314/keyboard/latin/utils/PopupKeysUtils.kt +++ b/app/src/main/java/helium314/keyboard/latin/utils/PopupKeysUtils.kt @@ -72,10 +72,10 @@ fun getHintLabel(popupSet: PopupSet<*>?, params: KeyboardParams, label: String): } if (hintLabel != null) break } - if (hintLabel in toolbarKeyStrings.values) - hintLabel = null // better show nothing instead of the toolbar key label + if (hintLabel in toolbarKeyStrings.values || hintLabel.isNullOrEmpty()) + return null // better show nothing instead of the toolbar key label - return hintLabel?.let { KeySpecParser.getLabel(transformLabel(it, params)) } + return KeySpecParser.getLabel(transformLabel(hintLabel!!, params)) // avoid e.g. !autoColumnOrder! as label // this will avoid having labels on comma and period keys ?.takeIf { !it.startsWith("!") || it.count { it == '!' } != 2 } // excluding the special labels diff --git a/app/src/main/java/helium314/keyboard/latin/utils/ScriptUtils.kt b/app/src/main/java/helium314/keyboard/latin/utils/ScriptUtils.kt index df442089d..ba0fca550 100644 --- a/app/src/main/java/helium314/keyboard/latin/utils/ScriptUtils.kt +++ b/app/src/main/java/helium314/keyboard/latin/utils/ScriptUtils.kt @@ -162,13 +162,13 @@ object ScriptUtils { return SCRIPT_LATIN } return when (language) { - "ar", "ur", "fa" -> SCRIPT_ARABIC + "ar", "ckb", "ur", "fa" -> SCRIPT_ARABIC "hy" -> SCRIPT_ARMENIAN "bn" -> SCRIPT_BENGALI "sr", "mk", "ru", "uk", "mn", "be", "kk", "ky", "bg", "xdq", "cv", "mhr", "mns", "dru" -> SCRIPT_CYRILLIC "ka" -> SCRIPT_GEORGIAN "el" -> SCRIPT_GREEK - "iw" -> SCRIPT_HEBREW + "iw", "he" -> SCRIPT_HEBREW "km" -> SCRIPT_KHMER "lo" -> SCRIPT_LAO "ml" -> SCRIPT_MALAYALAM @@ -184,4 +184,12 @@ object ScriptUtils { else -> SCRIPT_LATIN // use as fallback } } + + @JvmStatic + fun isScriptRtl(script: String): Boolean { + return when (script) { + SCRIPT_ARABIC, SCRIPT_HEBREW -> true + else -> false + } + } } diff --git a/app/src/main/java/helium314/keyboard/latin/utils/SpacedTokens.kt b/app/src/main/java/helium314/keyboard/latin/utils/SpacedTokens.kt new file mode 100644 index 000000000..01f4c718b --- /dev/null +++ b/app/src/main/java/helium314/keyboard/latin/utils/SpacedTokens.kt @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: GPL-3.0-only + +package helium314.keyboard.latin.utils + +/** + * Tokenizes strings by groupings of non-space characters, making them iterable. Note that letters, + * punctuations, etc. are all treated the same by this construct. + */ +class SpacedTokens(phrase: String) : Iterable { + private val mPhrase = phrase + private val mLength = phrase.length + private val mStartPos = phrase.indexOfFirst { !Character.isWhitespace(it) } + // the iterator should start at the first non-whitespace character + + override fun iterator() = object : Iterator { + private var startPos = mStartPos + + override fun hasNext(): Boolean { + return startPos < mLength && startPos != -1 + } + + override fun next(): String { + var endPos = startPos + + do if (++endPos >= mLength) break + while (!Character.isWhitespace(mPhrase[endPos])) + val word = mPhrase.substring(startPos, endPos) + + if (endPos < mLength) { + do if (++endPos >= mLength) break + while (Character.isWhitespace(mPhrase[endPos])) + } + startPos = endPos + + return word + } + } +} diff --git a/app/src/main/java/helium314/keyboard/latin/utils/SubtypeLocaleUtils.java b/app/src/main/java/helium314/keyboard/latin/utils/SubtypeLocaleUtils.java deleted file mode 100644 index bb99355b6..000000000 --- a/app/src/main/java/helium314/keyboard/latin/utils/SubtypeLocaleUtils.java +++ /dev/null @@ -1,318 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * modified - * SPDX-License-Identifier: Apache-2.0 AND GPL-3.0-only - */ - -package helium314.keyboard.latin.utils; - -import android.content.Context; -import android.content.res.Resources; -import android.view.inputmethod.InputMethodSubtype; - -import helium314.keyboard.compat.ConfigurationCompatKt; -import helium314.keyboard.latin.R; -import helium314.keyboard.latin.common.Constants; -import helium314.keyboard.latin.common.LocaleUtils; -import helium314.keyboard.latin.common.StringUtils; - -import java.util.HashMap; -import java.util.Locale; - -import static helium314.keyboard.latin.common.Constants.Subtype.ExtraValue.COMBINING_RULES; -import static helium314.keyboard.latin.common.Constants.Subtype.ExtraValue.UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -/** - * A helper class to deal with subtype locales. - */ -// TODO: consolidate this into RichInputMethodSubtype -// todo (later): see whether this complicated mess can be simplified -public final class SubtypeLocaleUtils { - static final String TAG = SubtypeLocaleUtils.class.getSimpleName(); - - // This reference class {@link R} must be located in the same package as LatinIME.java. - // switched to context.getPackageName(), which works with changed debug package name - // any reason to prefer original version? -// private static final String RESOURCE_PACKAGE_NAME = R.class.getPackage().getName(); - - // Special language code to represent "no language". - public static final String NO_LANGUAGE = "zz"; - public static final String QWERTY = "qwerty"; - public static final String EMOJI = "emoji"; - public static final int UNKNOWN_KEYBOARD_LAYOUT = R.string.subtype_generic; - - private static volatile boolean sInitialized = false; - private static final Object sInitializeLock = new Object(); - private static Resources sResources; - // Keyboard layout to its display name map. - private static final HashMap sKeyboardLayoutToDisplayNameMap = new HashMap<>(); - // Keyboard layout to subtype name resource id map. - private static final HashMap sKeyboardLayoutToNameIdsMap = new HashMap<>(); - // Exceptional locale whose name should be displayed in Locale.ROOT. - private static final HashMap sExceptionalLocaleDisplayedInRootLocale = new HashMap<>(); - // Exceptional locale to subtype name resource id map. - private static final HashMap sExceptionalLocaleToNameIdsMap = new HashMap<>(); - // Exceptional locale to subtype name with layout resource id map. - private static final HashMap sExceptionalLocaleToWithLayoutNameIdsMap = new HashMap<>(); - private static final HashMap sResourceSubtypeDisplayNames = new HashMap<>(); - private static final String SUBTYPE_NAME_RESOURCE_PREFIX = "string/subtype_"; - private static final String SUBTYPE_NAME_RESOURCE_GENERIC_PREFIX = "string/subtype_generic_"; - private static final String SUBTYPE_NAME_RESOURCE_WITH_LAYOUT_PREFIX = "string/subtype_with_layout_"; - private static final String SUBTYPE_NAME_RESOURCE_NO_LANGUAGE_PREFIX = "string/subtype_no_language_"; - private static final String SUBTYPE_NAME_RESOURCE_IN_ROOT_LOCALE_PREFIX = "string/subtype_in_root_locale_"; - - private SubtypeLocaleUtils() { - // Intentional empty constructor for utility class. - } - - // Note that this initialization method can be called multiple times. - public static void init(final Context context) { - synchronized (sInitializeLock) { - if (!sInitialized) { - initLocked(context); - sInitialized = true; - } - } - } - - private static void initLocked(final Context context) { - final String RESOURCE_PACKAGE_NAME = context.getPackageName(); - final Resources res = context.getResources(); - sResources = res; - - final String[] predefinedLayoutSet = res.getStringArray(R.array.predefined_layouts); - final String[] layoutDisplayNames = res.getStringArray(R.array.predefined_layout_display_names); - for (int i = 0; i < predefinedLayoutSet.length; i++) { - final String layoutName = predefinedLayoutSet[i]; - sKeyboardLayoutToDisplayNameMap.put(layoutName, layoutDisplayNames[i]); - final String resourceName = SUBTYPE_NAME_RESOURCE_GENERIC_PREFIX + layoutName; - final int resId = res.getIdentifier(resourceName, null, RESOURCE_PACKAGE_NAME); - sKeyboardLayoutToNameIdsMap.put(layoutName, resId); - // Register subtype name resource id of "No language" with key "zz_" - final String noLanguageResName = SUBTYPE_NAME_RESOURCE_NO_LANGUAGE_PREFIX + layoutName; - final int noLanguageResId = res.getIdentifier(noLanguageResName, null, RESOURCE_PACKAGE_NAME); - final String key = getNoLanguageLayoutKey(layoutName); - sKeyboardLayoutToNameIdsMap.put(key, noLanguageResId); - } - - final String[] exceptionalLocaleInRootLocale = res.getStringArray(R.array.subtype_locale_displayed_in_root_locale); - for (final String languageTag : exceptionalLocaleInRootLocale) { - final String resourceName = SUBTYPE_NAME_RESOURCE_IN_ROOT_LOCALE_PREFIX + languageTag.replace('-', '_'); - final int resId = res.getIdentifier(resourceName, null, RESOURCE_PACKAGE_NAME); - sExceptionalLocaleDisplayedInRootLocale.put(languageTag, resId); - } - - final String[] exceptionalLocales = res.getStringArray(R.array.subtype_locale_exception_keys); - for (final String languageTag : exceptionalLocales) { - final String resourceName = SUBTYPE_NAME_RESOURCE_PREFIX + languageTag.replace('-', '_'); - final int resId = res.getIdentifier(resourceName, null, RESOURCE_PACKAGE_NAME); - sExceptionalLocaleToNameIdsMap.put(languageTag, resId); - final String resourceNameWithLayout = SUBTYPE_NAME_RESOURCE_WITH_LAYOUT_PREFIX + languageTag.replace('-', '_'); - final int resIdWithLayout = res.getIdentifier(resourceNameWithLayout, null, RESOURCE_PACKAGE_NAME); - sExceptionalLocaleToWithLayoutNameIdsMap.put(languageTag, resIdWithLayout); - } - } - - public static boolean isExceptionalLocale(final Locale locale) { - return sExceptionalLocaleToNameIdsMap.containsKey(locale.toLanguageTag()); - } - - private static String getNoLanguageLayoutKey(final String keyboardLayoutName) { - return NO_LANGUAGE + "_" + keyboardLayoutName; - } - - public static int getSubtypeNameResId(final Locale locale, final String keyboardLayoutName) { - final String languageTag = locale.toLanguageTag(); - if (isExceptionalLocale(locale)) { - return sExceptionalLocaleToWithLayoutNameIdsMap.get(languageTag); - } - final String key = NO_LANGUAGE.equals(languageTag) - ? getNoLanguageLayoutKey(keyboardLayoutName) - : keyboardLayoutName; - final Integer nameId = sKeyboardLayoutToNameIdsMap.get(key); - return nameId == null ? UNKNOWN_KEYBOARD_LAYOUT : nameId; - } - - @NonNull - public static Locale getDisplayLocaleOfSubtypeLocale(@NonNull final Locale locale) { - final String languageTag = locale.toLanguageTag(); - if (NO_LANGUAGE.equals(languageTag)) { - return ConfigurationCompatKt.locale(sResources.getConfiguration()); - } - if (sExceptionalLocaleDisplayedInRootLocale.containsKey(languageTag)) { - return Locale.ROOT; - } - return locale; - } - - public static String getSubtypeLocaleDisplayNameInSystemLocale(@NonNull final Locale locale) { - final Locale displayLocale = ConfigurationCompatKt.locale(sResources.getConfiguration()); - return getSubtypeLocaleDisplayNameInternal(locale, displayLocale); - } - - @NonNull - public static String getSubtypeLocaleDisplayName(@NonNull final Locale locale) { - final Locale displayLocale = getDisplayLocaleOfSubtypeLocale(locale); - return getSubtypeLocaleDisplayNameInternal(locale, displayLocale); - } - - @NonNull - public static String getSubtypeLanguageDisplayName(@NonNull final Locale locale) { - final Locale displayLocale = getDisplayLocaleOfSubtypeLocale(locale); - final Locale languageLocale; - if (sExceptionalLocaleDisplayedInRootLocale.containsKey(locale.toLanguageTag())) { - languageLocale = locale; - } else { - languageLocale = LocaleUtils.constructLocale(locale.getLanguage()); - } - return getSubtypeLocaleDisplayNameInternal(languageLocale, displayLocale); - } - - @NonNull - private static String getSubtypeLocaleDisplayNameInternal(@NonNull final Locale locale, - @NonNull final Locale displayLocale) { - final String languageTag = locale.toLanguageTag(); - if (NO_LANGUAGE.equals(locale.toLanguageTag())) { - // No language subtype should be displayed in system locale. - return sResources.getString(R.string.subtype_no_language); - } - final Integer exceptionalNameResId; - if (displayLocale.equals(Locale.ROOT) - && sExceptionalLocaleDisplayedInRootLocale.containsKey(languageTag)) { - exceptionalNameResId = sExceptionalLocaleDisplayedInRootLocale.get(languageTag); - } else if (sExceptionalLocaleToNameIdsMap.containsKey(languageTag)) { - exceptionalNameResId = sExceptionalLocaleToNameIdsMap.get(languageTag); - } else { - exceptionalNameResId = null; - } - - final String displayName; - if (exceptionalNameResId != null) { - displayName = RunInLocaleKt.runInLocale(sResources, displayLocale, res -> res.getString(exceptionalNameResId)); - } else { - displayName = LocaleUtils.getLocaleDisplayNameInLocale(locale, sResources, displayLocale); - } - return StringUtils.capitalizeFirstCodePoint(displayName, displayLocale); - } - - // InputMethodSubtype's display name in its locale. - // isAdditionalSubtype (T=true, F=false) - // locale layout | display name - // ------ ------- - ---------------------- - // en_US qwerty F English (US) exception - // en_GB qwerty F English (UK) exception - // es_US spanish F Español (EE.UU.) exception - // fr azerty F Français - // fr_CA qwerty F Français (Canada) - // fr_CH swiss F Français (Suisse) - // de qwertz F Deutsch - // de_CH swiss T Deutsch (Schweiz) - // zz qwerty F Alphabet (QWERTY) in system locale - // fr qwertz T Français (QWERTZ) - // de qwerty T Deutsch (QWERTY) - // en_US azerty T English (US) (AZERTY) exception - // zz azerty T Alphabet (AZERTY) in system locale - - @NonNull - private static String getReplacementString(@NonNull final InputMethodSubtype subtype, - @NonNull final Locale displayLocale) { - if (subtype.containsExtraValueKey(UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME)) { - return subtype.getExtraValueOf(UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME); - } - return getSubtypeLocaleDisplayNameInternal(SubtypeUtilsKt.locale(subtype), displayLocale); - } - - @NonNull - public static String getDisplayNameInSystemLocale(@NonNull final String mainLayoutName, @NonNull final Locale locale) { - final String displayName = getMainLayoutDisplayName(mainLayoutName); - if (displayName != null) // works for custom and latin layouts - return displayName; - // we have some locale-specific layout - for (InputMethodSubtype subtype : SubtypeSettings.INSTANCE.getResourceSubtypesForLocale(locale)) { - final String main = LayoutType.Companion.getMainLayoutFromExtraValue(subtype.getExtraValue()); - if (mainLayoutName.equals(main)) - return getSubtypeDisplayNameInSystemLocale(subtype); - } - return mainLayoutName; // should never happen... - } - - @NonNull - public static String getSubtypeDisplayNameInSystemLocale(@NonNull final InputMethodSubtype subtype) { - final String cached = sResourceSubtypeDisplayNames.get(subtype.hashCode()); - if (cached != null) return cached; - - final Locale displayLocale = ConfigurationCompatKt.locale(sResources.getConfiguration()); - final String displayName = getSubtypeDisplayNameInternal(subtype, displayLocale); - - if (!subtype.containsExtraValueKey(Constants.Subtype.ExtraValue.IS_ADDITIONAL_SUBTYPE)) { - sResourceSubtypeDisplayNames.put(subtype.hashCode(), displayName); - } - return displayName; - } - - public static void clearDisplayNameCache() { - sResourceSubtypeDisplayNames.clear(); - } - - @NonNull - public static String getSubtypeNameForLogging(@Nullable final InputMethodSubtype subtype) { - if (subtype == null) { - return ""; - } - return SubtypeUtilsKt.locale(subtype) + "/" + getMainLayoutName(subtype); - } - - @NonNull - private static String getSubtypeDisplayNameInternal(@NonNull final InputMethodSubtype subtype, - @NonNull final Locale displayLocale) { - final String replacementString = getReplacementString(subtype, displayLocale); - final int nameResId = subtype.getNameResId(); - return RunInLocaleKt.runInLocale(sResources, displayLocale, - res -> { - try { - return StringUtils.capitalizeFirstCodePoint(res.getString(nameResId, replacementString), displayLocale); - } catch (Resources.NotFoundException e) { - Log.w(TAG, "Unknown subtype: mode=" + subtype.getMode() - + " nameResId=" + subtype.getNameResId() - + " locale=" + subtype.getLocale() - + " extra=" + subtype.getExtraValue() - + "\n" + DebugLogUtils.getStackTrace()); - return ""; - } - }); - } - - @Nullable - public static String getMainLayoutDisplayName(@NonNull final InputMethodSubtype subtype) { - final String layoutName = getMainLayoutName(subtype); - return getMainLayoutDisplayName(layoutName); - } - - @Nullable - public static String getMainLayoutDisplayName(@NonNull final String layoutName) { - if (LayoutUtilsCustom.INSTANCE.isCustomLayout(layoutName)) - return LayoutUtilsCustom.INSTANCE.getDisplayName(layoutName); - return sKeyboardLayoutToDisplayNameMap.get(layoutName); - } - - @NonNull - public static String getMainLayoutName(final InputMethodSubtype subtype) { - String mainLayoutName = SubtypeUtilsKt.mainLayoutName(subtype); - if (mainLayoutName == null && subtype.isAsciiCapable()) { - mainLayoutName = QWERTY; - } - if (mainLayoutName == null) { // we could search for a subtype with the correct script, but this is a bug anyway... - Log.w(TAG, "KeyboardLayoutSet not found, use QWERTY: " + - "locale=" + subtype.getLocale() + " extraValue=" + subtype.getExtraValue()); - return QWERTY; - } - return mainLayoutName; - } - - public static String getCombiningRulesExtraValue(final InputMethodSubtype subtype) { - return subtype.getExtraValueOf(COMBINING_RULES); - } -} diff --git a/app/src/main/java/helium314/keyboard/latin/utils/SubtypeLocaleUtils.kt b/app/src/main/java/helium314/keyboard/latin/utils/SubtypeLocaleUtils.kt new file mode 100644 index 000000000..0861bf952 --- /dev/null +++ b/app/src/main/java/helium314/keyboard/latin/utils/SubtypeLocaleUtils.kt @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * modified + * SPDX-License-Identifier: Apache-2.0 AND GPL-3.0-only + */ +package helium314.keyboard.latin.utils + +import android.content.Context +import android.content.res.Resources +import android.view.inputmethod.InputMethodSubtype +import helium314.keyboard.compat.locale +import helium314.keyboard.latin.R +import helium314.keyboard.latin.common.Constants.Subtype.ExtraValue +import helium314.keyboard.latin.common.LocaleUtils.constructLocale +import helium314.keyboard.latin.common.LocaleUtils.localizedDisplayName +import helium314.keyboard.latin.common.StringUtils +import helium314.keyboard.latin.utils.LayoutType.Companion.getMainLayoutFromExtraValue +import java.util.Locale +import kotlin.concurrent.Volatile + +/** + * A helper class to deal with subtype locales. + */ +object SubtypeLocaleUtils { + @Volatile + private var initialized = false + private lateinit var resources: Resources + + // Keyboard layout to its display name map. + private val keyboardLayoutToDisplayName = HashMap() + + // Exceptional locale whose name should be displayed in Locale.ROOT. + private val exceptionalLocaleDisplayedInRootLocale = HashMap() + + private val resourceSubtypeDisplayNameCache = HashMap() + + // Note that this initialization method can be called multiple times. + @JvmStatic + fun init(context: Context) { + synchronized(this) { + if (!initialized) { + initLocked(context) + initialized = true + } + } + } + + private fun initLocked(context: Context) { + resources = context.resources + + // todo: layout names are currently translatable in subtype_no_language_* but not the default names + // just remove the separate "alphabet ()" strings and have a single "alphabet (%s)"? + // or rather use the same style as for languages and only have "alphabet" + val predefinedLayouts = resources.getStringArray(R.array.predefined_layouts) + val layoutDisplayNames = resources.getStringArray(R.array.predefined_layout_display_names) + for (i in predefinedLayouts.indices) { + val layoutName = predefinedLayouts[i] + keyboardLayoutToDisplayName[layoutName] = layoutDisplayNames[i] + } + + val exceptionalLocaleInRootLocale = resources.getStringArray(R.array.subtype_locale_displayed_in_root_locale) + val exceptionalLocaleInRootLocaleDisplayNames = resources.getStringArray(R.array.subtype_locale_displayed_in_root_locale_display_names) + for (i in exceptionalLocaleInRootLocale.indices) { + exceptionalLocaleDisplayedInRootLocale[exceptionalLocaleInRootLocale[i]] = exceptionalLocaleInRootLocaleDisplayNames[i] + } + } + + // see SubtypeUtilsAdditional.getAdditionalExtraValues, currently not needed + //fun isExceptionalLocale(locale: Locale) = exceptionalLocaleDisplayedInRootLocale.containsKey(locale.toLanguageTag()) + + /** Usually the [locale], but Locale.ROOT for exceptionalLocaleDisplayedInRootLocale, and system locale for NO_LANGUAGE */ + private fun getDisplayLocaleOfSubtypeLocale(locale: Locale): Locale { + val languageTag = locale.toLanguageTag() + if (languageTag == NO_LANGUAGE) + return resources.configuration.locale() + if (exceptionalLocaleDisplayedInRootLocale.containsKey(languageTag)) + return Locale.ROOT + return locale + } + + /** Returns the full locale display name for use on space bar (considers exceptionalLocaleDisplayedInRootLocale) */ + fun getSubtypeLocaleDisplayName(locale: Locale): String { + val displayLocale = getDisplayLocaleOfSubtypeLocale(locale) + return getSubtypeLocaleDisplayNameInternal(locale, displayLocale) + } + + /** Returns the language display name for use on space bar (considers exceptionalLocaleDisplayedInRootLocale) */ + fun getSubtypeLanguageDisplayName(locale: Locale): String { + val languageLocale = if (exceptionalLocaleDisplayedInRootLocale.containsKey(locale.toLanguageTag())) + locale + else + locale.language.constructLocale() + return getSubtypeLocaleDisplayNameInternal(languageLocale, getDisplayLocaleOfSubtypeLocale(locale)) + } + + /** + * Display name of subtype [locale] in [displayLocale]. + * Considers exceptionalLocaleDisplayedInRootLocale and exceptionalLocaleToNameIds, defaults to Locale.localizedDisplayName. + */ + private fun getSubtypeLocaleDisplayNameInternal(locale: Locale, displayLocale: Locale): String { + val languageTag = locale.toLanguageTag() + if (languageTag == NO_LANGUAGE) { + // "No language" subtype should be displayed in system locale. + return resources.getString(R.string.subtype_no_language) + } + val displayName = if (displayLocale == Locale.ROOT && exceptionalLocaleDisplayedInRootLocale.containsKey(languageTag)) { + exceptionalLocaleDisplayedInRootLocale[languageTag]!! + } else { + locale.localizedDisplayName(resources, displayLocale) + } + return StringUtils.capitalizeFirstCodePoint(displayName, displayLocale) + } + + @JvmStatic + fun clearSubtypeDisplayNameCache() { + resourceSubtypeDisplayNameCache.clear() + } + + @JvmStatic + fun getSubtypeNameForLogging(subtype: InputMethodSubtype?): String { + if (subtype == null) { + return "" + } + return subtype.locale().toString() + "/" + subtype.mainLayoutNameOrQwerty() + } + + /** + * Subtype display name is when using the default layout, or () otherwise + * [displayLocale] defaults to system locale + */ + fun InputMethodSubtype.displayName(displayLocale: Locale? = null): String { + if (displayLocale == null) resourceSubtypeDisplayNameCache[hashCode()]?.let { return it } + + val layoutName = mainLayoutName() + if (layoutName != null && LayoutUtilsCustom.isCustomLayout(layoutName)) { + return resources.getString( + R.string.subtype_with_layout_generic, + locale().localizedDisplayName(resources, displayLocale), + LayoutUtilsCustom.getDisplayName(layoutName) + ) + } + // if it's a default layout, we want to use the nameResId instead of explicitly showing the layout name + if (keyboardLayoutToDisplayName.containsKey(layoutName) + && SubtypeSettings.getResourceSubtypesForLocale(locale()).none { it.mainLayoutName() == layoutName }) { + return resources.getString( + R.string.subtype_with_layout_generic, + locale().localizedDisplayName(resources, displayLocale), + keyboardLayoutToDisplayName[layoutName] + ) + } + + val actualDisplayLocale = displayLocale ?: resources.configuration.locale() + // replacement for %s in nameResId, which now always is the locale + // not read from ExtraValue.UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME any more + val replacementString = getSubtypeLocaleDisplayNameInternal(locale(), actualDisplayLocale) + + val name = runCatching { + if (displayLocale == null) resources.getString(nameResId, replacementString) + else runInLocale(resources, displayLocale) { resources.getString(nameResId, replacementString) } + }.getOrNull() ?: locale().localizedDisplayName(resources, displayLocale) + val displayName = StringUtils.capitalizeFirstCodePoint(name, actualDisplayLocale) + if (displayLocale == null && !containsExtraValueKey(ExtraValue.IS_ADDITIONAL_SUBTYPE)) + resourceSubtypeDisplayNameCache[hashCode()] = displayName + return displayName + } + + fun getMainLayoutDisplayName(layoutName: String): String? = + if (LayoutUtilsCustom.isCustomLayout(layoutName)) LayoutUtilsCustom.getDisplayName(layoutName) + else keyboardLayoutToDisplayName[layoutName] + + fun getLayoutDisplayNameInSystemLocale(mainLayoutName: String, locale: Locale): String { + getMainLayoutDisplayName(mainLayoutName)?.let { return it } // works for custom and latin layouts + + // we have some locale-specific layout, use the subtype name + for (subtype in SubtypeSettings.getResourceSubtypesForLocale(locale)) { + if (mainLayoutName == getMainLayoutFromExtraValue(subtype.extraValue)) + return subtype.displayName() + } + return mainLayoutName // should never happen... + } + + @JvmStatic + fun getCombiningRulesExtraValue(subtype: InputMethodSubtype): String? = subtype.getExtraValueOf(ExtraValue.COMBINING_RULES) + + // Special language code to represent "no language". + const val NO_LANGUAGE = "zz" + const val QWERTY = "qwerty" + const val EMOJI = "emoji" + val UNKNOWN_KEYBOARD_LAYOUT = R.string.subtype_generic +} diff --git a/app/src/main/java/helium314/keyboard/latin/utils/SubtypeSettings.kt b/app/src/main/java/helium314/keyboard/latin/utils/SubtypeSettings.kt index 18739953b..69db1b4a4 100644 --- a/app/src/main/java/helium314/keyboard/latin/utils/SubtypeSettings.kt +++ b/app/src/main/java/helium314/keyboard/latin/utils/SubtypeSettings.kt @@ -52,9 +52,8 @@ object SubtypeSettings { fun addEnabledSubtype(prefs: SharedPreferences, newSubtype: InputMethodSubtype) { val subtype = newSubtype.toSettingsSubtype() - val subtypes = prefs.getString(Settings.PREF_ENABLED_SUBTYPES, Defaults.PREF_ENABLED_SUBTYPES)!! - .split(Separators.SETS).filter { it.isNotBlank() }.map { it.toSettingsSubtype() } + subtype - val newString = subtypes.map { it.toPref() }.toSortedSet().joinToString(Separators.SETS) + val subtypes = createSettingsSubtypes(prefs.getString(Settings.PREF_ENABLED_SUBTYPES, Defaults.PREF_ENABLED_SUBTYPES)!!) + subtype + val newString = createPrefSubtypes(subtypes) prefs.edit { putString(Settings.PREF_ENABLED_SUBTYPES, newString) } if (newSubtype !in enabledSubtypes) { @@ -74,10 +73,8 @@ object SubtypeSettings { fun getSelectedSubtype(prefs: SharedPreferences): InputMethodSubtype { val selectedSubtype = prefs.getString(Settings.PREF_SELECTED_SUBTYPE, Defaults.PREF_SELECTED_SUBTYPE)!!.toSettingsSubtype() - if (selectedSubtype.isAdditionalSubtype(prefs)) { - val selectedAdditionalSubtype = selectedSubtype.toAdditionalSubtype() - if (selectedAdditionalSubtype != null) return selectedAdditionalSubtype - } + if (selectedSubtype.isAdditionalSubtype(prefs)) + return selectedSubtype.toAdditionalSubtype() // no additional subtype, must be a resource subtype val subtype = enabledSubtypes.firstOrNull { it.toSettingsSubtype() == selectedSubtype } @@ -127,23 +124,39 @@ object SubtypeSettings { fun getAvailableSubtypeLocales(): List = resourceSubtypesByLocale.keys.toList() + /** + * Update subtypes that contain the layout. If new name is null (layout deleted) and the + * subtype is now identical to a resource subtype, remove the subtype from additional subtypes. + */ fun onRenameLayout(type: LayoutType, from: String, to: String?, context: Context) { val prefs = context.prefs() + val editor = prefs.edit() // calling apply for each separate setting would result in an invalid intermediate state listOf( Settings.PREF_ADDITIONAL_SUBTYPES to Defaults.PREF_ADDITIONAL_SUBTYPES, Settings.PREF_ENABLED_SUBTYPES to Defaults.PREF_ENABLED_SUBTYPES, Settings.PREF_SELECTED_SUBTYPE to Defaults.PREF_SELECTED_SUBTYPE ).forEach { (key, default) -> - val new = prefs.getString(key, default)!!.split(Separators.SETS).mapTo(mutableSetOf()) { + val new = prefs.getString(key, default)!!.split(Separators.SETS).mapNotNullTo(mutableSetOf()) { + if (it.isEmpty()) return@mapNotNullTo null val subtype = it.toSettingsSubtype() if (subtype.layoutName(type) == from) { - if (to == null) subtype.withoutLayout(type).toPref() + if (to == null) { + val defaultLayout = if (type !== LayoutType.MAIN) null + // if we just delete a main layout, we may end up with something like Hindi (QWERTY) + // so better replace it with a default layout for that locale + else resourceSubtypesByLocale[subtype.locale]?.first()?.mainLayoutName() + val newSubtype = if (defaultLayout == null) subtype.withoutLayout(type) + else subtype.withLayout(type, defaultLayout) + if (newSubtype.isSameAsDefault() && key == Settings.PREF_ADDITIONAL_SUBTYPES) null + else newSubtype.toPref() + } else subtype.withLayout(type, to).toPref() } else subtype.toPref() }.joinToString(Separators.SETS) - prefs.edit().putString(key, new).apply() + editor.putString(key, new) } + editor.apply() if (Settings.readDefaultLayoutName(type, prefs) == from) Settings.writeDefaultLayoutName(to, type, prefs) reloadEnabledSubtypes(context) @@ -151,12 +164,21 @@ object SubtypeSettings { fun reloadEnabledSubtypes(context: Context) { enabledSubtypes.clear() - removeInvalidCustomSubtypes(context) loadAdditionalSubtypes(context.prefs()) loadEnabledSubtypes(context) - RichInputMethodManager.getInstance().refreshSubtypeCaches() + if (RichInputMethodManager.isInitialized()) + RichInputMethodManager.getInstance().refreshSubtypeCaches() } + fun createSettingsSubtypes(prefSubtypes: String): List = + prefSubtypes.split(Separators.SETS).mapNotNull { + if (it.isEmpty()) null + else it.toSettingsSubtype() + } + + fun createPrefSubtypes(subtypes: Collection): String = + subtypes.map { it.toPref() }.toSortedSet().joinToString(Separators.SETS) + fun init(context: Context) { SubtypeLocaleUtils.init(context) // necessary to get the correct getKeyboardLayoutSetName @@ -165,7 +187,6 @@ object SubtypeSettings { reloadSystemLocales(context) loadResourceSubtypes(context.resources) - removeInvalidCustomSubtypes(context) loadAdditionalSubtypes(context.prefs()) loadEnabledSubtypes(context) } @@ -193,23 +214,6 @@ object SubtypeSettings { } } - // remove custom subtypes without a layout file - private fun removeInvalidCustomSubtypes(context: Context) { - val prefs = context.prefs() - val additionalSubtypes = prefs.getString(Settings.PREF_ADDITIONAL_SUBTYPES, Defaults.PREF_ADDITIONAL_SUBTYPES)!!.split(Separators.SETS) - val customLayoutFiles by lazy { LayoutUtilsCustom.getLayoutFiles(LayoutType.MAIN, context).map { it.name } } - val subtypesToRemove = mutableListOf() - additionalSubtypes.forEach { - val name = it.toSettingsSubtype().mainLayoutName() ?: SubtypeLocaleUtils.QWERTY - if (!LayoutUtilsCustom.isCustomLayout(name)) return@forEach - if (name !in customLayoutFiles) - subtypesToRemove.add(it) - } - if (subtypesToRemove.isEmpty()) return - Log.w(TAG, "removing custom subtypes without main layout files: $subtypesToRemove") - Settings.writePrefAdditionalSubtypes(prefs, additionalSubtypes.filterNot { it in subtypesToRemove }.joinToString(Separators.SETS)) - } - private fun loadAdditionalSubtypes(prefs: SharedPreferences) { additionalSubtypes.clear() val additionalSubtypeString = prefs.getString(Settings.PREF_ADDITIONAL_SUBTYPES, Defaults.PREF_ADDITIONAL_SUBTYPES)!! @@ -220,15 +224,11 @@ object SubtypeSettings { // requires loadResourceSubtypes to be called before private fun loadEnabledSubtypes(context: Context) { val prefs = context.prefs() - val settingsSubtypes = prefs.getString(Settings.PREF_ENABLED_SUBTYPES, Defaults.PREF_ENABLED_SUBTYPES)!! - .split(Separators.SETS).filter { it.isNotEmpty() }.map { it.toSettingsSubtype() } + val settingsSubtypes = createSettingsSubtypes(prefs.getString(Settings.PREF_ENABLED_SUBTYPES, Defaults.PREF_ENABLED_SUBTYPES)!!) for (settingsSubtype in settingsSubtypes) { if (settingsSubtype.isAdditionalSubtype(prefs)) { - val additionalSubtype = settingsSubtype.toAdditionalSubtype() - if (additionalSubtype != null) { - enabledSubtypes.add(additionalSubtype) - continue - } + enabledSubtypes.add(settingsSubtype.toAdditionalSubtype()) + continue } val subtypesForLocale = resourceSubtypesByLocale[settingsSubtype.locale] if (subtypesForLocale == null) { @@ -241,7 +241,7 @@ object SubtypeSettings { continue } - val subtype = subtypesForLocale.firstOrNull { SubtypeLocaleUtils.getMainLayoutName(it) == (settingsSubtype.mainLayoutName() ?: SubtypeLocaleUtils.QWERTY) } + val subtype = subtypesForLocale.firstOrNull { it.mainLayoutNameOrQwerty() == (settingsSubtype.mainLayoutName() ?: SubtypeLocaleUtils.QWERTY) } if (subtype == null) { val message = "subtype $settingsSubtype could not be loaded" Log.w(TAG, message) @@ -258,12 +258,11 @@ object SubtypeSettings { /** @return whether pref was changed */ private fun removeEnabledSubtype(prefs: SharedPreferences, subtype: SettingsSubtype): Boolean { - val oldSubtypes = prefs.getString(Settings.PREF_ENABLED_SUBTYPES, Defaults.PREF_ENABLED_SUBTYPES)!! - .split(Separators.SETS).filter { it.isNotEmpty() }.map { it.toSettingsSubtype() } + val oldSubtypes = createSettingsSubtypes(prefs.getString(Settings.PREF_ENABLED_SUBTYPES, Defaults.PREF_ENABLED_SUBTYPES)!!) val newSubtypes = oldSubtypes - subtype if (oldSubtypes == newSubtypes) return false // already removed - prefs.edit { putString(Settings.PREF_ENABLED_SUBTYPES, newSubtypes.joinToString(Separators.SETS) { it.toPref() }) } + prefs.edit { putString(Settings.PREF_ENABLED_SUBTYPES, createPrefSubtypes(newSubtypes)) } if (subtype == prefs.getString(Settings.PREF_SELECTED_SUBTYPE, Defaults.PREF_SELECTED_SUBTYPE)!!.toSettingsSubtype()) { // switch subtype if the currently used one has been disabled try { diff --git a/app/src/main/java/helium314/keyboard/latin/utils/SubtypeUtils.kt b/app/src/main/java/helium314/keyboard/latin/utils/SubtypeUtils.kt index a210174ac..1b69075c3 100644 --- a/app/src/main/java/helium314/keyboard/latin/utils/SubtypeUtils.kt +++ b/app/src/main/java/helium314/keyboard/latin/utils/SubtypeUtils.kt @@ -1,6 +1,5 @@ package helium314.keyboard.latin.utils -import android.content.Context import android.content.SharedPreferences import android.content.res.Resources import android.os.Build @@ -10,7 +9,6 @@ import helium314.keyboard.latin.common.Constants.Separators import helium314.keyboard.latin.common.Constants.Subtype.ExtraValue import helium314.keyboard.latin.common.Constants.Subtype.ExtraValue.KEYBOARD_LAYOUT_SET import helium314.keyboard.latin.common.LocaleUtils.constructLocale -import helium314.keyboard.latin.common.LocaleUtils.localizedDisplayName import helium314.keyboard.latin.settings.Defaults import helium314.keyboard.latin.settings.Settings import helium314.keyboard.latin.settings.SettingsSubtype.Companion.getExtraValueOf @@ -30,6 +28,8 @@ fun InputMethodSubtype.mainLayoutName(): String? { return map[LayoutType.MAIN] } +fun InputMethodSubtype.mainLayoutNameOrQwerty(): String = mainLayoutName() ?: SubtypeLocaleUtils.QWERTY + fun getResourceSubtypes(resources: Resources): List { val subtypes = mutableListOf() val xml = resources.getXml(R.xml.method) @@ -64,15 +64,6 @@ fun getResourceSubtypes(resources: Resources): List { return subtypes } -/** Workaround for SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale ignoring custom layout names */ -// todo (later): this should be done properly and in SubtypeLocaleUtils -fun InputMethodSubtype.displayName(context: Context): String { - val layoutName = SubtypeLocaleUtils.getMainLayoutName(this) - if (LayoutUtilsCustom.isCustomLayout(layoutName)) - return "${locale().localizedDisplayName(context)} (${LayoutUtilsCustom.getDisplayName(layoutName)})" - return SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(this) -} - fun getHasLocalizedNumberRow(subtype: InputMethodSubtype, prefs: SharedPreferences): Boolean = subtype.getExtraValueOf(ExtraValue.LOCALIZED_NUMBER_ROW)?.toBoolean() ?: prefs.getBoolean(Settings.PREF_LOCALIZED_NUMBER_ROW, Defaults.PREF_LOCALIZED_NUMBER_ROW) diff --git a/app/src/main/java/helium314/keyboard/latin/utils/SubtypeUtilsAdditional.kt b/app/src/main/java/helium314/keyboard/latin/utils/SubtypeUtilsAdditional.kt index 048a7410b..a2d839266 100644 --- a/app/src/main/java/helium314/keyboard/latin/utils/SubtypeUtilsAdditional.kt +++ b/app/src/main/java/helium314/keyboard/latin/utils/SubtypeUtilsAdditional.kt @@ -9,9 +9,13 @@ import helium314.keyboard.latin.common.Constants import helium314.keyboard.latin.common.Constants.Separators import helium314.keyboard.latin.common.Constants.Subtype.ExtraValue import helium314.keyboard.latin.settings.Defaults +import helium314.keyboard.latin.settings.Defaults.default import helium314.keyboard.latin.settings.Settings import helium314.keyboard.latin.settings.SettingsSubtype import helium314.keyboard.latin.settings.SettingsSubtype.Companion.toSettingsSubtype +import helium314.keyboard.latin.utils.LayoutType.Companion.toExtraValue +import helium314.keyboard.latin.utils.ScriptUtils.script +import java.util.EnumMap import java.util.Locale object SubtypeUtilsAdditional { @@ -46,17 +50,27 @@ object SubtypeUtilsAdditional { fun createDummyAdditionalSubtype(locale: Locale, mainLayoutName: String) = createAdditionalSubtype(locale, "${ExtraValue.KEYBOARD_LAYOUT_SET}=MAIN${Separators.KV}$mainLayoutName", false, false) + // only used in tests fun createEmojiCapableAdditionalSubtype(locale: Locale, mainLayoutName: String, asciiCapable: Boolean) = createAdditionalSubtype(locale, "${ExtraValue.KEYBOARD_LAYOUT_SET}=MAIN${Separators.KV}$mainLayoutName", asciiCapable, true) + /** creates a subtype with every layout being the default for its type */ + fun createDefaultSubtype(locale: Locale): InputMethodSubtype { + val layouts = LayoutType.entries.associateWithTo(LayoutType.getLayoutMap(null)) { it.default } + SubtypeSettings.getResourceSubtypesForLocale(locale).firstOrNull()?.mainLayoutName()?.let { layouts[LayoutType.MAIN] = it } + val extra = ExtraValue.KEYBOARD_LAYOUT_SET + "=" + layouts.toExtraValue() + return createAdditionalSubtype(locale, extra, locale.script() == ScriptUtils.SCRIPT_LATIN, true) + } + fun removeAdditionalSubtype(context: Context, subtype: InputMethodSubtype) { val prefs = context.prefs() SubtypeSettings.removeEnabledSubtype(context, subtype) val oldAdditionalSubtypesString = prefs.getString(Settings.PREF_ADDITIONAL_SUBTYPES, Defaults.PREF_ADDITIONAL_SUBTYPES)!! - val oldAdditionalSubtypes = createAdditionalSubtypes(oldAdditionalSubtypesString) - val newAdditionalSubtypes = oldAdditionalSubtypes.filter { it != subtype } - val newAdditionalSubtypesString = createPrefSubtypes(newAdditionalSubtypes) - Settings.writePrefAdditionalSubtypes(prefs, newAdditionalSubtypesString) + val oldAdditionalSubtypes = SubtypeSettings.createSettingsSubtypes(oldAdditionalSubtypesString) + val settingsSubtype = subtype.toSettingsSubtype() + val newAdditionalSubtypes = oldAdditionalSubtypes.filter { it != settingsSubtype } + val newAdditionalSubtypesString = SubtypeSettings.createPrefSubtypes(newAdditionalSubtypes) + prefs.edit().putString(Settings.PREF_ADDITIONAL_SUBTYPES, newAdditionalSubtypesString).apply() } // updates additional subtypes, enabled subtypes, and selected subtype @@ -66,38 +80,39 @@ object SubtypeUtilsAdditional { val isSelected = prefs.getString(Settings.PREF_SELECTED_SUBTYPE, Defaults.PREF_SELECTED_SUBTYPE)!!.toSettingsSubtype() == from val isEnabled = prefs.getString(Settings.PREF_ENABLED_SUBTYPES, Defaults.PREF_ENABLED_SUBTYPES)!!.split(Separators.SETS) .any { it.toSettingsSubtype() == from } - val new = prefs.getString(Settings.PREF_ADDITIONAL_SUBTYPES, Defaults.PREF_ADDITIONAL_SUBTYPES)!! - .split(Separators.SETS).mapNotNullTo(sortedSetOf()) { - if (it == from.toPref()) null else it - } + to.toPref() - prefs.edit().putString(Settings.PREF_ADDITIONAL_SUBTYPES, new.joinToString(Separators.SETS)).apply() - - val fromSubtype = from.toAdditionalSubtype() // will be null if we edit a resource subtype - val toSubtype = to.toAdditionalSubtype() // should never be null - if (isSelected && toSubtype != null) { - SubtypeSettings.setSelectedSubtype(prefs, toSubtype) + val additionalSubtypes = SubtypeSettings.createSettingsSubtypes(prefs.getString(Settings.PREF_ADDITIONAL_SUBTYPES, Defaults.PREF_ADDITIONAL_SUBTYPES)!!) + .toMutableList() + additionalSubtypes.remove(from) + if (!to.isSameAsDefault()) { + // We only add the "to" subtype if it's not equal to a resource subtype. + // This means we make additional subtype disappear as magically as it was added if all settings are default. + // If we don't do this, enabling the base subtype will result in the additional subtype being enabled, + // as both have the same settingsSubtype. + additionalSubtypes.add(to) } - if (fromSubtype != null && isEnabled && toSubtype != null) { - SubtypeSettings.removeEnabledSubtype(context, fromSubtype) - SubtypeSettings.addEnabledSubtype(prefs, toSubtype) + val editor = prefs.edit() + editor.putString(Settings.PREF_ADDITIONAL_SUBTYPES, SubtypeSettings.createPrefSubtypes(additionalSubtypes)) + if (isSelected) { + editor.putString(Settings.PREF_SELECTED_SUBTYPE, to.toPref()) } + if (isEnabled) { + val enabled = SubtypeSettings.createSettingsSubtypes(prefs.getString(Settings.PREF_ENABLED_SUBTYPES, Defaults.PREF_ENABLED_SUBTYPES)!!) + .toMutableList() + enabled.remove(from) + enabled.add(to) + editor.putString(Settings.PREF_ENABLED_SUBTYPES, SubtypeSettings.createPrefSubtypes(enabled)) + } + editor.apply() + SubtypeSettings.reloadEnabledSubtypes(context) } - fun createAdditionalSubtypes(prefSubtypes: String): List { - if (prefSubtypes.isEmpty()) - return emptyList() - return prefSubtypes.split(Separators.SETS).mapNotNull { it.toSettingsSubtype().toAdditionalSubtype() } - } - - fun createPrefSubtypes(subtypes: Collection): String { - if (subtypes.isEmpty()) - return "" - return subtypes.joinToString(Separators.SETS) { it.toSettingsSubtype().toPref() } - } + fun createAdditionalSubtypes(prefSubtypes: String): List = + prefSubtypes.split(Separators.SETS).mapNotNull { + if (it.isEmpty()) null + else it.toSettingsSubtype().toAdditionalSubtype() + } private fun getNameResId(locale: Locale, mainLayoutName: String): Int { - val nameId = SubtypeLocaleUtils.getSubtypeNameResId(locale, mainLayoutName) - if (nameId != SubtypeLocaleUtils.UNKNOWN_KEYBOARD_LAYOUT) return nameId SubtypeSettings.getResourceSubtypesForLocale(locale).forEach { if (it.mainLayoutName() == mainLayoutName) return it.nameResId } @@ -146,15 +161,17 @@ object SubtypeUtilsAdditional { val extraValueItems = mutableListOf() if (isAsciiCapable) extraValueItems.add(ExtraValue.ASCII_CAPABLE) - if (SubtypeLocaleUtils.isExceptionalLocale(locale)) { +/* if (SubtypeLocaleUtils.isExceptionalLocale(locale)) { // this seems to be for shorter names (e.g. English (US) instead English (United States)) // but is now also used for languages that are not known by Android (at least older versions) // todo: actually this should never contain a custom layout name, because it may contain any // characters including , and = which may break extra values + // todo: disabled for now, not necessary with the more generic subtype name + // might become necessary again when exposing subtypes to the system extraValueItems.add( ExtraValue.UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME + "=" + SubtypeLocaleUtils.getMainLayoutDisplayName(mainLayoutName) ) - } + }*/ if (isEmojiCapable) extraValueItems.add(ExtraValue.EMOJI_CAPABLE) extraValueItems.add(ExtraValue.IS_ADDITIONAL_SUBTYPE) diff --git a/app/src/main/java/helium314/keyboard/latin/utils/Timestamp.kt b/app/src/main/java/helium314/keyboard/latin/utils/Timestamp.kt new file mode 100644 index 000000000..ebe2bd0e8 --- /dev/null +++ b/app/src/main/java/helium314/keyboard/latin/utils/Timestamp.kt @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-3.0-only +package helium314.keyboard.latin.utils + +import android.content.Context +import helium314.keyboard.latin.settings.Defaults +import helium314.keyboard.latin.settings.Settings +import java.text.SimpleDateFormat +import java.util.Calendar + +fun getTimestamp(context: Context): String { + val format = context.prefs().getString(Settings.PREF_TIMESTAMP_FORMAT, Defaults.PREF_TIMESTAMP_FORMAT) + val formatter = runCatching { SimpleDateFormat(format, Settings.getValues().mLocale) }.getOrNull() + ?: SimpleDateFormat(Defaults.PREF_TIMESTAMP_FORMAT, Settings.getValues().mLocale) + return formatter.format(Calendar.getInstance().time) +} + +fun checkTimestampFormat(format: String) = runCatching { SimpleDateFormat(format, Settings.getValues().mLocale) }.isSuccess diff --git a/app/src/main/java/helium314/keyboard/settings/Misc.kt b/app/src/main/java/helium314/keyboard/settings/Misc.kt index 05925afb3..2ca4add2c 100644 --- a/app/src/main/java/helium314/keyboard/settings/Misc.kt +++ b/app/src/main/java/helium314/keyboard/settings/Misc.kt @@ -1,13 +1,18 @@ // SPDX-License-Identifier: GPL-3.0-only package helium314.keyboard.settings +import android.graphics.drawable.VectorDrawable +import androidx.annotation.DrawableRes +import androidx.compose.foundation.Image import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size import androidx.compose.material3.DropdownMenu import androidx.compose.material3.DropdownMenuItem +import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -17,8 +22,15 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.asImageBitmap +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.style.TextDirection import androidx.compose.ui.unit.dp - +import androidx.core.content.ContextCompat +import androidx.core.graphics.drawable.toBitmap +import androidx.core.util.TypedValueCompat @Composable fun WithSmallTitle( @@ -31,6 +43,19 @@ fun WithSmallTitle( } } +/** Icon if resource is a vector image, (bitmap) Image otherwise */ +@Composable +fun IconOrImage(@DrawableRes resId: Int, name: String?, sizeDp: Float) { + val ctx = LocalContext.current + val drawable = ContextCompat.getDrawable(ctx, resId) + if (drawable is VectorDrawable) + Icon(painterResource(resId), name, Modifier.size(sizeDp.dp)) + else { + val px = TypedValueCompat.dpToPx(sizeDp, ctx.resources.displayMetrics).toInt() + Image(drawable!!.toBitmap(px, px).asImageBitmap(), name) + } +} + @Composable fun DropDownField( items: List, @@ -67,3 +92,5 @@ fun DropDownField( } } } + +val contentTextDirectionStyle = TextStyle(textDirection = TextDirection.Content) diff --git a/app/src/main/java/helium314/keyboard/settings/SearchScreen.kt b/app/src/main/java/helium314/keyboard/settings/SearchScreen.kt index 7184d981c..66ba49f64 100644 --- a/app/src/main/java/helium314/keyboard/settings/SearchScreen.kt +++ b/app/src/main/java/helium314/keyboard/settings/SearchScreen.kt @@ -6,9 +6,13 @@ import androidx.compose.animation.AnimatedVisibility import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.WindowInsetsSides import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.only import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.safeDrawing import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.foundation.rememberScrollState @@ -20,6 +24,7 @@ import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.LocalTextStyle import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.material3.TextField @@ -33,7 +38,6 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember -import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.draw.rotate @@ -59,36 +63,42 @@ fun SearchSettingsScreen( content = { if (content != null) content() else { - Column(Modifier.verticalScroll(rememberScrollState())) { - settings.forEach { - if (it is Int) { - PreferenceCategory(stringResource(it)) - } else { - // this only animates appearing prefs - // a solution would be using a list(visible to key) - AnimatedVisibility(visible = it != null) { - if (it != null) - SettingsActivity.settingsContainer[it]?.Preference() + Scaffold( + contentWindowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Bottom) + ) { innerPadding -> + Column( + Modifier.verticalScroll(rememberScrollState()).then(Modifier.padding(innerPadding)) + ) { + settings.forEach { + if (it is Int) { + PreferenceCategory(stringResource(it)) + } else { + // this only animates appearing prefs + // a solution would be using a list(visible to key) + AnimatedVisibility(visible = it != null) { + if (it != null) + SettingsActivity.settingsContainer[it]?.Preference() + } } } } + // lazyColumn has janky scroll for a while (not sure why compose gets smoother after a while) + // maybe related to unnecessary recompositions? but even for just displaying text it's there + // didn't manage to improve things with @Immutable list wrapper and other lazy list hints + // so for now: just use "normal" Column + // even though it takes up to ~50% longer to load it's much better UX + // and the missing appear animations could be added + // LazyColumn { + // items(prefs.filterNotNull(), key = { it }) { + // Box(Modifier.animateItem()) { + // if (it is Int) + // PreferenceCategory(stringResource(it)) + // else + // SettingsActivity.settingsContainer[it]!!.Preference() + // } + // } + // } } - // lazyColumn has janky scroll for a while (not sure why compose gets smoother after a while) - // maybe related to unnecessary recompositions? but even for just displaying text it's there - // didn't manage to improve things with @Immutable list wrapper and other lazy list hints - // so for now: just use "normal" Column - // even though it takes up to ~50% longer to load it's much better UX - // and the missing appear animations could be added -// LazyColumn { -// items(prefs.filterNotNull(), key = { it }) { -// Box(Modifier.animateItem()) { -// if (it is Int) -// PreferenceCategory(stringResource(it)) -// else -// SettingsActivity.settingsContainer[it]!!.Preference() -// } -// } -// } } }, filteredItems = { SettingsActivity.settingsContainer.filter(it) }, @@ -103,96 +113,99 @@ fun SearchScreen( title: @Composable () -> Unit, filteredItems: (String) -> List, itemContent: @Composable (T) -> Unit, + icon: @Composable (() -> Unit)? = null, menu: List Unit>>? = null, content: @Composable (ColumnScope.() -> Unit)? = null, ) { - var searchText by rememberSaveable(stateSaver = TextFieldValue.Saver) { mutableStateOf(TextFieldValue()) } - Column(Modifier.fillMaxSize()) { - var showSearch by remember { mutableStateOf(false) } + // searchText and showSearch should have the same remember or rememberSaveable + // saveable survives orientation changes and switching between screens, but shows the + // keyboard in unexpected situations such as going back from another screen, which is rather annoying + var searchText by remember { mutableStateOf(TextFieldValue()) } + var showSearch by remember { mutableStateOf(false) } + Scaffold(contentWindowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Horizontal + WindowInsetsSides.Top)) + { innerPadding -> + Column(Modifier.fillMaxSize().padding(innerPadding)) { - fun setShowSearch(value: Boolean) { - showSearch = value - if (!value) searchText = TextFieldValue() - } - BackHandler { - if (showSearch || searchText.text.isNotEmpty()) setShowSearch(false) - else onClickBack() - } - Surface( - color = MaterialTheme.colorScheme.surfaceContainer, - ) { - Column { - TopAppBar( - title = title, - windowInsets = TopAppBarDefaults.windowInsets, - navigationIcon = { - IconButton(onClick = { - if (showSearch) setShowSearch(false) - else onClickBack() - }) { - Icon( - painterResource(R.drawable.ic_arrow_back), - stringResource(R.string.spoken_description_action_previous) - ) - } - }, - actions = { - IconButton(onClick = { setShowSearch(!showSearch) }) - { SearchIcon() } - if (menu != null) - Box { - var showMenu by remember { mutableStateOf(false) } - IconButton( - onClick = { showMenu = true } - ) { Icon(painterResource(R.drawable.ic_arrow_left), "menu", Modifier.rotate(-90f)) } - DropdownMenu( - expanded = showMenu, - onDismissRequest = { showMenu = false } - ) { - menu.forEach { - DropdownMenuItem( - text = { Text(it.first) }, - onClick = { showMenu = false; it.second() } - ) + fun setShowSearch(value: Boolean) { + showSearch = value + if (!value) searchText = TextFieldValue() + } + BackHandler { + if (showSearch || searchText.text.isNotEmpty()) setShowSearch(false) + else onClickBack() + } + Surface( + color = MaterialTheme.colorScheme.surfaceContainer, + ) { + Column { + TopAppBar( + title = title, + windowInsets = WindowInsets(0), + navigationIcon = { + IconButton(onClick = { + if (showSearch) setShowSearch(false) + else onClickBack() + }) { + Icon( + painterResource(R.drawable.ic_arrow_back), + stringResource(R.string.spoken_description_action_previous) + ) + } + }, + actions = { + if (icon == null) + IconButton(onClick = { setShowSearch(!showSearch) }) { SearchIcon() } + else + icon() + if (menu != null) + Box { + var showMenu by remember { mutableStateOf(false) } + IconButton( + onClick = { showMenu = true } + ) { Icon(painterResource(R.drawable.ic_arrow_left), "menu", Modifier.rotate(-90f)) } + DropdownMenu( + expanded = showMenu, + onDismissRequest = { showMenu = false } + ) { + menu.forEach { + DropdownMenuItem( + text = { Text(it.first) }, + onClick = { showMenu = false; it.second() } + ) + } } } - } - }, - ) - ExpandableSearchField( - expanded = showSearch, - onDismiss = { setShowSearch(false) }, - search = searchText, - onSearchChange = { searchText = it }, - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 16.dp, vertical = 8.dp), - colors = TextFieldDefaults.colors( - focusedContainerColor = MaterialTheme.colorScheme.surface + }, + ) + ExpandableSearchField( + expanded = showSearch, + onDismiss = { setShowSearch(false) }, + search = searchText, + onSearchChange = { searchText = it }, + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp, vertical = 8.dp), + colors = TextFieldDefaults.colors( + focusedContainerColor = MaterialTheme.colorScheme.surface + ) ) - ) - } - } - CompositionLocalProvider(LocalTextStyle provides MaterialTheme.typography.bodyLarge) { - if (searchText.text.isBlank() && content != null) { - Column( - // todo: how and where to best deal with insets? - // here? manifest android:windowSoftInputMode="adjustResize"? - // other? -// Modifier -// .windowInsetsPadding( -// WindowInsets.safeDrawing.only( -// WindowInsetsSides.Horizontal + WindowInsetsSides.Bottom -// ) -// ) - ) { - content() } - } else { - val items = filteredItems(searchText.text) - LazyColumn { - items(items) { - itemContent(it) + } + CompositionLocalProvider(LocalTextStyle provides MaterialTheme.typography.bodyLarge) { + if (searchText.text.isBlank() && content != null) { + Column { + content() + } + } else { + val items = filteredItems(searchText.text) + Scaffold( + contentWindowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Bottom) + ) { innerPadding -> + LazyColumn(contentPadding = innerPadding) { + items(items) { + itemContent(it) + } + } } } } @@ -227,7 +240,8 @@ fun ExpandableSearchField( else onSearchChange(TextFieldValue()) }) { CloseIcon(android.R.string.cancel) } }, singleLine = true, - colors = colors + colors = colors, + textStyle = contentTextDirectionStyle ) } } diff --git a/app/src/main/java/helium314/keyboard/settings/SettingsActivity.kt b/app/src/main/java/helium314/keyboard/settings/SettingsActivity.kt index 498b7293c..df7dfa861 100644 --- a/app/src/main/java/helium314/keyboard/settings/SettingsActivity.kt +++ b/app/src/main/java/helium314/keyboard/settings/SettingsActivity.kt @@ -5,32 +5,41 @@ import android.content.Context import android.content.Intent import android.content.SharedPreferences import android.net.Uri -import android.os.Build import android.os.Bundle -import android.view.View -import android.view.WindowInsets.Type import android.view.inputmethod.EditorInfo import android.view.inputmethod.InputMethodManager import androidx.activity.ComponentActivity +import androidx.activity.enableEdgeToEdge import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.safeDrawing +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.Scaffold import androidx.compose.material3.Surface import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBar import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier import androidx.compose.ui.platform.ComposeView -import androidx.core.view.ViewCompat +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource import helium314.keyboard.compat.locale import helium314.keyboard.keyboard.KeyboardSwitcher import helium314.keyboard.latin.BuildConfig import helium314.keyboard.latin.InputAttributes +import helium314.keyboard.latin.R import helium314.keyboard.latin.common.FileUtils import helium314.keyboard.latin.define.DebugFlags import helium314.keyboard.latin.settings.Settings +import helium314.keyboard.latin.utils.DeviceProtectedUtils import helium314.keyboard.latin.utils.ExecutorUtils -import helium314.keyboard.latin.utils.ResourceUtils import helium314.keyboard.latin.utils.UncachedInputMethodManagerUtils import helium314.keyboard.latin.utils.cleanUnusedMainDicts import helium314.keyboard.latin.utils.prefs @@ -53,11 +62,13 @@ import java.util.zip.ZipOutputStream class SettingsActivity : ComponentActivity(), SharedPreferences.OnSharedPreferenceChangeListener { private val prefs by lazy { this.prefs() } val prefChanged = MutableStateFlow(0) // simple counter, as the only relevant information is that something changed + fun prefChanged() = prefChanged.value++ private val dictUriFlow = MutableStateFlow(null) private val cachedDictionaryFile by lazy { File(this.cacheDir.path + File.separator + "temp_dict") } private val crashReportFiles = MutableStateFlow>(emptyList()) private var paused = true + @OptIn(ExperimentalMaterial3Api::class) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) if (Settings.getValues() == null) { @@ -67,19 +78,8 @@ class SettingsActivity : ComponentActivity(), SharedPreferences.OnSharedPreferen ExecutorUtils.getBackgroundExecutor(ExecutorUtils.KEYBOARD).execute { cleanUnusedMainDicts(this) } if (BuildConfig.DEBUG || DebugFlags.DEBUG_ENABLED) crashReportFiles.value = findCrashReports() - setSystemBarIconColor() val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager - // with this the layout edit dialog is not covered by the keyboard - // alternative of Modifier.imePadding() and properties = DialogProperties(decorFitsSystemWindows = false) has other weird side effects - ViewCompat.setOnApplyWindowInsetsListener(window.decorView.rootView) { _, insets -> - @Suppress("DEPRECATION") - bottomInsets.value = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) - insets.getInsets(Type.ime()).bottom - else insets.systemWindowInsetBottom - insets - } - settingsContainer = SettingsContainer(this) val spellchecker = intent?.getBooleanExtra("spellchecker", false) ?: false @@ -97,12 +97,47 @@ class SettingsActivity : ComponentActivity(), SharedPreferences.OnSharedPreferen || !UncachedInputMethodManagerUtils.isThisImeEnabled(this, imm) ) } if (spellchecker) - Column { // lazy way of implementing spell checker settings - settingsContainer[Settings.PREF_USE_CONTACTS]!!.Preference() - settingsContainer[Settings.PREF_BLOCK_POTENTIALLY_OFFENSIVE]!!.Preference() + Scaffold(contentWindowInsets = WindowInsets.safeDrawing) { innerPadding -> + Column(Modifier.padding(innerPadding)) { + TopAppBar( + title = { Text(stringResource(R.string.android_spell_checker_settings)) }, + windowInsets = WindowInsets(0), + navigationIcon = { + IconButton(onClick = { this@SettingsActivity.finish() }) { + Icon( + painterResource(R.drawable.ic_arrow_back), + stringResource(R.string.spoken_description_action_previous) + ) + } + }, + ) + settingsContainer[Settings.PREF_USE_CONTACTS]!!.Preference() + settingsContainer[Settings.PREF_USE_APPS]!!.Preference() + settingsContainer[Settings.PREF_BLOCK_POTENTIALLY_OFFENSIVE]!!.Preference() + } } - else + else { SettingsNavHost(onClickBack = { this.finish() }) + if (showWelcomeWizard) { + WelcomeWizard(close = { showWelcomeWizard = false }, finish = this::finish) + } else if (crashReports.isNotEmpty()) { + ConfirmationDialog( + cancelButtonText = "ignore", + onDismissRequest = { crashReportFiles.value = emptyList() }, + neutralButtonText = "delete", + onNeutral = { crashReports.forEach { it.delete() }; crashReportFiles.value = emptyList() }, + confirmButtonText = "get", + onConfirmed = { + val intent = Intent(Intent.ACTION_CREATE_DOCUMENT) + intent.addCategory(Intent.CATEGORY_OPENABLE) + intent.putExtra(Intent.EXTRA_TITLE, "crash_reports.zip") + intent.setType("application/zip") + crashFilePicker.launch(intent) + }, + content = { Text("Crash report files found") }, + ) + } + } if (dictUri != null) { NewDictionaryDialog( onDismissRequest = { dictUriFlow.value = null }, @@ -110,26 +145,6 @@ class SettingsActivity : ComponentActivity(), SharedPreferences.OnSharedPreferen mainLocale = null ) } - if (!showWelcomeWizard && !spellchecker && crashReports.isNotEmpty()) { - ConfirmationDialog( - cancelButtonText = "ignore", - onDismissRequest = { crashReportFiles.value = emptyList() }, - neutralButtonText = "delete", - onNeutral = { crashReports.forEach { it.delete() }; crashReportFiles.value = emptyList() }, - confirmButtonText = "get", - onConfirmed = { - val intent = Intent(Intent.ACTION_CREATE_DOCUMENT) - intent.addCategory(Intent.CATEGORY_OPENABLE) - intent.putExtra(Intent.EXTRA_TITLE, "crash_reports.zip") - intent.setType("application/zip") - crashFilePicker.launch(intent) - }, - content = { Text("Crash report files found") }, - ) - } - if (!spellchecker && showWelcomeWizard) { - WelcomeWizard(close = { showWelcomeWizard = false }, finish = this::finish) - } } } } @@ -142,6 +157,8 @@ class SettingsActivity : ComponentActivity(), SharedPreferences.OnSharedPreferen } intent = null } + + enableEdgeToEdge() } override fun onStart() { @@ -176,8 +193,9 @@ class SettingsActivity : ComponentActivity(), SharedPreferences.OnSharedPreferen private fun findCrashReports(): List { // find crash report files - val dir: File = getExternalFilesDir(null) ?: return emptyList() - val allFiles = dir.listFiles() ?: return emptyList() + val dir = getExternalFilesDir(null) + val unprotectedDir = DeviceProtectedUtils.getFilesDir(this) + val allFiles = dir?.listFiles()?.toList().orEmpty() + unprotectedDir?.listFiles().orEmpty() return allFiles.filter { it.name.startsWith("crash_report") } } @@ -205,23 +223,6 @@ class SettingsActivity : ComponentActivity(), SharedPreferences.OnSharedPreferen } } - // deprecated but works... ideally it would be done automatically like it worked before switching to compose - private fun setSystemBarIconColor() { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return - val view = window.decorView - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - if (ResourceUtils.isNight(resources)) - view.systemUiVisibility = view.systemUiVisibility and View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.inv() and View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR.inv() - else - view.systemUiVisibility = view.systemUiVisibility or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR or View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR - } else { - if (ResourceUtils.isNight(resources)) - view.systemUiVisibility = view.systemUiVisibility and View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.inv() - else - view.systemUiVisibility = view.systemUiVisibility or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR - } - } - companion object { // public write so compose previews can show the screens // having it in a companion object is not ideal as it will stay in memory even after settings are closed @@ -230,12 +231,9 @@ class SettingsActivity : ComponentActivity(), SharedPreferences.OnSharedPreferen var forceNight: Boolean? = null var forceTheme: String? = null - - // weird inset forwarding because otherwise layout dialog sometimes doesn't care about keyboard showing - var bottomInsets = MutableStateFlow(0) } override fun onSharedPreferenceChanged(prefereces: SharedPreferences?, key: String?) { - prefChanged.value++ + prefChanged() } } diff --git a/app/src/main/java/helium314/keyboard/settings/SettingsNavHost.kt b/app/src/main/java/helium314/keyboard/settings/SettingsNavHost.kt index f3773125e..7a694070f 100644 --- a/app/src/main/java/helium314/keyboard/settings/SettingsNavHost.kt +++ b/app/src/main/java/helium314/keyboard/settings/SettingsNavHost.kt @@ -1,16 +1,22 @@ // SPDX-License-Identifier: GPL-3.0-only package helium314.keyboard.settings +import android.provider.Settings +import android.provider.Settings.Global +import androidx.compose.animation.core.tween import androidx.compose.animation.slideInHorizontally import androidx.compose.animation.slideOutHorizontally import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalLayoutDirection +import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.LayoutDirection import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController import helium314.keyboard.latin.common.LocaleUtils.constructLocale +import helium314.keyboard.latin.settings.SettingsSubtype.Companion.toSettingsSubtype import helium314.keyboard.settings.screens.AboutScreen import helium314.keyboard.settings.screens.AdvancedSettingsScreen import helium314.keyboard.settings.screens.AppearanceScreen @@ -24,6 +30,7 @@ import helium314.keyboard.settings.screens.PersonalDictionariesScreen import helium314.keyboard.settings.screens.PersonalDictionaryScreen import helium314.keyboard.settings.screens.PreferencesScreen import helium314.keyboard.settings.screens.SecondaryLayoutScreen +import helium314.keyboard.settings.screens.SubtypeScreen import helium314.keyboard.settings.screens.TextCorrectionScreen import helium314.keyboard.settings.screens.ToolbarScreen import kotlinx.coroutines.CoroutineScope @@ -41,6 +48,10 @@ fun SettingsNavHost( val dir = if (LocalLayoutDirection.current == LayoutDirection.Ltr) 1 else -1 val target = SettingsDestination.navTarget.collectAsState() + // duration does not change when system setting changes, but that's rare enough to not care + val duration = (250 * Settings.System.getFloat(LocalContext.current.contentResolver, Global.TRANSITION_ANIMATION_SCALE, 1f)).toInt() + val animation = tween(durationMillis = duration) + fun goBack() { if (!navController.popBackStack()) onClickBack() } @@ -48,10 +59,10 @@ fun SettingsNavHost( NavHost( navController = navController, startDestination = startDestination ?: SettingsDestination.Settings, - enterTransition = { slideInHorizontally(initialOffsetX = { +it * dir }) }, - exitTransition = { slideOutHorizontally(targetOffsetX = { -it * dir }) }, - popEnterTransition = { slideInHorizontally(initialOffsetX = { -it * dir }) }, - popExitTransition = { slideOutHorizontally(targetOffsetX = { +it * dir }) } + enterTransition = { slideInHorizontally(initialOffsetX = { +it * dir }, animationSpec = animation) }, + exitTransition = { slideOutHorizontally(targetOffsetX = { -it * dir }, animationSpec = animation) }, + popEnterTransition = { slideInHorizontally(initialOffsetX = { -it * dir }, animationSpec = animation) }, + popExitTransition = { slideOutHorizontally(targetOffsetX = { +it * dir }, animationSpec = animation) } ) { composable(SettingsDestination.Settings) { MainSettingsScreen( @@ -117,6 +128,9 @@ fun SettingsNavHost( composable(SettingsDestination.ColorsNight + "{theme}") { ColorsScreen(isNight = true, theme = it.arguments?.getString("theme"), onClickBack = ::goBack) } + composable(SettingsDestination.Subtype + "{subtype}") { + SubtypeScreen(initialSubtype = it.arguments?.getString("subtype")!!.toSettingsSubtype(), onClickBack = ::goBack) + } } if (target.value != SettingsDestination.Settings/* && target.value != navController.currentBackStackEntry?.destination?.route*/) navController.navigate(route = target.value) @@ -137,6 +151,7 @@ object SettingsDestination { const val PersonalDictionaries = "personal_dictionaries" const val PersonalDictionary = "personal_dictionary/" const val Languages = "languages" + const val Subtype = "subtype/" const val Layouts = "layouts" const val Dictionaries = "dictionaries" val navTarget = MutableStateFlow(Settings) diff --git a/app/src/main/java/helium314/keyboard/settings/Theme.kt b/app/src/main/java/helium314/keyboard/settings/Theme.kt index e8924a300..32d8121b9 100644 --- a/app/src/main/java/helium314/keyboard/settings/Theme.kt +++ b/app/src/main/java/helium314/keyboard/settings/Theme.kt @@ -12,9 +12,6 @@ import androidx.compose.material3.lightColorScheme import androidx.compose.runtime.Composable import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.colorResource -import androidx.compose.ui.text.font.DeviceFontFamilyName -import androidx.compose.ui.text.font.Font -import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.font.FontWeight import helium314.keyboard.latin.R @@ -36,20 +33,9 @@ fun Theme(dark: Boolean = isSystemInDarkTheme(), content: @Composable () -> Unit MaterialTheme( colorScheme = colorScheme, typography = Typography( - headlineMedium = material3.headlineMedium.copy(fontWeight = FontWeight.Bold), - headlineSmall = material3.headlineSmall.copy(fontWeight = FontWeight.Bold), - titleLarge = material3.titleLarge.copy( - fontWeight = FontWeight.Bold, - fontFamily = FontFamily(Font(DeviceFontFamilyName("sans-serif-condensed"), FontWeight.Bold)) - ), - titleMedium = material3.titleMedium.copy( - fontWeight = FontWeight.Bold, - fontFamily = FontFamily(Font(DeviceFontFamilyName("sans-serif-condensed"), FontWeight.Bold)) - ), - titleSmall = material3.titleSmall.copy( - fontWeight = FontWeight.Bold, - fontFamily = FontFamily(Font(DeviceFontFamilyName("sans-serif-condensed"), FontWeight.Bold)) - ) + titleLarge = material3.titleLarge.copy(fontWeight = FontWeight.Bold), + titleMedium = material3.titleMedium.copy(fontWeight = FontWeight.Bold), + titleSmall = material3.titleSmall.copy(fontWeight = FontWeight.Bold) ), //shapes = Shapes(), content = content diff --git a/app/src/main/java/helium314/keyboard/settings/dialogs/ColorPickerDialog.kt b/app/src/main/java/helium314/keyboard/settings/dialogs/ColorPickerDialog.kt index 15e926acb..d1771b61b 100644 --- a/app/src/main/java/helium314/keyboard/settings/dialogs/ColorPickerDialog.kt +++ b/app/src/main/java/helium314/keyboard/settings/dialogs/ColorPickerDialog.kt @@ -7,6 +7,7 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material3.Surface import androidx.compose.material3.Text @@ -24,6 +25,7 @@ import androidx.compose.ui.graphics.PaintingStyle import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.text.TextRange +import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.tooling.preview.Preview @@ -109,8 +111,12 @@ fun ColorPickerDialog( ) TextField( value = textValue, - // todo: KeyboardType.Password is a crappy way of avoiding suggestions... is there really no way in compose? - keyboardOptions = KeyboardOptions(autoCorrectEnabled = false, keyboardType = KeyboardType.Password), + keyboardOptions = KeyboardOptions( + autoCorrectEnabled = false, + keyboardType = KeyboardType.Password, // todo: KeyboardType.Password is a crappy way of avoiding suggestions... is there really no way in compose? + imeAction = ImeAction.Done, + ), + keyboardActions = KeyboardActions(onDone = { onDismissRequest(); onConfirmed(controller.selectedColor.value.toArgb()) }), onValueChange = { textValue = it val androidColor = runCatching { android.graphics.Color.parseColor("#${it.text}") }.getOrNull() diff --git a/app/src/main/java/helium314/keyboard/settings/dialogs/ColorThemePickerDialog.kt b/app/src/main/java/helium314/keyboard/settings/dialogs/ColorThemePickerDialog.kt index ac97743f8..24101e86e 100644 --- a/app/src/main/java/helium314/keyboard/settings/dialogs/ColorThemePickerDialog.kt +++ b/app/src/main/java/helium314/keyboard/settings/dialogs/ColorThemePickerDialog.kt @@ -60,6 +60,7 @@ import helium314.keyboard.settings.Theme import helium314.keyboard.settings.filePicker import helium314.keyboard.settings.previewDark import helium314.keyboard.settings.screens.SaveThoseColors +import helium314.keyboard.settings.contentTextDirectionStyle import kotlinx.coroutines.launch import kotlinx.serialization.SerializationException import kotlinx.serialization.json.Json @@ -187,7 +188,8 @@ private fun AddColorRow(onDismissRequest: () -> Unit, userColors: Collection @@ -108,10 +114,9 @@ fun LayoutEditDialog( } valid && nameValid // don't allow saving with invalid name, but inform user about issues with layout content }, - // this looks weird when the text field is not covered by the keyboard (long dialog) - // but better than not seeing the bottom part of the field... - modifier = Modifier.padding(bottom = with(LocalDensity.current) - { (bottomInsets / 2 + 36).toDp() }), // why is the /2 necessary? + properties = DialogProperties(usePlatformDefaultWidth = false, dismissOnClickOutside = false, dismissOnBackPress = false), + modifier = Modifier.windowInsetsPadding(WindowInsets.ime.exclude(WindowInsets.systemBars)) + .padding(horizontal = 16.dp), // dialog is rather wide, but shouldn't go all the way to the screen edges reducePadding = true, ) } diff --git a/app/src/main/java/helium314/keyboard/settings/dialogs/LayoutPickerDialog.kt b/app/src/main/java/helium314/keyboard/settings/dialogs/LayoutPickerDialog.kt index 7355c7e41..ace5aafb8 100644 --- a/app/src/main/java/helium314/keyboard/settings/dialogs/LayoutPickerDialog.kt +++ b/app/src/main/java/helium314/keyboard/settings/dialogs/LayoutPickerDialog.kt @@ -50,6 +50,7 @@ import helium314.keyboard.settings.EditButton import helium314.keyboard.settings.Setting import helium314.keyboard.settings.SettingsActivity import helium314.keyboard.settings.Theme +import helium314.keyboard.settings.contentTextDirectionStyle import helium314.keyboard.settings.layoutFilePicker import helium314.keyboard.settings.layoutIntent import helium314.keyboard.settings.previewDark @@ -140,7 +141,8 @@ private fun AddLayoutRow(onNewLayout: (String) -> Unit, layoutType: LayoutType, value = textValue, onValueChange = { textValue = it }, modifier = Modifier.weight(1f), - singleLine = true + singleLine = true, + textStyle = contentTextDirectionStyle, ) EditButton(textValue.text.isNotEmpty() && LayoutUtilsCustom.getLayoutName(textValue.text, layoutType) !in userLayouts) { onNewLayout(textValue.text) @@ -202,6 +204,7 @@ private fun LayoutItemRow( onConfirmed = { showDeleteDialog = false onDelete(layoutName) + (ctx.getActivity() as? SettingsActivity)?.prefChanged() } ) } diff --git a/app/src/main/java/helium314/keyboard/settings/dialogs/NewDictionaryDialog.kt b/app/src/main/java/helium314/keyboard/settings/dialogs/NewDictionaryDialog.kt index 2bf3da39c..1405c71ae 100644 --- a/app/src/main/java/helium314/keyboard/settings/dialogs/NewDictionaryDialog.kt +++ b/app/src/main/java/helium314/keyboard/settings/dialogs/NewDictionaryDialog.kt @@ -32,6 +32,7 @@ import helium314.keyboard.settings.DropDownField import helium314.keyboard.settings.WithSmallTitle import java.io.File import java.util.Locale +import androidx.compose.ui.platform.LocalConfiguration @Composable fun NewDictionaryDialog( @@ -52,10 +53,10 @@ fun NewDictionaryDialog( val locales = SubtypeSettings.getAvailableSubtypeLocales() .filter { it.script() == dictLocale.script() || it.script() == mainLocale?.script() } .sortedWith(comparer) - val cacheDir = DictionaryInfoUtils.getAndCreateCacheDirectoryForLocale(locale, ctx) + val cacheDir = DictionaryInfoUtils.getCacheDirectoryForLocale(locale, ctx) val dictFile = File(cacheDir, header.mIdString.substringBefore(":") + "_" + DictionaryInfoUtils.USER_DICTIONARY_SUFFIX) val type = header.mIdString.substringBefore(":") - val info = header.info(ctx.resources.configuration.locale()) + val info = header.info(LocalConfiguration.current.locale()) ThreeButtonAlertDialog( onDismissRequest = { onDismissRequest(); cachedFile.delete() }, onConfirmed = { @@ -64,7 +65,7 @@ fun NewDictionaryDialog( cachedFile.renameTo(dictFile) if (type == Dictionary.TYPE_MAIN) { // replaced main dict, remove the one created from internal data - val internalMainDictFile = File(cacheDir, DictionaryInfoUtils.getExtractedMainDictFilename()) + val internalMainDictFile = File(cacheDir, DictionaryInfoUtils.MAIN_DICT_FILE_NAME) internalMainDictFile.delete() } val newDictBroadcast = Intent(DictionaryPackConstants.NEW_DICTIONARY_INTENT_ACTION) @@ -80,7 +81,7 @@ fun NewDictionaryDialog( selectedItem = locale, onSelected = { locale = it }, items = locales - ) { Text(it.localizedDisplayName(ctx)) } + ) { Text(it.localizedDisplayName(ctx.resources)) } } if (locale.script() != dictLocale.script()) { // whatever, still allow it if the user wants @@ -92,7 +93,7 @@ fun NewDictionaryDialog( ) } if (dictFile.exists()) { - val oldInfo = DictionaryInfoUtils.getDictionaryFileHeaderOrNull(dictFile, 0, dictFile.length())?.info(ctx.resources.configuration.locale()) + val oldInfo = DictionaryInfoUtils.getDictionaryFileHeaderOrNull(dictFile, 0, dictFile.length())?.info(LocalConfiguration.current.locale()) HorizontalDivider() Text( stringResource(R.string.replace_dictionary_message, type, oldInfo ?: "(no info)", info), diff --git a/app/src/main/java/helium314/keyboard/settings/dialogs/TextInputDialog.kt b/app/src/main/java/helium314/keyboard/settings/dialogs/TextInputDialog.kt index d23f76daa..fa9b8a105 100644 --- a/app/src/main/java/helium314/keyboard/settings/dialogs/TextInputDialog.kt +++ b/app/src/main/java/helium314/keyboard/settings/dialogs/TextInputDialog.kt @@ -22,6 +22,7 @@ import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.window.DialogProperties import helium314.keyboard.settings.Theme +import helium314.keyboard.settings.contentTextDirectionStyle import helium314.keyboard.settings.previewDark // mostly taken from StreetComplete / SCEE @@ -76,7 +77,8 @@ fun TextInputDialog( .focusRequester(focusRequester), label = textInputLabel, keyboardOptions = KeyboardOptions(keyboardType = keyboardType), - singleLine = singleLine + singleLine = singleLine, + textStyle = contentTextDirectionStyle, ) }, properties = properties, diff --git a/app/src/main/java/helium314/keyboard/settings/dialogs/ThreeButtonAlertDialog.kt b/app/src/main/java/helium314/keyboard/settings/dialogs/ThreeButtonAlertDialog.kt index 2b34bcd89..cc20a4e63 100644 --- a/app/src/main/java/helium314/keyboard/settings/dialogs/ThreeButtonAlertDialog.kt +++ b/app/src/main/java/helium314/keyboard/settings/dialogs/ThreeButtonAlertDialog.kt @@ -64,7 +64,7 @@ fun ThreeButtonAlertDialog( bottom = if (reducePadding) 2.dp else 6.dp )) { title?.let { - CompositionLocalProvider(LocalTextStyle provides MaterialTheme.typography.titleLarge) { + CompositionLocalProvider(LocalTextStyle provides MaterialTheme.typography.titleMedium) { Box(Modifier.padding(PaddingValues(bottom = if (reducePadding) 4.dp else 16.dp))) { title() } @@ -82,7 +82,7 @@ fun ThreeButtonAlertDialog( TextButton( onClick = onNeutral ) { Text(neutralButtonText) } - Spacer(modifier.weight(1f)) + Spacer(Modifier.weight(1f)) TextButton(onClick = onDismissRequest) { Text(cancelButtonText) } if (confirmButtonText != null) TextButton( diff --git a/app/src/main/java/helium314/keyboard/settings/preferences/BackgroundImagePreference.kt b/app/src/main/java/helium314/keyboard/settings/preferences/BackgroundImagePreference.kt index 8b70448b8..0f500cdf9 100644 --- a/app/src/main/java/helium314/keyboard/settings/preferences/BackgroundImagePreference.kt +++ b/app/src/main/java/helium314/keyboard/settings/preferences/BackgroundImagePreference.kt @@ -105,6 +105,7 @@ fun BackgroundImagePref(setting: Setting, isLandscape: Boolean) { getFile().delete() Settings.clearCachedBackgroundImages() KeyboardSwitcher.getInstance().setThemeNeedsReload() + showSelectionDialog = false } ) } diff --git a/app/src/main/java/helium314/keyboard/settings/preferences/BackupRestorePreference.kt b/app/src/main/java/helium314/keyboard/settings/preferences/BackupRestorePreference.kt index 675dc2c9d..e156a5d21 100644 --- a/app/src/main/java/helium314/keyboard/settings/preferences/BackupRestorePreference.kt +++ b/app/src/main/java/helium314/keyboard/settings/preferences/BackupRestorePreference.kt @@ -3,6 +3,8 @@ package helium314.keyboard.settings.preferences import android.content.Intent import android.content.SharedPreferences +import android.os.Looper +import android.widget.Toast import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -13,13 +15,12 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import helium314.keyboard.dictionarypack.DictionaryPackConstants import helium314.keyboard.keyboard.KeyboardSwitcher +import helium314.keyboard.keyboard.emoji.SupportedEmojis import helium314.keyboard.latin.R import helium314.keyboard.latin.checkVersionUpgrade import helium314.keyboard.latin.common.FileUtils -import helium314.keyboard.latin.common.LocaleUtils.constructLocale import helium314.keyboard.latin.settings.Settings import helium314.keyboard.latin.utils.DeviceProtectedUtils -import helium314.keyboard.latin.utils.DictionaryInfoUtils import helium314.keyboard.latin.utils.ExecutorUtils import helium314.keyboard.latin.utils.LayoutUtilsCustom import helium314.keyboard.latin.utils.Log @@ -51,10 +52,10 @@ fun BackupRestorePreference(setting: Setting) { val prefs = ctx.prefs() var error: String? by rememberSaveable { mutableStateOf(null) } val backupFilePatterns by lazy { listOf( - "blacklists/.*\\.txt".toRegex(), - "layouts/${LayoutUtilsCustom.CUSTOM_LAYOUT_PREFIX}+\\..{0,4}".toRegex(), // can't expect a period at the end, as this would break restoring older backups - "dicts/.*/.*user\\.dict".toRegex(), - "UserHistoryDictionary.*/UserHistoryDictionary.*\\.(body|header)".toRegex(), + "blacklists${File.separator}.*\\.txt".toRegex(), + "layouts${File.separator}.*${LayoutUtilsCustom.CUSTOM_LAYOUT_PREFIX}+\\..{0,4}".toRegex(), // can't expect a period at the end, as this would break restoring older backups + "dicts${File.separator}.*${File.separator}.*user\\.dict".toRegex(), + "UserHistoryDictionary.*${File.separator}UserHistoryDictionary.*\\.(body|header)".toRegex(), "custom_background_image.*".toRegex(), "custom_font".toRegex(), ) } @@ -131,13 +132,11 @@ fun BackupRestorePreference(setting: Setting) { if (entry.name.startsWith("unprotected${File.separator}")) { val adjustedName = entry.name.substringAfter("unprotected${File.separator}") if (backupFilePatterns.any { adjustedName.matches(it) }) { - val targetFileName = upgradeFileNames(adjustedName) - val file = File(deviceProtectedFilesDir, targetFileName) + val file = File(deviceProtectedFilesDir, adjustedName) FileUtils.copyStreamToNewFile(zip, file) } } else if (backupFilePatterns.any { entry!!.name.matches(it) }) { - val targetFileName = upgradeFileNames(entry.name) - val file = File(filesDir, targetFileName) + val file = File(filesDir, entry.name) FileUtils.copyStreamToNewFile(zip, file) } else if (entry.name == PREFS_FILE_NAME) { val prefLines = String(zip.readBytes()).split("\n") @@ -154,6 +153,9 @@ fun BackupRestorePreference(setting: Setting) { } } } + + Looper.prepare() + Toast.makeText(ctx, ctx.getString(R.string.backup_restored), Toast.LENGTH_LONG).show() } catch (t: Throwable) { error = "r" + t.message Log.w("AdvancedScreen", "error during restore", t) @@ -168,7 +170,9 @@ fun BackupRestorePreference(setting: Setting) { val newDictBroadcast = Intent(DictionaryPackConstants.NEW_DICTIONARY_INTENT_ACTION) ctx.getActivity()?.sendBroadcast(newDictBroadcast) LayoutUtilsCustom.onLayoutFileChanged() - (ctx.getActivity() as? SettingsActivity)?.prefChanged?.value = 210 // for settings reload + LayoutUtilsCustom.removeMissingLayouts(ctx) + (ctx.getActivity() as? SettingsActivity)?.prefChanged() + SupportedEmojis.load(ctx) KeyboardSwitcher.getInstance().setThemeNeedsReload() } Preference(name = setting.title, onClick = { showDialog = true }) @@ -253,38 +257,5 @@ private fun readJsonLinesToSettings(list: List, prefs: SharedPreferences } } -// todo (later): remove this when new package name has been in use for long enough, this is only for migrating from old openboard name -private fun upgradeFileNames(originalName: String): String { - return when { - originalName.endsWith(DictionaryInfoUtils.USER_DICTIONARY_SUFFIX) -> { - // replace directory after switch to language tag - val dirName = originalName.substringAfter(File.separator).substringBefore(File.separator) - originalName.replace(dirName, dirName.constructLocale().toLanguageTag()) - } - originalName.startsWith("blacklists") -> { - // replace file name after switch to language tag - val fileName = originalName.substringAfter("blacklists${File.separator}").substringBefore(".txt") - originalName.replace(fileName, fileName.constructLocale().toLanguageTag()) - } - originalName.startsWith("layouts") -> { - // replace file name after switch to language tag, but only if it's not a layout - val localeString = originalName.substringAfter(".").substringBefore(".") - if (localeString in listOf("symbols", "symbols_shifted", "symbols_arabic", "number", "numpad", "numpad_landscape", "phone", "phone_symbols")) - return originalName // it's a layout! - val locale = localeString.constructLocale() - if (locale.toLanguageTag() != "und") - originalName.replace(localeString, locale.toLanguageTag()) - else - originalName // no valid locale -> must be symbols layout, don't change - } - originalName.startsWith("UserHistoryDictionary") -> { - val localeString = originalName.substringAfter(".").substringBefore(".") - val locale = localeString.constructLocale() - originalName.replace(localeString, locale.toLanguageTag()) - } - else -> originalName - } -} - private const val PREFS_FILE_NAME = "preferences.json" private const val PROTECTED_PREFS_FILE_NAME = "protected_preferences.json" diff --git a/app/src/main/java/helium314/keyboard/settings/preferences/LoadGestureLibPreference.kt b/app/src/main/java/helium314/keyboard/settings/preferences/LoadGestureLibPreference.kt index 591d4a5c7..5b51bdbe2 100644 --- a/app/src/main/java/helium314/keyboard/settings/preferences/LoadGestureLibPreference.kt +++ b/app/src/main/java/helium314/keyboard/settings/preferences/LoadGestureLibPreference.kt @@ -35,10 +35,13 @@ fun LoadGestureLibPreference(setting: Setting) { val abi = Build.SUPPORTED_ABIS[0] val libFile = File(ctx.filesDir?.absolutePath + File.separator + JniUtils.JNI_LIB_IMPORT_FILE_NAME) fun renameToLibFileAndRestart(file: File, checksum: String) { + libFile.setWritable(true) libFile.delete() - // store checksum in default preferences (soo JniUtils) + // store checksum in default preferences (see JniUtils) prefs.edit().putString(Settings.PREF_LIBRARY_CHECKSUM, checksum).commit() - file.renameTo(libFile) + file.copyTo(libFile) + libFile.setReadOnly() + file.delete() Runtime.getRuntime().exit(0) // exit will restart the app, so library will be loaded } var tempFilePath: String? by rememberSaveable { mutableStateOf(null) } diff --git a/app/src/main/java/helium314/keyboard/settings/preferences/Preference.kt b/app/src/main/java/helium314/keyboard/settings/preferences/Preference.kt index 33cd45b63..63fc46922 100644 --- a/app/src/main/java/helium314/keyboard/settings/preferences/Preference.kt +++ b/app/src/main/java/helium314/keyboard/settings/preferences/Preference.kt @@ -10,7 +10,6 @@ import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon import androidx.compose.material3.LocalContentColor @@ -29,6 +28,7 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import helium314.keyboard.latin.R +import helium314.keyboard.settings.IconOrImage import helium314.keyboard.settings.Theme import helium314.keyboard.settings.previewDark @@ -64,12 +64,12 @@ fun Preference( .fillMaxWidth() .clickable { onClick() } .heightIn(min = 44.dp) - .padding(12.dp), + .padding(vertical = 10.dp, horizontal = 12.dp), horizontalArrangement = Arrangement.spacedBy(12.dp), verticalAlignment = Alignment.CenterVertically ) { if (icon != null) - Icon(painterResource(icon), name, modifier = Modifier.size(36.dp)) + IconOrImage(icon, name, 32f) Column(modifier = Modifier.weight(1f)) { Text(text = name, style = MaterialTheme.typography.bodyLarge) if (description != null) { diff --git a/app/src/main/java/helium314/keyboard/settings/preferences/SliderPreference.kt b/app/src/main/java/helium314/keyboard/settings/preferences/SliderPreference.kt index 1eae33b41..97138672a 100644 --- a/app/src/main/java/helium314/keyboard/settings/preferences/SliderPreference.kt +++ b/app/src/main/java/helium314/keyboard/settings/preferences/SliderPreference.kt @@ -26,7 +26,8 @@ fun SliderPreference( default: T, range: ClosedFloatingPointRange, stepSize: Int? = null, - onValueChanged: (Float) -> Unit = { }, + onValueChanged: (Float?) -> Unit = { }, + onConfirmed: (T) -> Unit = { }, ) { val ctx = LocalContext.current val prefs = ctx.prefs() @@ -48,8 +49,13 @@ fun SliderPreference( SliderDialog( onDismissRequest = { showDialog = false }, onDone = { - if (default is Int) prefs.edit().putInt(key, it.toInt()).apply() - else prefs.edit().putFloat(key, it).apply() + if (default is Int) { + prefs.edit().putInt(key, it.toInt()).apply() + onConfirmed(it.toInt() as T) + } else { + prefs.edit().putFloat(key, it).apply() + onConfirmed(it as T) + } }, initialValue = initialValue.toFloat(), range = range, @@ -59,7 +65,7 @@ fun SliderPreference( }, onValueChanged = onValueChanged, showDefault = true, - onDefault = { prefs.edit().remove(key).apply() }, + onDefault = { prefs.edit().remove(key).apply(); onConfirmed(default) }, intermediateSteps = stepSize?.let { // this is not nice, but slider wants it like this... ((range.endInclusive - range.start) / it - 1).toInt() diff --git a/app/src/main/java/helium314/keyboard/settings/preferences/TextInputPreference.kt b/app/src/main/java/helium314/keyboard/settings/preferences/TextInputPreference.kt new file mode 100644 index 000000000..3bf2ce8e9 --- /dev/null +++ b/app/src/main/java/helium314/keyboard/settings/preferences/TextInputPreference.kt @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: GPL-3.0-only +package helium314.keyboard.settings.preferences + +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.platform.LocalContext +import helium314.keyboard.keyboard.KeyboardSwitcher +import helium314.keyboard.latin.utils.prefs +import helium314.keyboard.settings.Setting +import helium314.keyboard.settings.dialogs.TextInputDialog + +@Composable +fun TextInputPreference(setting: Setting, default: String, checkTextValid: (String) -> Boolean = { true }) { + var showDialog by rememberSaveable { mutableStateOf(false) } + val prefs = LocalContext.current.prefs() + Preference( + name = setting.title, + onClick = { showDialog = true }, + description = prefs.getString(setting.key, default)?.takeIf { it.isNotEmpty() } + ) + if (showDialog) { + TextInputDialog( + onDismissRequest = { showDialog = false }, + onConfirmed = { + prefs.edit().putString(setting.key, it).apply() + KeyboardSwitcher.getInstance().setThemeNeedsReload() + }, + initialText = prefs.getString(setting.key, default) ?: "", + title = { Text(setting.title) }, + checkTextValid = checkTextValid + ) + } +} diff --git a/app/src/main/java/helium314/keyboard/settings/screens/AboutScreen.kt b/app/src/main/java/helium314/keyboard/settings/screens/AboutScreen.kt index 0b827952b..36a5cb734 100644 --- a/app/src/main/java/helium314/keyboard/settings/screens/AboutScreen.kt +++ b/app/src/main/java/helium314/keyboard/settings/screens/AboutScreen.kt @@ -2,6 +2,7 @@ package helium314.keyboard.settings.screens import android.app.Activity +import android.app.AlertDialog import android.content.Context import android.content.Intent import android.text.method.LinkMovementMethod @@ -10,7 +11,6 @@ import android.widget.TextView import android.widget.Toast import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.result.contract.ActivityResultContracts -import androidx.appcompat.app.AlertDialog import androidx.compose.material3.Surface import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -54,7 +54,7 @@ fun AboutScreen( SettingsWithoutKey.LICENSE, SettingsWithoutKey.HIDDEN_FEATURES, SettingsWithoutKey.GITHUB, - SettingsWithoutKey.SAVE_LOG + SettingsWithoutKey.SAVE_LOG, ) SearchSettingsScreen( onClickBack = onClickBack, @@ -69,7 +69,7 @@ fun createAboutSettings(context: Context) = listOf( name = it.title, description = it.description, onClick = { }, - icon = R.drawable.ic_launcher_foreground // use the bitmap trick here if we really want the colored icon + icon = R.mipmap.ic_launcher_round ) }, Setting(context, SettingsWithoutKey.VERSION, R.string.version) { @@ -150,7 +150,11 @@ fun createAboutSettings(context: Context) = listOf( val uri = result.data?.data ?: return@rememberLauncherForActivityResult scope.launch(Dispatchers.IO) { ctx.getActivity()?.contentResolver?.openOutputStream(uri)?.use { os -> - os.bufferedWriter().use { it.write(Log.getLog().joinToString("\n")) } + os.writer().use { + val logcat = Runtime.getRuntime().exec("logcat -d -b all *:W").inputStream.use { it.reader().readText() } + val internal = Log.getLog().joinToString("\n") + it.write(logcat + "\n\n" + internal) + } } } } diff --git a/app/src/main/java/helium314/keyboard/settings/screens/AdvancedScreen.kt b/app/src/main/java/helium314/keyboard/settings/screens/AdvancedScreen.kt index 3605a4228..e57f6a5ca 100644 --- a/app/src/main/java/helium314/keyboard/settings/screens/AdvancedScreen.kt +++ b/app/src/main/java/helium314/keyboard/settings/screens/AdvancedScreen.kt @@ -17,6 +17,7 @@ import androidx.compose.ui.tooling.preview.Preview import helium314.keyboard.keyboard.KeyboardActionListener import helium314.keyboard.keyboard.KeyboardLayoutSet import helium314.keyboard.keyboard.KeyboardSwitcher +import helium314.keyboard.keyboard.emoji.SupportedEmojis import helium314.keyboard.keyboard.internal.keyboard_parser.POPUP_KEYS_ALL import helium314.keyboard.keyboard.internal.keyboard_parser.POPUP_KEYS_MAIN import helium314.keyboard.keyboard.internal.keyboard_parser.POPUP_KEYS_MORE @@ -29,6 +30,7 @@ import helium314.keyboard.latin.common.splitOnWhitespace import helium314.keyboard.latin.settings.DebugSettings import helium314.keyboard.latin.settings.Defaults import helium314.keyboard.latin.settings.Settings +import helium314.keyboard.latin.utils.checkTimestampFormat import helium314.keyboard.latin.utils.prefs import helium314.keyboard.settings.NextScreenIcon import helium314.keyboard.settings.SettingsContainer @@ -45,6 +47,7 @@ import helium314.keyboard.settings.Theme import helium314.keyboard.settings.dialogs.TextInputDialog import helium314.keyboard.settings.preferences.BackupRestorePreference import helium314.keyboard.settings.preferences.LoadGestureLibPreference +import helium314.keyboard.settings.preferences.TextInputPreference import helium314.keyboard.settings.previewDark @Composable @@ -66,10 +69,12 @@ fun AdvancedSettingsScreen( Settings.PREF_ENABLE_EMOJI_ALT_PHYSICAL_KEY, if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) Settings.PREF_SHOW_SETUP_WIZARD_ICON else null, Settings.PREF_ABC_AFTER_SYMBOL_SPACE, + Settings.PREF_ABC_AFTER_NUMPAD_SPACE, Settings.PREF_ABC_AFTER_EMOJI, Settings.PREF_ABC_AFTER_CLIP, Settings.PREF_CUSTOM_CURRENCY_KEY, Settings.PREF_MORE_POPUP_KEYS, + Settings.PREF_TIMESTAMP_FORMAT, SettingsWithoutKey.BACKUP_RESTORE, if (BuildConfig.DEBUG || prefs.getBoolean(DebugSettings.PREF_SHOW_DEBUG_SETTINGS, Defaults.PREF_SHOW_DEBUG_SETTINGS)) SettingsWithoutKey.DEBUG_SETTINGS else null, @@ -154,6 +159,11 @@ fun createAdvancedSettings(context: Context) = listOf( { SwitchPreference(it, Defaults.PREF_ABC_AFTER_SYMBOL_SPACE) }, + Setting(context, Settings.PREF_ABC_AFTER_NUMPAD_SPACE, + R.string.switch_keyboard_after, R.string.after_numpad_and_space) + { + SwitchPreference(it, Defaults.PREF_ABC_AFTER_NUMPAD_SPACE) + }, Setting(context, Settings.PREF_ABC_AFTER_EMOJI, R.string.switch_keyboard_after, R.string.after_emoji) { SwitchPreference(it, Defaults.PREF_ABC_AFTER_EMOJI) }, @@ -189,6 +199,9 @@ fun createAdvancedSettings(context: Context) = listOf( Setting(context, SettingsWithoutKey.BACKUP_RESTORE, R.string.backup_restore_title) { BackupRestorePreference(it) }, + Setting(context, Settings.PREF_TIMESTAMP_FORMAT, R.string.timestamp_format_title) { + TextInputPreference(it, Defaults.PREF_TIMESTAMP_FORMAT) { checkTimestampFormat(it) } + }, Setting(context, SettingsWithoutKey.DEBUG_SETTINGS, R.string.debug_settings_title) { Preference( name = it.title, @@ -196,6 +209,7 @@ fun createAdvancedSettings(context: Context) = listOf( ) { NextScreenIcon() } }, Setting(context, Settings.PREF_EMOJI_MAX_SDK, R.string.prefs_key_emoji_max_sdk) { setting -> + val ctx = LocalContext.current SliderPreference( name = setting.title, key = setting.key, @@ -221,7 +235,10 @@ fun createAdvancedSettings(context: Context) = listOf( else -> "version unknown" } }, - onValueChanged = { KeyboardSwitcher.getInstance().setThemeNeedsReload() } + onConfirmed = { + SupportedEmojis.load(ctx) + KeyboardSwitcher.getInstance().setThemeNeedsReload() + } ) }, Setting(context, Settings.PREF_URL_DETECTION, R.string.url_detection_title, R.string.url_detection_summary) { diff --git a/app/src/main/java/helium314/keyboard/settings/screens/AppearanceScreen.kt b/app/src/main/java/helium314/keyboard/settings/screens/AppearanceScreen.kt index f8a43ca25..016db3f0b 100644 --- a/app/src/main/java/helium314/keyboard/settings/screens/AppearanceScreen.kt +++ b/app/src/main/java/helium314/keyboard/settings/screens/AppearanceScreen.kt @@ -4,7 +4,6 @@ package helium314.keyboard.settings.screens import android.content.Context import android.os.Build import androidx.compose.material3.Surface -import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue @@ -35,10 +34,10 @@ import helium314.keyboard.settings.preferences.SwitchPreference import helium314.keyboard.settings.Theme import helium314.keyboard.settings.dialogs.ColorThemePickerDialog import helium314.keyboard.settings.dialogs.CustomizeIconsDialog -import helium314.keyboard.settings.dialogs.TextInputDialog import helium314.keyboard.settings.initPreview import helium314.keyboard.settings.preferences.BackgroundImagePref import helium314.keyboard.settings.preferences.CustomFontPreference +import helium314.keyboard.settings.preferences.TextInputPreference import helium314.keyboard.settings.previewDark @Composable @@ -82,6 +81,9 @@ fun AppearanceScreen( SettingsWithoutKey.CUSTOM_FONT, Settings.PREF_FONT_SCALE, Settings.PREF_EMOJI_FONT_SCALE, + Settings.PREF_EMOJI_KEY_FIT, + if (prefs.getInt(Settings.PREF_EMOJI_MAX_SDK, Defaults.PREF_EMOJI_MAX_SDK) >= 24) + Settings.PREF_EMOJI_SKIN_TONE else null, ) SearchSettingsScreen( onClickBack = onClickBack, @@ -263,26 +265,8 @@ fun createAppearanceSettings(context: Context) = listOf( description = { "${(100 * it).toInt()}%" } ) { KeyboardSwitcher.getInstance().setThemeNeedsReload() } }, - Setting(context, Settings.PREF_SPACE_BAR_TEXT, R.string.prefs_space_bar_text) { setting -> - var showDialog by rememberSaveable { mutableStateOf(false) } - val prefs = LocalContext.current.prefs() - Preference( - name = setting.title, - onClick = { showDialog = true }, - description = prefs.getString(setting.key, Defaults.PREF_SPACE_BAR_TEXT)?.takeIf { it.isNotEmpty() } - ) - if (showDialog) { - TextInputDialog( - onDismissRequest = { showDialog = false }, - onConfirmed = { - prefs.edit().putString(setting.key, it).apply() - KeyboardSwitcher.getInstance().setThemeNeedsReload() - }, - initialText = prefs.getString(setting.key, Defaults.PREF_SPACE_BAR_TEXT) ?: "", - title = { Text(setting.title) }, - checkTextValid = { true } - ) - } + Setting(context, Settings.PREF_SPACE_BAR_TEXT, R.string.prefs_space_bar_text) { + TextInputPreference(it, Defaults.PREF_SPACE_BAR_TEXT) }, Setting(context, SettingsWithoutKey.CUSTOM_FONT, R.string.custom_font) { CustomFontPreference(it) @@ -305,6 +289,20 @@ fun createAppearanceSettings(context: Context) = listOf( description = { "${(100 * it).toInt()}%" } ) { KeyboardSwitcher.getInstance().setThemeNeedsReload() } }, + Setting(context, Settings.PREF_EMOJI_KEY_FIT, R.string.prefs_emoji_key_fit) { + SwitchPreference(it, Defaults.PREF_EMOJI_KEY_FIT) { KeyboardSwitcher.getInstance().setThemeNeedsReload() } + }, + Setting(context, Settings.PREF_EMOJI_SKIN_TONE, R.string.prefs_emoji_skin_tone) { setting -> + val items = listOf( + stringResource(R.string.prefs_emoji_skin_tone_neutral) to "", + "\uD83C\uDFFB" to "\uD83C\uDFFB", + "\uD83C\uDFFC" to "\uD83C\uDFFC", + "\uD83C\uDFFD" to "\uD83C\uDFFD", + "\uD83C\uDFFE" to "\uD83C\uDFFE", + "\uD83C\uDFFF" to "\uD83C\uDFFF" + ) + ListPreference(setting, items, Defaults.PREF_EMOJI_SKIN_TONE) { KeyboardSwitcher.getInstance().setThemeNeedsReload() } + }, ) @Preview diff --git a/app/src/main/java/helium314/keyboard/settings/screens/ColorsScreen.kt b/app/src/main/java/helium314/keyboard/settings/screens/ColorsScreen.kt index 5d2a46f12..976a17800 100644 --- a/app/src/main/java/helium314/keyboard/settings/screens/ColorsScreen.kt +++ b/app/src/main/java/helium314/keyboard/settings/screens/ColorsScreen.kt @@ -58,6 +58,7 @@ import helium314.keyboard.settings.CloseIcon import helium314.keyboard.settings.SearchScreen import helium314.keyboard.settings.SettingsActivity import helium314.keyboard.settings.Theme +import helium314.keyboard.settings.contentTextDirectionStyle import helium314.keyboard.settings.dialogs.ColorPickerDialog import helium314.keyboard.settings.previewDark import kotlinx.serialization.Serializable @@ -70,6 +71,14 @@ fun ColorsScreen( onClickBack: () -> Unit ) { val ctx = LocalContext.current + val prefs = ctx.prefs() + val b = (ctx.getActivity() as? SettingsActivity)?.prefChanged?.collectAsState() + if ((b?.value ?: 0) < 0) + Log.v("irrelevant", "stupid way to trigger recomposition on preference change") + + val themeName = theme ?: if (isNight) prefs.getString(Settings.PREF_THEME_COLORS_NIGHT, Defaults.PREF_THEME_COLORS_NIGHT)!! + else prefs.getString(Settings.PREF_THEME_COLORS, Defaults.PREF_THEME_COLORS)!! + var newThemeName by rememberSaveable(stateSaver = TextFieldValue.Saver) { mutableStateOf(TextFieldValue(themeName)) } // is there really no better way of only setting forceOpposite while the screen is shown (and not paused)? // lifecycle stuff is weird, there is no pause and similar when activity is paused @@ -82,21 +91,14 @@ fun ColorsScreen( val lifecycleState by lifecycleOwner.lifecycle.currentStateFlow.collectAsState() LaunchedEffect(lifecycleState) { if (lifecycleState == Lifecycle.State.RESUMED) { - (ctx.getActivity() as? SettingsActivity)?.setForceTheme(theme, isNight) + (ctx.getActivity() as? SettingsActivity)?.setForceTheme(newThemeName.text, isNight) } } - val prefs = ctx.prefs() - val b = (ctx.getActivity() as? SettingsActivity)?.prefChanged?.collectAsState() - if ((b?.value ?: 0) < 0) - Log.v("irrelevant", "stupid way to trigger recomposition on preference change") - - val themeName = theme ?: if (isNight) prefs.getString(Settings.PREF_THEME_COLORS_NIGHT, Defaults.PREF_THEME_COLORS_NIGHT)!! - else prefs.getString(Settings.PREF_THEME_COLORS, Defaults.PREF_THEME_COLORS)!! - val moreColors = KeyboardTheme.readUserMoreColors(prefs, themeName) - val userColors = KeyboardTheme.readUserColors(prefs, themeName) + val moreColors = KeyboardTheme.readUserMoreColors(prefs, newThemeName.text) + val userColors = KeyboardTheme.readUserColors(prefs, newThemeName.text) val shownColors = if (moreColors == 2) { - val allColors = KeyboardTheme.readUserAllColors(prefs, themeName) + val allColors = KeyboardTheme.readUserAllColors(prefs, newThemeName.text) ColorType.entries.map { ColorSetting(it.name, null, allColors[it] ?: it.default()) } @@ -113,12 +115,11 @@ fun ColorsScreen( fun ColorSetting.displayColor() = if (auto == true) KeyboardTheme.determineUserColor(userColors, ctx, name, isNight) else color ?: KeyboardTheme.determineUserColor(userColors, ctx, name, isNight) - var newThemeName by rememberSaveable(stateSaver = TextFieldValue.Saver) { mutableStateOf(TextFieldValue(themeName)) } var chosenColorString: String by rememberSaveable { mutableStateOf("") } val chosenColor = runCatching { Json.decodeFromString(chosenColorString) }.getOrNull() - val saveLauncher = rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) { - if (it.resultCode != Activity.RESULT_OK) return@rememberLauncherForActivityResult - val uri = it.data?.data ?: return@rememberLauncherForActivityResult + val saveLauncher = rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> + if (result.resultCode != Activity.RESULT_OK) return@rememberLauncherForActivityResult + val uri = result.data?.data ?: return@rememberLauncherForActivityResult ctx.getActivity()?.contentResolver?.openOutputStream(uri)?.writer()?.use { it.write(getColorString(prefs, newThemeName.text)) } } SearchScreen( @@ -129,14 +130,17 @@ fun ColorsScreen( value = nameField, onValueChange = { nameValid = KeyboardTheme.renameUserColors(newThemeName.text, it.text, prefs) - if (nameValid) + if (nameValid) { newThemeName = it + SettingsActivity.forceTheme = newThemeName.text + } nameField = it }, isError = !nameValid, // supportingText = { if (!nameValid) Text(stringResource(R.string.name_invalid)) } // todo: this is cutting off bottom half of the actual text... trailingIcon = { if (!nameValid) CloseIcon(R.string.name_invalid) }, singleLine = true, + textStyle = contentTextDirectionStyle, ) }, menu = listOf( @@ -193,11 +197,11 @@ fun ColorsScreen( } } if (colorSetting.auto != null) - Switch(colorSetting.auto, onCheckedChange = { - val oldUserColors = KeyboardTheme.readUserColors(prefs, themeName) - val newUserColors = (oldUserColors + ColorSetting(colorSetting.name, it, colorSetting.color)) + Switch(colorSetting.auto, onCheckedChange = { checked -> + val oldUserColors = KeyboardTheme.readUserColors(prefs, newThemeName.text) + val newUserColors = (oldUserColors + ColorSetting(colorSetting.name, checked, colorSetting.color)) .reversed().distinctBy { it.displayName } - KeyboardTheme.writeUserColors(prefs, themeName, newUserColors) + KeyboardTheme.writeUserColors(prefs, newThemeName.text, newUserColors) }) } } @@ -207,16 +211,16 @@ fun ColorsScreen( onDismissRequest = { chosenColorString = "" }, initialColor = chosenColor.displayColor(), title = chosenColor.displayName, - ) { + ) { color -> if (moreColors == 2) { - val oldColors = KeyboardTheme.readUserAllColors(prefs, themeName) - oldColors[ColorType.valueOf(chosenColor.name)] = it - KeyboardTheme.writeUserAllColors(prefs, themeName, oldColors) + val oldColors = KeyboardTheme.readUserAllColors(prefs, newThemeName.text) + oldColors[ColorType.valueOf(chosenColor.name)] = color + KeyboardTheme.writeUserAllColors(prefs, newThemeName.text, oldColors) } else { - val oldUserColors = KeyboardTheme.readUserColors(prefs, themeName) - val newUserColors = (oldUserColors + ColorSetting(chosenColor.name, false, it)) + val oldUserColors = KeyboardTheme.readUserColors(prefs, newThemeName.text) + val newUserColors = (oldUserColors + ColorSetting(chosenColor.name, false, color)) .reversed().distinctBy { it.displayName } - KeyboardTheme.writeUserColors(prefs, themeName, newUserColors) + KeyboardTheme.writeUserColors(prefs, newThemeName.text, newUserColors) } } } diff --git a/app/src/main/java/helium314/keyboard/settings/screens/DictionaryScreen.kt b/app/src/main/java/helium314/keyboard/settings/screens/DictionaryScreen.kt index 77d1b9b42..dc64cadd8 100644 --- a/app/src/main/java/helium314/keyboard/settings/screens/DictionaryScreen.kt +++ b/app/src/main/java/helium314/keyboard/settings/screens/DictionaryScreen.kt @@ -55,7 +55,7 @@ fun DictionaryScreen( ) { val ctx = LocalContext.current val enabledLanguages = SubtypeSettings.getEnabledSubtypes(true).map { it.locale().language } - val cachedDictFolders = DictionaryInfoUtils.getCachedDirectoryList(ctx).orEmpty().map { it.name } + val cachedDictFolders = DictionaryInfoUtils.getCacheDirectories(ctx).map { it.name } val comparer = compareBy({ it.language !in enabledLanguages }, { it.toLanguageTag() !in cachedDictFolders}, { it.displayName }) val dictionaryLocales = getDictionaryLocales(ctx).sortedWith(comparer).toMutableList() dictionaryLocales.add(0, Locale(SubtypeLocaleUtils.NO_LANGUAGE)) @@ -69,7 +69,7 @@ fun DictionaryScreen( if (term.isBlank()) dictionaryLocales else dictionaryLocales.filter { loc -> loc.language != SubtypeLocaleUtils.NO_LANGUAGE - && loc.localizedDisplayName(ctx).replace("(", "") + && loc.localizedDisplayName(ctx.resources).replace("(", "") .splitOnWhitespace().any { it.startsWith(term, true) } } }, @@ -98,7 +98,7 @@ fun DictionaryScreen( val types = dicts.mapTo(mutableListOf()) { it.name.substringBefore("_${DictionaryInfoUtils.USER_DICTIONARY_SUFFIX}") } if (hasInternal && !types.contains(Dictionary.TYPE_MAIN)) types.add(0, stringResource(R.string.internal_dictionary_summary)) - Text(locale.localizedDisplayName(ctx)) + Text(locale.localizedDisplayName(ctx.resources)) Text( types.joinToString(", "), style = MaterialTheme.typography.bodyMedium, @@ -142,8 +142,8 @@ fun DictionaryScreen( fun getUserAndInternalDictionaries(context: Context, locale: Locale): Pair, Boolean> { val userDicts = mutableListOf() var hasInternalDict = false - val userLocaleDir = File(DictionaryInfoUtils.getCacheDirectoryForLocale(locale, context)) - if (userLocaleDir.exists() && userLocaleDir.isDirectory) { + val userLocaleDir = DictionaryInfoUtils.getCacheDirectoryForLocale(locale, context)?.let { File(it) } + if (userLocaleDir?.exists() == true && userLocaleDir.isDirectory) { userLocaleDir.listFiles()?.forEach { if (it.name.endsWith(DictionaryInfoUtils.USER_DICTIONARY_SUFFIX)) userDicts.add(it) @@ -155,7 +155,7 @@ fun getUserAndInternalDictionaries(context: Context, locale: Locale): Pair Unit, ) { val ctx = LocalContext.current - var sortedSubtypes by remember { mutableStateOf(getSortedSubtypes(ctx)) } + val sortedSubtypes by remember { mutableStateOf(getSortedSubtypes(ctx)) } val prefs = ctx.prefs() val b = (LocalContext.current.getActivity() as? SettingsActivity)?.prefChanged?.collectAsState() if ((b?.value ?: 0) < 0) Log.v("irrelevant", "stupid way to trigger recomposition on preference change") - var selectedSubtype: String? by rememberSaveable { mutableStateOf(null) } val enabledSubtypes = SubtypeSettings.getEnabledSubtypes() SearchScreen( onClickBack = onClickBack, @@ -78,7 +75,7 @@ fun LanguageScreen( }, filteredItems = { term -> sortedSubtypes.filter { - it.displayName(ctx).replace("(", "") + it.displayName().replace("(", "") .splitOnWhitespace().any { it.startsWith(term, true) } } }, @@ -87,15 +84,17 @@ fun LanguageScreen( verticalAlignment = Alignment.CenterVertically, modifier = Modifier .fillMaxWidth() - .clickable { selectedSubtype = item.toSettingsSubtype().toPref() } + .clickable { + SettingsDestination.navigateTo(SettingsDestination.Subtype + item.toSettingsSubtype().toPref()) + } .padding(vertical = 6.dp, horizontal = 16.dp) ) { var showNoDictDialog by remember { mutableStateOf(false) } Column(modifier = Modifier.weight(1f)) { - Text(item.displayName(ctx), style = MaterialTheme.typography.bodyLarge) + Text(item.displayName(), style = MaterialTheme.typography.bodyLarge) val description = if (SubtypeSettings.isAdditionalSubtype(item)) { val secondaryLocales = item.getExtraValueOf(ExtraValue.SECONDARY_LOCALES)?.split(Separators.KV) - ?.joinToString(", ") { it.constructLocale().localizedDisplayName(ctx) } + ?.joinToString(", ") { it.constructLocale().localizedDisplayName(ctx.resources) } stringResource(R.string.custom_subtype) + (secondaryLocales?.let { "\n$it" } ?: "") } else null if (description != null) @@ -119,19 +118,6 @@ fun LanguageScreen( } } ) - if (selectedSubtype != null) { - val oldSubtype = selectedSubtype!!.toSettingsSubtype() - SubtypeDialog( - onDismissRequest = { - selectedSubtype = null - sortedSubtypes = getSortedSubtypes(ctx) - }, - onConfirmed = { - SubtypeUtilsAdditional.changeAdditionalSubtype(oldSubtype, it, ctx) - }, - initialSubtype = oldSubtype - ) - } } private fun dictsAvailable(locale: Locale, context: Context): Boolean { @@ -143,7 +129,7 @@ private fun dictsAvailable(locale: Locale, context: Context): Boolean { private fun getSortedSubtypes(context: Context): List { val systemLocales = SubtypeSettings.getSystemLocales() val enabledSubtypes = SubtypeSettings.getEnabledSubtypes(true) - val localesWithDictionary = DictionaryInfoUtils.getCachedDirectoryList(context)?.mapNotNull { dir -> + val localesWithDictionary = DictionaryInfoUtils.getCacheDirectories(context)?.mapNotNull { dir -> if (!dir.isDirectory) return@mapNotNull null if (dir.list()?.any { it.endsWith(DictionaryInfoUtils.USER_DICTIONARY_SUFFIX) } == true) @@ -167,7 +153,7 @@ private fun getSortedSubtypes(context: Context): List { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) it.languageTag == SubtypeLocaleUtils.NO_LANGUAGE else it.locale == SubtypeLocaleUtils.NO_LANGUAGE }, - { it.displayName(context) } + { it.displayName() } ) return SubtypeSettings.getAllAvailableSubtypes().sortedWith(subtypeSortComparator) } diff --git a/app/src/main/java/helium314/keyboard/settings/screens/MainSettingsScreen.kt b/app/src/main/java/helium314/keyboard/settings/screens/MainSettingsScreen.kt index 85fde377a..3d8af0c5a 100644 --- a/app/src/main/java/helium314/keyboard/settings/screens/MainSettingsScreen.kt +++ b/app/src/main/java/helium314/keyboard/settings/screens/MainSettingsScreen.kt @@ -2,8 +2,14 @@ package helium314.keyboard.settings.screens import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.WindowInsetsSides +import androidx.compose.foundation.layout.only +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.safeDrawing import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.Scaffold import androidx.compose.material3.Surface import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier @@ -12,13 +18,13 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import helium314.keyboard.latin.R import helium314.keyboard.latin.utils.JniUtils +import helium314.keyboard.latin.utils.SubtypeLocaleUtils.displayName import helium314.keyboard.latin.utils.SubtypeSettings -import helium314.keyboard.latin.utils.displayName import helium314.keyboard.settings.NextScreenIcon -import helium314.keyboard.settings.preferences.Preference import helium314.keyboard.settings.SearchSettingsScreen import helium314.keyboard.settings.Theme import helium314.keyboard.settings.initPreview +import helium314.keyboard.settings.preferences.Preference import helium314.keyboard.settings.previewDark @Composable @@ -35,66 +41,69 @@ fun MainSettingsScreen( onClickDictionaries: () -> Unit, onClickBack: () -> Unit, ) { - val ctx = LocalContext.current SearchSettingsScreen( onClickBack = onClickBack, title = stringResource(R.string.ime_settings), settings = emptyList(), ) { val enabledSubtypes = SubtypeSettings.getEnabledSubtypes(true) - Column(Modifier.verticalScroll(rememberScrollState())) { - Preference( - name = stringResource(R.string.language_and_layouts_title), - description = enabledSubtypes.joinToString(", ") { it.displayName(ctx) }, - onClick = onClickLanguage, - icon = R.drawable.ic_settings_languages - ) { NextScreenIcon() } - Preference( - name = stringResource(R.string.settings_screen_preferences), - onClick = onClickPreferences, - icon = R.drawable.ic_settings_preferences - ) { NextScreenIcon() } - Preference( - name = stringResource(R.string.settings_screen_appearance), - onClick = onClickAppearance, - icon = R.drawable.ic_settings_appearance - ) { NextScreenIcon() } - Preference( - name = stringResource(R.string.settings_screen_toolbar), - onClick = onClickToolbar, - icon = R.drawable.ic_settings_toolbar - ) { NextScreenIcon() } - if (JniUtils.sHaveGestureLib) + Scaffold(contentWindowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Bottom)) { innerPadding -> + Column( + Modifier.verticalScroll(rememberScrollState()).then(Modifier.padding(innerPadding)) + ) { Preference( - name = stringResource(R.string.settings_screen_gesture), - onClick = onClickGestureTyping, - icon = R.drawable.ic_settings_gesture + name = stringResource(R.string.language_and_layouts_title), + description = enabledSubtypes.joinToString(", ") { it.displayName() }, + onClick = onClickLanguage, + icon = R.drawable.ic_settings_languages ) { NextScreenIcon() } - Preference( - name = stringResource(R.string.settings_screen_correction), - onClick = onClickTextCorrection, - icon = R.drawable.ic_settings_correction - ) { NextScreenIcon() } - Preference( - name = stringResource(R.string.settings_screen_secondary_layouts), - onClick = onClickLayouts, - icon = R.drawable.ic_ime_switcher - ) { NextScreenIcon() } - Preference( - name = stringResource(R.string.dictionary_settings_category), - onClick = onClickDictionaries, - icon = R.drawable.ic_dictionary - ) { NextScreenIcon() } - Preference( - name = stringResource(R.string.settings_screen_advanced), - onClick = onClickAdvanced, - icon = R.drawable.ic_settings_advanced - ) { NextScreenIcon() } - Preference( - name = stringResource(R.string.settings_screen_about), - onClick = onClickAbout, - icon = R.drawable.ic_settings_about - ) { NextScreenIcon() } + Preference( + name = stringResource(R.string.settings_screen_preferences), + onClick = onClickPreferences, + icon = R.drawable.ic_settings_preferences + ) { NextScreenIcon() } + Preference( + name = stringResource(R.string.settings_screen_appearance), + onClick = onClickAppearance, + icon = R.drawable.ic_settings_appearance + ) { NextScreenIcon() } + Preference( + name = stringResource(R.string.settings_screen_toolbar), + onClick = onClickToolbar, + icon = R.drawable.ic_settings_toolbar + ) { NextScreenIcon() } + if (JniUtils.sHaveGestureLib) + Preference( + name = stringResource(R.string.settings_screen_gesture), + onClick = onClickGestureTyping, + icon = R.drawable.ic_settings_gesture + ) { NextScreenIcon() } + Preference( + name = stringResource(R.string.settings_screen_correction), + onClick = onClickTextCorrection, + icon = R.drawable.ic_settings_correction + ) { NextScreenIcon() } + Preference( + name = stringResource(R.string.settings_screen_secondary_layouts), + onClick = onClickLayouts, + icon = R.drawable.ic_ime_switcher + ) { NextScreenIcon() } + Preference( + name = stringResource(R.string.dictionary_settings_category), + onClick = onClickDictionaries, + icon = R.drawable.ic_dictionary + ) { NextScreenIcon() } + Preference( + name = stringResource(R.string.settings_screen_advanced), + onClick = onClickAdvanced, + icon = R.drawable.ic_settings_advanced + ) { NextScreenIcon() } + Preference( + name = stringResource(R.string.settings_screen_about), + onClick = onClickAbout, + icon = R.drawable.ic_settings_about + ) { NextScreenIcon() } + } } } } diff --git a/app/src/main/java/helium314/keyboard/settings/screens/PersonalDictionaryScreen.kt b/app/src/main/java/helium314/keyboard/settings/screens/PersonalDictionaryScreen.kt index a7bb82f2c..7c0d88b3e 100644 --- a/app/src/main/java/helium314/keyboard/settings/screens/PersonalDictionaryScreen.kt +++ b/app/src/main/java/helium314/keyboard/settings/screens/PersonalDictionaryScreen.kt @@ -11,6 +11,7 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.safeDrawingPadding import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material3.ExtendedFloatingActionButton @@ -177,6 +178,7 @@ fun PersonalDictionaryScreen( text = { Text(stringResource(R.string.user_dict_add_word_button)) }, icon = { Icon(painter = painterResource(R.drawable.ic_edit), stringResource(R.string.user_dict_add_word_button)) }, modifier = Modifier.wrapContentSize(Alignment.BottomEnd).padding(all = 12.dp) + .then(Modifier.safeDrawingPadding()) ) } @@ -241,7 +243,7 @@ private fun getSpecificallySortedLocales(firstLocale: Locale?): List { } fun Locale?.getLocaleDisplayNameForUserDictSettings(context: Context) = - this?.localizedDisplayName(context) ?: context.resources.getString(R.string.user_dict_settings_all_languages) + this?.localizedDisplayName(context.resources) ?: context.resources.getString(R.string.user_dict_settings_all_languages) // weight is frequency but different name towards user private data class Word(val word: String, val shortcut: String?, val weight: Int?) diff --git a/app/src/main/java/helium314/keyboard/settings/screens/PreferencesScreen.kt b/app/src/main/java/helium314/keyboard/settings/screens/PreferencesScreen.kt index 17486bae8..272757201 100644 --- a/app/src/main/java/helium314/keyboard/settings/screens/PreferencesScreen.kt +++ b/app/src/main/java/helium314/keyboard/settings/screens/PreferencesScreen.kt @@ -46,6 +46,7 @@ fun PreferencesScreen( Settings.PREF_POPUP_KEYS_LABELS_ORDER else null, Settings.PREF_POPUP_KEYS_ORDER, Settings.PREF_SHOW_POPUP_HINTS, + Settings.PREF_SHOW_TLD_POPUP_KEYS, Settings.PREF_POPUP_ON, if (AudioAndHapticFeedbackManager.getInstance().hasVibrator()) Settings.PREF_VIBRATE_ON else null, @@ -89,6 +90,12 @@ fun createPreferencesSettings(context: Context) = listOf( Setting(context, Settings.PREF_POPUP_KEYS_ORDER, R.string.popup_order) { ReorderSwitchPreference(it, Defaults.PREF_POPUP_KEYS_ORDER) }, + Setting( + context, Settings.PREF_SHOW_TLD_POPUP_KEYS, R.string.show_tld_popup_keys, + R.string.show_tld_popup_keys_summary + ) { + SwitchPreference(it, Defaults.PREF_SHOW_TLD_POPUP_KEYS) { KeyboardSwitcher.getInstance().setThemeNeedsReload() } + }, Setting(context, Settings.PREF_SHOW_POPUP_HINTS, R.string.show_popup_hints, R.string.show_popup_hints_summary) { SwitchPreference(it, Defaults.PREF_SHOW_POPUP_HINTS) { KeyboardSwitcher.getInstance().setThemeNeedsReload() } }, @@ -110,7 +117,7 @@ fun createPreferencesSettings(context: Context) = listOf( SwitchPreference(it, Defaults.PREF_ENABLE_CLIPBOARD_HISTORY) }, Setting(context, Settings.PREF_SHOW_NUMBER_ROW, R.string.number_row, R.string.number_row_summary) { - SwitchPreference(it, Defaults.PREF_SHOW_NUMBER_ROW) { KeyboardSwitcher.getInstance().reloadKeyboard() } + SwitchPreference(it, Defaults.PREF_SHOW_NUMBER_ROW) { KeyboardSwitcher.getInstance().setThemeNeedsReload() } }, Setting(context, Settings.PREF_LOCALIZED_NUMBER_ROW, R.string.localized_number_row, R.string.localized_number_row_summary) { SwitchPreference(it, Defaults.PREF_LOCALIZED_NUMBER_ROW) { @@ -149,10 +156,10 @@ fun createPreferencesSettings(context: Context) = listOf( key = setting.key, default = Defaults.PREF_CLIPBOARD_HISTORY_RETENTION_TIME, description = { - if (it < 0) stringResource(R.string.settings_no_limit) + if (it > 120) stringResource(R.string.settings_no_limit) else stringResource(R.string.abbreviation_unit_minutes, it.toString()) }, - range = -1f..120f, + range = 1f..121f, ) }, Setting(context, Settings.PREF_VIBRATION_DURATION_SETTINGS, R.string.prefs_keypress_vibration_duration_settings) { setting -> @@ -165,7 +172,7 @@ fun createPreferencesSettings(context: Context) = listOf( else stringResource(R.string.abbreviation_unit_milliseconds, it.toString()) }, range = -1f..100f, - onValueChanged = { AudioAndHapticFeedbackManager.getInstance().vibrate(it.toLong()) } + onValueChanged = { it?.let { AudioAndHapticFeedbackManager.getInstance().vibrate(it.toLong()) } } ) }, Setting(context, Settings.PREF_KEYPRESS_SOUND_VOLUME, R.string.prefs_keypress_sound_volume_settings) { setting -> @@ -179,7 +186,7 @@ fun createPreferencesSettings(context: Context) = listOf( else (it * 100).toInt().toString() }, range = -0.01f..1f, - onValueChanged = { audioManager.playSoundEffect(AudioManager.FX_KEYPRESS_STANDARD, it) } + onValueChanged = { it?.let { audioManager.playSoundEffect(AudioManager.FX_KEYPRESS_STANDARD, it) } } ) }, ) diff --git a/app/src/main/java/helium314/keyboard/settings/dialogs/SubtypeDialog.kt b/app/src/main/java/helium314/keyboard/settings/screens/SubtypeScreen.kt similarity index 65% rename from app/src/main/java/helium314/keyboard/settings/dialogs/SubtypeDialog.kt rename to app/src/main/java/helium314/keyboard/settings/screens/SubtypeScreen.kt index 7da713ec3..7387974fb 100644 --- a/app/src/main/java/helium314/keyboard/settings/dialogs/SubtypeDialog.kt +++ b/app/src/main/java/helium314/keyboard/settings/screens/SubtypeScreen.kt @@ -1,19 +1,24 @@ -// SPDX-License-Identifier: GPL-3.0-only -package helium314.keyboard.settings.dialogs +package helium314.keyboard.settings.screens import android.content.Context -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.WindowInsetsSides import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.only import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.safeDrawing +import androidx.compose.foundation.layout.widthIn import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Surface import androidx.compose.material3.Switch import androidx.compose.material3.Text import androidx.compose.material3.TextButton @@ -58,6 +63,7 @@ import helium314.keyboard.latin.utils.Log import helium314.keyboard.latin.utils.ScriptUtils import helium314.keyboard.latin.utils.ScriptUtils.script import helium314.keyboard.latin.utils.SubtypeLocaleUtils +import helium314.keyboard.latin.utils.SubtypeLocaleUtils.displayName import helium314.keyboard.latin.utils.SubtypeSettings import helium314.keyboard.latin.utils.SubtypeUtilsAdditional import helium314.keyboard.latin.utils.appendLink @@ -68,22 +74,27 @@ import helium314.keyboard.latin.utils.getStringResourceOrName import helium314.keyboard.latin.utils.mainLayoutName import helium314.keyboard.latin.utils.prefs import helium314.keyboard.settings.DefaultButton +import helium314.keyboard.settings.DeleteButton import helium314.keyboard.settings.DropDownField +import helium314.keyboard.settings.SearchScreen import helium314.keyboard.settings.SettingsActivity import helium314.keyboard.settings.Theme import helium314.keyboard.settings.WithSmallTitle +import helium314.keyboard.settings.dialogs.ConfirmationDialog +import helium314.keyboard.settings.dialogs.LayoutEditDialog +import helium314.keyboard.settings.dialogs.ListPickerDialog +import helium314.keyboard.settings.dialogs.MultiListPickerDialog +import helium314.keyboard.settings.dialogs.ReorderDialog import helium314.keyboard.settings.initPreview import helium314.keyboard.settings.layoutFilePicker import helium314.keyboard.settings.layoutIntent import helium314.keyboard.settings.previewDark -import helium314.keyboard.settings.screens.GetIcon import java.util.Locale @Composable -fun SubtypeDialog( - onDismissRequest: () -> Unit, +fun SubtypeScreen( initialSubtype: SettingsSubtype, - onConfirmed: (SettingsSubtype) -> Unit, + onClickBack: () -> Unit, ) { val ctx = LocalContext.current val prefs = ctx.prefs() @@ -92,7 +103,10 @@ fun SubtypeDialog( Log.v("irrelevant", "stupid way to trigger recomposition on preference change") var currentSubtypeString by rememberSaveable { mutableStateOf(initialSubtype.toPref()) } val currentSubtype = currentSubtypeString.toSettingsSubtype() - fun setCurrentSubtype(subtype: SettingsSubtype) { currentSubtypeString = subtype.toPref() } + fun setCurrentSubtype(subtype: SettingsSubtype) { + SubtypeUtilsAdditional.changeAdditionalSubtype(currentSubtype, subtype, ctx) + currentSubtypeString = subtype.toPref() + } LaunchedEffect(currentSubtypeString) { if (ScriptUtils.scriptSupportsUppercase(currentSubtype.locale)) return@LaunchedEffect // update the noShiftKey extra value @@ -120,45 +134,46 @@ fun SubtypeDialog( var showMorePopupsDialog by remember { mutableStateOf(false) } val scrollState = rememberScrollState() val customMainLayouts = LayoutUtilsCustom.getLayoutFiles(LayoutType.MAIN, ctx, currentSubtype.locale).map { it.name } - ThreeButtonAlertDialog( - onDismissRequest = onDismissRequest, - onConfirmed = { onConfirmed(currentSubtype) }, - neutralButtonText = if (initialSubtype.isAdditionalSubtype(prefs)) stringResource(R.string.delete) else null, - onNeutral = { - SubtypeUtilsAdditional.removeAdditionalSubtype(ctx, initialSubtype.toAdditionalSubtype()!!) - SubtypeSettings.removeEnabledSubtype(ctx, initialSubtype.toAdditionalSubtype()!!) - onDismissRequest() - }, - title = { - val mainLayout = initialSubtype.mainLayoutName() ?: SubtypeLocaleUtils.QWERTY - Text(SubtypeLocaleUtils.getDisplayNameInSystemLocale(mainLayout, initialSubtype.locale)) - }, - content = { + SearchScreen( + onClickBack = onClickBack, + icon = { if (currentSubtype.isAdditionalSubtype(prefs)) DeleteButton { + SubtypeUtilsAdditional.removeAdditionalSubtype(ctx, currentSubtype.toAdditionalSubtype()) + SubtypeSettings.removeEnabledSubtype(ctx, currentSubtype.toAdditionalSubtype()) + onClickBack() + } }, + title = { Text(currentSubtype.toAdditionalSubtype().displayName()) }, + itemContent = { }, + filteredItems = { emptyList() } + ) { + Scaffold( + contentWindowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Bottom) + ) { innerPadding -> Column( - modifier = Modifier.verticalScroll(scrollState), + modifier = Modifier.verticalScroll(scrollState).padding(horizontal = 12.dp) + .then(Modifier.padding(innerPadding)), verticalArrangement = Arrangement.spacedBy(8.dp), ) { - MainLayoutRow(initialSubtype, currentSubtype, customMainLayouts) { setCurrentSubtype(it) } + MainLayoutRow(currentSubtype, customMainLayouts) { setCurrentSubtype(it) } if (availableLocalesForScript.size > 1) { WithSmallTitle(stringResource(R.string.secondary_locale)) { TextButton(onClick = { showSecondaryLocaleDialog = true }) { val text = getSecondaryLocales(currentSubtype.extraValues).joinToString(", ") { - it.localizedDisplayName(ctx) - }.ifEmpty { stringResource(R.string.action_none) } - Text(text, Modifier.fillMaxWidth(), style = MaterialTheme.typography.bodyLarge) + it.localizedDisplayName(ctx.resources) + }.ifEmpty { stringResource(R.string.action_none) } + Text(text, Modifier.fillMaxWidth()) } } } Row { TextButton(onClick = { showKeyOrderDialog = true }, Modifier.weight(1f)) - { Text(stringResource(R.string.popup_order), style = MaterialTheme.typography.bodyLarge) } + { Text(stringResource(R.string.popup_order)) } DefaultButton(currentSubtype.getExtraValueOf(ExtraValue.POPUP_ORDER) == null) { setCurrentSubtype(currentSubtype.without(ExtraValue.POPUP_ORDER)) } } Row { TextButton(onClick = { showHintOrderDialog = true }, Modifier.weight(1f)) - { Text(stringResource(R.string.hint_source), style = MaterialTheme.typography.bodyLarge) } + { Text(stringResource(R.string.hint_source)) } DefaultButton(currentSubtype.getExtraValueOf(ExtraValue.HINT_ORDER) == null) { setCurrentSubtype(currentSubtype.without(ExtraValue.HINT_ORDER)) } @@ -166,7 +181,10 @@ fun SubtypeDialog( if (currentSubtype.locale.script() == ScriptUtils.SCRIPT_LATIN) { WithSmallTitle(stringResource(R.string.show_popup_keys_title)) { val explicitValue = currentSubtype.getExtraValueOf(ExtraValue.MORE_POPUPS) - val value = explicitValue ?: prefs.getString(Settings.PREF_MORE_POPUP_KEYS, Defaults.PREF_MORE_POPUP_KEYS)!! + val value = explicitValue ?: prefs.getString( + Settings.PREF_MORE_POPUP_KEYS, + Defaults.PREF_MORE_POPUP_KEYS + )!! Row { TextButton(onClick = { showMorePopupsDialog = true }, Modifier.weight(1f)) { Text(stringResource(morePopupKeysResId(value))) } @@ -181,7 +199,10 @@ fun SubtypeDialog( val checked = currentSubtype.getExtraValueOf(ExtraValue.LOCALIZED_NUMBER_ROW)?.toBoolean() Text(stringResource(R.string.localized_number_row), Modifier.weight(1f)) Switch( - checked = checked ?: prefs.getBoolean(Settings.PREF_LOCALIZED_NUMBER_ROW, Defaults.PREF_LOCALIZED_NUMBER_ROW), + checked = checked ?: prefs.getBoolean( + Settings.PREF_LOCALIZED_NUMBER_ROW, + Defaults.PREF_LOCALIZED_NUMBER_ROW + ), onCheckedChange = { setCurrentSubtype(currentSubtype.with(ExtraValue.LOCALIZED_NUMBER_ROW, it.toString())) } @@ -192,7 +213,10 @@ fun SubtypeDialog( } } HorizontalDivider() - Text(stringResource(R.string.settings_screen_secondary_layouts), style = MaterialTheme.typography.titleMedium) + Text( + stringResource(R.string.settings_screen_secondary_layouts), + style = MaterialTheme.typography.titleMedium + ) LayoutType.entries.forEach { type -> if (type == LayoutType.MAIN) return@forEach WithSmallTitle(stringResource(type.displayNameId)) { @@ -206,20 +230,31 @@ fun SubtypeDialog( onSelected = { setCurrentSubtype(currentSubtype.withLayout(type, it)) }, - extraButton = { DefaultButton(explicitLayout == null) { - setCurrentSubtype(currentSubtype.withoutLayout(type)) - } }, + extraButton = { + DefaultButton(explicitLayout == null) { + setCurrentSubtype(currentSubtype.withoutLayout(type)) + } + }, ) { - val displayName = if (LayoutUtilsCustom.isCustomLayout(it)) LayoutUtilsCustom.getDisplayName(it) - else it.getStringResourceOrName("layout_", ctx) + val displayName = + if (LayoutUtilsCustom.isCustomLayout(it)) LayoutUtilsCustom.getDisplayName(it) + else it.getStringResourceOrName("layout_", ctx) var showLayoutEditDialog by remember { mutableStateOf(false) } Row( horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically, modifier = Modifier.fillMaxWidth() ) { - Text(displayName, Modifier.padding(end = 8.dp)) + Text(displayName) if (LayoutUtilsCustom.isCustomLayout(it)) - Icon(painterResource(R.drawable.ic_edit), stringResource(R.string.edit_layout), Modifier.clickable { showLayoutEditDialog = true }) + IconButton({ + showLayoutEditDialog = true + }) { + Icon( + painterResource(R.drawable.ic_edit), + stringResource(R.string.edit_layout) + ) + } } if (showLayoutEditDialog) LayoutEditDialog( @@ -233,67 +268,74 @@ fun SubtypeDialog( } } } - ) - if (showSecondaryLocaleDialog) - MultiListPickerDialog( - onDismissRequest = { showSecondaryLocaleDialog = false }, - onConfirmed = { locales -> - val newValue = locales.joinToString(Separators.KV) { it.toLanguageTag() } - setCurrentSubtype( - if (newValue.isEmpty()) currentSubtype.without(ExtraValue.SECONDARY_LOCALES) - else currentSubtype.with(ExtraValue.SECONDARY_LOCALES, newValue) - ) - }, - title = { Text(stringResource(R.string.locales_with_dict)) }, - items = availableLocalesForScript, - initialSelection = currentSubtype.getExtraValueOf(ExtraValue.SECONDARY_LOCALES) - ?.split(Separators.KV)?.map { it.constructLocale() }.orEmpty(), - getItemName = { it.localizedDisplayName(ctx) } - ) - if (showKeyOrderDialog) { - val setting = currentSubtype.getExtraValueOf(ExtraValue.POPUP_ORDER) - PopupOrderDialog( - onDismissRequest = { showKeyOrderDialog = false }, - initialValue = setting ?: prefs.getString(Settings.PREF_POPUP_KEYS_ORDER, Defaults.PREF_POPUP_KEYS_ORDER)!!, - title = stringResource(R.string.popup_order), - showDefault = setting != null, - onConfirmed = { - setCurrentSubtype( - if (it == null) currentSubtype.without(ExtraValue.POPUP_ORDER) - else currentSubtype.with(ExtraValue.POPUP_ORDER, it) - ) - } - ) - } - if (showHintOrderDialog) { - val setting = currentSubtype.getExtraValueOf(ExtraValue.HINT_ORDER) - PopupOrderDialog( - onDismissRequest = { showHintOrderDialog = false }, - initialValue = setting ?: prefs.getString(Settings.PREF_POPUP_KEYS_LABELS_ORDER, Defaults.PREF_POPUP_KEYS_LABELS_ORDER)!!, - title = stringResource(R.string.hint_source), - showDefault = setting != null, - onConfirmed = { - setCurrentSubtype( - if (it == null) currentSubtype.without(ExtraValue.HINT_ORDER) - else currentSubtype.with(ExtraValue.HINT_ORDER, it) - ) - } - ) - } - if (showMorePopupsDialog) { - val items = listOf(POPUP_KEYS_NORMAL, POPUP_KEYS_MAIN, POPUP_KEYS_MORE, POPUP_KEYS_ALL) - val explicitValue = currentSubtype.getExtraValueOf(ExtraValue.MORE_POPUPS) - val value = explicitValue ?: prefs.getString(Settings.PREF_MORE_POPUP_KEYS, Defaults.PREF_MORE_POPUP_KEYS) - ListPickerDialog( - onDismissRequest = { showMorePopupsDialog = false }, - items = items, - getItemName = { stringResource(morePopupKeysResId(it)) }, - selectedItem = value, - onItemSelected = { setCurrentSubtype(currentSubtype.with(ExtraValue.MORE_POPUPS, it)) } - ) + if (showSecondaryLocaleDialog) + MultiListPickerDialog( + onDismissRequest = { showSecondaryLocaleDialog = false }, + onConfirmed = { locales -> + val newValue = locales.joinToString(Separators.KV) { it.toLanguageTag() } + setCurrentSubtype( + if (newValue.isEmpty()) currentSubtype.without(ExtraValue.SECONDARY_LOCALES) + else currentSubtype.with(ExtraValue.SECONDARY_LOCALES, newValue) + ) + }, + title = { Text(stringResource(R.string.locales_with_dict)) }, + items = availableLocalesForScript, + initialSelection = currentSubtype.getExtraValueOf(ExtraValue.SECONDARY_LOCALES) + ?.split(Separators.KV)?.map { it.constructLocale() }.orEmpty(), + getItemName = { it.localizedDisplayName(ctx.resources) } + ) + if (showKeyOrderDialog) { + val setting = currentSubtype.getExtraValueOf(ExtraValue.POPUP_ORDER) + PopupOrderDialog( + onDismissRequest = { showKeyOrderDialog = false }, + initialValue = setting ?: prefs.getString( + Settings.PREF_POPUP_KEYS_ORDER, + Defaults.PREF_POPUP_KEYS_ORDER + )!!, + title = stringResource(R.string.popup_order), + showDefault = setting != null, + onConfirmed = { + setCurrentSubtype( + if (it == null) currentSubtype.without(ExtraValue.POPUP_ORDER) + else currentSubtype.with(ExtraValue.POPUP_ORDER, it) + ) + } + ) + } + if (showHintOrderDialog) { + val setting = currentSubtype.getExtraValueOf(ExtraValue.HINT_ORDER) + PopupOrderDialog( + onDismissRequest = { showHintOrderDialog = false }, + initialValue = setting ?: prefs.getString( + Settings.PREF_POPUP_KEYS_LABELS_ORDER, + Defaults.PREF_POPUP_KEYS_LABELS_ORDER + )!!, + title = stringResource(R.string.hint_source), + showDefault = setting != null, + onConfirmed = { + setCurrentSubtype( + if (it == null) currentSubtype.without(ExtraValue.HINT_ORDER) + else currentSubtype.with(ExtraValue.HINT_ORDER, it) + ) + } + ) + } + if (showMorePopupsDialog) { + val items = listOf(POPUP_KEYS_NORMAL, POPUP_KEYS_MAIN, POPUP_KEYS_MORE, POPUP_KEYS_ALL) + val explicitValue = currentSubtype.getExtraValueOf(ExtraValue.MORE_POPUPS) + val value = explicitValue ?: prefs.getString(Settings.PREF_MORE_POPUP_KEYS, Defaults.PREF_MORE_POPUP_KEYS) + ListPickerDialog( + onDismissRequest = { showMorePopupsDialog = false }, + items = items, + getItemName = { stringResource(morePopupKeysResId(it)) }, + selectedItem = value, + onItemSelected = { setCurrentSubtype(currentSubtype.with(ExtraValue.MORE_POPUPS, it)) } + ) + } } } + // from ReorderSwitchPreference @Composable private fun PopupOrderDialog( @@ -336,7 +378,6 @@ private fun PopupOrderDialog( @Composable private fun MainLayoutRow( - initialSubtype: SettingsSubtype, currentSubtype: SettingsSubtype, customLayouts: List, setCurrentSubtype: (SettingsSubtype) -> Unit, @@ -352,8 +393,12 @@ private fun MainLayoutRow( DropDownField( items = appLayouts + customLayouts, selectedItem = currentSubtype.mainLayoutName() ?: SubtypeLocaleUtils.QWERTY, - onSelected = { - setCurrentSubtype(currentSubtype.withLayout(LayoutType.MAIN, it)) + onSelected = { layout -> + // if the locale defaults to qwerty, use it as implicit default to avoid creating unnecessary additional subtypes + if (layout == SubtypeLocaleUtils.QWERTY + && SubtypeSettings.getResourceSubtypesForLocale(currentSubtype.locale).any { it.mainLayoutName() == null }) + setCurrentSubtype(currentSubtype.withoutLayout(LayoutType.MAIN)) + else setCurrentSubtype(currentSubtype.withLayout(LayoutType.MAIN, layout)) }, extraButton = { IconButton({ showAddLayoutDialog = true }) @@ -364,28 +409,33 @@ private fun MainLayoutRow( Row( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween, - modifier = Modifier.fillMaxWidth() + modifier = Modifier.widthIn(min = 200.dp).fillMaxWidth() ) { - Text(SubtypeLocaleUtils.getDisplayNameInSystemLocale(it, currentSubtype.locale)) + Text(SubtypeLocaleUtils.getLayoutDisplayNameInSystemLocale(it, currentSubtype.locale)) Row (verticalAlignment = Alignment.CenterVertically) { - Icon(painterResource(R.drawable.ic_edit), stringResource(R.string.edit_layout), Modifier.clickable { showLayoutEditDialog = it to null }) - if (it in customLayouts && initialSubtype.mainLayoutName() != it) // don't allow current main layout - Icon(painterResource(R.drawable.ic_bin), stringResource(R.string.delete), Modifier.clickable { showLayoutDeleteDialog = true }) + IconButton({ showLayoutEditDialog = it to null }) { Icon(painterResource(R.drawable.ic_edit), stringResource(R.string.edit_layout)) } + if (it in customLayouts) + IconButton({ showLayoutDeleteDialog = true }) { Icon(painterResource(R.drawable.ic_bin), stringResource(R.string.delete)) } } } if (showLayoutDeleteDialog) { val others = SubtypeSettings.getAdditionalSubtypes().filter { st -> st.mainLayoutName() == it } - .any { it.toSettingsSubtype() != initialSubtype } + .any { it.toSettingsSubtype() != currentSubtype } ConfirmationDialog( onDismissRequest = { showLayoutDeleteDialog = false }, confirmButtonText = stringResource(R.string.delete), title = { Text(stringResource(R.string.delete_layout, LayoutUtilsCustom.getDisplayName(it))) }, content = { if (others) Text(stringResource(R.string.layout_in_use)) }, onConfirmed = { - if (it == currentSubtype.mainLayoutName()) - setCurrentSubtype(currentSubtype.withoutLayout(LayoutType.MAIN)) + if (it == currentSubtype.mainLayoutName()) { + // similar to what is done in SubtypeSettings.onRenameLayout + val defaultLayout = SubtypeSettings.getResourceSubtypesForLocale(currentSubtype.locale).firstOrNull()?.mainLayoutName() + val newSubtype = if (defaultLayout == null) currentSubtype.withoutLayout(LayoutType.MAIN) + else currentSubtype.withLayout(LayoutType.MAIN, defaultLayout) + setCurrentSubtype(newSubtype) + } LayoutUtilsCustom.deleteLayout(it, LayoutType.MAIN, ctx) - (ctx.getActivity() as? SettingsActivity)?.prefChanged?.value = 1234 + (ctx.getActivity() as? SettingsActivity)?.prefChanged() } ) } @@ -393,7 +443,7 @@ private fun MainLayoutRow( if (showLayoutEditDialog != null) { val layoutName = showLayoutEditDialog!!.first val startContent = showLayoutEditDialog?.second - ?: if (layoutName in appLayouts) LayoutUtils.getContent(LayoutType.MAIN, layoutName, ctx) + ?: if (layoutName in appLayouts) LayoutUtils.getContentWithPlus(layoutName, currentSubtype.locale, ctx) else null LayoutEditDialog( onDismissRequest = { showLayoutEditDialog = null }, @@ -401,10 +451,11 @@ private fun MainLayoutRow( initialLayoutName = layoutName, startContent = startContent, locale = currentSubtype.locale, - // only can edit name for new custom layout - isNameValid = if (layoutName in customLayouts) null else ({ it !in customLayouts }), + isNameValid = { it !in customLayouts }, onEdited = { - if (layoutName !in customLayouts) + if (layoutName !in customLayouts // edited a built-in layout, set new one as current + || layoutName != it && layoutName == currentSubtype.mainLayoutName() // layout name for current subtype changed + ) setCurrentSubtype(currentSubtype.withLayout(LayoutType.MAIN, it)) } ) @@ -447,6 +498,8 @@ private fun getAvailableSecondaryLocales(context: Context, mainLocale: Locale): private fun Preview() { initPreview(LocalContext.current) Theme(previewDark) { - SubtypeDialog({}, SettingsSubtype(Locale.ENGLISH, "")) { } + Surface { + SubtypeScreen(SettingsSubtype(Locale.ENGLISH, "")) { } + } } } diff --git a/app/src/main/java/helium314/keyboard/settings/screens/TextCorrectionScreen.kt b/app/src/main/java/helium314/keyboard/settings/screens/TextCorrectionScreen.kt index 97d641885..3d4ae3dc7 100644 --- a/app/src/main/java/helium314/keyboard/settings/screens/TextCorrectionScreen.kt +++ b/app/src/main/java/helium314/keyboard/settings/screens/TextCorrectionScreen.kt @@ -22,6 +22,7 @@ import helium314.keyboard.latin.R import helium314.keyboard.latin.permissions.PermissionsUtil import helium314.keyboard.latin.settings.Defaults import helium314.keyboard.latin.settings.Settings +import helium314.keyboard.latin.utils.JniUtils import helium314.keyboard.latin.utils.Log import helium314.keyboard.latin.utils.getActivity import helium314.keyboard.latin.utils.prefs @@ -49,6 +50,7 @@ fun TextCorrectionScreen( Log.v("irrelevant", "stupid way to trigger recomposition on preference change") val autocorrectEnabled = prefs.getBoolean(Settings.PREF_AUTO_CORRECTION, Defaults.PREF_AUTO_CORRECTION) val suggestionsEnabled = prefs.getBoolean(Settings.PREF_SHOW_SUGGESTIONS, Defaults.PREF_SHOW_SUGGESTIONS) + val gestureEnabled = JniUtils.sHaveGestureLib && prefs.getBoolean(Settings.PREF_GESTURE_INPUT, Defaults.PREF_GESTURE_INPUT) val items = listOf( SettingsWithoutKey.EDIT_PERSONAL_DICTIONARY, R.string.settings_category_correction, @@ -57,17 +59,26 @@ fun TextCorrectionScreen( if (autocorrectEnabled) Settings.PREF_MORE_AUTO_CORRECTION else null, if (autocorrectEnabled) Settings.PREF_AUTOCORRECT_SHORTCUTS else null, if (autocorrectEnabled) Settings.PREF_AUTO_CORRECT_THRESHOLD else null, + if (autocorrectEnabled) Settings.PREF_BACKSPACE_REVERTS_AUTOCORRECT else null, Settings.PREF_AUTO_CAP, + R.string.settings_category_space, Settings.PREF_KEY_USE_DOUBLE_SPACE_PERIOD, Settings.PREF_AUTOSPACE_AFTER_PUNCTUATION, + Settings.PREF_AUTOSPACE_AFTER_SUGGESTION, + if (gestureEnabled) Settings.PREF_AUTOSPACE_BEFORE_GESTURE_TYPING else null, + if (gestureEnabled) Settings.PREF_AUTOSPACE_AFTER_GESTURE_TYPING else null, + Settings.PREF_SHIFT_REMOVES_AUTOSPACE, R.string.settings_category_suggestions, Settings.PREF_SHOW_SUGGESTIONS, if (suggestionsEnabled) Settings.PREF_ALWAYS_SHOW_SUGGESTIONS else null, + if (suggestionsEnabled && prefs.getBoolean(Settings.PREF_ALWAYS_SHOW_SUGGESTIONS, Defaults.PREF_ALWAYS_SHOW_SUGGESTIONS)) + Settings.PREF_ALWAYS_SHOW_SUGGESTIONS_EXCEPT_WEB_TEXT else null, if (suggestionsEnabled) Settings.PREF_CENTER_SUGGESTION_TEXT_TO_ENTER else null, Settings.PREF_KEY_USE_PERSONALIZED_DICTS, Settings.PREF_BIGRAM_PREDICTIONS, Settings.PREF_SUGGEST_CLIPBOARD_CONTENT, Settings.PREF_USE_CONTACTS, + Settings.PREF_USE_APPS, if (prefs.getBoolean(Settings.PREF_KEY_USE_PERSONALIZED_DICTS, Defaults.PREF_KEY_USE_PERSONALIZED_DICTS)) Settings.PREF_ADD_TO_PERSONAL_DICTIONARY else null ) @@ -114,6 +125,9 @@ fun createCorrectionSettings(context: Context) = listOf( // todo: consider making it a slider, and maybe somehow adjust range so we can show % ListPreference(it, items, Defaults.PREF_AUTO_CORRECT_THRESHOLD) }, + Setting(context, Settings.PREF_BACKSPACE_REVERTS_AUTOCORRECT, R.string.backspace_reverts_autocorrect) { + SwitchPreference(it, Defaults.PREF_BACKSPACE_REVERTS_AUTOCORRECT) + }, Setting(context, Settings.PREF_AUTO_CAP, R.string.auto_cap, R.string.auto_cap_summary ) { @@ -129,6 +143,18 @@ fun createCorrectionSettings(context: Context) = listOf( ) { SwitchPreference(it, Defaults.PREF_AUTOSPACE_AFTER_PUNCTUATION) }, + Setting(context, Settings.PREF_AUTOSPACE_AFTER_SUGGESTION, R.string.autospace_after_suggestion) { + SwitchPreference(it, Defaults.PREF_AUTOSPACE_AFTER_SUGGESTION) + }, + Setting(context, Settings.PREF_AUTOSPACE_AFTER_GESTURE_TYPING, R.string.autospace_after_gesture_typing) { + SwitchPreference(it, Defaults.PREF_AUTOSPACE_AFTER_GESTURE_TYPING) + }, + Setting(context, Settings.PREF_AUTOSPACE_BEFORE_GESTURE_TYPING, R.string.autospace_before_gesture_typing) { + SwitchPreference(it, Defaults.PREF_AUTOSPACE_BEFORE_GESTURE_TYPING) + }, + Setting(context, Settings.PREF_SHIFT_REMOVES_AUTOSPACE, R.string.shift_removes_autospace, R.string.shift_removes_autospace_summary) { + SwitchPreference(it, Defaults.PREF_SHIFT_REMOVES_AUTOSPACE) + }, Setting(context, Settings.PREF_SHOW_SUGGESTIONS, R.string.prefs_show_suggestions, R.string.prefs_show_suggestions_summary ) { @@ -139,6 +165,11 @@ fun createCorrectionSettings(context: Context) = listOf( ) { SwitchPreference(it, Defaults.PREF_ALWAYS_SHOW_SUGGESTIONS) }, + Setting(context, Settings.PREF_ALWAYS_SHOW_SUGGESTIONS_EXCEPT_WEB_TEXT, + R.string.prefs_always_show_suggestions_except_web_text, R.string.prefs_always_show_suggestions_except_web_text_summary + ) { + SwitchPreference(it, Defaults.PREF_ALWAYS_SHOW_SUGGESTIONS_EXCEPT_WEB_TEXT) + }, Setting(context, Settings.PREF_KEY_USE_PERSONALIZED_DICTS, R.string.use_personalized_dicts, R.string.use_personalized_dicts_summary ) { setting -> @@ -195,6 +226,11 @@ fun createCorrectionSettings(context: Context) = listOf( } ) }, + Setting(context, Settings.PREF_USE_APPS, + R.string.use_apps_dict, R.string.use_apps_dict_summary + ) { setting -> + SwitchPreference(setting, Defaults.PREF_USE_APPS) + }, Setting(context, Settings.PREF_ADD_TO_PERSONAL_DICTIONARY, R.string.add_to_personal_dictionary, R.string.add_to_personal_dictionary_summary ) { diff --git a/app/src/main/res/drawable-hdpi/emoji_category_tab_selected_holo_white.9.png b/app/src/main/res/drawable-hdpi/emoji_category_tab_selected_holo_white.9.png deleted file mode 100644 index 345d05e9d..000000000 Binary files a/app/src/main/res/drawable-hdpi/emoji_category_tab_selected_holo_white.9.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/emoji_category_tab_unselected_holo_dark.9.png b/app/src/main/res/drawable-hdpi/emoji_category_tab_unselected_holo_dark.9.png deleted file mode 100644 index bbcfb2c64..000000000 Binary files a/app/src/main/res/drawable-hdpi/emoji_category_tab_unselected_holo_dark.9.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/emoji_category_tab_selected_holo_white.9.png b/app/src/main/res/drawable-mdpi/emoji_category_tab_selected_holo_white.9.png deleted file mode 100644 index 6354b997a..000000000 Binary files a/app/src/main/res/drawable-mdpi/emoji_category_tab_selected_holo_white.9.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/emoji_category_tab_unselected_holo_dark.9.png b/app/src/main/res/drawable-mdpi/emoji_category_tab_unselected_holo_dark.9.png deleted file mode 100644 index bb45ab960..000000000 Binary files a/app/src/main/res/drawable-mdpi/emoji_category_tab_unselected_holo_dark.9.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/emoji_category_tab_selected_holo_white.9.png b/app/src/main/res/drawable-xhdpi/emoji_category_tab_selected_holo_white.9.png deleted file mode 100644 index 5e8549bdd..000000000 Binary files a/app/src/main/res/drawable-xhdpi/emoji_category_tab_selected_holo_white.9.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/emoji_category_tab_unselected_holo_dark.9.png b/app/src/main/res/drawable-xhdpi/emoji_category_tab_unselected_holo_dark.9.png deleted file mode 100644 index 8cede8d5e..000000000 Binary files a/app/src/main/res/drawable-xhdpi/emoji_category_tab_unselected_holo_dark.9.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/emoji_category_tab_selected_holo_white.9.png b/app/src/main/res/drawable-xxhdpi/emoji_category_tab_selected_holo_white.9.png deleted file mode 100644 index c81e651dd..000000000 Binary files a/app/src/main/res/drawable-xxhdpi/emoji_category_tab_selected_holo_white.9.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/emoji_category_tab_unselected_holo_dark.9.png b/app/src/main/res/drawable-xxhdpi/emoji_category_tab_unselected_holo_dark.9.png deleted file mode 100644 index 5a9f92438..000000000 Binary files a/app/src/main/res/drawable-xxhdpi/emoji_category_tab_unselected_holo_dark.9.png and /dev/null differ diff --git a/app/src/main/res/drawable/sym_keyboard_paste_rounded.xml b/app/src/main/res/drawable/sym_keyboard_paste_rounded.xml index 6e57a69b2..051630b7d 100644 --- a/app/src/main/res/drawable/sym_keyboard_paste_rounded.xml +++ b/app/src/main/res/drawable/sym_keyboard_paste_rounded.xml @@ -8,8 +8,7 @@ android:width="24dp" android:height="24dp" android:viewportWidth="960" - android:viewportHeight="960" - android:tint="?attr/colorControlNormal"> + android:viewportHeight="960"> \ No newline at end of file diff --git a/app/src/main/res/drawable/toolbar_expand_key_background.xml b/app/src/main/res/drawable/toolbar_expand_key_background.xml new file mode 100644 index 000000000..105d1a42a --- /dev/null +++ b/app/src/main/res/drawable/toolbar_expand_key_background.xml @@ -0,0 +1,14 @@ + + + + diff --git a/app/src/main/res/layout/emoji_category_view.xml b/app/src/main/res/layout/emoji_category_view.xml new file mode 100644 index 000000000..cbef189b9 --- /dev/null +++ b/app/src/main/res/layout/emoji_category_view.xml @@ -0,0 +1,20 @@ + + + + + + diff --git a/app/src/main/res/layout/emoji_palettes_view.xml b/app/src/main/res/layout/emoji_palettes_view.xml index ecf75b6ba..0625d09ac 100644 --- a/app/src/main/res/layout/emoji_palettes_view.xml +++ b/app/src/main/res/layout/emoji_palettes_view.xml @@ -15,11 +15,10 @@ android:background="@android:color/transparent" style="?attr/emojiPalettesViewStyle" > - + android:layout_height="wrap_content" /> "Aktiveer verdeelde sleutelbord" "Skakel oor na die ander invoermetodes" "Taal-wisselsleutel" - %sms + %sms "Stelsel se verstek" "Gebruik name van kontakte vir voorstelle en korreksies" "Gepersonaliseerde voorstelle" @@ -49,20 +49,9 @@ "Spaans (VS)" "Hinglish" "Serwies (Latyns)" - Engels (VK) (%s) - Engels (VS) (%s) - Spaans (VS) (%s) - Hinglish (%s) - Serwies (%s) - %s (Tradisioneel) - %s (Kompak) - "Geen taal nie (alfabet)" - "Alfabet (QWERTY)" - "Alfabet (QWERTZ)" - "Alfabet (AZERTY)" - "Alfabet (Dvorak)" - "Alfabet (Colemak)" - "Alfabet (PC)" + %s (Tradisioneel) + %s (Kompak) + "Geen taal nie" "Emosiekone" "Voeg by" "Verwyder" @@ -75,38 +64,33 @@ "Emosiekone vir fisieke sleutelbord" "Fisieke Alt-sleutel wys die emosiekoon-palet" "Verstek" - Welkom by %s + Welkom by %s "met Gebaar-tik" "Kom aan die gang" - "Volgende stap" - Stel %s op - Aktiveer %s - Gaan asseblief \"%s\" in jou Tale- en invoer-instellings na. Dit sal dit magtig om op jou toestel te werk. - %s is reeds in jou Tale- en invoer-instellings geaktiveer – dus is hierdie stap klaar. Doen die volgende een! + Stel %s op + Aktiveer %s + Gaan asseblief \"%s\" in jou Tale- en invoer-instellings na. Dit sal dit magtig om op jou toestel te werk. "Aktiveer in instellings" - Skakel oor na %s - Volgende, kies \"%s\" as jou aktiewe teks-invoermetode. + Skakel oor na %s + Volgende, kies \"%s\" as jou aktiewe teks-invoermetode. "Wissel invoermetodes" "Veels geluk, jy\'s gereed!" - Nou kan jy in al jou gunsteling-programme tik met %s. + Nou kan jy in al jou gunsteling-programme tik met %s. "Klaar" "Wys program-ikoon" "Wys program-ikoon in die lanseerpoort" - "Voeg woordeboeke by" + "Voeg woordeboeke by" "Woordeboek beskikbaar" - "Geen woordeboeke beskikbaar nie" "Laas opgedateer" "Instellings" "Vee uit" - Weergawe %1$s - "Voeg by" + Weergawe %1$s "Voeg by woordeboek" "Kortpad:" "Taal:" "Tik \'n woord in" "Opsionele kortpad" "Redigeer woord" - "Jy het geen woorde in die gebruikerwoordeboek nie. Tik op die Voeg By-knoppie (+) om \'n woord by te voeg." "Vir alle tale" "Nog tale…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" @@ -114,7 +98,7 @@ Voorstelle Eksperimenteel Allerlei - %smin. + %smin. Geen beperking Aktiveer knipbord geskiedenis Indien gedeaktiveerd, sal knipbord sleutel plak as dit inhoud het @@ -131,15 +115,13 @@ Skrap met vee Emoji sleutel Doen \'n vee van die skrap sleutel om \'n groter seleksie van teks eenmaal te skrap - %s (Akkhor) + %s (Akkhor) Dwing incognito-modus Deaktiveer die leer van nuwe woorde Meer sleutels Lang-druk van spasiebalk sal toevoer metode seleksie skerm wys Outo-spasie na leestekens Plaas \'n spasie na \'n leesteken sodra \'n nuwe woord getik word - Alphabet (Workman) - Alphabet (Colemak Mod-DH) HeliBoard Instellings Invoer Bykomende Sleutels diff --git a/app/src/main/res/values-am/strings.xml b/app/src/main/res/values-am/strings.xml index e9a384c81..5953a6151 100644 --- a/app/src/main/res/values-am/strings.xml +++ b/app/src/main/res/values-am/strings.xml @@ -16,7 +16,7 @@ "የተከፈለ ቁልፍ ሰሌዳ አንቃ" "ወደ ሌሎች የግቤት ስልቶች ቀይር" "የቋንቋ መቀየሪያ ቁልፍ" - "%sሚሊሰከንድ" + "%sሚሊሰከንድ" "የስርዓት ነባሪ" "ከዕውቂያዎች ለጥቆማዎች እና ማስተካከያዎች ስሞች ተጠቀም" "ግላዊ የጥቆማ አስተያየቶች" @@ -49,20 +49,9 @@ "ስፓኒሽኛ (ዩኤስ)" "ሂንግሊሽ" "ሰርብያኛ (ላቲን)" - "እንግሊዝኛ (ዩኬ) (%s)" - "እንግሊዝኛ (አሜሪካ) (%s)" - "ስፓኒሽ (አሜሪካ) (%s)" - "ሂንግሊሽ (%s)" - "ሰርቢያኛ (%s)" - "%s (ተለምዷዊ)" - "%s (እስግ)" - "ምንም ቋንቋ (ፊደላት)" - "ፊደላት (QWERTY)" - "ፊደላት (QWERTZ)" - "ፊደላት (AZERTY)" - "ፊደላት (Dvorak)" - "ፊደላት (Colemak)" - "ፊደላት (ፒሲ)" + "%s (ተለምዷዊ)" + "%s (እስግ)" + "ምንም ቋንቋ" "ኢሞጂ" "አክል" "አስወግድ" @@ -75,38 +64,33 @@ "ስሜት ገላጭ ምስሎች ለአካላዊ ቁልፍ ሰሌዳ" "አካላዊ Alt ቁልፍ የስሜት ገላጭ ቤተ-ስዕልን ያሳያል" "ነባሪ" - "እንኳን ወደ %s በደህና መጡ" + "እንኳን ወደ %s በደህና መጡ" "በጣት ምልክት መተየብ" "ጀምር" - "ቀጣይ ደረጃ" - %sን በማዋቀር ላይ\" - %sን ያንቁ\" - እባክዎ %s»ን በእርስዎ የቋንቋ እና ግቤት ቅንብሮች ውስጥ መኖሩን ያረጋግጡት። ይሄ እሱ በመሣሪያዎ ላይ እንዲሄድ ይፈቅድለታል።\" - "%s አስቀድሞ በእርስዎ ቋንቋ እና ግቤት ቅንብሮች ውስጥ ነቅቷል፣ ስለዚህ ይህ ደረጃ ተከናውኗል። ወደ ቀጣዩ እንሂድ!" + %sን በማዋቀር ላይ\" + %sን ያንቁ\" + እባክዎ %s»ን በእርስዎ የቋንቋ እና ግቤት ቅንብሮች ውስጥ መኖሩን ያረጋግጡት። ይሄ እሱ በመሣሪያዎ ላይ እንዲሄድ ይፈቅድለታል።\" "በቅንብሮች ውስጥ ያንቁ" - "ወደ %s ይቀይሩ" - በመቀጠል %s»ን እንደ የጽሑፍ ግቤት ስልትዎ ይምረጡት።\" + "ወደ %s ይቀይሩ" + በመቀጠል %s»ን እንደ የጽሑፍ ግቤት ስልትዎ ይምረጡት።\" "የግቤት ስልቶችን ቀያይር" "እንኳን ደስ አለዎት፣ በቃ ጨርሰዋል!" - "አሁን በሁሉም ተወዳጅ መተግበሪያዎችዎ ላይ በ%s መተየብ ይችላሉ።" + "አሁን በሁሉም ተወዳጅ መተግበሪያዎችዎ ላይ በ%s መተየብ ይችላሉ።" "ጨርሷል" "የመተግበሪያ አዶ አሳይ" "የመተግበሪያ አዶውን በማስጀመሪያው ውስጥ አሳይ" - "ጭማሪ መዝገበ-ቃላት" + "ጭማሪ መዝገበ-ቃላት" "መዝገበ-ቃላት ይገኛል" - "ምንም መዝገበ-ቃላት የሉም" "ለመጨረሻ ጊዜ የተዘመነው" "ቅንብሮች" "ሰርዝ" - "ሥሪት %1$s" - "አክል" + "ሥሪት %1$s" "ወደ መዝገበ-ቃላት አክል" "አቋራጭ፦" "ቋንቋ፦" "አንድ ቃል ይተይቡ" "አማራጭ አቋራጭ" "ቃሉን አርትዕ" - "በተጠቃሚ መዝገበ-ቃላቱ ውስጥ ምንም ቃላት የለዎትም። አንድ ቃል ለማከል የአክል (+) አዝራሩን መታ ያድርጉ።" "ለሁሉም ቋንቋዎች" "ተጨማሪ ቋንቋዎች…" " ሀለሐመሠረሰሸቀበቨተቸኀነኘአከኸወዐዘዠየደጀገጠጨጰጸፀፈፐ" diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 04d268499..0774c6472 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -16,7 +16,7 @@ فعّل تقسيم لوحة المفاتيح "التبديل إلى أسلوب إدخال آخر" "مفتاح تبديل اللغة" - %s ملي ثانية + %s ملي ثانية "الضبط التلقائي للنظام" "استخدام الأسماء من جهات الاتصال للاقتراحات والتصحيحات" "اقتراحات مخصصة" @@ -49,20 +49,9 @@ "الإسبانية (الأميركية)" "هنجليزية" "الصربية (اللاتينية)" - الإنجليزية (المملكة المتحدة) (%s) - الإنجليزية (الولايات المتحدة) (%s) - الإسبانية (الولايات المتحدة) (%s) - الهنجليزية (%s) - الصربية (%s) - %s (التقليدية) - %s (مضغوط) - "بدون لغة (أبجدية)" - "‏الأبجدية (QWERTY)" - "‏الأبجدية (QWERTZ)" - "‏الأبجدية (AZERTY)" - "‏الأبجدية (Dvorak)" - "‏الأبجدية (Colemak)" - "‏الأبجدية (PC)" + %s (التقليدية) + %s (مضغوط) + "بدون لغة" "الرموز التعبيرية" أضف "إزالة" @@ -75,38 +64,33 @@ "الرموز التعبيرية للوحة مفاتيح فعلية" "‏مفتاح Alt الفعلي يعرض لوحة الرموز التعبيرية" "التلقائية" - مرحبًا بكم في%s + مرحبًا بكم في %s مع الكتابة بالإيماءة "بدء الاستخدام" - "الخطوة التالية" - قيد الإعداد%s - مكِّن%s - يرجى التحقق من \\%s\" في إعدادات الإدخال واللغات. سيؤدي ذلك إلى تمكين لوحة المفاتيح على جهازك.\" - <xliff:g id=\"APPLICATION_NAME\" مثال=\"لوحة مفاتيح أندرويد\">%s</xliff:g> ممكّن بالفعل في إعدادات اللغات &amp؛ إعدادات الإدخال، لذا فقد تم الانتهاء من هذه الخطوة. إلى الخطوة التالية!\" + قيد الإعداد %s + مكِّن %s + يُرجى التحقق من \"%s\" في إعدادات الإدخال واللغات. سيؤدي ذلك إلى تمكين لوحة المفاتيح على جهازك. "تفعيل في الإعدادات" - قم بالتبديل إلى%s - بعد ذلك، اختر \\<<xliff:g id=\"APPLICATION_NAME\" مثال=\"لوحة مفاتيح أندرويد\">%s</xliff:g>” كطريقة إدخال النص النشط.“ + بدّل إلى %s + بعد ذلك، اختر \"%s” كطريقة إدخال النص النشط. "تبديل أساليب الإدخال" تهانينا ، لقد انتهيت من الإعداد! - الآن أصبح بإمكانك الكتابة في جميع تطبيقاتك المفضلة باستخدام %s. + الآن أصبح بإمكانك الكتابة في جميع تطبيقاتك المفضلة باستخدام %s. "إنهاء العملية" اعرض رمز التطبيق اعرض رمز التطبيق في المشغل - "القواميس الإضافية" + "القواميس الإضافية" "القاموس متاح" - "لا تتوفر أي قواميس" "تاريخ آخر تحديث" "إعدادات" "حذف" - الإصدار %1$s - أضف + الإصدار %1$s أضف إلى القاموس "الاختصار:" "اللغة:" "اكتب كلمة" "اختصار اختياري" "تعديل كلمة" - "ليس هناك أي كلمات في قاموس المستخدم. لإضافة كلمة، انقر على زر الإضافة (+)." "لجميع اللغات" "مزيد من اللغات…" " أ ب ت ث ج ح خ د ذ ر ز س ش ص ض ط ظ ع غ ف ق ك ل م ن ه و ي" @@ -141,13 +125,11 @@ "اختيار أسلوب الإدخال" أظهِر تلميحات المفاتيح عند الضغط لفترة طويلة سيقوم الضغط المطول على مفتاح المسافة بإظهار قائمة اختيار أساليب الإدخال - %s (أخور) + %s (أخور) ضع مسافةً بعد علامات الترقيم تلقائيًا أدرج مسافةً تلقائيًا بعد علامة الترقيم عند كتابة كلمة جديدة افرض وضع التخفي - %s min - الأبجدية (Colemak Mod-DH) - الأبجدية (Workman) + %s min ثقة التصحيح التلقائي "تراجع" "إعادة" @@ -163,7 +145,7 @@ الألوان صف الأرقام %s (تجريبي) - اللغة + @string/subtype_locale استخدمه على أي حال النمط دائري @@ -179,7 +161,6 @@ خلفية لوحة المفاتيح نص الأزرار اختيار تلقائي للون - انقر للمعانية الإصدار غلق المظهر @@ -247,10 +228,10 @@ الرموز الرموز(العربية) ارقام - لوحة ارقام + لوحة الأرقام الهاتف رموز الهاتف - لوحة رقمية (أفقي) + لوحة الأرقام (أفقي) هل تريد حقًا إزالة القاموس الذي أضافه المستخدم \"%s\"؟ خطأ: الملف المحدد ليس ملف قاموس صالح اسود @@ -277,13 +258,11 @@ اليسار الكامل اليمين الكامل أظهِر تلميحات إذا كان الضغط لفترة طويلة على المفتاح يؤدي إلى تشغيل وظائف إضافية - كايتاج (%s) تعيين الصورة لوضع النهار أو الليل؟ صباح - %s (Sebeolsik Final) + %s (Sebeolsik Final) حدد ملفًا بتنسيق متوافق. المعلومات حول التنسيقات متاحة %s. انسخ التخطيط الموجود - تعيين اسم التخطيط هل تريد حقًا حذف التخطيط المخصص %s؟ خطأ في التخطيط: %s انقر لتحرير التخطيط الأولي @@ -318,61 +297,24 @@ خطأ: البرنامج النصي غير متوافق مع لوحة المفاتيح هذه أظهِر المتغيرات المحددة بلغات لوحة المفاتيح مقياس الحشو السفلي - "► يؤدي الضغط لفترة طويلة على مفاتيح شريط الأدوات المثبتة إلى وظائف إضافية: <br> -\n • الحافظة &#65515; لصق <br> -\n • تحرك لليسار/ لليمين &#65515; كلمة يسار/يمين <br> -\n • التحرك لأعلى/لأسفل &#65515; الصفحة لأعلى/لأسفل <br> -\n • كلمة يسار/يمين &#65515; بداية/نهاية السطر <br> -\n • صفحة لأعلى/لأسفل &#65515; بداية/نهاية الصفحة <br> -\n • نسخة &#65515; قطع <br> -\n • اختر كلمة &#8596; حدد الكل <br> -\n • التراجع &#8596; إعادة <br> <br> -\n► يؤدي الضغط لفترة طويلة على المفاتيح في شريط أدوات شريط الاقتراحات إلى تثبيتها على شريط الاقتراحات. <br><br> -\n► اضغط لفترة طويلة على مفتاح الفاصلة للوصول إلى عرض الحافظة، أو عرض الرموز التعبيرية، أو الوضع بيد واحدة، أو الإعدادات، أو تبديل اللغة: <br> -\n • سيختفي عرض الرموز التعبيرية وتبديل اللغة إذا كان لديك المفتاح المقابل ممكّنًا. <ر> -\n • بالنسبة لبعض التخطيطات، فهو ليس مفتاح الفاصلة، ولكنه المفتاح الموجود في نفس الموضع (على سبيل المثال، إنه \\\'q\\\' لتخطيط Dvorak). <br><br> -\n► عند تمكين وضع التصفح المتخفي، لن يتم تعلم أي كلمات، ولن تتم إضافة أي رموز تعبيرية إلى الرسائل الأخيرة. <br><br> -\n► اضغط على أيقونة التصفح المتخفي للوصول إلى شريط الأدوات. <br><br> -\n► إدخال مفتاح منزلق: اسحب من مفتاح Shift إلى مفتاح آخر لكتابة مفتاح واحد كبير: <br> -\n • يعمل هذا أيضًا مع المفتاح \\\'?123\\\' لكتابة رمز واحد من لوحة مفاتيح الرموز، وللمفاتيح ذات الصلة. <br><br> -\n► اضغط مع الاستمرار على مفتاح Shift أو مفتاح الرمز، واضغط على مفتاح واحد أو أكثر، ثم حرر مفتاح Shift أو مفتاح الرمز للعودة إلى لوحة المفاتيح السابقة. <br><br> -\n► اضغط لفترة طويلة على أحد الاقتراحات في شريط الاقتراحات لإظهار المزيد من الاقتراحات، ثم اضغط على زر الحذف لإزالة هذا الاقتراح. <br><br> -\n► اسحب لأعلى من أحد الاقتراحات لفتح المزيد من الاقتراحات، ثم حرر الاقتراح لتحديده. <br><br> -\n► اضغط لفترة طويلة على أحد الإدخالات في سجل الحافظة لتثبيته (احتفظ به في الحافظة حتى تقوم بإلغاء تثبيته). <br><br> -\n► اسحب لليسار في عرض الحافظة لإزالة إدخال (باستثناء عندما يكون مثبتًا) <br> <br> -\n► حدد النص واضغط على مفتاح Shift للتبديل بين الكلمات الكبيرة والصغيرة والأحرف الكبيرة. <br><br> -\n► يمكنك إضافة قواميس عن طريق فتحها في مستكشف الملفات: <br> -\n • يعمل هذا فقط مع <i>content-uris</i> وليس مع <i>file-uris</i>، مما يعني أنه قد لا يعمل مع بعض مستكشفات الملفات. <br><br> -\n► بالنسبة للمستخدمين الذين يقومون بالنسخ الاحتياطي اليدوي مع الوصول إلى الجذر: <br> -\n • بدءًا من Android 7، لا يكون ملف التفضيلات المشتركة في الموقع الافتراضي، لأن التطبيق يستخدم %s. يعد ذلك ضروريًا حتى يمكن قراءة الإعدادات قبل إلغاء قفل الجهاز، على سبيل المثال. في التمهيد؛ <ر> -\n • الملف موجود في /data/user_de/0/package_id/shared_prefs/ على الرغم من أن هذا قد يعتمد على الجهاز وإصدار Android. <br><br> -\n<i><b>وضع التصحيح / تصحيح APK</b></i> <br> <br> -\n► اضغط لفترة طويلة على اقتراح لإظهار القاموس المصدر. <br><br> -\n► عند استخدام debug APK، يمكنك العثور على إعدادات Debug ضمن التفضيلات المتقدمة، على الرغم من أن الفائدة محدودة باستثناء تفريغ القواميس في السجل. <ر> -\n • بالنسبة لإصدار APK، تحتاج إلى النقر على الإصدار في <i>حول</i> عدة مرات، ثم يمكنك العثور على إعدادات تصحيح الأخطاء في <i>التفضيلات المتقدمة</i>. <ر> -\n • عند تمكين <i>إظهار معلومات الاقتراح</i>، ستحتوي الاقتراحات على بعض الأرقام الصغيرة في الأعلى لإظهار بعض النتائج الداخلية وقاموس المصدر. <br><br> -\n► في حالة تعطل التطبيق، سيُطلب منك ما إذا كنت تريد سجلات التعطل عند فتح الإعدادات. <br><br> -\n► عند استخدام الكتابة متعددة اللغات، سيُظهر شريط المسافة قيمة الثقة المستخدمة لتحديد اللغة المستخدمة حاليًا. <br><br> -\n► ستحتوي الاقتراحات على بعض الأرقام الصغيرة في الأعلى لإظهار بعض النتائج الداخلية وقاموس المصدر (يمكن تعطيله)." + "► يؤدي الضغط لفترة طويلة على مفاتيح شريط الأدوات المثبتة إلى وظائف إضافية: <br>\n\n • الحافظة &#65515; لصق <br>\n\n • تحرك لليسار/ لليمين &#65515; كلمة يسار/يمين <br>\n\n • التحرك لأعلى/لأسفل &#65515; الصفحة لأعلى/لأسفل <br>\n\n • كلمة يسار/يمين &#65515; بداية/نهاية السطر <br>\n\n • صفحة لأعلى/لأسفل &#65515; بداية/نهاية الصفحة <br>\n\n • نسخة &#65515; قطع <br>\n\n • اختر كلمة &#8596; حدد الكل <br>\n\n • التراجع &#8596; إعادة <br> <br>\n\n► يؤدي الضغط لفترة طويلة على المفاتيح في شريط أدوات شريط الاقتراحات إلى تثبيتها على شريط الاقتراحات. <br><br>\n\n► اضغط لفترة طويلة على مفتاح الفاصلة للوصول إلى عرض الحافظة، أو عرض الرموز التعبيرية، أو الوضع بيد واحدة، أو الإعدادات، أو تبديل اللغة: <br>\n\n • سيختفي عرض الرموز التعبيرية وتبديل اللغة إذا كان لديك المفتاح المقابل ممكّنًا. <ر>\n\n • بالنسبة لبعض التخطيطات، فهو ليس مفتاح الفاصلة، ولكنه المفتاح الموجود في نفس الموضع (على سبيل المثال، إنه \\\'q\\\' لتخطيط Dvorak). <br><br>\n\n► عند تمكين وضع التصفح المتخفي، لن يتم تعلم أي كلمات، ولن تتم إضافة أي رموز تعبيرية إلى الرسائل الأخيرة. <br><br>\n\n► اضغط على أيقونة التصفح المتخفي للوصول إلى شريط الأدوات. <br><br>\n\n► إدخال مفتاح منزلق: اسحب من مفتاح Shift إلى مفتاح آخر لكتابة مفتاح واحد كبير: <br>\n\n • يعمل هذا أيضًا مع المفتاح \\\'?123\\\' لكتابة رمز واحد من لوحة مفاتيح الرموز، وللمفاتيح ذات الصلة. <br><br>\n\n► اضغط مع الاستمرار على مفتاح Shift أو مفتاح الرمز، واضغط على مفتاح واحد أو أكثر، ثم حرر مفتاح Shift أو مفتاح الرمز للعودة إلى لوحة المفاتيح السابقة. <br><br>\n\n► اضغط لفترة طويلة على أحد الاقتراحات في شريط الاقتراحات لإظهار المزيد من الاقتراحات، ثم اضغط على زر الحذف لإزالة هذا الاقتراح. <br><br>\n\n► اسحب لأعلى من أحد الاقتراحات لفتح المزيد من الاقتراحات، ثم حرر الاقتراح لتحديده. <br><br>\n\n► اضغط لفترة طويلة على أحد الإدخالات في سجل الحافظة لتثبيته (احتفظ به في الحافظة حتى تقوم بإلغاء تثبيته). <br><br>\n\n► اسحب لليسار في عرض الحافظة لإزالة إدخال (باستثناء عندما يكون مثبتًا) <br> <br>\n\n► حدد النص واضغط على مفتاح Shift للتبديل بين الكلمات الكبيرة والصغيرة والأحرف الكبيرة. <br><br>\n\n► يمكنك إضافة قواميس عن طريق فتحها في مستكشف الملفات: <br>\n\n • يعمل هذا فقط مع <i>content-uris</i> وليس مع <i>file-uris</i>، مما يعني أنه قد لا يعمل مع بعض مستكشفات الملفات. <br><br>\n\n► بالنسبة للمستخدمين الذين يقومون بالنسخ الاحتياطي اليدوي مع الوصول إلى الجذر: <br>\n\n • بدءًا من Android 7، لا يكون ملف التفضيلات المشتركة في الموقع الافتراضي، لأن التطبيق يستخدم %s. يعد ذلك ضروريًا حتى يمكن قراءة الإعدادات قبل إلغاء قفل الجهاز، على سبيل المثال. في التمهيد؛ <ر>\n\n • الملف موجود في /data/user_de/0/package_id/shared_prefs/ على الرغم من أن هذا قد يعتمد على الجهاز وإصدار Android. <br><br>\n\n<i><b>وضع التصحيح / تصحيح APK</b></i> <br> <br>\n\n► اضغط لفترة طويلة على اقتراح لإظهار القاموس المصدر. <br><br>\n\n► عند استخدام debug APK، يمكنك العثور على إعدادات Debug ضمن التفضيلات المتقدمة، على الرغم من أن الفائدة محدودة باستثناء تفريغ القواميس في السجل. <ر>\n\n • بالنسبة لإصدار APK، تحتاج إلى النقر على الإصدار في <i>حول</i> عدة مرات، ثم يمكنك العثور على إعدادات تصحيح الأخطاء في <i>التفضيلات المتقدمة</i>. <br>\n\n • عند تمكين <i>إظهار معلومات الاقتراح</i>، ستحتوي الاقتراحات على بعض الأرقام الصغيرة في الأعلى لإظهار بعض النتائج الداخلية وقاموس المصدر. <br><br>\n\n► في حالة تعطل التطبيق، سيُطلب منك ما إذا كنت تريد سجلات التعطل عند فتح الإعدادات. <br><br>\n\n► عند استخدام الكتابة متعددة اللغات، سيُظهر شريط المسافة قيمة الثقة المستخدمة لتحديد اللغة المستخدمة حاليًا. <br><br>\n\n► ستحتوي الاقتراحات على بعض الأرقام الصغيرة في الأعلى لإظهار بعض النتائج الداخلية وقاموس المصدر (يمكن تعطيله)." رخصة جنو العامة v3.0 هذه الكلمة موجودة بالفعل في قاموس المستخدم %s. الرجاء كتابة واحدة أخرى. تفضيل المحلية على الأرقام اللاتينية حدد الألوان للنص والخلفيات "بدون قاموس، ستحصل فقط على اقتراحات للنص الذي أدخلته من قبل.<br>\n يمكنك تنزيل القواميس %1$s، أو التحقق مما إذا كان يمكن تنزيل قاموس لـ \"%2$s\" مباشرةً %3$s." - %s (Probhat) - %s (Sebeolsik 390) + %s (Probhat) + %s (Sebeolsik 390) اختر ترتيب المفاتيح المنبثقه - الأبجدية (بيبو) اضغط لفترة طويلة على مفتاح الرموز للوحة الرقمية قصّ - %s (طالب) + %s (طالب) استخدم دائمًا الاقتراح الأوسط عند الضغط على مسافة أو علامات الترقيم، سيتم إدخال الاقتراح الأوسط إغلاق تاريخ الحافظة حدد مفاتيح شريط أدوات الحافظة - %s (Extended) + %s (Extended) مانسي - مانسي (%s) أظهِر المزيد من الالوان يعرض هذا الإعداد كافة الألوان المستخدمة داخليًا. قد تتغير قائمة الألوان في أي وقت. اللون الافتراضي عشوائي، ولن تتم ترجمة الأسماء. مفاتيح وظيفية @@ -396,7 +338,6 @@ حمّل احفظ إلى الملف انسخ إلى الحافظة - سيؤدي التحميل إلى استبدال السمة الحالية بداية الصفحة نهاية الصفحة كلمة لليسار @@ -425,7 +366,7 @@ تبويب حذف تحويل - تحويل(معكوس) + تحويل (تحول) حرف كبير إنهاء وضع اليد الواحدة تحجيم وضع اليد الواحدة @@ -443,10 +384,9 @@ درغوة (أوراخي) اختصار التصحيح التلقائي قد يتم توسيع الاختصارات عند تمكينها بواسطة التصحيح التلقائي - أوراخي (%s) تعيين خط مخصص من الملف الاهتزاز في وضع عدم الازعاج - %s (صوتي) + %s (صوتي) هل تريد إعادة تعيين جميع الأيقونات المخصصة؟ تجاوز إصدار الرموز التعبيرية تعيين صورة الخلفية (أفقي) @@ -472,4 +412,29 @@ اللغات مع القواميس يمكنك العثور على المخططات ومشاركتها في %s. قسم المناقشة + نوع فرعي مخصّص + %s (Baishakhi) + أظهِر مفاتيح TLD المنبثقة + استبدل مفتاح الفترة المنبثقة مع مجالات المستوى الأعلى عند كتابة عناوين URL وعناوين البريد الإلكتروني + الضغط على إدخال أو مساحة بعد مفاتيح أخرى في لوحة الأرقام + لا تعرض دائمًا اقتراحات لحقول تحرير الويب + صف الرقم (أساسي) + المسافة + تعتبر حقول تحرير الويب (الموجودة في غالب المتصفحات) سببًا شائعًا جدًا للمشكلات المتعلقة بإعداد اقتراحات العرض دائمًا + مسافة تلقائية قبل إيماءة كتابة كلمة + مسافة تلقائية بعد إيماءة كتابة كلمة + يقوم التحويل بإزالة المسافة تلقائية المعلقة + مسافة تلقائية بعد اختيار اقتراح + يعود المسافة الخلفية إلى التصحيح التلقائي + لا مسافة تلقائية عند الضغط على تحويل + تنسيق لمفتاح الطابع الزمني + دغبانية + السوتية + استُعيدت النسخة الاحتياطية + حجّم مفتاح الإيموجي مع حجم الخط + ابحث عن أسماء التطبيقات + استخدام أسماء التطبيقات المثبتة للاقتراحات والتصحيحات + لون بشرة الرموز التعبيرية الافتراضي + طبيعي + %1$s (%2$s) diff --git a/app/src/main/res/values-as/strings.xml b/app/src/main/res/values-as/strings.xml index 25e970ef6..29ee765b6 100644 --- a/app/src/main/res/values-as/strings.xml +++ b/app/src/main/res/values-as/strings.xml @@ -58,17 +58,14 @@ "ডিফ\'ল্ট" "আঙুলি পিছলাই দিয়া নিৰ্দেশেৰে টাইপ কৰাৰ সুবিধাৰ সৈতে" "আৰম্ভ কৰক" - "পৰৱৰ্তী পদক্ষেপ" "সম্পূৰ্ণ হ’ল" "এপৰ আইকন দেখুৱাওক" "লঞ্চাৰত এপ্লিকেশ্বন আইকন দেখুৱাওক" - "অতিৰিক্ত অভিধান" + "অতিৰিক্ত অভিধান" "অভিধান উপলব্ধ" - "কোনো অভিধান নাই" "অন্তিমবাৰ আপডে’ট কৰা হৈছিল" "ছেটিংসমূহ" "মচক" - "যোগ কৰক" "অভিধানত যোগ কৰক" "শ্বৰ্টকাট:" "ভাষা:" diff --git a/app/src/main/res/values-az/strings.xml b/app/src/main/res/values-az/strings.xml index 526e0ba86..ee4d4a5ef 100644 --- a/app/src/main/res/values-az/strings.xml +++ b/app/src/main/res/values-az/strings.xml @@ -16,7 +16,7 @@ "Klaviaturanı ayırmağa icazə verin" "Digər daxiletmə metodlarına keçin" "Dil keçidi düyməsi" - "%s millisaniyə" + "%s millisaniyə" "Sistem defoltu" "Təklif və korreksiya üçün Kontaktlardakı adlardan istifadə edin" "Fərdiləşmiş təkliflər" @@ -49,20 +49,9 @@ "İspan (ABŞ)" "Hingilis" "Serb (Latın)" - "İngilis (Britaniya) (%s)" - "İngilis (Amerika) (%s)" - "İspan (Amerika) (%s)" - "Hingilis (%s)" - "Serb (%s)" - "%s (Ənənəvi)" - "%s (Kompakt)" - "Dil yoxdur (Əlifba)" - "Əlifba (QWERTY)" - "Əlifba (QWERTZ)" - "Əlifba (AZERTY)" - "Əlifba (Dvorak)" - "Əlifba (Colemak)" - "Əlifba (PC)" + "%s (Ənənəvi)" + "%s (Kompakt)" + "Dil yoxdur" "Emoji" "Əlavə et" "Ləğv et" @@ -75,38 +64,33 @@ "Fiziki klaviatura üçün emoji" "Fiziki ALt düyməsi emoji palletini göstərir" "Defolt" - %s təbiqinə xoş gəlmisiniz\" + %s təbiqinə xoş gəlmisiniz\" "Jest Yazısı ilə" "Başlayın" - "Növbəti addım" - %s quraşdırılır\" - %s tətbiqini aktivləşdir\" - "Lütfən, \"%s\" tətbiqini Dillər və daxiletmə ayarlarında yoxlayın. Bununla tətbiqin cihazınızda işləməsinə icazə veriləcək." - "%s artıq Dillər və daxiletmə ayarlarında aktivləşdirildi, beləliklə da bu mərhələ tamamlandı. İndi isə növbəti mərhələyə keçin!" + %s quraşdırılır\" + %s tətbiqini aktivləşdir\" + "Lütfən, \"%s\" tətbiqini Dillər və daxiletmə ayarlarında yoxlayın. Bununla tətbiqin cihazınızda işləməsinə icazə veriləcək." "Parametrlərdə aktivləşdir" - %s tətbiqinə keçin\" - "Sonra, \"%s\" tətbiqini aktiv mətn-daxiletmə metodu olaraq seçin." + %s tətbiqinə keçin\" + "Sonra, \"%s\" tətbiqini aktiv mətn-daxiletmə metodu olaraq seçin." "Daxil metodlarına keç" "Təbrik edirik, tam hazırsınız!" - "İndi siz %s ilə bütün sevimli tətbiqlərinizdə yaza bilərsiniz." + "İndi siz %s ilə bütün sevimli tətbiqlərinizdə yaza bilərsiniz." "Sona çatdı" "Tətbiq ikonasını göstər" "Başlatma panelində tətbiq ikonasını göstər" - "Əlavə lüğətlər" + "Əlavə lüğətlər" "Lüğət mövcuddur" - "Lüğət mövcud deyil" "Son yeniləmə" "Ayarlar" "Sil" - "%1$s nömrəli versiya" - "Əlavə edin" + "%1$s nömrəli versiya" "Lüğətə əlavə edin" "Qısayol:" "Dil:" "Bir söz yazın" "Qısayol" "Sözü redaktə edin" - "İstifadəçi lüğətinizdə heç bir söz yoxdur. Söz əlavə etmək üçün Əlavə et (+) düyməsinə tıklayın." "Bütün dillər üçün" "Digər dillər…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" diff --git a/app/src/main/res/values-b+sr+Latn/strings.xml b/app/src/main/res/values-b+sr+Latn/strings.xml index 66e0a0084..9278bc669 100644 --- a/app/src/main/res/values-b+sr+Latn/strings.xml +++ b/app/src/main/res/values-b+sr+Latn/strings.xml @@ -16,7 +16,7 @@ "Omogući podeljenu tastaturu" "Prebaci na druge metode unosa" "Taster za prebacivanje jezika" - "%s ms" + "%s ms" "Podrazumevano" "Koristi imena iz Kontakata za predloge i ispravke" "Personalizovani predlozi" @@ -49,20 +49,9 @@ "španski (SAD)" "hengleski" "srpski (latinica)" - "engleski (UK) (%s)" - "engleski (SAD) (%s)" - "španski (SAD) (%s)" - "hengleski (%s)" - "srpski (%s)" - "%s (tradicionalni)" - "%s (kompaktna)" - "Nema jezika (abeceda)" - "abeceda (QWERTY)" - "abeceda (QWERTZ)" - "abeceda (AZERTY)" - "abeceda (Dvorak)" - "abeceda (Colemak)" - "abeceda (PC)" + "%s (tradicionalni)" + "%s (kompaktna)" + "Nema jezika" "Emotikoni" "Dodaj" "Ukloni" @@ -75,38 +64,33 @@ "Emodži za fizičku tastaturu" "Fizički taster Alt pokazuje paletu emodžija" "Podrazumevano" - "Dobro došli u %s" + "Dobro došli u %s" "pomoću Kucanja pokretima" "Započnimo" - "Sledeći korak" - "Podešavanje aplikacije %s" - "Omogućite aplikaciju %s" - Potvrdite aplikaciju %s“ u Podešavanjima jezika i unosa. Tako joj odobravate pokretanje na uređaju.\" - "Aplikacija %s je već omogućena u Podešavanjima jezika i unosa, pa je ovaj korak gotov. Pređimo na sledeći!" + "Podešavanje aplikacije %s" + "Omogućite aplikaciju %s" + Potvrdite aplikaciju %s“ u Podešavanjima jezika i unosa. Tako joj odobravate pokretanje na uređaju.\" "Omogući u Podešavanjima" - "Prebacite na %s" - Zatim izaberite %s“ kao aktivni metod unosa teksta.\" + "Prebacite na %s" + Zatim izaberite %s“ kao aktivni metod unosa teksta.\" "Prebaci metode unosa" "Čestitamo, sve je spremno!" - "Sada možete da kucate u svim omiljenim aplikacijama pomoću %s." + "Sada možete da kucate u svim omiljenim aplikacijama pomoću %s." "Završeno" "Prikaži ikonu aplikacije" "Ikona aplikacije se prikazuje u pokretaču" - "Pomoćni rečnici" + "Pomoćni rečnici" "Rečnik je dostupan" - "Nema dostupnih rečnika" "Poslednje ažuriranje" "Podešavanja" "Izbriši" - "Verzija %1$s" - "Dodaj" + "Verzija %1$s" "Dodavanje u rečnik" "Prečica:" "Jezik:" "Unesite reč" "Opcionalna prečica" "Izmena reči" - "Nemate nijednu reč u korisničkom rečniku. Da biste dodali reč, dodirnite dugme Dodaj (+)." "Za sve jezike" "Još jezika…" " ABVGDĐEŽZIJKLLJMNNJOPRSTĆUFHCČDŽŠ" @@ -123,4 +107,4 @@ "Traži" "Pauza" "Čekaj" - \ No newline at end of file + diff --git a/app/src/main/res/values-be/strings.xml b/app/src/main/res/values-be/strings.xml index 6397a7448..0af4e4d33 100644 --- a/app/src/main/res/values-be/strings.xml +++ b/app/src/main/res/values-be/strings.xml @@ -17,7 +17,7 @@ Ўключыць раздзеленую клавіятуру Змена метадаў ўводу Клавіша змены мовы - %s мс. + %s мс. "Стандартныя сістэмныя" Падказваць выпраўленні на аснове імёнаў са спісу кантактаў "Персанальныя прапановы" @@ -50,20 +50,9 @@ "Іспанская (ЗША)" хінгліш сербская (Лацініца) - Англійская (Вялікабрытанія) (%s) - Англійская (ЗША) (%s) - Іспанская (ЗША) (%s) - Хінгліш (%s) - Сербская (%s) - %s (Традыцыйная) - %s (Кампактная) - стандартная (лацініца) - "Лацініца (QWERTY)" - "Лацініца (QWERTZ)" - "Лацініца (AZERTY)" - "Лацініца (Дворак)" - "Лацініца (Colemak)" - "Лацініца (ПК)" + %s (Традыцыйная) + %s (Кампактная) + стандартная "Эмодзі" "Дадаць" "Выдаліць" @@ -76,38 +65,33 @@ "Эмодзі для фізічнай клавіятуры" "Фізічная клавіша Alt паказвае ўсе даступныя эмодзі" "Па змаўчанні" - Вітаем ў %s + Вітаем ў %s з ўводам жэстамі Пачаць працу - "Далей" - Наладка %s - Ўключыць %s - Праверце праграму \"%s\" ў сваіх наладах «Мова і ўвод». Гэта дазволіць ёй працаваць на вашай прыладзе. - Праграма %s ўжо ўключана ў наладах «Мова і ўвод». Перайдзіце да наступнага кроку! + Наладка %s + Ўключыць %s + Праверце праграму \"%s\" ў сваіх наладах «Мова і ўвод». Гэта дазволіць ёй працаваць на вашай прыладзе. Ўключыць ў наладах - Пераключыцца на %s - Выберыце «%s» бягучым метадам ўводу. + Пераключыцца на %s + Выберыце «%s» бягучым метадам ўводу. Змена спосабаў ўводу Ўсё гатова! - Цяпер вы можаце пісаць ва ўсіх вашых любімых праграмах з дапамогай %s. + Цяпер вы можаце пісаць ва ўсіх вашых любімых праграмах з дапамогай %s. "Гатова" "Паказаць значок прыкладання" Паказаць значок праграмы ў панэлi запуску - "Дадатковыя слоўнікі" + "Дадатковыя слоўнікі" "Даступны слоўнік" - "Слоўнікаў няма" "Апошняе абнаўленне" "Налады" "Выдаліць" - Версія %1$s - "Дадаць" + Версія %1$s Дадаць ў слоўнік "Гарачая клавіша:" "Мова:" Ўвядзіце слова "Неабавязковая гарачая клавіша" "Рэдагаваць слова" - Ў карыстальніцкім слоўніку няма ніводнага слова. Каб дадаць слова, дакраніце да кнопкі «Дадаць» (+). "Для ўсіх моў" "Іншыя мовы…" " АБВГДЕЁЖЗІЙКЛМНОПРСТУЎФХЦЧШЫЬЭЮЯ'" @@ -117,7 +101,7 @@ Эксперыментальныя Рознае Без абмежаванняў - %s хв. + %s хв. Налады праверкі правапісу HeliBoard Клавіша эмодзі Налады HeliBoard @@ -147,7 +131,6 @@ Карыстацкая Карыстацкая (цёмная тэма) Аўтаматычны выбар колеру - Націсніце для прадпрагляду Абярыце колеру для тэксту і фону Фон клавіятуры Тэкст клавіш @@ -170,7 +153,7 @@ Паказаць функцыі, якія могуць застацца незаўважанымі Заўсёды паказваць лічбавы радок Выдаліць свайпам - %s (Акхор) + %s (Акхор) Павялічаныя клавішы Шкала вышыні клавіятуры Выяўленне URL-адрасу @@ -180,7 +163,6 @@ Паказваць падказкі пры доўгім націску Змяніць метад ўводу з дапамогай клавішы прабел Доўгі націск клавішы прабел адкрые меню выбару метаду ўводу - Алфавіт (Colemak Mod-DH) Выкарыстоўваць тэму сістэмы Стыль тэмы Закруглены @@ -190,7 +172,6 @@ Правядзіце пальцам ад клавішы выдалення, каб выбраць і выдаліць адразу большыя часткі тэксту Аўтаматычна ўстаўляць прабел пасля знакаў прыпынку пры ўводзе новага слова Аўтапрабел пасля знакаў прыпынку - Алфавіт (Workman) Знешні выгляд будзе адпавядаць наладам сістэмы Канфідэнцыяльнасць аўтавыпраўлення "Адрабіць" @@ -247,10 +228,9 @@ Раскладка Лакалізаваць лікавы радок Выкарыстоўваць асабісты слоўнік прылады для захоўвання вывучаных слоў - Кайтагская (%s) - %s (Прабгат) - %s (Себяольсік 390) - %s (Себяольсік фінальная) + %s (Прабгат) + %s (Себяольсік 390) + %s (Себяольсік фінальная) Выдаліць карыстальніцкі слоўнік «%s»? Шэраг з лічбамі Выберыце парадак ўсплывальных клавіш @@ -260,7 +240,6 @@ Воблачна Доўгі націск клавішы сімвалаў для лічбавай клавіятуры Скапіяваць бягучую раскладку - Задаць імя раскладкі Сапраўды выдаліць карыстацкую раскладку %s? Памылка загрузкі файла слоўніка кайтагскі @@ -315,7 +294,6 @@ Карычневы Ўвод жэстамі Захаваць лог - Алфавіт (Бепо) Замяніць карыстацкі слоўнік «%1$s»? \n \nБягучы слоўнік: \n%2$s \n \nНовы слоўнік: \n%3$s Без слоўніка вы будзеце атрымліваць прапановы толькі для ўведзенага раней тэксту.<br> \nВы можаце загрузіць слоўнікі %1$s або праверыць, ці можна загрузіць слоўнік для «%2$s» напрамую %3$s. сховішча, абароненае прыладай @@ -323,7 +301,7 @@ Дадаць слоўнік з файла Вага: Пошук - %s (Студэнцкая) + %s (Студэнцкая) Заўсёды пачынаць неадкладна Хаваць панэль інструментаў пры з\'яўленні прапаноў Замацоўваць клавішы панэлі інструментаў пры працяглым націску @@ -339,12 +317,11 @@ Пры націску кропкі або пунктуацыі будзе выкарыстана сярэдняя прапанова Гэта адключыць астатнія функцыі клавіш панэлі інструментаў пры працяглым націску Закрыць буфер абмену - %s (Пашыраная) + %s (Пашыраная) Эмодзі Выбраць замацаваныя клавішы панэлі інструментаў Панэль інструментаў Мансійская - Мансійская (%s) Паказаць больш колераў Функцыянальныя клавішы Функцыянальныя клавішы (Сімвалы) @@ -354,7 +331,6 @@ Захаваць у файл Скапіяваць у буфер абмену Загрузіць - Загрузка перазапіша бягучую тэму Старонка ўверх Старонка ўніз Пачатак старонкі @@ -370,5 +346,63 @@ Пераключыць лічбавую клавіятуру Дадаць самыя распаўсюджаныя варыянты (па змаўчанні) Выдаліць лішнія ўсплывальныя вокны - Прыбраць усплывальныя клавішы, якія прысутнічаюць у базавай раскладцы + Прыбраць усплывальныя клавішы, якія ўжо прысутнічаюць у базавай раскладцы + Плаваючы прадпрагляд + Бачыць прапанаванае слова падчас набору жэстамі + Раздзельная клавіятура + Вібрацыя ў рэжыме «Не турбаваць» + Уключыць падзеленую клавіятуру (альбомная) + Адлегласць падзелу (альбомная) + Перамяшчаць прадпрагляд падчас набору жэстамі + Час жыцця следа жэста + Аўтакарэкцыя спалучэнняў клавіш + Калі ўключана, спалучэнні клавіш могуць быць пашыраны з дапамогай аўтакарэкцыі + Маштаб ніжняга водступу (альбомная) + Маштаб бакавога водступу + Паказваць падказкі ў шэрагу з лічбамі + Мовы са слоўнікамі + Карыстацкі падтып + Радок эмодзі ўнізе + Радок буфера абмену ўнізе + Папярэджанне: раскладка ў дадзены момант выкарыстоўваецца + Наладзіць значкі + Сапраўды скінуць усе настроеныя значкі? + Шэраг з лічбамі + Усталяваць фонавы малюнак (альбомная) + Перавызначыць версію эмодзі + Даргінскі (Урахі) + Код клавішы + Сапраўды выдаліць %s? + Усталяваць карыстацкі шрыфт з файла + Калі не ўстаноўлена, будзе выкарыстоўвацца партрэтны малюнак + Раз\'яднальнік нулявой шырыні + Вы сапраўды хочаце выдаліць усе настроеныя коды клавіш? + Дадатковыя раскладкі + Функцыянальныя клавішы (вялікі экран) + Стыль значкоў + Злучальнік нулявой шырыні + Сметніца + Недапушчальнае імя + Выдаліць + Увод + Shift + Табуляцыя + Shift (націснута) + Маштаб шрыфта клавіятуры + Маштаб шрыфта адлюстравання эмодзі + Маштаб бакавога водступу (альбомная) + Код доўгага націску + Адлегласць змахвання для пераключэння мовы + Наладзіць коды клавіш панэлі інструментаў + Карыстацкі тэкст на клавішы прабела + Прабел (раскладка лічбаў) + Пераключыць бок рэжыму адной рукой + Знайсці і падзяліцца колерамі ў %s. + Знайсці і падзяліцца раскладкамі ў %s. + абмеркавання + Caps lock + Завяршыць рэжым адной рукой + Змяніць памер у рэжыме адной рукой + Галасавы ўвод адключаны + Паказаць / схаваць панэль інструментаў diff --git a/app/src/main/res/values-bg/strings.xml b/app/src/main/res/values-bg/strings.xml index db9082308..aa14f79d2 100644 --- a/app/src/main/res/values-bg/strings.xml +++ b/app/src/main/res/values-bg/strings.xml @@ -14,9 +14,9 @@ "Разширени" "Тема" "Активиране на разделената клавиатура" - "Други методи за въвеждане" + Превключване към други методи на въвеждане "Клавиш за превкл. на езика" - "%s милисек" + "%s милисек" "Станд. за системата" "Използване на имена от „Контакти“ за предложения и поправки" "Персонализ. предложения" @@ -49,20 +49,9 @@ "испански (САЩ)" "Хинглиш" "Сръбска (латиница)" - "английски (Великобр.) (%s)" - "английски (САЩ) (%s)" - "испански (САЩ) (%s)" - "Хинглиш (%s)" - "Сръбска (%s)" - "%s (традиционна клавиатура)" - "%s (компактна)" - "Без език (латиница)" - "латиница (QWERTY)" - "латиница (QWERTZ)" - "латиница (AZERTY)" - "латиница (Дворак)" - "латиница (Коулмак)" - "латиница (PC)" + "%s (традиционна клавиатура)" + "%s (компактна)" + "Без език" "Емотикони" "Добавяне" "Премахване" @@ -75,38 +64,33 @@ "Емотикони за физическа клавиатура" "При натискане на клавиша „Alt“ се показва панелът за емотикони" "Стандартно" - "Добре дошли в/ъв %s" + "Добре дошли в/ъв %s" "с въвеждане чрез жест" "Първи стъпки" - "Следваща стъпка" - "Настройване на %s" - "Активирайте %s" - Моля, проверете \\%s\" на вашите езици & входни настройки. Това ще го разреши да работи на вашето устройство.\" - "Приложението %s вече е активирано от „Език и въвеждане“, така че тази стъпка е изпълнена. Преминете към следващата!" + "Настройване на %s" + "Активирайте %s" + Моля, проверете \\%s\" на вашите Езици & входни настройки. Това ще го разреши да работи на вашето устройство. "Активиране в настройките" - "Превключете към %s" - След това изберете \\%s\"като ваш активен метод за въвеждане на текст.\" + "Превключете към %s" + След това изберете \"%s\" като активен метод за въвеждане на текст. "Превключване на методите на въвеждане" "Поздравления! Вече сте готови!" - Вече можете да пишете във всичките си любими приложения с %s. - "Край" + Вече можете да пишете във всичките си любими приложения с %s. + Завършено Показване на иконата на приложението "Показване на иконата на приложението в стартовия панел" - "Добавени речници" + "Добавени речници" "Речникът е налице" - "Няма налични речници" Последна актуализация "Настройки" "Изтриване" - "Версия %1$s" - "Добавяне" + Версия %s "Добавяне в речника" "Пряк път:" "Език:" "Напишете дума" "Незадължителен пряк път" "Редактиране на дума" - "Нямате думи в потребителския речник. За да добавите, докоснете бутона за добавяне (+)." "За всички езици" "Още езици…" " АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЬЪЮЯ" @@ -148,12 +132,12 @@ Архивиране и възстановяване Осигурете собствена библиотека, за да активирате писането с жестове Разделено разстояние - Превключете и двете + Превключване и на двете Предупреждение: Деактивирането на тази настройка ще изчисти научените данни Игнорирайте искането на други приложения за деактивиране на предложенията (може да причини проблеми) Повече автоматична корекция Изтриване на библиотека - Език + @string/subtype_locale Поведение на клавиша за превключване на език Автоматично коригиране, дори когато не е изрично поискано от полето за въвеждане Доверие за автоматично коригиране @@ -179,7 +163,7 @@ Автоматично вмъкване на интервал след препинателни знаци, когато пишете нова дума Неизвестен библиотечен файл. Сигурни ли сте, че сте го получили от доверен източник и е за \'%s\'? Покажи повече букви с диакритични знаци в изскачащ прозорец - Показване на варианти, дефинирани в езиците на клавиатурата + Покажи вариантите, дефинирани в езиците на клавиатурата Добавяне на общи варианти Езици и оформления Ред с числа @@ -207,7 +191,7 @@ Напълно вляво Напълно вдясно Затваряне на хронологията на клипборда - Изберете клавиши от лентата с инструменти за клипборд + Избиране на клавиши от лентата с инструменти за клипборд Закачи клавиш от лентата с инструменти при дълго натискане Цифрова клавиатура Персонализиран текст в лентата за интервал @@ -224,7 +208,7 @@ Продължителното натискане на клавиш със символи за цифровата клавиатура Клипборда долен ред Емотикони долен ред - Задайте фоново изображение + Задаване на фоново изображение Изберете език Файлът не може да се прочете Не показвай отново @@ -270,7 +254,6 @@ Задаване на основен и до 6 допълнителни символа на валута, разделени с интервал Изберете речник за добавяне. Речниците във формат .dict могат да бъдат изтеглени %s. Числа - Задайте име на оформлението Наистина ли изтривате персонализирано оформление %s? Добавете персонализирано оформление Изберете файл в съвместим формат. Информация за форматите е налична %s. @@ -315,7 +298,6 @@ Грешка при зареждането на речниковия файл Синьо сиво Кафяво - Кликнете за преглед Запазване на дневника Текст на лентата с предложения Клавиши фон @@ -339,7 +321,6 @@ Стил Закръглена Шоколадово - Зареждането ще презапише текущата тема Фон на клавиатурата Функционален клавишен фон Фон на интервала @@ -383,17 +364,14 @@ Пространство (оформление с числа) Пясък Изтриване - Мансийски (%s) - %s (Пробхат) - %s мин - %s (Себолсик 390) + %s (Пробхат) + %s мин + %s (Себолсик 390) Кайтагски - %s (Разширено) - Кайтагски (%s) - %s (Студент) - %s (Себолсик Финална) - %s (Akkhor) - Латиница (Бепо) + %s (Разширено) + %s (Студент) + %s (Себолсик Финална) + %s (Akkhor) ► Продължителното натискане на фиксирани клавиши на лентата с инструменти води до допълнителна функционалност: <br> \n\t• клипборд &#65515; паста <br> \n\t• движение наляво/надясно &#65515; дума ляво/дясно <br> @@ -431,14 +409,11 @@ \n► Когато използвате многоезично въвеждане, интервалът ще покаже стойност на достоверност, използвана за определяне на използвания в момента език. <br> <br> \n► Предложенията ще имат малки числа отгоре, показващи някакъв вътрешен резултат и изходен речник (може да бъде деактивиран). Мансийски - Латиница (Workman) - Латиница (Colemak Mod-DH) Кошче Наистина ли нулирате всички персонализирани икони? Вибриране в режим „Не ме безпокойте“ - %s (Фонетичен) + %s (Фонетичен) Замяна на версията на емотиконите - Уракски (%s) Даргва (Уракски) Преки пътища за автоматично коригиране Когато са активирани, преките пътища може да бъдат разширени чрез автоматично коригиране @@ -453,7 +428,7 @@ Мащаб на страничната подложка (пейзаж) Показване на подсказки на реда с числа Разстояние на плъзгане за превключване на езика - Разстояние на разделяне (пейзаж) + Разделно разстояние (пейзаж) Разделена клавиатура Активиране на разделена клавиатура (пейзаж) Наистина ли изтривате %s? @@ -466,5 +441,28 @@ раздел за обсъждане Можете да намирате и споделяте цветове в %s. Персонализиран подтип - %s (Байсахи) + %s (Байсахи) + Показване на TLD изскачащи клавиши + Заместване на изскачащите прозорци с клавиши за период с домейни от първо ниво при въвеждане на URL и имейл адреси + Натискане на въвеждане или интервал след други клавиши в цифровата клавиатура + Не винаги показвай предложения за полета за уеб редактиране + Полетата за уеб редактиране (най-вече в браузърите) са много честа причина за проблеми с настройката за винаги показване на предложения + Числов ред (основен) + Интервал + Автоматичен интервал преди въвеждане на дума с жест + Автоматичен интервал след избиране на предложение + Автоматичен интервал след въвеждане на дума с жест + Без автоматичен интервал при натискане на Shift + Обратен интервал връща автоматичното коригиране + Shift премахва чакащия автоматичен интервал + Формат на клавиша за времево клеймо + Сото + Дагбани + Мащабиране на размера на клавишите за емотикони с размера на шрифта + Резервното копие е възстановено + Търсене на имена на приложения + Използване на имената на инсталираните приложения за предложения и корекции + Тон на кожата на емотиконите по подразбиране + Неутрален + %1$s (%2$s) diff --git a/app/src/main/res/values-bn/strings.xml b/app/src/main/res/values-bn/strings.xml index afb898f87..b73d177c3 100644 --- a/app/src/main/res/values-bn/strings.xml +++ b/app/src/main/res/values-bn/strings.xml @@ -29,8 +29,8 @@ উভয় পরিবর্তন ভাষা পরিবর্তন বোতাম ইমোজি বোতাম - %s মিলিসেকেন্ড - %s মিনিট + %s মিলিসেকেন্ড + %s মিনিট সিস্টেম ডিফল্ট সীমাহীন পরামর্শ ও সংশোধনীর জন্য পরিচিতি থেকে নাম ব্যবহার @@ -66,13 +66,11 @@ বন্ধ থাকলে ক্লিপবোর্ড বোতাম ক্লিপবোর্ডে থাকা আধেয় পেস্ট করবে ইতিহাস স্থিতির সময়কাল বিলোপ অভিস্পর্শ - লেখার বড়ো অংশ একসাথে সিলেক্ট করে বিলোপ করার জন্য অভিস্পর্শ করুন + লেখার বড়ো অংশ একসাথে সিলেক্ট করে অপসারণ করার জন্য অভিস্পর্শ করুন বহুভাষী টাইপিং অঙ্গুলিহেলন টাইপিং লাইব্রেরি অধিযোগ অঙ্গুলিহেলনের মাধ্যমে টাইপিং সক্রিয় করার জন্য স্থানীয় লাইব্রেরি সরবরাহ - \'%s\' এর জন্য লাইব্রেরি প্রয়োজন। অসামঞ্জস্যপূর্ণ লাইব্রেরি ব্যবহার অঙ্গুলিহেলন টাইপিংয়ের সময় ক্রাশ করতে পারে। -\n -\nসতর্কতা: বাহ্যিক কোডের অধিযোজন নিরাপত্তা ঝুঁকির কারণ হতে পারে। বিশ্বস্ত উৎসের লাইব্রেরি ব্যবহার করুন। + \'%s\' এর জন্য লাইব্রেরি প্রয়োজন। অসামঞ্জস্যপূর্ণ লাইব্রেরি ব্যবহার অঙ্গুলিহেলন টাইপিংয়ের সময় ক্রাশ করতে পারে। \n\nসতর্কতা: বাহ্যিক কোডের অধিযোজন নিরাপত্তা ঝুঁকির কারণ হতে পারে। বিশ্বস্ত উৎসের লাইব্রেরি ব্যবহার করুন। লাইব্রেরি অধিযোগ লাইব্রেরি বিলোপ যতিচিহ্নের পরে স্বয়ংক্রিয় স্পেস @@ -99,28 +97,15 @@ অপরিদৃষ্ট হতে পারে এমন বৈশিষ্ট্যের বর্ণনা ডিভাইস সুরক্ষিত স্টোরেজ ► পিন করে রাখা টুলবার বোতামে দীর্ঘ চাপ দিলে তা অতিরিক্ত কাজ করবে: <br> \n\t• ক্লিপবোর্ড &#65515; পেস্ট <br> \n\t• বামে/ডানে স্থানান্তর &#65515; সম্পূর্ণ বামে/ডানে স্থানান্তর <br> \n\t• উপরে/নিচে স্থানান্তর &#65515; পৃষ্ঠার উপরে/নিচে <br> \n\t• শব্দের ডানে/বামে &#65515; লাইনের শুরু/শেষ <br> \n\t• পাতার উপরে/নিচে &#65515; পাতার শুরু/শেষ <br> \n\t• অনুলিপি &#65515; কর্তন <br> \n\t• শব্দ নির্বাচন &#8596; সমস্ত নির্বাচন <br> \n\t• পূর্বাবস্থা &#8596; পুনরাবৃত্তি <br> <br> \n► পরামর্শ ফলকের টুলবারের কোনো বোতামে দীর্ঘ চাপ দিলে তা পরামর্শ ফলকে আবদ্ধ হবে। <br> <br> \n► কমা বোতামে দীর্ঘ চাপ দিলে ক্লিপবোর্ড দর্শন, ইমোজি দর্শন, একক হাত মোড, সেটিংস অথবা ভাষা পরিবর্তন বোতাম উপলব্ধ হবে:<br> \n\t• সংশ্লিষ্ট বোতাম সক্ষম থাকলে ইমোজি দর্শন বা ভাষা পরিবর্তন বোতাম দৃশ্যমান থাকবে না; <br> \n\t• কিছু লেআউটের জন্য কমা বোতাম নয়, কিন্তু একই জায়গার বোতামটি, যেমন: Dvorak লেআউটে \'q\' বোতাম। <br> <br> \n► ছদ্মবেশী মোড সক্রিয় থাকলে শব্দ শিখন বন্ধ থাকবে, এবং সাম্প্রতিকে কোনো ইমোজি যুক্ত হবে না। <br> <br> \n► ছদ্মবেশী বোতামে চাপ দিলে টুলবার উপলব্ধ হবে। <br> <br> \n► স্লাইডিং কি ইনপুট: বড়ো হাতের অক্ষর লেখার জন্য শিফট বোতাম থেকে অন্য বোতামে অভিস্পর্শ করুন: <br> \n\t• সিম্বল কিবোর্ড থেকে সিম্বল এবং সম্পর্কিত অক্ষর লেখার জন্য \'?123\' বোতামেও এটি কাজ করে।<br> <br> \n► শিফট অথবা প্রতীক বোতাম চেপে ধরে এক বা একাধিক বোতাম চাপার পর শিফট অথবা প্রতীক বোতাম ছেড়ে দিলে তা পূর্ববর্তী কিবোর্ডে নিয়ে যাবে। <br> <br> \n► পরামর্শ ফলকে কোনো পরামর্শে দীর্ঘ চাপ দিলে আরও পরামর্শ, বিলোপ করার জন্য অপসারণ বোতাম প্রদর্শিত হবে। <br> <br> \n► আরও পরামর্শ খুলতে কোনো পরামর্শ থেকে উপরে অভিস্পর্শ করুন এবং নির্দিষ্ট পরামর্শ নির্বাচনের জন্য ছেড়ে দিন। <br> <br> \n► ক্লিপবোর্ড ইতিহাসে কোনো অন্তর্ভুক্তিতে দীর্ঘ চাপ দিয়ে তা পিন করা যাবে (আনপিন না করা পর্যন্ত তা ক্লিপবোর্ডে থাকবে) \n► ক্লিপবোর্ড দর্শনে বাম পাশে অভিস্পর্শ করলে অন্তর্ভুক্তি অপসারণ হবে (যদি না সেটি পিন করা থাকে)। <br> <br> \n► লেখা সিলেক্ট করে শিফট চাপলে তা বড়ো হাতের অক্ষর, ছোটো হাতের অক্ষর এবং সব অক্ষর বড়ো হাতের হবে। <br> <br> \n► আপনি ফাইল এক্সপ্লোরারে খোলার মাধ্যমে অভিধান সংযুক্ত করতে পারেন: <br> \n\t• এটি কেবল <i>content-uris</i> এর সাথে কাজ করে, <i>file-uris</i> এর সাথে নয়। অর্থাৎ কিছু ফাইল এক্সপ্লোরারের সাথে নাও কাজ করতে পারে। <br> <br> \n► রুট উপলব্ধতাসহ ম্যানুয়াল ব্যাকআপ করা ব্যবহারকারীদের জন্য: <br> \nঅ্যান্ড্রয়েড ৭ থেকে শেয়ারড্ প্রেফারেন্স ফাইল ডিফল্ট জায়গা নয়। কারণ অ্যাপ %s ব্যবহার করছে। ডিভাইস আনলকের আগে সেটিংস খোলার জন্য এটি প্রয়োজনীয়, যেমন: বুট করার সময়। <br> \nফাইলটি /data/user_de/0/package_id/shared_prefs/ থাকে। যদিও এটা ডিভাইস এবং অ্যান্ড্রয়েড সংস্করণের উপরে নির্ভর করে। <br> <br> \n<i><b>কেবল ডিবাগ এপিকে</b></i> <br> <br> \n► পরামর্শে দীর্ঘ চাপ দিলে তার উৎস-অভিধান দেখাবে। <br> <br> \n► ডিবাগ সেটিংস উচ্চতর সেটিংসে উপলব্ধ। যদিও লগ ফাইলে অভিধান অবমুক্ত করা ছাড়া এর ব্যবহারযোগ্যতা সীমিত। <br> \n\t• রিলিজ এপিকে এর জন্য <i>সম্পর্কে</i> এর সংস্করণে কয়েকবার চাপ দিতে হবে। তাহলে <i>উচ্চতর</i>-এ ডিবাগ সেটিংস উপলব্ধ হবে। <br> \n\t• <i>পরামর্শ তথ্য প্রদর্শন</i> চালু করলে পরামর্শের উপরে কিছু ছোটো নম্বর থাকবে যা অভ্যন্তরীণ হিসাব ও উৎস অভিধান নির্দেশ করে। <br> <br> \n► অ্যাপ্লিকেশন ক্র্যাশের পরে সেটিংস খুললে আপনি ক্র্যাশ লগ চান কি না তা জিজ্ঞেস করা হবে৷ <br> <br> \n► বহুভাষী টাইপিং ব্যবহারের সময় স্পেসবার বর্তমান ভাষা নির্ধারণের জন্য একটি দৃঢ়তা মান দেখাবে। <br> <br> \n► পরামর্শের উপরে কিছু ছোটো নম্বর থাকবে যা অভ্যন্তরীণ হিসাব ও উৎস অভিধান নির্দেশ করে (নিষ্ক্রিয় করা যেতে পারে)। - সার্বীয় (ল্যাটিন) - ইংরেজি (ইউকে) (%s) - ইংরেজি (ইউএস) (%s) - স্প্যানিশ (ইউএস) (%s) - হিংলিশ (%s) - সার্বিয়ান (%s) - %s (প্রথাগত) - %s (অক্ষর) - %s (প্রভাত) - %s (বৈশাখী) - %s (সংক্ষিপ্ত) - %s (সেবালসিক 390) - %s (সেবালসিক Final) - ভাষাহীন (বর্ণমালা) - বর্ণমালা (QWERTY) - বর্ণমালা (QWERTZ) - বর্ণমালা (AZERTY) - বর্ণমালা (Dvorak) - বর্ণমালা (Colemak) - বর্ণমালা (Colemak Mod-DH) - আলফাবেট (ওয়ার্কম্যান) - বর্ণমালা (PC) + সার্বিয়ান (ল্যাটিন) + %s (প্রথাগত) + %s (অক্ষর) + %s (প্রভাত) + %s (বৈশাখী) + %s (সংক্ষিপ্ত) + %s (সেবালসিক ৩৯০) + %s (সেবালসিক চূড়ান্ত) + ভাষাহীন ইমোজি সংযুক্ত করুন অপসারণ করুন @@ -133,62 +118,50 @@ ভৌত কিবোর্ডের জন্য ইমোজি ভৌত Alt বোতামে ইমোজি প্যালেট প্রদর্শন ডিফল্ট - %s এ স্বাগত\" + %s এ স্বাগত অঙ্গুলিহেলন টাইপিংয়ের সাথে শুরু করা যাক - পরবর্তী পদক্ষেপ - %s সন্নিবেশিত হচ্ছে\" - %s সক্ষম করুন\" - "ভাষা ও ইনপুট সেটিংসে \"%s\" সক্রিয় করুন। ফলে এটি আপনার ডিভাইসে চলার অনুমোদন পাবে।" - "আপনার ভাষা ও ইনপুট সেটিংসে ইতোমধ্যে %s সক্ষম করা হয়েছে; তাই এই পদক্ষেপটি সমাপ্ত হয়েছে। পরবর্তীটিতে যান!" + %s সন্নিবেশিত হচ্ছে + %s সক্ষম করুন + ভাষা ও ইনপুট সেটিংসে \"%s\" সক্রিয় করুন। ফলে এটি আপনার ডিভাইসে চলার অনুমোদন পাবে। সেটিংসে সক্ষম করুন - %s এ পরিবর্তন করুন\" - এখন সক্রিয় লিখন-ইনপুট পদ্ধতি হিসেবে \\%s\" বেছে নিন।\" + %s এ পরিবর্তন করুন + এখন সক্রিয় লিখন-ইনপুট পদ্ধতি হিসেবে \"%s\" বেছে নিন। ইনপুট পদ্ধতি পরিবর্তন "অভিনন্দন, আপনি পুরোপুরি প্রস্তুত!" - এখন %s দিয়ে আপনার সব পছন্দের অ্যাপে লিখতে পারবেন। + এখন %s দিয়ে আপনার সব পছন্দের অ্যাপে লিখতে পারবেন। কিবোর্ড সংস্থাপন সম্পন্ন অ্যাপ আইকন প্রদর্শন লঞ্চারে অ্যাপ আইকন প্রদর্শন - অ্যাড-অন অভিধান + অ্যাড-অন অভিধান অভিধান অভ্যন্তরীণ মূল অভিধান "ফাইল থেকে অভিধান সংযুক্তি" ভাষা নির্বাচন - ব্যবহারকারী-যোগকৃত অভিধান \"%1$s\" প্রতিস্থাপন করতে নিশ্চিত? -\n -\nবর্তমান অভিধান: -\n%2$s -\n -\nনতুন অভিধান: -\n%3$s + ব্যবহারকারী-যোগকৃত অভিধান \"%1$s\" প্রতিস্থাপন করতে নিশ্চিত?\nবর্তমান অভিধান: %2$s\nনতুন অভিধান: %3$s "অভিধান প্রতিস্থাপন" ব্যবহারকারী-সংযুক্ত অভিধান \"%s\" অপসারণ করতে নিশ্চিত? - "অভিধান ব্যতীত কেবল পূর্বে সন্নিবেশিত শব্দের জন্য পরামর্শ পাওয়া যাবে।<br> - আপনি %1$s অভিধান ডাউনলোড করতে পারেন, অথবা \"%2$s\" এর জন্য অভিধান সরাসরি ডাউনলোড করা যায় কি না %3$s যাচাই করতে পারেন।" + অভিধান ব্যতীত কেবল পূর্বে সন্নিবেশিত শব্দের জন্য পরামর্শ পাওয়া যাবে।<br> আপনি %1$s অভিধান ডাউনলোড করতে পারেন, অথবা \"%2$s\" এর জন্য অভিধান সরাসরি ডাউনলোড করা যায় কি না %3$s যাচাই করতে পারেন। পুনরায় প্রদর্শিত হবে না অভিধান যোগ করার জন্য নির্বাচন করুন। %s .dict ফরম্যাটে অভিধান ডাউনলোড করা যেতে পারে। ত্রুটি: এই কিবোর্ডের সাথে সামঞ্জস্যপূর্ণ স্ক্রিপ্ট নয় এখানে "ত্রুটি: নির্বাচিত ফাইলটি বৈধ অভিধান ফাইল নয়" "নির্বাচিত ফাইলটি %1$s এর জন্য, %2$s এর জন্য ফাইল প্রয়োজন। তবুও %2$s এর জন্য ব্যবহৃত হবে?" - "তবুও ব্যবহার করুন" + তবুও ব্যবহৃত হবে অভিধান ফাইল অধিযোজন করতে ত্রুটি অভিধান উপলব্ধ - কোনো অভিধান উপলব্ধ নয় সর্বশেষ আপডেট সেটিংস বিলোপ করুন - সংস্করণ %1$s - সংযুক্ত করুন + সংস্করণ %s অভিধানে যোগ শর্টকাট: ভাষা: শব্দ টাইপ করুন ঐচ্ছিক শর্টকাট শব্দ সম্পাদনা - ব্যবহারকারী অভিধানে আপনার কোনো শব্দ নেই। শব্দ যোগ করতে (+) বোতামটি ট্যাপ করুন। সব ভাষার জন্য আরও ভাষা… \u0020অআইঈউঊঋএঐওঔংঃকখগঘঙচছজঝঞটঠডঢণতথদধনপফবভমযরলশষসহ @@ -207,7 +180,6 @@ ব্যবহারকারী নির্ধারিত ব্যবহারকারী নির্ধারিত (অন্ধকার) স্বয়ংক্রিয় রং নির্বাচন - প্রাগ্‌দর্শনের জন্য ক্লিক করুন লেখা এবং পটভূমির জন্য রং নির্বাচন কিবোর্ডের পটভূমি বোতামের লেখা @@ -247,7 +219,6 @@ অপরিচিত লাইব্রেরি ফাইল। আপনি কি নিশ্চিত যে এটি একটি বিশ্বস্ত উৎস থেকে প্রাপ্ত এবং \'%s\' এর জন্য? পরিবর্তনশীল রং কাইডাগ - কাইডাগ (%s) কেবল মূল রং প্রদর্শন প্রতীক প্রতীক (আরবি) @@ -260,7 +231,7 @@ বোতামের ইঙ্গিতের উৎস পপআপ বোতামের ক্রমিক নির্ধারণ নম্বর সারি - ভাষা + @string/subtype_locale ভাষা (অগ্রাধিকার) লেআউট প্রতীক @@ -277,7 +248,6 @@ ফাইল অধিযোগ অপঠনযোগ্য ফাইল বিদ্যমান লেআউট অনুলিপি - লেআউটের নাম লেআউট ত্রুটি: %s মূল লেআউট সম্পাদনা করতে ট্যাপ করুন অধিক প্রতীক @@ -318,7 +288,6 @@ টুলবার বোতাম নির্বাচন সম্পূর্ণ ডান নিম্ন প্যাডিং স্কেল - বর্ণমালা (Bépo) সামঞ্জস্যপূর্ণ ফরম্যাটে ফাইল নির্বাচন করুন। %s ফরম্যাট সম্পর্কিত তথ্য রয়েছে। নিজস্বীকৃত লেআউট সংযুক্তি নিজস্বীকৃত লেআউট %s বিলোপ করতে নিশ্চিত? @@ -333,7 +302,7 @@ টুলবারের পরিবর্তনশীল দিক ডান থেকে বাম কিবোর্ড নির্বাচন করলে দিক বিপরীত হবে ভাষা পরিবর্তন অভিস্পর্শের দূরত্ব - %s (শিক্ষার্থী) + %s (শিক্ষার্থী) ভাষা পরিবর্তন বোতামের আচরণ পিন করে রাখা টুলবার বোতাম নির্বাচন টুলবার বোতামে দীর্ঘ চাপ পিন করবে @@ -344,13 +313,12 @@ স্বয়ংক্রিয় টুলবার প্রদর্শন ক্লিপবোর্ড ইতিহাস বন্ধকরণ ক্লিপবোর্ড টুলবার বোতাম নির্বাচন - %s (বর্ধিত) + %s (বর্ধিত) ইমোজি টুলবার সর্বদা মধ্যবর্তী পরামর্শ ব্যবহার করবে স্পেস বা বিরামচিহ্ন চাপ দিলে মধ্যবর্তী পরামর্শ সন্নিবেশিত হবে মানসি - মানসি (%s) পিন করা নেই এমন অন্য টুলবার বোতামের দীর্ঘচাপের কার্যাবলি নিষ্ক্রিয় করবে অধিক রং প্রদর্শন এই সেটিংস অভ্যন্তরীণভাবে ব্যবহৃত সকল রং প্রকাশ করে। রঙের তালিকা যেকোনো সময় পরিবর্তিত হতে পারে। ডিফল্ট রং যেকোনো একটি হতে পারে এবং রঙের নাম অনুবাদ করা হবে না। @@ -364,7 +332,6 @@ ফাইল হিসেবে সংরক্ষণ ক্লিপবোর্ডে অনুলিপি অধিযোগ - অধিযোজন করলে তা বর্তমান থিমকে প্রতিস্থাপন করবে শব্দের বাম শব্দের ডান পাতার উপর @@ -411,10 +378,9 @@ বিলোপাধার নিজস্বীকৃত আইকন পুনঃসংস্থাপন করতে নিশ্চিত? বিরক্ত করবেন না মোডে কম্পন - %s (ফোনেটিক) + %s (ফোনেটিক) ইমোজি সংস্করণ অগ্রাহ্যকরণ দারগয়া (উরাখি) - উরাখি (%s) স্বতঃসংশোধন শর্টকাট সক্রিয় থাকলে স্বতঃসংশোধন দ্বারা শর্টকাট বর্ধিত হতে পারে ফাইল থেকে নিজস্বীকৃত ফন্ট নির্ধারণ @@ -437,7 +403,30 @@ অভিধানসহ ভাষা আলোচনা বিভাগ সতর্কতা: লেআউট বর্তমানে ব্যবহৃত হচ্ছে - আপনি %s-তে রং খোঁজা ও শেয়ার করতে পারেন। - আপনি %s-তে লেআউট খোঁজা ও শেয়ার করতে পারেন। + আপনি %s-তে রং সন্ধান ও শেয়ার করতে পারেন। + আপনি %s-তে লেআউট সন্ধান ও শেয়ার করতে পারেন। নিজস্বীকৃত সাবটাইপ + টিএলডি পপআপ বোতাম প্রদর্শন + ইউআরএল ও ইমেইল ঠিকানা লেখার জন্য দাঁড়ি বোতাম টপ লেভেল ডোমেইন দ্বারা প্রতিস্থাপন + নম্বর প্যাডে অন্য বোতামের পরে এন্টার বা স্পেস চাপ + নম্বর সারি (প্রাথমিক) + ওয়েব সম্পাদনা ফিল্ডে সর্বদা পরামর্শ প্রদর্শন করবে না + ওয়েব সম্পাদনা ফিল্ড (প্রধানত ব্রাউজারে উপলভ্য) সর্বদা পরামর্শ প্রদর্শন সেটিংসে সমস্যার একটি সাধারণ কারণ + স্পেস + অঙ্গুলিহেলন টাইপিংয়ের শব্দের পরে স্বয়ংক্রিয় স্পেস + অঙ্গুলিহেলন টাইপিংয়ের শব্দের পূর্বে স্বয়ংক্রিয় স্পেস + শিফট চাপের পরে স্বয়ংক্রিয় স্পেস নয় + ব্যাকস্পেস দ্বারা স্বতঃসংশোধন প্রত্যাবর্তন + পরামর্শ বাছাইয়ের পরে স্বয়ংক্রিয় স্পেস + শিফট অনিষ্পাদিত স্বয়ংক্রিয় স্পেস অপসারণ করবে + টাইমস্ট্যাম্পের ফরম্যাট + সেসুতু + ডাগবানি + ফন্টের আকারের সাথে ইমোজি বোতামের আকারের সমন্বয় + ব্যাকআপ পুনরুদ্ধার হয়েছে + অ্যাপের নামে সন্ধান + পরামর্শ ও সংশোধনের জন্য ইন্সটলকৃত অ্যাপের নাম ব্যবহার + ডিফল্ট ইমোজির ত্বকের রং + নিরপেক্ষ + %1$s (%2$s) diff --git a/app/src/main/res/values-bs/strings.xml b/app/src/main/res/values-bs/strings.xml index 17f43c24c..e5a022ba4 100644 --- a/app/src/main/res/values-bs/strings.xml +++ b/app/src/main/res/values-bs/strings.xml @@ -18,7 +18,7 @@ "Omogući podijeljenu tastaturu" "Prebacite na druge načine unosa" "Tipka za zamjenu jezika" - "%sms" + "%sms" "Sistemski zadano" "Za prijedloge i ispravke koristi imena iz Kontakata" "Prilagođeni prijedlozi" @@ -51,20 +51,9 @@ "španski (SAD)" "Hindu engleski" "Srpski (latinica)" - "Engleski (UK) (%s)" - "Engleski (SAD) (%s)" - "Španski (SAD) (%s)" - "Hindu engleski (%s)" - "Srpski (%s)" - "%s (tradicionalan)" - "%s (kompaktan)" - "Nema jezika (abeceda)" - "Abeceda (QWERTY)" - "Abeceda (QWERTZ)" - "Abeceda (AZERTY)" - "Abeceda (Dvorak)" - "Abeceda (Colemak)" - "Abeceda (PC)" + "%s (tradicionalan)" + "%s (kompaktan)" + "Nema jezika" "Emoji" "Dodaj" "Ukloni" @@ -77,38 +66,33 @@ "Emoji za fizičku tastaturu" "Tipka Alt na fizičkoj tastaturi aktivira paletu za emoji" "Zadano" - "Dobro došli u aplikaciju %s" + "Dobro došli u aplikaciju %s" "s Pisanjem pokretima" "Započnite" - "Sljedeći korak" - "Postavljanje aplikacije %s" - "Omogući aplikaciju %s" - "Označite aplikaciju \"%s\" u postavkama odjeljka Jezici i unos. Na taj način ćete joj dozvoliti da se pokrene na vašem uređaju." - "Aplikacija %s je već omogućena u vašim postavkama odjeljka Jezici i unos, tako da je ovaj korak završen. Pređite na sljedeći!" + "Postavljanje aplikacije %s" + "Omogući aplikaciju %s" + "Označite aplikaciju \"%s\" u postavkama odjeljka Jezici i unos. Na taj način ćete joj dozvoliti da se pokrene na vašem uređaju." "Omogući u Postavkama" - "Prebacite se na aplikaciju %s" - "Zatim odaberite aplikaciju \"%s\" kao vaš aktivni način unosa teksta." + "Prebacite se na aplikaciju %s" + "Zatim odaberite aplikaciju \"%s\" kao vaš aktivni način unosa teksta." "Zamijeni načine unosa" "Odlično, sve je spremno!" - "Sada možete upisivati u svim omiljenim aplikacijama pomoću aplikacije %s." + "Sada možete upisivati u svim omiljenim aplikacijama pomoću aplikacije %s." "Završeno" "Prikaži ikonu aplikacije" "Prikazivanje ikone aplikacije na pokretaču" - "Dodatni rječnici" + "Dodatni rječnici" "Rječnik je dostupan" - "Nema dostupnih rječnika" "Posljednji put ažurirano" "Postavke" "Izbriši" - "Verzija %1$s" - "Dodaj" + "Verzija %1$s" "Dodaj u rječnik" "Prečica:" "Jezik:" "Unesite riječ" "Opcionalna prečica" "Uređivanje riječi" - "Nemate nijednu riječ u korisničkom rječniku. Za dodavanje riječi, dodirnite dugme Dodaj (+)" "Za sve jezike" "Više jezika…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" diff --git a/app/src/main/res/values-ca/strings.xml b/app/src/main/res/values-ca/strings.xml index a2ffde555..1749c605e 100644 --- a/app/src/main/res/values-ca/strings.xml +++ b/app/src/main/res/values-ca/strings.xml @@ -16,7 +16,7 @@ Activa el teclat dividit "Altres mètodes d\'introducció" "Tecla de canvi d\'idioma" - %s ms + %s ms "Predeterminat" "Utilitza els noms de contactes per fer suggeriments i correccions" "Suggeriments personalitzats" @@ -49,20 +49,9 @@ "Espanyol (EUA)" Hinglish "Serbi (llatí)" - Anglès (Regne Unit) (%s) - Anglès (EUA) (%s) - Espanyol (EUA) (%s) - Hinglish (%s) - Serbi (%s) - %s (Tradicional) - %s (Compacte) - Cap idioma (alfabet) - "Alfabet (QWERTY)" - "Alfabet (QWERTZ)" - "Alfabet (AZERTY)" - "Alfabet (Dvorak)" - "Alfabet (Colemak)" - "Alfabet (PC)" + %s (Tradicional) + %s (Compacte) + Cap idioma Emojis "Afegeix" "Elimina" @@ -75,38 +64,33 @@ Emojis amb el teclat físic Amb la tecla Alt del teclat físic es mostra la paleta d\'emojis "Predeterminat" - Us donem la benvinguda a %s + Us donem la benvinguda a %s amb escriptura gestual "Comença" - "Pas següent" - S\'està configurant %s - Habilitar %s - Comproveu \\%s\" a la configuració d\'idiomes i entrada. Això li permetrà executar-se al vostre dispositiu.\" - %s ja està activada a la configuració d\'idiomes i entrada, així que ja s\'ha acabat aquest pas. Cap al següent!\" + S\'està configurant %s + Habilitar %s + Comproveu «%s» a la configuració d\'idiomes i entrada. Això li permetrà executar-se al vostre dispositiu. Habilita a la configuració - Canviar a %s - A continuació, seleccioneu \\%s\" com a mètode d\'entrada de text actiu.\" + Canviar a %s + A continuació, seleccioneu «%s» com a mètode d\'entrada de text actiu. Canvia els mètodes d\'entrada "Enhorabona, ja has acabat!" - Ara ja podeu escriure en totes les vostres aplicacions preferides amb %s. + Ara ja podeu escriure en totes les vostres aplicacions preferides amb %s. "Finalitzat" "Mostra la icona de l\'aplicació" "Mostra la icona de l\'aplicació al menú d\'aplicacions" - "Diccionaris complementaris" + "Diccionaris complementaris" "Diccionari disponible" - "Cap diccion. dispon." "Última actualització" "Configuració" "Suprimeix" - Versió %1$s - "Afegeix" + Versió %s "Afegeix al diccionari" "Drecera:" "Idioma:" "Escriu una paraula" "Drecera opcional" "Edició de la paraula" - "No tens cap paraula al diccionari de l\'usuari. Toca el botó Afegeix (+) per afegir-n\'hi una." "Per a tots els idiomes" "Més idiomes…" " ABCÇDEFGHIJKLMNOPQRSTUVWXYZ" @@ -116,7 +100,7 @@ Temps de manteniment a l\'historial Llisqueu damunt de la tecla d\'esborrar per seleccionar i treure grans parts de text d\'un sol cop Força el mode d\'incògnit - %s min + %s min Corrector ortogràfic de l\'HeliBoard Configuració del corrector ortogràfic de l\'HeliBoard Esborra amb lliscament @@ -141,11 +125,9 @@ Mantenint premuda la barra espaiadora s\'obrirà el menú de selecció del mètode d\'entrada Canvia el mètode d\'entrada amb la barra espaiadora Mostra consells quan es mantingui premuda una tecla - %s (Akkhor) + %s (Akkhor) Escala de l\'alçada del teclat - Alfabet (Workman) L\'aspecte seguirà la configuració del sistema - Alfabet (Colemak Mod-DH) Confidència d\'autocorrecció "Utilitza els idiomes del sistema" Selecciona un mètode d\'entrada @@ -197,7 +179,7 @@ Prefereix els localitzats als nombres llatins Fixa la tecla de la barra d\'eines en prémer llargament Fila de nombres - Idioma + @string/subtype_locale Idioma (prioritat) Selecciona l\'origen del consell Disposició @@ -214,7 +196,6 @@ Eliminar realment el diccionari afegit per l\'usuari «%s»? Selecciona les tecles de la barra d\'eines del porta-retalls Tanca l\'historial del porta-retalls - Estableix el nom de la disposició Símbols (Àrab) Símbols Carrega @@ -234,10 +215,9 @@ Dreta Idiomes i disposicions Kaytak - %s (Estès) + %s (Estès) Carrega fitxer - %s (Fonètic) - Alfabet (Bépo) + %s (Fonètic) Afegeix una disposició personalitzada Copia al porta-retalls Copia la disposició existent @@ -245,7 +225,6 @@ Telefon Anul·la la versió d\'emojis Darguà (Urakhi) - Darguà (%s) Símbols telefònics Nombres Teclat numèric @@ -282,7 +261,6 @@ Esborra el porta-retalls Entrada de veu Estableix un tipus de lletra personalitzat des de fitxer - Mansi (%s) Teclat numèric (apaïsat) Estableix imatge de fons (apaïsat) Si no s\'estableix, s\'utilitzarà la imatge vertical @@ -290,11 +268,10 @@ Establir la imatge per al mode dia o nocturn? Dia Nit - %s (Probhat) + %s (Probhat) Mostra consells funcionals - Kaytak (%s) - %s (Sebeolsik 390) - %s (Sebeolsik Final) + %s (Sebeolsik 390) + %s (Sebeolsik Final) Canvia al teclat principal després de… Seleccionar l\'entrada de l\'historial del porta-retalls Seleccionar emoji a la visualització d\'emojis @@ -306,7 +283,7 @@ Tecles funcionals (Símbols) Tecles funcionals (Més símbols) Mansi - %s (Estudiant) + %s (Estudiant) Blau Gris Tancar Llicència pública general GNU v3.0 @@ -353,8 +330,6 @@ Cap Codi de tecla Arrodonit - La càrrega sobreescriurà el tema actual - Feu clic per a una vista prèvia Mostra només els colors principals Aquesta configuració exposa tots els colors que s\'utilitzen internament. La llista de colors pot canviar en qualsevol moment. El color predeterminat és aleatori i els noms no es traduiran. Descripció de les característiques ocultes @@ -424,10 +399,33 @@ Tecles de funció (pantalla gran) Nom no vàlid Subtipus personalitzat - %s (Baishakhi) + %s (Baishakhi) Avís: la disposició s\'està utilitzant actualment Idiomes amb diccionaris Podeu trobar i compartir colors a %s. Podeu trobar i compartir disposicions a %s. secció de discussió + Substituir les finestres emergents de la tecla punt per dominis de primer nivell en escriure URLs i adreces de correu electrònic + Mostra tecles emergents de TLD + Prement Intro o espai després d\'altres tecles del teclat numèric + Els camps d\'edició web (sobretot que es troben als navegadors) són una causa molt freqüent de problemes amb la configuració Mostrar sempre suggeriments + Fila de nombres (bàsic) + No mostrar sempre suggeriments per als camps d\'edició web + Espai + Espai automàtic abans d\'escriure una paraula amb gest + Cap espai automàtic en prémer la majúscula + Espai automàtic després d\'escriure una paraula amb gest + Shift elimina l\'espai automàtic pendent + Retrocès reverteix l\'auto-correcció + Espai automàtic després de triar suggeriment + Format de la clau de marca de temps + Dagbani + Sesotho + Escala la mida de la tecla emoji amb la de la font + Tema d\'emoji predeterminat + Còpia de seguretat restaurada + Cercar noms d\'aplicacions + Utilitzar els noms de les aplicacions instal·lades per a suggeriments i correccions + Neutre + %1$s (%2$s) diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index cec8a5419..dbb74c6b4 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -17,7 +17,7 @@ "Aktivovat rozdělenou klávesnici" "Přepínat metody zadávání" "Klávesa přepínání jazyka" - "%s ms" + "%s ms" "Výchozí nastavení" Použít jména ze seznamu kontaktů k návrhům a opravám "Personalizované návrhy" @@ -48,22 +48,11 @@ "Angličtina (Velká Británie)" "Angličtina (USA)" "Španělština (USA)" - hinglish + Hinglish srbština (Latinka) - "Angličtina (Velká Británie) (%s)" - "Angličtina (USA) (%s)" - "Španělština (USA) (%s)" - hinglish (%s) - "Srbština (%s)" - "%s (Tradiční)" - "%s (Kompaktní)" - standardní (Latinka) - "Latinka (QWERTY)" - "Latinka (QWERTZ)" - "Latinka (AZERTY)" - "Latinka (Dvorak)" - "Latinka (Colemak)" - "Latinka (PC)" + "%s (Tradiční)" + "%s (Kompaktní)" + standardní "Emodži" "Přidat" "Odebrat" @@ -76,38 +65,33 @@ "Emodži pro fyzickou klávesnici" Paletu emodži zobrazíte stisknutím fyzické klávesy Alt "Výchozí" - "Vítá vás %s" + "Vítá vás %s" "s psaním gesty" "Začínáme" - "Další krok" - "Nastavení aplikace %s" - "Zapnutí aplikace %s" - Zaškrtněte aplikaci%s v nastavení Jazyky a zadávání, povolíte tak její spuštění.\" - Aplikace %s je již v nastavení Jazyky a zadávání zapnuta, tento krok je tedy již proveden. Pokračujte dalším! + "Nastavení aplikace %s" + "Zapnutí aplikace %s" + Povolte aplikaci „%s“ v nastavení Jazyky a zadávání. Tím povolíte její spuštění ve vašem zařízení. "Aktivovat v nastavení" - "Přepnutí na aplikaci %s" - Poté vyberte jako aktivní metodu zadávání textu možnost%s.\" + "Přepnutí na aplikaci %s" + Poté vyberte jako aktivní metodu zadávání textu možnost „%s“. "Přepnout metody zadávání" Gratulujeme, vše je připraveno! - "Nyní můžete ve všech svých oblíbených aplikacích psát pomocí aplikace %s." + Nyní můžete ve všech svých oblíbených aplikacích psát pomocí aplikace %s. "Hotovo" "Zobrazit ikonu aplikace" "Zobrazí ikonu aplikace ve spouštěči" - "Doplňkové slovníky" + "Doplňkové slovníky" "Slovník k dispozici" - "Žádné slovníky" "Poslední aktualizace" "Nastavení" "Smazat" - "Verze %1$s" - "Přidat" + Verze %s "Přidat do slovníku" "Zkratka:" "Jazyk:" "Napište slovo" "Volitelná zkratka" "Upravit slovo" - "V uživatelském slovníku nejsou žádná slova. Slovo můžete přidat klepnutím na tlačítko Přidat (+)." "Pro všechny jazyky" "Další jazyky…" " ABCČDEFGHChIJKLMNOPQRŘSŠTUVWXYZŽ" @@ -117,7 +101,7 @@ "Vybrat metodu zadávání" Experimentální Různé - %smin. + %s min. Bez limitu Povolit historii schránky Doba zachování historie @@ -139,10 +123,8 @@ Vzhled podle systémového nastavení Nastavení HeliBoard Návrhy - Emoji klávesa - Abeceda (Workman) + Klávesa pro emodži Pokud vypnuto, tlačítko schránky vloží obsah schránky, pokud nějaký existuje - Abeceda (Colemak Mod-DH) Automatická mezera po znaménkách Více kláves Posuňte prstem z tlačítka Delete a mažte větší části textu společně @@ -165,7 +147,7 @@ Použít osobní slovník zařízení k ukládání naučených slovíček Další automatické opravy Automatické opravy, i když to není výslovně požadováno ve vstupním poli - Jazyk + @string/subtype_locale Denní Vždy používat prostřední návrh Po stisknutí mezery nebo interpunkčního znaménka se zadá prostřední návrh @@ -177,7 +159,7 @@ Načíst knihovnu Odstranit knihovnu Zobrazit další písmena s diakritikou ve vyskakovacím okně - Zobrazit varianty definované v jazycích klávesnice (výchozí) + Zobrazit varianty definované v jazycích klávesnice Přidat společné varianty Přidat všechny dostupné varianty Detekce URL @@ -218,10 +200,8 @@ Kaitag Zavřít historii schránky Výběr kláves panelu nástrojů schránky - Měřítko dolní výplně - Kaitag (%s) + Měřítko dolního odsazení Zkopírovat stávající rozložení - Nastavit název rozvržení Vybrat soubor v kompatibilním formátu. Informace o formátech jsou k dispozici %s. Symboly Symboly (arabské) @@ -245,7 +225,7 @@ Přesun kurzoru Svislé gesto přejetí mezerníku Ignorovat požadavek jiných aplikací na zakázání návrhů (může způsobit problémy) - "Bez slovníku se zobrazí pouze návrhy textu, který jste zadali dříve.<br>\n\n Můžete si stáhnout slovníky %1$s nebo zkontrolovat, zda lze slovník pro „%2$s“ stáhnout přímo %3$s." + "Bez slovníku se zobrazí pouze návrhy textu, který jste zadali dříve.<br>\n Můžete si stáhnout slovníky %1$s nebo zkontrolovat, zda lze slovník pro „%2$s“ stáhnout přímo %3$s." zde Vybrat slovník, který chcete přidat. Slovníky ve formátu .dict lze stáhnout %s. %s (experimentální) @@ -282,10 +262,9 @@ Hlasové zadávání Úplně vpravo Zobrazit tipy, pokud dlouhé stisknutí klávesy aktivuje další funkce - %s (Akkhor) - %s (Sebeolsik 390) - %s (Sebeolsik Final) - Abeceda (Bépo) + %s (Akkhor) + %s (Sebeolsik 390) + %s (Sebeolsik Final) Načíst soubor Přidat slovo Světlý @@ -307,20 +286,20 @@ \n \nVarování: načítání externího kódu může představovat bezpečnostní riziko. Používejte pouze knihovnu ze zdroje, kterému důvěřujete. Popis skrytých funkcí - %s (Rozšířené) - ► Dlouhým stisknutím klávesy schránky (volitelná v pruhu návrhů) vložíte obsah systémové schránky. <br> <br> ► Dlouhé stisknutí kláves na panelu nástrojů pruhu návrhů je připne na pruh návrhů. <br> <br> ► Dlouhým stisknutím klávesy čárka otevřete zobrazení schránky, zobrazení emodži, režim jedné ruky, nastavení nebo přepnutí jazyka: <br> • Zobrazení emodži a přepínání jazyků zmizí, pokud máte odpovídající klávesu povoleno; <br> • U některých rozvržení to není klávesa Comma, ale klávesa na stejné pozici (např. je to \'q\' pro rozvržení Dvorak). <br> <br> ► Když je povolen režim inkognito, nebudou se učit žádná slova a nebudou přidány žádné emotikony. <br> <br> ► Stisknutím ikony inkognito otevřete panel nástrojů. <br> <br> ► Zadávání pomocí posuvné klávesy: Přejetím z Shift na jinou klávesu zadejte jednu klávesu velkých písmen: <br> • Toto funguje také pro klávesu „?123“ pro psaní jediného symbolu z klávesnice se symboly a pro související klíče. <br> <br> ► Dlouhým stisknutím návrhu v pruhu návrhů zobrazíte další návrhy a stisknutím tlačítka Smazat tento návrh odstraníte. <br> <br> ► Přejetím prstem nahoru z návrhu otevřete další návrhy a uvolněním návrh jej vyberte. <br> <br> ► Dlouhým stisknutím položky v historii schránky ji připnete (uchovávejte ji ve schránce, dokud ji neuvolníte). <br> <br> ► Slovníky můžete přidávat tak, že je otevřete v průzkumníku souborů: <br> • Toto funguje pouze s <i>content-uris</i> a nikoli s <i>file-uris</i> , což znamená, že nemusí fungovat s některými průzkumníky souborů. <br> <br> <i>Režim ladění / ladění APK</i> <br> <br> • Dlouhým stisknutím návrhu zobrazíte zdrojový slovník.<br> <br> • Při použití ladícího souboru APK můžete najděte Nastavení ladění v Pokročilých předvolbách, i když užitečnost je omezená s výjimkou ukládání slovníků do protokolu. <br> <br> • V případě pádu aplikace budete při otevření Nastavení dotázáni, zda chcete protokoly o selhání. <br> <br> • Při použití vícejazyčného psaní bude mezerník zobrazovat hodnotu spolehlivosti používanou k určení aktuálně používaného jazyka. <br> <br> • Návrhy budou mít navrchu malá čísla zobrazující nějaké interní skóre a zdrojový slovník (lze vypnout). <br> <br> ► Pro uživatele, kteří provádějí ruční zálohování s přístupem root: Počínaje Androidem 7 není soubor sdílených předvoleb ve výchozím umístění, protože aplikace používá %s. <br> To je nezbytné, aby bylo možné načíst nastavení před odemknutím zařízení, např. při startu. <br> Soubor se nachází v /data/user_de/0/package_id/shared_prefs/, i když to může záviset na zařízení a verzi Androidu. + %s (Rozšířené) + ► Dlouhý stisk kláves na připnuté liště nástrojů vyvolá další funkce: <br> \n\t• schránka &#65515; vložit <br> \n\t• pohyb doleva/doprava &#65515; slovo doleva/doprava <br> \n\t• pohyb nahoru/dolů &#65515; stránka nahoru/dolů <br> \n\t• slovo doleva/doprava &#65515; začátek/konec řádku <br> \n\t• stránka nahoru/dolů &#65515; začátek/konec stránky <br> \n\t• kopírovat &#65515; vystřihnout <br> \n\t• vybrat slovo &#8596; vybrat vše <br> \n\t• zrušit &#8596; opakovat <br> <br> \n► Dlouhý stisk kláves v liště s návrhy je připne. <br> <br> \n► Dlouhý stisk klávesy čárky pro přístup k zobrazení schránky, zobrazení emodži, režimu pro jedno ruce, nastavení nebo přepnutí jazyka: <br> \n\t• Zobrazení emodži a přepnutí jazyka zmizí, pokud máte odpovídající klávesu povolenou; <br> \n\t• U některých rozložení to není klávesa čárky, ale klávesa na stejné pozici (např. u Dvorak rozložení je to klávesa \'q\'). <br> <br> \n► Při zapnutém inkognito režimu se nebudou učit žádná slova a žádná emodži nebudou přidána do historie. <br> <br> \n► Stiskněte ikonu inkognito pro přístup k liště nástrojů. <br> <br> \n► Posuvný vstup klávesy: Přejeďte od klávesy Shift na jinou klávesu pro napsání jednoho velkého písmene: <br> \n\t• Toto také funguje pro klávesu \'?123\' pro napsání jednoho symbolu z klávesnice symbolů a pro související klávesy. <br> <br> \n► Držte klávesu Shift nebo symbolu, stiskněte jednu nebo více kláves a pak uvolněte Shift nebo symbolovou klávesu pro návrat na předchozí klávesnici. <br> <br> \n► Dlouhý stisk návrhu v liště návrhů pro zobrazení více návrhů a tlačítko pro smazání tohoto návrhu. <br> <br> \n► Přejeďte prstem nahoru z návrhu pro otevření více návrhů a uvolněte prst na návrhu pro jeho výběr. <br> <br> \n► Dlouhý stisk položky v historii schránky pro její připnutí (udržení v schránce, dokud ji neodpinete). <br> <br> \n► Přejeďte prstem doleva ve zobrazení schránky pro odstranění položky (kromě případů, kdy je připnuta). <br> <br> \n► Vyberte text a stiskněte Shift pro přepínání mezi velkými písmeny, malými písmeny a velkými prvními písmeny slov. <br> <br> \n► Můžete přidat slovníky otevřením v průzkumníku souborů: <br> \n\t• Toto funguje pouze s <i>content-uris</i>, nikoliv s <i>file-uris</i>, což znamená, že to nemusí fungovat u některých průzkumníků souborů. <br> <br> \n► Pro uživatele provádějící manuální zálohy s root přístupem: <br> \n\t• Začínaje Androidem 7, soubor sdílených preferencí není na výchozím místě, protože aplikace používá %s. To je nutné, aby nastavení mohla být přečtena před odemknutím zařízení, např. při spuštění; <br> \n\t• Soubor se nachází v /data/user_de/0/package_id/shared_prefs/, i když to může záviset na zařízení a verzi Androidu. <br> <br> \n<i><b>Režim ladění / ladící APK</b></i> <br> <br> \n► Dlouhý stisk návrhu pro zobrazení zdrojového slovníku. <br> <br> \n► Při používání ladícího APK najdete Nastavení ladění v pokročilých preferencích, i když jejich užitečnost je omezená, kromě dumpování slovníků do logu. <br> \n\t• Pro vydané APK je nutné několikrát stisknout verzi v <i>O aplikaci</i>, poté najdete nastavení ladění v <i>Pokročilých preferencích</i>. <br> \n\t• Při povolení <i>Zobrazit informace o návrzích</i> budou návrhy mít malá čísla nahoře ukazující interní skóre a zdrojový slovník. <br> <br> \n► Při pádu aplikace budete vyzváni, zda chcete získat záznamy o pádu, když otevřete Nastavení. <br> <br> \n► Při používání vícejazyčného psaní bude klávesa mezerníku zobrazovat hodnotu důvěry, která se používá k určení aktuálně používaného jazyka. <br> <br> \n► Návrhy budou mít malá čísla nahoře ukazující interní skóre a zdrojový slovník (může být vypnuto). Nelze přečíst soubor Další symboly Telefon Telefonní symboly - Opravdu nahradit uživatelem přidaný slovník „%1$s“? \n \nAktuální slovník: \n%2$s \n \nNový slovník: \n%3$s + Opravdu chcete nahradit uživatelem přidaný slovník „%1$s“?\n\nAktuální slovník:\n%2$s\n\nNový slovník:\n%3$s Nahradit slovník Opravdu odstranit slovník „%s“ přidaný uživatelem? Open-source licence GNU General Public License v3.0 Zavřít Klepnutím na jazyk otevřete nastavení - %s (Probhat) + %s (Probhat) Výběr barev pro text a pozadí Fialový Uživatelsky definovaný @@ -328,6 +307,128 @@ Vybrat barvu automaticky Zobrazit pouze hlavní barvy Zobrazit všechny barvy - Klikněte pro náhled - %s (Student) + %s (Student) + Chování klávesy pro přepínání jazyků + Vibrace v režimu nerušit + Mezerník + Vzdálenost rozdělení (na šířku) + Povolit rozdělenou klávesnici (na šířku) + Webová pole pro úpravu (nacházejí se převážně v prohlížečích) jsou velmi častou příčinou problémů s nastavením zobrazování návrhů + Nezobrazovat návrhy pro webová pole pro úpravu + Začátek stránky + Konec stránky + Stránka nahoru + Stránka dolů + Rozdělená klávesnice + Backspace vrátí automatickou opravu + Plovoucí náhled + Zobrazit navržené slovo během gest + Přesunout náhled během gesta + Vždy okamžitě začít + Nahradit vyskakovací okno tečky doménami nejvyšší úrovně při zadávání adres URL a e-mailových adres + Automatická mezera pov výběru návrhu + Automatická mezera po napsání slova gestem + Zakázat automatickou mezeru po stisku Shiftu + Shift odstraní čekající automatickou mezeru + Zobrazit vyskakovací klávesy domén + Formát pro klíč časové značky + Automaticky opravovat zkratky + Pokud je povoleno, mohou být zkratky rozbaleny automatickým opravením + Zpomalení rychlého psaní + Doba do zmizení stopy gesta + Automatická mezera před napsáním slova gestem + Navrhovat obsah schránky + Zobrazit nedávno zkopírovaný obsah jako návrh + Slovo doleva + Slovo doprava + Přidat velmi běžné varianty (výchozí) + Zobrazit nápovědy na číselném řádku + Jazyky se slovníky + Uložit do souboru + Připnout klávesu do panelu nástrojů při dlouhém podržení + Nastavit hlavní a až 6 dalších symbolů měny, oddělených mezerami + Neplatný název + Dolní řádek schránky + Dolní řádek emodži + Stisknutí klávesy Enter nebo mezerníku po ostatních klávesách v numerické klávesnici + Mezerník (číselné rozložení) + Změnit velikost režimu jedné ruky + Opravdu chcete resetovat všechny přizpůsobené ikony? + Číselný řádek (základní) + Shift (stisknutý) + Obsah zkopírován + %s (Baishakhi) + Ukončit režim jedné ruky + Vlastní text na mezerníku + Zobrazit další barvy + Načíst + Emodži + Hlasový vstup zakázán + Přizpůsobit měny + %s (fonetická) + Dargwa (Urakhi) + Zkopírovat do schránky + Přepsat verzi emodži + Tab + Caps Lock + Zobrazit / skrýt panel nástrojů + Nespojovač s nulovou šířkou + Přepnout numerickou klávesnici + Přizpůsobit kódy kláves v panelu nástrojů + Automaticky zobrazit panel nástrojů + Zobrazit panel nástrojů, když je spuštěn vstup nebo vybrán text + Automaticky skrýt panel nástrojů + Skrýt panel nástrojů, když jsou dostupné návrhy + Přizpůsobit ikony + Vlastní podtyp + Varování: rozložení se aktuálně používá + Opravdu chcete odstranit %s? + Nastavit vlastní písmo ze souboru + Nastavit obrázek na pozadí (na šířku) + Pokud není nastaven, bude použit obrázek na výšku + Panel nástrojů + Kód dlouhého stisknutí + Přepnout stranu režimu jedné ruky + Spojovač s nulovou šířkou + Výběr emodži v zobrazení emodži + Odstranit přebytečné vyskakovací klávesy + Opravdu chcete vymazat všechny přizpůsobené kódy kláves? + Sekundární rozložení + Funkční klávesy (velká obrazovka) + Číselný řádek + Přepnout na hlavní klávesnici po… + Výběr záznamu v historii schránky + Stisknutí klávesy Enter nebo mezerníku v zobrazení znaků + Toto nastavení odhalí všechny interně používané barvy. Seznam barev se může kdykoli změnit. Výchozí barva je náhodná a názvy se nepřekládají. + Mansijština + Funkční klávesy + Funkční klávesy (znaky) + Funkční klávesy (další znaky) + Enter + Styl ikon + Měřítko dolního odsazení (na šířku) + Měřítko písma klávesnice + Měřítko písma v zobrazení emodži + Měřítko postranního odsazení (na šířku) + Měřítko postranního odsazení + Koš + Kód klávesy + Delete + Shift + Přepnout vzdálenost přejetí jazyka + Vyberte připnuté klávesy v panelu nástrojů + Toto zakáže další akce dlouhého stisknutí pro klávesy panelu nástrojů, které nejsou připnuty + Zakázat vyskakovací klávesy, které se již nacházejí v základním rozložení klávesnice + Barvy můžete najít a sdílet v %s. + sekci diskuze + Rozložení můžete najít a sdílet v %s. + Sesothština + Dagbani + Škálovat velikost kláves emodži velikostí s velikostí písma + Záloha obnovena + Používat názvy nainstalovaných aplikací pro návrhy a opravy + Používat názvy aplikací + Neutrální + Výchozí barva pokožky emodži + %1$s (%2$s) diff --git a/app/src/main/res/values-da/strings.xml b/app/src/main/res/values-da/strings.xml index e66f23bcd..ddbc3cbe3 100644 --- a/app/src/main/res/values-da/strings.xml +++ b/app/src/main/res/values-da/strings.xml @@ -16,7 +16,7 @@ Aktivér opdelt tastatur "Skift inputmetode" Tast til sprogskift - %s ms + %s ms "Systemstandard" "Brug navne fra Kontakter til forslag og rettelser" Personlige forslag @@ -49,20 +49,9 @@ "Spansk (USA)" "Hinglish" Serbisk (latin) - Engelsk (Storbritannien) (%s) - Engelsk (USA) (%s) - Spansk (USA) (%s) - Hinglish (%s) - Serbisk (%s) - %s (traditionel) - %s (kompakt) - "Intet sprog (Alfabet)" - "Alfabet (QWERTY)" - "Alfabet (QWERTZ)" - "Alfabet (AZERTY)" - "Alfabet (Dvorak)" - "Alfabet (Colemak)" - "Alfabet (PC)" + %s (traditionel) + %s (kompakt) + "Intet sprog" "Emoji" "Tilføj" "Fjern" @@ -75,38 +64,33 @@ "Emoji på fysisk tastatur" Alt-tast på fysisk tastatur viser emoji-paletten "Standard" - Velkommen til%s + Velkommen til%s "med glidende indtastning" Kom i gang - "Næste trin" - %s konfigureres - Aktivér%s - Markér \"%s\" i dine indstillinger for sprog og indtastning. Dermed får appen tilladelse til at køre på din enhed. - %s er allerede aktiveret i dine indstillinger for sprog og indtastning, så dette trin er gennemført. Fortsæt til næste! + %s konfigureres + Aktivér%s + Markér \"%s\" i dine indstillinger for sprog og indtastning. Dermed får appen tilladelse til at køre på din enhed. "Aktivér i Indstillinger" - Skift til%s - Vælg derefter \\%s\" som din aktive tekstinputmetode.\" + Skift til%s + Vælg derefter \\%s\" som din aktive tekstinputmetode.\" Skift inputmetode Tillykke, du er klar! - Nu kan du skrive i alle dine favoritapps med %s. + Nu kan du skrive i alle dine favoritapps med %s. "Afslut" "Vis appikon" Vis applikationsikon i launcheren - "Ekstra ordbøger" + "Ekstra ordbøger" Ordbog tilgængelig - "Ingen tilg. ordbøger" "Sidst opdateret" "Indstillinger" "Slet" - Version %1$s - "Tilføj" + Version %1$s "Føj til ordbog" "Genvej:" "Sprog:" "Skriv et ord" "Valgfri genvej" "Rediger ord" - Du har ingen ord i brugerordbogen. Tilføj et ord ved at trykke på knappen Tilføj (+). Til alle sprog "Flere sprog…" " ABCDEFGHIJKLMNOPQRSTUVWXYZÆØÅ" @@ -118,11 +102,10 @@ Aktivér udklipsholderhistorik Hvis deaktiveret, indsætter udklipsholdertasten eventuelt indhold af udklipsholderen Opbevaringstid for historik - Alfabet (Colemak Mod-DH) Tastekanter Automatisk dag-/nattilstand Udseende følger systemindstillinger - %s min. + %s min. HeliBoard-stavekontrol Vis tastehints Talrække @@ -134,8 +117,7 @@ Indstillinger for HeliBoard-stavekontrol Indsæt automatisk mellemrum efter skilletegn, når du skriver et nyt ord Auto-mellemrum efter skilletegn - %s (Akkhor) - Alfabet (Workman) + %s (Akkhor) HeliBoard-indstillinger Input Yderligere taster @@ -193,7 +175,7 @@ Sprog Indstil primær og op til 6 sekundære valutasymboler, adskilt med mellemrum Vis funktionelle hints - %s (Sebeolsik 390) + %s (Sebeolsik 390) Kaitag Vælg sprog %s (eksperimentel) @@ -245,7 +227,6 @@ Tilføj meget almindelige varianter (standard) URL-registrering Prøv at registrere URL\'er og lignende som et enkelt ord - Indstil layoutnavn Foreslå indhold fra udklipsholder Vis nyligt kopieret udklipsholderindhold som forslag Gem eller indlæs fra fil. Advarsel: Gendannelse overskriver eksisterende data @@ -294,12 +275,8 @@ Skala for padding i siderne Skala for padding i bunden (liggende) Mansi - %s (udvidet) + %s (udvidet) Skift til hovedtastatur efter… - Mansi (%s) - Urakhi (%s) - Kaitag (%s) - Alfabet (Bépo) Sekundære layouts "Uden en ordbog får du kun forslag til tekst, du har indtastet før.<br>\n Du kan hente ordbøger %1$s eller tjekke, om en ordbog for \"%2$s\" kan hentes direkte %3$s." Vælg en fil i et kompatibelt format. Oplysninger om formaterne er tilgængelige %s. @@ -308,7 +285,6 @@ Indhold kopieret Brugerdefineret Auto-vis værktøjslinje - Tryk for forhåndsvisning Luk Udseende Tastetekst @@ -362,7 +338,6 @@ Auto-skjul værktøjslinje Skjul værktøjslinjen, når forslag bliver tilgængelige Tastekode - Indlæsning overskriver det nuværende tema Ryd alle tilpassede tastekoder? Ugyldigt navn diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index e0092f3f8..0e9f906fb 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -9,14 +9,14 @@ "Ton bei Tastendruck" Popup bei Tastendruck Optionen - "Gesteneingabe" + Gesten-Tippen "Textkorrektur" "Erweitert" "Design" "Geteilte Tastatur aktivieren" "Eingabemethoden wechseln" Sprachwechseltaste - "%s ms" + "%s ms" Systemstandard Namen aus Kontakten für Vorschläge und Korrekturen verwenden "Personalisierte Vorschläge" @@ -38,7 +38,7 @@ "Sehr stark" "Vorschläge für nächstes Wort" "Anhand des vorherigen Wortes Vorschläge machen" - Gesteneingabe aktivieren + Gesten-Tippen aktivieren Gib ein Wort ein, indem du durch die Buchstaben gleitest Gestenspur anzeigen Schwebender Echtzeit-Vorschlag @@ -49,20 +49,9 @@ "Spanisch (USA)" Hinglisch "Serbisch (Lateinisch)" - Englisch (GB) (%s) - Englisch (USA) (%s) - Spanisch (USA) (%s) - Hinglisch (%s) - Serbisch (%s) - %s (Traditionell) - %s (Kompakt) - "Keine Sprache (lat. Alphabet)" - "Lat. Alphabet (QWERTY)" - "Lat. Alphabet (QWERTZ)" - "Lat. Alphabet (AZERTY)" - "Lat. Alphabet (Dvorak)" - "Lat. Alphabet (Colemak)" - "Lat. Alphabet (PC)" + %s (Traditionell) + %s (Kompakt) + "Keine Sprache" "Emoji" "Hinzufügen" "Entfernen" @@ -75,38 +64,33 @@ "Emoji für physische Tastatur" "Emoji-Palette auf physischen Tastaturen über Alt-Taste aufrufen" "Standard" - Willkommen bei %s - "mit Gesteneingabe" + Willkommen bei %s + mit Gesten-Tippen "Jetzt starten" - "Nächster Schritt" - %s einrichten - %s aktivieren - Bitte aktiviere %s\" unter der Systemeinstellung „Sprachen und Eingabe“, damit die App auf deinem Gerät verwendet werden darf.\" - %s ist bereits in deiner Systemeinstellung „Sprachen und Eingabe“ aktiviert. Weiter mit dem nächsten Schritt!\" + %s einrichten + %s aktivieren + Bitte aktiviere %s\" unter der Systemeinstellung „Sprachen und Eingabe“. "In den Einstellungen aktivieren" - Zu %s wechseln - Wähle als nächstes %s\" als deine aktive Bildschirmtastatur.\" + Zu %s wechseln + Wähle als nächstes %s\" als deine aktive Bildschirmtastatur. "Eingabemethode wechseln" Hurra, die Einrichtung ist abgeschlossen! - Jetzt kannst du in all deinen Lieblingsapps mit %s schreiben. + Jetzt kannst du in all deinen Lieblingsapps mit %s schreiben. "Fertig" "App-Symbol anzeigen" "App-Symbol in der Übersicht anzeigen" - "Erweiterte Wörterbücher" + "Erweiterte Wörterbücher" "Wörterbuch verfügbar" - Keine Wörterbücher verfügbar "Zuletzt aktualisiert" "Einstellungen" "Löschen" - Version %1$s - "Hinzufügen" + Version %1$s "Zum Wörterbuch hinzufügen" "Tastaturkürzel:" "Sprache:" "Wort eingeben" "Optionales Tastaturkürzel" "Wort bearbeiten" - Es sind noch keine Wörter in deinem Wörterbuch vorhanden. Du kannst Wörter hinzufügen, indem du auf das „+“-Symbol tippst. "Für alle Sprachen" "Weitere Sprachen…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" @@ -119,7 +103,7 @@ HeliBoard-Einstellungen Experimentell Keine Begrenzung - %s Min. + %s Min. HeliBoard-Rechtschreibprüfung Emoji-Taste Eingabe @@ -145,9 +129,7 @@ Aussehen (hell/dunkel) folgt der Systemeinstellung für den Tag-/Nachtmodus Tastenränder Automatischer Tag-/Nachtmodus - %s (Bengali) - Lat. Alphabet (Workman) - Lat. Alphabet (Colemak Mod-DH) + %s (Bengali) Vertrauen in die Autokorrektur Rückgängig "Wiederholen" @@ -174,13 +156,13 @@ Fehler beim Wiederherstellen der Sicherung: %s Farben Funktionstastenhintergrund - %s (Sebeolsik 390) + %s (Sebeolsik 390) Persönliches Wörterbuch des Gerätes verwenden, um gelernte Wörter zu speichern Dieses Wort ist bereits im Benutzer-Wörterbuch %s vorhanden. Bitte gib ein anderes Wort ein. Abgerundet Sicherung Schwarz - %s (Sebeolsik Final) + %s (Sebeolsik Final) Schokolade Soll das vom Benutzer hinzugefügte Wörterbuch \"%s\" wirklich entfernt werden? Wolkig @@ -201,9 +183,7 @@ Navigationsleiste einfärben Trotzdem benutzen Wald - Du benötigst die Bibliothek für „%s“. Inkompatible Bibliotheken können zu Abstürzen bei der Gesteneingabe führen. -\n -\nWarnung: Das Laden von externem Code kann ein Sicherheitsrisiko darstellen. Verwende nur Bibliotheken aus Quellen, denen du vertraust. + Du benötigst die Bibliothek für „%s“. Inkompatible Bibliotheken können zu Abstürzen beim Gesten-Tippen führen. \n \nWarnung: Das Laden von externem Code kann ein Sicherheitsrisiko darstellen. Verwende nur Bibliotheken aus Quellen, denen du vertraust. Wörterbuch zum Hinzufügen auswählen. Wörterbücher im .dict-Format können %s heruntergeladen werden. Bibliothek löschen Sprache @@ -216,7 +196,6 @@ Hell Wort hinzufügen Textfarbe Wortvorschlag - Für Vorschau klicken In den Tastatursprachen definierte Varianten anzeigen Gemeinsame Varianten hinzufügen Benutzerdefiniert @@ -227,17 +206,16 @@ Akzent Auf GitHub ansehen Zahlenzeile - Alphabet (Bépo) Wiederherstellen Popup-Tastenreihenfolge wählen Version Hinweis-Quelle wählen - Native Bibliothek bereitstellen, um Gesteneingabe zu aktivieren + Native Bibliothek bereitstellen, um Gesten-Tippen zu aktivieren Mehr Symbole Versuche URLs und Ähnliches als einzelnes Wort zu erkennen Sprache auswählen Tastenbeschriftung - Gesteneingabe-Bibliothek laden + Gesten-Tippen-Bibliothek laden Leertastenhintergrund Dunkler Bild für den Tag- oder Nachtmodus festlegen? @@ -278,7 +256,6 @@ Teilungsabstand Gewichtung: Ignoriere Anfragen anderer Apps, Vorschläge zu deaktivieren (kann Probleme verursachen) - Layout-Name festlegen Sprache wechseln Zwischenablage löschen Nacht @@ -303,7 +280,7 @@ Autokorrektur, auch wenn dies vom Eingabefeld nicht explizit angefordert wird Holo-Weiß Beides wechseln - ► Durch langes Drücken der angehefteten Tasten in der Symbolleiste erhälst du zusätzliche Funktionen: <br> \n\t•Zwischenablage &#65515; einfügen <br> \n\t• nach links/rechts bewegen &#65515; Wort links/rechts <br> \n\t• aufwärts/abwärts bewegen &#65515; Seite auf/ab <br> \n\t• Wort links/rechts &#65515; Zeilenanfang/-ende <br> \n\t• Seite auf/ab &#65515; Seite Anfang/Ende <br> \n\t• kopieren. &#65515; ausschneiden <br> \n\t•Wort wählen &#8596; alle auswählen <br> \n\t• rückgängig &#8596; wiederherstellen. <br> <br> \n► Durch langes Drücken von Tasten in der Symbolleiste der Vorschlagsleiste werden diese an die Vorschlagsleiste angeheftet. <br> <br> \n► Drücke lange auf die Komma-Taste, um die Zwischenablage-Ansicht, die Emoji-Ansicht, den Einhandmodus, die Einstellungen oder die Sprache zu wechseln.: <br> \n\t• Die Emoji-Ansicht und die Sprachumschaltung werden ausgeblendet, wenn du die entsprechende Taste aktiviert hast.; <br> \n\t• Bei einigen Layouts ist es nicht die Komma-Taste, sondern die Taste an der gleichen Position (z.B. \'q\' beim Dvorak-Layout). <br> <br> \n► Wenn der Inkognito-Modus aktiviert ist, werden keine Wörter gelernt und keine Emojis zu den Notizen hinzugefügt. <br> <br> \n► Drücke auf das Symbol Inkognito, um die Symbolleiste aufzurufen. <br> <br> \n► Gleitende Tasteneingabe: Streiche von der Umschalttaste zu einer anderen Taste, um einen einzelnen Großbuchstaben einzugeben: <br> \n\t• Dies funktioniert auch für die Taste \'?123\', um ein einzelnes Symbol von der Symboltastatur einzugeben, und für verwandte Tasten. <br> <br> \n► Halte die Umschalt- oder Symboltaste gedrückt, drücke eine oder mehrere Tasten, und lasse dann die Umschalt- oder Symboltaste los, um zur vorherigen Tastatur zurückzukehren.. <br> <br> \n► Drücke lange auf einen Vorschlag in der Vorschlagsleiste, um weitere Vorschläge anzuzeigen, und eine Löschtaste, um diesen Vorschlag zu entfernen. <br> <br> \n► Wische von einem Vorschlag nach oben, um weitere Vorschläge zu öffnen, und lasse den Vorschlag los, um ihn auszuwählen. <br> <br> \n► Drücke lange auf einen Eintrag in der Zwischenablage, um ihn anzuheften (er bleibt in der Zwischenablage, bis du die Anheftung aufhebst). <br> <br> \n► Wische in der Zwischenablageansicht nach links, um einen Eintrag zu entfernen (außer wenn er angeheftet ist) <br> <br> \n► Markiere den Text und drücke die Umschalttaste, um zwischen Groß- und Kleinschreibung sowie Großschreibung zu wechseln. <br> <br> \n► Du kannst Wörterbücher hinzufügen, indem du sie in einem Datei-Explorer öffnest: <br> \n\t• Dies funktioniert nur mit <i>content-uris</i> und nicht mit <i>file-uris</i>, was bedeutet, dass es mit einigen Datei-Explorern möglicherweise nicht funktioniert. <br> <br> \n► Für Benutzer, die manuelle Backups mit Root-Zugriff durchführen: <br> \n\t• Ab Android 7 befindet sich die gemeinsam genutzte Einstellungsdatei nicht am Standardspeicherort, da die App %s verwendet. Dies ist notwendig, damit die Einstellungen gelesen werden können, bevor das Gerät entsperrt wird, z. B. beim Booten; <br> \n\t• Die Datei befindet sich in /data/user_de/0/package_id/shared_prefs/, wobei dies vom jeweiligen Gerät und der Android-Version abhängen kann. <br> <br> \n<i><b>Debug-Modus / Debug-APK</b></i> <br> <br> \n► Drücke lange auf einen Vorschlag, um das Quellwörterbuch anzuzeigen. <br> <br> \n► Wenn du die Debug-APK verwendest, kannst du die Debug-Einstellungen in den erweiterten Einstellungen finden, obwohl die Nützlichkeit begrenzt ist, außer für die Ausgabe von Wörterbüchern in das Protokoll. <br> \n\t• Für eine Release-APK musst du die Version in <i>About</i> mehrmals antippen, dann findest du Debug-Einstellungen in <i>Erweiterte Einstellungen</i>. <br> \n\t• Wenn du die Option <i>Informationen zu Vorschlägen anzeigen</i> aktivierst, werden die Vorschläge mit kleinen Zahlen versehen, die die interne Bewertung und das Quellenwörterbuch anzeigen. <br> <br> \n► Im Falle eines Anwendungsabsturzes wirst du beim Öffnen der Einstellungen gefragt, ob du die Absturzprotokolle erhalten möchtest. <br> <br> \n► Bei mehrsprachiger Eingabe zeigt die Leertaste einen Vertrauenswert an, der zur Bestimmung der aktuell verwendeten Sprache verwendet wird. <br> <br> \n► Bei den Vorschlägen werden oben einige kleine Zahlen angezeigt, die den internen Punktestand und das Quellenwörterbuch anzeigen (kann deaktiviert werden). + ► Durch langes Drücken der angehefteten Tasten in der Symbolleiste erhält du zusätzliche Funktionen: <br> \n\t•Zwischenablage &#65515; einfügen <br> \n\t• nach links/rechts bewegen &#65515; Wort links/rechts <br> \n\t• aufwärts/abwärts bewegen &#65515; Seite auf/ab <br> \n\t• Wort links/rechts &#65515; Zeilenanfang/-ende <br> \n\t• Seite auf/ab &#65515; Seite Anfang/Ende <br> \n\t• kopieren. &#65515; ausschneiden <br> \n\t•Wort wählen &#8596; alle auswählen <br> \n\t• rückgängig &#8596; wiederherstellen. <br> <br> \n► Durch langes Drücken von Tasten in der Symbolleiste der Vorschlagsleiste werden diese an die Vorschlagsleiste angeheftet. <br> <br> \n► Drücke lange auf die Komma-Taste, um die Zwischenablage-Ansicht, die Emoji-Ansicht, den Einhandmodus, die Einstellungen oder die Sprache zu wechseln.: <br> \n\t• Die Emoji-Ansicht und die Sprachumschaltung werden ausgeblendet, wenn du die entsprechende Taste aktiviert hast.; <br> \n\t• Bei einigen Layouts ist es nicht die Komma-Taste, sondern die Taste an der gleichen Position (z.B. \'q\' beim Dvorak-Layout). <br> <br> \n► Wenn der Inkognito-Modus aktiviert ist, werden keine Wörter gelernt und keine Emojis zu den Notizen hinzugefügt. <br> <br> \n► Drücke auf das Symbol Inkognito, um die Symbolleiste aufzurufen. <br> <br> \n► Gleitende Tasteneingabe: Streiche von der Umschalttaste zu einer anderen Taste, um einen einzelnen Großbuchstaben einzugeben: <br> \n\t• Dies funktioniert auch für die Taste \'?123\', um ein einzelnes Symbol von der Symboltastatur einzugeben, und für verwandte Tasten. <br> <br> \n► Halte die Umschalt- oder Symboltaste gedrückt, drücke eine oder mehrere Tasten, und lasse dann die Umschalt- oder Symboltaste los, um zur vorherigen Tastatur zurückzukehren.. <br> <br> \n► Drücke lange auf einen Vorschlag in der Vorschlagsleiste, um weitere Vorschläge anzuzeigen, und eine Löschtaste, um diesen Vorschlag zu entfernen. <br> <br> \n► Wische von einem Vorschlag nach oben, um weitere Vorschläge zu öffnen, und lasse den Vorschlag los, um ihn auszuwählen. <br> <br> \n► Drücke lange auf einen Eintrag in der Zwischenablage, um ihn anzuheften (er bleibt in der Zwischenablage, bis du die Anheftung aufhebst). <br> <br> \n► Wische in der Zwischenablageansicht nach links, um einen Eintrag zu entfernen (außer wenn er angeheftet ist) <br> <br> \n► Markiere den Text und drücke die Umschalttaste, um zwischen Groß- und Kleinschreibung sowie Großschreibung zu wechseln. <br> <br> \n► Du kannst Wörterbücher hinzufügen, indem du sie in einem Datei-Explorer öffnest: <br> \n\t• Dies funktioniert nur mit <i>content-uris</i> und nicht mit <i>file-uris</i>, was bedeutet, dass es mit einigen Datei-Explorern möglicherweise nicht funktioniert. <br> <br> \n► Für Benutzer, die manuelle Backups mit Root-Zugriff durchführen: <br> \n\t• Ab Android 7 befindet sich die gemeinsam genutzte Einstellungsdatei nicht am Standardspeicherort, da die App %s verwendet. Dies ist notwendig, damit die Einstellungen gelesen werden können, bevor das Gerät entsperrt wird, z. B. beim Booten; <br> \n\t• Die Datei befindet sich in /data/user_de/0/package_id/shared_prefs/, wobei dies vom jeweiligen Gerät und der Android-Version abhängen kann. <br> <br> \n<i><b>Debug-Modus / Debug-APK</b></i> <br> <br> \n► Drücke lange auf einen Vorschlag, um das Quellwörterbuch anzuzeigen. <br> <br> \n► Wenn du die Debug-APK verwendest, kannst du die Debug-Einstellungen in den erweiterten Einstellungen finden, obwohl die Nützlichkeit begrenzt ist, außer für die Ausgabe von Wörterbüchern in das Protokoll. <br> \n\t• Für eine Release-APK musst du die Version in <i>About</i> mehrmals antippen, dann findest du Debug-Einstellungen in <i>Erweiterte Einstellungen</i>. <br> \n\t• Wenn du die Option <i>Informationen zu Vorschlägen anzeigen</i> aktivierst, werden die Vorschläge mit kleinen Zahlen versehen, die die interne Bewertung und das Quellenwörterbuch anzeigen. <br> <br> \n► Im Falle eines Anwendungsabsturzes wirst du beim Öffnen der Einstellungen gefragt, ob du die Absturzprotokolle erhalten möchtest. <br> <br> \n► Bei mehrsprachiger Eingabe zeigt die Leertaste einen Vertrauenswert an, der zur Bestimmung der aktuell verwendeten Sprache verwendet wird. <br> <br> \n► Bei den Vorschlägen werden oben einige kleine Zahlen angezeigt, die den internen Punktestand und das Quellenwörterbuch anzeigen (kann deaktiviert werden). "Ohne Wörterbuch erhältst du nur Vorschläge für Text, den du zuvor eingegeben hast.<br>\n Du kannst Wörterbücher %1$s herunterladen oder %3$s überprüfen, ob ein Wörterbuch für \"%2$s\" direkt heruntergeladen werden kann." %s (experimentell) Symbole @@ -314,7 +291,6 @@ Ziffernblock Ziffernblock (Querformat) Kaitakisch - Kaitakisch (%s) Vertikale Wischgeste der Leertaste Nichts Cursor bewegen @@ -323,13 +299,13 @@ Ausschneiden Variable Symbolleisten-Richtung Richtung umkehren, wenn die Tastatur einer Rechts-nach-Links-Sprache ausgewählt ist - %s (Student) - %s (Probhat) + %s (Student) + %s (Probhat) Bei Eingabe eines Leerzeichens oder eines Punktes wird der mittlere Vorschlag gewählt Zwischenablage-Verlauf schließen Immer mittleren Vorschlag verwenden Tasten der Symbolleiste für die Zwischenablage auswählen - %s (Erweitert) + %s (Erweitert) Angeheftete Tasten der Symbolleiste auswählen Dadurch werden andere Langdruck-Aktionen für Tasten der Symbolleiste, die nicht angeheftet sind, deaktiviert Inhalt kopiert @@ -341,7 +317,6 @@ Symbolleisten-Taste bei langem Drücken anheften Symbolleiste Emoji - Mansi (%s) Mansi Mehr Farben anzeigen Diese Einstellung legt alle intern verwendeten Farben offen. Die Liste der Farben kann sich jederzeit ändern. Die Standardfarbe ist zufällig und die Namen werden nicht übersetzt. @@ -355,7 +330,6 @@ Laden In Datei speichern In Zwischenablage kopieren - Laden wird die aktuelle Darstellung überschreiben Seitenende Linkes Wort Rechtes Wort @@ -363,7 +337,7 @@ Seite runter Seitenanfang Zuletzt kopierte Inhalte der Zwischenablage als Vorschlag anzeigen - Schlage Zwischenablagen-Inhalt vor + Zwischenablagen-Inhalt vorschlagen Drücken der Eingabetaste oder der Leertaste nach anderen Tasten in der Symbolansicht Auswählen eines Eintrags des Zwischenablagenverlaufs Auswählen eines Emojis in der Emojiansicht @@ -419,17 +393,39 @@ Sprachen mit Wörterbüchern Du kannst Farben im %s finden und teilen. Dargwa (Urakhi) - Urakhi (%s) Sekundäre Layouts Funktionstasten (großer Bildschirm) Randabstand unten (Querformat) Seitenabstand Seitenabstand (Querformat) - %s (Phonetisch) + %s (Phonetisch) Warnung: Das Layout wird derzeit verwendet Du kannst Layouts im %s finden und freigeben. Diskussionsbereich %s wirklich löschen? Ungültiger Name Benutzerdefinierter Subtyp + %s (Baisakhi) + Zeige TLD-Popup-Tasten + Ersetze Punkt-Tastenpopups mit Top-Level-Domains wenn URLs und Mailadressen eingegeben werden + Nicht immer Vorschläge für Web-Editierfelder anzeigen + Zahlenreihe (Basis) + Web-Eingabefelder (meist in Browsern) sind eine häufige Ursache für Probleme mit der Einstellung \"Immer Vorschläge anzeigen\" + Drücken der Eingabetaste oder der Leertaste nach anderen Tasten im Ziffernblock + Leertaste + Shift entfernt anstehende automatische Leerzeichen + Leerzeichen nach Wörtern bei Gesten-Tippen + Kein automatisches Leerzeichen beim drücken von Shift + Leerzeichen vor Wörtern bei Gesten-Tippen + Format der Timestamp-Taste + Dagbani + Sesotho + Rücktaste macht Autokorrektur rückgängig + Automatische Leerzeichen nach Auswählen eines Vorschlags + Skaliere den Emoji-Knopf mit der Schriftgröße + Backup wiederhergestellt + App-Namen nachschlagen + Namen der installierten Apps für Vorschläge und Korrekturen verwenden + Standard-Emoji-Hautton + Neutral diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index c2134e233..1f4c9966a 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -17,7 +17,7 @@ "Ενεργοποίηση διαχωρισμού πληκτρολογίου" "Άλλη μέθοδος εισόδου" "Πλήκτρο εναλλαγής γλώσσας" - "%sχλστ. δ." + "%sχλστ. δ." "Προεπιλογή" "Χρησιμοποιήστε ονόματα από τις Επαφές για προτάσεις και διορθ." "Εξατομικευμένες προτάσεις" @@ -50,20 +50,9 @@ "Ισπανικά (ΗΠΑ)" "Hinglish" "Σερβικά (Λατινικά)" - "Αγγλικά (Ηνωμένο Βασίλειο) (%s)" - "Αγγλικά (ΗΠΑ) (%s)" - "Ισπανικά (ΗΠΑ) (%s)" - "Hinglish (%s)" - "Σερβικά (%s)" - "%s (Παραδοσιακά)" - "%s (Συμπαγές)" - "Καμία γλώσσα (Αλφάβητο)" - "Αλφάβητο (QWERTY)" - "Αλφάβητο (QWERTZ)" - "Αλφάβητο (AZERTY)" - "Αλφάβητο (Dvorak)" - "Αλφάβητο (Colemak)" - "Αλφάβητο (PC)" + "%s (Παραδοσιακά)" + "%s (Συμπαγές)" + "Καμία γλώσσα" "Emoticon" "Προσθήκη" "Κατάργηση" @@ -76,38 +65,33 @@ "Emoji για φυσικό πληκτρολόγιο" "Το φυσικό πλήκτρο Alt εμφανίζει την παλέτα emoji" "Προεπιλογή" - "Καλώς ορίσατε στο %s" + "Καλώς ορίσατε στο %s" "με Πληκτρολόγηση με κίνηση" "Έναρξη" - "Επόμενο βήμα" - "Ρύθμιση της εφαρμογής %s" - "Ενεργοποιήστε την εφαρμογή %s" - "Επιλέξτε \"%s\" στις Ρυθμίσεις γλώσσας και εισαγωγής, για να το εξουσιοδοτήσετε να εκτελείται στη συσκευή σας." - "Το %s είναι ήδη ενεργοποιημένο στις Ρυθμίσεις γλώσσας και εισαγωγής, συνεπώς το βήμα έχει ολοκληρωθεί. Πάμε στο επόμενο!" + "Ρύθμιση της εφαρμογής %s" + "Ενεργοποιήστε την εφαρμογή %s" + "Επιλέξτε \"%s\" στις Ρυθμίσεις γλώσσας και εισαγωγής, για να το εξουσιοδοτήσετε να εκτελείται στη συσκευή σας." "Ενεργοποίηση στις Ρυθμίσεις" - "Μετάβαση στην εφαρμογή %s" - "Στη συνέχεια, επιλέξτε \"%s\" ως την ενεργή μέθοδο εισαγωγής κειμένου." + "Μετάβαση στην εφαρμογή %s" + "Στη συνέχεια, επιλέξτε \"%s\" ως την ενεργή μέθοδο εισαγωγής κειμένου." "Εναλλαγή μεθόδων εισαγωγής" "Συγχαρητήρια, είστε έτοιμοι!" - "Πλέον μπορείτε να πληκτρολογήσετε όλες τις αγαπημένες σας εφαρμογές με το %s." + "Πλέον μπορείτε να πληκτρολογήσετε όλες τις αγαπημένες σας εφαρμογές με το %s." "Ολοκληρώθηκε" "Εμφάνιση εικονιδίου εφαρμογής" "Εμφάνιση εικονιδίου εφαρμογής στο πρόγραμμα εκκίνησης" - "Πρόσθετα λεξικά" + "Πρόσθετα λεξικά" "Διαθέσιμο λεξικό" - "Δεν υπάρχουν λεξικά" "Τελευταία ενημέρωση" "Ρυθμίσεις" "Διαγραφή" - "Έκδοση %1$s" - "Προσθήκη" + "Έκδοση %1$s" "Προσθήκη στο λεξικό" "Συντόμευση:" "Γλώσσα:" "Πληκτρολογήστε μια λέξη" "Προαιρετική συντόμευση" "Επεξεργασία λέξης" - "Δεν υπάρχουν καταχωρισμένες λέξεις στο λεξικό χρήστη. Για να προσθέσετε μια λέξη, πατήστε το κουμπί Προσθήκης (+)." "Για όλες τις γλώσσες" "Περισσότερες γλώσσες…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" @@ -127,7 +111,7 @@ Ρυθμίσεις ορθογραφικού ελέγχου HeliBoard Ιστορικό πρόχειρου Διάφορα - %smin. + %smin. Εάν είναι απενεργοποιημένο, το πλήκτρο του προχείρου θα επικολλήσει το περιεχόμενο του προχείρου εάν υπάρχει Περίγραμμα πλήκτρου Αυτόματη λειτουργία ημέρας/νύχτας @@ -136,9 +120,7 @@ Αριθμητική σειρά Να εμφανίζεται πάντα η αριθμητική σειρά Αλλάξτε τη μέθοδο εισαγωγής με το πλήκτρο διαστήματος - %s (Akkhor) - Αλφάβητο (Colemak Mod-DH) - Αλφάβητο (Workman) + %s (Akkhor) Η εμφάνιση θα ακολουθεί τις ρυθμίσεις του συστήματος Αυτόματο κενό μετά τη στίξη Ρυθμίσεις HeliBoard diff --git a/app/src/main/res/values-en-rAU/strings.xml b/app/src/main/res/values-en-rAU/strings.xml index 335d7f915..22e8d9a76 100644 --- a/app/src/main/res/values-en-rAU/strings.xml +++ b/app/src/main/res/values-en-rAU/strings.xml @@ -17,7 +17,7 @@ "Enable split keyboard" "Switch to other input methods" "Language switch key" - "%sms" + "%sms" "System default" "Use names from Contacts for suggestions and corrections" "Personalised suggestions" @@ -51,21 +51,9 @@ "Hinglish" "Kaitag" "Serbian (Latin)" - "English (UK) (%s)" - "English (US) (%s)" - "Spanish (US) (%s)" - "Hinglish (%s)" - "Kaitag (%s)" - "Serbian (%s)" - "%s (Traditional)" - "%s (Compact)" - "No language (Alphabet)" - "Alphabet (QWERTY)" - "Alphabet (QWERTZ)" - "Alphabet (AZERTY)" - "Alphabet (Dvorak)" - "Alphabet (Colemak)" - "Alphabet (PC)" + "%s (Traditional)" + "%s (Compact)" + "No language" "Emoji" "Add" "Remove" @@ -78,38 +66,33 @@ "Emoji for physical keyboard" "Physical Alt key shows the emoji palette" "Default" - "Welcome to %s" + "Welcome to %s" "with Gesture Typing" "Get started" - "Next step" - "Setting up %s" - "Enable %s" - "Please tick \"%s\" in your Languages & input settings. This will authorise it to run on your device." - "%s is already enabled in your Languages & input settings, so this step is complete. On to the next one." + "Setting up %s" + "Enable %s" + "Please tick \"%s\" in your Languages & input settings. This will authorise it to run on your device." "Enable in Settings" - "Switch to %s" - "Next, select \"%s\" as your active text-input method." + "Switch to %s" + "Next, select \"%s\" as your active text-input method." "Switch input methods" "Congratulations, you\'re all set!" - "Now you can type in all your favourite apps with %s." + "Now you can type in all your favourite apps with %s." "Finished" "Show app icon" "Display application icon in the launcher" - "Add-on dictionaries" + "Add-on dictionaries" "Dictionary available" - "No dictionaries available" "Last updated" "Settings" "Delete" - "Version %1$s" - "Add" + "Version %1$s" "Add to dictionary" "Shortcut:" "Language:" "Type a word" "Optional shortcut" "Edit word" - "You don\'t have any words in the user dictionary. To add a word, tap the Add (+) button." "For all languages" "More languages…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" diff --git a/app/src/main/res/values-en-rCA/strings.xml b/app/src/main/res/values-en-rCA/strings.xml index 335d7f915..22e8d9a76 100644 --- a/app/src/main/res/values-en-rCA/strings.xml +++ b/app/src/main/res/values-en-rCA/strings.xml @@ -17,7 +17,7 @@ "Enable split keyboard" "Switch to other input methods" "Language switch key" - "%sms" + "%sms" "System default" "Use names from Contacts for suggestions and corrections" "Personalised suggestions" @@ -51,21 +51,9 @@ "Hinglish" "Kaitag" "Serbian (Latin)" - "English (UK) (%s)" - "English (US) (%s)" - "Spanish (US) (%s)" - "Hinglish (%s)" - "Kaitag (%s)" - "Serbian (%s)" - "%s (Traditional)" - "%s (Compact)" - "No language (Alphabet)" - "Alphabet (QWERTY)" - "Alphabet (QWERTZ)" - "Alphabet (AZERTY)" - "Alphabet (Dvorak)" - "Alphabet (Colemak)" - "Alphabet (PC)" + "%s (Traditional)" + "%s (Compact)" + "No language" "Emoji" "Add" "Remove" @@ -78,38 +66,33 @@ "Emoji for physical keyboard" "Physical Alt key shows the emoji palette" "Default" - "Welcome to %s" + "Welcome to %s" "with Gesture Typing" "Get started" - "Next step" - "Setting up %s" - "Enable %s" - "Please tick \"%s\" in your Languages & input settings. This will authorise it to run on your device." - "%s is already enabled in your Languages & input settings, so this step is complete. On to the next one." + "Setting up %s" + "Enable %s" + "Please tick \"%s\" in your Languages & input settings. This will authorise it to run on your device." "Enable in Settings" - "Switch to %s" - "Next, select \"%s\" as your active text-input method." + "Switch to %s" + "Next, select \"%s\" as your active text-input method." "Switch input methods" "Congratulations, you\'re all set!" - "Now you can type in all your favourite apps with %s." + "Now you can type in all your favourite apps with %s." "Finished" "Show app icon" "Display application icon in the launcher" - "Add-on dictionaries" + "Add-on dictionaries" "Dictionary available" - "No dictionaries available" "Last updated" "Settings" "Delete" - "Version %1$s" - "Add" + "Version %1$s" "Add to dictionary" "Shortcut:" "Language:" "Type a word" "Optional shortcut" "Edit word" - "You don\'t have any words in the user dictionary. To add a word, tap the Add (+) button." "For all languages" "More languages…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" diff --git a/app/src/main/res/values-en-rGB/strings.xml b/app/src/main/res/values-en-rGB/strings.xml index 3fb416e45..848286f3b 100644 --- a/app/src/main/res/values-en-rGB/strings.xml +++ b/app/src/main/res/values-en-rGB/strings.xml @@ -16,7 +16,7 @@ "Enable split keyboard" "Switch to other input methods" "Language switch key" - "%s ms" + "%s ms" "System default" "Use names from Contacts for suggestions and corrections" "Personalised suggestions" @@ -50,21 +50,9 @@ "Hinglish" "Kaitag" "Serbian (Latin)" - English (UK) (%s) - English (US) (%s) - Spanish (US) (%s) - Hinglish (%s) - Kaitag (%s) - Serbian (%s) - %s (Traditional) - %s (Compact) - "No language (Alphabet)" - "Alphabet (QWERTY)" - "Alphabet (QWERTZ)" - "Alphabet (AZERTY)" - "Alphabet (Dvorak)" - "Alphabet (Colemak)" - "Alphabet (PC)" + %s (Traditional) + %s (Compact) + "No language" "Emoji" "Add" "Remove" @@ -77,38 +65,33 @@ "Emoji for physical keyboard" "Physical Alt key shows the emoji palette" "Default" - Welcome to %s + Welcome to %s "with Gesture Typing" "Get started" - "Next step" - Setting up %s - Enable %s - Please tick \"%s\" in your Languages & input settings. This will authorise it to run on your device. - %s is already enabled in your Languages & input settings, so this step is done. On to the next one! + Setting up %s + Enable %s + Please tick \"%s\" in your Languages & input settings. This will authorise it to run on your device. "Enable in Settings" - Switch to %s - Next, select \"%s\" as your active text-input method. + Switch to %s + Next, select \"%s\" as your active text-input method. "Switch input methods" "Congratulations, you\'re all set!" - Now you can type in all your favourite apps with %s. + Now you can type in all your favourite apps with %s. "Finished" "Show app icon" "Display application icon in the launcher" - "Add-on dictionaries" + "Add-on dictionaries" "Dictionary available" - "No dictionaries available" "Last updated" "Settings" "Delete" - Version %1$s - "Add" + Version %1$s "Add to dictionary" "Shortcut:" "Language:" "Type a word" "Optional shortcut" "Edit word" - "You don\'t have any words in the user dictionary. To add a word, tap the Add (+) button." "For all languages" "More languages…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" @@ -134,18 +117,16 @@ Auto day/night mode Key borders Additional keys - Alphabet (Colemak Mod-DH) - Alphabet (Workman) Appearance will follow system settings Change input method with space key Long pressing space key will prompt input method selection menu No limit Clipboard history - %s min + %s min Enable clipboard history If disabled, clipboard key will paste clipboard content if any History retention time - %s (Akkhor) + %s (Akkhor) Autospace after punctuation Automatically insert space after punctuation when typing a new word "Use system languages" diff --git a/app/src/main/res/values-en-rIN/strings.xml b/app/src/main/res/values-en-rIN/strings.xml index 455fd6493..8aae2be22 100644 --- a/app/src/main/res/values-en-rIN/strings.xml +++ b/app/src/main/res/values-en-rIN/strings.xml @@ -17,7 +17,7 @@ "Enable split keyboard" "Switch to other input methods" "Language switch key" - "%sms" + "%sms" "System default" "Use names from Contacts for suggestions and corrections" "Personalised suggestions" @@ -51,21 +51,9 @@ "Hinglish" "Kaitag" "Serbian (Latin)" - "English (UK) (%s)" - "English (US) (%s)" - "Spanish (US) (%s)" - "Hinglish (%s)" - "Kaitag (%s)" - "Serbian (%s)" - "%s (Traditional)" - "%s (Compact)" - "No language (Alphabet)" - "Alphabet (QWERTY)" - "Alphabet (QWERTZ)" - "Alphabet (AZERTY)" - "Alphabet (Dvorak)" - "Alphabet (Colemak)" - "Alphabet (PC)" + "%s (Traditional)" + "%s (Compact)" + "No language" "Emoji" "Add" "Remove" @@ -78,38 +66,33 @@ "Emoji for physical keyboard" "Physical Alt key shows the emoji palette" "Default" - "Welcome to %s" + "Welcome to %s" "with Gesture Typing" "Get started" - "Next step" - "Setting up %s" - "Enable %s" - "Please tick \"%s\" in your Languages & input settings. This will authorise it to run on your device." - "%s is already enabled in your Languages & input settings, so this step is complete. On to the next one." + "Setting up %s" + "Enable %s" + "Please tick \"%s\" in your Languages & input settings. This will authorise it to run on your device." "Enable in Settings" - "Switch to %s" - "Next, select \"%s\" as your active text-input method." + "Switch to %s" + "Next, select \"%s\" as your active text-input method." "Switch input methods" "Congratulations, you\'re all set!" - "Now you can type in all your favourite apps with %s." + "Now you can type in all your favourite apps with %s." "Finished" "Show app icon" "Display application icon in the launcher" - "Add-on dictionaries" + "Add-on dictionaries" "Dictionary available" - "No dictionaries available" "Last updated" "Settings" "Delete" - "Version %1$s" - "Add" + "Version %1$s" "Add to dictionary" "Shortcut:" "Language:" "Type a word" "Optional shortcut" "Edit word" - "You don\'t have any words in the user dictionary. To add a word, tap the Add (+) button." "For all languages" "More languages…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" diff --git a/app/src/main/res/values-en-rXC/strings.xml b/app/src/main/res/values-en-rXC/strings.xml index 38445f734..c0680a9c6 100644 --- a/app/src/main/res/values-en-rXC/strings.xml +++ b/app/src/main/res/values-en-rXC/strings.xml @@ -17,7 +17,7 @@ "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‏‎‎‏‏‎‏‎‎‎‏‏‏‎‎‏‏‏‎‏‏‏‏‎‎‎‎‏‏‎‎‏‏‎‏‎‎‏‏‏‎‏‎‎‎‏‏‎‏‏‏‎‎‏‎‎Enable split keyboard‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‏‏‎‎‎‎‎‎‏‏‏‎‏‏‏‎‎‎‏‎‏‏‎‎‎‏‏‏‏‎‎‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‎‏‎‎‏‏‏‎‏‎‏‏‎Switch to other input methods‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‎‎‎‎‏‎‎‏‎‏‏‏‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‎‎‏‎‎‏‏‏‎‎‎‏‏‏‎‏‏‎‏‏‎‎‎‎‎‏‏‎Language switch key‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‏‏‏‏‎‏‏‎‏‎‎‎‎‎‎‎‎‏‏‎‏‏‎‎‏‏‏‏‏‎‏‏‎‏‎‏‎‎‎‎‏‏‏‎‏‎‎‎‏‎‎‎‏‏‎‎‏‎‎‏‏‎%s‎‏‎‎‏‏‏‎ms‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‏‏‏‏‎‏‏‎‏‎‎‎‎‎‎‎‎‏‏‎‏‏‎‎‏‏‏‏‏‎‏‏‎‏‎‏‎‎‎‎‏‏‏‎‏‎‎‎‏‎‎‎‏‏‎‎‏‎‎‏‏‎%s‎‏‎‎‏‏‏‎ms‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‎‎‏‎‎‏‎‏‏‎‎‏‎‏‎‎‏‏‎‎‏‏‎‎‎‎‎‎‏‎‎‎‎‎‎‏‎‏‎‎‎‏‎‎‏‎‎‎‎‎‎‏‏‎‎‏‎‏‎‏‏‏‎System default‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‎‎‎‎‎‏‏‎‎‎‎‎‎‎‏‎‎‏‏‏‎‏‎‏‏‎‏‏‏‏‏‏‏‎‎‏‎‏‏‎‏‎‎‏‏‎‏‎‏‏‎‎‏‏‎‏‎Use names from Contacts for suggestions and corrections‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‏‏‎‎‏‏‏‎‎‎‏‏‎‏‎‎‎‎‎‏‎‏‎‎‎‏‏‎‏‏‎‏‏‎‏‎‏‎‎‏‏‎‏‏‏‎‎‏‏‎‏‏‏‏‎Personalized suggestions‎‏‎‎‏‎" @@ -50,20 +50,9 @@ "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‏‏‏‏‎‏‏‎‏‎‏‎‎‎‎‏‏‏‏‏‎‎‎‏‎‎‎‏‎‎‎‏‎‏‎‎‎‎‎‎‏‎‎‏‏‎‏‎‏‏‎‏‎‎‎‎Spanish (US)‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‏‏‏‎‏‏‎‏‎‏‎‎‎‏‎‏‎‏‎‎‏‎‎‏‏‏‏‎‏‎‎‏‏‎‎‎‎‏‏‎‎‏‏‎‎‎‏‎‎‎‏‏‏‏‏‎Hinglish‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‏‎‎‎‏‏‎‏‎‎‎‎‎‎‏‎‏‏‏‏‏‎‎‎‎‏‏‎‎‎‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‎‏‎‎‏‏‏‎Serbian (Latin)‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‎‏‏‏‎‏‎‏‏‎‎‏‏‎‎‎‏‎‏‏‎‏‏‏‎‎‎‎‏‎‏‎‏‏‎‎‎‎‎‎‏‏‎‏‏‎‎‎‏‎‏‏‎‏‏‏‏‏‏‎‎‎‎‎English (UK) (‎‏‎‎‏‏‎%s‎‏‎‎‏‏‏‎)‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‎‎‏‎‎‎‎‎‎‏‏‏‏‎‏‎‏‏‏‏‏‎‎‎‏‎‎‏‏‏‎‎‏‎‎‎‎‏‏‎‏‏‎‎‏‎‏‏‎‎‏‏‎‏‏‏‎‎English (US) (‎‏‎‎‏‏‎%s‎‏‎‎‏‏‏‎)‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‎‏‏‏‏‏‎‎‎‏‎‏‏‏‎‎‏‏‎‎‎‎‏‎‎‎‏‏‏‎‎‏‏‏‎‏‏‎‏‏‎‏‏‏‎‏‎‏‎‎‎‎‎‎‎‏‎‏‏‎‏‎‎Spanish (US) (‎‏‎‎‏‏‎%s‎‏‎‎‏‏‏‎)‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‏‎‏‎‎‎‎‎‎‏‏‏‎‏‏‎‏‎‎‏‏‏‏‏‎‎‎‎‎‎‏‏‏‏‎‎‏‎‎‎Hinglish (‎‏‎‎‏‏‎%s‎‏‎‎‏‏‏‎)‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‎‏‎‎‏‏‏‏‎‏‎‏‏‎‏‎‏‎‎‏‎‏‏‏‏‏‎‎‎‏‎‎‎‎‎‏‏‏‎‎‎‎‎‎‎‎‏‎‎‎‎‎‎‏‎‏‏‏‏‎‏‏‏‎Serbian (‎‏‎‎‏‏‎%s‎‏‎‎‏‏‏‎)‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‎‎‎‏‎‏‎‎‏‏‎‏‏‎‎‎‏‎‏‎‎‎‎‏‏‏‏‏‎‏‎‎‏‏‏‏‎‎‏‎‏‎‎‎‎‏‎‎‎‏‎‏‎‎‎‏‎‎‏‏‎%s‎‏‎‎‏‏‏‎ (Traditional)‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‎‏‎‏‏‏‎‏‎‎‎‏‎‏‎‏‎‏‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‏‎‏‏‎‎‎‎‎‏‎‏‎‏‏‏‏‎‏‏‎‏‏‎‏‎‏‎‎‎‏‎‎‏‏‎%s‎‏‎‎‏‏‏‎ (Compact)‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‎‎‎‏‏‎‏‎‎‎‏‏‎‏‎‎‏‏‏‏‎‎‏‏‎‏‎‎‏‏‎‏‎‎‏‎‎‏‏‎‏‎‎‏‎‎‎‏‏‏‎‎‏‏‏‎No language (Alphabet)‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‎‏‎‏‏‎‏‏‎‎‏‎‎‎‎‎‎‏‏‏‏‏‏‎‎‎‏‏‏‏‏‎‎‏‏‏‎‎‎‏‎‏‎‏‏‏‏‏‎‏‎‏‎‏‏‎‎‏‏‎‎‎Alphabet (QWERTY)‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‎‏‏‏‏‎‎‎‏‎‎‏‏‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‏‎‏‎‏‏‏‎‏‏‏‏‎‏‏‏‎‏‎‎‎‏‎‏‎‎‏‎‎‎‎Alphabet (QWERTZ)‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‎‎‎‏‏‎‏‎‎‎‏‎‎‏‏‏‎‏‎‏‎‏‏‏‎‏‎‎‎‏‎‎‎‏‏‏‏‏‎‎‏‎‏‎‎‎‎‎‎‏‎‏‏‏‎Alphabet (AZERTY)‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‏‎‏‏‎‏‏‎‎‎‏‏‎‎‏‏‏‎‎‏‏‏‎‎‎‏‏‏‎‎‏‎‎‏‏‎‎‎‎‏‎‏‎‎‎‏‎‏‎‎‎‎‏‏‏‎‎Alphabet (Dvorak)‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‎‎‏‎‎‎‎‎‎‏‎‏‎‏‎‏‏‎‏‎‎‎‏‏‎‏‏‎‏‎‏‏‎‎‏‏‏‏‏‎‎‎‏‎‏‏‏‎‏‎‎‏‎‎‏‏‏‏‏‎Alphabet (Colemak)‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‎‏‎‏‎‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‎‎‏‎‏‎‏‎‏‏‏‎‎‏‏‎‎‎‎‎‎‏‏‎‎‏‎‎‏‏‎‏‎‎‏‎‎Alphabet (PC)‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‎‎‎‏‎‏‎‎‏‏‎‏‏‎‎‎‏‎‏‎‎‎‎‏‏‏‏‏‎‏‎‎‏‏‏‏‎‎‏‎‏‎‎‎‎‏‎‎‎‏‎‏‎‎‎‏‎‎‏‏‎%s‎‏‎‎‏‏‏‎ (Traditional)‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‎‏‎‏‏‏‎‏‎‎‎‏‎‏‎‏‎‏‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‏‎‏‏‎‎‎‎‎‏‎‏‎‏‏‏‏‎‏‏‎‏‏‎‏‎‏‎‎‎‏‎‎‏‏‎%s‎‏‎‎‏‏‏‎ (Compact)‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‎‎‎‏‏‎‏‎‎‎‏‏‎‏‎‎‏‏‏‏‎‎‏‏‎‏‎‎‏‏‎‏‎‎‏‎‎‏‏‎‏‎‎‏‎‎‎‏‏‏‎‎‏‏‏‎No language‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‏‏‎‏‏‎‏‏‎‎‎‎‏‎‏‎‎‏‎‏‎‏‏‏‏‏‎‏‎‎‎‎‎‎‎‎‎‎‏‏‏‎‏‏‏‎‏‏‏‏‎‎‏‏‎‎‎Emoji‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‎‏‎‏‏‏‏‎‎‎‏‏‏‏‎‏‎‎‎‎‎‏‎‎‎‎‎‏‏‎‏‏‎‎‎‎‎‎‏‎‎‎‎‎‏‎‎‏‏‎‏‏‏‏‏‎Add‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‎‎‎‏‎‏‎‏‏‏‎‏‎‏‏‎‏‎‏‎‎‏‎‏‏‎‎‎‏‏‎‎‎‏‏‎‏‏‏‏‎‎‎‏‏‏‏‏‎‏‎‎‏‏‎‎‎Remove‎‏‎‎‏‎" @@ -76,38 +65,33 @@ "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‎‏‎‏‏‏‏‎‎‎‎‏‎‎‏‏‏‎‎‏‎‏‏‎‎‏‏‏‏‏‏‎‎‏‏‏‎‎‎‏‏‏‎‎‏‏‎‏‏‏‏‎‏‏‎‎‎‎Emoji for physical keyboard‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‎‎‏‏‎‏‏‏‏‎‏‎‎‎‏‏‏‏‏‎‏‎‏‎‏‎‏‎‎‎‎‎‎‎‎‎‏‎‏‏‏‏‎‏‏‏‎‎‎‎‎‎‎‎‏‎‏‏‎‎‏‎‎Physical Alt key shows the emoji palette‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‏‎‏‏‏‏‎‏‎‏‏‏‎‎‏‎‎‏‎‎‏‏‎‎‏‎‎‏‏‎‎‏‎‏‎‏‏‏‏‏‎‎‏‎‏‏‏‎‏‎‏‎‎‏‎‏‎‎‎Default‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‏‎‏‎‏‎‏‎‎‎‏‏‎‏‎‏‏‏‏‎‏‎‏‎‎‏‏‏‏‎‏‏‏‎‏‎‏‎‏‏‎‎‎‏‏‎‏‏‏‏‎‎‎‏‏‎Welcome to ‎‏‎‎‏‏‎%s‎‏‎‎‏‏‏‎‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‏‎‏‎‏‎‏‎‎‎‏‏‎‏‎‏‏‏‏‎‏‎‏‎‎‏‏‏‏‎‏‏‏‎‏‎‏‎‏‏‎‎‎‏‏‎‏‏‏‏‎‎‎‏‏‎Welcome to ‎‏‎‎‏‏‎%s‎‏‎‎‏‏‏‎‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‏‏‏‎‎‏‏‏‏‏‎‎‏‏‎‏‏‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‏‏‎‏‏‎‎‏‎‏‏‎‏‏‎‎‏‏‏‏‏‏‏‏‎with Gesture Typing‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‏‎‎‏‎‎‏‎‏‎‎‎‎‎‎‏‎‏‏‎‎‎‎‎‎‎‎‏‎‎‎‏‏‏‏‏‎‎‎‏‎‎‏‎‏‎‏‏‎‏‎‏‏‎‏‎‏‎Get started‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‎‎‎‏‏‏‏‏‎‏‎‏‏‎‎‏‏‎‎‏‏‏‎‏‎‎‎‎‎‎‎‎‏‎‏‎‏‎‏‏‏‎‏‎‎‏‏‏‎‎‎‏‏‏‎Next step‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‏‎‏‎‎‏‎‏‎‏‏‎‎‎‏‎‏‎‏‏‏‎‏‎‏‎‏‎‏‎‏‏‎‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎Setting up ‎‏‎‎‏‏‎%s‎‏‎‎‏‏‏‎‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‏‎‏‎‏‏‏‏‏‏‎‏‎‎‏‏‏‏‏‎‎‎‎‏‏‎‎‎‏‏‎‏‏‎‏‎‏‏‏‏‏‎‎‏‎‎‏‏‎‎‏‎‏‎‏‏‎Enable ‎‏‎‎‏‏‎%s‎‏‎‎‏‏‏‎‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‏‏‎‎‏‏‏‎‎‎‏‏‏‏‏‏‏‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‎‏‏‏‎‏‏‎‏‏‎‏‎‎‎‏‏‏‏‏‏‎‏‎Please check \"‎‏‎‎‏‏‎%s‎‏‎‎‏‏‏‎\" in your Languages & input settings. This will authorize it to run on your device.‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‎‎‎‎‏‏‎‏‏‏‎‏‏‎‏‎‎‏‏‎‏‎‎‏‏‎‏‏‏‏‎‏‎‏‏‎‎‎‏‏‏‏‎‎‏‎‏‎‎‎‎‏‏‎‎‏‎‎‏‏‎%s‎‏‎‎‏‏‏‎ is already enabled in your Languages & input settings, so this step is done. On to the next one!‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‏‎‏‎‎‏‎‏‎‏‏‎‎‎‏‎‏‎‏‏‏‎‏‎‏‎‏‎‏‎‏‏‎‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎Setting up ‎‏‎‎‏‏‎%s‎‏‎‎‏‏‏‎‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‏‎‏‎‏‏‏‏‏‏‎‏‎‎‏‏‏‏‏‎‎‎‎‏‏‎‎‎‏‏‎‏‏‎‏‎‏‏‏‏‏‎‎‏‎‎‏‏‎‎‏‎‏‎‏‏‎Enable ‎‏‎‎‏‏‎%s‎‏‎‎‏‏‏‎‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‏‏‎‎‏‏‏‎‎‎‏‏‏‏‏‏‏‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‎‏‏‏‎‏‏‎‏‏‎‏‎‎‎‏‏‏‏‏‏‎‏‎Please check \"‎‏‎‎‏‏‎%s‎‏‎‎‏‏‏‎\" in your Languages & input settings. This will authorize it to run on your device.‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‎‏‏‏‏‎‎‏‎‎‏‏‎‎‎‏‏‏‏‏‎‎‎‏‏‏‎‏‏‎‎‏‏‏‎‎‎‎‎‏‎‎‏‏‎‏‎‏‎‏‏‎‏‏‎‎‎‏‎‎‎‎‎‎Enable in Settings‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‎‏‏‎‏‏‎‎‎‏‏‎‎‎‏‎‏‏‏‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‏‎‏‏‎‎‎‎‎‎‏‏‎‎‎‏‎‎‎‏‎‎Switch to ‎‏‎‎‏‏‎%s‎‏‎‎‏‏‏‎‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‏‎‏‎‎‎‏‎‎‎‏‎‏‏‎‏‎‎‏‏‏‎‏‎‏‎‎‏‎‏‏‎‏‏‏‏‎‏‏‏‎‎‎‏‎‏‎‏‎‎‎‎Next, select \"‎‏‎‎‏‏‎%s‎‏‎‎‏‏‏‎\" as your active text-input method.‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‎‏‏‎‏‏‎‎‎‏‏‎‎‎‏‎‏‏‏‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‏‎‏‏‎‎‎‎‎‎‏‏‎‎‎‏‎‎‎‏‎‎Switch to ‎‏‎‎‏‏‎%s‎‏‎‎‏‏‏‎‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‏‎‏‎‎‎‏‎‎‎‏‎‏‏‎‏‎‎‏‏‏‎‏‎‏‎‎‏‎‏‏‎‏‏‏‏‎‏‏‏‎‎‎‏‎‏‎‏‎‎‎‎Next, select \"‎‏‎‎‏‏‎%s‎‏‎‎‏‏‏‎\" as your active text-input method.‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‎‏‏‎‏‏‏‎‎‎‎‏‎‏‎‏‎‏‎‏‏‎‏‏‎‎‏‏‏‏‎‎‎‎‏‏‎‎‎‎‎‎‏‎‎‏‏‏‎‎‏‎‏‏‏‏‏‎‏‎‎‎‏‎Switch input methods‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‏‏‎‎‎‏‏‏‏‏‏‏‎‎‏‎‏‏‏‏‎‎‎‏‏‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‎‏‏‏‏‏‎‎‏‏‏‎‏‎‎‏‎Congratulations, you\'re all set!‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‏‎‎‎‏‎‎‎‎‎‎‎‏‏‏‏‏‏‎‎‏‏‎‏‎‏‎‏‏‏‎‏‎‏‏‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‎‎‎‎‎Now you can type in all your favorite apps with ‎‏‎‎‏‏‎%s‎‏‎‎‏‏‏‎.‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‏‎‎‎‏‎‎‎‎‎‎‎‏‏‏‏‏‏‎‎‏‏‎‏‎‏‎‏‏‏‎‏‎‏‏‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‎‎‎‎‎Now you can type in all your favorite apps with ‎‏‎‎‏‏‎%s‎‏‎‎‏‏‏‎.‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‎‎‏‏‎‎‏‏‎‎‏‏‏‏‎‏‎‏‎‎‏‏‎‎‎‏‎‎‎‎‎‏‎‏‎‏‏‏‎‎‏‏‎‎‎‎‎‎‎‏‏‏‎‏‏‎‎‎Finished‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‎‏‏‎‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‎‏‏‎‎‏‎‎‎‏‏‏‎‏‎‎‎‏‏‎‎‎‏‎‏‎‏‏‎‎‎‎‏‏‏‏‏‎Show app icon‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‎‎‏‎‎‏‏‏‏‎‏‏‎‎‎‎‎‎‏‏‎‏‎‎‏‏‏‏‏‏‎‎‏‏‎‏‏‏‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‎‏‎‏‏‏‏‎‏‎Display application icon in the launcher‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‎‏‎‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎‏‏‏‏‎‏‏‎‏‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‏‏‎‎‏‏‏‏‎‎‏‏‎‏‎Add-on dictionaries‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‎‏‎‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎‏‏‏‏‎‏‏‎‏‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‏‏‎‎‏‏‏‏‎‎‏‏‎‏‎Add-on dictionaries‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‎‎‎‏‏‎‎‏‎‎‏‏‏‎‏‏‎‎‏‏‏‏‎‏‏‎‎‎‎‎‏‏‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‏‎‎‏‎‎‏‎‏‎Dictionary available‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‎‎‎‎‏‏‏‎‎‎‏‎‎‏‏‎‎‏‎‎‎‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‎‎‎‏‏‏‎‎‎‎‎‏‏‏‎‏‏‏‎‎No dictionaries available‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‎‎‏‎‏‏‎‏‏‏‏‏‏‎‎‎‏‏‎‎‎‎‎‏‎‎‏‏‏‏‏‎‎‎‎‎‎‏‎‎‏‏‎‎‎Last updated‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‏‏‏‎‎‏‏‎‎‏‎‏‎‎‏‎‎‏‎‏‏‎‎‏‏‎‏‏‏‎‎‎‏‏‏‎‏‏‏‎‎‏‎‎‎‏‎‏‏‏‎‏‏‎‎‎‎Settings‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‎‏‏‏‎‎‎‎‎‏‎‎‎‏‏‏‏‏‎‏‏‎‏‏‎‏‎‎‏‎‎‎‏‎‏‏‏‎‏‎‎‏‎‏‏‏‎‏‎‎‏‏‎‏‎‏‏‎‎‏‎‎‎Delete‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‎‏‎‎‏‎‏‏‎‏‎‏‏‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‎‏‏‏‎‎‎‎‏‎‎‏‎‏‎‎‎‏‎‏‏‎‏‏‎‏‏‎‎‎‏‎‎‏‎Version ‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‎‎‎‏‎‎‎‎‎‎‏‏‏‎‎‎‎‎‏‏‎‏‎‎‎‎‏‎‎‏‎‏‏‏‏‎‏‎‎‏‏‏‏‎‎‎‏‏‏‎‏‏‏‎‏‏‎Add‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‎‏‎‎‏‎‏‏‎‏‎‏‏‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‎‏‏‏‎‎‎‎‏‎‎‏‎‏‎‎‎‏‎‏‏‎‏‏‎‏‏‎‎‎‏‎‎‏‎Version ‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‎‏‎‎‏‎‏‏‏‎‎‎‎‏‏‎‎‏‏‎‎‏‏‏‏‎‏‎‏‎‎‏‏‎‎‏‎‎‎‏‏‏‎‎‎‎‏‏‏‎‎‏‎‏‏‎‏‎‎‎‎‎‎‎Add to dictionary‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‎‎‎‏‎‎‎‏‏‏‏‎‏‏‎‏‏‏‎‏‏‏‏‎‏‏‎‏‎‎‏‎‎‏‎‏‏‏‎‎‏‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‏‎Shortcut:‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‏‎‎‏‏‏‎‎‏‎‎‎‎‏‎‏‎‏‎‏‎‏‏‏‎‏‎‎‏‎‏‏‏‏‎‎‏‎‎‏‎‏‏‏‎‏‏‏‏‏‎‏‏‏‎‏‏‎Language:‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‎‎‎‎‏‏‎‎‎‎‎‎‎‏‎‏‏‏‏‏‎‎‏‎‏‎‎‎‏‎‏‎‎‏‎‎‏‏‏‎‏‏‏‏‎‎‎‎‏‏‎‏‎‏‎‏‏‎Type a word‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‎‏‏‎‏‏‎‏‏‏‎‎‎‎‏‎‎‏‏‏‎‎‏‏‎‎‎‎‎‎‏‏‎‎‎‎‏‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‎‎Optional shortcut‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‏‎‏‎‏‎‎‏‏‎‏‎‎‏‎‏‎‏‎‎‏‏‏‏‏‏‎‏‏‏‎‏‎‏‎‏‎‏‎‎‏‎‎‏‏‎‎‏‏‏‎‏‎‎‎‎‏‏‎Edit word‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‎‏‎‎‏‎‏‏‏‏‎‎‏‎‎‎‏‏‏‏‏‎‎‎‎‎‎‏‏‎‎‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‏‎‎‏‎‎‎‎‎‎‎‏‏‏‎‎‏‎You don\'t have any words in the user dictionary. To add a word, tap the Add (+) button.‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‎‏‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‎‏‏‎‎‎‎‎‏‎‎‎‎‏‎‎‏‎‏‏‏‎‎‎‏‎‎For all languages‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‏‎‎‏‎‎‏‎‏‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‎‏‎‏‏‎‏‎‎‎‏‏‎‎‏‏‎‎‎‎‎‎‎‎‎‏‎‎‎‏‏‎‎More languages…‎‏‎‎‏‎" " ‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‎‎‏‎‎‎‎‎‏‎‏‏‎‏‎‎‏‏‎‎‏‎‏‎‎‏‎‏‏‏‎‏‎‏‏‎‏‎‏‎‏‏‏‏‏‎‏‎‎‏‎‏‎‏‎‎ ABCDEFGHIJKLMNOPQRSTUVWXYZ‎‏‎‎‏‎" diff --git a/app/src/main/res/values-es-rUS/strings.xml b/app/src/main/res/values-es-rUS/strings.xml index 0a03b783f..80027c77c 100644 --- a/app/src/main/res/values-es-rUS/strings.xml +++ b/app/src/main/res/values-es-rUS/strings.xml @@ -16,7 +16,7 @@ "Habilitar teclado dividido" "Otros métodos de entrada" "Tecla de selección de idioma" - "%s ms" + "%s ms" "Predeterminado/a" Usar nombres de los contactos para sugerencias y correcciones "Sugerenc. personalizadas" @@ -49,20 +49,9 @@ "Español (EE.UU.)" "Hinglish" "Serbio (latino)" - "Inglés, Reino Unido (%s)" - "Inglés, EE. UU. (%s)" - "Español, EE. UU. (%s)" - "Hinglish (%s)" - "Serbio (%s)" - "%s (tradicional)" - "%s (compacto)" - "Ningún idioma (alfabeto)" - "Alfabeto (QWERTY)" - "Alfabeto (QWERTZ)" - "Alfabeto (AZERTY)" - "Alfabeto (Dvorak)" - "Alfabeto (Colemak)" - "Alfabeto (PC)" + "%s (tradicional)" + "%s (compacto)" + "Ningún idioma" "Emoji" "Agregar" "Eliminar" @@ -75,44 +64,39 @@ "Emoji para teclado físico" "La tecla Alt física muestra la paleta de emojis" "Predeterminado" - "Te damos la bienvenida a %s" + "Te damos la bienvenida a %s" "con escritura gestual" "Comenzar" - "Siguiente paso" - "Configurando %s…" - "Habilitar %s" - "Marca \"%s\" en Teclado e idioma para permitir que la app se ejecute en tu dispositivo." - "Debido a que la app de %s ya está habilitada en Teclado e idioma, pasaremos al siguiente paso." + "Configurando %s…" + "Habilitar %s" + "Marca \"%s\" en Teclado e idioma para permitir que la app se ejecute en tu dispositivo." "Habilitar en Configuración" - "Cambiar a %s" - "A continuación, selecciona \"%s\" como tu método de entrada de texto activo." + "Cambiar a %s" + "A continuación, selecciona \"%s\" como tu método de entrada de texto activo." "Cambiar métodos de entrada" "¡Felicitaciones, ya terminaste!" - "Ahora puedes escribir en todas las aplicaciones que quieras con %s." + "Ahora puedes escribir en todas las aplicaciones que quieras con %s." "Listo" "Mostrar ícono de aplicación" "Mostrar ícono de aplicación en el selector" - "Diccionarios complementarios" + "Diccionarios complementarios" "Diccionario disponible" - "No hay diccionarios." "Última actualización" "Configuración" "Eliminar" - "Versión %1$s" - "Agregar" + "Versión %1$s" "Agregar al diccionario" "Acceso directo:" "Idioma:" "Escribe una palabra" "Acceso directo opcional" "Editar palabra" - "El diccionario del usuario no contiene ninguna palabra. Para agregar una, presiona el botón Agregar (+)." "Todos los idiomas" "Más idiomas" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" Habilitar historial del portapapeles Tiempo para mantener el historial - %smin. + %smin. Corrector ortográfico de HeliBoard Ajustes del corrector ortográfico de HeliBoard Escala de altura del teclado @@ -133,13 +117,11 @@ Deshabilitar aprendizaje de nuevas palabras Fila de números Cambiar el método de entrada con la barra espaciadora - %s (Akkhor) + %s (Akkhor) Más teclas Mostrar símbolos sugeridos - Alfabeto (Colemak Mod-DH) Bordes de teclas Seguir la configuración del sistema - Alfabeto (Workman) Modo claro/oscuro automático Ajustes de HeliBoard Entrada @@ -238,13 +220,11 @@ Pulsación larga de la tecla de símbolos para cambiar al teclado numérico Reducir la distancia de las teclas Kaitag - Alfabeto (Bépo) Añadir diseño personalizado Cargar archivo No se puede leer el archivo Seleccione un archivo en un formato compatible. La información sobre los formatos está disponible %s. Copiar diseño existente - Establecer el nombre del diseño ¿Borrar realmente el diseño personalizado %s? Error de diseño: %s Pulse para editar el diseño sin procesar @@ -288,7 +268,6 @@ Escoger colores automáticamente Mostrar sólo los colores principales Mostrar todos los colores - Haga clic para ver la vista previa Seleccionar colores para el texto y los fondos Fondo del teclado Texto de la tira de sugerencias @@ -308,9 +287,9 @@ Mostrar características que pueden pasar desapercibidas Dirección variable de la barra de herramientas Invertir la dirección cuando se selecciona un subtipo de teclado de derecha a izquierda - %s (Probhat) - %s (Sebeolsik 390) - %s (Sebeolsik Final) + %s (Probhat) + %s (Sebeolsik 390) + %s (Sebeolsik Final) Océano Oscuro Más oscuro @@ -323,12 +302,11 @@ Bosque Indigo A la izquierda - %s (Student) + %s (Student) Utilizar el diccionario personal del dispositivo para almacenar las palabras aprendidas Ignorar la petición de otras aplicaciones de desactivar las sugerencias (puede producir problemas) Mostrar pistas de funciones Escala del borde inferior - Kaitag (%s) "Sin diccionario, sólo obtendrá sugerencias para el texto que haya introducido anteriormente.<br> \n Puede descargar los diccionarios %1$s, o comprobar si se puede descargar directamente un diccionario para \"%2$s\" %3$s." ► Pulsando prolongadamente la tecla del portapapeles (la opcional en la tira de sugerencias) se pega el contenido del portapapeles del sistema. <br> <br> ► Al pulsar prolongadamente las teclas de la barra de sugerencias, éstas se fijan a la barra de sugerencias. <br> <br> ► Pulse prolongadamente la tecla Coma para acceder a la vista del portapapeles, la vista de emoji, el modo de una mano, Ajustes o Cambiar idioma: <br> \t• La vista Emoji y el cambio de idioma desaparecerán si tienes activada la tecla correspondiente; <br> \t• Para algunas distribuciones no es la tecla Coma, sino la tecla en la misma posición (por ejemplo, es \'q\' para la distribución Dvorak). <br> <br> ► Cuando el modo incógnito está activado, no se aprende ninguna palabra ni se añaden emojis a los favoritos. <br> <br> ► Pulse el icono Incógnito para acceder a la barra de herramientas. <br> <br> ► Tecla deslizante: Desliza desde Mayúsculas a otra tecla para escribir una sola mayúscula: <br> \t• Esto también funciona con la tecla \'?123\' para escribir un solo símbolo del teclado de símbolos, y con las teclas relacionadas. <br> <br> ► Mantenga pulsada una sugerencia en la tira de sugerencias para mostrar más sugerencias, y el botón suprimir para eliminar esta sugerencia. <br> <br> ► Desliza el dedo hacia arriba desde una sugerencia para abrir más sugerencias y suéltalo para seleccionarla. <br> <br> ► Mantén pulsada una entrada del historial del portapapeles para anclarla (se mantendrá en el portapapeles hasta que la desancles). <br> <br> ► Puedes añadir diccionarios abriéndolos en un explorador de archivos: <br> \t• Esto sólo funciona con <i>content-uris</i> y no con <i>file-uris</i>, lo que significa que puede no funcionar con algunos exploradores de archivos. <br> <br> <i>Modo depuración / depurar APK</i> <br> <br> \t• Pulsa prolongadamente una sugerencia para mostrar el diccionario de origen.<br> <br> \t• Cuando se utiliza el APK de depuración, se puede encontrar la Configuración de Depuración dentro de las Preferencias Avanzadas, aunque la utilidad es limitada excepto para volcar diccionarios en el registro. <br> <br> \t• En caso de que se bloquee una aplicación, se te preguntará si quieres los registros de bloqueo cuando abras la Configuración. <br> <br> \t• Al utilizar la escritura multilingüe, la barra espaciadora mostrará un indicador de confianza utilizado para determinar el idioma utilizado en ese momento. <br> <br> \t• Las sugerencias tendrán unos pequeños números en la parte superior mostrando alguna puntuación interna y el diccionario de fuentes (se puede desactivar). <br> <br> ► Para usuarios que realizan copias de seguridad manuales con acceso root: A partir de Android 7, el archivo de preferencias compartidas no está en la ubicación predeterminada, porque la aplicación está utilizando %s. <br> Esto es necesario para poder leer los ajustes antes de desbloquear el dispositivo, por ejemplo, en el arranque. <br> El archivo se encuentra en /data/user_de/0/package_id/shared_prefs/, aunque esto puede depender del dispositivo y de la versión de Android. @@ -336,9 +314,8 @@ Al presionar espacio o puntuación, se ingresará la sugerencia central Cerrar el historial del portapapeles Seleccionar teclas de la barra de herramientas del portapapeles - %s (Extendido) + %s (Extendido) Mansi - Mansi (%s) Mostrar más colores Esta configuración muestra todos los colores que se utilizan internamente. La lista de colores puede cambiar en cualquier momento. El color predeterminado es aleatorio, y los nombres no se traducirán. Teclas funcionales @@ -358,7 +335,6 @@ Enfriamiento de escritura rápida Siempre iniciar instantáneamente Personalizar divisas - La carga sobrescribirá el tema actual Final de página Inicio de página Palabra izquierda diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index c3130ca58..af8adef7a 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -16,7 +16,7 @@ "Habilitar teclado dividido" "Otros métodos de introducción" "Tecla para cambiar de idioma" - "%s ms" + "%s ms" "Predeterminado" Utilizar nombres de contactos para sugerencias y correcciones "Sugerencias personalizadas" @@ -49,20 +49,9 @@ "Español (EE.UU.)" inglés indio "Serbio (latino)" - Inglés (Reino Unido) (%s) - Inglés (EE.UU.) (%s) - Español (EE.UU.)) (%s) - inglés indio (%s) - Serbio (%s) - %s (Tradicional) - %s (Compacto) - "Ningún idioma (alfabeto)" - "Alfabeto (QWERTY)" - "Alfabeto (QWERTZ)" - "Alfabeto (AZERTY)" - "Alfabeto (Dvorak)" - "Alfabeto (Colemak)" - "Alfabeto (PC)" + %s (Tradicional) + %s (Compacto) + "Ningún idioma" "Emoji" "Añadir" "Quitar" @@ -75,44 +64,37 @@ "Emojis para teclado físico" "La tecla Alt física muestra la lista de emojis" "Predeterminado" - Bienvenido a%s + Bienvenido a %s "con escritura gestual" "Empezar" - "Siguiente paso" - Configurando%s - Activar%s - Por favor, compruebe \"%s\" en sus ajustes de entrada de Idiomas. Esto lo autorizará a ejecutarse en su dispositivo.\" - %s ya está habilitado en sus idiomas & configuración de entrada, por lo que este paso está hecho. ¡En el siguiente! + Configurando %s + Activar %s + Por favor, compruebe \"%s\" en sus ajustes de entrada de Idiomas. Esto lo autorizará a ejecutarse en su dispositivo.\" "Habilitar en Ajustes" - Cambiar a %s - A continuación, seleccione \\%s\" como su método de entrada de texto activo.\" + Cambiar a %s + A continuación, seleccione \\%s\" como su método de entrada de texto activo.\" Cambiar métodos de entrada "¡Enhorabuena, has terminado!" - Ahora puedes escribir en todas tus aplicaciones favoritas con %s. + Ahora puedes escribir en todas tus aplicaciones favoritas con %s. "Listo" "Mostrar icono de aplicación" "Mostrar icono de aplicación en menú de aplicaciones" - "Diccionarios complementarios" + "Diccionarios complementarios" "Diccionario disponible" - "No hay diccionarios" "Última actualización" "Ajustes" "Eliminar" - Versión %1$s - "Añadir" + Versión %1$s "Añadir al diccionario" "Acceso directo:" "Idioma:" "Escribe una palabra" "Introducir" "Editar palabra" - "No tienes ninguna palabra en el diccionario del usuario. Toca el botón (+) para añadir una." "Todos los idiomas" "Más idiomas…" " ABCDEFGHIJKLMNÑOPQRSTUVWXYZ" - Alfabeto (Colemak Mod-DH) La apariencia seguirá los ajustes del sistema - Alfabeto (Workman) Mostrar siempre fila de números Teclas adicionales Cambiar método de entrada con la barra espaciadora @@ -141,8 +123,8 @@ Sin límite Habilitar el historial del portapapeles Tiempo a mantener guardado el historial - %s min - %s (Akkhor) + %s min + %s (Akkhor) Si está deshabilitada, la tecla del portapapeles pegará el contenido del portapapeles, si lo hay Espacio automático después del punto Insertar un espacio automático después del punto cuando se escriba una nueva palabra @@ -205,7 +187,6 @@ Cargar archivo Error al leer archivo Copiar diseño existente - Definir el nombre del diseño ¿Desea borrar el diseño personalizado %s? aquí %s (experimental) @@ -300,14 +281,13 @@ Día Dirección variable de la barra de herramientas Kaitag - Kaitag (%s) Cerrar historial del portapapeles Seleccionar teclas de la barra de herramientas del portapapeles Mostar indicaciones funcionales Mostar indicaciones si pulsar una tecla prolongadamente activa funcionalidad adicional Invertir dirección cuando un subtipo de teclado Derecha-a-Izquierda está seleccionado - %s (Estudiante) - %s (Extendido) + %s (Estudiante) + %s (Extendido) Definido por el usuario Rosa Arena @@ -330,22 +310,19 @@ Ocultar barra de herramientas cuando hay sugerencias disponibles Cortar Texto de la tira de sugerencias - %s (Bengalí) - %s (Sebeolsik 390) - %s (Sebeolsik Final) + %s (Bengalí) + %s (Sebeolsik 390) + %s (Sebeolsik Final) Azúl grisáceo Chocolate Nuboso Bosque Índigo Océano - Alfabeto (Bépo) Mostrar la barra de herramientas si se ingresa o selecciona texto Mansi - Mansi (%s) Definido por el usuario (noche) Esta configuración muestra todos los colores que se usan internamente. La lista de colores puede cambiar en cualquier momento. El color por defecto es aleatorio y los nombres no serán traducidos. - Toca para previsualizar Seleccionar colores para el texto y fondos Texto del indicio de tecla Fondo de tecla @@ -404,14 +381,12 @@ Código de presión prolongada Personalizar iconos Añadir variantes muy comunes (defecto) - Cargar sobreescribirá el tema actual Papelera ¿Realmente restablecer todos los íconos personalizados? Vibrar en el modo No molestar - %s (Fonético) + %s (Fonético) Sustituir versión de Emoji Dargwa (Urakhi) - Urakhi (%s) Si se activa, los accesos directos pueden expandirse con la autocorrección Atajos de autocorrección Establecer una fuente personalizada desde un archivo @@ -423,4 +398,34 @@ Tamaño de fuente de la vista Emoji Escala de relleno lateral (apaisado) Escala de relleno lateral + Subtipo personalizado + Los campos de edición web (que se encuentran sobre todo en los navegadores) son una causa muy común de problemas con la configuración de mostrar siempre sugerencias + No mostrar siempre las sugerencias para los campos de edición web + Fila de números (básica) + %s (Baishakhi) + Nombre inválido + Distancia de dividido (paisaje) + Habilitar teclado dividido (paisaje) + Espacio + Retroceso revierte la autocorrección + Mostrar teclas emergentes TLD + Auto espacio después de utilizar una sugerencia + Auto espacio después de escribir una palabra gestualmente + No auto espacio cuando se presiona shift + Shift elimina el autoespacio pendiente + sección de discusión + Auto espacio antes de escribir gestualmente una palabra + Sustituir las ventanas emergentes por dominios de nivel superior al escribir URL y direcciones de correo electrónico + Formato de la fecha y hora + Pulsar intro o espacio después de otras teclas en el teclado numérico + ¿Borrar %s realmente? + Diseños secundarios + Teclas funcionales (pantalla grande) + Mostrar pistas en la fila de números + Distancia de deslizamiento para cambiar de idioma + Idiomas con diccionarios + Teclado dividido + Advertencia: el diseño está en uso actualmente + Puedes encontrar y compartir colores en %s. + Puedes encontrar y compartir diseños en %s. diff --git a/app/src/main/res/values-et/strings.xml b/app/src/main/res/values-et/strings.xml index 544a0a0ee..c42959fd6 100644 --- a/app/src/main/res/values-et/strings.xml +++ b/app/src/main/res/values-et/strings.xml @@ -16,7 +16,7 @@ Kasuta kaheks jaotatud klahvistikku "Vaheta sisestusmeetodit" "Keelevahetuse nupp" - "%s ms" + "%s ms" Süsteemi väärtus "Kasuta soovitusteks ja parandusteks nimesid kontaktiloendist" "Isikupärast. soovitused" @@ -49,20 +49,9 @@ Hispaania (USA) "Hindi-inglise" "Serbia (ladina)" - "Inglise (Ühendk.) (%s)" - "Inglise (USA) (%s)" - "Hispaania (USA) (%s)" - "Hindi-inglise (%s)" - "Serbia (%s)" - "%s (traditsiooniline)" - "%s (kompaktne)" - "Keel puudub (tähestik)" - "Tähestik (QWERTY)" - "Tähestik (QWERTZ)" - "Tähestik (AZERTY)" - "Tähestik (Dvorak)" - "Tähestik (Colemak)" - "Tähestik (PC)" + "%s (traditsiooniline)" + "%s (kompaktne)" + "Keel puudub" "Emotikon" "Lisa" "Eemalda" @@ -75,38 +64,33 @@ Füüsilise klahvistiku emoji "Füüsiline klahv Alt kuvab emotikonide paleti" "Vaikeväärtus" - "Tere tulemast rakendusse %s" + "Tere tulemast rakendusse %s" "joonistusega sisestamisega" Alusta siit - "Järgmine toiming" - "Rakenduse %s seadistamine" - Võta %s kasutusele - Palun märgi nutiseadme keele- ja sisendiseadetes „%s“ lubatuks. See võimaldab rakenduse kasutamist sinu nutiseadmes. - %s on sinu nutiseadme keele- ja sisendiseadetes juba lubatud, seega on see toiming tehtud. Asu järgmise toimingu juurde! + "Rakenduse %s seadistamine" + Võta %s kasutusele + Palun märgi nutiseadme keele- ja sisendiseadetes „%s“ lubatuks. See võimaldab rakenduse kasutamist sinu nutiseadmes. "Luba seadetes" - Võta %s kõikjal kasutusele - Järgmisena vali aktiivseks tekstisisestusmeetodiks rakendus „%s“. + Võta %s kõikjal kasutusele + Järgmisena vali aktiivseks tekstisisestusmeetodiks rakendus „%s“. "Vaheta sisestusmeetodeid" "Õnnitleme. Kõik on valmis!" - Nüüd saad rakendusega %s sisestada kõikides oma lemmikrakendustes. + Nüüd saad rakendusega %s sisestada kõikides oma lemmikrakendustes. "Lõpetatud" "Kuva rakenduse ikoon" "Rakenduse ikooni kuvamine käivitajas" - "Pistiksõnastikud" + "Pistiksõnastikud" "Sõnastik on saadaval" - "Sõnastikke pole" "Viimati värskendatud" "Seaded" "Kustuta" - "Versioon %1$s" - "Lisa" + Versioon %s "Sõnaraamatusse lisamine" "Otsetee:" "Keel:" "Sisestage sõna" "Valikuline otsetee" "Sõna muutmine" - "Kasutaja sõnaraamatus ei ole ühtki sõna. Sõna lisamiseks puudutage nuppu Lisa (+)." "Kõikides keeltes" "Rohkem keeli …" " ABCDEFGHIJKLMNOPQRSŠZŽTUVWÕÄÖÜXY" @@ -127,7 +111,6 @@ Lõikelaua ajalugu Sisend Lisaklahvid - Eelvaateks klõpsi Vaheta sisestusmeetodit tühikuklahviga Seadista klahvistikku HeliBoardi õigekirjakontroll @@ -138,7 +121,6 @@ Klahvistiku kõrguse proportsioonid Pika vajutusega tühikuklahvile avaneb sisestusmeetodite valiku menüü Viga: märgistik ei ühildu selle klahvistikuga - Mansi (%s) Numbririda Ujuv eelvaade Viipamisel kuvatakse soovitatud sõna klahvistiku kohal @@ -146,7 +128,7 @@ Viipe kestus Lokaliseeri numbririda Emoji klahv - %s min + %s min Keelevahetuse nupu käitumine Lisa sõnad isiklikku sõnastikku Kasuta selles seadmes isiklikku sõnastikku meeldejäetud sõnade salvestamiseks @@ -221,7 +203,7 @@ Lehekülg alla Keel (prioriteetne) Numbrite rida - Keel + @string/subtype_locale Paigutus Sümbolid Üles @@ -237,9 +219,8 @@ Laadi fail Mansi Sinu tekst tühikuklahvil - Anna paigutusele nimi Vali lõikelaua nupud tööriistariba jaoks - %s (laiendatud) + %s (laiendatud) Laadi Lisa kohandatud paigutus Vali õiges vormingus fail. Teavet vormingute kohta leiad: %s. @@ -292,10 +273,9 @@ Ikooni stiil Numbririda Sisu on kopeeritud - %s (Õpilaste) + %s (Õpilaste) Funktsiooniklahvid - %s (Sebeolsiku lõppvariant) - Kaitagi (%s) + %s (Sebeolsiku lõppvariant) Peidetud funktsionaalsuse kirjeldus seadme turvatud andmekogu Funktsiooniklahvid (sümbolid) @@ -331,7 +311,6 @@ Sinu määratud Sinu määratud (öövaade) Näita kõiki värve - Uue välimuse laadimine asendab praeguse Vali värv automaatselt Näita vaid põhivärve Šokolaadipruun @@ -341,7 +320,7 @@ Püstise tühikuklahvi viipežest Rõhtse tühikuklahvi viipežest Liiguta kursorit - %s (Akkhor) + %s (Akkhor) Näita tööriistariba niipea, kui hakkad andmeid sisestama või valid teksti Peida tööriistariba automaatselt Peida tööriistariba niipea, kui soovitused on olemas @@ -427,19 +406,15 @@ GNU Üldine Avalik Litsents - versioon 3.0 Välimus Funktsiooniklahvid (täiendavad sümbolid) - %s (Probhat) - %s (Sebeolsik 390) - Tähestik (Workman) - Tähestik (Colemak Mod-DH) - Tähestik (Bépo) + %s (Probhat) + %s (Sebeolsik 390) Tööriistariba Prügikast Kas kindlasti soovid lähtestada kõik sinu seadistatud ikoonid? Vibreeri rahulikus režiimis - %s (Phonetic) + %s (Phonetic) Ära arvesta emojide versiooni Androidis Dargi (Urahhi) - Urahhi (%s) Paranda lühendid automaatselt Selle valikuga luuakse lühendist või sõnaosast terve sõna Vali taustapilt (rõhtvormingus) @@ -466,5 +441,28 @@ kogukonna vestlustes Uusi värve võid leida ja jagada %s. Sinu loodud alamtüüp - %s (Baishakhi) + %s (Baishakhi) + Näita tippdomeenide hüpikklahve + Võrgu- ja e-posti aadresside kirjutamisel asenda punktuatsiooni hüpikaknad tipptaseme domeenide omadega + Vajutades numbriklahvistikus peale muud sisestust tühiku- või sisestusklahvi + Numbririda (lihtne) + Ära alati näita sisestuse soovitusi täites veebivormide välju + Kui alati näitad sisestuse soovitusi veebivormide väljadel (nii nagu sa neid veebibrauseris näed), siis võib sellest tekkida probleeme + Tühik + Tagasivõtuklahv muudab autokorrektsiooni tagasi + Automaatne tühik peale soovituse valimist + Automaatne tühik enne viipamisega sõna kirjutamist + Automaatse tühiku keelamine shift-klahviga + Shift-klahvi vajutus välistab lisatava automaatse tühiku + Automaatne tühik peale viipamisega sõna kirjutamist + Ajatempli klahvi vorming + dagbani + sotho + Kohenda emoji klahvi suurust tavateksti klahvide suuruste järgi + Varukoopiast taastamine õnnestus + Otsi välja rakenduste nimed + Otsi soovituste ja paranduste jaoks välja paigaldatud rakenduste nimed + Emoji vaikimisi taustavärv + Neutraalne + %1$s (%2$s) diff --git a/app/src/main/res/values-eu/strings.xml b/app/src/main/res/values-eu/strings.xml index 10a1140bc..b7fda8f1a 100644 --- a/app/src/main/res/values-eu/strings.xml +++ b/app/src/main/res/values-eu/strings.xml @@ -16,7 +16,7 @@ "Gaitu teklatu banatua" "Aldatu idazketa-metodoa" "Hizkuntza aldatzeko tekla" - "%s ms" + "%s ms" Sistemak lehenetsitakoa Erabili kontaktuen izenak iradokizunak eta zuzenketak egiteko "Iradokizun pertsonalizatuak" @@ -49,20 +49,9 @@ "Gaztelania (AEB)" "Hinglisha" "Serbiarra (latindarra)" - Ingelesa (Erresuma Batua) (%s) - Ingelesa (Estatu Batuak) (%s) - Gaztelania (AEB) (%s) - Hinglisha (%s) - Serbiarra (%s) - %s (Tradizionala) - %s (Trinkoa) - "Ez dago hizkuntzarik (alfabetoa)" - Alfabetoa (QWERTY) - Alfabetoa (QWERTZ) - Alfabetoa (AZERTY) - Alfabetoa (Dvorak) - Alfabetoa (Colemak) - Alfabetoa (PC) + %s (Tradizionala) + %s (Trinkoa) + "Ez dago hizkuntzarik" "Emojiak" "Gehitu" "Kendu" @@ -75,38 +64,33 @@ "Teklatu fisikorako emojiak" "Teklatu fisikoko Alt tekla sakatuta emojiak agertzen dira" "Lehenetsia" - Ongi etorri %s aplikaziora + Ongi etorri %s aplikaziora Keinu-idazketarekin "Hasi erabiltzen" - "Hurrengo urratsa" - %s konfiguratzen - %s gaitu - Hautatu \"%s\" Hizkuntza eta idazketa ataleko ezarpenetan &. Horrek gailuan exekutatzea baimenduko dio. - %s gaituta duzu Hizkuntza eta idazketa ataleko ezarpenetan & beraz, urratsa eginda dago. Ekin hurrengoari! + %s konfiguratzen + %s gaitu + Hautatu \"%s\" Hizkuntza eta idazketa ataleko ezarpenetan &. Horrek gailuan exekutatzea baimenduko dio. Gaitu Ezarpenetan - Aldatu %s aplikaziora - Ondoren, hautatu \"%s\" idazketa-metodo aktibo gisa. + Aldatu %s aplikaziora + Ondoren, hautatu \"%s\" idazketa-metodo aktibo gisa. "Aldatu idazketa-metodoak" "Dena prest duzu!" - Gogokoen dituzun aplikazioetan idatz dezakezu dagoeneko %s erabilita. + Gogokoen dituzun aplikazioetan idatz dezakezu dagoeneko %s erabilita. "Amaituta" "Erakutsi aplikazioaren ikonoa" Bistaratu aplikazioaren ikonoa panelean - "Hiztegi gehigarriak" + "Hiztegi gehigarriak" "Hiztegia erabilgarri" - "Ez dago hiztegirik erabilgarri" "Azken eguneratzea" "Ezarpenak" "Ezabatu" - %1$s bertsioa - "Gehitu" + %1$s bertsioa "Gehitu hiztegian" "Lasterbidea:" "Hizkuntza:" "Idatzi hitz bat" "Aukerako lasterbidea" "Editatu hitza" - "Hutsik daukazu erabiltzailearen hiztegia. Hitzak gehitzeko, sakatu Gehitu (+) botoia." "Hizkuntza guztietan" "Hizkuntza gehiago…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" @@ -116,7 +100,7 @@ Esperimentala Denetarikoa Mugarik ez - %sminutu + %sminutu Erakutsi beti zenbakien errenkada Erakutsi teklen iradokizunak Erakutsi sakatze luzeen iradokizunak @@ -130,7 +114,7 @@ HeliBoard ortografia zuzentzailea Zuriunea puntuazioen ondoren Behartu ezkutuko modua - %s (Akkhor hizkuntza) + %s (Akkhor hizkuntza) Sarrera Teklen ertzak Egun/gau modu automatikoa @@ -144,8 +128,6 @@ Sartu automatikoki zuriunea puntuazioen ondoren hitz berri bat idaztean Aldatu idazketa-metodoa zuriune teklarekin Teklatuaren altuera eskala - Alfabetoa (Colemak Mod-DH) - Alfabetoa (Workman) "Erabili sistemaren hizkuntzak" "Aukeratu idazketa-metodoa" "Desegin" @@ -203,12 +185,10 @@ Sakatu luze ikurren tekla teklatu numerikorako Murriztu teklen arteko tarteak Beheko betegarriaren eskala - Kaitag (%s) ikurrak Pisua: Marroia Erabiltzaileak definituta (gauekoa) - Egin klik aurrebista ikusteko Hautatu koloreak testurako eta atzeko planoetarako Kaitag Itxi @@ -244,15 +224,13 @@ Moztu Garbitu arbela Hautatu hitza - %s (Sebeolsik 390) - %s (Sebeolsik Final) - Alfabetoa (Bépo) + %s (Sebeolsik 390) + %s (Sebeolsik Final) Gehitu diseinu pertsonalizatua Hautatu fitxategi bat formatu bateragarri batean. Formatuei buruzko informazioa eskuragarri dago %s. Kargatu fitxategia Ezin da fitxategia irakurri Kopiatu lehendik dagoen diseinua - Ezarri diseinuaren izena Benetan ezabatu %s diseinu pertsonalizatua? Sakatu diseinu gordina editatzeko Ikurrak (Arabiarrak) @@ -316,12 +294,12 @@ gailuak babestutako biltegiratzea Tresna-barraren norabide aldakorra ► Arbeleko tekla luze sakatuz (iradokizunen zerrendako aukerakoa) sistemako arbeleko edukia itsatsi egiten da. <br> <br> Iradokizun-zerrendako tresna-barrako teklak luze sakatuz gero, iradokizun-zerrendan finkatzen dira. <br> <br> Luze sakatu koma tekla arbelaren ikuspegia, emoji ikuspegia, esku bakarreko modua, ezarpenak edo hizkuntza aldatzeko atzitzeko: <br> • Emoji ikuspegia eta hizkuntza aldatzea desagertuko dira dagokion tekla baduzu. gaituta; <br> • Diseinu batzuetan ez da koma-tekla, posizio berean dagoen tekla baizik (adibidez, \'q\' da Dvorak diseinurako). <br> <br> Ezkutuko modua gaituta dagoenean, ez da hitzik ikasiko eta ez da emojirik gehituko azken berrietan. <br> <br> Sakatu ezkutuko ikonoa tresna-barrara sartzeko. <br> <br> Irristatu teklaren sarrera: Irristatu shift batetik beste tekla batera maiuskulazko tekla bakarra idazteko: <br> • Honek \'?123\' teklak ere balio du sinboloen teklatuan ikur bakarra idazteko eta erlazionatutako gakoak. <br> <br> Luze sakatu iradokizunen zerrendako iradokizun bat iradokizun gehiago erakusteko, eta ezabatzeko botoia iradokizun hau kentzeko. <br> <br> Irristatu gorantz iradokizun batetik iradokizun gehiago irekitzeko, eta askatu iradokizuna hautatzeko. <br> <br> Luze sakatu arbeleko historiako sarrera bat ainguratzeko (jar ezazu arbelean aingura kendu arte). <br> <br> Hiztegiak gehi ditzakezu fitxategi-esploratzaile batean irekita: <br> • Honek <i>content-uris</i>-ekin bakarrik funtzionatzen du eta ez <i>file-uris</i>-ekin , hau da, baliteke fitxategi-esploratzaile batzuekin ez funtzionatzea. <br> <br> <i>Arazte modua / APK arazketa</i> <br> <br> • Luze sakatu iradokizun bat iturburu-hiztegia erakusteko.<br> <br> • Arazketa APK erabiltzean, dezakezu bilatu Arazte-ezarpenak Hobespen aurreratuen barruan, nahiz eta erabilgarritasuna mugatua den hiztegiak erregistroan isurtzea izan ezik. <br> <br> • Aplikazioaren hutsegite bat gertatuz gero, Ezarpenak irekitzean hutsegiteen erregistroak nahi dituzun galdetuko zaizu. <br> <br> • Idazketa eleanitza erabiltzean, zuriune-barrak unean erabiltzen den hizkuntza zehazteko erabiltzen den konfiantza-balioa erakutsiko du. <br> <br> • Iradokizunek goian zenbaki txiki batzuk izango dituzte barne puntuazio eta iturburu-hiztegiren bat erakutsiz (desgaitu daiteke). <br> <br> Root sarbidearekin eskuzko babeskopiak egiten dituzten erabiltzaileentzat: Android 7-tik aurrera, partekatutako hobespen-fitxategia ez dago lehenetsitako kokapenean, aplikazioa %s erabiltzen ari delako. <br> Hau beharrezkoa da ezarpenak irakurri ahal izateko gailua desblokeatu aurretik, adibidez. abioan. <br> Fitxategia /data/user_de/0/package_id/shared_prefs/ helbidean dago, baina gailuaren eta Android bertsioaren araberakoa izan daiteke. - %s (Probhat) + %s (Probhat) Diseinu errorea: %s Beltza Kolore dinamikoak Alderantzikatu norabidea eskuinetik ezkerrera teklatu mota hautatzen denean - %s (Ikasle) + %s (Ikasle) Hiztegiak Barneko hiztegi nagusia Gehitu hiztegia fitxategitik @@ -353,9 +331,8 @@ Hizkuntza aldatzeko teklaren portaera Ezkutatu tresna-barra iradokizunak erabilgarri daudenean Hasi beti berehala - Mansi (%s) Idazketa azkarraren itxaron denbora - %s (Extended) + %s (Extended) Emojia Mansi Aurrebista flotagarria @@ -372,7 +349,6 @@ Hitzaren eskuinean Orria behera Orria gora - Kargatzeak uneko gaia gainidatziko du Iradoki arbeleko edukia Erakutsi duela gutxi kopiatutako arbeleko edukia iradokizun gisa Mugitu aurrebista keinu egitean @@ -405,4 +381,56 @@ Pertsonalizatu tresna-barrako tekla-kodeak Tekla-kodea Sakatze luzeko kodea + Ez erakutsi beti iradokizunik web edizioko eremuetarako + Banatze-tartea (horizontala) + Zuriunea + Erabili instalatutako aplikazioen izenak iradokizunak eta zuzenketak egiteko + Gaitu teklatu banatua (horizontala) + Egin dar-dar ez molestatzeko moduan + Web ediziorako eremuak (batez ere nabigatzaileetan aurkitzen direnak) oso ohiko arrazoia dira iradokizunen konfigurazioa beti erakusten duten arazoetarako + Zuzenketa automatikorako lasterbideak + Atzera-espazioak autozuzenketa desegiten du + Txertatu zuriunea iradokizun bat aukeratu ondoren + Denbora-zigilu gakoaren formatua + Mayus-ek kentzen du zuriune automatikoa + Gaituta dagoenean, lasterbideak autozuzenketaren bidez zabal daitezke + Bilatu aplikazioen izenak + Babeskopia berrezarri da + Txertatu zuriunea hitz bat idazteko keinuaren aurretik + Txertatu zuriunea hitz bat idazteko keinuaren ondoren + Ez txertatu zuriunerik Mayus sakatzean + Erakutsi zenbaki-errenkadako argibideak + Hiztegiak dituzten hizkuntzak + Erakutsi TLD popup teklak + Azpimota pertsonalizatua + URLak eta helbide elektronikoak idaztean, periodoen teklen popupak lehen mailako domeinuekin ordeztu + Zenbakien errenkada (oinarrizkoa) + %s (Baishakhi) + %s-n koloreak aurki eta parteka ditzakezu. + Override Emoji bertsioa + Emojien azalaren tonu lehenetsia + %s (Phonetic) + Sartu edo zuriunea sakatuta, numpad-eko beste teklen ondoren + Seguru %s ezabatu nahi duzula? + Ezarri letra-tipo pertsonalizatua fitxategitik + Dagbani + Sesotho + Eskalatu emojiak karaktereen tamainarekin + Bigarren mailako diseinuak + Abisua: hori da une honetan erabiltzen ari den diseinua + Tekla funtzionalak (pantaila handia) + Beheko betegarriaren eskala (horizontala) + Alboko betegarriaren eskala (horizontala) + Alboko betegarriaren eskala + Ezarri atzeko planoko irudia (horizontala) + Ezartzen ez bada, irudia bertikala erabiliko da + Seguru berrezarri nahi duzula ikono pertsonalizatu guztiak? + Banatu teklatua + Teklatuko karaktereen eskala + Emojien eskala + Neutroa + Dargwa (Urakhi) + % s-n diseinuak aurki eta parteka ditzakezu. + eztabaiden atala + Izen baliogabea diff --git a/app/src/main/res/values-fa/strings.xml b/app/src/main/res/values-fa/strings.xml index dd4c26268..ebbd536e9 100644 --- a/app/src/main/res/values-fa/strings.xml +++ b/app/src/main/res/values-fa/strings.xml @@ -16,7 +16,7 @@ "فعال کردن دونیم‌کردن صفحه‌کلید" "تغییر به دیگر روش‌های ورودی" "کلید تغییر زبان" - "%s میلی‌ثانیه" + "%s میلی‌ثانیه" "پیش‌فرض سیستم" برای پیشنهاد و تصحیح از نام مخاطبین استفاده شود "پیشنهادات شخصی شده" @@ -49,20 +49,9 @@ "اسپانیایی (امریکا)" "هندی انگلیسی" "صربی (لاتین)" - انگلیسی (بریتانیا) (%s) - انگلیسی (امریکا) (%s) - اسپانیایی (امریکا) (%s) - هندی انگلیسی (%s) - صربی (%s) - %s (سنتی) - %s (فشرده) - "بدون زبان (حروف الفبا)" - "‏حروف الفبا (QWERTY)" - "‏حروف الفبا (QWERTZ)" - "‏حروف الفبا (AZERTY)" - "‏حروف الفبا (Dvorak)" - "‏حروف الفبا (Colemak)" - "‏حروف الفبا (PC)" + %s (سنتی) + %s (فشرده) + "بدون زبان" "اموجی" "افزودن" "حذف" @@ -75,38 +64,33 @@ "اموجی برای صفحه‌کلید فیزیکی" "‏کلید Alt صفحه‌کلید فیزیکی، پالت اموجی را نشان می‌دهد" "پیش‌فرض" - به %s خوش آمدید + به %s خوش آمدید "با ورودی اشاره‌ای" "شروع به کار" - "مرحله بعد" - راه‌اندازی %s - فعال‌سازی %s - لطفاً «%s» را در تنظیمات «زبان‌ها و ورودی» علامت بزنید. این کار مجوز اجرا در دستگاه است. - %s از قبل در تنظیمات «زبان‌ها و ورودی» شما فعال شده است، بنابراین این مرحله تمام است. به مرحله بعد بروید! + راه‌اندازی %s + فعال‌سازی %s + لطفاً «%s» را در تنظیمات «زبان‌ها و ورودی» علامت بزنید. این کار مجوز اجرا در دستگاه است. "فعال‌سازی در تنظیمات" - به %s تعویض کنید - در مرحله بعد، «%s» را به عنوان روش ورودی نوشتار فعال خود انتخاب کنید. + به %s تعویض کنید + در مرحله بعد، «%s» را به عنوان روش ورودی نوشتار فعال خود انتخاب کنید. "تغییر روش‌های ورودی" "تبریک می‌گوییم، اکنون کاملاً آماده هستید!" - اکنون می‌توانید در همه برنامه‌های دلخواه خود با %s تایپ کنید. + اکنون می‌توانید در همه برنامه‌های دلخواه خود با %s تایپ کنید. "تمام شد" "نمایش نماد برنامه" "نمایش نماد برنامه در راه‌انداز" - "واژه‌نامه‌های برافزا" + "واژه‌نامه‌های برافزا" "واژه‌نامه موجود است" - "هیچ فرهنگ لغتی موجود نیست" "آخرین به‌روزرسانی" "تنظیمات" "حذف" - نسخه %1$s - "افرودن" + نسخه %1$s "افزودن به واژه‌نامه" "میان‌بر:" "زبان:" "کلمه‌ای تایپ کنید" "میان‌بر اختیاری" "ویرایش کلمه" - "واژه‌ای در واژه‌نامه کاربر ندارید. برای افزودن واژه، روی دکمه افزودن (+) ضربه بزنید." "برای همه زبان‌ها" "زبان‌های بیشتر…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" @@ -128,11 +112,9 @@ مدت زمان نگهداری تاریخچه کلید‌های بیشتر با فشار طولانی کلید فاصله، منوی انتخاب روش ورودی را باز می کند - حروف الفبا (Colemak Mod-DH) - حروف الفبا (Workman) ظاهر از تنظیمات سیستم پیروی می‌کند اگر غیرفعال باشد، کلید کلیپ بورد، محتوای خود را در صورت وجود جایگذاری می‌کند - %sدقیقه. + %sدقیقه. ردیف اعداد همیشه ردیف اعداد نشان داده شود روش ورودی را با کلید فاصله تغییر دهید @@ -145,7 +127,7 @@ مقیاس ارتفاع صفحه کلید نمایش اشاره کلید‌ها نمایش اشاره لمس طولانی - %s (حروف) + %s (حروف) حاشیه کلید حالت روز/شب خودکار "لغو" diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index cc252abda..be3ca8137 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -16,7 +16,7 @@ "Ota jaettu näppäimistö käyttöön" "Käytä toista syöttötapaa" "Kielenvaihtonäppäin" - "%s ms" + "%s ms" "Järjestelmän oletusarvo" Käytä yhteystietojen nimiä ehdotuksissa ja korjauksissa "Personoidut ehdotukset" @@ -49,20 +49,9 @@ "espanja (Yhdysvallat)" "Hindienglanti" "serbialainen (latinal.)" - "englanti (UK) (%s)" - "englanti (US) (%s)" - "espanja (US) (%s)" - "Hindienglanti (%s)" - "serbialainen (%s)" - "%s (perinteinen)" - "%s (tiivis)" - "Ei kieltä (aakkoset)" - "aakkoset (QWERTY)" - "Aakkoset (QWERTZ)" - "Aakkoset (AZERTY)" - "Aakkoset (Dvorak)" - "Aakkoset (Colemak)" - "Aakkoset (PC)" + "%s (perinteinen)" + "%s (tiivis)" + "Ei kieltä" "Emoji" "Lisää" "Poista" @@ -75,38 +64,33 @@ "Hymiö fyysisellä näppäimistöllä" Fyysinen Alt-näppäin näyttää emoji-paletin "Oletusarvot" - "Tervetuloa käyttämään sovellusta %s" + "Tervetuloa käyttämään sovellusta %s" "ja piirtokirjoitus" "Aloita" - "Seuraava vaihe" - "Sovelluksen %s asetukset" - "Ota %s käyttöön" - Valitse%s Kielet ja syöttötapa ‑asetuksissa. Se antaa sovellukselle luvan toimia laitteellasi.\" - "%s on jo otettu käyttöön Kielet ja syöttötapa ‑asetuksissa, joten tämä vaihe on valmis. Siirrytään eteenpäin!" + "Sovelluksen %s asetukset" + "Ota %s käyttöön" + Valitse%s Kielet ja syöttötapa ‑asetuksissa. Se antaa sovellukselle luvan toimia laitteellasi.\" "Ota käyttöön asetuksissa" - "Siirry sovellukseen %s" - Valitse%s käytössä olevaksi tekstinsyöttötavaksi.\" + "Siirry sovellukseen %s" + Valitse%s käytössä olevaksi tekstinsyöttötavaksi.\" "Vaihda syöttötapaa" "Onneksi olkoon, valmista tuli!" - Nyt voit kirjoittaa kaikki suosikkisovelluksesi %s. + Nyt voit kirjoittaa kaikki suosikkisovelluksesi %s. "Valmis" "Näytä sovelluskuvake" Näytä sovelluskuvake käynnistysohjelmassa - "Sanakirjalisäosat" + "Sanakirjalisäosat" "Sanakirja saatavilla" - "Ei sanak. saatavilla" "Päivitetty viimeksi" "Asetukset" "Poista" - "Versio %1$s" - "Lisää" + "Versio %1$s" "Lisää sanakirjaan" "Pikanäppäin:" "Kieli:" "Kirjoita sana" "Valinnainen pikanäppäin" "Muokkaa sanaa" - "Käyttäjän sanakirjassa ei ole sanoja. Lisää sana koskettamalla Lisää (+) ‑painiketta." "Kaikille kielille" "Lisää kieliä…" " ABCDEFGHIJKLMNOPQRSTUVWXYZÅÄÖ" @@ -156,7 +140,7 @@ Näppäinreunat Automaattinen päivä-/yötila Kielen vaihtonäppäimen toiminta - %s min + %s min Lisää sanat henkilökohtaiseen sanakirjaan Näytä ehdotukset aina Enemmän autom. korjausta @@ -200,7 +184,6 @@ Tummempi Pilvinen Värit (yö) - Lataaminen korvaa nykyisen teeman Ulkoasu seuraa järjestelmän asetuksia Näppäimistön tausta Emoji @@ -227,7 +210,6 @@ Tyhjennä leikepöytä Valitse tekstin ja taustan värit - Anna asettelulle nimi Korvaa sanakirja Tyyli %s (kokeellinen) @@ -315,4 +297,4 @@ Lisää hyvin yleiset muunnelmat (oletus) Poista ylimääräiset ponnahdusikkunat Näytä vihjeet numerorivillä - \ No newline at end of file + diff --git a/app/src/main/res/values-fil/strings.xml b/app/src/main/res/values-fil/strings.xml index 0e1020576..26585ae54 100644 --- a/app/src/main/res/values-fil/strings.xml +++ b/app/src/main/res/values-fil/strings.xml @@ -22,7 +22,7 @@ Ilipat ang pareho Key sa paglipat ng wika Key ng emoji - %s min + %s min Default ng sistema Walang limitasyon Babala: Ang pag-disable ng setting na ito ay iki-clear ang mga natutong data @@ -50,7 +50,7 @@ Mga Setting ng Spell Checker ng Heliboard Hanapin ang mga pangalan ng contact Mga mungkahi - %s ms + %s ms Gamitin ang pangalan mula sa Mga Contact para sa mungkahi at pagtatama Idagdag ang mga salita sa personal na diksyunaryo Naglalagay ng tuldok na may puwang ang pag-double tap sa spacebar diff --git a/app/src/main/res/values-fr-rCA/strings.xml b/app/src/main/res/values-fr-rCA/strings.xml index 2cd616469..adc25ab40 100644 --- a/app/src/main/res/values-fr-rCA/strings.xml +++ b/app/src/main/res/values-fr-rCA/strings.xml @@ -16,7 +16,7 @@ "Activer le clavier en deux parties" "Autres modes de saisie" "Touche de sélection de langue" - "%s ms" + "%s ms" "Paramètres par défaut" "Utiliser des noms de contacts pour les suggestions et corrections" "Suggestions personnalisées" @@ -49,20 +49,9 @@ "Espagnol (États-Unis)" "Hinglish" "Serbe (latin)" - "anglais (Royaume-Uni) (%s)" - "anglais (États-Unis) (%s)" - "espagnol (États-Unis) (%s)" - "Hinglish (%s)" - "Serbe (%s)" - "%s (traditionnel)" - "%s (compact)" - "Aucune langue (alphabet)" - "Alphabet latin (QWERTY)" - "Alphabet latin (QWERTZ)" - "Alphabet latin (AZERTY)" - "Alphabet latin (Dvorak)" - "Alphabet latin (Colemak)" - "Alphabet latin (PC)" + "%s (traditionnel)" + "%s (compact)" + "Aucune langue" "Emoji" "Ajouter" "Supprimer" @@ -75,38 +64,33 @@ "Emoji pour clavier physique" "La touche Alt affiche la palette d\'emoji" "Par défaut" - "Bienvenue dans %s" + "Bienvenue dans %s" "avec la saisie gestuelle" "Commencer" - "Étape suivante" - "Configurer %s" - "Activer %s" - Cochez «%s » dans le menu Langues et méthodes d\'entrée. Cela permettra à l\'application de fonctionner sur votre appareil.\" - "%s est déjà activée dans le menu Langues et méthodes d\'entrée. Excellent, passons à la prochaine étape!" + "Configurer %s" + "Activer %s" + Cochez «%s » dans le menu Langues et méthodes d\'entrée. Cela permettra à l\'application de fonctionner sur votre appareil.\" "Activer le clavier dans les paramètres" - "Basculer vers %s" - "Sélectionnez ensuite \"%s\" comme mode de saisie actif." + "Basculer vers %s" + "Sélectionnez ensuite \"%s\" comme mode de saisie actif." "Changer de mode de saisie" "Félicitations, l\'opération est terminée" - "Avec %s, vous pouvez saisir du texte dans toutes vos applications préférées." + "Avec %s, vous pouvez saisir du texte dans toutes vos applications préférées." "OK" "Afficher icône application" "Afficher l\'icône de l\'application dans le lanceur" - "Dictionnaires complémentaires" + "Dictionnaires complémentaires" "Dictionnaire disponible" - "Aucun dictionnaire" "Dernière mise à jour" "Paramètres" "Supprimer" - "Version %1$s" - "Ajouter" + "Version %1$s" "Ajouter au dictionnaire" "Raccourci :" "Langue :" "Entrez un mot" "Raccourci facultatif" "Modifier le mot" - "Votre dictionnaire personnel ne contient aucun mot. Pour ajouter un mot, touchez le bouton d\'ajout (+)." "Pour toutes les langues" "Plus de langues…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" @@ -123,4 +107,4 @@ "Rech." "Pause" "Att." - \ No newline at end of file + diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 8e797e67c..821a4d993 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -19,7 +19,7 @@ Changer de langue Changer les deux "Touche de sélection de langue" - "%s ms" + "%s ms" "Paramètres par défaut" Utilise les noms de contacts pour les suggestions et les corrections "Suggestions personnalisées" @@ -59,20 +59,9 @@ "Espagnol (États-Unis)" "Hindi/Anglais" "Serbe (latin)" - Anglais (Royaume-Uni) (%s) - Anglais (États-Unis) (%s) - Espagnol (États-Unis) (%s) - Hindi/Anglais (%s) - Serbe (%s) - %s (Traditionnel) - %s (Compact) - "Aucune langue (latin)" - "Alphabet latin (QWERTY)" - "Alphabet latin (QWERTZ)" - "Alphabet latin (AZERTY)" - "Alphabet latin (Dvorak)" - "Alphabet latin (Colemak)" - "Alphabet latin (PC)" + %s (Traditionnel) + %s (Compact) + "Aucune langue" Émoji "Ajouter" "Supprimer" @@ -83,7 +72,6 @@ Sélectionner un fichier dans un format compatible. Des informations sur les formats sont disponibles %s. Charger fichier Copier une disposition existante - Définir le nom de la disposition Souhaitez-vous réellement supprimer la disposition personnalisée %s ? Erreur de disposition : %s Appuyez pour modifier la disposition d\'origine @@ -95,28 +83,26 @@ "Durée de vibration des touches" "Volume du son des touches" "Délai d\'un appui long sur les touches" - "Emojis pour clavier physique" + Émojis pour clavier physique "La touche Alt physique permet d\'afficher la palette d\'emoji" "Par défaut" - Bienvenue sur %s + Bienvenue sur %s "avec la saisie gestuelle" "Commencer" - "Étape suivante" - Configurer %s - Activer %s - Veuillez vérifier que %s est activé dans vos paramètres de langue et de saisie. Cela autorisera son fonctionnement sur votre appareil. - L’application %s est déjà activée dans vos paramètres « Langues et saisie ». Passez à l’étape suivante ! + Configurer %s + Activer %s + Veuillez vérifier que %s est activé dans vos paramètres de langue et de saisie. Cela autorisera son fonctionnement sur votre appareil. "Activer le clavier dans les paramètres" - Basculer vers %s - Sélectionnez ensuite « %s » comme méthode de saisie active. + Basculer vers %s + Sélectionnez ensuite « %s » comme méthode de saisie active. "Changer de mode de saisie" Félicitations, l\'opération est terminée ! - Avec %s, vous pouvez saisir du texte dans toutes vos applications préférées. + Avec %s, vous pouvez saisir du texte dans toutes vos applications préférées. Configurer le clavier "OK" "Afficher l\'icône de l\'application" "Affiche l\'icône de l\'application dans le lanceur" - "Dictionnaires complémentaires" + "Dictionnaires complémentaires" Dictionnaires Dictionnaires intégrés "Ajouter dictionnaire" @@ -139,11 +125,9 @@ Nouveau dictionnaire: "Utiliser quand même" "Erreur de chargement du fichier dictionnaire" "Dictionnaire disponible" - "Aucun dictionnaire" "Dernière mise à jour" "Supprimer" - Version %1$s - "Ajouter" + Version %s "Ajouter au dictionnaire" "Raccourci :" Poids : @@ -151,7 +135,6 @@ Nouveau dictionnaire: "Saisissez un mot" "Raccourci facultatif" "Modifier le mot" - "Votre dictionnaire personnel ne contient aucun mot. Pour ajouter un mot, appuyez sur le bouton d\'ajout \"+\"." "Pour toutes les langues" "Plus de langues…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" @@ -195,7 +178,7 @@ Nouveau dictionnaire: Sélectionner la source des indices Sélectionner l\'ordre des touches pop-up Nombre - Langue + @string/subtype_locale Langue (prioritaire) Disposition Symboles @@ -241,7 +224,6 @@ Nouveau dictionnaire: Choix automatique de la couleur Afficher les couleurs principales Afficher toutes les couleurs - Cliquez pour voir l\'aperçu Sélection des couleurs du texte et de l\'arrière-plan Arrière-plan du clavier Texte des touches @@ -265,8 +247,6 @@ Nouveau dictionnaire: Bordures des touches Mode jour/nuit automatique Réduire l\'espace entre les touches - Alphabet (Workman) - Alphabet (Colemak Mod-DH) Touche d\'accès aux émojis Touches supplémentaires Historique du presse-papier @@ -274,8 +254,8 @@ Nouveau dictionnaire: Temps de rétention de l\'historique Si désactivé, l\'appui sur la touche presse-papier collera l’éventuel contenu du presse-papier Activer l\'historique - %smin. - %s (Akkhor) + %s min. + %s (Akkhor) Espace automatique après la ponctuation Insertion automatique d\'un espace après la ponctuation lors de la saisie d\'un nouveau mot Afficher plus de signes diacritiques dans les pop-ups @@ -303,12 +283,11 @@ Nouveau dictionnaire: Rechercher "Pause" "Attente" - Alphabet (Bépo) %s (expérimental) Version Impossible de lire le fichier - %s (Sebeolsik 390) - %s (Sebeolsik Final) + %s (Sebeolsik 390) + %s (Sebeolsik Final) Sens variable de la barre d\'outils Appui long sur la touche des symboles pour afficher le pavé numérique Pavé téléphonique @@ -318,7 +297,6 @@ Nouveau dictionnaire: Balayage horizontal de la barre d\'espace Pavé numérique (paysage) Couper - Kaitag (%s) Symboles (Arabe) Symboles du pavé téléphonique Chiffres @@ -327,15 +305,14 @@ Nouveau dictionnaire: Balayage vertical de la barre espace Inverser le sens de la barre d\'outils lorsqu\'un clavier droite-gauche est sélectionné Symboles - %s (Étudiant) - %s (Probhat) + %s (Étudiant) + %s (Probhat) Toujours utiliser la suggestion du milieu En appuyant sur espace ou sur un signe de ponctuation, la suggestion du milieu sera saisie Fermer le presse-papiers Sélectionner les touches de la barre d\'outils du presse-papiers - %s (Étendu) + %s (Étendu) Mansi - Mansi (%s) Afficher plus de couleurs Ce paramètre expose toutes les couleurs utilisées en interne. La liste des couleurs peut être modifiée à tout moment. La couleur par défaut est aléatoire et les noms ne seront pas traduits. Touches fonctionnelles @@ -367,12 +344,11 @@ Nouveau dictionnaire: Mot de droite Haut de page Bas de page - Le chargement écrasera le thème actuel Basculer vers le pavé numérique Passer au clavier principal après avoir… Sélectionné une entrée dans l\'historique du presse-papiers - Appuyé sur Entrée ou sur Espace après la sélection d\'un symbole dans la vue des symboles - Sélectionné un emoji dans la vue des emojis + Appuyé sur Entrée ou sur la barre d\'espace après la sélection d\'un symbole dans la vue des symboles + Sélectionné un émoji dans la vue des émojis Ajouter les variantes les plus courantes (par défaut) Supprimer les touches pop-up déjà présentes dans la disposition de base Supprimer les pop-ups redondants @@ -384,7 +360,7 @@ Nouveau dictionnaire: Rangée de chiffres Texte personnalisé sur la barre d\'espace Rangée inférieure du presse-papier - Rangée inférieure des emojis + Rangée inférieure des émojis Tabulation Supprimer Majuscule @@ -406,10 +382,9 @@ Nouveau dictionnaire: Voulez-vous vraiment réinitialiser toutes les icônes personnalisées ? Corbeille Vibrer en mode Ne pas déranger - %s (Phonétique) - Remplacer la version des Emojis + %s (Phonétique) + Remplacer la version des émojis Dargwa (Urakhi) - Urakhi (%s) Correction automatique des raccourcis Lorsque les raccourcis sont activés, ils peuvent être étendus par correction automatique Définir une police personnalisée à partir d\'un fichier @@ -429,7 +404,7 @@ Nouveau dictionnaire: Voulez-vous vraiment supprimer %s ? Nom invalide Sous-type personnalisé - %s (Baishakhi) + %s (Baishakhi) Dispositions secondaires Touches fonctionnelles (grand écran) Langues avec dictionnaires @@ -437,4 +412,27 @@ Nouveau dictionnaire: Vous pouvez trouver et partager des couleurs dans le %s. Vous pouvez trouver et partager des dispositions dans le %s. Section de discussion + Afficher les suggestions de domaines (TLD) + Remplacer les suggestions de la touche point par des extensions de domaine (TLD) lors de la saisie d’URL ou d’adresses e-mail + Appuyé sur Entrée ou sur la barre d\'espace après d\'autres touches du pavé numérique + Les champs d\'édition Web (principalement présents dans les navigateurs) sont une cause très courante de problèmes avec le paramètre « Toujours afficher les suggestions » + Rangée numérique (standard) + Ne pas forcer l\'affichage des suggestions pour les champs de saisie web + Espace + Espace automatique avant de saisir un mot par geste + Espace automatique après la saisie gestuelle d\'un mot + Shift supprime l\'espace automatique en attente + Espace automatique après avoir sélectionné une suggestion + La touche Retour arrière annule la correction automatique + Pas d\'espace automatique lors de l\'appui sur Maj + Format de la clé d\'horodatage + Dagbani + Sesotho + Ajuster la taille des touches emoji à la taille de la police + Sauvegarde restaurée + Rechercher les noms des applications + Utiliser les noms des applications installées pour les suggestions et les corrections + Neutre + Teint de peau par défaut des emojis + %1$s (%2$s) diff --git a/app/src/main/res/values-gl/strings.xml b/app/src/main/res/values-gl/strings.xml index c2fa7a993..197b7db35 100644 --- a/app/src/main/res/values-gl/strings.xml +++ b/app/src/main/res/values-gl/strings.xml @@ -16,7 +16,7 @@ "Activar teclado dividido" "Outros métodos de entrada" "Tecla de cambio de idioma" - "%s ms" + "%s ms" "Predeterminado do sistema" "Utiliza nomes de contactos para as suxestións e correccións" "Suxestións personalizadas" @@ -49,20 +49,9 @@ "Español (EUA)" "Hinglish" "Serbio (alfabeto latino)" - "Inglés (Reino Unido) (%s)" - "Inglés (EUA) (%s)" - "Español (EUA) (%s)" - "Hinglish (%s)" - "Serbio (%s)" - "%s (tradicional)" - "%s (compacto)" - "Ningún idioma (alfabeto)" - "alfabeto (QWERTY)" - "Alfabeto (QWERTZ)" - "Alfabeto (AZERTY)" - "Alfabeto (Dvorak)" - "Alfabeto (Colemak)" - "Alfabeto (PC)" + "%s (tradicional)" + "%s (compacto)" + "Ningún idioma" "Emoji" "Engadir" "Eliminar" @@ -75,38 +64,33 @@ "Emojis para o teclado físico" "A tecla Alt física mostra a paleta de emoji" "Predeterminado" - Ben vida a %s + Ben vida a %s "con escritura por xestos" "Comezar" - "Seguinte paso" - "Configurando %s" - "Activar %s" - Comproba a aplicación%s\" na configuración Idioma e introdución de texto para que se poida executar no teu dispositivo.\" - %s xa está activada en Idiomas e Axustes de escritura, así que isto xa está. Imos ao seguinte paso!\" + "Configurando %s" + "Activar %s" + Comproba a aplicación%s\" na configuración Idioma e introdución de texto para que se poida executar no teu dispositivo.\" "Activar en Configuración" - "Cambiar a %s" - "A continuación, selecciona \"%s\" como o método de introdución de texto activo." + "Cambiar a %s" + "A continuación, selecciona \"%s\" como o método de introdución de texto activo." "Cambiar métodos de entrada" "Parabéns, está todo listo!" - "Agora podes escribir en todas as túas aplicacións favoritas con %s." + "Agora podes escribir en todas as túas aplicacións favoritas con %s." "Finalizado" "Mostrar icona da aplicación" "Mostra a icona da aplicación no Launcher" - "Dicionarios complementarios" + "Dicionarios complementarios" "Dicionario dispoñible" - "Non hai dicionarios" "Última actualización" "Configuración" "Eliminar" - "Versión %1$s" - "Engadir" + "Versión %1$s" "Engadir ao dicionario" "Atallo:" "Idioma:" "Escribe unha palabra" "Atallo opcional" "Editar palabra" - "Non tes ningunha palabra no dicionario de usuario. Toca o botón Engadir (+) para engadir unha palabra." "Para todos os idiomas" "Máis idiomas…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" @@ -123,9 +107,9 @@ "Buscar" "Pausa" "Espera" - %s min - %s (Akkhor) - %s (Sebeolsik 390) + %s min + %s (Akkhor) + %s (Sebeolsik 390) %s (experimental) Tamaño: Engadir unha palabra @@ -154,7 +138,6 @@ Elixir cor automáticamente Mostrar só cores principais Mostrar todas as cores - Preme para vista previa Elixe as cores do texto e fondo Fodo do teclado Texto da tecla @@ -254,15 +237,12 @@ Espazo reducido entre teclas Escala de altura do teclado Escala do espazo inferior do teclado - %s (Sebeolsik Final) - Alfabeto (Colemak Mod-DH) - Alfabeto (Bépo) + %s (Sebeolsik Final) Engadir disposición persoal Elixe un ficheiro cun formato compatible. Tes información sobre os formatos en %s. Cargar ficheiro Non se puido ler o ficheiro Copiar disposición existente - Dar nome á disposición Queres eliminar a disposición persoal %s? Erro na disposición: %s Toca para editar a disposición @@ -300,7 +280,6 @@ aquí Fondo da tecla función O ficheiro seleccionado é para %1$s, mais agardábase %2$s. Usar igualmente para %2$s? - Alfabeto (Workman) Revisor de Ortografía Axustes do revisor de Ortografía de HeliBoard Vas precisar a biblioteca para \'%s\': As bibliotecas incompatibles podería estragar a app ao escribir. @@ -320,7 +299,6 @@ Teclado numérico Teclado Num (paisaxe) ► Coa pulsación longa na tecla do Portapapeis (opcional nas barra coas suxestións) pegas o contido do portapapeis. <br><br> ► Coa pulsación longa nunha tecla la barra de suxestións fíxala na barra. <br> <br> ► Coa pulsación longa na telca da vírgula accedes a Vista do Portapapeis, Vista de Emojis, Modo dunha soa man, Axustes ou Cambiar de Idioma: <br> • A Vista de Emoji e Cambio de Idioma aparecerán se tes a tecla correspondente activada; <br> \t • Nalgunhas disposicións non é a tecla da Vírgula, se non a tecla que está na mesma posición (ex. é \'q\' no teclado Dvorak). <br> <br> ► Co modo Incógnito activado, non aprenderá palabras, e tampouco se engaden emojis aos recentes. <br> <br> ► Preme na icona Incógnito para acceder ás ferramentas. <br> <br> ► Escribir con tecla esvaradía: Despraza desde a tecla Shift hacia outra letra para escribir unha sóa maiúscula: <br> \t• Isto tamén funciona para a tecla \'?123\" para escribir un só símbolo dos do teclado de símbolos, e as teclas relacionadas. <br> <br> ► Coa pulsación longa nunha suxestión da barra de suxestións aparecen máis suxestións, e tamén un botón para eliminar esa suxestión. <br> <br> ► Desprázate hacia arriba para ter máis suxestións, e solta onde estea suxestión que queres. <br> <br> ► Fixa unha entrada do historial do portapapeis coa pulsación longa sobre ela (mantela no portapapeis ata que a liberes). <br> <br> ► Podes engadir dicionarios abríndoos nun explorador de ficheiros: <br> \t• Isto só funciona con <i>content-uris</i> e non con <i>file-uris</i>, polo que podería non funcionar nalgúns exploradores de ficheiros. <br> <br> <i>Modo depuración / APK debug</i> <br> <br> \t • Pulsación longa sobre unha suxestión para mostrar o dicionario de orixe.<br> <br> \t • No modo depuración APK, podes atopar os Axustes de Depuración dentro de Preferencias Avanzadas, aínda que a utilidade é limitada excepto para meter os dicionarios no ficheiro de depuración.<br> <br> \t • Se fallase a aplicación, pediráseche se queres ver os ficheiros de depuración ao abrir os Axustes. <br> <br> \t• Ao usar a escritura multi-idioma, a barra espazadora mostrará un valor de confianza usado para determinar o idioma que estás a usar. <br> <br> \t• As suxestións terán un número pequeniño enriba mostrando unha puntuación interna e o dicionario de orixe (pode desactivarse).<br> <br> ► Para as usuarias que fan copias de apoio con acceso root: Desde Android 7, o ficheiro de preferencias compartidas non está na localización por defecto, xa que a app usa %s. <br> isto é preciso para que os axustes se poidan ler antes de que o dispositivo se desbloquee, por exemplo no inicio (boot). <br> O ficheiro está en /data/user_de/0/package_id/shared_prefs/, aínda que podería depender da versión do dispositivo Android. - Kaitag (%s) Kaitag Xesto de desprazamento vertical na barra Xesto de desprazamento horizontal na barra @@ -328,17 +306,16 @@ Mover Cursor Dirección variable barra ferramentas Dirección inversa cando está seleccionado o tipo de teclado de dereita a esquerda - %s (Probhat) - %s (Estudante) + %s (Probhat) + %s (Estudante) Tecla con pulsación longa para teclado numérico Cortar Usar sempre a suxestión do medio Ao premer no espazo ou puntuación, escríbese a suxestión do medio Escoller teclas da barra de ferramentas do portapapeis Pechar historial do portapapeis - %s (Extendido) + %s (Extendido) Mansi - Mansi (%s) Mostrar máis cores Este axuste expón todas as cores que se usan internamente. A lista de cores pode cambiar en calquera momento. A cor por defecto é aleatoria, e os nomes non serán traduciddos. Teclas función @@ -362,7 +339,6 @@ Gardar nun ficheiro Copiar ao Portapapeis Cargar - Ao cargar sobreescribe o decorado actual Inicio da páxina Final da páxina Esquerda da palabra @@ -408,10 +384,9 @@ Papeleira Restablecer todas as iconas personalizadas? Vibrar no modo non molestar - %s (Fonético) + %s (Fonético) Sobrescribir versión Emoji Dargwa (Urakhi) - Urakhi (%s) Atallos para autocorrector Ao activar os atallos poderían despregarse polo autocorrector Establecer tipo de letra persoal desde ficheiro @@ -433,5 +408,28 @@ Idiomas con dicionarios zona de conversa Podes atopar e compartir disposicións na %s. - %s (Baishakhi) + %s (Baishakhi) + Subtipo personalizado + Non mostrar sempre suxestións para os campos texto nas webs + Os campos de texto nas webs (principalmente no navegador) son causa frecuente de problemas coas suxestións automáticas + Fila de números (básica) + Substitúe na emerxente da tecla do punto con dominios de alto nivel ao escribir URL e enderezos de correo + Mostrar teclas emerxentes TLD + Ao premer enter ou espazo após escribir no teclado numérico + caracter separador ancho cero + Eliminar %s? + Tes certeza de querer limpar todos os códigos personalizados? + Nome non válido + Distancia de desprazamento cambio de idioma + Espazo + Espazo automatico despois do xesto escribindo palabra + Non autoespazo ao premer maiúscula + Maiúscula quita o espazo automatico pendente + Formato para a tecla de marca temporal + Espazo automatico despois de elexir suxestión + Espazo automatico antes do xesto escribindo palabra + Dagbani + Sesotho + Escalar tamaño da tecla emoji ao tamaño da letra + Retroceso reverte a autocorrección diff --git a/app/src/main/res/values-gu/strings.xml b/app/src/main/res/values-gu/strings.xml index df251d843..c33613888 100644 --- a/app/src/main/res/values-gu/strings.xml +++ b/app/src/main/res/values-gu/strings.xml @@ -16,7 +16,7 @@ "વિભાજિત કીબોર્ડ સક્ષમ કરો" "અન્ય ઇનપુટ પદ્ધતિઓ પર સ્વિચ કરો" "ભાષા સ્વિચ કી" - "%sms" + "%sms" "સિસ્ટમ ડિફોલ્ટ" "સૂચનો અને સુધારાઓ માટે સંપર્કોમાંથી નામોનો ઉપયોગ કરો" "વ્યક્તિગત સૂચનો" @@ -49,20 +49,9 @@ "સ્પેનિશ (US)" "હિંગ્લિશ" "સર્બિયન (લેટિન)" - "અંગ્રેજી (યુકે) (%s)" - "અંગ્રેજી (યુએસ) (%s)" - "સ્પેનિશ (યુએસ) (%s)" - "હિંગ્લિશ (%s)" - "સર્બિયન (%s)" - "%s (પરંપરાગત)" - "%s (કોમ્પેક્ટ)" - "ભાષા નથી (આલ્ફાબેટ)" - "આલ્ફાબેટ (QWERTY)" - "આલ્ફાબેટ (QWERTZ)" - "આલ્ફાબેટ (AZERTY)" - "આલ્ફાબેટ (Dvorak)" - "આલ્ફાબેટ (Colemak)" - "આલ્ફાબેટ (PC)" + "%s (પરંપરાગત)" + "%s (કોમ્પેક્ટ)" + "ભાષા નથી" "ઇમોજી" "ઉમેરો" "દૂર કરો" @@ -75,38 +64,33 @@ "ભૌતિક કીબોર્ડ માટે ઇમોજી" "ભૌતિક Alt કી ઇમોજી પેલેટ દર્શાવે છે" "ડિફોલ્ટ" - %s પર સ્વાગત છે\" + %s પર સ્વાગત છે\" "સાંકેતિક ટાઇપિંગ દ્વારા" "પ્રારંભ કરો" - "આગલું પગલું" - %s સેટ કરી રહ્યું છે\" - %s સક્ષમ કરો\" - "કૃપા કરીને \"%s\" ને તમારી ભાષાઓ અને ઇનપુટ સેટિંગ્સમાં તપાસો. આ તેને તમારા ઉપકરણ પર ચાલવા માટે અધિકૃત કરશે." - "%s એ તમારી ભાષાઓ અને ઇનપુટ સેટિંગ્સમાં પહેલાથી જ સક્ષમ કરેલું છે, તેથી આ પગલું પૂર્ણ થયું. હવે આગલા પર!" + %s સેટ કરી રહ્યું છે\" + %s સક્ષમ કરો\" + "કૃપા કરીને \"%s\" ને તમારી ભાષાઓ અને ઇનપુટ સેટિંગ્સમાં તપાસો. આ તેને તમારા ઉપકરણ પર ચાલવા માટે અધિકૃત કરશે." "સેટિંગ્સમાં સક્ષમ કરો" - %s પર સ્વિચ કરો\" - "આગલું, \"%s\" ને તમારા સક્રિય ટેક્સ્ટ-ઇનપુટ પદ્ધતિ તરીકે પસંદ કરો." + %s પર સ્વિચ કરો\" + "આગલું, \"%s\" ને તમારા સક્રિય ટેક્સ્ટ-ઇનપુટ પદ્ધતિ તરીકે પસંદ કરો." "ઇનપુટ પદ્ધતિઓ પર સ્વિચ કરો" "અભિનંદન, તમે બધું સેટ કર્યું છે!" - "હવે તમે તમારી મનપસંદ એપ્લિકેશન્સમાં %s થી ટાઇપ કરી શકો છો." + "હવે તમે તમારી મનપસંદ એપ્લિકેશન્સમાં %s થી ટાઇપ કરી શકો છો." "સમાપ્ત થયું" "ઍપ્લિકેશન આયકન બતાવો" "લોંચરમાં ઍપ્લિકેશન આયકન પ્રદર્શિત કરો" - "એડ-ઓન શબ્દકોશ" + "એડ-ઓન શબ્દકોશ" "શબ્દકોશ ઉપલબ્ધ છે" - "કોઈ શબ્દકોશ ઉપલબ્ધ નથી" "છેલ્લે અપડેટ કર્યું" "સેટિંગ્સ" "કાઢી નાખો" - "સંસ્કરણ %1$s" - "ઉમેરો" + "સંસ્કરણ %1$s" "શબ્દકોષમાં ઉમેરો" "શોર્ટકટ:" "ભાષા:" "એક શબ્દ લખો" "વૈકલ્પિક શોર્ટકટ" "શબ્દ સંપાદિત કરો" - "તમારી પાસે વપરાશકર્તા શબ્દકોશમાં કોઈપણ શબ્દ નથી. શબ્દને ઉમેરવા માટે, ઉમેરો (+) બટન ટૅપ કરો." "તમામ" "વધુ ભાષાઓ…" " [અ આ ઇ ઈ ઉ ઊ ઋ એ ઐ ઓ ઔ ક ખ ગ ઘ ઙ ચ છ જ ઝ ઞ ટ ઠ ડ ઢ ણ ત થ દ ધ ન પ ફ બ ભ મ ય ર લ વ શ ષ સ હ ળ]" diff --git a/app/src/main/res/values-hi/strings.xml b/app/src/main/res/values-hi/strings.xml index 18cfa548b..e6d7ace04 100644 --- a/app/src/main/res/values-hi/strings.xml +++ b/app/src/main/res/values-hi/strings.xml @@ -16,7 +16,7 @@ "स्प्लिट कीबोर्ड चालू करें" "अन्‍य इनपुट पद्धतियों पर जाएं" "भाषा स्विच कुंजी" - "%s मिलीसेकंड" + "%s मिलीसेकंड" "सिस्टम डिफ़ॉल्ट" "सुझाव और सुधार के लिए संपर्क से नामों का उपयोग करें" "मनमुताबिक सुझाव" @@ -49,20 +49,9 @@ "स्पेनिश (यूएस)" "हिंग्लिश" "सर्बियाई (लैटिन)" - "अंग्रेज़ी (यूके) (%s)" - "अंग्रेज़ी (यूएस) (%s)" - "स्‍पेनिश (यूएस) (%s)" - "हिंग्लिश (%s)" - "सर्बियाई (%s)" - "%s (पारंपरिक)" - "%s (संक्षिप्त)" - "भाषा उपलब्ध नहीं है (लैटिन वर्णाक्षर)" - "वर्णाक्षर (QWERTY)" - "वर्णाक्षर (QWERTZ)" - "वर्णाक्षर (AZERTY)" - "वर्णाक्षर (Dvorak)" - "वर्णाक्षर (Colemak)" - "वर्णाक्षर (PC)" + "%s (पारंपरिक)" + "%s (संक्षिप्त)" + "भाषा उपलब्ध नहीं है" "Emoji" "जोड़ें" "निकालें" @@ -75,38 +64,33 @@ "कीबोर्ड के लिए स्माइलीज़" "भौतिक Alt कुंजी इमोजी पैलेट दिखाती है" "सामान्य" - %s में आपका स्वागत है\" + %s में आपका स्वागत है\" "जेस्चर टाइपिंग के साथ" "आरंभ करें" - "अगला चरण" - %s सेट करना\" - %s को चालू करें\" - "कृपया अपनी भाषा और इनपुट सेटिंग में \"%s\" को सही का निशान लगाकर चुनें. इससे उसे आपके डिवाइस पर चलने की अनुमति मिल जाएगी." - "%s आपकी भाषा और इनपुट सेटिंग में पहले से सक्षम है, इसलिए यह चरण पूरा हो गया है. अगले चरण पर जाएं!" + %s सेट करना\" + %s को चालू करें\" + "कृपया अपनी भाषा और इनपुट सेटिंग में \"%s\" को सही का निशान लगाकर चुनें. इससे उसे आपके डिवाइस पर चलने की अनुमति मिल जाएगी." "सेटिंग में चालू करें" - %s पर स्विच करें\" - "इसके बाद, \"%s\" को अपने सक्रिय पाठ-इनपुट के तरीके के तौर पर चुनें." + %s पर स्विच करें\" + "इसके बाद, \"%s\" को अपने सक्रिय पाठ-इनपुट के तरीके के तौर पर चुनें." "इनपुट पद्धतियां स्विच करें" "बधाई हो, आप बिल्कुल तैयार हैं!" - "अब आप %s के साथ अपने सभी पसंदीदा ऐप्स में लिख सकते हैं." + "अब आप %s के साथ अपने सभी पसंदीदा ऐप्स में लिख सकते हैं." "खत्म" "ऐप्लिकेशन का आइकॉन दिखाएं" "लॉन्चर में ऐप आइकॉन दिखाएं" - "अन्य शब्दकोष" + "अन्य शब्दकोष" "शब्दकोश उपलब्‍ध" - "डिक्‍शनरी अनुपलब्‍ध" "आख़री बार अपडेट किया गया" "सेटिंग" "मिटाएं" - "वर्शन %1$s" - "जोड़ें" + "वर्शन %1$s" "शब्दकोश में जोड़ें" "शॉर्टकट:" "भाषा:" "कोई शब्द लिखें" "वैकल्पिक शॉर्टकट" "शब्द बदलें" - "आपके पास उपयोगकर्ता डिक्शनरी में कोई भी शब्द नहीं है. कोई शब्द जोड़ने के लिए, जोड़ें (+) बटन छूएं." "सभी भाषाओं के लिए" "ज़्यादा भाषाएं…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" diff --git a/app/src/main/res/values-hr/strings.xml b/app/src/main/res/values-hr/strings.xml index a65b72f7a..2c40c47d5 100644 --- a/app/src/main/res/values-hr/strings.xml +++ b/app/src/main/res/values-hr/strings.xml @@ -16,7 +16,7 @@ "Omogući razdvojenu tipkovnicu" "Prebaci na druge unose" "Tipka za izmjenjivanje jezika" - "%s ms" + "%s ms" "Zadano sustavom" "Koristi imena iz Kontakata za prijedloge i ispravke" "Prilagođeni prijedlozi" @@ -49,20 +49,9 @@ Španjolski (SAD) "Hinglish" "Srpski (latinica)" - Engleski (UK) (%s) - Engleski (US) (%s) - Španjolski (US) (%s) - Hinglish (%s) - Srpski (%s) - %s (traditionalno) - %s (kompaktno) - Neodređen jezik (abeceda) - Abeceda (QWERTY) - Abeceda (QWERTZ) - Abeceda (AZERTY) - Abeceda (Dvorak) - Abeceda (Colemak) - Abeceda (PC) + %s (traditionalno) + %s (kompaktno) + Neodređen jezik "Emoji" "Dodaj" "Ukloni" @@ -75,53 +64,46 @@ "Emoji za fizičku tipkovnicu" "Fizička tipka Alt prikazuje paletu emojija" "Zadano" - Dobro došli u %s + Dobro došli u %s "s Pisanjem kretnjama" "Počnite s radom" - "Sljedeći korak" - Postavljanje aplikacije %s - Aktiviraj %s - Označi „%s” u postavkama jezika i unosa. Time se omogućuje izvođenje aplikacije na uređaju. - Aplikacija %s je već aktivirana u postavkama jezika i unosa, stoga je taj korak gotov. Nastavi sa sljedećim korakom! + Postavljanje aplikacije %s + Aktiviraj %s + Označi „%s” u postavkama jezika i unosa. Time se omogućuje izvođenje aplikacije na uređaju. Aktiviraj u postavkama - Prijeđi na %s - Zatim odaberi „%s” kao aktivan način unosa teksta. + Prijeđi na %s + Zatim odaberi „%s” kao aktivan način unosa teksta. Prijeđi na drugi način unosa Čestitamo, sve je spremno! - Sada možeš pisati u svim svojim omiljenim aplikacijama pomoću aplikacije %s. + Sada možeš pisati u svim svojim omiljenim aplikacijama pomoću aplikacije %s. "Završeno" "Prikaži ikonu aplikacije" "Prikazivanje ikone aplikacije u pokretaču" - "Rječnici kao dodaci" + "Rječnici kao dodaci" "Dostupan je rječnik" - "Rječnici nedostupni" "Zadnje ažuriranje" "Postavke" "Izbriši" - Verzija %1$s - "Dodavanje" + Verzija %1$s "Dodaj u rječnik" "Prečac:" "Jezik:" "Upišite riječ" "Neobavezni prečac" "Uređivanje riječi" - "Nemate nijednu riječ u korisničkom rječniku. Da biste dodali riječ, dodirnite gumb Dodaj (+)." "Za sve jezike" "Više jezika…" " ABCČĆDDŽĐEFGHIJKLLJMNNJOPRSŠTUVZŽ" HeliBoard provjera pravopisa Postavke HeliBoard provjere pravopisa - %s (Akkhor) - Abeceda (Colemak Mod-DH) + %s (Akkhor) Prijedlozi - Abeceda (Workman) Povijest međuspremnika Razno Ispravci Eksperimentalno Tipka za emojije - %s min + %s min Bez ograničenja HeliBoard postavke Unos diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index e2aa6ff7a..71e01e9c8 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -16,7 +16,7 @@ Kétoldali billentyűzet bekapcsolása "Váltás más beviteli módra" Nyelvkapcsoló gomb - "%s ms" + "%s ms" Rendszer alapértelmezett Névjegyek használata javaslatokhoz és javításokhoz "Testreszabott javaslatok" @@ -49,20 +49,9 @@ Spanyol (amerikai) "Hinglish (hindi-angol)" "Szerb (latin)" - Angol (brit) (%s) - Angol (amerikai) (%s) - Spanyol (amerikai) (%s) - "Hinglish (hindi-angol, %s)" - Szerb (%s) - %s (Hagyományos) - %s (Kompakt) - "Nincs nyelv (ábécé)" - "Ábécé (QWERTY)" - "Ábécé (QWERTZ)" - "Ábécé (AZERTY)" - "Ábécé (Dvorak)" - "Ábécé (Colemak)" - "Ábécé (PC)" + %s (Hagyományos) + %s (Kompakt) + "Nincs nyelv" "Hangulatjel" "Hozzáadás" "Eltávolítás" @@ -75,38 +64,33 @@ Hangulatjelek a fizikai billentyűhöz Fizikai Alt gomb megjeleníti a hangulatjel palettát "Alapértelmezett" - Üdvözöljük a %s + Üdvözöljük a %s gesztusokkal történő bevitellel "Első lépések" - "Következő lépés" - Beállítani a %s-t - %s engedélyezése - Ellenőrizze a \"%s\" saját nyelvén a beviteli beállításokban. Ezzel engedélyezheti, hogy fusson a készülékén. - %s már engedélyezve van a nyelve beviteli beállításainál, így ez a lépés nem szükséges. Lépjen a következőre! + Beállítani a %s-t + %s engedélyezése + Ellenőrizze a \"%s\" saját nyelvén a beviteli beállításokban. Ezzel engedélyezheti, hogy fusson a készülékén. Engedélyezés a Beállításokban - Váltás a %s - Válassza ki a \"%s\" mint aktív szövegbeviteli eszközét. + Váltás a %s + Válassza ki a \"%s\" mint aktív szövegbeviteli eszközét. "Váltás a beviteli módok között" Gratulálunk, minden beállításra került! - Immáron a kedvenc applikációjában gépelhet a %s. + Immáron a kedvenc applikációjában gépelhet a %s. "Befejeződött" "Alkalmazásikon megjelenítése" "Alkalmazásikon megjelenítése az indítóban" - Bővítmény szótárak + Bővítmény szótárak "Van rendelkezésre álló szótár" - Nem elérhető szótár "Legutóbb frissítve" "Beállítások" "Törlés" - Verzió %1$s - "Hozzáadás" + Verzió %1$s "Hozzáadás a szótárhoz" "Gyorsparancs:" "Nyelv:" "Írjon be egy szót" "Választható gyorsparancs" "Szó szerkesztése" - Nincsenek szavak a felhasználói szótárban. Új szavakat a Hozzáadás (+) gombra nyomva vehet fel. Minden nyelvhez "További nyelvek…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" @@ -127,11 +111,9 @@ Billentyűzet magassági skála Mindig mutassa a számsort Kulcsfontosságú tippek megjelenítése - Ábécé (Colemak Mod-DH) Hosszan-lenyomott tippek megjelenítése A szóköz billentyű hosszan történő megnyomásával a beviteli módszer kiválasztási menüje jelenik meg Beviteli mód megváltoztatása a szóközzel - Ábécé (Munkás) Automatikus nappali/éjszakai üzemmód HeliBoard helyesírás-ellenőrző Csúsztató törlése @@ -162,7 +144,7 @@ Bizalom az automata javításban Más appok javaslat tiltó kérelmét figyelmen kívül hagyja (hibákhoz vezethet) Nyelv váltás - %s perc + %s perc Vigyázat: Ezen beállítás kikapcsolása törli az eddigi tanult adatokat Használja az eszköz saját szótárát a megtanult szavak tárolására Mentés vagy visszatöltés fájlból. Figyelem: a visszaállítás felülírja a jelenlegi adatot @@ -243,15 +225,13 @@ Visszavon Helyrehoz Funkcionális gombok mutatása - Kaitag (%s) - %s (Akkhor) - %s (Sebeolsik 390) - %s (Sebeolsik Végleges) + %s (Akkhor) + %s (Sebeolsik 390) + %s (Sebeolsik Végleges) Válasszon ki egy kompatibilis formájú fájlt. A formátumokról a következő helyen érhető el információ: %s. Fájl betöltése Fájl nem olvasható Már létező elrendezés másolása - Elrendezés név beállítása Törölni kívánja a %s egyéni elrendezést? Elrendezés hiba: %s Több szimbólum @@ -260,7 +240,6 @@ Numerikus Numerikus (táj) Háttérkép beállítása - Ábécé (Bépo) Legyen külön kép nappali és éjjeli módban? Nappal Éjjel @@ -306,7 +285,6 @@ Szín automatikus kiválasztása Csak fő színek mutatása Minden szín mutatása - Nyomjon rá az előnézethez Billentyűzet háttér Gomb szöveg Gomb tipp szöveg diff --git a/app/src/main/res/values-hy/strings.xml b/app/src/main/res/values-hy/strings.xml index 417434a3d..c18fcff9a 100644 --- a/app/src/main/res/values-hy/strings.xml +++ b/app/src/main/res/values-hy/strings.xml @@ -16,7 +16,7 @@ "Միացնել բաժանված ստեղնաշարը" "Անցնել մուտքագրման այլ եղանակների" "Լեզվի փոխարկման ստեղն" - "%sմվ" + "%sմվ" "Համակարգի լռելյայնները" "Օգտագործել կոնտակտների անունները՝ առաջարկների և ուղղումների համար" "Անհատականացված հուշումներ" @@ -49,20 +49,9 @@ "Իսպաներեն (ԱՄՆ)" "Հինգլիշ" "Սերբերեն (Լատինական)" - "Անգլերեն (ՄԹ) (%s)" - "Անգլերեն (ԱՄՆ) (%s)" - "Իսպաներեն (ԱՄՆ) (%s)" - "Հինգլիշ (%s)" - "Սերբերեն (%s)" - "%s (ավանդական)" - "%s (սեղմ)" - "Ոչ մի լեզվով (Այբուբեն)" - "Այբուբեն (QWERTY)" - "Այբուբեն (QWERTZ)" - "Այբուբեն (AZERTY)" - "Այբուբեն (Dvorak)" - "Այբուբեն (Colemak)" - "Այբուբեն (PC)" + "%s (ավանդական)" + "%s (սեղմ)" + "Ոչ մի լեզվով" "Զմայլիկներ" "Ավելացնել" "Հեռացնել" @@ -75,38 +64,33 @@ "Ֆիզիկական ստեղնաշարի զմայլիկ" "Alt ստեղնը ցուցադրում է զմայլիկների պնակը" "Լռելյայնը" - "Բարի գալուստ %s" + "Բարի գալուստ %s" "Ժեստային մուտքագրմամբ" "Սկսել" - "Հաջորդ քայլը" - "Տեղադրվում է %s-ը" - "Միացնել %s-ը" - Նշեք %s» հավելվածը Լեզուների և մուտքագրման կարգավորումներում՝ ձեր սարքում դրա աշխատանքը թույլ տալու համար:\" - "%s-ն արդեն միացված է ձեր Լեզուների և մուտքագրման կարգավորումներում, այնպես որ այս քայլն արդեն կատարված է:Անցեք հաջորդին:" + "Տեղադրվում է %s-ը" + "Միացնել %s-ը" + Նշեք %s» հավելվածը Լեզուների և մուտքագրման կարգավորումներում՝ ձեր սարքում դրա աշխատանքը թույլ տալու համար:\" "Միացնել կարգավորումներից" - "Փոխարկել %s-ին" - Հաջորդիվ, ընտրեք %s»-ը որպես ձեր ակտիվ տեքստային մուտքագրման եղանակ:\" + "Փոխարկել %s-ին" + Հաջորդիվ, ընտրեք %s»-ը որպես ձեր ակտիվ տեքստային մուտքագրման եղանակ:\" "Փոխարկել մուտքագրման եղանակները" "Շնորհավորում ենք, դուք տեղադրեցիք բոլորը:" - "Այժմ դուք կարող եք մուտքագրել ձեր բոլոր սիրելի հավելվածներում %s-ով:" + "Այժմ դուք կարող եք մուտքագրել ձեր բոլոր սիրելի հավելվածներում %s-ով:" "Ավարտված" "Ցույց տալ հավելվածի պատկերակը" "Ցուցադրել հավելվածի պատկերակը գործարկիչում" - "Հավելյալ բառարաններ" + "Հավելյալ բառարաններ" "Բառարանն առկա է" - "Բառարաններ չկան" "Վերջին անգամ թարմացվել է" "Կարգավորումներ" "Ջնջել" - "Տարբերակ %1$s" - "Ավելացնել" + "Տարբերակ %1$s" "Ավելացնել բառարանում" "Դյուրանցումը՝" "Lեզուն՝" "Մուտքագրեք բառը" "Ընտրովի դյուրանցում" "Խմբագրել բառը" - "Օգտատիրոջ բառարանում ոչ մի բառ չկա: Բառեր ավելացնելու համար հպեք Ավելացնել (+) կոճակին:" "Բոլոր լեզուներով" "Ավելի շատ լեզուներով…" " ԱԲԳԴԵԶԷԸԹԺԻԼԽԾԿՀՁՂՃՄՅՆՇՈՉՊՋՌՍՎՏՐՑՈՒՓՔԵւՕՖ" @@ -124,4 +108,4 @@ "Որոնում" "Դադարեցնել" "Սպասել" - \ No newline at end of file + diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml index bc5756263..0007f9950 100644 --- a/app/src/main/res/values-in/strings.xml +++ b/app/src/main/res/values-in/strings.xml @@ -5,7 +5,7 @@ SPDX-License-Identifier: Apache-2.0 AND GPL-3.0-only --> "Cari nama kontak" - "Getar jika tombol ditekan" + Bergetar saat tombol ditekan "Berbunyi jika tombol ditekan" "Muncul saat tombol ditekan" "Preferensi" @@ -16,8 +16,8 @@ "Aktifkan keyboard terpisah" "Beralih ke metode masukan lain" "Tombol pengalih bahasa" - "%s md" - "Default sistem" + %s md + Sistem bawaan "Menggunakan nama dari Kontak untuk saran dan koreksi" "Saran hasil personalisasi" "Titik spasi ganda" @@ -49,20 +49,9 @@ "Spanyol (AS)" "Hinglish" "Serbia (Latin)" - Inggris (UK) (%s) - Inggris (US) (%s) - Spanyol (US) (%s) - Hinglish (%s) - Serbia (%s) - %s (Tradisional) - %s (Ringkas) - "Tidak ada bahasa (Abjad)" - "Abjad (QWERTY)" - "Abjad (QWERTZ)" - "Abjad (AZERTY)" - "Abjad (Dvorak)" - "Abjad (Colemak)" - "Abjad (PC)" + %s (Tradisional) + %s (Ringkas) + "Tidak ada bahasa" "Emoji" "Tambahkan" "Hapus" @@ -75,38 +64,33 @@ "Emoji untuk keyboard fisik" "Tombol Alt fisik menampilkan palet emoji" "Default" - Selamat datang di %s + Selamat datang di %s "dengan Ketikan Gestur" "Memulai" - "Langkah berikutnya" - Menyiapkan<xliff:g id=\"NAMA_APLIKASI\" contoh=\"Papan Ketik Android\">%s<xliff:g> - Aktifkan<xliff:g id=\"NAMA_APLIKASI\" contoh=\"Papan Ketik Android\">%s<xliff:g> - Harap periksa \\<xliff:g id=\"NAMA_APLIKASI\" contoh=\"Papan Ketik Android\">%s<xliff:g>\" di setelan Bahasa &amp; masukan Anda. Ini akan mengizinkannya untuk berjalan di perangkat Anda.\" - <xliff:g id=\"NAMA_APLIKASI\" contoh=\"Papan Ketik Android\">%s<xliff:g> sudah diaktifkan di pengaturan Bahasa &amp; masukan Anda, jadi langkah ini sudah selesai. Lanjut ke langkah berikutnya!\" + Menyiapkan %s + Aktifkan %s + Harap periksa \"%s\" di setelan Bahasa masukan Anda. Ini akan mengizinkannya untuk berjalan di perangkat Anda. "Aktifkan dalam Setelan" - Switch to%s - Next, select \\%s\" as your active text-input method.\" + Beralih ke %s + Selanjutnya, pilih \"%s\" sebagai metode input teks aktif Anda. "Alihkan metode masukan" "Selamat, Anda sudah siap!" - Sekarang Anda bisa mengetik di semua aplikasi favorit Anda dengan %s. + Sekarang Anda bisa mengetik di semua aplikasi favorit Anda dengan %s. "Selesai" "Tampilkan ikon aplikasi" "Menampillkan ikon aplikasi di peluncur" - "Kamus pengaya" + "Kamus pengaya" "Kamus yang tersedia" - "Tidak tersedia kamus" "Terakhir diperbarui" "Setelan" "Hapus" - Versi %1$s - "Tambahkan" + Versi %1$s "Tambahkan ke kamus" "Pintasan:" "Bahasa:" "Ketik kata" "Pintasan opsional" "Edit kata" - Belum ada kata di dalam kamus pengguna Anda. Untuk menambahkan kata, ketuk tombol Tambahkan (+). "Untuk semua bahasa" "Bahasa lainnya…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" @@ -114,13 +98,12 @@ Gestur hapus Sentuh dan geser ke kiri pada tombol hapus untuk menghapus beberapa huruf/kata sekaligus Riwayat papan klip - Tidak terbatas + Tidak ada batas Aktifkan riwayat papan klip Waktu simpan riwayat Tampilkan petunjuk tombol Selalu tampilkan baris angka - %smnt - Alfabet (Workman) + %s mnt Pemeriksa Ejaan HeliBoard Pengaturan Pemeriksa Ejaan HeliBoard Baris angka @@ -131,19 +114,18 @@ Masukan Tombol tambahan Saran - Eksperimental + Percobaan Lainnya Koreksi Tombol lainnya Nonaktifkan pembelajaran kata baru Menekan lama pada tombol spasi akan menampilkan menu pemilihan metode masukan Tampilkan petunjuk tekan-lama - Alfabet (Colemak Mod-DH) Batas tombol Mode siang/malam otomatis Tampilan mengikuti pengaturan sistem Jika dinonaktifkan, menekan tombol ikon papan klip akan menempelkan konten yang disalin (jika ada) - %s (Akkhor) + %s (Akkhor) Spasi otomatis setelah tanda baca Otomatis sisipkan spasi setelah tanda baca saat mengetik kata baru Tingkat ketepercayaan koreksi otomatis @@ -169,7 +151,7 @@ Kesalahan saat menyimpan data cadangan: %s Gagal memuat data cadangan: %s Cadangkan - Kembalikan + Pulihkan Bawah Pengetikan multibahasa Muat pustaka pengetikan gestur @@ -204,28 +186,26 @@ Tampilkan petunjuk jika menekan suatu tombol dengan lama memicu fungsi tambahan Sempitkan jarak antara tombol Skala bantalan bawah - %s (Sebeolsik Final) + %s (Sebeolsik Final) Muat file File tidak terbaca Salin tata letak saat ini - Ubah nama tata letak Yakin ingin menghapus tata letak kustom %s? Kesalahan tata letak: %s Tekan untuk mengubah tata letak versi polos Peringatan: Menonaktifkan pengaturan ini akan menghapus data yang telah diperoleh Selalu tampilkan saran - Simpan data cadangan dan kembalikan + Pencadangan dan pemulihan Mode satu tangan - %s (Sebeolsik 390) + %s (Sebeolsik 390) Tambahkan tata letak kustom - Pisahkan jarak + Jarak pisah Abaikan permintaan aplikasi lain untuk menonaktifkan saran (dapat menimbulkan masalah) Anda membutuhkan pustaka untuk \'%s\'. Pustaka yang tidak cocok mungkin bisa mengeluarkan Anda dari aplikasi secara tiba-tiba saat menggunakan pengetikan gestur. \n \nPeringatan: memuat kode eksternal dapat menimbulkan resiko keamanan. Gunakan pustaka yang hanya Anda percaya. Mencoba untuk mendeteksi URL dan sejenisnya sebagai kata tunggal Tampilkan petunjuk fungsional - Alfabet (Bépo) Pilih file dalam format yang kompatibel. Informasi tentang format tersedia %s. Ganti Bahasa Pilih sumber petunjuk @@ -236,11 +216,11 @@ Simbol telepon Angka Papan nomor - Papan nomor (mode bentang) + Papan nomor (lanskap) Ubah gambar latar belakang Ubah gambar untuk mode cerah atau malam? Malam - Cerah + Siang Kamus Kamus utama internal Tambahkan kamus dari file @@ -294,7 +274,6 @@ Pilih warna secara otomatis Tampilkan warna utama saja Tampilkan semua warna - Klik untuk melihat pratinjau Pilih warna untuk teks dan latar belakang Latar belakang papan ketik Tombol teks @@ -323,13 +302,11 @@ Ungu lembayung Lisensi Publik Umum GPU v3.0 Kaitag - Kaitag (%s) - Tutup riwayat clipboard + Tutup riwayat papan klip Emoji Potong - %s (Probhat) + %s (Probhat) Mansi - Mansi (%s) Tampilkan lebih banyak warna Pendinginan pengetikan cepat Selalu mulai secara instan @@ -342,15 +319,15 @@ Sesuaikan mata uang Konten disalin Bilah alat pertunjukan otomatis - %s (Student) + %s (Student) Tombol fungsi (Lebih banyak simbol) Selalu gunakan saran pertengahan Saat menekan spasi atau tanda baca, saran tengah akan dimasukkan Emoji baris bawah - Baris bawah clipboard + Baris bawah papan klip Tetapkan simbol mata uang utama dan hingga 6 simbol mata uang sekunder, dipisahkan dengan spasi Arah bilah alat variabel - <xliff:g id=\"NAMA_BAHASA\" contoh=\"Bahasa Kannada\">%s<xliff:g> (Diperluas) + %s (Diperluas) Memuat Simpan ke file Tampilkan bilah alat jika input dimulai atau teks dipilih @@ -358,30 +335,28 @@ Bergetar dalam mode jangan ganggu Akhir halaman Kata tersisa - Pilih tombol bilah alat clipboard + Pilih tombol bilah alat papan klip Sematkan tombol bilah alat saat ditekan lama Ini akan menonaktifkan tindakan tekan lama lainnya untuk tombol bilah alat yang tidak disematkan - Tekan lama tombol simbol untuk numpad - <xliff:g id=\"NAMA_BAHASA\" contoh=\"Bahasa Hindi\">%s<xliff:g> (Fonetik) + Tekan lama tombol simbol untuk papan nomor + %s (Fonetik) Ganti versi Emoji Kode tekan lama - Dargwa(Urakhi) - Urakhi (<xliff:g id=\"LAYOUT_KEYBOARD\" contoh=\"QWERTY\">%s<xliff:g>) + Dargwa (Urakhi) Kode kunci Kunci huruf kapital - Space (tata letak angka) + Spasi (tata letak angka) Akhiri mode satu tangan Ubah ukuran mode satu tangan - Alihkan Numpad + Alihkan Papan nomor Pintasan koreksi otomatis Saat diaktifkan, pintasan mungkin diperluas dengan koreksi otomatis Halaman bawah Pilih tombol bilah alat yang disematkan Halaman atas Kata yang tepat - Memuat akan menimpa tema saat ini Atur font khusus dari file - Salin ke clipboard + Salin ke papan klip Mengatur gambar latar belakang (lanskap) Jika tidak diatur, gambar potret akan digunakan Penggabung lebar nol @@ -393,7 +368,7 @@ Menekan enter atau spasi setelah tombol lain dalam tampilan simbol Beralih ke keyboard utama setelah… Memilih emoji dalam tampilan emoji - Memilih entri riwayat clipboard + Memilih entri riwayat papan klip Tambahkan varian yang sangat umum (default) Tekan tombol popup yang sudah ada pada tata letak dasar Bilah Alat @@ -401,7 +376,7 @@ Benarkah harus mereset semua ikon yang disesuaikan? Perilaku tombol alih bahasa Sarankan konten papan klip - Tampilkan konten clipboard yang baru saja disalin sebagai saran + Tampilkan konten papan klip yang baru saja disalin sebagai saran Benarkah semua kode kunci yang disesuaikan terhapus? ► Menekan lama tombol bilah alat yang disematkan menghasilkan fungsi tambahan: <br> \n• clipboard &#65515; tempel <br> \n• pindahkan ke kiri dan kanan &#65515; kata ke kiri dan kanan <br> \n• pindahkan ke atas dan bawah &#65515; halaman ke atas dan bawah <br> \n• kata ke kiri dan kanan &#65515; awal baris <br> \n• halaman ke atas dan bawah &#65515; awal halaman <br> \n• salin &#65515; potong <br> \n• pilih kata &#8596; pilih semua <br> \n• batalkan &#8596; ulangi <br> <br> \n► Menekan lama tombol pada bilah alat strip saran akan menyematkannya ke strip saran. <br> <br> \n► Tekan lama tombol Koma untuk mengakses Tampilan Clipboard, Tampilan Emoji, Mode Satu Tangan, Pengaturan, atau Ganti Bahasa: <br> \n• Tampilan Emoji dan Ganti Bahasa akan menghilang jika Anda mengaktifkan tombol terkait; <br> \n• Untuk beberapa tata letak, yang aktif bukanlah tombol Koma, tetapi tombol pada posisi yang sama (misalnya, \'q\' untuk tata letak Dvorak). <br> <br> \n► Saat mode penyamaran diaktifkan, tidak ada kata yang akan dipelajari, dan tidak ada emoji yang akan ditambahkan ke yang terbaru. <br> <br> \n► Tekan ikon Penyamaran untuk mengakses bilah alat. <br> <br> \n► Input tombol geser: Geser dari shift ke tombol lain untuk mengetik satu tombol huruf kapital: <br> \n• Ini juga berfungsi untuk tombol \'?123\' untuk mengetik satu simbol dari papan ketik simbol, dan untuk tombol terkait. <br> <br> \n► Tahan tombol shift atau simbol, tekan satu atau beberapa tombol, lalu lepaskan tombol shift atau simbol untuk kembali ke papan ketik sebelumnya. <br> <br> \n► Tekan lama saran di strip saran untuk menampilkan lebih banyak saran, dan tombol hapus untuk menghapus saran ini. <br> <br> \n► Geser ke atas dari saran untuk membuka lebih banyak saran, dan lepaskan pada saran untuk memilihnya. <br> <br> \n► Tekan lama entri dalam riwayat clipboard untuk menyematkannya (simpan di clipboard hingga Anda melepas sematannya). <br> <br> \n► Geser ke kiri dalam tampilan clipboard untuk menghapus entri (kecuali saat disematkan) <br> <br> \n► Pilih teks dan tekan shift untuk beralih antara kata-kata huruf besar, huruf kecil, dan huruf kapital. <br> <br> \n► Anda dapat menambahkan kamus dengan membukanya di file explorer: <br> \n• Ini hanya berfungsi dengan <i>content-uris<i> dan tidak dengan <i>file-uris<i>, yang berarti mungkin tidak berfungsi dengan beberapa file explorer. <br> <br> \n► Untuk pengguna yang melakukan pencadangan manual dengan akses root: <br> \n• Dimulai pada Android 7, file preferensi bersama tidak berada di lokasi default, karena aplikasi menggunakan %s. Ini diperlukan agar pengaturan dapat dibaca sebelum perangkat dibuka kuncinya, misalnya saat boot; <br> \n• File terletak di datauser_de0package_idshared_prefs meskipun ini mungkin bergantung pada perangkat dan versi Android. <br> <br> \n<i><b>Debug mode debug APK<b><i> <br> <br> \n► Tekan lama saran untuk menampilkan kamus sumber. <br> <br> \n► Saat menggunakan APK debug, Anda dapat menemukan Setelan Debug di Preferensi Lanjutan, meskipun kegunaannya terbatas kecuali untuk membuang kamus ke dalam log. <br> \n• Untuk APK rilis, Anda perlu mengetuk versi di <i>Tentang<i> beberapa kali, lalu Anda dapat menemukan setelan debug di <i>Preferensi Lanjutan<i>. <br> \n• Saat mengaktifkan <i>Tampilkan info saran<i>, saran akan memiliki beberapa angka kecil di atas yang menunjukkan beberapa skor internal dan kamus sumber. <br> <br> \n► Jika terjadi kerusakan aplikasi, Anda akan diminta apakah Anda menginginkan log kerusakan saat membuka Setelan. <br> <br> \n► Saat menggunakan pengetikan multibahasa, bilah spasi akan menunjukkan nilai keyakinan yang digunakan untuk menentukan bahasa yang saat ini digunakan. <br> <br> \n► Saran akan memiliki beberapa angka kecil di bagian atas yang menunjukkan beberapa skor internal dan kamus sumber (dapat dinonaktifkan). Pengaturan ini menampilkan semua warna yang digunakan secara internal. Daftar warna dapat berubah sewaktu-waktu. Warna default bersifat acak, dan nama-namanya tidak akan diterjemahkan. @@ -423,10 +398,10 @@ Bagian Diskusi PERINGATAN: Tata letak sedang digunakan saat ini Kunci fungsional (layar besar) - %s (Baishakhi) + %s (Baishakhi) Anda dapat menemukan dan berbagi tata letak di %s. - Aktifkan keyboard split (lansekap) - Jarak split (lanskap) + Aktifkan keyboard terpisah (lanskap) + Jarak pisah (lanskap) Benaran mau dihapus %s? Nama invalid Skala padding bawah (lanskap) @@ -439,4 +414,26 @@ Bahasa dengan kamus Keyboard terpisah Anda dapat menemukan dan berbagi warna di %s. + Baris nomor (dasar) + Bidang edit web (kebanyakan ditemukan di browser) adalah penyebab yang sangat umum untuk masalah dengan pengaturan saran yang selalu ditampilkan + Jangan selalu menampilkan saran untuk bidang edit web + Spasi + Tidak ada spasi otomatis saat menekan shift + Shift menghapus spasi otomatis yang tertunda + Format kunci stempel waktu + Spasi otomatis sebelum mengetik kata dengan isyarat + Spasi otomatis setelah mengetik kata dengan isyarat + Menampilkan tombol popup TLD + Ganti popup tombol titik dengan domain tingkat atas saat mengetik URL dan alamat email + Menekan enter atau spasi setelah tombol lain di papan nomor + Dagbani + Sesotho + Menskala ukuran tombol emoji dengan ukuran font + Spasi otomatis setelah memilih saran + Cadangan dipulihkan + Cari nama aplikasi + Gunakan nama aplikasi yang terinstal untuk saran dan koreksi + Backspace mengembalikan koreksi otomatis + Warna kulit emoji bawaan + Netral diff --git a/app/src/main/res/values-is/strings.xml b/app/src/main/res/values-is/strings.xml index 6ab84a443..cf987ff2a 100644 --- a/app/src/main/res/values-is/strings.xml +++ b/app/src/main/res/values-is/strings.xml @@ -16,7 +16,7 @@ "Virkja skipt lyklaborð" "Skipta um innsláttaraðferð" "Lykill til að breyta tungumáli" - %s msek + %s msek Sjálfgefið í kerfi "Nota nöfn úr tengiliðum fyrir tillögur og leiðréttingar" "Persónulegar tillögur" @@ -49,20 +49,9 @@ "Spænskt (US)" "Hinglish" "Serbneskt (latneskt)" - "Enskt (Bretland) (%s)" - "Enskt (Bandaríkin) (%s)" - "Spænskt (Bandaríkin) (%s)" - "Hinglish (%s)" - "Serbneskt (%s)" - "%s (hefðbundið)" - "%s (lítið)" - "Ekkert tungumál (stafróf)" - "Stafróf (QWERTY)" - "Stafróf (QWERTZ)" - "Stafróf (AZERTY)" - "Stafróf (Dvorak)" - "Stafróf (Colemak)" - "Stafróf (tölva)" + "%s (hefðbundið)" + "%s (lítið)" + "Ekkert tungumál" Tjáningartákn "Bæta við" "Fjarlægja" @@ -75,38 +64,33 @@ Tjáningartákn fyrir vélbúnaðarlyklaborð Alt-lykillinn á lyklaborðinu birtir töflu yfir tjáningartákn "Sjálfgefið" - "Velkomin(n) í %s" + "Velkomin(n) í %s" "með bendingainnslætti" "Hefjast handa" - "Næsta skref" - "Uppsetning %s" - "Virkjaðu %s" - Merktu við %s“ í stillingum tungumálsins þíns og innsláttar. Þetta veitir því heimild til að keyra í tækinu.\" - "%s er þegar virkt í stillingum tungumáls og innsláttar og lokið hefur verið við þetta skref. Vindum okkur í næsta!" + "Uppsetning %s" + "Virkjaðu %s" + Merktu við %s“ í stillingum tungumálsins þíns og innsláttar. Þetta veitir því heimild til að keyra í tækinu.\" "Virkja í stillingum" - "Skiptu yfir í %s" - Næst skaltu velja %s“ sem virka innsláttaraðferð fyrir texta.\" + "Skiptu yfir í %s" + Næst skaltu velja %s“ sem virka innsláttaraðferð fyrir texta.\" "Skipta um innsláttaraðferð" "Til hamingju, allt er klárt!" - Nú geturðu notað%s til að skrifa í öllum uppáhaldsforritunum þínum. + Nú geturðu notað%s til að skrifa í öllum uppáhaldsforritunum þínum. "Lokið" "Sýna forritstákn" "Sýna forritstákn í ræsiforritinu" - Viðbótarorðasöfn + Viðbótarorðasöfn Orðasafn í boði - Engin orðasöfn eru í boði "Síðast uppfært" "Stillingar" "Eyða" - "Útgáfa %1$s" - "Bæta við" + "Útgáfa %1$s" Bæta við orðasafni Stytting: "Tungumál:" "Sláðu inn orð" Valfrjáls stytting "Breyta orði" - Engin orð eru í orðasafni notanda. Bættu við orðum með því að ýta á hnappinn Bæta við (+). "Fyrir öll tungumál" "Fleiri tungumál…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" @@ -132,7 +116,6 @@ Sérsníða gjaldmiðla Litir Rúnnað - Kaitag (%s) Stíll Stafsetningarleiðrétting HeliBoard Stillingar HeliBoard @@ -174,10 +157,10 @@ Síða upp Síða niður Loka klippispjaldsferli - %s (viðaukið) - %s (Akkhor) + %s (viðaukið) + %s (Akkhor) Nótt - %s (hljóðfræðitákn) + %s (hljóðfræðitákn) Hlaða Vista í skrá Afrita á klippispjald @@ -188,7 +171,6 @@ Tungumál og framsetning Alltaf sýna talnaröð Talnaröð - Urakhi (%s) Afrita fyrirliggjandi framsetningu Tungumál (forgangs) Klippispjald @@ -198,9 +180,9 @@ Get ekki lesið skrá Hlaða inn skrá Kaitag - %s (Sebeolsik 390) - %s (Probhat) - %s (Sebeolsik Final) + %s (Sebeolsik 390) + %s (Probhat) + %s (Sebeolsik Final) Setja bakgrunnsmynd (lárétt) Stilla lyklaborðið %s (á tilraunastigi) @@ -221,7 +203,6 @@ Upphaf síðu Endir síðu Færa bendil - Mansi (%s) Ekki birta þetta aftur Lykilkóði Stroka til að eyða @@ -229,7 +210,7 @@ Sérsniðinn texti á bilslá Birta verkfærastiku sjálfvirkt Jaðrar lykla - %s mín + %s mín Hegðun lykils til að breyta tungumáli Engin takmörk Dekkra @@ -252,7 +233,6 @@ Titra í \'Ekki ónáða\'-ham Lengd skiptingar Alltaf birta tillögur - Stilla heiti framsetningar Virkilega eyða sérsniðnu framsetningunni %s? Bæta við sérsniðinni framsetningu Fleiri sjálfvirkar leiðréttingar @@ -294,7 +274,6 @@ Sjálfvirkur dags-/næturhamur Viltu í alvörunni hreinsa alla sérsniðna lyklakóða? Velja lit sjálfvirkt - Smelltu til að forskoða Sýna fleiri liti Sýna alla liti Færsla / Enter @@ -325,12 +304,9 @@ Sérsníða lyklakóða verkfærastiku Fela verkfærastiku sjálfvirkt Tími sem á að geyma breytingaferil - %s (námsmanna) - Stafróf (Workman) - Stafróf (Colemak Mod-DH) + %s (námsmanna) Sjálfvirkt bil á eftir greinamerkjum Velja sérsniðið letur úr skrá - Stafróf (Bépo) Veldu uppruna ábendinga Veldu lykla á verkfærastiku Veldu klippispjaldslykla á verkfærastiku @@ -368,7 +344,6 @@ Kvarði leturs í tjáningartáknasýn Kvarði fyllingar til hliðar Kvarði fyllingar til hliðar (lárétt) - Að hlaða inn þessu mun skrifa yfir fyrirliggjandi þema Lýsing á földum eiginleikum Gera óvirkt að læra ný orð Festa verkfærastikulykil við að ýta lengi diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 6710cee0c..5fc514a1a 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -16,7 +16,7 @@ Tastiera divisa Cambia tastiera Tasto \'Cambia lingua\' - "%s ms" + "%s ms" "Predefinito" Utilizza i nomi dei contatti per suggerimenti e correzioni "Suggerimenti personalizzati" @@ -49,20 +49,9 @@ Spagnolo (Stati Uniti) "Hinglish" Serbo (Latino) - Inglese (Regno Unito) (%s) - Inglese (Stati Uniti) (%s) - Spagnolo (Stati Uniti) (%s) - Hinglish (%s) - Serbo (%s) - %s (tradizionale) - %s (compatto) - "Nessuna lingua (alfabeto)" - "Alfabeto (QWERTY)" - "Alfabeto (QWERTZ)" - "Alfabeto (AZERTY)" - "Alfabeto (Dvorak)" - "Alfabeto (Colemak)" - "Alfabeto (PC)" + %s (tradizionale) + %s (compatto) + "Nessuna lingua" "Emoji" "Aggiungi" "Rimuovi" @@ -71,53 +60,46 @@ "Layout" Durata vibrazione tasti Volume del suono dei tasti - Pressione lunga per input secondario + Durata della pressione lunga dei tasti Tasto fisico per passare alle emoji Il tasto ALT di una tastiera collegata apre il pannello emoji "Predefinito" - Benvenuto in %s + Benvenuto in %s con digitazione gestuale "Inizia" - "Passaggio successivo" - Configurazione di %s - Attiva %s - Scegli %s nelle impostazioni \'Lingua e immissione\' per autorizzare l\'app. - %s è già attiva nelle impostazioni Lingua e immissione.\" + Configura %s + Attiva %s + Scegli %s nelle impostazioni \'Lingua e immissione\' per autorizzare l\'app. Attiva nelle impostazioni - Passa a %s - Infine, attiva \\%s come metodo di immissione di testo. + Passa a %s + Infine, attiva %s come metodo di immissione di testo. "Cambia metodo di immissione" Tutto pronto! - Puoi usare %s per digitare in qualsiasi app. + Puoi usare %s per digitare in qualsiasi app. Fine Mostra l\'icona dell\'app Mostra HeliBoard tra le app di Android - Dizionari + Dizionari "Dizionario disponibile" - "Nessun dizionario" "Ultimo aggiornamento" "Impostazioni" "Elimina" - Versione %1$s - "Aggiungi" + Versione %s "Aggiungi al dizionario" "Scorciatoia:" "Lingua:" "Digita una parola" - "Scorciatoia facoltativa" + Scorciatoia (opzionale) "Modifica parola" - Il dizionario utente è vuoto. Premi \'Aggiungi\' (+) per aggiungere manualmente una parola. "Per tutte le lingue" "Altre lingue…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" Altezza tastiera - Alfabeto (Colemak Mod-DH) Spazio automatico dopo la punteggiatura Altri tasti Aggiunge automaticamente uno spazio dopo ogni parola seguita da punteggiatura - Alfabeto (Workman) Cronologia appunti - %s min + %s min Nessun limite Attiva la cronologia appunti Se disattivata, il tasto \'Appunti\' incolla direttamente l\'ultimo contenuto @@ -134,7 +116,7 @@ Suggerisce in piccolo sul tasto il carattere ottenibile con la pressione lunga Cambia metodo di immissione con la barra spaziatrice Premendo a lungo la barra spaziatrice si attiva il menu di selezione del metodo di immissione - %s (Akkhor) + %s (Akkhor) Il tema seguirà le impostazioni di sistema Tasti aggiuntivi Correzioni @@ -177,7 +159,7 @@ \n \nAttenzione: il caricamento di codice esterno può essere un rischio per la sicurezza. Utilizzare solo librerie di provenienza affidabile. Elimina libreria - Lingua + @string/subtype_locale Cursore a destra Mostra i numeri in uso nella lingua attiva anziché quelli latini File di libreria sconosciuto. Verifica di averlo ottenuto da una fonte affidabile e che sia per \'%s\'. @@ -186,7 +168,7 @@ Appunti Riga dei numeri Ripristino - Ordine / priorità dei tasti popup + Ordine e priorità dei tasti popup Fonti degli indicatori Carica il file della libreria nativa per la digitazione gestuale Cerca di rilevare URL e simili come una singola parola @@ -209,7 +191,6 @@ Correzione automatica aggiuntiva Distanza tra le due parti Ignora la richiesta di altre applicazioni di disabilitare i suggerimenti (potrebbe causare problemi) - Nome del layout Cambia lingua Svuota gli appunti Riduci lo spazio tra i tasti @@ -225,11 +206,10 @@ Layout Correzione automatica anche quando non è esplicitamente richiesta dal campo di input Cambia entrambi - %s (tipo tastiera Sebeolsik 390) - %s (Tipo tastiera Sebeolsik Final) + %s (tipo tastiera Sebeolsik 390) + %s (Tipo tastiera Sebeolsik Final) Chiaro Imposta un\'immagine di sfondo - Alfabeto (Bépo) Altri simboli Vuoi impostare l\'immagine per il tema chiaro o scuro? Dizionari @@ -266,7 +246,6 @@ Chiaro Aggiungi una parola Testo dei suggerimenti - Tocca per vedere l\'anteprima Personalizzato (tema chiaro) Sostituisci dizionario Sfondo della tastiera @@ -304,7 +283,7 @@ Il dizionario è stato creato per la lingua %1$s, ma lo stai aggiungendo a %2$s. Confermi? Chiudi Traccia dell\'input gestuale - Tocca la lingua per aprire le impostazioni + Tocca la lingua per impostazioni Salva log Holo bianco Dizionario interno principale @@ -317,19 +296,18 @@ Tastierino numerico (orizzontale) Tastierino numerico Simboli telefono - %s (studenti) + %s (studenti) Kaitag Scorrimento verticale sulla barra spaziatrice Nessuno Scorrimento orizzontale sulla barra spaziatrice Sposta il cursore - Kaitag (%s) - %s (Probhat) + %s (Probhat) Pressione lunga sul tasto simboli per aprire il tastierino numerico Taglia Inverte la direzione quando la tastiera è di tipo destra-sinistra Direzione della barra degli strumenti - Colore accento + Colore di risalto ► La pressione prolungata dei tasti fissati sulla barra degli strumenti attiva delle funzionalità aggiuntive: <br>\n\t• Appunti &#65515; Incolla<br> \n\t• Cursore a sinistra/destra &#65515; Parola a sinistra/destra<br> \n\t• Cursore su/giù &#65515; Pagina su/giù<br> \n\t• Parola a sinistra/destra &#65515; Inizio/fine riga<br> \n\t• Pagina su/giù &#65515; Inizio/fine documento<br> \n\t• Copia &#65515; Taglia<br> \n\t• Seleziona parola &#8596; Seleziona tutto<br> \n\t• Annulla &#8596; Ripeti<br><br> \n► La pressione prolungata dei tasti nella barra dei suggerimenti li blocca sulla barra. <br> <br>\n► Con la pressione prolungata del tasto virgola si accede alle funzionalità appunti, emoji, modalità a una mano, impostazioni e cambio lingua: <br>\n\t• Le funzionalità emoji e cambio lingua non saranno visibili se il tasto corrispondente è abilitato. <br> \n\t• Per alcuni layout non è il tasto virgola, ma quello presente nella stessa posizione (ad es. \"q\" per il layout Dvorak). <br> <br> \n► Quando è abilitata la modalità incognito, l\'apprendimento delle parole è sospeso e le emoji recenti non sono memorizzate. <br> <br>\n► In modalità incognito, si accede alla barra degli strumenti toccando l\'icona \"Incognito\". <br> <br>\n► Scorrimento da \"Maiuscolo\": lo scorrimento dal tasto \"Maiuscolo\" a una lettera permette di digitare in maiuscolo solo il carattere scelto. <br> <br>\n► È possibile tenere premuto il tasto \"Maiuscolo\" o \"Simboli\", digitare uno o più caratteri e rilasciare per tornare alla tastiera precedente. <br> <br>\n► La pressione lunga su un suggerimento mostra altri suggerimenti, più un tasto \"Elimina\" per rimuovere il suggerimento stesso. <br> <br>\n► È possibile scorrere verso l\'alto da un suggerimento per aprire altri suggerimenti e rilasciare su un suggerimento per selezionarlo. <br> <br>\n► È possibile toccare a lungo una voce della cronologia appunti per fissarla (rimane negli appunti finché non viene rilasciata nello stesso modo). <br> <br>\n► È possibile eliminare facilmente una voce della cronologia appunti trascinandola verso sinistra fuori dallo schermo (tranne quando è fissata). <br> <br>\n► Premendo il tasto \"Maiuscolo\" dopo aver selezionato un testo, è possibile renderlo tutto in maiuscolo, tutto in minuscolo oppure con le iniziali maiuscole. <br> <br>\n► È possibile aggiungere dizionari aprendoli da un qualsiasi gestore file. <br>\n\t• Supporta solo <i>content-uri</i>, non <i>file-uri</i>: potrebbe non funzionare con alcuni gestori di file.<br><br> \n► Per gli utenti che eseguono manualmente il backup con accesso root: <br>\n\t• Su Android 7 e versioni successive, il file delle preferenze non si trova nella cartella predefinita, perché l\'app usa lo %s al fine di permettere il caricamento delle impostazioni prima dello sblocco del dispositivo (per es. all\'avvio del sistema). <br>\n\t• Il file si trova invece nella cartella <i>/data/user_de/0/package_id/shared_prefs/</i> (potrebbe variare in base al dispositivo e alla versione di Android). <br><br> \n<i><b>Modalità debug / APK di debug</b></i><br><br> \n► È possibile premere a lungo un suggerimento per mostrare il dizionario di origine. <br> <br>\n► Quando si utilizza un APK di debug, è possibile trovare le impostazioni di debug nella sezione \"Avanzate\". Non sono particolarmente utili, se non per scaricare i dizionari nel log. <br>\n\t• Nella versione normale (release) dell\'app, è possibile accedervi solo dopo aver toccato più volte la versione dell\'app nella sezione \"Informazioni\". <br>\n\t• Quando si abilita \"Mostra informazioni sui suggerimenti\", sopra ai suggerimenti appariranno alcuni indicatori numerici che mostrano un determinato punteggio interno e il dizionario di origine. <br> <br>\n► In caso di arresto anomalo dell\'app, verrà chiesto se si desidera ottenere i log dell\'arresto anomalo al successivo accesso alle impostazioni. <br> <br>\n► Se è attiva la digitazione multilingue, la barra spaziatrice mostrerà il valore di affidabilità usato per determinare la lingua corrente. <br> <br>\n► Per nascondere gli indicatori numerici accanto ai suggerimenti, disabilitare \"Mostra informazioni sui suggerimenti\". Scegli i tasti permanenti (visibili anche con la barra degli strumenti nascosta) Fissa i tasti alla barra degli strumenti con una pressione lunga @@ -339,8 +317,7 @@ Nasconde la barra degli strumenti quando è possibile mostrare le parole suggerite Mostra automaticamente la barra degli strumenti Le azioni alternative su pressione lunga saranno disponibili solo sui tasti già fissati - %s (Extended) - Mansi (%s) + %s (Estesa) Tasti funzione (Simboli) Tasti funzione (Altri simboli) Barra degli strumenti @@ -352,7 +329,7 @@ Testo copiato Mansi Mostra i colori estesi - Nella lista completa, i colori sono elencati come stringhe di sistema che non possono essere rinominate o tradotte (e potrebbero essere soggette a variazioni in versioni future). I valori iniziali sono casuali. + Nella lista completa, i colori sono elencati come stringhe di sistema che non possono essere rinominate o tradotte (e potrebbero essere soggette a variazioni in versioni future). Emoji Attesa per l\'inserimento gestuale Nessuna @@ -365,7 +342,7 @@ Inizio documento Fine documento Suggerisci il testo copiato - Propone l\'ultimo testo copiato come \'pill\' nella barra dei suggerimenti + Propone l\'ultimo testo copiato nella barra dei suggerimenti Copia negli appunti Torna alla tastiera principale… Dopo l\'inserimento di un\'emoji dalla schermata emoji @@ -376,8 +353,7 @@ Pagina giù Passa al tastierino numerico Rimuovi i tasti popup ripetuti - Rimuovi i tasti popup già presenti nel layout base - Attenzione: l\'importazione sovrascriverà il tema attuale + Rimuove i tasti popup già presenti nel layout base Mostra dinamicamente le parole suggerite durante l\'inserimento Durata della traccia del gesto Anteprima mobile dinamica @@ -408,10 +384,9 @@ Vuoi davvero resettare tutte le icone personalizzate? Elimina parola dal dizionario utente Vibrazione attiva in modalità \'Non disturbare\' - %s (Fonetico) - Forza la versione di emoji + %s (Fonetico) + Forza la versione delle emoji Dargwa (Urakhi) - Urakhi (%s) Tastiera divisa (orizzontale) Distanza (orizzontale) Tastiera divisa @@ -432,4 +407,34 @@ Scorciatoie correzione Nome non valido Distanza del trascinamento per il cambio lingua + Sotto-tipo personalizzato + %s (Baishakhi) + Attenzione: il layout è in uso + Lingue con dizionari + discussione dedicata + Scopri nuovi layout o condividi quelli che hai creato nella %s. + Scopri nuove combinazioni di colori o condividi le tue nella %s. + Mostra popup con TLD + Sostituisce il popup standard del tasto . (punto) con desinenze TLD internazionali durante la digitazione di URL e email + Dopo uno spazio o la pressione di ⏎ (invio) dal tastierino numerico + Non forzare i suggerimenti in tutti i campi di testo + I campi di testo Web (specie all\'interno dei browser) sono una causa ricorrente di problemi con i suggerimenti sempre attivi + Barra dei numeri (base) + Spazio + Nessuno spazio automatico alla pressione di ⇧ (maiuscolo) dopo un gesto + Spazio automatico dopo la scelta di una parola suggerita + Spazio automatico dopo una parola aggiunta con l\'inserimento gestuale + Spazio automatico disattivato dopo Maiuscolo + Usa Backspace per annullare l\'autocorrezione + Spazio automatico prima di una parola aggiunta con l\'inserimento gestuale + Formato per il tasto data/ora + Dagbani + Sesotho + Scala la dimensione dei tasti con la dimensione dei caratteri + %1$s (%2$s) + Backup ripristinato + Suggerisci nomi delle app installate + Aggiunge i nomi delle app installate alla lista di suggerimenti e correzioni + Tonalità di pelle predefinita per le emoji + Neutro (giallo) diff --git a/app/src/main/res/values-iw/strings.xml b/app/src/main/res/values-iw/strings.xml index 04bf34fba..a2e8898e1 100644 --- a/app/src/main/res/values-iw/strings.xml +++ b/app/src/main/res/values-iw/strings.xml @@ -16,7 +16,7 @@ הפעלת מקלדת מפוצלת "עבור לשיטות קלט אחרות" "מתג החלפת שפה" - "%s אלפ\' שניה" + "%s אלפ\' שניה" "ברירת מחדל של המערכת" השתמש בשמות מרשימת אנשי הקשר עבור הצעות ותיקונים "הצעות מותאמות אישית" @@ -49,24 +49,13 @@ "ספרדית (ארצות הברית)" "אנגלית הודית" "סרבית (באותיות לטיניות)" - אנגלית (בריטניה)‏ %s) - אנגלית (ארה\"ב) ‏%s) - ספרדית (ארה\"ב) ‏%s) - אנגלית הודית %s) - סרבית ) %s) - "%s (מסורתית)" - "%s (קומפקטית)" - "ללא שפה (אלף-בית)" - "‏אלף-בית (QWERTY)" - "‏אלף-בית (QWERTZ)" - "‏אלף-בית (AZERTY)" - "‏אלף-בית (Dvorak)" - "‏אלף-בית (Colemak)" - "‏אלף-בית (PC)" + "%s (מסורתית)" + "%s (קומפקטית)" + "ללא שפה" "אמוג\'י" - "הוסף" - "הסר" - "שמור" + הוספה + הסרה + שמירה "שפה" "פריסה" משך הרטט של לחיצת מקש @@ -75,43 +64,38 @@ "אמוג\'י בשביל מקלדת פיזית" "‏מקש Alt הפיזי מציג את לוח סמלי האמוג\'י" "ברירת מחדל" - "ברוכים הבאים אל %s" + "ברוכים הבאים אל %s" "עם הקלדה רציפה" "תחילת העבודה" - "השלב הבא" - "הגדרת %s" - "הפעל את %s" - "סמן את \"%s\" בהגדרות השפה והקלט שלך. פעולה זו תאפשר לה לפעול במכשיר." - "האפליקציה %s כבר פועלת בהגדרות השפה והקלט שלך, אז השלב הזה הסתיים. ממשיכים הלאה לשלב הבא!" + "הגדרת %s" + "הפעל את %s" + "סמן את \"%s\" בהגדרות השפה והקלט שלך. פעולה זו תאפשר לה לפעול במכשיר." "הפעל בהגדרות" - "עבור אל %s" - בשלב הבא, יש לבחור ב-%s\' כשיטת ההזנה הפעילה להזנת מלל.\" + "עבור אל %s" + בשלב הבא, יש לבחור ב-\"%s\" כשיטת ההזנה הפעילה להזנת מלל. החלפת שיטת הזנה "ברכותינו, הכל מוכן!" - "כעת תוכל להקליד בכל האפליקציות המועדפות עליך באמצעות %s." + "כעת תוכל להקליד בכל האפליקציות המועדפות עליך באמצעות %s." "סיום" "הצג את סמל האפליקציה" "הצג את סמל האפליקציה במפעיל" - "תוספי מילונים" + "תוספי מילונים" "מילון זמין" - "אין מילונים זמינים" "עודכן לאחרונה" "הגדרות" "מחק" - "גרסה %1$s" - "הוסף" + "גרסה %1$s" הוספה למילון "קיצור דרך:" "שפה:" "הקלד מילה" "קיצור דרך אופציונלי" "עריכת מילה" - "לא מוגדרות מילים במילון המשתמש. הוסף מילה על ידי הקשה על לחצן \'הוסף\' (+)." "לכל השפות" "עוד שפות…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" ללא גבול - %smin + %smin הפעל את היסטוריית הלוח אם מושבת, לוח מקשים ידביק את תוכן הלוח אם קיים שמירת זמן היסטוריה @@ -126,14 +110,12 @@ הגדרות בודק האיות של HeliBoard שינוי שיטת ההזנה על-ידי מקש רווח מקש אמוג\'י - %s (תווים) + %s (תווים) בודק האיות של HeliBoard היסטוריית הלוח רווח אוטומטי לאחר סימני פיסוק - אלפבית (Colemak Mod-DH) המראה יעקוב אחר הגדרות המערכת הוסף רווח אוטומטי לאחר סימני פיסוק בעת הקלדת מילה חדשה - אלפבית (עובד) הגדרות HeliBoard קֶלֶט נסיוני @@ -208,17 +190,15 @@ בחירת כפתורי סרגל הכלים מרווחי קלידים צרים תרגום number row - שורת המספרים - שפה + שורת מספרים + @string/subtype_locale שפה (עדיפות) פריסה סימנים שכפול פריסה קיימת הקובץ אינו ניתן לקריאה - הגדרת שם הפריסה באמת להסיר את המילון שנוסף ע\"י המשתמש \"%s\"? - "ללא מילון, תקבלו הצעות למלל שהקלדתם בעבר בלבד.<br> -\n באפשרותך להוריד מילונים %1$s, או לבדוק אם מילון עבור \"%2$s\" ניתן להורדה ישירות %3$s." + "ללא מילון, תקבלו הצעות למלל שהקלדתם בעבר בלבד.<br>\n באפשרותך להוריד מילונים %1$s, או לבדוק אם מילון עבור \"%2$s\" ניתן להורדה ישירות %3$s." לא להציג שוב בחירת המילון להוספה. מילונים בפורמט .dict ניתנים להורדה %s. כאן @@ -316,10 +296,8 @@ טעינת קובץ הגדרת תמונת רקע הצגת כל הצבעים - הטעינה תחליף את ערכת הנושא הנוכחית בחירת צבעים למלל ולרקעים רקע המקלדת - לחיצה לתצוגה מקדימה מעוגל שמירת לוג מטה @@ -369,19 +347,16 @@ כפתורים פונקציונליים כפתורים פונקציונליים (סימנים) כפתורים פונקציונליים (סימנים נוספים) - קייטאג(%s) תצוגה מקדימה צפה הצגת המילה המוצעת תוך כדי מחווה משך הצגת עקבת נתיב המחווה תזוזת התצוגה המקדימה תוך כדי מחווה - %s (Extended) - %s (Sebeolsik Final) + %s (מורחבת) + %s (Sebeolsik סופי) ◄ לחיצה ממושכת על כפתורי סרגל הכלים מאפשרת פונקציונליות נוספת: <br> \n\t• לוח &#65515; הדבקה <br> \n\t• תזוזה שמאלה/ימינה &#65515; מילה שמאלה/ימינה <br> \n\t• תזוזה למעלה/למטה &#65515; דף למעלה/למטה <br> \n\t• מילה שמאלה/ימינה &#65515; תחילת שורה/סוף שורה <br> \n\t• דף למעלה/למטה &#65515; תחילת דף/סוף דף <br> \n\t• העתקה &#65515; גזירה <br> \n\t• בחירת מילה &#8596; בחירת הכל <br> \n\t• ביטול &#8596; ביצוע בשנית <br> <br> \n◄ לחיצה ממושכת על כפתורים בסרגל ההצעות של סרגל הכלים נועצת אותם בסרגל ההצעות. <br> <br> \n◄ לחיצה ממושכת על מקש פסיק לגישה לתצוגת הלוח, תצוגת אימוג\'ים, מצב עבודה ביד אחת, הגדרות, או מעבר שפה: <br> \n\t• תצוגת אימוג\'ים ומעבר שפה לא יוצגו אם הכפתורים המתאימים כבר מוצגים; <br> \n\t• בחלק מהפריסות האפשרות איננה במקש הפסיק, אלא במקש המוצג באותו מקום (לדוגמה, בפריסת Dvorak התו \'q\'). <br> <br> \n◄ כאשר מצב פרטיות מופעל, לא יילמדו כלל מילים, ולא יתווספו אימוג\'ים ל\'בשימוש לאחרונה\'. <br> <br> \n◄ ליחצו על סמל הפרטיות לגישה לסרגל הכלים. <br> <br> \n◄ הקלדה בהחלקה: החליקו מ-shift למקש אחר כדי להקיש אות גדולה יחידה: <br> \n\t• זה עובד באופן דומה גם למקש \'?123\' להקלדת סימן יחיד מלוח הסמלים, ולמקשים קשורים. <br> <br> \n◄ ליחצו על shift או על מקש הסמלים, ליחצו על מקש אחד או יותר, ואז הרפו מ-shift או ממקש הסמלים לחזרה למקלדת הקודמת. <br> <br> \n◄ לחיצה ממושכת על הצעה בסרגל ההצעות להצגת הצעות נוספות, ומקש מחיקה להסרת הצעה זו. <br> <br> \n◄ החליקו למעלה מהצעה לפתיחת הצעות נוספות, והרפו על ההצעה הרצויה לבחירתה. <br> <br> \n◄ לחיצה ממושכת על רשומה בהיסטוריית הלוח לנעיצתה (שמירתה בלוח עד לביטול הנעיצה). <br> <br> \n◄ החלקה שמאלה על רשומה בתצוגת הלוח להסרתה מהלוח (אם היא לא נעוצה) <br> <br> \n◄ בחירת מלל ולחיצה על shift למעבר בין אותיות גדולות, אותיות קטנות ורישיות מילים גדולות. <br> <br> \n◄ ניתן להוסיף מילונים ע\"י פתיחתם באמצעות יישום סייר קבצים: <br> \n\t• פועל רק עם <i>content-uris</i> ולא עם <i>file-uris</i>, ז\"א שזה עלול שלא לעבוד בחלק מיישומי סייר קבצים. <br> <br> \n◄ משתמשים המבצעים גיבויים ידניים עם הרשאת גישה root: <br> \n\t• החל באנדרואיד 7, קובץ ההעדפות המשותף איננו בנתיב ברירת המחדל, כיוון שהיישום עושה שימוש ב %s. הדבר נחוץ כדי שההגדרות יהיו קריאות לפני שהמכשיר נפתח, לדוגמה: בהפעלה; <br> \n\t• הקובץ ממוקם בנתיב /data/user_de/0/package_id/shared_prefs/ אך זה עשוי להשתנות בתלות בגירסאות המכשיר ומערכת אנדרואיד. <br> <br> \n<i><b>Debug mode / debug APK</b></i> <br> <br> \n◄ לחיצה ממושכת על הצעה להצגת מילון המקור. <br> <br> \n◄ בשימוש ב-debug APK, באפשרותך למצוא את הגדרות ה-Debug Settings בהעדפות המתקדמות,אך השימושיות מוגבלת למעט dumping של מילונים ליומן (log). <br> \n\t• עבור APK רשמי, עליך ללחוץ על הגירסה <i>About</i> מספר פעמים, ואז ניתן למצוא אתהגדרות ה-debug ב-<i>העדפות מתקדמות</i>. <br> \n\t• כאשר מופעלת <i>הצגת מידע על הצעות</i>, יוצגו מספרים זעירים בסמוך להצעות המייצגים דירוג פנימי ומילון מקור. <br> <br> \n◄ במקרה של קריסת יישום, תוצג לך שאלה האם ברצונך ביומני הקריסה בפתיחת ההגדרות. <br> <br> \n◄ בעת שימוש בהקלדה מרובת שפות, מקש הרווח יציג מדד אמון המשמש לברירת השפה שבשימוש כעת. <br> <br> \n◄ בסמוך להצעות יוצגו מספרים זעירים המייצגים דירוג פנימי ומילון מקור (התצוגה ניתנת להשבתה). - %s (Probhat) - %s (Sebeolsik 390) - אלפבית (Bépo) - %s (Student) - מנסי (%s) + %s (Probhat) + %s (Sebeolsik 390) + %s (Student) סגנון הסמלים שורת המספרים מלל מותאם על מקש הרווח @@ -408,7 +383,7 @@ תו בלתי-מחבר ברוחב אפס האם באמת ברצונך למחוק את כל הסמלים המותאמים? רטט במצב נא לא להפריע - %s (פונטי) + %s (פונטי) עקיפת גירסת אמוג\'י האם למחוק את כל קודי המקשים המותאמים? קיצורי דרך של תיקון שגיאות אוטומטי @@ -428,15 +403,37 @@ מקלדת מפוצלת השם אינו תקף תת-סוג מותאם - %s (באישאקי) + %s (באישאקי) התרעה: הפריסה בשימוש כעת מקשים פונקציונליים (מסך גדול) דרגווה (אוראקי) - אוראקי(%s) באמת למחוק את %s? פריסות משניות שפות ומילונים באפשרותך למצוא ולשתף צבעים ב %s. באפשרותך למצוא ולשתף פריסות ב %s. מקטע הדיונים + הצגת חלון צץ של סיומות אינטרנט + החלפת חלון צץ של מקש נקודה ברשימת סיומות אינטרנט נפוצות בעת הקלדת כתובות אינטרנט ודוא\"ל + לאחר לחיצת Enter או רווח לאחר מקשים אחרים במקלדת המספרים + לא תמיד להציג הצעות לשדות עריכה ב-Web + שדות עריכה ב-Web (בדר\"כ יוצגו בדפדפן) הם גורם נפוץ מאד לבעיות בהגדרה \'הצגת הצעות תמיד\' + שורת המספרים (פריסת בסיס) + רווח + הוספת רווח אוטומטית אחרי בחירת הצעה + הוספת רווח אוטומטית לפני הקלדת מילה במחווה + הוספת רווח אוטומטית לאחר הקלדת מילה במחווה + ביטול הצעת התיקון האוטומטי במחיקה לאחור + ללא רווח אוטומטי בעת לחיצת Shift + Shift מבטל את הרווח האוטומטי המיועד + פורמט למקש חתימת הזמן + דאגבני + ססוטו + התאמת גודל מקש האמוג\'י לגודל הגופן + הגיבוי שוחזר + רשימת שמות יישומים לאיתור + גוון עור ברירת-מחדל לאמוג\'י + נייטרלי + שימוש בשמות יישומים מותקנים להצעות ולתיקונים + %1$s (%2$s) diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index bcaa4b17a..5b63425f5 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -16,7 +16,7 @@ "スプリットキーボードを有効にする" "他の入力方法に切り替え" "言語切り替えキー" - "%sミリ秒" + "%sミリ秒" "システムのデフォルト" "連絡先の名前を使用して候補表示や自動修正を行う" "入力候補のカスタマイズ" @@ -49,20 +49,9 @@ "スペイン語 (米国)" "ヒングリッシュ" "セルビア語(ラテン文字)" - "英語(英国)(%s)" - "英語(米国)(%s)" - "スペイン語(米国)(%s)" - "ヒングリッシュ(%s)" - "セルビア語(%s)" - "%s(伝統言語)" - "%s(コンパクト)" - "言語なし(アルファベット)" - "アルファベット(QWERTY)" - "アルファベット(QWERTZ)" - "アルファベット(AZERTY)" - "アルファベット(Dvorak)" - "アルファベット(Colemak)" - "アルファベット(PC)" + "%s(伝統言語)" + "%s(コンパクト)" + 言語なし(アルファベット) "絵文字" "追加" "削除" @@ -75,38 +64,33 @@ "物理キーボードの絵文字" "物理Altキーによって絵文字パレットが表示されます" "デフォルト" - %sへようこそ\" + %sへようこそ\" "新しいジェスチャー入力をお試しください" "開始" - "次のステップ" - %sの設定\" - %sの有効化\" - [言語と入力] 設定で%s」のチェックボックスをオンにしてください。これで、このデバイスで利用できるようになります。\" - "[言語と入力] 設定で「%s」は既に有効になっているため、このステップは完了です。次のステップに進んでください。" + %sの設定\" + %sの有効化\" + [言語と入力] 設定で%s」のチェックボックスをオンにしてください。これで、このデバイスで利用できるようになります。\" "設定での有効化" - %sへの切り替え\" - 次に、有効なテキスト入力方法として%s」を選択します。\" + %sへの切り替え\" + 次に、有効なテキスト入力方法として%s」を選択します。\" "入力方法を切り替える" "設定完了" - "これで、お気に入りのすべてのアプリで%sを使用して入力できます。" + "これで、お気に入りのすべてのアプリで%sを使用して入力できます。" "完了" "アプリアイコンを表示" "ランチャーにアプリアイコンを表示します" - "アドオン辞書" + "アドオン辞書" "辞書を利用できます" - "辞書はありません" "最終更新" "設定" "削除" - "バージョン%1$s" - "追加" + "バージョン%1$s" "辞書に追加" "ショートカット:" "言語:" "単語を入力します" "オプションのショートカット" "語句の編集" - "単語リストに登録がありません。単語を追加するには、追加ボタン [+] をタップします。" "すべての言語用" "その他の言語…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" diff --git a/app/src/main/res/values-jpr/strings.xml b/app/src/main/res/values-jpr/strings.xml index ca462e407..463fe85c5 100644 --- a/app/src/main/res/values-jpr/strings.xml +++ b/app/src/main/res/values-jpr/strings.xml @@ -2,7 +2,6 @@ מנטׄימאת ברגזידה חדֿףֿ - חרוףֿ אלפֿבא (QWERTZ) בזרגכרדן כֿודכאר חרוףֿ תצחיח כֿודכאר מנטׄימאת HeliBoard‬‏ @@ -50,10 +49,8 @@ שאם פישפֿרץֿ שרוע בה כאר - מרחלה בעד תמאם שוד לגֿאת - אפֿרודן וזן:‏ זבאן:‏ רפֿתן @@ -62,7 +59,6 @@ מכת אנתטׄאר בסיאר שדיד - חרוףֿ אלפֿבא (QWERTY) באזאנגׄאם בעדי קבלי diff --git a/app/src/main/res/values-ka/strings.xml b/app/src/main/res/values-ka/strings.xml index 04b1e76f8..b4f2ccdb4 100644 --- a/app/src/main/res/values-ka/strings.xml +++ b/app/src/main/res/values-ka/strings.xml @@ -16,7 +16,7 @@ "გაყოფილი კლავიატურის გააქტიურება" "შეყვანის სხვა მეთოდებზე გადართვა" "ენის გადართვის კლავიში" - "%sმწმ" + "%sმწმ" "სისტემის ნაგულისხმევი" "კონტაქტებიდან სახელების გამოყენება შეთავაზებებისთვის და კორექციისთვის" "პერსონალიზებული შეთავაზებები" @@ -49,20 +49,9 @@ "ესპანური (აშშ)" "ჰინგლისური" "სერბული (ლათინური)" - ინგლისური (UK) %s - ინგლისური (აშშ) (%s) - ესპანური (აშშ) (%s) - ჰინგლისური (%s) - სერბული (%s) - %s (ტრადიციული) - %s (კომპაქტური) - "ენის გარეშე (ლათინური ანბანი)" - "ლათ. ანბანი (QWERTY)" - "ანბანი (QWERTZ)" - "ანბანი (AZERTY)" - "ანბანი (Dvorak)" - "ანბანი (Colemak)" - "ანბანი (PC)" + %s (ტრადიციული) + %s (კომპაქტური) + "ენის გარეშე" "სიცილაკები" "დამატება" "ამოშლა" @@ -75,38 +64,33 @@ "სიცილაკები ფიზიკური კლავიატურისთვის" "ფიზიკური ღილაკი Alt აჩვენებს სიცილაკების პალიტრას" "ნაგულისხმევი" - მოგესალმებათ %s + მოგესალმებათ %s "ჟესტებით წერით" "დაწყება" - "შემდეგი საფეხური" - %s-ის მორგება - %s-ის ჩართვა - შეყვანის პარამეტრებში გადაამოწმეთ %s&. ეს თქვენს მოწყობილობაზე გაშვების ავტორიზაციას მოგცემთ. - %s& თქვენი შეყვანის ენის პარამეტრებში უკვე ჩართულია. შემდეგ საფეხური! + %s-ის მორგება + %s-ის ჩართვა + შეყვანის პარამეტრებში გადაამოწმეთ %s&. ეს თქვენს მოწყობილობაზე გაშვების ავტორიზაციას მოგცემთ. "პარამეტრებში გააქტიურება" - გადაერთეთ %s-ზე - შემდეგ, აირჩიეთ „%s“ თქვენს აქტიურ შეყვანის მეთოდად. + გადაერთეთ %s-ზე + შემდეგ, აირჩიეთ „%s“ თქვენს აქტიურ შეყვანის მეთოდად. "შეყვანის მეთოდების გადართვა" "გილოცავთ, პროცესი დასრულდა!" - ახლა თქვენს საყვარელ აპებში შეგიძლიათ %s-ით აკრიფოთ. + ახლა თქვენს საყვარელ აპებში შეგიძლიათ %s-ით აკრიფოთ. "დასრულებული" "აპის ხატულის ჩვენება" "აპის ხატულის ჩვენება გამშვებში" - "დამატებითი ლექსიკონები" + "დამატებითი ლექსიკონები" "ხელმისაწვდომია ლექსიკონი" - "ლექსიკონები მიუწვდომელია" "ბოლო განახლება" "პარამეტრები" "წაშლა" - ვერსია %1$s - "დამატება" + ვერსია %1$s "ლექსიკონში დამატება" "მალსახმობი:" "ენა:" "შიყვანეთ სიტყვა" "არასავალდებულო მალსა" "სიტყვის შესწორება" - "მომხმარებლის ლექსიკონში სიტყვები არ არის. სიტყვის დასამატებლად, შეეხეთ დამატების (+) ღილაკს." "ყველა ენისთვის" "სხვა ენები…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" @@ -119,7 +103,7 @@ პუნქტუაციის შემდეგ ადგილის ავტომტური გამოტოვება ახალი სიტყვის დაწყებისას პუნქტუაციის შემდეგ გამოტოვების ავტომატური ჩასმა ციფრებანი მწკრივი - %s (აკხორი) + %s (აკხორი) გარეგნობა სისტემურ პარამეტრებს დაეყრდნობა ბუფერის ისტორია შესწორებები @@ -142,13 +126,11 @@ მინიშნებები ექსპერიმენტალური რიცხვებიანი მწკრივის ყოველთვის ჩვენება - ანბანი (Workman) - %sწთ. + %sწთ. ისტორიის შენახვის დრო მეტი ღილაკი კლავიატურის სიმაღლის მასშტაბი ღილაკის კონტურები - ანბანი (Colemak Mod-DH) დღის/ღამის ავტ. არჩევანი "დაბრუნება" "გამეორება" diff --git a/app/src/main/res/values-kab/strings.xml b/app/src/main/res/values-kab/strings.xml index 430b55ff7..463cd8515 100644 --- a/app/src/main/res/values-kab/strings.xml +++ b/app/src/main/res/values-kab/strings.xml @@ -7,7 +7,6 @@ Imenyafen Iɣewwaren n HeliBoard Wiyyaḍ - Rnu Tutlayt : Beddel awal-a Sekles @@ -51,13 +50,8 @@ Immed Uṭṭunen Taglizit (Tagelda Yedduklen) - Agemmay alatini (AZERTY) - Agemmay alatini (Colemak) - Agemmay (Workman) - Agemmay (Bépo) - Agemmay (Colemak Mod-DH) Fren tarrayt n usekcem - %s ms + %s ms Ulac tilisa Amawal udmawan Aseɣti awurman @@ -65,11 +59,9 @@ Ssken-d isumar n useɣti Iḍ Ur ttεawad ara ad d-tsekneḍ - Ulac imawalen yellan Aseɣti n uḍris Iseɣtiyen Taqeffalt n ubeddel n tutlayin - Agemmay alatini (aselkim) Assuter i wawal i d-iteddun Ass Ssken-d tignit n usnas @@ -90,8 +82,7 @@ Asekcem agetlan Taspenyulit (Iwunak Yeddukklen) Taglizit (Iwunak Yeddukklen) - War tutlayt (Agemmay) - Agemmay alatini (DVORAK) + War tutlayt Rnu ɣer umawal Sken ugar n yiniten Seqdec tutlayin n unagraw @@ -99,7 +90,6 @@ Anekcam n taɣect Tutlayin akked tneɣrufin Tiqeffalin nniḍen - Agemmay alatini (QWERTY) Aberkan Aḍris n tqeffalin Ɛebbi afaylu @@ -109,7 +99,17 @@ Fren awal Zelmaḍ Yeffus - Agemmay alatini (QWERTZ) Adda Lqem aneggaru - \ No newline at end of file + Sali + Armitan + Ṛǧu + Tallunt + Ijdi + Mansi + Aɣanib + Afeggag n ifecka + Ubrik + Kaitag + Imawalen nniḍen + diff --git a/app/src/main/res/values-kk/strings.xml b/app/src/main/res/values-kk/strings.xml index 7ac658539..11250f354 100644 --- a/app/src/main/res/values-kk/strings.xml +++ b/app/src/main/res/values-kk/strings.xml @@ -16,7 +16,7 @@ "Бөлінген пернетақтаны қосу" "Басқа енгізу әдістеріне ауыстырыңыз" "Тілді ауыстыру пернесі" - "%sмс" + "%sмс" "Жүйенің әдепкі мәні" "Ұсыныстар мен түзетулер үшін контакт аттарын пайдалану" "Жекелендірілген ұсыныстар" @@ -49,20 +49,9 @@ "Испан (АҚШ)" "Хинглиш" "Серб (латын жазуы)" - "Ағылшын (Құрама Корольдік) (%s)" - "Ағылшын (АҚШ) (%s)" - "Испан (АҚШ) (%s)" - "Хинглиш (%s)" - "Серб (%s)" - "%s (дәстүрлі)" - "%s (шағын)" - "Тіл жоқ (әліпби)" - "Әліпби (QWERTY)" - "Әліпби (QWERTZ)" - "Әліпби (AZERTY)" - "Әліпби (Dvorak)" - "Әліпби (Colemak)" - "Әліпби (ДК)" + "%s (дәстүрлі)" + "%s (шағын)" + "Тіл жоқ" "Эмодзи" "Қосу" "Өшіру" @@ -75,38 +64,33 @@ "Қатты пернетақтадан енгізілетін эмодзи" "Alt пернесі арқылы эмодзилерді ашуға болады" "Әдепкі" - %s қолданбасына қош келдіңіз\" + %s қолданбасына қош келдіңіз\" "Қимылмен теру арқылы" "Іске қосылды" - "Келесі қадам" - %s орнату\" - %s қосу\" - "\"Тілдер және енгізу\" параметрлерінде %s қолданбасына құсбелгі қойыңыз. Сонда оны құрылғыңызда қолдануға рұқсат беріледі." - "%s қолданбасы \"Тілдер және енгізу\" параметрлерінде бұрыннан қосылған. Келесі қадамға өтіңіз!" + %s орнату\" + %s қосу\" + "\"Тілдер және енгізу\" параметрлерінде %s қолданбасына құсбелгі қойыңыз. Сонда оны құрылғыңызда қолдануға рұқсат беріледі." "Параметрлер ішінде қосу" - %s қолданбасына ауыстыру\" - "Одан кейін \"%s\" қолданбасын белсенді мәтінді енгізу әдісі ретінде таңдаңыз." + %s қолданбасына ауыстыру\" + "Одан кейін \"%s\" қолданбасын белсенді мәтінді енгізу әдісі ретінде таңдаңыз." "Енгізу әдістерін ауыстыру" "Құттықтаймыз, барлығы дайын!" - "Қазір барлық таңдаулы қолданбаларда %s арқылы теруге болады." + "Қазір барлық таңдаулы қолданбаларда %s арқылы теруге болады." "Аяқталған" "Қолданба белгішесін көрсету" "Іске қосу құралында қолданба белгішесін көрсету" - "Қосымша сөздіктер" + "Қосымша сөздіктер" "Сөздік қолжетімді" - "Сөздіктер қолжетімсіз" "Соңғы жаңартылған" "Параметрлер" "Жою" - "%1$s нұсқасы" - "Қосу" + "%1$s нұсқасы" "Сөздікке қосу" "Пернелер тіркесімі:" "Тіл:" "Сөзді теріңіз" "Қосымша пернелер тіркесімі" "Сөзді өңдеу" - "Пайдаланушы сөздігінде сөздер жоқ. Сөзді қосу үшін \"Қосу\" (+) түймесін түртіңіз." "Барлық тілдер үшін" "Қосымша тілдер…" " АӘБВГҒДЕЁЖЗИЙКҚЛМНҢОӨПРСТУҰҮФХҺЦЧШЩЪЫІЬЭЮЯ" diff --git a/app/src/main/res/values-km/strings.xml b/app/src/main/res/values-km/strings.xml index 813846419..f7458e425 100644 --- a/app/src/main/res/values-km/strings.xml +++ b/app/src/main/res/values-km/strings.xml @@ -17,7 +17,7 @@ "បើក​ការ​បំបែក​ក្ដារចុច" "ប្ដូរ​ទៅ​​​វិធីសាស្ត្រ​បញ្ចូល​​​ផ្សេង​ទៀត" "គ្រាប់​ចុច​ប្ដូរ​​ភាសា" - "%s មិល្លី​វិនាទី" + "%s មិល្លី​វិនាទី" "លំនាំ​ដើម​​​ប្រព័ន្ធ" "ប្រើ​ឈ្មោះ​ពី​ទំនាក់ទំនង​សម្រាប់​ការ​​ស្នើ និង​​​កែ" "ការ​ស្នើ​ផ្ទាល់​ខ្លួន" @@ -50,20 +50,9 @@ "អេស្ប៉ាញ (សហរដ្ឋ​អាមេរិក​)" "Hinglish" "សើប (ឡាតាំង​)" - "អង់គ្លេស (ចក្រភព​អង់គ្លេស) (%s)" - "អង់គ្លេស (អាមេរិក) (%s)" - "អេស្ប៉ាញ (អាមេរិក) (%s)" - "Hinglish (%s)" - "សើប (%s)" - "%s (អក្សរ​ពេញ)" - "%s (បង្រួម)" - "គ្មាន​ភាសា (អក្សរ​ក្រម)" - "តាម​លំដាប់​អក្សរក្រម (QWERTY)" - "តាម​លំដាប់​អក្សរក្រម (QWERTZ)" - "តាម​លំដាប់​អក្សរក្រម (AZERTY)" - "តាម​លំដាប់​អក្សរក្រម (Dvorak)" - "តាម​លំដាប់​អក្សរក្រម (Colemak)" - "តាម​លំដាប់​អក្សរក្រម (កុំព្យូទ័រ)" + "%s (អក្សរ​ពេញ)" + "%s (បង្រួម)" + "គ្មាន​ភាសា" "សញ្ញា​អារម្មណ៍" "បន្ថែម" "លុប​ចេញ" @@ -76,38 +65,33 @@ "សញ្ញាអារម្មណ៍សម្រាប់ក្តារចុចពិតប្រាកដ" "គ្រាប់ចុច Alt បង្ហាញផ្ទាំងសញ្ញាអារម្មណ៍" "លំនាំដើម" - "សូម​ស្វាគមន៍​មក​កាន់ %s" + "សូម​ស្វាគមន៍​មក​កាន់ %s" "ជាមួយ​​​ការ​វាយ​បញ្ចូល​ដោយ​ប្រើ​​​កាយវិការ" "បាន​ចាប់ផ្ដើម" - "ជំហាន​បន្ទាប់" - "រៀបចំ %s" - "បើក %s" - "សូមពិនិត្យ \"%s\" ក្នុងការកំណត់ភាសា និងបញ្ចូលរបស់អ្នក។ វានឹងផ្តល់សិទ្ធិឲ្យកម្មវិធីនេះដំណើរការនៅលើឧបករណ៍របស់អ្នក។" - "%s ត្រូវបានបើកដំណើរការនៅក្នុងការកំណត់ភាសា និងបញ្ចូលរបស់អ្នករួចហើយ ដូច្នេះជំហ៊ាននេះបានបញ្ចប់ហើយ។ ចូលទៅជំហ៊ានបន្ទាប់!" + "រៀបចំ %s" + "បើក %s" + "សូមពិនិត្យ \"%s\" ក្នុងការកំណត់ភាសា និងបញ្ចូលរបស់អ្នក។ វានឹងផ្តល់សិទ្ធិឲ្យកម្មវិធីនេះដំណើរការនៅលើឧបករណ៍របស់អ្នក។" "បើក​នៅ​ក្នុង​ការ​កំណត់" - "ប្ដូរ​ទៅ %s" - "បន្ទាប់ ជ្រើស \"%s\" ជា​វិធី​សាស្ត្រ​បញ្ចូល​អត្ថបទ​សកម្ម​របស់​អ្នក។" + "ប្ដូរ​ទៅ %s" + "បន្ទាប់ ជ្រើស \"%s\" ជា​វិធី​សាស្ត្រ​បញ្ចូល​អត្ថបទ​សកម្ម​របស់​អ្នក។" "ប្ដូរ​វិធីសាស្ត្រ​បញ្ចូល" "សូម​អបអរ​សាទរ,​ អ្នក​​បាន​កំណត់​​រួចរាល់​ហើយ!" - "ឥឡូវ​​អ្នក​អាច​​វាយ​បញ្ចូល​នៅ​ក្នុង​​កម្មវិធី​​ពេញ​ចិត្ត​របស់​អ្នក​ទាំងអស់​ជាមួយ %s ។" + "ឥឡូវ​​អ្នក​អាច​​វាយ​បញ្ចូល​នៅ​ក្នុង​​កម្មវិធី​​ពេញ​ចិត្ត​របស់​អ្នក​ទាំងអស់​ជាមួយ %s ។" "បាន​បញ្ចប់" "បង្ហាញ​រូប​កម្មវិធី" "បង្ហាញ​រូប​កម្មវិធី​នៅ​ក្នុង​កម្ម​​វិធី​ចាប់ផ្ដើម" - "ផ្នែក​បន្ថែម​វចនានុក្រម​​" + "ផ្នែក​បន្ថែម​វចនានុក្រម​​" "វចនានុក្រម​​​អាច​ប្រើ​បាន" - "គ្មាន​វចនានុក្រម" "បាន​ធ្វើ​បច្ចុប្បន្នភាព​ចុងក្រោយ" "ការ​កំណត់" "លុប" - "កំណែ %1$s" - "បន្ថែម" + "កំណែ %1$s" "បន្ថែម​ទៅ​វចនានុក្រម" "ផ្លូវកាត់​៖" "ភាសា៖" "វាយ​បញ្ចូល​ពាក្យ​" "ផ្លូវកាត់​ជា​ជម្រើស" "កែ​ពាក្យ" - "អ្នកមិនមានពាក្យនៅក្នុងវចនានុក្រមអ្នកប្រើទេ។ ដើម្បីបន្ថែមពាក្យ សូមប៉ះប៊ូតុងបន្ថែម (+)។" "សម្រាប់​ភាសា​ទាំងអស់" "ភាសា​ច្រើន​ទៀត…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" diff --git a/app/src/main/res/values-kn/strings.xml b/app/src/main/res/values-kn/strings.xml index 10e8f28ed..da525a771 100644 --- a/app/src/main/res/values-kn/strings.xml +++ b/app/src/main/res/values-kn/strings.xml @@ -16,7 +16,7 @@ "ಬೇರ್ಪಡೆ ಕೀಬೋರ್ಡ್ ಸಕ್ರಿಯಗೊಳಿಸಿ" "ಇತರೆ ಇನ್‌ಪುಟ್ ವಿಧಾನಗಳಿಗೆ ಬದಲಾಯಿಸು" "ಭಾಷೆ ಬದಲಾವಣೆ ಕೀ" - "%sಮಿ.ಸೆ." + "%sಮಿ.ಸೆ." "ಸಿಸ್ಟಂ ಡಿಫಾಲ್ಟ್" "ಸಲಹೆಗಳು ಮತ್ತು ತಿದ್ದುಪಡಿಗಳಿಗಾಗಿ ಸಂಪರ್ಕಗಳಲ್ಲಿನ ಹೆಸರುಗಳನ್ನು ಬಳಸಿ" "ವೈಯುಕ್ತೀಕರಿಸಿದ ಸಲಹೆಗಳು" @@ -49,21 +49,10 @@ "ಸ್ಪ್ಯಾನಿಷ್ (US)" "ಹಿಂಗ್ಲಿಷ್" "ಸರ್ಬಿಯನ್ (ಲ್ಯಾಟಿನ್)" - "ಇಂಗ್ಲಿಷ್ (ಯುಕೆ) (%s)" - "ಇಂಗ್ಲಿಷ್ (US) (%s)" - "ಸ್ಪ್ಯಾನಿಷ್ (US) (%s)" - "ಹಿಂಗ್ಲಿಷ್ (%s)" - "%s (ವಿಸ್ತರಿಸಲಾಗಿದೆ)" - "ಸರ್ಬಿಯನ್ (%s)" - "%s (ಸಾಂಪ್ರದಾಯಿಕ)" - "%s (ಕಾಂಪ್ಯಾಕ್ಟ್‌‌)" - "ಯಾವುದೇ ಭಾಷೆಯಿಲ್ಲ (ವರ್ಣಮಾಲೆ)" - "ವರ್ಣಮಾಲೆ (QWERTY)" - "ವರ್ಣಮಾಲೆ (QWERTZ)" - "ವರ್ಣಮಾಲೆ (AZERTY)" - "ವರ್ಣಮಾಲೆ (ಡ್ವೊರಕ್)" - "ವರ್ಣಮಾಲೆ (ಕೋಲ್‌ಮ್ಯಾಕ್)" - "ವರ್ಣಮಾಲೆ (PC)" + "%s (ವಿಸ್ತರಿಸಲಾಗಿದೆ)" + "%s (ಸಾಂಪ್ರದಾಯಿಕ)" + "%s (ಕಾಂಪ್ಯಾಕ್ಟ್‌‌)" + "ಯಾವುದೇ ಭಾಷೆಯಿಲ್ಲ" "ಎಮೋಜಿ" "ಸೇರಿಸು" "ತೆಗೆದುಹಾಕಿ" @@ -76,38 +65,33 @@ "ಭೌತಿಕ ಕೀಬೋರ್ಡ್‌ಗೆ ಎಮೋಜಿ" "ಭೌತಿಕ Alt ಕೀ ಎಮೋಜಿ ಪ್ಯಾಲೆಟ್ ತೋರಿಸುತ್ತದೆ" "ಡಿಫಾಲ್ಟ್" - %s ಗೆ ಸುಸ್ವಾಗತ\" + %s ಗೆ ಸುಸ್ವಾಗತ\" "ಗೆಶ್ಚರ್ ಟೈಪಿಂಗ್‌ನೊಂದಿಗೆ" "ಪ್ರಾರಂಭ" - "ಮುಂದಿನ ಹಂತ" - %s ಅನ್ನು ಹೊಂದಿಸಲಾಗುತ್ತಿದೆ\" - %s ಸಕ್ರಿಯಗೊಳಿಸಿ\" - "ನಿಮ್ಮ ಭಾಷೆಗಳು & ಇನ್‌ಪುಟ್ ಸೆಟ್ಟಿಂಗ್‌ಗಳಲ್ಲಿ ದಯವಿಟ್ಟು \"%s\" ಅನ್ನು ಪರಿಶೀಲಿಸಿ. ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿ ಅದನ್ನು ರನ್ ಮಾಡಲು ಅದು ಅನುಮತಿ ನೀಡುತ್ತದೆ." - "%s ಅನ್ನು ಈಗಾಗಲೇ ನಿಮ್ಮ ಭಾಷೆಗಳು & ಇನ್‌ಪುಟ್ ಸೆಟ್ಟಿಂಗ್‌ಗಳಲ್ಲಿ ಸಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ, ಹೀಗಾಗಿ ಈ ಹಂತ ಮುಗಿದಿದೆ. ಮುಂದಿನದಕ್ಕೆ ತೆರಳಿ!" + %s ಅನ್ನು ಹೊಂದಿಸಲಾಗುತ್ತಿದೆ\" + %s ಸಕ್ರಿಯಗೊಳಿಸಿ\" + "ನಿಮ್ಮ ಭಾಷೆಗಳು & ಇನ್‌ಪುಟ್ ಸೆಟ್ಟಿಂಗ್‌ಗಳಲ್ಲಿ ದಯವಿಟ್ಟು \"%s\" ಅನ್ನು ಪರಿಶೀಲಿಸಿ. ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿ ಅದನ್ನು ರನ್ ಮಾಡಲು ಅದು ಅನುಮತಿ ನೀಡುತ್ತದೆ." "ಸೆಟ್ಟಿಂಗ್‌ಗಳಲ್ಲಿ ಸಕ್ರಿಯಗೊಳಿಸು" - %s ಗೆ ಬದಲಾಯಿಸಿ\" - "ಮುಂದೆ, ನಿಮ್ಮ ಸಕ್ರಿಯ ಪಠ್ಯ-ಇನ್‌ಪುಟ್ ವಿಧಾನವಾಗಿ \"%s\" ಅನ್ನು ಆಯ್ಕೆಮಾಡಿ." + %s ಗೆ ಬದಲಾಯಿಸಿ\" + "ಮುಂದೆ, ನಿಮ್ಮ ಸಕ್ರಿಯ ಪಠ್ಯ-ಇನ್‌ಪುಟ್ ವಿಧಾನವಾಗಿ \"%s\" ಅನ್ನು ಆಯ್ಕೆಮಾಡಿ." "ಇನ್‌ಪುಟ್ ವಿಧಾನಗಳನ್ನು ಬದಲಾಯಿಸು" "ಅಭಿನಂದನೆಗಳು, ನೀವೀಗ ಎಲ್ಲವನ್ನೂ ಹೊಂದಿಸಿರುವಿರಿ!" - "ಈಗ ನೀವು %s ನೊಂದಿಗೆ ನಿಮ್ಮ ಎಲ್ಲ ಮೆಚ್ಚಿನ ಅಪ್ಲಿಕೇಶನ್‌ಗಳಲ್ಲಿ ಟೈಪ್ ಮಾಡಬಹುದು." + "ಈಗ ನೀವು %s ನೊಂದಿಗೆ ನಿಮ್ಮ ಎಲ್ಲ ಮೆಚ್ಚಿನ ಅಪ್ಲಿಕೇಶನ್‌ಗಳಲ್ಲಿ ಟೈಪ್ ಮಾಡಬಹುದು." "ಮುಕ್ತಾಯಗೊಂಡಿದೆ" "ಅಪ್ಲಿಕೇಶನ್ ಐಕಾನ್ ತೋರಿಸು" "ಲಾಂಚರ್‌ನಲ್ಲಿ ಅಪ್ಲಿಕೇಶನ್ ಐಕಾನ್ ಪ್ರದರ್ಶಿಸು" - "ಆಡ್-ಆನ್ ನಿಘಂಟುಗಳು" + "ಆಡ್-ಆನ್ ನಿಘಂಟುಗಳು" "ನಿಘಂಟು ಲಭ್ಯವಿದೆ" - "ನಿಘಂಟುಗಳು ಲಭ್ಯವಿಲ್ಲ" "ಕೊನೆಯದಾಗಿ ನವೀಕರಿಸಿರುವುದು" "ಸೆಟ್ಟಿಂಗ್‌ಗಳು" "ಅಳಿಸಿ" - "ಆವೃತ್ತಿ %1$s" - "ಸೇರಿಸು" + "ಆವೃತ್ತಿ %1$s" "ನಿಘಂಟಿಗೆ ಸೇರಿಸಿ" "ಶಾರ್ಟ್‌ಕಟ್:" "ಭಾಷೆ:" "ಪದವನ್ನು ಟೈಪ್ ಮಾಡಿ" "ಐಚ್ಛಿಕ ಶಾರ್ಟ್‌ಕಟ್" "ಪದವನ್ನು ಎಡಿಟ್ ಮಾಡಿ" - "ಬಳಕೆದಾರರ ನಿಘಂಟಿನಲ್ಲಿ ನೀವು ಯಾವುದೇ ಪದಗಳನ್ನು ಹೊಂದಿಲ್ಲ. ಪದವನ್ನು ಸೇರಿಸಲು, ಸೇರಿಸು (+) ಬಟನ್ ಟ್ಯಾಪ್ ಮಾಡಿ." "ಎಲ್ಲ ಭಾಷೆಗಳಿಗೆ" "ಇನ್ನಷ್ಟು ಭಾಷೆಗಳು…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 0863c8235..a95063e0d 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -16,7 +16,7 @@ "분할 키보드 사용" "다른 입력 방법으로 전환" "언어 전환 키" - "%sms" + "%sms" "시스템 기본값" "추천 및 수정에 주소록의 이름 사용" "맞춤 추천 검색어" @@ -49,20 +49,9 @@ "스페인어(미국)" "인도 영어" "세르비아어(라틴 문자)" - 영어(영국)(%s) - 영어(미국)(%s) - 스페인어 (미국) (%s) - 인도 영어(%s) - 세르비아어(%s) - %s (번체) - %s (소형) - "언어 없음(알파벳)" - "알파벳(QWERTY)" - "알파벳(QWERTZ)" - "알파벳(AZERTY)" - "알파벳(드보락)" - "알파벳(콜맥)" - "알파벳(PC)" + %s (번체) + %s (소형) + "언어 없음" "이모티콘" "추가" "삭제" @@ -75,38 +64,33 @@ "물리적 키보드용 그림 이모티콘" "물리적 Alt 키로 그림 이모티콘 팔레트 표시" "기본값" - %s에 오신 것을 환영합니다 + %s에 오신 것을 환영합니다 "제스처 타이핑 사용" "시작하기" - "다음 단계" - %s 설정 - %s 사용 설정 - & 입력 설정에서 \"%s\" 를 확인해주세요. 이것은 이 기기에서 작동하기 위해 인증합니다. - %s 은(는) 언어 및 입력 설정에서 이미 사용하도록 설정되어 있으므로 이 단계는 완료되었습니다. 다음 단계로 이동하세요! + %s 설정 + %s 사용 설정 + & 입력 설정에서 \"%s\" 를 확인해주세요. 이것은 이 기기에서 작동하기 위해 인증합니다. "\'설정\'에서 사용 설정" - %s(으)로 전환 - 그리고, 텍스트 입력 방법으로 \'%s\'을(를) 선택합니다. + %s(으)로 전환 + 그리고, 텍스트 입력 방법으로 \'%s\'을(를) 선택합니다. "입력 방법 전환" 모든 설정이 완료되었습니다! - 이제 즐겨찾는 앱을 %s과 함께 입력할 수 있습니다. + 이제 즐겨찾는 앱을 %s과 함께 입력할 수 있습니다. "완료됨" "앱 아이콘 표시" "런처에 애플리케이션 아이콘 표시" - "사전 추가" + "사전 추가" "사전 사용 가능" - "사용할 수 있는 사전이 없습니다." "최종 업데이트" "설정" "삭제" - 버전 %1$s - "추가" + 버전 %1$s "사전에 추가" "단축키:" "언어:" "단어 입력" "선택적 단축키" "단어 수정" - "사용자 사전에 단어가 없습니다. 추가(+) 버튼을 탭하여 단어를 추가할 수 있습니다." "모든 언어" "더보기…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" @@ -121,7 +105,7 @@ 자동 교정 정확도 추천 실험적 기능 - %s분. + %s분. 클립보드 기록 활성화 스와이프 삭제 이모지 키 @@ -146,9 +130,7 @@ 시스템 설정에 따른 모양 한번에 많은 글자들을 선택하고 제거하기 위해서는 삭제 키를 스와이프하기 키의 경계 - 알파벳 (Workman) - %s (벵골어) - 알파벳 (Colemak Mod-DH) + %s (벵골어) "실행취소" "다시 실행" "사용자의 대화 내용과 입력한 데이터를 통해 단어 추천의 정확도를 개선합니다." diff --git a/app/src/main/res/values-ky/strings.xml b/app/src/main/res/values-ky/strings.xml index c038863d0..ae9b26f06 100644 --- a/app/src/main/res/values-ky/strings.xml +++ b/app/src/main/res/values-ky/strings.xml @@ -16,7 +16,7 @@ "Баскычтопту бөлүүнү иштетүү" "Башка киргзүү ыкмалрна которуу" "Тил которуштуруу баскычы" - "%sмсек." + "%sмсек." "Демейки тутум" "Сунуштар жана оңдоолор үчүн Байланыштардагы ысымдарды пайдалануу" "Жекечелештирилгн сунуштр" @@ -49,20 +49,9 @@ "Испанча (US)" "Хинглиш" "Сербче (Латын)" - "Англисче (UK) (%s)" - "Англисче (US) (%s)" - "Испанча (US) (%s)" - "Хинглиш (%s)" - "Сербче (%s)" - "%s (Салттык)" - "%s (Чакан)" - "Тил жок (Алфавит)" - "Алфавит (QWERTY)" - "Алфавит (QWERTZ)" - "Алфавит (AZERTY)" - "Алфавит (Dvorak)" - "Алфавит (Colemak)" - "Алфавит (PC)" + "%s (Салттык)" + "%s (Чакан)" + "Тил жок" "Эмодзи" "Кошуу" "Алып салуу" @@ -75,38 +64,33 @@ "Тышкы тергич үчүн быйтыкчалар" "Alt баскычы басылганда быйтыкчалар тактасы көрүнөт" "Демейки" - %s кош келиңиз\" + %s кош келиңиз\" "Жаңсап терүү менен" "Баштоо" - "Кийинки кадам" - %s орнотулууда\" - %s иштетүү\" - "Тилдер жана киргизүү жөндөөлөрүнөн \"%s\" колдонмосун караңыз. Ушуну менен аны түзмөгүңүздө иштете аласыз." - "%s мурунтан эле Тилдер жана киргизүү жөндөөлөрүндө иштетилгендиктен бул кадам аткарылды деп, кийинкисине өтө бериңиз!" + %s орнотулууда\" + %s иштетүү\" + "Тилдер жана киргизүү жөндөөлөрүнөн \"%s\" колдонмосун караңыз. Ушуну менен аны түзмөгүңүздө иштете аласыз." "Жөндөөлөрдөн иштетүү" - %s которулуу\" - "Андан соң, \"%s\" жигердүү текст киргизүү ыкмасы катары коюңуз." + %s которулуу\" + "Андан соң, \"%s\" жигердүү текст киргизүү ыкмасы катары коюңуз." "Киргизүү ыкмаларын которуштуруу" "Куттуктайбыз, бардыгы коюлду!" - "Эми бардык сүйүктүү колдонмолоруңузда %s менен тере аласыз." + "Эми бардык сүйүктүү колдонмолоруңузда %s менен тере аласыз." "Аяктады" "Колдонмонун сүрөтчөсүн көрсөтүү" "Колдонмонун сүрөтчөсү иштетүү тактасында көрүнөт" - "Кошумча сөздүктөр" + "Кошумча сөздүктөр" "Сөздүк бар" - "Сөздүктөр жок" "Акыркы жолу жаңыртылган" "Жөндөөлөр" "Жок кылуу" - "Версиясы %1$s" - "Кошуу" + "Версиясы %1$s" "Сөздүккө кошуу" "Кыска жол:" "Тил:" "Сөз териңиз" "Кошумча кыска жол" "Сөздү түзөтүү" - "Колдонуучу сөздүгүңүздө бир дагы сөз жок. Сөз кошуу үчүн кошуу (+) баскычын таптап коюңуз." "Бардык тилдер үчүн" "Дагы тилдер…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" diff --git a/app/src/main/res/values-lo/strings.xml b/app/src/main/res/values-lo/strings.xml index ad9fdad0f..f6938b8c1 100644 --- a/app/src/main/res/values-lo/strings.xml +++ b/app/src/main/res/values-lo/strings.xml @@ -17,7 +17,7 @@ "ເປີດ​ນຳ​ໃຊ້​ແປ້ນ​ພິມ​ແຍກ​ຕົວ" "ປ່ຽນໄປໃຊ້ການປ້ອນຂໍ້ມູນແບບອື່ນ" "ປຸ່ມປ່ຽນພາສາ" - "%sms" + "%sms" "ຄ່າເລີ່ມຕົ້ນຂອງລະບົບ" "ໃຊ້ຊື່ຈາກລາຍຊື່ຜູ່ຕິດຕໍ່ສຳລັບການແນະນຳ ແລະ ການຊ່ວຍແກ້ຄຳ" "ຄຳແນະນຳຕາມການນຳໃຊ້ຂອງທ່ານ" @@ -50,20 +50,9 @@ "ສະເປນ (ອາເມລິກາ)" "ຮິງ​ລິສ" "ເຊີ​ບຽນ (​ລາ​ຕິນ)" - "ອັງ​ກິດ (ສະ​ຫະ​ລາດ​ຊະ​ອາ​ນາ​ຈັກ) (%s)" - "ອັງ​ກິດ (ສະ​ຫະ​ລັດຯ) (%s)" - "ສະ​ແປນ​ນິດ (ສະ​ຫະ​ລັດຯ) (%s)" - "ຮິງ​ລິສ (%s)" - "ເຊີ​ບຽນ (%s)" - "%s (ດັ້ງ​ເດີມ)" - "%s (ກະ​ທັດ​ຮັດ)" - "ບໍ່ມີພາສາ (ໂຕອັກສອນ)" - "ໂຕອັກສອນ (QWERTY)" - "ໂຕອັກສອນ (QWERTZ)" - "ໂຕອັກສອນ (AZERTY)" - "ໂຕອັກສອນ (Dvorak)" - "ໂຕອັກສອນ (Colemak)" - "ໂຕອັກສອນ (PC)" + "%s (ດັ້ງ​ເດີມ)" + "%s (ກະ​ທັດ​ຮັດ)" + "ບໍ່ມີພາສາ" "ອີໂມຈິ" "ເພີ່ມ" "ລຶບອອກ" @@ -76,38 +65,33 @@ "Emoji ສຳ​ລັບ​ແປ້ນ​ພິມ​ແທ້" "ປຸ່ມ Alt ແທ້​ສະ​ແດງ​ແຜ່ນ​ຮອງ emoji" "ຄ່າເລີ່ມຕົ້ນ" - "ຍິນ​ດີ​ຕ້ອນ​ຮັບສູ່ %s" + "ຍິນ​ດີ​ຕ້ອນ​ຮັບສູ່ %s" "ດ້ວຍການພິມແບບ Gesture" "ເລີ່ມຕົ້ນ" - "ຂັ້ນຕອນຕໍ່ໄປ" - "ຕັ້ງຄ່າ %s" - "ເປີດນຳໃຊ້ %s" - "ກະລຸນາກວດເບິ່ງ \"%s\" ໃນການຕັ້ງຄ່າພາສາ ແລະ ການປ້ອນຂໍ້ມູນຂອງທ່ານ. ນີ້ຈະເປັນການອະນຸຍາດໃຫ້ມັນເຮັດວຽກໃນອຸປະກອນຂອງທ່ານ." - "%s ຖືກເປີດນຳໃຊ້ໃນການຕັ້ງຄ່າພາສາ ແລະ ການປ້ອນຂໍ້ມູນຂອງທ່ານແລ້ວ, ສະນັ້ນຂັ້ນຕອນນີ້ແມ່ນສຳເລັດໄປແລ້ວ. ໄປທີ່ຂັ້ນຕອນຕໍ່ໄປ!" + "ຕັ້ງຄ່າ %s" + "ເປີດນຳໃຊ້ %s" + "ກະລຸນາກວດເບິ່ງ \"%s\" ໃນການຕັ້ງຄ່າພາສາ ແລະ ການປ້ອນຂໍ້ມູນຂອງທ່ານ. ນີ້ຈະເປັນການອະນຸຍາດໃຫ້ມັນເຮັດວຽກໃນອຸປະກອນຂອງທ່ານ." "ເປີດນຳໃຊ້ໃນການຕັ້ງຄ່າ" - "ປ່ຽນເປັນ %s" - "ຕໍ່ໄປ, ເລືອກເອົາ \"%s\" ເປັນຮູບແບບການປ້ອນຂໍ້ມູນຂອງທ່ານ." + "ປ່ຽນເປັນ %s" + "ຕໍ່ໄປ, ເລືອກເອົາ \"%s\" ເປັນຮູບແບບການປ້ອນຂໍ້ມູນຂອງທ່ານ." "ປ່ຽນຮູບແບບການປ້ອນຂໍ້ມູນ" "ຍິນດີດ້ວຍ, ທ່ານເຮັດແລ້ວໆ!" - "ຕອນນີ້ທ່ານສາມາດພິມໃນແອັບຯທີ່ທ່ານມັກໄດ້ທຸກແອັບຯດ້ວຍ %s." + "ຕອນນີ້ທ່ານສາມາດພິມໃນແອັບຯທີ່ທ່ານມັກໄດ້ທຸກແອັບຯດ້ວຍ %s." "ສຳເລັດແລ້ວ" "ສະແດງໄອຄອນຂອງແອັບ" "ສະແດງໄອຄອນຂອງແອັບໃນ Launcher" - "ໂຕເສີມວັດຈະນານຸກົມ" + "ໂຕເສີມວັດຈະນານຸກົມ" "ມີວັດຈະນານຸກົມ" - "ບໍ່ມີວັດຈະນານຸກົມ" "ອັບເດດຫຼ້າສຸດ" "ການຕັ້ງຄ່າ" "ລຶບ" - "ເວີຊັນ %1$s" - "ເພີ່ມ" + "ເວີຊັນ %1$s" "ເພີ່ມໄປທີ່ວັດຈະນານຸກົມ" "ທາງລັດ:" "ພາສາ:" "ພິມ​ຄໍາ​ສັບ​ໃດ​ນຶ່ງ" "ຕົວເລືອກທາງລັດ" "ແກ້ໄຂຄຳສັບ" - "ທ່ານບໍ່ມີຄຳສັບໃດໆໃນວັດຈະນານຸກົມຜູ້ໃຊ້ເທື່ອ. ເພື່ອເພີ່ມຄຳສັບ, ໃຫ້ແຕະປຸ່ມເພີ່ມ (+)." "ສໍາ​ລັບ​ທຸກໆ​ພາ​ສາ" "ພາສາອື່ນໆ…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" diff --git a/app/src/main/res/values-lt/strings.xml b/app/src/main/res/values-lt/strings.xml index 2ba198735..8b9b803a8 100644 --- a/app/src/main/res/values-lt/strings.xml +++ b/app/src/main/res/values-lt/strings.xml @@ -16,7 +16,7 @@ "Įgalinti suskaidytą klaviatūrą" "Perj. į kt. įvesties būd." "Kalbos keitimo klavišas" - "%s ms" + "%s ms" "Sist. numat. nustat." "Siūlant ir taisant naudoti vardus iš „Kontaktų“" "Suasmeninti pasiūlymai" @@ -49,20 +49,9 @@ "Ispanų k. (JAV)" "Hindi ir anglų k. derinys" "Serbų k. (lot. rašmenys)" - "Anglų (JK) (%s)" - "Anglų (JAV) (%s)" - "Ispanų (JAV) (%s)" - "Hindi ir anglų derinys (%s)" - "Serbų k. (%s)" - "%s (tradicinė)" - "%s (kompaktiška)" - "Kalbos nėra (abėcėlė)" - "Abėcėlė (QWERTY)" - "Abėcėlė (QWERTZ)" - "Abėcėlė (AZERTY)" - "Abėcėlė (Dvorako)" - "Abėcėlė („Colemak“)" - "Abėcėlė (PC)" + "%s (tradicinė)" + "%s (kompaktiška)" + "Kalbos nėra" "Jaustukai" "Pridėti" "Pašalinti" @@ -75,40 +64,35 @@ "Fizinės klaviatūros jaustukai" "Paspaudus fizinį klavišą „Alt“ rodoma jaustukų paletė" "Numatytieji" - "Sveiki! Tai „%s“" + "Sveiki! Tai „%s“" "naudojant įvestį gestais" "Pradėti" - "Kitas veiksmas" - "„%s“ sąranka" - "Įgalinkite „%s“" - Skiltyje „Kalbos ir įvesties nustatymai“ žr. %s“. Programa bus įgalinta veikti įrenginyje.\" - "„%s“ jau įgalinta jūsų „Kalbos ir įvesties nustatymuose“, todėl šis veiksmas yra atliktas. Galite pereiti prie kito!" + "„%s“ sąranka" + "Įgalinkite „%s“" + Skiltyje „Kalbos ir įvesties nustatymai“ žr. %s“. Programa bus įgalinta veikti įrenginyje.\" "Įgalinti nustatymuose" - "Perjungimas į „%s“" - Toliau pasirinkite %s“ kaip aktyvų teksto įvesties metodą.\" + "Perjungimas į „%s“" + Toliau pasirinkite %s“ kaip aktyvų teksto įvesties metodą.\" "Perjungti įvesties metodus" "Sveikiname, viską nustatėte!" - "Dabar galite įvesti visas mėgstamas programas naudodami „%s“." + "Dabar galite įvesti visas mėgstamas programas naudodami „%s“." "Baigta" "Rodyti programos piktogramą" "Pateikti programos piktogramą paleidimo priemonėje" - "Papildomi žodynai" + "Papildomi žodynai" "Galimas žodynas" - "Nėra galimų žodynų" "Paskutinį kartą atnaujinta" "Nustatymai" "Ištrinti" - - "%1$s versija" - "Pridėti" + "%1$s versija" "Pridėti prie žodyno" "Spartusis klavišas:" "Kalba:" "Įveskite žodį" "Pasirenkamasis spartusis klavišas" "Redaguoti žodį" - "Neturite jokių žodžių naudotojo žodyne. Kad pridėtumėte žodį, palieskite mygtuką „Pridėti“ (+)." "Visos kalbos" "Daugiau kalbų…" " AĄBCČDEĘĖFGHIĮYJKLMNOPRSŠTUŲŪVZŽ" @@ -125,4 +109,4 @@ "Paieška" "Pris." "Lauk." - \ No newline at end of file + diff --git a/app/src/main/res/values-lv/strings.xml b/app/src/main/res/values-lv/strings.xml index 92516e306..075eb6792 100644 --- a/app/src/main/res/values-lv/strings.xml +++ b/app/src/main/res/values-lv/strings.xml @@ -8,7 +8,7 @@ "Vibrēt, nospiežot taustiņu" "Skaņa, nospiežot taustiņu" "Parādās, nospiežot taustiņu" - "Preferences" + Iestatījumi "Ievadīt ar žestiem" "Teksta korekcija" "Papildu" @@ -16,14 +16,14 @@ "Iespējot dalīto tastatūru" "Pārsl. uz citām iev. met." "Valodas pārslēgšanas taustiņš" - "%s ms" + "%s ms" "Sistēmas noklusējums" "Izmantot kontaktpersonu vārdus kā ieteikumus un labojumus" "Personalizēti ieteikumi" "Dubultpiesk. = punkts" - "Divreiz pieskaroties atst. taustiņam, ievada punktu un atstarpi." + Divreiz piesitot atstarpes taustiņu, ievada punktu un atstarpi pēc tā "Automātiska lielo burtu lietošana" - "Katra teikuma pirmo vārdu rakstīt ar lielo burtu." + Automātiski sākt rakstīt teikumu ar lielo burtu "Personiskā vārdnīca" "Galvenā vārdnīca" "Rādīt labojumu ieteikumus" @@ -49,20 +49,9 @@ "Spāņu (ASV)" "Hindi–angļu valoda" "Serbu (latīņu)" - "Angļu (Lielbritānija) (%s)" - "Angļu (ASV) (%s)" - "Spāņu (ASV) (%s)" - "Hindi–angļu valoda (%s)" - "Serbu (%s)" - "%s (tradicionālā)" - "%s (kompaktā)" - "Nav valodas (alfabēts)" - "Alfabēts (QWERTY)" - "Alfabēts (QWERTZ)" - "Alfabēts (AZERTY)" - "Alfabēts (Dvorak)" - "Alfabēts (Colemak)" - "Alfabēts (PC)" + "%s (tradicionālā)" + "%s (kompaktā)" + "Nav valodas" "Japāņu emocijzīmes" "Pievienot" "Noņemt" @@ -75,38 +64,33 @@ "Emocijzīmes fiziskajai tastatūrai" "Nospiežot taustiņu Alt, tiek parādīta emocijzīmju palete." "Noklusējums" - "Laipni lūdzam pakalpojumā %s," + "Laipni lūdzam pakalpojumā %s," "kurā varat izmantot ievadi ar žestiem" "Sākt darbu" - "Nākamā darbība" - "Lietojumprogrammas %s iestatīšana" - "Lietojumprogrammas %s iespējošana" - Valodu un ievades iestatījumos atzīmējiet lietotni %s”, autorizējot tās palaišanu savā ierīcē.\" - "Tā kā lietotne %s jau ir iespējota valodu un ievades iestatījumos, šī darbība ir pabeigta. Veiciet nākamo darbību!" + "Lietojumprogrammas %s iestatīšana" + "Lietojumprogrammas %s iespējošana" + Valodu un ievades iestatījumos atzīmējiet lietotni %s”, autorizējot tās palaišanu savā ierīcē.\" "Iespējot iestatījumos" - "Pārslēgšanās uz lietojumprogrammu %s" - Pēc tam atlasiet %s” kā aktīvo ievades metodi.\" + "Pārslēgšanās uz lietojumprogrammu %s" + Pēc tam atlasiet %s” kā aktīvo ievades metodi.\" "Pārslēgt ievades metodes" "Gatavs!" - "Izmantojot lietojumprogrammu %s, varat rakstīt visās iecienītākajās lietotnēs." + "Izmantojot lietojumprogrammu %s, varat rakstīt visās iecienītākajās lietotnēs." "Pabeigts" "Rādīt lietotnes ikonu" "Rādīt palaidēja ekrānā lietojumprogrammas ikonu" - "Papildināmas vārdnīcas" + "Papildināmas vārdnīcas" "Vārdnīca ir pieejama" - "Vārdn. nav pieejamas" "Pēdējo reizi atjaunināts" "Iestatījumi" "Dzēst" - "Versija %1$s" - "Pievienot" + "Versija %1$s" "Pievienot vārdnīcai" "Saīsne:" "Valoda:" "Ierakstiet vārdu." "Izvēles saīsne" "Vārda rediģēšana" - "Lietotāja vārdnīcā nav neviena vārda. Lai pievienotu vārdu, pieskarieties pogai Pievienot (+)." "Visās valodās" "Citas valodas…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" @@ -123,4 +107,14 @@ "Meklēt" "Pauze" "Gaidīt" - \ No newline at end of file + HeliBoard pareizrakstības pārbaudītājs + HeliBoard iestatījumi + HeliBoard pareizrakstības pārbaudītāja iestatījumi + Ieteikumi + Ievade + Papildus taustiņi + Starpliktuves vēsture + Labojumi + Atstarpe + Vibrēt \"Netraucēt\" režīmā + diff --git a/app/src/main/res/values-mk/strings.xml b/app/src/main/res/values-mk/strings.xml index d2bd41b24..4c8bf334e 100644 --- a/app/src/main/res/values-mk/strings.xml +++ b/app/src/main/res/values-mk/strings.xml @@ -16,7 +16,7 @@ "Овозможи поделена тастатура" "Префрли на други влезни методи" "Копче за промена на јазик" - "%s ms" + "%s ms" "Стандардно за системот" "Употреби имиња од Контакти за предлози и корекции" "Персонализирани предлози" @@ -49,20 +49,9 @@ "шпански (САД)" "Хинглиш" "Српски (латиница)" - "англиски (ОК) (%s)" - "англиски (САД) (%s)" - "шпански (САД) (%s)" - "Хинглиш (%s)" - "Српски (%s)" - "%s (традиционален)" - "%s (Компактна)" - "Нема јазик (азбука)" - "Азбука (QWERTY)" - "Азбука (QWERTZ)" - "Азбука (AZERTY)" - "Азбука (Dvorak)" - "Азбука (Colemak)" - "Азбука (PC)" + "%s (традиционален)" + "%s (Компактна)" + "Нема јазик" "Емотикони" "Додај" "Отстрани" @@ -75,38 +64,33 @@ "Емотикони за физичка тастатура" "Физичкото копче Alt ја прикажува палетата емотикони" "Стандардно" - "Добре дојдовте во %s" + "Добре дојдовте во %s" "со Пишување со движење" "Започнете" - "Следен чекор" - "Се поставува %s" - "Овозможи %s" - Означете ја апликацијата %s“ во поставките за Јазици и внесување. Со тоа ќе авторизирате да се активира на уредот.\" - "%s веќе е овозможена во поставките за Jазици и внесување, така што завршивте со овој чекор. Одете на следниот." + "Се поставува %s" + "Овозможи %s" + Означете ја апликацијата %s“ во поставките за Јазици и внесување. Со тоа ќе авторизирате да се активира на уредот.\" "Овозможи во Поставки" - "Префрлете се на %s" - Следно, изберете %s“ како активен метод за внесување текст.\" + "Префрлете се на %s" + Следно, изберете %s“ како активен метод за внесување текст.\" "Префрли се помеѓу методи на влез" "Честитки, завршивте!" - "Сега може да ги впишете сите омилени апликации со %s." + "Сега може да ги впишете сите омилени апликации со %s." "Завршено" "Покажи икона на апликација" "Прикажи икона на апликација во стартувачот" - "Додатоци за речници" + "Додатоци за речници" "Речникот е достапен" - "Нема достапен речник" "Последен пат ажурирано" "Поставки" "Избриши" - "Верзија %1$s" - "Додај" + "Верзија %1$s" "Додај во речник" "Кратенка:" "Јазик:" "Внесете збор" "Изборна кратенка" "Измени збор" - "Немате зборови во корисничкиот речник. За да додадете збор, допрете го копчето Додај (+)." "За сите јазици" "Повеќе јазици…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" @@ -123,4 +107,4 @@ "Барај" "Пауза" "Чекај" - \ No newline at end of file + diff --git a/app/src/main/res/values-ml/strings.xml b/app/src/main/res/values-ml/strings.xml index 72c161fc6..6b1716477 100644 --- a/app/src/main/res/values-ml/strings.xml +++ b/app/src/main/res/values-ml/strings.xml @@ -16,7 +16,7 @@ "സ്‌പ്‌ലിറ്റ് കീബോർഡ് പ്രവർത്തനക്ഷമമാക്കുക" "മറ്റു ടൈപ്പുചെയ്യൽ രീതികളിലേക്ക് മാറുക" "ഭാഷ മാറൽ കീ" - "%sമി.സെ" + "%sമി.സെ" "സ്ഥിരമായ സിസ്റ്റം" നിർദ്ദേശങ്ങൾക്കും തിരുത്തലുകൾക്കുമായി കോൺടാക്‌റ്റുകളിൽ നിന്നുള്ള പേരുകൾ ഉപയോഗിക്കുക "വ്യക്തിഗത നിർദ്ദേശങ്ങൾ" @@ -49,20 +49,9 @@ "സ്‌പാനിഷ് (യുഎസ്)" "ഹിംഗ്ലീഷ്" "സെർബിയൻ (ലാറ്റിൻ)" - ഇംഗ്ലീഷ് (യുകെ) (%s) - ഇംഗ്ലീഷ് (യുഎസ്) (%s) - സ്‌പാനിഷ് (യുഎസ്) (%s) - ഹിംഗ്ലീഷ് (%s) - സെർബിയൻ (%s) - %s (പരമ്പരാഗതം) - %s (കോം‌പാക്‌ട്) - "ഭാഷയില്ല (അക്ഷരമാല)" - "അക്ഷരമാല (QWERTY)" - "അക്ഷരമാല (QWERTZ)" - "അക്ഷരമാല (AZERTY)" - "അക്ഷരമാല (Dvorak)" - "അക്ഷരമാല (Colemak)" - "അക്ഷരമാല (PC)" + %s (പരമ്പരാഗതം) + %s (കോം‌പാക്‌ട്) + "ഭാഷയില്ല" "ഇമോജി" "ചേര്‍ക്കുക" "നീക്കംചെയ്യുക" @@ -75,38 +64,33 @@ "പ്രത്യക്ഷ കീബോഡിനുള്ള ഇമോജി" "പ്രത്യക്ഷ Alt കീ ഇമോജി പാലറ്റിനെ കാണിക്കുന്നു" "സ്ഥിരമായത്" - %s എന്നതിലേക്ക് സ്വാഗതം + %s എന്നതിലേക്ക് സ്വാഗതം "വിരൽചലിത ടൈപ്പിംഗിനൊപ്പം" "ആരംഭിക്കുക" - "അടുത്ത ചുവട്" - %s സജ്ജമാക്കുന്നു - %s പ്രവർത്തനക്ഷമമാക്കുക - ഭാഷയും ഇൻപുട്ടും ക്രമീകരണത്തിൽ \"%s\" ചെക്കുചെയ്യുക. ചെക്കുചെയ്യുന്നത് ഉപകരണത്തിൽ പ്രവർത്തിക്കാൻ ഇതിന് അംഗീകാരം നൽകും. - ഭാഷയും ഇൻപുട്ടും ക്രമീകരണത്തിൽ ഇതിനകം തന്നെ %s പ്രവർത്തനക്ഷമമാക്കിയതിനാൽ ഈ ഘട്ടം പൂർത്തിയായി. അടുത്ത ഘട്ടത്തിലേക്ക് പോകുക! + %s സജ്ജമാക്കുന്നു + %s പ്രവർത്തനക്ഷമമാക്കുക + ഭാഷയും ഇൻപുട്ടും ക്രമീകരണത്തിൽ \"%s\" ചെക്കുചെയ്യുക. ചെക്കുചെയ്യുന്നത് ഉപകരണത്തിൽ പ്രവർത്തിക്കാൻ ഇതിന് അംഗീകാരം നൽകും. "ക്രമീകരണങ്ങളിൽ പ്രവർത്തനക്ഷമമാകുക" - %s എന്നതിലേക്ക് മാറുക - അടുത്തത്, \"%s\" എന്നതിനെ നിങ്ങളുടെ സജീവ വാചക-ടൈപ്പുചെയ്യൽ രീതിയായി തിരഞ്ഞെടുക്കുക. + %s എന്നതിലേക്ക് മാറുക + അടുത്തത്, \"%s\" എന്നതിനെ നിങ്ങളുടെ സജീവ വാചക-ടൈപ്പുചെയ്യൽ രീതിയായി തിരഞ്ഞെടുക്കുക. "ടൈപ്പുചെയ്യൽ രീതികൾ മാറുക" "അഭിനന്ദനങ്ങൾ, നിങ്ങൾ എല്ലാം പൂർത്തിയാക്കി!" - %s ഉപയോഗിച്ച് നിങ്ങളുടെ പ്രിയപ്പെട്ട എല്ലാ അപ്ലിക്കേഷനുകളിലും ഇപ്പോൾ ടൈപ്പുചെയ്യാനാകും. + %s ഉപയോഗിച്ച് നിങ്ങളുടെ പ്രിയപ്പെട്ട എല്ലാ അപ്ലിക്കേഷനുകളിലും ഇപ്പോൾ ടൈപ്പുചെയ്യാനാകും. "പൂർത്തിയായി" "അപ്ലിക്കേഷൻ ഐക്കൺ കാണിക്കുക" "ലോഞ്ചറിൽ അപ്ലിക്കേഷൻ ഐക്കൺ പ്രദർശിപ്പിക്കുക" - "ആഡ്-ഓൺ നിഘണ്ടുക്കൾ" + "ആഡ്-ഓൺ നിഘണ്ടുക്കൾ" "നിഘണ്ടു ലഭ്യമാണ്" - "നിഘണ്ടുക്കളൊന്നും ലഭ്യമല്ല" "അവസാനം അപ്ഡേറ്റുചെയ്തത്" "ക്രമീകരണം" "ഇല്ലാതാക്കുക" - വേർഷൻ %1$s - "ചേര്‍ക്കുക" + വേർഷൻ %1$s "നിഘണ്ടുവിൽ ചേർക്കുക" "കുറുക്കുവഴി:" "ഭാഷ:" "ഒരു പദം ടൈപ്പുചെയ്യുക" "ഓപ്‌ഷണൽ കുറുക്കുവഴി" "പദം എഡിറ്റുചെയ്യുക" - "ഉപയോക്തൃ നിഘണ്ടുവിൽ നിങ്ങൾക്ക് പദങ്ങളൊന്നുമില്ല. ഒരു പദം ചേർക്കുന്നതിന്, ചേർക്കുക (+) ബട്ടൺ ടാപ്പ് ചെയ്യുക." "എല്ലാ ഭാഷകൾക്കുമായി" "കൂടുതൽ ഭാഷകൾ…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" @@ -134,14 +118,12 @@ രൂപഭാവം സിസ്റ്റം ക്രമീകരണങ്ങൾ പിന്തുടരും കീ അതിരുകൾ ഓട്ടോ പകൽ/രാത്രി മോഡ് - %sമിനിറ്റ് . + %sമിനിറ്റ് . വിരാമചിഹ്നത്തിന് ശേഷം ഒരു പുതിയ വാക്ക് ടൈപ്പുചെയ്യുമ്പോൾ സ്വയം സ്പേസ് ചേർക്കുക സ്പേസ് കീ ദീർഘനേരം അമർത്തുന്നത് ഇൻപുട്ട് രീതി തിരഞ്ഞെടുക്കൽ മെനു പ്രദർശിപ്പിക്കും കീബോർഡ് ഉയരം സ്കെയിൽ - അക്ഷരമാല (Colemak Mod-DH) - അക്ഷരമാല (ജോലിക്കാരൻ) വിരാമചിഹ്നത്തിനു ശേഷമുള്ള ഓട്ടോസ്പേസ് - %s (അഖോർ ) + %s (അഖോർ ) പരീക്ഷണാത്മകം ഇൻപുട്ട് അധിക കീകൾ diff --git a/app/src/main/res/values-mn/strings.xml b/app/src/main/res/values-mn/strings.xml index 6ab815798..091866816 100644 --- a/app/src/main/res/values-mn/strings.xml +++ b/app/src/main/res/values-mn/strings.xml @@ -16,7 +16,7 @@ "Хуваагдмал гарыг идэвхжүүлэх" "Оруулах өөр арга руу шилжүүлэх" "Хэл солих товч" - "%sмс" + "%sмс" "Системийн өгөгдмөл" "Санал болгох, залруулахда Харилцагчдын нэрсээс ашиглах" "Хувийн тохиргоотой зөвлөмжүүд" @@ -49,20 +49,9 @@ "Испани (АНУ)" "Хинглиш" "Серьби хэл (латин)" - "Англи (ИБ) ( %s )" - "Англи (АНУ) ( %s )" - "Испани (АНУ-ын) (%s)" - "Хинглиш (%s)" - "Серьби хэл (%s)" - "%s (уламжлалт)" - "%s (Компакт)" - "Хэл байхгүй (Цагаан толгой)" - "Цагаан толгой (QWERTY)" - "Цагаан толгой (QWERTZ)" - "Цагаан толгой (AZERTY)" - "Цагаан толгой (Dvorak)" - "Цагаан толгой (Colemak)" - "Цагаан толгой (PC)" + "%s (уламжлалт)" + "%s (Компакт)" + "Хэл байхгүй" "Инээмсэглэл" "Нэмэх" "Устгах" @@ -75,38 +64,33 @@ "Бодит гарт зориулсан эможи" "Бодит Alt товчлуур нь эможи палитрыг харуулдаг" "Үндсэн" - "Та %s-д тавтай морилно уу" + "Та %s-д тавтай морилно уу" "Зангаагаар бичихээр" "Эхлэх" - "Дараагийн алхам" - %s-г тохируулж байна\" - %s-г идэвхжүүлэх\" - "Хэл, оролтын тохиргоо хэсгээс \"%s\"-г сонгоно уу. Ингэснээр үүнийг таны төхөөрөмжид ажиллах зөвшөөрлийг өгөх болно." - "%s-г Хэл, оролтын тохиргоонд аль хэдийн идэвхжүүлснээр энэ алхам дууслаа. Дараагийн алхмыг хийцгээе!" + %s-г тохируулж байна\" + %s-г идэвхжүүлэх\" + "Хэл, оролтын тохиргоо хэсгээс \"%s\"-г сонгоно уу. Ингэснээр үүнийг таны төхөөрөмжид ажиллах зөвшөөрлийг өгөх болно." "Тохиргоо дотроос идэвхжүүлэх" - %s рүү шилжих\" - "Дараа нь \"%s\"-г өөрийн идэвхтэй текст-оруулах аргаар сонгоно уу." + %s рүү шилжих\" + "Дараа нь \"%s\"-г өөрийн идэвхтэй текст-оруулах аргаар сонгоно уу." "Оруулах аргыг солих" "Баяр хүргэе, та бүгдийг нь тохируулчихлаа!" - "Та одоо өөрийн дуртай апп-ууд дотроо %s ашиглан бичих болохоор боллоо." + "Та одоо өөрийн дуртай апп-ууд дотроо %s ашиглан бичих болохоор боллоо." "Дууссан" "Апп дүрсийг харуулах" "Эхлүүлэгч дээр аппликейшний дүрсийг харуулах" - "Нэмэлт толь бичгүүд" + "Нэмэлт толь бичгүүд" "Толь бичиг байна" - "Толь бичиг байхгүй" "Сүүлд шинэчлэгдсэн" "Тохиргоо" "Устгах" - "Хувилбар %1$s" - "Нэмэх" + "Хувилбар %1$s" "Толь бичигт нэмэх" "Товчилбор:" "Хэл:" "Үг оруулна уу" "Зайлшгүй биш товчилбор" "Үг засах" - "Таны хэрэглэгчийн толь бичигт ямар ч үг байхгүй байна. Үг нэмэхийн тулд Нэмэх (+) товчлуурыг дарна уу." "Бүх хэлэнд" "Өөр хэлүүд…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" diff --git a/app/src/main/res/values-mr/strings.xml b/app/src/main/res/values-mr/strings.xml index 154a9169d..475179769 100644 --- a/app/src/main/res/values-mr/strings.xml +++ b/app/src/main/res/values-mr/strings.xml @@ -16,7 +16,7 @@ "विभाजित कीबोर्ड सुरू करा" "अन्य इनपुट पद्धतींवर स्विच करा" "भाषा स्विच की" - "%sमिसे" + "%sमिसे" "सिस्टम डीफॉल्ट" "सूचनांसाठी आणि सुधारणांसाठी संपर्कांमधील नावे वापरा" "पर्सनलाइझ केलेल्या सूचना" @@ -49,20 +49,9 @@ "स्पॅनिश (यूएस)" "हिंग्लिश" "सर्बियन (लॅटिन)" - "इंग्रजी (यूके) (%s)" - "इंग्रजी (यूएस) (%s)" - "स्पॅनिश (यूएस) (%s)" - "हिंग्लिश (%s)" - "सर्बियन (%s)" - "%s (पारंपारिक)" - "%s (संक्षिप्त)" - "भाषा नाही (वर्णमाला)" - "वर्णमाला (QWERTY)" - "वर्णमाला (QWERTZ)" - "वर्णमाला (AZERTY)" - "वर्णमाला (ड्व्होरॅक)" - "वर्णमाला (कोलमॅक)" - "वर्णमाला (PC)" + "%s (पारंपारिक)" + "%s (संक्षिप्त)" + "भाषा नाही" "इमोजी" "जोडा" "काढा" @@ -75,38 +64,33 @@ "वास्तविक कीबोर्डसाठी इमोजी" "वास्तविक Alt की इमोजी पॅलेट दर्शविते" "डीफॉल्ट" - %s वर स्वागत आहे\" + %s वर स्वागत आहे\" "जेश्चर टायपिंग करून" "सुरू करा" - "पुढील चरण" - %s सेट अप करत आहे\" - %s सुरू करा\" - "कृपया आपल्या भाषांमध्ये आणि इनपुट सेटिंग्जमध्ये \"%s\" तपासा. आपल्या डिव्हाइसवर चालण्यासाठी त्यास हे अधिकृत करेल." - "%s आपल्या भाषांमध्ये आणि इनपुट सेटिंग्जमध्ये आधीपासून सक्षम केला आहे, त्यामुळे हे चरण पूर्ण झाले आहे. पुढील चरणावर!" + %s सेट अप करत आहे\" + %s सुरू करा\" + "कृपया आपल्या भाषांमध्ये आणि इनपुट सेटिंग्जमध्ये \"%s\" तपासा. आपल्या डिव्हाइसवर चालण्यासाठी त्यास हे अधिकृत करेल." "सेटिंग्जमध्ये सुरू करा" - %s वर स्विच करा\" - "पुढे, तुमची सक्रिय मजकूर-इनपुट पद्धत म्हणून \"%s\" निवडा." + %s वर स्विच करा\" + "पुढे, तुमची सक्रिय मजकूर-इनपुट पद्धत म्हणून \"%s\" निवडा." "इनपुट पद्धती स्विच करा" "अभिनंदन, आता तुम्ही तयार आहात!" - "आता तुम्ही %s सह आपल्या सर्व आवडत्या अॅप्समध्ये टाइप करू शकता." + "आता तुम्ही %s सह आपल्या सर्व आवडत्या अॅप्समध्ये टाइप करू शकता." "समाप्त" "अ‍ॅप आयकन दर्शवा" "लाँचर मध्ये ॲप्लिकेशन आयकन दाखवा" - "ॲड-ऑन शब्दकोश" + "ॲड-ऑन शब्दकोश" "शब्दकोश उपलब्ध" - "कोणतेही शब्दकोश उपलब्ध नाहीत" "अंतिम अपडेट" "सेटिंग्ज" "हटवा" - "आवृत्ती %1$s" - "जोडा" + "आवृत्ती %1$s" "डिक्शनरीत जोडा" "शॉर्टकट:" "भाषा:" "एक शब्द टाईप करा" "पर्यायी शॉर्टकट" "शब्द संपादित करा" - "वापरकर्ता डिक्शनरीमध्ये तुमच्याकडे कोणतेही शब्द नाहीत. एखादा शब्द जोडण्यासाठी, जोडा (+) बटणावर टॅप करा." "सर्व भाषांसाठी" "अधिक भाषा…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" diff --git a/app/src/main/res/values-ms/strings.xml b/app/src/main/res/values-ms/strings.xml index 11126791c..152ce36dc 100644 --- a/app/src/main/res/values-ms/strings.xml +++ b/app/src/main/res/values-ms/strings.xml @@ -17,7 +17,7 @@ "Dayakan papan kekunci terpisah" "Tukar ke kaedah input lain" "Kekunci tukar bahasa" - "%sms" + "%sms" "Tetapan asal sistem" "Menggunakan nama daripada Kenalan untuk cadangan dan pembetulan" "Cadangan diperibadikan" @@ -50,20 +50,9 @@ "Bahasa Sepanyol (AS)" "Hinglish" "Bahasa Serbia (Latin)" - "Bahasa Inggeris (UK) (%s)" - "Bahasa Inggeris (AS) (%s)" - "Bahasa Sepanyol (AS) (%s)" - "Hinglish (%s)" - "Bahasa Serbia (%s)" - "%s (Tradisional)" - "%s (Sarat)" - "Tiada bahasa (Abjad)" - "Abjad (QWERTY)" - "Abjad (QWERTZ)" - "Abjad (AZERTY)" - "Abjad (Dvorak)" - "Abjad (Colemak)" - "Abjad (PC)" + "%s (Tradisional)" + "%s (Sarat)" + "Tiada bahasa" "Emoji" "Tambah" "Alih Keluar" @@ -76,38 +65,33 @@ "Emoji untuk papan kekunci fizikal" "Kekunci Alt fizikal menunjukkan palet emoji" "Lalai" - "Selamat datang ke %s" + "Selamat datang ke %s" "dengan Taipan Gerak Isyarat" "Bermula" - "Langkah seterusnya" - "Menyediakan %s" - "Dayakan %s" - "Sila tandai \"%s\" dalam tetapan Bahasa & input anda. Tindakan ini akan membenarkan apl itu dijalankan pada peranti anda." - "%s sudah didayakan dalam tetapan Bahasa & input anda, jadi langkah ini telah selesai. Beralih ke langkah seterusnya!" + "Menyediakan %s" + "Dayakan %s" + "Sila tandai \"%s\" dalam tetapan Bahasa & input anda. Tindakan ini akan membenarkan apl itu dijalankan pada peranti anda." "Dayakan dalam Tetapan" - "Beralih ke %s" - "Seterusnya, pilih \"%s\" sebagai kaedah input teks aktif anda." + "Beralih ke %s" + "Seterusnya, pilih \"%s\" sebagai kaedah input teks aktif anda." "Tukar kaedah input" "Tahniah, anda sudah sedia!" - "Kini anda boleh menaip dalam semua apl kegemaran anda dengan %s." + "Kini anda boleh menaip dalam semua apl kegemaran anda dengan %s." "Selesai" "Tunjukkan ikon apl" "Paparkan ikon apl dalam pelancar" - "Kamus tambahan" + "Kamus tambahan" "Kamus tersedia" - "Tiada kamus tersedia" "Kali terakhir dikemas kini" "Tetapan" "Padam" - "Versi %1$s" - "tambah" + "Versi %1$s" "Tambah ke kamus" "Pintasan:" "Bahasa:" "Taip perkataan" "Pintasan pilihan" "Edit perkataan" - "Anda tiada sebarang perkataan dalam kamus pengguna. Untuk menambahkan perkataan, ketik butang Tambah (+)." "Untuk semua bahasa" "Lebih banyak bahasa…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" diff --git a/app/src/main/res/values-my/strings.xml b/app/src/main/res/values-my/strings.xml index c9c82653a..c12da3e83 100644 --- a/app/src/main/res/values-my/strings.xml +++ b/app/src/main/res/values-my/strings.xml @@ -16,7 +16,7 @@ "ကီးဘုတ် ခွဲခြမ်းမှု ဖွင့်ထားရန်" "အခြားထည့်သွင်းမည့် နည်းလမ်းများသို့ ပြောင်းရန်" "ဘာသာစကား ပြောင်းခလုတ်" - "%sms" + "%sms" "စနစ်ပုံသေ" "အကြံပြုချက်များနှင့် အမှားပြင်ခြင်းများအတွက် အဆက်သွယ်မှ အမည်များ အသုံးပြုမည်" "ကိုယ်ရေးကိုယ်တာ အကြံပြုချက်များ" @@ -49,20 +49,9 @@ "စပိန် (ယူအက်စ်)" "ဟင်ဂလိပ်" "ဆားဘီယား (လက်တင်)" - "အင်္ဂလိပ် (ယူကေ) (%s)" - "အင်္ဂလိပ် (ယူအက်စ်) (%s)" - "စပိန် (ယူအက်စ်) (%s)" - "ဟင်ဂလိပ် (%s)" - "ဆားဘီယား (%s)" - "%s (ရိုးရာ)" - "%s (ကျစ်လစ်သော)" - "ဘာသာစကားမရှိ (ဗျည်းအက္ခရာ)" - "ဗျည်းအက္ခရာ (ကွာတီ)" - "ဗျည်းအက္ခရာ (ကွာတီ)" - "ဗျည်း (အဇာတည်)" - "ဗျည်းအက္ခရာ (ဒီဘိုရခ်)" - "ဗျည်းအက္ခရာ (ကိုလ်မာ့ခ်)" - "ဗျည်း (PC)" + "%s (ရိုးရာ)" + "%s (ကျစ်လစ်သော)" + "ဘာသာစကားမရှိ" "အီမိုဂျီ" "ထည့်ရန်" "ဖယ်ရှားပါ" @@ -75,38 +64,33 @@ "ခလုတ်ရှိ ကီးဘုတ်အတွက် အီမိုဂျိ" "အီမိုဂျီ ဘုတ်ပြားပြသော Alt ခလုတ်" "ပုံသေ" - %s မှကြိုဆိုပါသည်\" + %s မှကြိုဆိုပါသည်\" "အမူယာ ရိုက်ခြင်းဖြင့်" "စတင်ပါတော့" - "နောက်တစ်ဆင့်" - %s တပ်ဆင်ရန်\" - %s ဖွင့်ရန်\" - "\"%s\" ကို ဘာသာစကားနှင့် စာရိုက်စနစ်တွင် စစ်ပါ။ ဤသို့ဖြင့် သင့်စက်ပစ္စည်းပေါ်တွင် ၎င်းကိုဖွင့်ရန်အတည်ပြုပေးပါလိမ့်မည်။" - "%s ကို သင့်ဘာသာစကားနှင့် စာရိုက်စနစ်ဆက်တင်များတွင် ဖွင့်ထားပြီးဖြစ်၍ ဤအဆင့်ပြီးပါပြီ။ နောက်တစ်ခုသို့ သွားပါ။" + %s တပ်ဆင်ရန်\" + %s ဖွင့်ရန်\" + "\"%s\" ကို ဘာသာစကားနှင့် စာရိုက်စနစ်တွင် စစ်ပါ။ ဤသို့ဖြင့် သင့်စက်ပစ္စည်းပေါ်တွင် ၎င်းကိုဖွင့်ရန်အတည်ပြုပေးပါလိမ့်မည်။" "ဆက်တင်များတွင် ဖွင့်ရန်" - %s သို့ပြောင်းမည်\" - "ရှေ့၊ \"%s\" အားသင်၏ ပွင့်နေသည့်ထည့်သွင်းမှု နည်းလမ်းအဖြစ်ရွေးပါ။" + %s သို့ပြောင်းမည်\" + "ရှေ့၊ \"%s\" အားသင်၏ ပွင့်နေသည့်ထည့်သွင်းမှု နည်းလမ်းအဖြစ်ရွေးပါ။" "စာရိုက်သွင်းမှုနည်းလမ်း ပြောင်းရန်" "ဝမ်းသာပါသည်၊ သင်အားလုံးသတ်မှတ်ပြီးပါပြီ!" - "%s ဖြင့်သင့် ကြိုက်နှစ်သက်ရာ အပလီကေးရှင်းများအားလုံးအား ရိုက်ထည့်နိုင်ပါပြီ။" + "%s ဖြင့်သင့် ကြိုက်နှစ်သက်ရာ အပလီကေးရှင်းများအားလုံးအား ရိုက်ထည့်နိုင်ပါပြီ။" "ပြီးဆုံးသွားပြီ" "အက်ပ်သင်္ကေတပြခြင်း" "launcher တွင် အပလီကေးရှင်း သင်္ကေတကိုပြရန်" - "ပေါင်းထည့်ထားသည့် အဘိဓါန်များ" + "ပေါင်းထည့်ထားသည့် အဘိဓါန်များ" "အဘိဓါန်ရရှိနိုင်" - "အဘိဓါန်မရှိ" "နောက်ဆုံး အသစ်မွမ်းမံမှု" "ဆက်တင်များ" "ဖျက်ရန်" - "ဗားရှင်း %1$s" - "ထည့်ရန်" + "ဗားရှင်း %1$s" "အဘိဓာန်ထဲ ထည့်ပါ" "အတိုကောက်:" "ဘာသာစကား:" "စကားလုံးတစ်လုံး ရိုက်ပါ" "ရွေးစရာအတိုကောက်" "စာလုံးကို ပြင်ဆင်မည်" - "အသုံးပြုသူ အဘိဓာန်တွင် မည်သည့်စကားလုံးမျှ မရှိပါ။ စကားလုံးကိုပေါင်းထည့်ရန် (+) ခလုတ် ကိုတို့ပါ။" "ဘာသာစကားအားလုံးအတွက်" "ဘာသာစကားပိုများများ…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" diff --git a/app/src/main/res/values-nb/strings.xml b/app/src/main/res/values-nb/strings.xml index b881f5837..50aaba246 100644 --- a/app/src/main/res/values-nb/strings.xml +++ b/app/src/main/res/values-nb/strings.xml @@ -16,7 +16,7 @@ "Aktivér delt tastatur" "Bytt inndatametode" Knapp for språkskifte - "%s ms" + "%s ms" "Systemstandard" "Bruk navn fra Kontakter til forslag og korrigeringer" "Spesialtilpassede forslag" @@ -49,20 +49,9 @@ "spansk (USA)" "Hinglish" "Serbisk (latin)" - "Engelsk (Storbritannia) (%s)" - "Engelsk (USA) (%s)" - Spansk (USA) (%s) - "Hinglish (%s)" - "Serbisk (%s)" - "%s (tradisjonelt)" - "%s (kompakt)" - "Ingen språk (alfabet)" - Alfabet (QWERTY) - "Alfabet (QWERTZ)" - "Alfabet (AZERTY)" - "Alfabet (Dvorak)" - "Alfabet (Colemak)" - "Alfabet (PC)" + "%s (tradisjonelt)" + "%s (kompakt)" + "Ingen språk" "Emoji" "Legg til" "Fjern" @@ -75,38 +64,33 @@ "Emoji for fysisk tastatur" "Fysisk Alt-tast som viser emojiutvalget" "Standard" - "Velkommen til %s" + "Velkommen til %s" "med Ordføring" "Startveiledning" - "Neste trinn" - Sett opp %s - Skru på %s - Sjekk «%s» i Språk og inndata-innstillingene dine. Dette tillater programmet å kjøre på enheten. - "%s er allerede slått på i Språk og inndata-innstillingene dine, så dette trinnet er fullført. Gå til neste trinn!" + Sett opp %s + Skru på %s + Sjekk «%s» i Språk og inndata-innstillingene dine. Dette tillater programmet å kjøre på enheten. Skru på i programinnstillingene - "Bytt til %s" - Deretter velger du «%s» som aktiv inndatametode for tekst. + "Bytt til %s" + Deretter velger du «%s» som aktiv inndatametode for tekst. "Bytt inndatametode" "Gratulerer, du er klar!" - "Nå kan du skrive inn alle favorittappene dine med %s." + "Nå kan du skrive inn alle favorittappene dine med %s." "Ferdig" "Vis app-ikonet" "Vis app-ikonet i appoversikten" - "Tilleggsordlister" + "Tilleggsordlister" "Ordliste tilgjengelig" - "Fant ingen ordlister" "Sist oppdatert" "Innstillinger" "Slett" - "Versjon %1$s" - "Legg til" + "Versjon %1$s" "Legg til i ordlisten" "Snarvei:" "Språk:" "Skriv inn et ord" "Valgfri snarvei" "Rediger ord" - "Du har ingen ord i brukerordlisten. Du kan legge til ord ved å trykke på Legg til-knappen (+)." "For alle språk" Flere språk… " ABCDEFGHIJKLMNOPQRSTUVWXYZÆØÅ" @@ -115,10 +99,8 @@ Automatisk dag/nattmodus Langtrykke på mellomromstasten for inndatametode-valgmeny HeliBoard-innstillinger - Alfabet (Colemak Mod-DH) HeliBoard-stavekontroll Innstillinger for HeliBoard-stavekontroll - Alfabet (Workman) Slettingsdragning Emoji-tast Utfør en dragning fra Delete-tasten for å velge og fjerne større deler av tekst samtidig @@ -247,12 +229,11 @@ Smal tastemellomrom Kaitag Velg verktøylinjetaster - %s (Akkhor) + %s (Akkhor) Se på GitHub - %s (Sebeolsik Final) + %s (Sebeolsik Final) Last inn fil Kopier eksisterende oppsett - Sett navn på oppsett Oppsettsfeil: %s Sett bakgrunnsbilde Sett bilde for dag- eller natt-modus? @@ -290,7 +271,6 @@ Indigo Fiolett Brukerdefinert - Klikk for forhåndsvisning Velg farger for tekst og bakgrunner Tastaturbakgrunn Tastaturtekst @@ -312,20 +292,18 @@ Virkelig slette tilpasset oppsett %s? Trykk for å redigere råoppsett Vis flere bokstaver med diakritiske tegn i sprettoppvinduet - %s min + %s min Legg til tilpasset oppsett Legg til fil med kompatibelt format. Informasjon om kompatible format %s. Mørkere Lagre logg - %s (Sebeolsik 390) + %s (Sebeolsik 390) Uten ordbok vil du kun få forslag til tekst som du tidligere har skrevet.<br> \n........Du kan laste ned ordbøker %1$s, eller sjekke om ordbok for \"%2$s\" kan lastes ned direkte %3$s. Dette ordet finnes allerede i %s brukerordbok. Vennligst skriv et annet. Nederste polstringsskala - %s (Probhat) - Alfabet (Bépo) + %s (Probhat) Fargepreg - Kaitag (%s) ► Et langt trykk på utklippstavlen (den valgfrie i forslagsstripen) limer inn innholdet i systemets utklippstavle. <br> <br> ► Et langt trykk på tastene på verktøylinjen for forslagsstripen fester dem til forslagsstripen. <br> <br> ► Trykk lenge på komma-tasten for å få tilgang til utklippstavlevisning, emojivisning, enhåndsmodus, innstillinger eller språkbytte: <br> \t• Emoji View og språkbytteknappen forsvinner hvis du har den tilsvarende nøkkelen aktivert; <br> \t• For noen oppsett er det ikke kommatasten, men tasten i samme posisjon (f.eks. er det \"q\" for Dvorak-oppsettet). <br> <br> ► Når inkognitomodus er aktivert, vil ingen ord læres, og ingen emojier blir lagt til i \"nylige\". <br> <br> ► Trykk på inkognitoikonet for å få tilgang til verktøylinjen. <br> <br> ► Skyvetastinntasting: Sveip fra skift til en annen tast for å skrive inn en enkelt stor bokstav: <br> \t• Dette fungerer også for \'?123\'-tasten for å skrive inn et enkelt symbol fra symboltastaturet, og for relaterte taster. <br> <br> ► Trykk lenge på et forslag i forslagsstripen for å vise flere forslag, og sletteknappen for å fjerne dette forslaget. <br> <br> ► Sveip opp fra et forslag for å åpne flere forslag, og slipp forslaget for å velge det. <br> <br> ► Trykk lenge på en oppføring i utklippstavleloggen for å feste den (behold den i utklippstavlen til du løsner den). <br> <br> ► Du kan legge til ordbøker ved å åpne dem i en filutforsker: <br> \t• Dette fungerer bare med <i>content-uris</i> og ikke med <i>file-uris</i>, noe som betyr at det kanskje ikke fungerer med enkelte filutforskere. <br> <br> <i>Feilsøkingsmodus / feilsøk APK</i> <br> <br> \t• Trykk lenge på et forslag for å vise kildeordboken.<br> <br> \t• Når du bruker debug APK, kan du finne feilsøkingsinnstillinger i de avanserte innstillingene, selv om nytten er begrenset bortsett fra å dumpe ordbøker i loggen. <br> <br> \t• Ved et programkrasj vil du bli spurt om du vil ha krasjloggene når du åpner Innstillinger. <br> <br> \t• Når du bruker flerspråklig skriving, vil mellomromstasten vise en konfidensverdi som brukes til å bestemme språket som brukes for øyeblikket. <br> <br> \t• \"Forslag\" vil ha noen små tall på toppen som viser noe internt partitur og kildeordbok (kan deaktiveres). <br> <br> ► For brukere som tar manuelle sikkerhetskopier med rottilgang: Fra og med Android 7 er ikke den delte preferansefilen på standardplasseringen, fordi appen bruker %s. <br> Dette er nødvendig for at innstillingene kan leses før enheten låses opp, f.eks. ved oppstart. <br> Filen ligger i /data/user_de/0/package_id/shared_prefs/, men dette kan avhenge av enheten og Android-versjonen. - %s (Student) + %s (Student) diff --git a/app/src/main/res/values-ne/strings.xml b/app/src/main/res/values-ne/strings.xml index fec0e8952..5d97a53f7 100644 --- a/app/src/main/res/values-ne/strings.xml +++ b/app/src/main/res/values-ne/strings.xml @@ -16,7 +16,7 @@ "विभाजित कुञ्जीपाटी सक्षम गर्नुहोस्" "अन्य इनपुट विधिमा स्विच गर्नुहोस्" "भाषा स्विच कुञ्जी" - "%s मिलिसेकेन्ड" + "%s मिलिसेकेन्ड" "पूर्वनिर्धारित प्रणाली" "सुझाव र सुधारका लागि सम्पर्कबाट नामहरू प्रयोग गर्नुहोस्" "निजीकृत सुझावहरू" @@ -49,20 +49,9 @@ "स्पेनिस (युएस्)" "हिङ्लिस" "सर्बियाई (ल्याटिन)" - "अंग्रेजी (बेलायत) ( %s )" - "अंग्रेजी (अमेरिका) (%s)" - "स्पेनेली (अमेरिका) (%s)" - "हिङ्लिस (%s)" - "सर्बियाई (%s)" - "%s (परम्परागत)" - "%s (संकुचित)" - "कुनै भाषा होइन (वर्णमाला)" - "वर्णमाला (QWERTY)" - "वर्णमाला (QWERTZ)" - "वर्णमाला (AZERTY)" - "वर्णमाला (Dvorak)" - "वर्णमाला (Colemak)" - "वर्णमाला (PC)" + "%s (परम्परागत)" + "%s (संकुचित)" + "कुनै भाषा होइन" "इमोजी" "थप्नुहोस्" "हटाउनुहोस्" @@ -75,38 +64,33 @@ "भौतिक किबोर्डको लागि इमोजी" "भौतिक Alt कुञ्जीले इमोजी प्यालेट देखाउँछ" "पूर्वनिर्धारित" - "तपाईँलाई स्वागत छ%s" + "तपाईँलाई स्वागत छ%s" "इशारा टाइप गर्नेसँग" "सुरु गरौं" - "अर्को चरण" - "स्थापना गर्दै %s" - "सक्षम पार्नुहोस् %s" - "कृपया आफ्नो भाषा र इनपुट सम्बन्धी सेटिङहरूमा \"%s\" अनुप्रयोगलाई जाँच गर्नुहोस्। यस कारबाहीले अनुप्रयोगलाई तपाईँको यन्त्रमा सञ्चालन हुन आधिकार प्रदान गर्ने छ।" - "तपाईँको भाषा र इनपुट सम्बन्धी सेटिङहरूमा %s लाई पहिले नै सक्रिय गरिएको छ, त्यसैले यो चरण सम्पन्न भइसकेको छ। अर्को चरणमा जानुहोस्!" + "स्थापना गर्दै %s" + "सक्षम पार्नुहोस् %s" + "कृपया आफ्नो भाषा र इनपुट सम्बन्धी सेटिङहरूमा \"%s\" अनुप्रयोगलाई जाँच गर्नुहोस्। यस कारबाहीले अनुप्रयोगलाई तपाईँको यन्त्रमा सञ्चालन हुन आधिकार प्रदान गर्ने छ।" "सेटिङहरूमा सक्षम पार्नुहोस्" - %sमा स्विच गर्नुहोस्\" - "त्यसपछि, \"%s\" लाई तपाईँको सक्रिय पाठ इनपुट विधिका रूपमा चयन गर्नुहोस्।" + %sमा स्विच गर्नुहोस्\" + "त्यसपछि, \"%s\" लाई तपाईँको सक्रिय पाठ इनपुट विधिका रूपमा चयन गर्नुहोस्।" "इनपुट विधि स्विच गर्नुहोस्" "बधाई छ, तपाईँले सेट पुरा गर्नुभयो!" - "अब तपाईं %sका साथ तपाईंका सम्पूर्ण मन पर्ने अनुप्रयोगहरू टाइप गर्न सक्नुहुन्छ।" + "अब तपाईं %sका साथ तपाईंका सम्पूर्ण मन पर्ने अनुप्रयोगहरू टाइप गर्न सक्नुहुन्छ।" "समाप्त भयो" "अनुप्रयोग आइकन देखाउनुहोस्" "लन्चरमा अनुप्रयोग आइकन देखाउनुहोस्" - "एड-अन शब्दकोश" + "एड-अन शब्दकोश" "उपलब्ध शब्दकोश" - "शब्दकोशहरू उपलब्ध छैनन्" "पछिल्लो अद्यावधिक" "सेटिङहरू" "मेट्नुहोस्" - "संस्करण %1$s" - "थप्नुहोस्" + "संस्करण %1$s" "शब्दकोशमा थप्नुहोस्" "सर्टकट:" "भाषा:" "एउटा शब्द टाइप गर्नुहोस्" "वैकल्पिक सर्टकट" "शब्द सम्पादन गर्नुहोस्" - "तपाईँको प्रयोगकर्ता शब्दकोषमा कुनै पनि शब्दहरू छैनन्। शब्द थप्न थप्नुहोस् (+) बटनलाई ट्याप गर्नुहोस्।" "सबै भाषाहरूका लागि" "थप भाषाहरू…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 71ac1c1b8..e9302ddc1 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -4,7 +4,7 @@ modified SPDX-License-Identifier: Apache-2.0 AND GPL-3.0-only --> - Contactpersoonnamen opzoeken + Contactnamen opzoeken "Trillen bij toetsaanslag" "Geluid bij toetsaanslag" "Pop-up bij toetsaanslag" @@ -16,9 +16,9 @@ Gesplitst toetsenbord Andere invoermethode Taalkeuzetoets - %s ms + %s ms "Systeemstandaard" - "Namen uit Contacten gebruiken voor suggesties en correcties" + Gebruik namen uit Contacten voor suggesties en correcties "Gepersonaliseerde suggesties" Dubbel-spatie punt Dubbele tik op spatiebalk voor een punt gevolgd door een spatie @@ -44,25 +44,14 @@ "Dynamisch zwevend voorbeeld" Woordgroepen gebaren Spaties invoeren door te vegen over de spatiebalk - "Engels (GB)" + Engels (VK) "Engels (VS)" "Spaans (VS)" "Hindi-Engels" "Servisch (Latijns)" - Engels (VK) (%s) - Engels (VS) (%s) - Spaans (VS) (%s) - Hindi-Engels (%s) - Servisch (%s) - %s (Traditional) - %s (Compact) - "Geen taal (alfabet)" - "Alfabet (QWERTY)" - "Alfabet (QWERTZ)" - "Alfabet (AZERTY)" - "Alfabet (Dvorak)" - "Alfabet (Colemak)" - Alfabet (PC) + %s (Traditional) + %s (Compact) + "Geen taal" "Emoji" "Toevoegen" "Verwijderen" @@ -75,38 +64,33 @@ "Emoji voor fysiek toetsenbord" Emoji-palet weergeven bij fysieke Alt-toets "Standaard" - Welkom bij %s + Welkom bij %s met Typen met gebaren "Aan de slag" - "Volgende stap" - %s instellen - %s inschakelen - Vink %s aan in de instellingen bij \'Talen & invoer\'. De app kan dan worden uitgevoerd op dit apparaat. - %s is al ingeschakeld in de instellingen bij \'Talen & invoer\', dus deze stap is voltooid. Op naar de volgende! + %s instellen + %s inschakelen + Selecteer %s in de instellingen bij \'Talen & invoer\'. De app kan dan worden uitgevoerd op dit apparaat. "Inschakelen in \'Instellingen\'" - Overschakelen naar %s - Selecteer vervolgens %s als \"actieve tekstinvoermethode.\" + Overschakelen naar %s + Selecteer vervolgens %s als actieve methode voor tekstinvoer. "Schakelen tussen invoermethoden" Gefeliciteerd, je kunt nu aan de slag! - Je kunt nu in al je favoriete apps typen met %s. + Je kunt nu in al je favoriete apps typen met %s. "Voltooid" "App-pictogram weergeven" "App-pictogram weergeven in het opstartprogramma" - Aanvullende woordenboeken + Aanvullende woordenboeken "Woordenboek beschikbaar" - "Geen woordenboeken" "Laatst bijgewerkt" "Instellingen" "Verwijderen" - Versie %1$s - "Toevoegen" + Versie %s "Toevoegen aan woordenboek" "Sneltoets:" "Taal:" "Typ een woord" "Optionele snelkoppeling" "Woord bewerken" - "Er staan geen woorden in het gebruikerswoordenboek. Tik op de knop Toevoegen (+) om een woord toe te voegen." "Voor alle talen" "Meer talen…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" @@ -117,7 +101,7 @@ Het uiterlijk volgt de systeeminstellingen Klembordgeschiedenis Experimenteel - Diversen + Overig Geen limiet Bewaartijd van de geschiedenis Verwijderen met veegbeweging @@ -132,7 +116,7 @@ Emojitoets Correcties Suggesties - %s min + %s min Druk lang op de spatietoets voor het selectiemenu van de invoermethode Betrouwbaarheid autocorrectie Indien uitgeschakeld, plakt de klembord-toets de inhoud van het klembord @@ -140,10 +124,8 @@ Het leren van nieuwe woorden uitschakelen Hints bij lang indrukken weergeven Toetsenbordhoogte schaal - %s (Akkhor) + %s (Akkhor) Invoermethode schakelen met spatietoets - Alfabet (Colemak Mod-DH) - Alfabet (Workman) Toetsranden Automatisch spatie invoegen na interpunctie en het typen van een nieuw woord HeliBoard-instellingen @@ -171,7 +153,7 @@ Beide Woorden toevoegen aan persoonlijk woordenboek Gebruik het persoonlijke woordenboek van het apparaat om geleerde woorden op te slaan - Waarschuwing: met het uitschakelen van deze instelling worden geleerde gegevens gewist + Waarschuwing: Als u deze instelling uitschakelt, worden de geleerde gegevens gewist Altijd suggesties tonen Automatisch corrigeren, zelfs als dit niet expliciet wordt gevraagd door het invoerveld Meer autocorrectie @@ -210,7 +192,6 @@ Volgorde pop-up toets kiezen Cijferregel Bodemafstand schaal - Naam van lay-out instellen Aangepaste lay-out %s verwijderen? Symbolen (Arabisch) Aangepast @@ -227,7 +208,7 @@ Fout: script niet compatibel met dit toetsenbord Gewicht: Bewolkt - %s (Extended) + %s (Extended) Taal kiezen Dit woord is al aanwezig in het gebruikerswoordenboek van %s. Typ er nog een. Woord toevoegen @@ -240,7 +221,7 @@ Klembord wissen Woord selecteren Werkbalktoetsen kiezen - Taal + @string/subtype_locale Geheel links Geheel rechts Links @@ -256,7 +237,7 @@ Numpad Numpad (liggend) Knippen - %s (Probhat) + %s (Probhat) Intern hoofdwoordenboek Over Versie @@ -267,11 +248,9 @@ Fout: Geselecteerd bestand is geen geldig woordenboekbestand Telefoonsymbolen Mansi - Mansi (%s) - Kaitag (%s) - %s (Sebeolsik 390) - %s (Sebeolsik Final) - %s (Student) + %s (Sebeolsik 390) + %s (Sebeolsik Final) + %s (Student) Aangepaste lay-out toevoegen Selecteer een bestand in een compatibel formaat. Informatie over de formaten is beschikbaar %s. Bestaande lay-out kopiëren @@ -303,7 +282,6 @@ Meer kleuren tonen Alle kleuren tonen Deze instelling toont alle kleuren bloot die intern worden gebruikt. De lijst met kleuren kan op elk moment veranderen. Er is een willekeurige standaardkleur en de namen worden niet vertaald. - Klik voor een voorbeeld Toetsenbord-achtergrond Toetstekst Toets-achtergrond @@ -332,7 +310,6 @@ \nJe kunt woordenboeken %1$s downloaden, of een woordenboek voor \"%2$s\" %3$s direct downloaden. Varianten gedefinieerd in toetsenbordtalen weergeven Functionele hints weergeven - Alfabet (Bépo) Het geselecteerde bestand is voor %1$s, maar %2$s werd verwacht. Toch gebruiken voor %2$s? Fout bij terugzetten van de back-up: %s Selecteer een woordenboek om toe te voegen. Woordenboeken in .dict-indeling kunnen %s worden gedownload. @@ -396,7 +373,6 @@ Valuta aanpassen Opslaan naar bestand Kopiëren naar klembord - Laden zal het huidige thema overschrijven Laden Pagina-einde Pagina-begin @@ -439,16 +415,15 @@ Werkbalktoetscodes aanpassen Code voor lang drukken Pictogrammen aanpassen - \@string/show_language_switch_key + @string/show_language_switch_key Shift (ingedrukt) Bediening met één hand wisselen Vuilnisbak Alle aangepaste pictogrammen herstellen? - Trillen in de nietstoren-modus + Trillen in de niet storen-modus Emoji-versie overschrijven - %s (Phonetic) + %s (Phonetic) Dargwa (Urakhi) - Urakhi (%s) Sneltoetsen autom. corrigeren Indien ingeschakeld, kunnen sneltoetsen worden uitgebreid met autocorrectie Aangepast lettertype instellen vanuit bestand @@ -475,5 +450,28 @@ Aangepast subtype Je kunt lay-outs zoeken en delen in de %s. discussiesectie - %s (Baishakhi) + %s (Baishakhi) + TLD-opties weergeven + Vervang pop-ups met interpunctie door topleveldomeinen bij het typen van URL\'s en e-mailadressen + Druk op enter of spatie na andere toetsen in het numpad + Cijferregel (basis) + Suggesties voor webbewerkingsvelden niet altijd weergeven + Webbewerkingsvelden (meestal te vinden in browsers) zijn een veel voorkomende oorzaak van problemen met de instelling Altijd suggesties weergeven + Spatie + Autom. spatie na keuze van suggestie + Autom. spatie voor typen van woord met gebaren + Autom. spatie na typen van woord met gebaren + Geen autom. spatie bij indrukken van shift + Shift verwijdert autom. spatie in afwachting + Backspace draait autocorrectie terug + Formaat voor tijdstempeltoetd + Dagbani + Sesotho + Emoji-toetsgrootte schalen met lettergrootte + Back-up hersteld + App-namen opzoeken + Gebruik de namen van geïnstalleerde apps voor suggesties en correcties + Neutraal + Standaard emoji-huidskleur + %1$s (%2$s) diff --git a/app/src/main/res/values-or/strings.xml b/app/src/main/res/values-or/strings.xml index 2b8696741..0c0b1e4b4 100644 --- a/app/src/main/res/values-or/strings.xml +++ b/app/src/main/res/values-or/strings.xml @@ -7,7 +7,6 @@ ଵିଵିଧ ଭାଷା - ଯୋଡ଼ନ୍ତୁ ଅଭିଧାନରେ ଯୋଡ଼ନ୍ତୁ ଭାଷା: ଶବ୍ଦ ସମ୍ପାଦନା diff --git a/app/src/main/res/values-ota/strings.xml b/app/src/main/res/values-ota/strings.xml index c160d2aa7..501d69a50 100644 --- a/app/src/main/res/values-ota/strings.xml +++ b/app/src/main/res/values-ota/strings.xml @@ -49,7 +49,6 @@ وارصاییلان سوزلوكلر سیل - اكلە سیقلق: دیل: یووارلادلمش @@ -89,4 +88,4 @@ قیصەیول: تماملاندی بورادە - \ No newline at end of file + diff --git a/app/src/main/res/values-pa-rPK/strings.xml b/app/src/main/res/values-pa-rPK/strings.xml index 21cc6ddc4..610409b33 100644 --- a/app/src/main/res/values-pa-rPK/strings.xml +++ b/app/src/main/res/values-pa-rPK/strings.xml @@ -26,7 +26,6 @@ ایموجی کیبورڈ دی چوݨ مٹاؤ - شامل کرو بولی خود بخود اکھر کیپیٹل ورتݨ بند @@ -105,4 +104,4 @@ دپھاڑ دا فاصلا ‫HeliBoard‬ لفظ جوڑن والا بولی بدلو - \ No newline at end of file + diff --git a/app/src/main/res/values-pa/strings.xml b/app/src/main/res/values-pa/strings.xml index 6cfaeee81..4f0c49294 100644 --- a/app/src/main/res/values-pa/strings.xml +++ b/app/src/main/res/values-pa/strings.xml @@ -16,7 +16,7 @@ "ਸਪਲਿਟ ਕੀ-ਬੋਰਡ ਨੂੰ ਚਾਲੂ ਕਰੋ" "ਹੋਰਾਂ ਇਨਪੁੱਟ ਵਿਧੀਆਂ ਤੇ ਸਵਿੱਚ ਕਰੋ" "ਭਾਸ਼ਾ ਸਵਿੱਚ ਕੁੰਜੀ" - "%sms" + "%sms" "ਸਿਸਟਮ ਪੂਰਵ-ਨਿਰਧਾਰਤ" "ਸੁਝਾਵਾਂ ਅਤੇ ਸੋਧਾਂ ਲਈ ਸੰਪਰਕਾਂ ਵਿੱਚੋਂ ਨਾਮ ਵਰਤੋ" "ਨਿੱਜੀ ਬਣਾਏ ਸੁਝਾਅ" @@ -49,20 +49,9 @@ "ਸਪੇਨੀ (ਅਮਰੀਕਾ)" "ਹਿੰਗਲਿੰਸ਼" "ਸਰਬੀਅਨ (ਲਾਤੀਨੀ)" - "ਅੰਗਰੇਜ਼ੀ (ਯੂ.ਕੇ.) (%s)" - "ਅੰਗਰੇਜ਼ੀ (ਅਮਰੀਕਾ) (%s)" - "ਸਪੇਨੀ (ਅਮਰੀਕਾ) (%s)" - "ਹਿੰਗਲਿਸ਼(%s)" - "ਸਰਬੀਅਨ (%s)" - "%s (ਪਰੰਪਰਿਕ)" - "%s (ਸੰਖਿਪਤ)" - "ਕੋਈ ਭਾਸ਼ਾ ਨਹੀਂ (ਵਰਨਮਾਲਾ)" - "ਵਰਨਮਾਲਾ (QWERTY)" - "ਵਰਨਮਾਲਾ (QWERTZ)" - "ਵਰਨਮਾਲਾ (AZERTY)" - "ਵਰਨਮਾਲਾ (ਵੋਰਕ)" - "ਵਰਨਮਾਲਾ (ਕੋਲਮੈਕ)" - "ਵਰਨਮਾਲਾ (PC)" + "%s (ਪਰੰਪਰਿਕ)" + "%s (ਸੰਖਿਪਤ)" + "ਕੋਈ ਭਾਸ਼ਾ ਨਹੀਂ" "ਇਮੋਜੀ" "ਸ਼ਾਮਲ ਕਰੋ" "ਹਟਾਓ" @@ -75,38 +64,33 @@ "ਭੌਤਿਕ ਕੀ-ਬੋਰਡ ਲਈ ਇਮੋਜੀ" "ਭੌਤਿਕ Alt ਕੁੰਜੀ ਇਮੋਜੀ ਪੈਲੇਟ ਦਿਖਾਉਂਦੀ ਹੈ" "ਪੂਰਵ-ਨਿਰਧਾਰਤ" - %s ਤੇ ਸੁਆਗਤ ਹੈ\" + %s ਤੇ ਸੁਆਗਤ ਹੈ\" "ਸੰਕੇਤ ਟਾਈਪਿੰਗ ਨਾਲ" "ਸ਼ੁਰੂਆਤ ਕਰੋ" - "ਅਗਲਾ ਸਟੈਪ" - %s ਸੈਟ ਅਪ ਕਰ ਰਿਹਾ ਹੈ\" - %s ਨੂੰ ਸਮਰੱਥ ਬਣਾਓ\" - "ਕਿਰਪਾ ਕਰਕੇ ਆਪਣੀਆਂ ਭਾਸ਼ਾਵਾਂ ਅਤੇ ਇਨਪੁੱਟ ਸੈਟਿੰਗਾਂ ਵਿੱਚ \"%s\" \'ਤੇ ਸਹੀ ਦਾ ਨਿਸ਼ਾਨ ਲਗਾਓ। ਇਹ ਉਸ ਨੂੰ ਤੁਹਾਡੇ ਡੀਵਾਈਸ \'ਤੇ ਚੱਲਣ ਲਈ ਅਧਿਕਾਰਿਤ ਕਰੇਗਾ।" - "%s ਨੂੰ ਪਹਿਲਾਂ ਹੀ ਤੁਹਾਡੀਆਂ ਭਾਸ਼ਾਵਾਂ ਅਤੇ ਇਨਪੁੱਟ ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਚਾਲੂ ਕੀਤਾ ਗਿਆ ਹੈ, ਇਸ ਲਈ ਇਹ ਪੜਾਅ ਪੂਰਾ ਹੋ ਗਿਆ ਹੈ। ਅਗਲੇ ਪੜਾਅ \'ਤੇ ਜਾਓ!" + %s ਸੈਟ ਅਪ ਕਰ ਰਿਹਾ ਹੈ\" + %s ਨੂੰ ਸਮਰੱਥ ਬਣਾਓ\" + "ਕਿਰਪਾ ਕਰਕੇ ਆਪਣੀਆਂ ਭਾਸ਼ਾਵਾਂ ਅਤੇ ਇਨਪੁੱਟ ਸੈਟਿੰਗਾਂ ਵਿੱਚ \"%s\" \'ਤੇ ਸਹੀ ਦਾ ਨਿਸ਼ਾਨ ਲਗਾਓ। ਇਹ ਉਸ ਨੂੰ ਤੁਹਾਡੇ ਡੀਵਾਈਸ \'ਤੇ ਚੱਲਣ ਲਈ ਅਧਿਕਾਰਿਤ ਕਰੇਗਾ।" "ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਚਾਲੂ ਕਰੋ" - %s \'ਤੇ ਸਵਿੱਚ ਕਰੋ\" - "ਫਿਰ, \"%s\" ਨੂੰ ਆਪਣੀ ਕਿਰਿਆਸ਼ੀਲ ਲਿਖਤ-ਇਨਪੁੱਟ ਵਿਧੀ ਦੇ ਤੌਰ ਤੇ ਚੁਣੋ।" + %s \'ਤੇ ਸਵਿੱਚ ਕਰੋ\" + "ਫਿਰ, \"%s\" ਨੂੰ ਆਪਣੀ ਕਿਰਿਆਸ਼ੀਲ ਲਿਖਤ-ਇਨਪੁੱਟ ਵਿਧੀ ਦੇ ਤੌਰ ਤੇ ਚੁਣੋ।" "ਇਨਪੁੱਟ ਵਿਧੀਆਂ ਸਵਿੱਚ ਕਰੋ" "ਵਧਾਈ ਹੋਵੇ, ਤੁਸੀਂ ਸਾਰਾ ਸੈਟ ਕਰ ਲਿਆ ਹੈ!" - "ਹੁਣ ਤੁਸੀਂ %s ਨਾਲ ਆਪਣੇ ਸਾਰੇ ਮਨਪਸੰਦ ਐਪਸ ਨੂੰ ਟਾਈਪ ਕਰ ਸਕਦੇ ਹੋ।" + "ਹੁਣ ਤੁਸੀਂ %s ਨਾਲ ਆਪਣੇ ਸਾਰੇ ਮਨਪਸੰਦ ਐਪਸ ਨੂੰ ਟਾਈਪ ਕਰ ਸਕਦੇ ਹੋ।" "ਪੂਰਾ ਹੋਇਆ" "ਐਪ ਪ੍ਰਤੀਕ ਦਿਖਾਓ" "ਲਾਂਚਰ ਵਿੱਚ ਐਪਲੀਕੇਸ਼ਨ ਪ੍ਰਤੀਕ ਪ੍ਰਦਰਸ਼ਿਤ ਕਰੋ" - "ਐਡ-ਆਨ ਸ਼ਬਦਕੋਸ਼" + "ਐਡ-ਆਨ ਸ਼ਬਦਕੋਸ਼" "ਸ਼ਬਦਕੋਸ਼ ਉਪਲਬਧ" - "ਕੋਈ ਸ਼ਬਦਕੋਸ਼ ਉਪਲਬਧ ਨਹੀਂ" "ਆਖਰੀ ਵਾਰ ਅੱਪਡੇਟ ਕੀਤਾ" "ਸੈਟਿੰਗਾਂ" "ਮਿਟਾਓ" - "ਰੂਪ %1$s" - "ਸ਼ਾਮਲ ਕਰੋ" + "ਰੂਪ %1$s" "ਸ਼ਬਦਕੋਸ਼ ਵਿੱਚ ਸ਼ਾਮਲ ਕਰੋ" "ਸ਼ਾਰਟਕੱਟ:" "ਭਾਸ਼ਾ:" "ਇੱਕ ਸ਼ਬਦ ਟਾਈਪ ਕਰੋ" "ਵਿਕਲਪਕ ਸ਼ਾਰਟਕੱਟ" "ਸ਼ਬਦ ਦਾ ਸੰਪਾਦਨ ਕਰੋ" - "ਤੁਹਾਡੇ ਕੋਲ ਵਰਤੋਂਕਾਰ ਸ਼ਬਦਕੋਸ਼ ਵਿੱਚ ਕੋਈ ਸ਼ਬਦ ਨਹੀਂ ਹਨ। ਇੱਕ ਸ਼ਬਦ ਸ਼ਾਮਲ ਕਰਨ ਲਈ \'ਸ਼ਾਮਲ ਕਰੋ\' (+) ਬਟਨ \'ਤੇ ਟੈਪ ਕਰੋ।" "ਸਾਰੀਆਂ ਭਾਸ਼ਾਵਾਂ ਲਈ" "ਹੋਰ ਭਾਸ਼ਾਵਾਂ…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 8c4746aad..9f9d1d445 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -17,7 +17,7 @@ "Włącz podzieloną klawiaturę" "Inne metody wprowadzania" "Klawisz zmiany języka" - "%s ms" + "%s ms" "Ustawienie domyślne" "W podpowiedziach i poprawkach używaj nazwisk z kontaktów" "Dostosowane sugestie" @@ -50,20 +50,9 @@ "Hiszpański (USA)" hinglish serbski (alfabet łaciński) - Angielski (Wielka Brytania) (%s) - Angielski (USA) (%s) - Hiszpański (USA) (%s) - hinglish (%s) - serbski (%s) - %s (tradycyjny) - %s (kompaktowy) - standardowy (Alfabet) - "Alfabet (QWERTY)" - "Alfabet (QWERTZ)" - "Alfabet (AZERTY)" - "Alfabet (Dvorak)" - "Alfabet (Colemak)" - "Alfabet (PC)" + %s (tradycyjny) + %s (kompaktowy) + standardowy "Emotikony" "Dodaj" "Usuń" @@ -76,44 +65,39 @@ "Emotikony z klawiatury fizycznej" "Naciśnięcie klawisza Alt przywołuje okienko wyboru emotikonów" "Domyślne" - Witamy w aplikacji %s + Witamy w aplikacji %s "z pisaniem gestami" "Rozpocznij" - "Następny krok" - Konfigurowanie aplikacji %s - Włącz aplikację %s - Zaznacz aplikację %s w ustawieniach Język i wprowadzanie tekstu. Umożliwi to jej uruchamianie na urządzeniu. - Aplikacja %s jest już włączona w ustawieniach Język i wprowadzanie tekstu. Przejdź do następnego kroku! + Konfigurowanie aplikacji %s + Włącz aplikację %s + Zaznacz aplikację %s w ustawieniach Język i wprowadzanie tekstu. Umożliwi to jej uruchamianie na urządzeniu. "Włącz w Ustawieniach" - Przełącz się na aplikację %s - Następnie wybierz %s jako aktywną metodę wprowadzania tekstu. + Przełącz się na aplikację %s + Następnie wybierz %s jako aktywną metodę wprowadzania tekstu. "Przełącz metody wprowadzania" Gratulacje, wszystko gotowe! - Teraz możesz pisać we wszystkich swoich ulubionych aplikacjach, używając aplikacji %s. + Teraz możesz pisać we wszystkich swoich ulubionych aplikacjach, używając aplikacji %s. Zakończ "Pokaż ikonę aplikacji" "Wyświetlaj ikonę aplikacji w programie uruchamiającym" - "Słowniki dodatkowe" - "Słownik dostępny" - "Brak słowników" + "Słowniki dodatkowe" + Dostępny słownik "Ostatnia aktualizacja" "Ustawienia" "Usuń" - Wersja %1$s - "Dodaj" + Wersja %1$s "Dodaj do słownika" "Skrót:" "Język:" "Wpisz słowo" "Opcjonalny skrót" "Edytuj słowo" - "Brak słów w słowniku użytkownika. Aby dodać słowo, kliknij przycisk Dodaj (+)." "Dla wszystkich języków" "Więcej języków…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" Korekty Różne - %s min. + %s min. Bez limitu Wyłącz naukę nowych słów Więcej klawiszy @@ -128,15 +112,13 @@ Zawsze pokazuj rząd numeryczny Zmień metodę wprowadzania za pomocą spacji Pokazuj wskazówki dotyczące długiego naciśnięcia przycisku - Alfabet (Colemak Mod-DH) Przesuń palcem od klawisza usuwania, aby zaznaczyć i usunąć większe fragmenty tekstu za jednym razem Po wyłączeniu, klawisz schowka będzie wklejał zawartość schowka, jeśli taka istnieje Gest usunięcia Długie naciśnięcie klawisza spacji spowoduje wyświetlenie menu wyboru metody wprowadzania tekstu Pokazuj wskazówki klawiszy Skala wysokości klawiatury - Alfabet (Workman) - %s (Akkhor) + %s (Akkhor) Ustawienia HeliBoard Dodatkowe klawisze Wprowadzanie @@ -174,13 +156,13 @@ Błąd podczas przywracania kopii zapasowej: %s Kolory Tło klawiszy funkcyjnych - %s (Sebeolsik 390) + %s (Sebeolsik 390) Używaj słownika osobistego do przechowywania nauczonych słów To słowo znajduje się już w słowniku: %s. Wpisz inne. Zaokrąglony Kopia Czarne - %s (Sebeolsik Final) + %s (Sebeolsik Final) Czekoladowe Na pewno usunąć słownik \"%s\" dodany przez użytkownika? Pochmurne @@ -195,7 +177,7 @@ Różowe Języki i układy Nie można odczytać pliku - stąd + tutaj Błąd: wybrany plik nie jest prawidłowym plikiem słownika chronionej pamięci urządzenia Koloruj pasek nawigacyjny @@ -206,7 +188,7 @@ \nUwaga: dodawanie zewnętrznego kodu może stanowić zagrożenie bezpieczeństwa. Korzystaj z biblioteki pochodzącej tylko z zaufanego źródła. Wybierz słownik do dodania. Słowniki w formacie .dict można pobrać %s. Usuń bibliotekę - Język (główny) + @string/subtype_locale W prawo Błąd podczas dodawania słownika Preferuj liczby lokalne zamiast łacińskich @@ -252,7 +234,6 @@ Jasne Dodaj słowo Tekst paska sugestii - Dotknij, aby wyświetlić podgląd Pokaż warianty zdefiniowane w językach klawiatury Pokaż popularne warianty Własne @@ -263,7 +244,6 @@ Akcent Zobacz na GitHubie Rząd numeryczny - Alfabet (Bépo) Przywracanie Wybierz kolejność klawiszy w wyskakującym okienku Wersja @@ -320,7 +300,6 @@ Szerokość podziału Wartość: Ignoruj prośby innych aplikacji o wyłączenie sugestii (może powodować problemy) - Nazwij układ Bez słownika będziesz otrzymywać jedynie sugestie dotyczące tekstu, który został wpisany wcześniej.<br> \nSłowniki możesz pobrać %1$s lub sprawdź, czy słownik \"%2$s\" można pobrać bezpośrednio %3$s. Zmień język @@ -352,7 +331,6 @@ Symbole (arabski) Telefon kaitag - kaitag (%s) Klawiatura numeryczna Klawiatura numeryczna (poziomo) Liczby @@ -360,19 +338,18 @@ Spacja - przesuwanie pionowe Spacja - przesuwanie poziome Przesuń kursor - Brak przesuwania + Brak Odwróć kierunek po wybraniu układu klawiatury od prawej do lewej Zmienny kierunek paska narzędzi - %s (Probhat) - %s (Uczeń) + %s (Probhat) + %s (Uczeń) Przytrzymaj klawisz symboli, aby wyświetlić klawiaturę numeryczną Wytnij Zawsze używaj środkowej sugestii Po naciśnięciu spacji lub znaku interpunkcyjnego zostanie wpisana środkowa sugestia Zamknij schowek Wybierz klawisze paska narzędzi w schowku - %s (rozszerzony) - mansyjski (%s) + %s (rozszerzony) mansyjski Pokaż więcej kolorów To ustawienie wyświetla wszystkie kolory używane wewnętrznie. Lista kolorów może w każdej chwili ulec zmianie. Domyślny kolor jest losowy, a nazwy nie zostaną przetłumaczone. @@ -392,9 +369,8 @@ Emotikony Ustaw główny i do 6 drugorzędnych symboli waluty, oddzielonych spacją Dostosuj waluty - Załaduj + Dodaj Skopiuj do schowka - Ładowanie spowoduje zastąpienie bieżącego motywu Zapisz do pliku Na początek strony Na koniec strony @@ -434,7 +410,7 @@ Usuwanie Wprowadzanie głosowe wyłączone Pokaż/ukryj pasek narzędzi - \@string/show_language_switch_key + @string/show_language_switch_key Dostosuj kody klawiszy paska narzędzi Kod klawisza Kod długiego naciśnięcia @@ -445,9 +421,8 @@ Usuń Na pewno zresetować wszystkie dostosowane ikony? Wibracje w trybie nie przeszkadzać - %s (fonetyczny) + %s (fonetyczny) Dargwa (Urakhi) - Urakhi (%s) Zastąp wersję emoji Autokorekta skrótów Po włączeniu skróty mogą być rozwijane przez autokorektę @@ -465,15 +440,38 @@ Włącz podzieloną klawiaturę (poziomo) Szerokość podziału (poziomo) Podziel klawiaturę - Na pewno usunąć %s ? + Na pewno usunąć %s? Inne układy Klawisze funkcyjne (tablet) Nieprawidłowa nazwa Języki ze słownikami Ostrzeżenie: ten układ jest aktualnie używany - Motywy możesz znaleźć i udostępnić w %s . - Układy możesz znaleźć i udostępnić w %s . + Motywy możesz znaleźć i udostępnić w %s. + Układy możesz znaleźć i udostępnić w %s. sekcji dyskusji - Własny podtyp - %s (Baishakhi) + Własny układ + %s (Baishakhi) + Pokaż wyskakujące okienka TLD + Zastąp wyskakujące okienka klawisza kropki domenami najwyższego poziomu podczas wpisywania adresów URL i adresów e-mail + Naciśnięciu enter lub spacji po innych klawiszach w klawiaturze numerycznej + Rząd numeryczny (podstawowy) + Nie zawsze pokazuj sugestie dla pól edycji w sieci + Pola edycji w sieci (zwykle znajdujące się w przeglądarkach) są bardzo częstą przyczyną problemów z ustawieniem \"zawsze pokazuj sugestie\" + Spacja + Automatyczna spacja po wybraniu sugestii + Automatyczna spacja po wpisaniu słowa gestem + Brak automatycznej spacji po wciśnięciu shift + Shift usuwa automatyczną spację + Backspace cofa autokorektę + Automatyczna spacja przed wpisaniem słowa gestem + Format klawisza znacznika czasu + dagbani + sesotho + Skaluj rozmiar emotikonów w zależności od rozmiaru czcionki + Kopia zapasowa przywrócona + Używaj nazw zainstalowanych aplikacji do sugestii i poprawek + Przeszukaj nazwy aplikacji + Domyślny odcień skóry emoji + Neutralny + %1$s (%2$s) diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 1529f56b9..0beff1f46 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -7,8 +7,8 @@ Configurações do HeliBoard Vibrar ao tocar nas teclas Som ao tocar nas teclas - Digitação por Gestos - Correção de Texto + Digitação por gestos + Correção de texto Avançado Tema Entrada @@ -16,7 +16,7 @@ Correções Outros Ativar teclado dividido - Experimental + Experimentos Usar nomes de contatos para sugestões e correções Sugestões personalizadas Duplo espaço para ponto @@ -48,15 +48,12 @@ Escala da altura do teclado Sempre mostrar a linha de números Inglês (Reino Unido) - Inglês (EUA) - Espanhol (EUA) - Hindi-Inglês + Inglês (Estados Unidos) + Espanhol (Estados Unidos) + Hinglês Sérvio (Latino) - Espanhol (EUA) (%s) - Sérvio %s - Nepali (Nepal) %s (Tradicional) - Bengali (Bangladesh) %s (Akkhor) - Alfabeto (PC) + Nepali (Nepal) %s (Tradicional) + Bengali (Bangladesh) %s (Akkhor) Emojis Adicionar Remover @@ -70,37 +67,33 @@ Padrão com Digitação por Gestos Começar - Próxima etapa - Ative %s + Ative %s Ativar nas Configurações Alterar os métodos de entrada Parabéns, está tudo pronto! Mostrar ícone do app - Adicionar dicionários - Nenhum dicionário disponível + Adicionar dicionários Última atualização em Configurações Excluir - Adicionar Atalho: Idioma: Editar palavra - Você não tem nenhuma palavra no dicionário do usuário. Para adicionar uma palavra, toque no botão Adicionar (+). Para todos os idiomas Mais idiomas… " ABCDEFGHIJKLMNOPQRSTUVWXYZ" Bordas nas teclas - Corretor Ortográfico do HeliBoard - Configurações do corretor ortográfico do HeliBoard + Verificador ortográfico do HeliBoard + Configurações do verificador ortográfico do HeliBoard Buscar por nomes de contatos Mostrar pop-up ao tocar em teclas Preferências Histórico da área de transferência Sugestões - %s ms - %s min + %s ms + %s min Sem limite - Padrão do Sistema + Padrão do sistema Dicionário pessoal Dicionário principal Mostrar sugestões de correção @@ -111,30 +104,19 @@ Alterar método de entrada com a tecla de espaço Tempo de retenção do histórico Linha de números - Inglês (Reino Unido) %s - Inglês (EUA) %s - Hindi-inglês %s - Nenhum idioma (Alfabeto) - Alfabeto (QWERTY) - %s já está ativado nas configurações de \'Idiomas e Entrada\'. Esta etapa já está concluída. Vamos avançar para a próxima!\" - Alfabeto (QWERTZ) - Alfabeto (AZERTY) - Alfabeto (Dvorak) - Alfabeto (Colemak) - Alfabeto (Colemak Mod-DH) - Alfabeto (Workman) - Bem-vindo ao %s + Nenhum idioma + Bem-vindo ao %s Mostrar a paleta de emojis ao tocar na tecla Alt física - Configurando %s - Por favor, ative o \\%s\" em \'Idiomas e Entrada\' nas configurações. Isso permitirá que ele seja usado no seu dispositivo.\" + Configurando %s + Por favor, ative o \"%s\" em \'Idiomas e Entrada\' nas configurações. Isso permitirá que ele seja usado no seu dispositivo. Concluído Mostrar o ícone do app na launcher Dicionário disponível - Alternar para %s - Em seguida, selecione \\%s\" como o seu método de entrada ativo.\" - Agora, você pode usar o %s para digitar nos seus apps favoritos. + Alternar para %s + Em seguida, selecione o \"%s\" como o seu método de entrada ativo. + Agora, você pode usar o %s para digitar nos seus apps favoritos. Adicionar ao dicionário - Versão %1$s + Versão %1$s Escreva uma palavra Atalho opcional Modo de dia/noite automático @@ -142,7 +124,7 @@ Alterar para outros métodos de entrada Tecla de alteração de idioma Tecla de emoji - Hindi %s (Compacto) + Hindi %s (Compacto) Se desativado, a tecla da área de transferência somente colará o conteúdo na área de transferência Espaço automático após pontuação Inserir um espaço automaticamente após a pontuação ao digitar uma nova palavra @@ -175,7 +157,7 @@ Selecionar fonte de dicas Selecionar ordem do pop-up de teclas Linha de números - Idioma + @string/subtype_locale Idioma (prioridade) Layout Símbolos @@ -198,7 +180,6 @@ Salvar ou carregar para/de um arquivo. Aviso: A restauração substituirá dados existentes Carregar arquivo Não foi possível ler o arquivo - Definir nome do layout Erro de layout: %s Definir imagem para o modo de dia ou noite? Dia @@ -207,18 +188,16 @@ Aprender de suas comunicações e dados digitados para melhorar sugestões Versão Sempre mostrar sugestões - Aviso: Desativar esta opção limpará dados aprendidos + Alerta: Desativar esta opção limpará dados aprendidos Ignorar a solicitação de outros apps de desativar as sugestões (pode causar problemas) Deseja realmente excluir o layout customizado %s? Definir imagem de fundo Configurar o teclado Adicionar dicionário por um arquivo - Clique para uma pré-visualização Fundo do teclado Espera - %s (Probhat) + %s (Probhat) "Sem um dicionário, você receberá apenas sugestões para o texto digitado antes.<br>\n Você pode baixar dicionários %1$s, ou verifique se um dicionário para \"%2$s\" pode ser baixado diretamente %3$s." - Alfabeto (Bépo) Essa palavra já está presente no dicionário do usuário %s. Digite outra. Definido pelo usuário (noite) Texto da tecla @@ -235,12 +214,11 @@ Mostrar dicas se um toque longo numa tecla ativa funcionalidade adicional Escala do preenchimento da parte inferior Kaitag - Kaitag (%s) Destaque Gesto de deslizar horizontal na barra de espaço Mover cursor - %s (Sebeolsik 390) - %s (Sebeolsik Final) + %s (Sebeolsik 390) + %s (Sebeolsik Final) Adicionar layout customizado Selecionar um arquivo num formato compatível. Infomações sobre os formatos estão disponíveis em %s. Copiar layout existente @@ -328,13 +306,13 @@ Inverter a direção quando um teclado do subtipo direita-para-esquerda é selecionado Pressione longamente a tecla de símbolos para abrir o teclado numérico Cortar - %s (Estudante) + %s (Estudante) Licença Pública Geral GNU v3.0 Sempre usar a sugestão do meio Ao pressionar espaço ou pontuação, a sugestão do meio será inserida Fechar histórico da área de transferência Selecionar teclas da barra de ferramentas de área de transferência - %s (Extendido) + %s (Extendido) Essa configuração expõe todas as cores que são usadas internamente. A lista de cores pode mudar a qualquer momento. A cor padrão é aleatória, e os nomes não são traduzidos. Selecionar teclas fixadas da barra de ferramentas Começar instantaneamente sempre @@ -362,9 +340,7 @@ Sugerir conteúdo da área de transferência Mostrar conteúdo recentemente copiado da área de transferência como uma sugestão Página para cima - O carregamento substituirá o tema atual Mansi - Mansi (%s) Mostrar mais cores Teclas funcionais Teclas funcionais (Símbolos) @@ -408,7 +384,7 @@ Você deseja realmente redefinir todos os ícones customizados? Lixeira Vibrar no modo Não Perturbe - %s (Fonético) + %s (Fonético) Sobrescrever versão de Emoji Realmente limpar todos os códigos de tecla customizados? Auto-corrrigir atalhos @@ -417,7 +393,6 @@ Definir imagem de fundo (paisagem) Se não definido, a imagem de retrato será usada Dargínico (Urakhi) - Urakhi (%s) Escala do espaço inferior (paisagem) Escala da fonte do teclado Escala da fonte na visualização de emoji @@ -438,5 +413,28 @@ Você pode encontrar e compartilhar layouts em %s. seção de discussão Subtipo customizado - %s (Baishakhi) + %s (Baishakhi) + Mostrar teclas de TLD + Substituir os pop-ups da tecla de ponto com domínios de topo ao digitar URLs e endereços de e-mail + Pressionando enter ou espaço após outras teclas no teclado de números + Linha de números (básica) + Não mostrar sugestões para campos de edição da web sempre + Campos de edição da web (encontrados normalmente em navegadores) são uma causa comum de problemas com a configuração de sempre mostrar sugestões + Espaço + Espaço automático após escolher uma sugestão + Espaço automática após digitar uma palavra com gestos + Sem espaço automático ao pressionar shift + O shift remove o espaço automático pendente + O backspace reverte a autocorreção + Espaço automático antes de digitar uma palavra com gestos + Formato da tecla de horário + Dagani + Sesoto + Redimensionar tamanho da tecla de emoji com o tamanho da fonte + O backup foi restaurado + Procurar nomes de apps + Usar nomes de apps instalados para sugestões e correções + Cor de pele padrão para os emojis + Neutra + %1$s (%2$s) diff --git a/app/src/main/res/values-pt-rPT/strings.xml b/app/src/main/res/values-pt-rPT/strings.xml index 5940ce6fd..d3b59e818 100644 --- a/app/src/main/res/values-pt-rPT/strings.xml +++ b/app/src/main/res/values-pt-rPT/strings.xml @@ -6,18 +6,18 @@ --> "Procurar nomes de contac." "Vibrar ao primir as teclas" - "Som ao premir as teclas" + Som ao premir tecla "Mostrar popup ao premir tecla" "Preferências" - Aparência & Esquemas + Aparência "Escrita com gestos" - "Correção de texto" + Correção de texto "Avançadas" "Tema" "Ativar teclado dividido" "Mudar p/ outros mét. ent." "Tecla alterar idioma" - "%s ms" + "%s ms" "Predef. do sistema" "Utilizar nomes dos Contactos para sugestões e correções" "Sugestões personalizadas" @@ -27,7 +27,7 @@ "Maiúscula no início da frase" "Dicionário pessoal" "Dicionário principal" - "Mostrar sugestões de correcção" + Mostrar sugestões de correção "Apresentar sugestões de palavras ao escrever" "Bloquear palavras ofensivas" "Não sugerir palavras potencialmente ofensivas" @@ -50,66 +50,50 @@ "Espanhol (EUA)" Hindi-Inglês Sérvio (Latino) - Inglês (Reino Unido) %s - Inglês (EUA) %s - Espanhol (EUA) (%s) - Hindi-inglês %s - Sérvio %s - %s (Tradicional) - %s (Compacto) - Nenhum idioma (alfabeto) - "Alfabeto (QWERTY)" - "Alfabeto (QWERTZ)" - "Alfabeto (AZERTY)" - "Alfabeto (Dvorak)" - "Alfabeto (Colemak)" - "Alfabeto (PC)" + %s (Tradicional) + %s (Compacto) + Nenhum idioma Emojis "Adicionar" "Remover" "Guardar" "Idioma" - "Esquema" + Layout "Duração vibr. ao premir teclas" "Volume do som ao premir teclas" "Atraso ao manter tecla premida" "Emoji para teclado físico" "A tecla Alt física mostra a paleta de emoji" "Predefinido" - Bem-vindo ao%s + Bem-vindo ao%s "com a Escrita com Gestos" "Começar" - "Passo seguinte" - A configurar%s - Ative o%s - Assinale %s na área \"Idioma e introdução\" das definições. Assim, já poderá executar a aplicação no dispositivo. - %s já está ativado em Idiomas e definições de entrada, pelo que este passo está concluído. Vamos avançar para a próxima!\" + A configurar%s + Ative o%s + Assinale %s na área \"Idioma e introdução\" das definições. Assim, já poderá executar a aplicação no dispositivo. Ativar nas definições - Alternar para%s - De seguida, selecione %s\" como método de introdução ativo.\" + Alternar para%s + De seguida, selecione %s\" como método de introdução ativo.\" Alternar métodos de introdução Parabéns, configuração terminada! - Agora, já pode utilizar o %s para escrever nas suas aplicações. + Agora, já pode utilizar o %s para escrever nas suas aplicações. "Concluído" "Mostrar ícone da aplicação" "Mostrar ícone da aplicação no iniciador" - "Dicionários suplementares" + "Dicionários suplementares" "Dicionário disponível" - "Nenhum dicionário" "Última atualização" "Definições" "Eliminar" - Versão %1$s - "Adicionar" + Versão %1$s "Adicionar ao dicionário" "Atalho:" - "Idioma:" + Língua: "Escreva uma palavra" "Atalho opcional" "Editar palavra" - "Não tem palavras no dicionário do utilizador. Para adicionar uma palavra, toque no botão Adicionar (+)." "Em todos os idiomas" - "Mais idiomas…" + Mais línguas… " ABCDEFGHIJKLMNOPQRSTUVWXYZ" Mostrar dicas com toque longo Deslize para eliminar @@ -118,36 +102,34 @@ Impor modo incógnito Modo diurno/noturno automático Aparência usa as definições do sistema - Verificação ortográfica HeliBoard - Definições HeliBoard + Corretor ortográfico de HeliBoard + Definições de HeliBoard Introdução - Teclas adiccionais - Correcções + Teclas adicionais + Correções Sugestões Experimental Outras Desativar aprendizagem de palavras Mais teclas - Número de linha - Mostrar sempre n.º de linha + Linha de números + Mostrar sempre linha de números Mostrar dicas de teclas Alterar método de introdução com a tecla Espaço Toque longo na tecla Espaço abre menu de seleção do método de introdução Altura do teclado - Alfabeto (Colemak Mod-DH) - Alfabeto (Workman) Limite das teclas - Definições de verificação ortográfica HeliBoard + Definições do corretor ortográfico de HeliBoard Confiança da correção automática Se desativado, a tecla da área de transferência colará o conteúdo, se houver - "Usar idiomas do sistema" + Usar linguagens do sistema "Escolher o método de entrada" - Tempo de retenção de historio + Tempo de retenção de histórico Espaço automático depois de pontuação - %s (Akkhor) + %s (Akkhor) Sem limite Ativar Histórico da Área de Transferência - %smin. + %smin. Inserir espaço automaticamente após pontuação ao digitar uma nova palavra Histórico da área de transferência "Anular" @@ -198,10 +180,9 @@ Tempo de vida do rasto do gesto Ficheiro de biblioteca desconhecido. Tem a certeza de que o obteve de uma fonte fiável e que é para \'%s\'? Vibrar no modo Não Incomodar - %s (Fonético) + %s (Fonético) Substituir a versão de Emoji Dargínico (Urakhi) - Urakhi (%s) Atalhos de correção automática Quando ativado, os atalhos podem ser expandidos pela correção automática Definir imagem de fundo (paisagem) @@ -226,4 +207,213 @@ Direita Idiomas com dicionários Área de transferência + Fixar tecla da barra de ferramentas em toque longo + Selecionar teclas fixadas da barra de ferramentas + Conteúdo copiado + Mudar o lado do modo de uma mão + Não foi possível ler o ficheiro + Copiar layout existente + Texto personalizado na barra de espaço + Mansi + Personalizar moedas + O ficheiro selecionado é para %1$s, mas %2$s era esperado. utilizar ele ainda para %2$s? + Erro: escrita não compatível com este teclado + Branco Holo + Mais escuro + Preto + Texto da dica da tecla + Texto da faixa de sugestão + Fundo da tecla + Escuro + Cores dinâmicas + Índigo + Oceano + Mostrar apenas cores principais + Subtipo personalizado + Noite + Números + Estilo + Fundo da tecla funcional + Escolher cor automaticamente + Selecionar teclas da barra de ferramentas + Teclas com espaços estreitos + Kaitag + Símbolos (Árabe) + Selecionar cores para texto e fundos + Fundo do teclado + Linha inferior de emojis + Linha inferior da área de transferência + Violeta + Não mostrar sempre sugestões para campos de edição web + Os campos de edição na Web (encontrados principalmente nos navegadores) são uma causa muito comum de problemas com a configuração de mostrar sempre sugestões + Detecção de URL + Tenta detetar URLs e similares como uma única palavra + Selecionar fonte de dicas + Escala do espaço inferior + Excluir realmente o layout personalizado%s? + Linha de números (básica) + Definir imagem de fundo + Não-conector de zero largura + Fechar histórico da área de transferência + Ainda usar + Claro + Destaque + Adicionar layout personalizado + Selecionar língua + "Substituir realmente o dicionário \"%1$s\" adicionado pelo utilizador?\n\nDicionário atual:\n%2$s \n\nDicionário novo:\n%3$s" + Selecione um dicionário para adicionar. Dicionários no formato .dict podem ser descarregados%s. + Inverter a direção quando um teclado do subtipo direita-para-esquerda é selecionado + Direção da barra de ferramentas variável + Gesto de deslizar vertical na barra de espaço + Mostrar funções que podem passar despercebidas + Selecionar ordem do popup de teclas + Copiar para a Área de Transferência + Aviso: o layout está em uso atualmente + Erro de layout: %s + Toque para editar o layout bruto + Teclas funcionais (Mais símbolos) + Símbolos + Símbolos de telefone + Dicionário interno principal + Eliminar realmente o dicionário \"%s\" adicionado pelo utilizador? + "Sem um dicionário, irá receber apenas sugestões para o texto introduzido antes.<br>\n Pode descarregar dicionários %1$s, ou verifique se um dicionário para \"%2$s\" pode ser dewscarregado diretamente %3$s." + Erro: O ficheiro selecionado não é um ficheiro de dicionário válido + Peso: + Fundo da barra de espaço + ► Pressionar teclas da barra de ferramentas resulta em funcionalidade adicional: <br>\n\t• área de transferência &#65515; colar <br>\n\t• mover para esquerda/direita &#65515; palavra para esquerda/direita <br>\n\t• mover para cima/baixo &#65515; página para cima/baixo <br>\n\t• palavra para esquerda/direita &#65515; linha início/fim <br>\n\t• página para cima/baixo &#65515; página início/fim <br>\n\t• copiar &#65515; cortar <br>\n\t• selecionar palavra &#8596; selecionar tudo <br>\n\t• desfazer &#8596; refazer <br> <br>\n► Pressionar as teclas da barra de sugestões fixam as mesmas. <br> <br>\n► Pressionar a tecla da vírgula para aceder à visualização da área de transferência, modo de uma mão, configurações, ou mudar de idioma: <br>\n\t• A Visualização de Emojis e Mudança de Idioma desaparecerão se tiver a tecla correspondente ativada; <br>\n\t• Para alguns layouts, não é a tecla de vírgula, mas a tecla que seria no mesmo sítio. (ex: \\\'q\'\\ para o layout Dvorak). <br> <br>\n► Quando o modo privado está ativado, nenhuma palavra será aprendida, e nenhum emoji será adicionado aos recentes. <br> <br>\n► Pressione o botão do modo privado para aceder à barra de ferramentas. <br> <br>\n► Digitação por gestos: Deslize do shift até outra tecla para escrevê-la em maiúscula: <br>\n\t• Isto também funciona para as teclas \\\'?123\\\' para escrever um único símbolo do teclado de símbolos, e para teclas relacionadas. <br> <br>\n► Pressione a tecla shift ou de símbolos, pressione uma ou mais teclas, e então solte a tecla shift ou de símbolos para voltar ao teclado anterior. <br> <br>\n► Pressione uma sugestão na barra de sugestões para mostrar mais sugestões, e um botão para apagar essa sugestão. <br> <br>\n► Deslize para cima a partir de uma sugestão para abrir mais sugestões, e solte na sugestão que selecionar para usá-la. <br> <br>\n► Pressione um item no histórico da área de transferência para fixá-lo (mantê-lo na área de transferência até que o desafixe). <br> <br>\n► Deslize para a esquerda na visualização da área de transferência para remover um item (exceto quando estiver fixado) <br> <br>\n► Selecione texto e pressione shift para alternar entre maiúscula, minúscula, e escrever palavras com letra maiúscula. <br> <br>\n► Pode adicionar dicionários abrindo-os em um explorador de ficheiros: <br>\n\t• Isto apenas funciona com <i>content-uris></i> e não com <i>file-uris</i>, significando que pode não funcionar com certos exploradores de ficheiros.\n► Para utilizadores a fazer backups manuais com acesso root: <br>\n\t• Começando com o Android 7, o ficheiro de preferências compartilhado não está na localização padrão, por que a app está a usar %s. Isso é necessário para que as configurações possam ser lidas antes que o dispositivo seja desbloqueado, como por exemplo no boot; <br>>\n\t• O ficheiros está localizado em /data/user_de/0/package_id/shared_prefs/ porém isso pode depender do dispositivo e versão do Android. <br> <br>\n<i><b>Modo de depuração / APK de depuração</b></i> <br> <br>\n► Pressionar uma sugestão mostrará o dicionário de origem. <br> <br>\n► Ao usar o APK de depuração, pode encontrar configurações de depuração dentro das opções avançadas, porém a utilidade é limitada exceto a exportar dicionários nos registros. <br>\n\t• Para o APK de lançamento, precisará tocar na versão em <i>Sobre</i> várias vezes, e assim poderá encontrar as opções de depuração em <i>Preferências Avançadas</i>. <br>\n\t• Ao ativar <i>Mostrar informações de sugestão</i>, sugestões terão pequenos números em cima a mostrar a sua pontuação interna e dicionário de origem. <br> <br>\n► Num eventual crash da aplicação, será perguntado caso queira os registros do crash quando abrir as Configurações. <br> <br>\n► Ao usar digitação multi-linguagem, a barra de espaço mostrará um número de confiança para determinar a linguagem atualmente usada. <br> <br>\n► Sugestões terão pequenos números em cima a mostrar a sua pontuação interna e dicionário de origem (pode ser desativado). + Código de tecla + Dicionários + Palavra para a esquerda + Início da página + Palavra para a direita + Fim da página + Página para cima + Adicionar dicionário de um ficheiro + Areia + Chocolate + Nublado + Ativar teclado dividido (paisagem) + Distância de separação (paisagem) + Prima longamente a tecla de símbolos para o teclado numérico + Carregar + Espaço + Espaço reverte a correção automática + Mais símbolos + Formato de data e hora + Espaço automático após utilizar uma sugestão + Sem espaço automático ao premir Shift + Shift elimina o espaço automático pendente + Espaço automático antes de digitar uma palavra com gestos + Espaço automática após digitar uma palavra com gestos + Linha de números + Mostrar teclas de TLD + Substituir os popups do ponto final com domínios de topo ao digitar URLs e endereços de e-mail + Teclado dividido + Página para baixo + Selecionar teclas da barra de ferramentas de área de transferência + Isto irá desativar outras ações de toque longo para teclas da barra de ferramentas que não estão fixas + Mostrar dicas funcionais + Mostrar dicas se um toque longo numa tecla ativa funcionalidade adicional + Pressionando enter ou espaço após outras teclas no teclado de números + Essa configuração expõe todas as cores que são usadas internamente. A lista de cores pode mudar a qualquer momento. A cor padrão é aleatória, e os nomes não são traduzidos. + Entrada de gesto + seção de discussão + Sobre + Versão + Ver no GitHub + Guardar log + Barra de Ferramentas + %s (experimental) + Shift (ativado) + Foresta + Esta palavra já está presente no dicionário de utilizador%s. Introduza outra. + Texto da barra de espaço + Mostrar a barra de ferramentas se a digitação começar ou se o texto é selecionado + Apagar %s realmente? + Carregar ficheiro + Definido pelo utilizador + Definido pelo utilizador (noite) + Mostrar todas as cores + Ocultar barra de ferramentas automaticamente + Ocultar barra de ferramentas quando sugestões ficam disponíveis + Entrada de voz + Modo de uma mão + Inteiramente para a esquerda + Inteiramente para a direita + Cinza azul + Castanho + Gesto de deslizar horizontal na barra de espaço + Não mostrar novamente + Erro ao carregar o ficheiro de dicionário + Fechar + Toque no idioma para abrir configurações + Shift + Maiúsculas + Desativar modo de uma mão + Alterar o tamanho do modo de uma mão + Adicionar palavra + Arredondado + Cores + Cores (noite) + Licença de código aberto + Altere para o teclado principal depois… + A selecionar emoji no ecrã de emojis + Selecionar um ficheiro em formato compatível. Infomações sobre os formatos estão disponíveis em %s. + Cor da barra de navegação + Texto da tecla + Descrição de funções escondidas + Dagbani + Sesotho + Personalizar códigos de teclas da barra de ferramentas + armazenamento protegido pelo dispositivo + Adicionar variantes muito comuns (padrão) + Remover popups redundantes + Suprimir popups de teclas que já estão presentes no layout base + Defina um símbolo principal e até 6 secundários para moedas, separado com espaço + Repor realmente todos os ícones personalizados? + Pressionar código + Mostrar automaticamente a barra de ferramentas + Layouts secundários + Teclas funcionais (ecrã grande) + Telefone + Teclado númerico + Teclado numérico (paisagem) + A selecionar entrada do histórico da área de transferência + Pressionando enter ou espaço após outras teclas na tela de símbolos + Definir imagem para o modo de dia ou noite? + Dia + Rosa + Nenhuma + Mover cursor + Alternar teclado numérico + Personalizar ícones + Nome inválido + Mostrar mais cores + Teclas funcionais + Teclas funcionais (Símbolos) + Enter + Tab + Delete + Entrada de voz desativada + Mostrar / ocultar barra de ferramentas + Estilo do ícone + Escala do espaço inferior (paisagem) + Escala da fonte do teclado + Escala da fonte na visualização de emoji + Substituir dicionário + Licença Pública Geral GNU v3.0 + Espaço (teclado numérico) + Conector de zero largura + Escala do espaço lateral + Escala do espaço lateral (paisagem) + Reciclagem + Idiomas & Layouts + Localizar linha de números + Preferir localizados em vez de números latinos + Guardar em ficheiro + aqui + Pode encontrar e partilhar cores em %s. + Pode encontrar e partilhar layouts em %s. + Configurar o teclado + Escalar tamanho da tecla emoji com o do tipo de letra diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index 8e3cc9507..984db73b1 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -16,7 +16,7 @@ "Ativar teclado dividido" "Outros métodos de entrada" "Tecla de seleção de idioma" - "%s ms" + "%s ms" "Padrão do sistema" "Usa nomes dos Contatos para sugestões e correções" "Sugestões personalizadas" @@ -49,20 +49,9 @@ Espanhol (EUA) Hindi-Inglês "Sérvio (Latino)" - Inglês (Reino Unido) %s - Inglês (EUA) %s - Espanhol (EUA) (%s) - Hindi-inglês %s - Sérvio %s - %s (Tradicional) - %s (Compacto) - "Nenhum idioma (alfabeto)" - "Alfabeto (QWERTY)" - "Alfabeto (QWERTZ)" - "Alfabeto (AZERTY)" - "Alfabeto (Dvorak)" - "Alfabeto (Colemak)" - "Alfabeto (PC)" + %s (Tradicional) + %s (Compacto) + "Nenhum idioma" "Emojis" "Adicionar" "Remover" @@ -75,38 +64,33 @@ "Emojis para teclado físico" "Exibe o teclado de emojis ao pressionar a tecla Alt" "Padrão" - Bem-vindo ao %s + Bem-vindo ao %s "com entrada por gestos" "Começar" - "Próxima etapa" - A configurar %s - Ative o %s - Assinale %s na área \"Idioma e introdução\" das definições. Assim, já poderá executar a aplicação no dispositivo. - %s já está ativado nas nas definições de idioma e introdução. Esta etapa está concluída. Vamos avançar para a próxima! + A configurar %s + Ative o %s + Assinale %s na área \"Idioma e introdução\" das definições. Assim, já poderá executar a aplicação no dispositivo. Ativar nas definições - Alternar para %s - De seguida, selecione \"%s\" como método de introdução. + Alternar para %s + De seguida, selecione \"%s\" como método de introdução. Alternar métodos de introdução Parabéns, configuração terminada! - Agora, já pode utilizar o %s para escrever nas suas aplicações. + Agora, já pode utilizar o %s para escrever nas suas aplicações. "Concluído" "Mostrar ícone do app" "Mostrar ícone do app no iniciador" - "Dicionários complementares" + "Dicionários complementares" "Dicionário disponível" - "Nenhum dicionário disponível" "Última atualização" "Configurações" "Excluir" - Versão %1$s - "Adicionar" + Versão %1$s "Adicionar ao dicionário" "Atalho:" "Idioma:" "Digite uma palavra" "Atalho opcional" "Editar palavra" - "Você não tem nenhuma palavra no dicionário do usuário. Para adicionar uma palavra, toque no botão de adição (+)." "Para todos os idiomas" "Mais idiomas…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" @@ -114,7 +98,6 @@ Definições de verificação ortográfica HeliBoard Número de linha Mostrar sempre n.º de linha - Alfabeto (Colemak Mod-DH) Desativar aprendizagem de palavras Impor modo incógnito Tecla de emoji @@ -133,7 +116,6 @@ Mostrar dicas com toque longo Limite das teclas Teclas adicionais - Alfabeto (Workman) Aparência usa as definições do sistema Modo diurno/noturno automático Alterar método de introdução com a tecla Espaço @@ -145,11 +127,11 @@ Espaço automático após pontuação Inserir automaticamente espaço após a pontuação ao digitar uma nova palavra Histórico da área de transferência - %smin. + %smin. Sem Limite Ativar histórico da área de transferência Tempo de retenção do histórico - %s (Akkhor) + %s (Akkhor) "Desfazer" "Refazer" "Aprender com mensagens e dados digitados para melhorar sugestões" @@ -161,4 +143,5 @@ "Pesquisar" "Pausa" "Esp." + Escalar tamanho da tecla emoji com o do tipo de letra diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml index 95df55569..d7adfaa7f 100644 --- a/app/src/main/res/values-ro/strings.xml +++ b/app/src/main/res/values-ro/strings.xml @@ -16,7 +16,7 @@ Activează tastatura divizată "Comut. alte metode de introd." "Tastă comutare limbi" - "%s msec." + "%s msec." "Valoare prestabilită" Utilizează numele din Agendă pentru sugestii și corecții "Sugestii personalizate" @@ -49,20 +49,9 @@ "spaniolă (S.U.A.)" "Hinglish" "Sârbă (caractere latine)" - "Engleză (Regatul Unit) (%s)" - "Engleză (S.U.A.) (%s)" - "Spaniolă (S.U.A.) (%s)" - "Hinglish (%s)" - "Sârbă (%s)" - "%s (tradițională)" - "%s (Compact)" - "Nicio limbă (alfabet)" - "Alfabet (QWERTY)" - "Alfabet (QWERTZ)" - "Alfabet (AZERTY)" - "Alfabet (Dvorak)" - "Alfabet (Colemak)" - "Alfabet (PC)" + "%s (tradițională)" + "%s (Compact)" + "Nicio limbă" "Emoji" Adaugă Elimină @@ -75,38 +64,33 @@ "Emoji pentru tastatura fizică" "Tasta fizică Alt afișează panoul de emoji" "Prestabilit" - "Bun venit la %s" + "Bun venit la %s" "cu Tastarea gestuală" Începe - "Pasul următor" - Se configurează %s - Activează %s - Bifează %s în „Limbi și introducerea textului”. Astfel, o vei autoriza să ruleze pe dispozitiv. - %s este activată deja în „Limbi și introducerea textului”, deci ai finalizat pasul. Treci la următorul! + Se configurează %s + Activează %s + Bifează %s în „Limbi și introducerea textului”. Astfel, o vei autoriza să ruleze pe dispozitiv. Activează în Setări - Comută la %s - Apoi, selectează \"%s\" ca metodă de introducere a textului. + Comută la %s + Apoi, selectează \"%s\" ca metodă de introducere a textului. Comută între metodele de introducere a textului Felicitări, ai finalizat! - Acum, poți introduce text în toate aplicațiile preferate, utilizând %s. + Acum, poți introduce text în toate aplicațiile preferate, utilizând %s. "Finalizat" Afișează pictograma aplicației Afișează pictograma aplicației în lansator - "Dicționare suplimentare" + "Dicționare suplimentare" "Dicționar disponibil" - "Niciun dicționar" "Data ultimei modificări" "Setări" Șterge - Versiunea %1$s - "Adăugați" + Versiunea %1$s Adaugă în dicționar "Comandă rapidă:" "Limbă:" Introdu un cuvânt "Comandă rapidă opțională" Editează cuvântul - Nu ai niciun cuvânt în dicționarul utilizatorului. Pentru a adăuga un cuvânt, atinge butonul Adaugă (+). "Pentru toate limbile" "Mai multe limbi…" " AĂÂBCDEFGHIÎJKLMNOPQRSȘTȚUVWXYZ" @@ -133,7 +117,7 @@ Distanță divizare Comută ambele Tasta Emoji - %s min + %s min Fără limită Adaugă cuvinte în dicționarul personal Utilizează dicționarul personal al dispozitivului pentru a stoca cuvintele învățate @@ -178,7 +162,7 @@ Mai multe taste Limbi și aspecte Rând de numere - Limbă + @string/subtype_locale Limbă (prioritate) Aspect Simboluri @@ -204,12 +188,10 @@ Inversează direcția când este selectat un subtip de tastatură de la dreapta la stânga Direcție variabilă a barei de instrumente Apasă lung tasta simbol pentru tastatura numerică - Alfabet (Workman) Adaugă un aspect personalizat Selectează un fișier într-un format compatibil. Informațiile despre formate sunt disponibile %s. Încarcă fișierul Nu se poate citi fișierul - Setează numele aspectului Atinge pentru a edita aspectul brut Simboluri Simboluri (Arabă) @@ -234,7 +216,6 @@ Noros Pădure Indigo - Clic pentru previzualizare Selectează culorile pentru text și fundal Fundalul tastaturii Descrierea caracteristicilor ascunse @@ -264,8 +245,6 @@ Eroare de aspect: %s Violet Adaugă dicționar din fișier - Alfabet (Colemak Mod-DH) - Alfabet (Bépo) Ștergi cu adevărat aspectul personalizat %s? "Fără un dicționar, vei primi doar sugestii pentru textul pe care l-ai introdus anterior.<br>\n\n Poți descărca dicționare %1$s sau poți verifica dacă un dicționar pentru „%2$s” poate fi descărcat direct %3$s." Greutate: @@ -296,13 +275,12 @@ Scala de umplere inferioară Stânga integral Dreapta integral - Kaitag (%s) - %s (Akkhor) + %s (Akkhor) Selectează un dicționar de adăugat. Dicționarele în format .dict pot fi descărcate %s. Întunecată - %s (Probhat) - %s (Sebeolsik 390) - %s (Sebeolsik Final) + %s (Probhat) + %s (Sebeolsik 390) + %s (Sebeolsik Final) Setează imaginea de fundal Setezi imaginea pentru modul zi sau noapte? Zi @@ -322,10 +300,9 @@ Gest de glisare pe bara de spațiu verticală Fără Mută cursorul - %s (Student) + %s (Student) Începe întotdeauna instantaneu Text personalizat pe bara de spațiu - Mansi (%s) Afișare automată bară de instrumente Personalizează monedele Setează simboluri valutare principale și până la 6 secundare, separate prin spațiu @@ -337,7 +314,7 @@ Rândul Clipboard de jos Ascundere automată a barei de instrumente Ascunde bara de instrumente când sugestiile devin disponibile - %s (Extins) + %s (Extins) Copiază în clipboard Încarcă Salvează în fișier @@ -351,9 +328,8 @@ Durata de viață a traseului gesturilor Selectează tastele fixate din bara de instrumente Rând de numere - %s (Fonetic) + %s (Fonetic) Dargwa (Urakhi) - Urakhi (%s) Cod tastă Cod apăsare lungă Conținut copiat @@ -361,7 +337,6 @@ Suprascrie versiunea Emoji Previzualizare plutitoare Stilul pictogramei - Încărcarea va suprascrie tema curentă Personalizează codurile tastelor din bara de instrumente Sugerează conținut din clipboard Afișează conținutul clipboard copiat recent ca sugestie @@ -399,4 +374,54 @@ Introducerea vocală este dezactivată Afișează/ascunde bara de instrumente Resetezi cu adevărat toate pictogramele personalizate? + Subtip personalizat + Nume greșit + %s (Baishakhi) + Limbi cu dicționare + Tastatură împărțită + AVERTIZARE: Aspectul este utilizat în prezent + Setează imaginea de fundal (peisaj) + Dacă nu este setat, se va folosi imaginea portret + Poți găsi și împărtăși aspecte în %s. + Conectorul lățimii zero + Ștergi cu adevărat toate codurile cheie personalizate? + Distanța divizării (peisaj) + Activează tastatura divizată (peisaj) + Timp de restabilire a tastării rapide + Comenzi rapide corectare automată + Dacă este activat, comenzile rapide pot fi extinse prin corecție automată + Chiar ștergi %s? + Setează font personalizat din fișier + Suprimă tastele pop-up care sunt deja prezente pe aspectul de bază + Taste funcționale (ecran mare) + Aspecte secundare + Scală umplutură inferioară (peisaj) + Scală font la tastatură + Scală font vizualizare emoji + Coș de reciclare + Scală umplutură laterală (peisaj) + Scală umplutură laterală + Afișează indicii pe rândul cu numere + Distanța de deplasare pentru comutarea limbii + Poți găsi și împărtăși culori în %s. + secțiunea de discuții + Nu afișa întotdeauna sugestii pentru câmpurile de editare web + Câmpurile de editare web (mai ales în browser-e) sunt o cauză foarte frecventă pentru problemele cu setarea de afișare a sugestiilor întotdeauna + Format pentru tasta Timestamp + Afișează tastele pop-up TLD + Apăsarea Backspace anulează corectarea automată + Spațiu automat după tastarea unui cuvânt prin gesturi + Fără spațiu automat la apăsarea tastei Shift + Shift elimină în spațiul automat în așteptare + Folosește numele aplicațiilor + Spațiu automat după ce s-a ales o sugestie + Spațiu + Spațiu automat înainte de tastarea unui cuvânt prin gesturi + Rândul cu numere (de bază) + Scalarea dimensiunii tastelor emoji împreună cu dimensiunea fontului + Copie de rezervă restabilită + Apăsarea Enter sau Spațiu după alte taste în Numpad + Utilizează numele aplicațiilor instalate pentru sugestii și corecții + Ton implicit al pielii emoji + Neutru diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index f20a02d33..45ae03f56 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -14,61 +14,47 @@ "Исправление текста" Дополнительные "Тема" - "Включить разделённую клавиатуру" + Включить разделение клавиатуры Смена методов ввода "Клавиша смены языка" - %s мс. + %s мс. "По умолчанию" - "Подсказывать исправления на основе имен из списка контактов" + Использовать имена из Контактов для предложений и исправлений "Пользовательские словари" "Точки автоматически" - Вводить точку с пробелом двойным нажатием пробела + Двойное нажатие на клавишу пробела вставляет точку и пробел "Заглавные автоматически" - "Писать первое слово предложения с прописной буквы" + Автоматически ставить заглавную букву в начале предложений "Личный словарь" "Основной словарь" - "Варианты исправлений" + Показывать варианты исправлений "Предлагать варианты слов во время ввода" - "Блокировка нецензурных слов" + Блокировать нецензурные слова "Не предлагать слова, которые могут быть сочтены оскорбительными" "Автоисправление" "Автоматическое исправление опечаток при вводе знака препинания или пробела" Откл. "Умеренное" - "Активно" - "Очень активно" - "Подсказывать слова" - "Предлагать подсказки на основе предыдущего слова" + Активное + Агрессивное + Предлагать следующее слово + Учитывать предыдущее слово при формировании предложений "Включить функцию" - "Вводите слова, не отрывая пальца от клавиатуры" + Набирайте текст, проводя по буквам и не отрывая палец от экрана Рисовать линию Показывать подсказки Непрерывный ввод фраз - Проводите по клавише пробела после каждого слова + Умный пробел при жестах: вводите несколько слов, проводя пальцем через пробел Английский (Великобритания) Английский (США) Испанский (США) Хинглиш Мансийский Кайтагский - Сербский (латиница) - Английский (Великобритания) (%s) - Английский (США) (%s) - Испанский (США) (%s) - Хинглиш (%s) - Мансийский (%s) - Урахинский (%s) - Кайтагский (%s) - Сербский (%s) - %s (Традиционная) - %s (Компактная) - Стандартная (латиница) - Латиница (QWERTY) - Латиница (QWERTZ) - Латиница (AZERTY) - Латиница (Dvorak) - Латиница (Colemak) - Латиница (ПК) + Сербский (Латиница) + %s (Традиционная) + %s (Компактная) + Стандартная Эмодзи Добавить Удалить @@ -77,79 +63,73 @@ Раскладка Вибросигнал при нажатии клавиш Звук при нажатии клавиш - Долгое нажатие + Длительность долгого нажатия Эмодзи для физической клавиатуры Физическая клавиша Alt показывает все доступные эмодзи По умолчанию - Добро пожаловать в %s + Добро пожаловать в %s с непрерывным вводом Начать работу - Далее - Настроить %s - Включить %s - Убедитесь, что \\%s\" включен в настройках языка и ввода. Это позволит ему работать на вашем устройстве.\" - Приложение %s уже включено в настройках языка и ввода. Перейдите к следующему шагу!\" + Настроить %s + Включить %s + Убедитесь, что приложение \"%s\" включено в настройках языка и ввода. Это позволит ему работать на вашем устройстве. Включить в настройках - Переключитесь на %s - Теперь выберите \\%s\" в качестве активного метода ввода текста.\" + Переключитесь на %s + Теперь выберите \"%s\" в качестве активного метода ввода текста. Другой способ ввода Поздравляем, всё готово! - Теперь вы можете использовать приложение %s для набора текста. + Теперь вы можете использовать приложение %s для набора текста. Готово Показывать значок приложения Отображать значок приложения на панели запуска - Дополнительные словари - Доступен словарь - Словарей нет + Дополнительные словари + Доступный словарь Последнее обновление Настройки Удалить - Версия %1$s - Добавить + Версия %s Добавление в словарь "Быстрые клавиши:" "Язык:" Введите слово Ярлык для фразы (необязательно) Изменение слова - В пользовательском словаре пока ничего нет. Добавлять слова можно с помощью кнопки Добавить (+). Для всех языков Другие языки… " АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ" Ряд с цифрами Всегда показывать ряд с цифрами - "Показывать спецсимволы" - Показывать спецсимволы на клавишах + Показывать дополнительные символы + Показывать дополнительные символы для ввода долгим нажатием Увеличенные клавиши Масштабирование по высоте Обнаружение URL-адреса - Попытаться обнаружить URL-адреса и подобные им строки, как одно слово + Попытаться обнаружить URL-адреса и схожие конструкции как единое целое Удаление жестом - Проведите пальцем от клавиши удаления, чтобы выделить и удалить большие фрагменты текста одновременно + Проведите пальцем от клавиши удаления, чтобы выделить и сразу удалить большие фрагменты текста Резервное копирование и восстановление - Сохраните или загрузите из файла. Внимание: восстановление перезапишет существующие данные + Сохранение в файл или загрузка из него. Внимание: восстановление перезапишет текущие данные Ошибка резервного копирования: %s Ошибка восстановления из резервной копии: %s - Резервное копирование - Восстановление + Сохранить + Загрузить Многоязычный набор текста Загрузить библиотеку ввода жестами Предоставьте встроенную библиотеку для включения ввода жестами Больше клавиш Включить режим инкогнито - Отключить запоминание слов + Отключить запоминание новых слов Клавиша эмодзи История буфера обмена Включить журнал буфера обмена Проверка правописания HeliBoard Настройки проверки правописания - %s мин. + %s мин. Настройки HeliBoard Без ограничения Время хранения журнала буфера обмена - %s (Акхор) + %s (Акхор) Даргинский (Урахи) - Латиница (Workman) Контуры клавиш Использовать тему системы Стиль темы @@ -158,10 +138,9 @@ Цвета темы (тёмная тема) Внешний вид будет следовать настройкам системы Автоматически добавлять пробел после знаков препинания при вводе нового слова - Если отключено, клавиша буфера обмена будет вставлять содержимое буфера обмена, если таковое имеется - Автоматическая подстановка пробела после точки + Если отключено, клавиша буфера обмена вставит содержимое буфера обмена, если оно есть + Автоматически добавлять пробел после знаков препинания Изменять метод ввода с помощью пробела - Латиница (Colemak Mod-DH) Экспериментальные Другие настройки (разное) Исправления @@ -178,7 +157,6 @@ Пользовательская Пользовательская (тёмная тема) Автоматический выбор цвета - Нажмите для предпросмотра Выберите цвета для текста и фона Фон клавиатуры Текст клавиш @@ -194,14 +172,14 @@ Лицензия с открытым исходным кодом GNU General Public License v3.0 Закрыть - Языки системы - Нажмите на язык, чтобы открыть настройки + Использовать языки системы + Нажмите на язык для настроек "Выберите метод ввода" Описание скрытых функций Показать функции, которые могут остаться незамеченными "Отменить" "Повторить" - "Устройство будет запоминать то, что вы вводите чаще всего" + Анализировать переписку и введённый текст для улучшения предложений "ОК" "Далее" "Назад" @@ -217,9 +195,9 @@ Динамические цвета Показать функциональные подсказки Выберите файл в совместимом формате. Информация о форматах доступна %s. - %s (Себольсик 390) + %s (Себольсик 390) Использовать личный словарь устройства для хранения выученных слов - %s (Себольсик Финальная) + %s (Себольсик финальная) Шоколад Облачная День @@ -232,8 +210,8 @@ хранилище, защищённое устройством Лес Вам понадобится библиотека для \'%s\'. Несовместимые библиотеки могут привести к сбою при использовании набора текста с помощью жестов. \n\nВнимание: загрузка внешнего кода может представлять угрозу безопасности. Используйте библиотеку только из источника, которому вы доверяете. - Удалить библиотеку - Язык + Удалить + @string/subtype_locale Предпочитать локализованные латинские цифры Неизвестный файл библиотеки. Вы уверены, что получили его из надёжного источника и оно предназначено для \'%s\'? Серо-голубой @@ -245,14 +223,13 @@ Буфер обмена Индиго Ряд с цифрами - Алфавит (Бепо) Выберите порядок всплывающих клавиш Выберите источник подсказки Выберите язык Установить изображение для дневного или ночного режима? - Выбор клавиш панели инструментов + Выбрать клавиши панели инструментов Океан - Показывать подсказки, если длительное нажатие клавиши запускает дополнительные функции + Отображать подсказки, если долгое нажатие клавиши запускает дополнительную функцию Песок Выберите слово Показывать все цвета @@ -266,7 +243,7 @@ Виолетта Локализация ряда с цифрами Добавить все доступные варианты - Больше автокоррекции + Больше автоисправлений Расстояние разделения Игнорировать запросы других приложений об отключении предложений (может вызвать проблемы) Смена языка @@ -274,40 +251,39 @@ Ночь Больше не показывать Предупреждение: Отключение этого параметра приведёт к удалению изученных данных - Загрузить библиотеку + Загрузить Высота нижнего отступа Ввод жестами - Показывать больше букв с диакритическими знаками при удержании + Показывать больше букв с диакритическими знаками в всплывающем окне Режим одной руки Сохранить журнал Раскладка - Автокоррекция, даже если это явно не запрошено в поле ввода + Автоматически исправлять даже если поле ввода не требует этого Holo Белая Смена обоих Вверх - Удалить пользовательский словарь \"%s\"? + Удалить пользовательский словарь «%s»? Не получается прочитать файл здесь - Выберите для добавления словаря. Словари в формате .dict можно скачать %s. + Выберите словарь для добавления. Словари в формате .dict можно загрузить %s. Вправо Ошибка загрузки файла словаря Больше символов Вниз - В левый конец + Полностью влево Влево Заменить пользовательский словарь \"%1$s\"?\n\nТекущий словарь:\n%2$s\n\nНовый словарь:\n%3$s - В правый конец + Полностью вправо Вес: - Задать имя раскладки Загрузить файл - Скопировать текущую раскладку + Копировать текущую раскладку Ошибка раскладки: %s Это слово уже присутствует в пользовательском словаре %s. Пожалуйста, введите другое. Ошибка: скрипт несовместим с этой клавиатурой - Всё ещё используется - Выбранный файл предназначен для %1$s, но ожидался %2$s. Всё ещё используете его для %2$s? + Всё равно использовать + Выбранный файл предназначен для %1$s, но ожидался %2$s. Всё равно использовать его для %2$s? Ошибка: выбранный файл не является корректным словарем - "Без словаря вы будете получать предложения только для введенного ранее текста.<br>\n Вы можете загрузить словари %1$s или проверить, можно ли загрузить словарь для \"%2$s\" напрямую %3$s." + "Без словаря вы будете получать предложения только для введенного ранее текста.<br>\n Вы можете загрузить словари %1$s или проверить, можно ли загрузить словарь для «%2$s» напрямую %3$s." %s (экспериментальный) Символы Символы (арабские) @@ -316,65 +292,30 @@ Числовая клавиатура (ландшафт) Телефон Символы телефона - ► Долгое нажатие на закреплённые клавиши панели инструментов открывает дополнительные функции:<br> -\n\t• буфер обмена &#65515; вставить <br> -\n\t• сдвинуть курсор влево/вправо &#65515; перейти на слово влево/вправо <br> -\n\t• сдвинуть курсор вверх/вниз &#65515; перейти на страницу вверх/вниз <br> -\n\t• слово левее/правее &#65515; перейти к началу/концу строки <br> -\n\t• страница вверх/вниз &#65515; перейти к началу/концу страниц<br> -\n\t• копировать &#65515; вырезать <br> -\n\t• выделить слово &#8596; выделить всё <br> -\n\t• отменить &#8596; повторить <br> <br> -\n► Долгое нажатие на клавиши в панели инструментов полосы подсказок - закрепляет их в полосе подсказок. <br> <br> -\n► Долгое нажатие на клавишу запятой - открывает Вид буфера обмена, Вид эмодзи, Режим одной руки, Настройки или Сменить язык: <br> -\n\t• Вид эмодзи и Смена языка будут недоступны, если соответствующая клавиша уже включена; <br> -\n\t• Для некоторых раскладок клавиатуры это не клавиша запятой, а клавиша, находящаяся в том же положении (например, это клавиша \"q\" для раскладки Dvorak). <br> <br> -\n► Когда включен режим инкогнито, никакие слова не будут сохранены, и эмодзи не будут добавлены в список использованных. <br> <br> -\n► Нажмите на иконку Инкогнито, чтобы получить доступ к панели инструментов.<br> <br> -\n► Скользящий ввод клавиш: Проведите пальцем от клавиши Shift к другой клавише, чтобы ввести одну заглавную букву: <br> -\n\t• Это также работает для клавиши \\\'?123\\\' чтобы ввести один символ из клавиатуры символов и для связанных с ней клавиш. <br> <br> -\n► Удерживайте клавишу Shift или клавишу символа, нажмите одну или несколько клавиш и затем отпустите клавишу Shift или клавишу символа, чтобы переключиться обратно на предыдущую клавиатуру. <br> <br> -\n► Долгое нажатие на подсказку в полосе подсказок показывает ещё больше подсказок и клавишу удаления для удаления этой подсказки. <br> <br> -\n► Проведите пальцем вверх от подсказки, чтобы показать больше подсказок и отпустите на нужной, чтобы выбрать её. <br> <br> -\n► Долгое нажатие на запись в истории буфера обмена закрепляет её (сохраняет в буфере обмена до тех пор, пока вы не отмените закрепление). <br> <br> -\n► Проведите пальцем влево в просмотре буфера обмена, чтобы удалить запись (кроме случаев, когда она закреплена). <br> <br> -\n► Выделите текст и нажмите клавишу Shift, чтобы переключаться между прописными, строчными буквами и капитализацией слов. <br> <br> -\n► Вы можете добавить словари, открыв их в файловом менеджере: <br> -\n\t• Это работает только с <i>content-uris</i> и не работает с <i>file-uris</i>, поэтому это может не работать с некоторыми файловыми менеджерами. <br> <br> -\n► Для пользователей, создающих резервные копии вручную с правами суперпользователя (root): <br> -\n\t• Начиная с Android 7, файл общих настроек находится в другом месте, поскольку приложение использует %s. Это необходимо, чтобы настройки можно было прочитать до разблокировки устройства, например, при запуске; <br> -\n\t• Файл находится в /data/user_de/0/package_id/shared_prefs/, хотя это может зависеть от устройства и версии Android. <br> <br> -\n<i><b>Режим отладки / отладочная версия APK</b></i> <br> <br> -\n► Долгое нажатие на подсказку показывает исходный словарь. <br> <br> -\n► Когда используется отладочная версия APK, можно найти в Настройки отладки в разделе Расширенные настройки, хотя их полезность ограничена, за исключением выгрузки словарей в журнал. <br> -\n\t• Для релизной версии APK необходимо несколько раз нажать на версию в разделе <i>О программе</i>, затем можно найти настройки отладки в разделе <i>Расширенные настройки</i>. <br> -\n\t• Когда включена опция <i>Показать информацию о подсказках</i>, подсказки будут иметь небольшие цифры вверху, которые показывают некоторые внутренние баллы и исходный словарь. <br> <br> -\n► В случае аварийного завершения работы приложения, вам будет предложено, получить журналы ошибок, когда вы откроете раздел Настройки. <br> <br> -\n► Когда используется многоязычный ввод, клавиша пробела будет показывать значение достоверности, которое используется для определения текущего используемого языка. <br> <br> -\n► Подсказки будут иметь небольшие цифры вверху, которые показывают некоторые внутренние баллы и исходный словарь (это можно отключить). + ► Долгое нажатие на закреплённые клавиши панели инструментов открывает дополнительные функции:<br> \n\t• буфер обмена &#65515; вставить <br> \n\t• сдвинуть курсор влево/вправо &#65515; перейти на слово влево/вправо <br> \n\t• сдвинуть курсор вверх/вниз &#65515; перейти на страницу вверх/вниз <br> \n\t• слово левее/правее &#65515; перейти к началу/концу строки <br> \n\t• страница вверх/вниз &#65515; перейти к началу/концу страниц<br> \n\t• копировать &#65515; вырезать <br> \n\t• выделить слово &#8596; выделить всё <br> \n\t• отменить &#8596; повторить <br> <br> \n► Долгое нажатие на клавиши в панели инструментов полосы предложений - закрепляет их в полосе предложений. <br> <br> \n► Долгое нажатие на клавишу запятой - открывает Вид буфера обмена, Вид эмодзи, Режим одной руки, Настройки или Сменить язык: <br> \n\t• Вид эмодзи и Смена языка будут недоступны, если соответствующая клавиша уже включена; <br> \n\t• Для некоторых раскладок клавиатуры это не клавиша запятой, а клавиша, находящаяся в том же положении (например, это клавиша \"q\" для раскладки Dvorak). <br> <br> \n► Когда включен режим инкогнито, никакие слова не будут сохранены, и эмодзи не будут добавлены в список использованных. <br> <br> \n► Нажмите на иконку Инкогнито, чтобы получить доступ к панели инструментов.<br> <br> \n► Скользящий ввод клавиш: Проведите пальцем от клавиши Shift к другой клавише, чтобы ввести одну заглавную букву: <br> \n\t• Также это работает для клавиши \\\'?123\\\', чтобы ввести один символ из клавиатуры символов и для связанных с ней клавиш. <br> <br> \n► Удерживайте клавишу Shift или клавишу символа, нажмите одну или несколько клавиш и затем отпустите клавишу Shift или клавишу символа, чтобы переключиться обратно на предыдущую клавиатуру. <br> <br> \n► Долгое нажатие на предложение в полосе предложений показывает ещё больше предложений и клавишу удаления для удаления этого предложения. <br> <br> \n► Проведите пальцем вверх от предложения, чтобы показать больше предложений и отпустите на нужном, чтобы выбрать его. <br> <br> \n► Долгое нажатие на запись в истории буфера обмена закрепляет её (сохраняет в буфере обмена до тех пор, пока вы не отмените закрепление). <br> <br> \n► Проведите пальцем влево в просмотре буфера обмена, чтобы удалить запись (кроме случаев, когда она закреплена). <br> <br> \n► Выделите текст и нажмите клавишу Shift, чтобы переключаться между прописными, строчными буквами и капитализацией слов. <br> <br> \n► Вы можете добавить словари, открыв их в файловом менеджере: <br> \n\t• Это работает только с <i>content-uris</i> и не работает с <i>file-uris</i>, поэтому это может не работать с некоторыми файловыми менеджерами. <br> <br> \n► Для пользователей, создающих резервные копии вручную с правами суперпользователя (root): <br> \n\t• Начиная с Android 7, файл общих настроек находится в другом месте, поскольку приложение использует %s. Это необходимо, чтобы настройки можно было прочитать до разблокировки устройства, например, при запуске; <br> \n\t• Файл находится в /data/user_de/0/package_id/shared_prefs/, хотя это может зависеть от устройства и версии Android. <br> <br> \n<i><b>Режим отладки / отладочная версия APK</b></i> <br> <br> \n► Долгое нажатие на подсказку показывает исходный словарь. <br> <br> \n► Когда используется отладочная версия APK, можно найти в Настройки отладки в разделе Расширенные настройки, хотя их полезность ограничена, за исключением выгрузки словарей в журнал. <br> \n\t• Для релизной версии APK необходимо несколько раз нажать на версию в разделе <i>О программе</i>, затем можно найти настройки отладки в разделе <i>Расширенные настройки</i>. <br> \n\t• Когда включена опция <i>Показать информацию о подсказках</i>, подсказки будут иметь небольшие цифры вверху, которые показывают некоторые внутренние баллы и исходный словарь. <br> <br> \n► В случае аварийного завершения работы приложения, вам будет предложено, получить журналы ошибок, когда вы откроете раздел Настройки. <br> <br> \n► Когда используется многоязычный ввод, клавиша пробела будет показывать значение достоверности, которое используется для определения текущего используемого языка. <br> <br> \n► Предложения будут иметь небольшие цифры вверху, которые показывают некоторые внутренние баллы и исходный словарь (это можно отключить). Обратное направление, если выбран подтип клавиатуры с письмом справа налево Переменное направление панели инструментов - %s (Пробхат) + %s (Пробхат) Горизонтальный свайп по пробелу Вертикальный свайп по пробелу Бездействие Перемещение курсора - Длительное нажатие клавиши символов для цифровой клавиатуры - %s (Студенческая) + Долгое нажатие клавиши символов для цифровой клавиатуры + %s (Студенческая) Вырезать - Поведение клавиши смены языка + Действие клавиши смены языка Эмодзи Выбрать закреплённые клавиши панели инструментов - Это отключит остальные функции клавиш панели инструментов при длительном нажатии - Закреплять клавиши панели инструментов при длительном нажатии + При этом отключатся остальные функции долгого нажатия для незакреплённых кнопок панели + Закреплять клавиши панели инструментов при долгом нажатии Контент скопирован Показывать панель инструментов автоматически Скрывать панель инструментов автоматически Всегда использовать среднее предложение - При нажатии точки или пунктуации будет использовано среднее предложение + При нажатии пробела или знака препинания будет использовано среднее предложение Закрыть буфер обмена - Выбрать клавиши панели инструментов буфера обмена - %s (Расширенная) + Выбрать клавиши панели буфера обмена + %s (Расширенная) Скрывать панель инструментов при появлении предложений Панель инструментов Показывать панель инструментов при вводе или при выборе текста @@ -385,12 +326,11 @@ Функциональные клавиши (Символы) Всегда начинать немедленно Время восстановления быстрой печати - Кастомизировать валюты - Установить главные и до 6 дополнительных символа валют, разделённых пробелом + Настройка валют + Укажите основные и до 6 доп. символов валют через пробел Загрузить Сохранить в файл - Скопировать в буфер обмена - Загрузка перезапишет текущую тему + Копировать в буфер обмена Начало страницы Конец страницы Слово левее @@ -401,14 +341,14 @@ Показать недавно скопированное содержимое буфера обмена в качестве предложения Переключить цифровую клавиатуру Вернуться к основной клавиатуре после… - Выбор эмодзи в режиме просмотра - Выбор записи из истории буфера обмена - Нажатие Enter или пробела после других клавиш в режиме символов + Выбора эмодзи в режиме просмотра + Выбора записи из истории буфера обмена + Нажатия Enter или пробела после других клавиш в режиме символов Добавить самые распространённые варианты (по умолчанию) Удалить лишние всплывающие окна Убрать всплывающие клавиши, присутствующие в базовой раскладке Ряд с цифрами - Видеть предложенное слово во время набора жестами + Показывать предложенное слово во время набора жестами Время жизни следа жеста Пользовательский текст на клавише пробела Строка буфера обмена внизу @@ -425,38 +365,38 @@ Shift Shift (нажат) Caps lock - Голосовой ввод отключен + Голосовой ввод отключён Показать / скрыть панель инструментов Соединитель нулевой ширины Настроить коды клавиш панели инструментов Код клавиши - Код длинного нажатия + Код долгого нажатия Настроить иконки Разъединитель нулевой ширины Выход из режима работы одной рукой Действительно сбросить все настроенные иконки? - Bin - Вибрировать в режиме Не беспокоить - %s (Фонетика) - Автокоррекция сочетаний клавиш + Корзина + Вибрация в режиме Не беспокоить + %s (Фонетика) + Автоисправление сокращений Установить пользовательский шрифт из файла Масштаб нижнего отступа (ландшафт) Масштаб шрифта клавиатуры Масштаб шрифта отображения эмодзи Масштаб бокового отступа Масштаб бокового отступа (ландшафт) - Если включено, сочетания клавиш могут быть расширены с помощью автокоррекции + Если включено, автоисправление превратит сокращения в полные слова Вы действительно хотите удалить все настроенные коды клавиш? Переопределить версию эмодзи Если не установлено, будет использоваться портретное изображение Установить фоновое изображение (ландшафт) - Показывать подсказки в ряде с цифрами + Показывать подсказки в ряду с цифрами Расстояние смахивания для переключения языка Расстояние разделения (ландшафт) Включить разделение клавиатуры (ландшафт) Разделение клавиатуры Пользовательский подтип - %s (Байсахи) + %s (Байсахи) Предупреждение: раскладка в данный момент используется Действительно удалить %s? Дополнительные раскладки @@ -466,4 +406,27 @@ Найти и поделиться раскладками в %s. обсуждения Недопустимое имя + Показать всплывающие клавиши TLD + При вводе URL и адресов электронной почты заменить всплывающие подсказки клавиши точки на подсказки с доменами верхнего уровня + Нажатия Enter или пробела после других клавиш на цифровой клавиатуре + Поля ввода на веб-страницах (в основном в браузерах) часто вызывают проблемы с настройкой постоянного отображения подсказок + Ряд с цифрами (основной) + Не всегда показывать подсказки для полей ввода на веб-страницах + Пробел + Автопробел после ручного выбора предложения + Автопробел после набора слова жестами + Автопробел отключается при нажатии Shift + Нажатие Shift убирает запланированный автопробел + Автопробел перед набором слова жестами + Нажатие Backspace отменяет автоисправление + Формат ключа временной метки + Дагбани + Сесото + Масштабировать размер клавиш эмодзи вместе с размером шрифта + Резервная копия восстановлена + Использовать названия приложений + Использовать названия установленных приложений для предложений и исправлений + Тон кожи эмодзи по умолчанию + Нейтральный + %1$s (%2$s) diff --git a/app/src/main/res/values-si/strings.xml b/app/src/main/res/values-si/strings.xml index d0c6e07ba..98a90b5b6 100644 --- a/app/src/main/res/values-si/strings.xml +++ b/app/src/main/res/values-si/strings.xml @@ -16,7 +16,7 @@ "බෙදු යතුරු පුවරුව සබල කරන්න" "වෙනත් ආදාන ක්‍රම වෙත මාරුවන්න" "භාෂා මාරු යතුර" - "%sms" + "%sms" "පද්ධති සුපුරුදු" "යෝජනා සහ නිවැරදි කිරීම් සඳහා සබඳතා වෙතින් නම් භාවිතා කරන්න" "පෞද්ගලීකරණය කළ යෝජනා" @@ -49,20 +49,9 @@ "ස්පාඤ්ඤ (US)" "හින්ග්ලිෂ්" "සර්බියානු (ලතින්)" - "ඉංග්‍රීසි (එ.රා) (%s)" - "ඉංග්‍රීසි (එ.ජ) (%s)" - "ස්පාඤ්ඤ (එ.ජ) (%s)" - "හින්ග්ලිෂ් (%s)" - "සර්බියානු (%s)" - "%s (සාම්ප්‍රදායික)" - "%s (සංයුක්ත)" - "භාෂාවක් නැත (අකාරාදිය)" - "අකාරාදිය (QWERTY)" - "අකාරාදිය (QWERTZ)" - "අකාරාදිය (AZERTY)" - "අකාරාදිය (Dvorak)" - "අකාරාදිය (Colemak)" - "අකාරාදිය (PC)" + "%s (සාම්ප්‍රදායික)" + "%s (සංයුක්ත)" + "භාෂාවක් නැත" "ඉමොජි" "එක් කරන්න" "ඉවත් කරන්න" @@ -75,38 +64,33 @@ "භෞතික යතුරුපුවරුව සඳහා ඉමොජි" "භෞතික Alt යතුර ඉමොජි පෙන්වයි" "සුපුරුදු" - %s වෙත සාදරයෙන් පිළිගනිමු\" + %s වෙත සාදරයෙන් පිළිගනිමු\" "ඉංගිත ටයිප් කිරීම් සමග" "අරඹන්න" - "ඊළඟ පියවර" - %s සැකසෙමින් පවතී\" - %s සබල කරන්න\" - "කරණාකර ඔබගේ භාෂාව සහ ආදාන සැකසීම් තුළ \"%s\" පරීක්ෂා කරන්න. මෙය ඔබගේ උපාංගය මත එයට ධාවනය වීමට අනුමැතිය දෙනු ඇත." - "%s දැනටමත් ඔබගේ භාෂාව සහ ආදාන සැකසීම් තුළ සබල කර ඇත, එම නිසා මෙම පියවර නිමයි. ඊළඟ එක වෙතට!" + %s සැකසෙමින් පවතී\" + %s සබල කරන්න\" + "කරණාකර ඔබගේ භාෂාව සහ ආදාන සැකසීම් තුළ \"%s\" පරීක්ෂා කරන්න. මෙය ඔබගේ උපාංගය මත එයට ධාවනය වීමට අනුමැතිය දෙනු ඇත." "සැකසීම් තුළ සබල කරන්න" - %s වෙත මාරුවන්න\" - "ඊළඟට, ඔබගේ සක්‍රිය පෙළ-ආදාන ක්‍රමය ලෙස \"%s\" තෝරන්න." + %s වෙත මාරුවන්න\" + "ඊළඟට, ඔබගේ සක්‍රිය පෙළ-ආදාන ක්‍රමය ලෙස \"%s\" තෝරන්න." "ආදාන ක්‍රම මාරු කරන්න" "සුබපැතුම්, ඔබ සියල්ල පිහිටුවා ඇත!" - "දැන් ඔබට %s සමගින් ඔබගේ සියළුම ප්‍රියතම යෙදුම් වලින් ටයිප් කළ හැක." + "දැන් ඔබට %s සමගින් ඔබගේ සියළුම ප්‍රියතම යෙදුම් වලින් ටයිප් කළ හැක." "අවසන්" "යෙදුම් නිරූපකය පෙන්වන්න" "දියත්කරනය තුළ යෙදුම් නිරූපකය දර්ශනය කරන්න" - "ඈඳුම් ශබ්ද කෝෂ" + "ඈඳුම් ශබ්ද කෝෂ" "ශබ්දකෝෂය ලබාගත හැක" - "ශබ්ද කෝෂ ලබාගත නොහැක" "අවසන් වරට යාවත්කාලීන කළේ" "සැකසීම්" "මකන්න" - "%1$s අනුවාදය" - "එක් කරන්න" + "%1$s අනුවාදය" "ශබ්ද කෝෂය වෙත එක් කරන්න" "කෙටිමග:" "භාෂාව:" "වචනයක් ටයිප් කරන්න" "විකල්පමය කෙටිමග" "වචනය සංස්කරණය කරන්න" - "ඔබට පරිශීලක ශබ්ද කෝෂය තුළ වචන කිසිවක් නැත. වචනයක් එක් කිරීමට, එක් කිරීමේ (+) බොත්තම තට්ටු කරන්න." "සියලු භාෂාවන් සඳහා" "තවත් භාෂා…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml index 2a59b8872..be6961034 100644 --- a/app/src/main/res/values-sk/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -16,7 +16,7 @@ "Povoliť rozdelenie klávesnice" "Prepnúť na iné metódy vstupu" "Kľúč na prepínanie jazyka" - "%s ms" + "%s ms" "Predvolené" "Používať mená z kontaktov na návrhy a opravy" "Prispôsobené návrhy" @@ -49,20 +49,9 @@ "španielčina (USA)" Indická angličtina "srbčina (latinka)" - "angličtina (VB) (%s)" - "angličtina (USA) (%s)" - "španielčina (USA) (%s)" - "Hinglish (%s)" - "srbčina (%s)" - "%s (tradičná)" - "%s (kompaktná)" - "Žiadny jazyk (latinka)" - "latinka (QWERTY)" - "Latinka (QWERTZ)" - "Latinka (AZERTY)" - "Latinka (Dvorak)" - "Latinka (Colemak)" - "Latinka (PC)" + "%s (tradičná)" + "%s (kompaktná)" + "Žiadny jazyk" "Emoji" "Pridať" "Odstrániť" @@ -75,38 +64,33 @@ "Emodži pre fyzickú klávesnicu" "Paletu emodži zobrazíte stlačením fyzického klávesa Alt." "Predvolené" - "Vitajte v aplikácii %s" + "Vitajte v aplikácii %s" "s funkciou Písanie gestami" "Začať" - "Ďalší krok" - "Nastavenie aplikácie %s" - "Povoľte aplikáciu %s" - V nastaveniach Jazyky a vstup začiarknite políčko%s. Týmto aplikácii povolíte spustenie v zariadení.\" - "Aplikácia %s je už v nastaveniach Jazyky a vstup povolená. Prejdite na ďalší krok." + "Nastavenie aplikácie %s" + "Povoľte aplikáciu %s" + V nastaveniach Jazyky a vstup začiarknite políčko%s. Týmto aplikácii povolíte spustenie v zariadení.\" "Povoliť v Nastaveniach" - "Prepnite na aplikáciu %s." - Potom vyberte aplikáciu%s ako aktívnu metódu textového vstupu.\" + "Prepnite na aplikáciu %s." + Potom vyberte aplikáciu%s ako aktívnu metódu textového vstupu.\" "Prepnúť metódu vstupu" "Blahoželáme, všetko je nastavené!" - "Pomocou aplikácie %s teraz môžete zadávať text vo všetkých obľúbených aplikáciách." + "Pomocou aplikácie %s teraz môžete zadávať text vo všetkých obľúbených aplikáciách." "Hotovo" "Zobraziť ikonu aplikácie" "Zobrazenie ikony aplikácie v spúšťači" - "Doplnkové slovníky" + "Doplnkové slovníky" "K dispozícii je slovník" - "Slovníky sú nedostupné" "Posledná aktualizácia" "Nastavenia" "Odstrániť" - "Verzia %1$s" - "Pridať" + "Verzia %1$s" "Pridať do slovníka" "Klávesová skratka" "Jazyk:" "Zadajte slovo" "Voliteľná skratka" "Upraviť slovo" - "V používateľskom slovníku nie sú žiadne slová. Slovo pridáte klepnutím na tlačidlo Pridať (+)." "pre všetky jazyky" "Ďalšie jazyky…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" @@ -141,4 +125,4 @@ "Hľadať" "Pauza" "Čakať" - \ No newline at end of file + diff --git a/app/src/main/res/values-sl/strings.xml b/app/src/main/res/values-sl/strings.xml index 3b33cbc78..2cb2eee4a 100644 --- a/app/src/main/res/values-sl/strings.xml +++ b/app/src/main/res/values-sl/strings.xml @@ -16,7 +16,7 @@ "Omogoči razdeljeno tipkovnico" "Prekl. na drug nač. vnosa" "Tipka za preklop med jeziki" - "%s ms" + "%s ms" "Sistemsko privzeto" "Uporaba imen iz stikov za predloge in popravke" "Prilagojeni predlogi" @@ -49,20 +49,9 @@ "španščina (ZDA)" "Hindujska angleščina" "Srbščina (latinica)" - "angleščina (VB) (%s)" - "angleščina (ZDA) (%s)" - "španščina (ZDA) (%s)" - "Hindujska angleščina (%s)" - "Srbščina (%s)" - "%s (tradicionalna)" - "%s (kompaktna)" - "Brez jezika (latinice)" - "Latinica (QWERTY)" - "Latinica (QWERTZ)" - "Latinica (AZERTY)" - "Latinica (Dvorak)" - "Latinica (Colemak)" - "Latinica (PC)" + "%s (tradicionalna)" + "%s (kompaktna)" + "Brez jezika" "Emodžiji" "Dodaj" "Odstrani" @@ -75,38 +64,33 @@ "Emodžiji za fizično tipkovnico" "Fizična tipka Alt prikaže nabor emodžijev" "Privzeto" - "Pozdravljeni v aplikaciji %s" + "Pozdravljeni v aplikaciji %s" "s pisanjem s kretnjami" "Začnite" - "Naslednji korak" - "Nastavitev aplikacije %s" - "Omogočanje aplikacije %s" - V nastavitvah »Jeziki in vnos« izberite aplikacijo %s«. S tem ji omogočite izvajanje v napravi.\" - "Aplikacija %s je že omogočena v nastavitvah »Jeziki in vnos«, zato je to že opravljeno. Nadaljujte." + "Nastavitev aplikacije %s" + "Omogočanje aplikacije %s" + V nastavitvah »Jeziki in vnos« izberite aplikacijo %s«. S tem ji omogočite izvajanje v napravi.\" "Omogoči v nastavitvah" - "Preklop na aplikacijo %s" - Nato izberite aplikacijo %s« kot aktivni način vnosa besedila.\" + "Preklop na aplikacijo %s" + Nato izberite aplikacijo %s« kot aktivni način vnosa besedila.\" "Preklopi način vnosa" "Čestitamo, pripravljeni ste." - "Zdaj lahko z aplikacijo %s tipkate v vseh svojih priljubljenih aplikacijah." + "Zdaj lahko z aplikacijo %s tipkate v vseh svojih priljubljenih aplikacijah." "Končano" "Pokaži ikono aplikacije" "Prikaz ikone aplikacije v zaganjalniku" - "Dodatni slovarji" + "Dodatni slovarji" "Slovar je na voljo" - "Ni slovarjev" "Nazadnje posodobljeno" "Nastavitve" "Izbriši" - "Različica %1$s" - "Dodaj" + "Različica %1$s" "Dodaj v slovar" "Bližnjica:" "Jezik:" "Vnesite besedo" "Izbirna bližnjica" "Uredi besedo" - "V uporabniškem slovarju ni besed. Če želite dodati besedo, se dotaknite gumba za dodajanje (+)." "Za vse jezike" "Več jezikov …" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" @@ -124,7 +108,7 @@ Predlogi Razno Brez omejitve - %smin. + %smin. Omogoči tipko odložišča Čas shranjevanja zgodovine Onemogočite, da boste s tipko odložišča lahko prilepili vsebino @@ -157,4 +141,4 @@ "Iskanje" "Zaus." "Čakaj" - \ No newline at end of file + diff --git a/app/src/main/res/values-sq/strings.xml b/app/src/main/res/values-sq/strings.xml index 74050b52e..e897dc659 100644 --- a/app/src/main/res/values-sq/strings.xml +++ b/app/src/main/res/values-sq/strings.xml @@ -17,7 +17,7 @@ "Aktivizo tastierën e ndarë" "Kalo në metoda të tjera hyrjeje" "Tasti i ndryshimit të gjuhës" - "%s milisek." + "%s milisek." "Parazgjedhja e sistemit" "Përdor emra nga \"Kontaktet\" për sugjerime dhe korrigjime" "Sugjerime të personalizuara" @@ -50,20 +50,9 @@ "spanjisht (SHBA)" "hinglisht" "serbisht (latin)" - "anglisht (MB) (%s)" - "anglisht (SHBA) (%s)" - "spanjisht (SHBA) (%s)" - "hinglisht (%s)" - "serbisht (%s)" - "%s (tradicionale)" - "%s (kompakte)" - "nuk ka gjuhë (alfabeti)" - "alfabeti (QWERTY)" - "alfabeti (QWERTZ)" - "alfabeti (AZERTY)" - "alfabeti (dvorak)" - "alfabeti (Colemak)" - "alfabeti (PC)" + "%s (tradicionale)" + "%s (kompakte)" + "nuk ka gjuhë" "\"Emoji\"" "Shto" "Hiq" @@ -76,38 +65,33 @@ "Emoji për tastierën fizike" "Tasti fizik Alt shfaq paletën me emoji" "I parazgjedhur" - "Mirë se erdhe në %s" + "Mirë se erdhe në %s" "me \"Shkrimin me gjeste\"" "Fillo" - "Hapi tjetër" - "Po konfiguron %s" - "Aktivizo %s" - "Kontrollo \"%s\" te \"Cilësimet e gjuhës dhe hyrjes\". Kjo do ta autorizojë atë që të ekzekutohet në pajisjen tënde." - "%s është i aktivizuar tashmë te \"Cilësimet e gjuhës dhe të hyrjes\", kështu që ky hap ka mbaruar. Vazhdo me hapin tjetër!" + "Po konfiguron %s" + "Aktivizo %s" + "Kontrollo \"%s\" te \"Cilësimet e gjuhës dhe hyrjes\". Kjo do ta autorizojë atë që të ekzekutohet në pajisjen tënde." "Aktivizo te \"Cilësimet\"" - "Kalo në %s" - "Më pas, përzgjidh \"%s\" si metodën tënde aktive të hyrjes së tekstit." + "Kalo në %s" + "Më pas, përzgjidh \"%s\" si metodën tënde aktive të hyrjes së tekstit." "Ndrysho metodat e hyrjes" "Urime, tani je gati!" - "Tani mund të shkruash të gjitha aplikacionet e tua të preferuara me %s." + "Tani mund të shkruash të gjitha aplikacionet e tua të preferuara me %s." "U përfundua" "Shfaq ikonën e aplikacionit" "Shfaq ikonën e aplikacionit në mekanizimin e nisjes" - "Fjalorë shtesë" + "Fjalorë shtesë" "Fjalor i përdorshëm" - "Nuk mund të përdoret asnjë fjalor" "Përditësimi i fundit" "Cilësimet" "Fshi" - "Versioni %1$s" - "Shto" + "Versioni %1$s" "Shto në fjalor" "Shkurtorja:" "Gjuha:" "Shkruaj një fjalë" "Shkurtore opsionale" "Redakto fjalën" - "Nuk ke asnjë fjalë në fjalorin e përdoruesit. Për të shtuar një fjalë, trokit te butoni \"Shto (+)\"." "Për të gjitha gjuhët" "Gjuhë të tjera…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" diff --git a/app/src/main/res/values-sr/strings.xml b/app/src/main/res/values-sr/strings.xml index fcee9f37c..c5c75d43a 100644 --- a/app/src/main/res/values-sr/strings.xml +++ b/app/src/main/res/values-sr/strings.xml @@ -16,7 +16,7 @@ "Омогући подељену тастатуру" "Пребаци на друге методе уноса" "Тастер за пребацивање језика" - %s мс + %s мс "Подразумевано" "Користи имена из Контаката за предлоге и исправке" "Персонализовани предлози" @@ -49,20 +49,9 @@ "шпански (САД)" "хенглески" "српски (латиница)" - енглески (UK) (%s) - енглески (US) (%s) - шпански (US) (%s) - хенглески (%s) - српски (%s) - %s (традиционални) - %s (компактна) - "Нема језика (абецеда)" - "абецеда (QWERTY)" - "абецеда (QWERTZ)" - "абецеда (AZERTY)" - "абецеда (Dvorak)" - "абецеда (Colemak)" - "абецеда (PC)" + %s (традиционални) + %s (компактна) + "Нема језика" "Емотикони" "Додај" "Уклони" @@ -75,38 +64,33 @@ "Емоџи за физичку тастатуру" "Физички тастер Alt показује палету емоџија" "Подразумевано" - Добро дошли у %s + Добро дошли у %s "помоћу Куцања покретима" "Започнимо" - "Следећи корак" - Подешавање апликације %s - Омогућите апликацију %s - Потврдите апликацију %s“ у Подешавањима језика и уноса. Тако јој одобравате покретање на уређају.\" - "Апликација %s је већ омогућена у Подешавањима језика и уноса, па је овај корак готов. Пређимо на следећи!" + Подешавање апликације %s + Омогућите апликацију %s + Потврдите апликацију %s“ у Подешавањима језика и уноса. Тако јој одобравате покретање на уређају.\" "Омогући у Подешавањима" - "Пребаците на %s" - Затим изаберите %s“ као активни метод уноса текста.\" + "Пребаците на %s" + Затим изаберите %s“ као активни метод уноса текста.\" "Пребаци методе уноса" "Честитамо, све је спремно!" - "Сада можете да куцате у свим омиљеним апликацијама помоћу %s." + "Сада можете да куцате у свим омиљеним апликацијама помоћу %s." "Завршено" "Прикажи икону апликације" "Икона апликације се приказује у покретачу" - "Помоћни речници" + "Помоћни речници" "Речник је доступан" - "Нема доступних речника" "Последње ажурирање" "Подешавања" "Избриши" - "Верзија %1$s" - "Додај" + "Верзија %1$s" "Додавање у речник" "Пречица:" "Језик:" "Унесите реч" "Опционална пречица" "Измена речи" - "Немате ниједну реч у корисничком речнику. Да бисте додали реч, додирните дугме Додај (+)." "За све језике" "Још језика…" " АБВГДЂЕЖЗИЈКЛЉМНЊОПРСТЋУФХЦЧЏШ" @@ -132,14 +116,12 @@ Дуг притисак на тастер за размак ће приказати мени за избор метода уноса Аутоматски режим дан/ноћ Изглед ће пратити подешавања система - %s (Акхор) - Абецеда (Colemak Mod-DH) - Абецеда (Workman) + %s (Акхор) Без лимита Омогући историју међуспремника Време задржавања историје Висина тастатуре - %sмин + %sмин Прикажи савете за дуги притисак Уклањање превлачењем Емоји кључ diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index 0d706689b..ef33bb2d8 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -16,7 +16,7 @@ "Aktivera delat tangentbord" Byt till andra inmatningssätt Språkbytestangent - %sms + %sms "Standardinställning" "Använd namn från Kontakter för förslag och korrigeringar" "Anpassade förslag" @@ -49,20 +49,9 @@ Spanska (USA) Hingelska "Serbiska (latinsk)" - Engelska (UK) (%s) - Engelska (USA) (%s) - Spanska (USA) (%s) - Hingelska (%s) - Serbiska (%s) - %s (traditionell) - %s (kompakt) - "Inget språk (alfabet)" - "Alfabet (QWERTY)" - "Alfabet (QWERTZ)" - "Alfabet (AZERTY)" - "Alfabet (Dvorak)" - "Alfabet (Colemak)" - Alfabet (pc) + %s (traditionell) + %s (kompakt) + "Inget språk" Emoji "Lägg till" "Ta bort" @@ -75,38 +64,33 @@ "Emoji för fysiskt tangentbord" "Den fysiska Alt-tangenten visar emoji-paletten" "Standard" - Välkommen till %s + Välkommen till %s "med svepskrivning" "Kom igång" - "Nästa steg" - Konfigurerar %s - Aktivera %s - Markera \"%s\" i dina Språk & inmatning-inställningar. Detta kommer att tillåta att den körs på din enhet. - %s är redan aktiverad i dina Språk & inmatning-inställningar, så detta steg är färdigt. Vidare till nästa! + Konfigurerar %s + Aktivera %s + Markera \"%s\" i dina Språk & inmatning-inställningar. Detta kommer att tillåta att den körs på din enhet. Aktivera i Inställningar - Byt till %s - Välj sedan \"%s\" som din aktiva textinmatningsmetod. + Byt till %s + Välj sedan \"%s\" som din aktiva textinmatningsmetod. "Byt inmatningsmetod" Grattis, nu är allt klart! - Nu kan du skriva i alla dina favoritappar med %s. + Nu kan du skriva i alla dina favoritappar med %s. Slutförd "Visa appikon" "Visa appikonen i startprogrammet" - "Tilläggsordlistor" + "Tilläggsordlistor" Ordlista tillgänglig - Inga ordlistor tillgängliga "Informationen uppdaterades senast" "Inställningar" "Ta bort" - Version %1$s - "Lägg till" + Version %1$s "Lägg till i ordlista" "Genväg:" "Språk:" "Skriv ett ord" "Valfri genväg" "Redigera ord" - "Du har inga ord i din egen ordlista. Tryck på knappen Lägg till (+) om du vill lägga till ett ord." "För alla språk" "Fler språk …" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" @@ -114,7 +98,7 @@ Förslag Experimentella Diverse - %s min + %s min Ingen gräns Långtryckning på mellanslagstangenten öppnar menyn för val av inmatningsmetod Ändra inmatningsmetod med mellanslagstangenten @@ -140,9 +124,7 @@ Automatiskt mellanslag efter skiljetecken Fler tangenter Skala för tangentbordets höjd - %s (akkhor) - Alfabet (Colemak Mod-DH) - Alfabet (Workman) + %s (akkhor) Kantlinjer runt tangenter Automatiskt dag-/nattläge Utseendet kommer att följa systeminställningarna diff --git a/app/src/main/res/values-sw/strings.xml b/app/src/main/res/values-sw/strings.xml index 7b249231e..917a2fe2d 100644 --- a/app/src/main/res/values-sw/strings.xml +++ b/app/src/main/res/values-sw/strings.xml @@ -17,7 +17,7 @@ "Washa muundo wa kibodi inayogawanyika" "Badilisha hadi kwa mbinu zingine za ingizo" "Kitufe cha kubadilisha lugha" - "Milisekunde %s" + "Milisekunde %s" "Chaguomsingi la mfumo" "Tumia majina kutoka kwa Anwani kama mapendekezo na marekebisho" "Mapendekezo yaliyobadilishwa kukufaa" @@ -50,20 +50,9 @@ "Kihispania (Marekani)" "Hinglish" "Kiserbia (Kilatino)" - "Kiingereza (UK) (%s)" - "Kiingereza (US) (%s)" - "Kihispania (US) (%s)" - "Hinglish (%s)" - "Kiserbia (%s)" - "%s (cha Jadi)" - "%s (Thabiti)" - "Hakuna lugha (Alfabeti)" - "Alfabeti (QWERTY)" - "Alfabeti (QWERTZ)" - "Alfabeti (AZERTY)" - "Alfabeti (Dvorak)" - "Alfabeti (Colemak)" - "Alfabeti (PC)" + "%s (cha Jadi)" + "%s (Thabiti)" + "Hakuna lugha" "Emoji" "Ongeza" "Ondoa" @@ -76,38 +65,33 @@ "Emoji za kibodi halisi" "Kitufe halisi cha Alt huonyesha kibao cha emoji" "Chaguomsingi" - "Karibu kwenye %s" + "Karibu kwenye %s" "kwa Kuandika kwa ishara" "Anza kutumia" - "Hatua inayofuata" - "Inasanidi %s" - "Washa %s" - "Tafadhali angalia \"%s\" katika mipangilio yako ya Lugha na mbinu ya kuingiza data. Hatua hii itairuhusu kutumika kwenye kifaa chako." - "%s tayari imewashwa katika mipangilio yako ya Lugha na kuingiza data, kwa hivyo hatua hii imekamilika. Nenda kwenye hatua inayofuata!" + "Inasanidi %s" + "Washa %s" + "Tafadhali angalia \"%s\" katika mipangilio yako ya Lugha na mbinu ya kuingiza data. Hatua hii itairuhusu kutumika kwenye kifaa chako." "Washa katika Mipangilio" - "Badilisha kwenda %s" - "Kisha, chagua \"%s\" kama mbinu yako inayotumika ya kuingiza data ya maandishi." + "Badilisha kwenda %s" + "Kisha, chagua \"%s\" kama mbinu yako inayotumika ya kuingiza data ya maandishi." "Badilisha mbinu za kuingiza data" "Hongera, uko tayari!" - "Sasa unaweza kuchapa programu zako zote uzipendazo ukitumia %s." + "Sasa unaweza kuchapa programu zako zote uzipendazo ukitumia %s." "Imemaliza" "Onyesha aikoni ya programu" "Onyesha aikoni ya programu kwenye kifungua programu" - "Kamusi za nyongeza" + "Kamusi za nyongeza" "Kamusi inapatikana" - "Hakuna kamusi inayopatikana" "Ilibadilishwa mwisho" "Mipangilio" "Futa" - "Toleo la %1$s" - "Ongeza" + "Toleo la %1$s" "Ongeza kwenye kamusi" "Njia ya mkato:" "Lugha:" "Chapa neno" "Njia ya mkato ya hiari" "Badilisha neno" - "Huna maneno yoyote katika kamusi ya mtumiaji. Gusa kitufe cha Ongeza (+) ili kuongeza neno." "Ya lugha zote" "Lugha zingine…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" diff --git a/app/src/main/res/values-ta/strings.xml b/app/src/main/res/values-ta/strings.xml index ceb060b1a..d9270daa0 100644 --- a/app/src/main/res/values-ta/strings.xml +++ b/app/src/main/res/values-ta/strings.xml @@ -16,7 +16,7 @@ "பிரிக்கப்பட்ட விசைப்பலகையை இயக்கு" "பிற உள்ளீட்டு முறைகளுக்கு மாறு" "மொழி மாற்ற விசை" - "%sமி.வி." + "%sமி.வி." "அமைப்பின் இயல்புநிலை" "பரிந்துரைகள், திருத்தங்கள் ஆகியவற்றிற்கு தொடர்புகளிலிருந்து பெயர்களை பயன்படுத்து" "தனிப்பட்ட பரிந்துரைகள்" @@ -49,20 +49,9 @@ "ஸ்பானிஷ் (யூஎஸ்)" "ஹிங்கிலிஷ்" "செர்பியன் (லத்தீன்)" - "ஆங்கிலம் (யூகே) (%s)" - "ஆங்கிலம் (யூஎஸ்) (%s)" - "ஸ்பானிஷ் (யூஎஸ்) (%s)" - "ஹிங்கிலிஷ் (%s)" - "செர்பியன் (%s)" - "%s (பாரம்பரியமானது)" - "%s (வசதியான)" - "மொழியில்லை (அகரவரிசை)" - "அகரவரிசை (க்வெர்டி)" - "அகரவரிசை (க்வெர்ட்ச்)" - "அகரவரிசை (எசெர்டி)" - "அகரவரிசை (ட்வொராக்)" - "அகரவரிசை (கொல்மக்)" - "அகரவரிசை (பிசி)" + "%s (பாரம்பரியமானது)" + "%s (வசதியான)" + "மொழியில்லை" "எமோஜி" "சேர்" "அகற்று" @@ -75,38 +64,33 @@ "கைமுறை விசைப்பலகைக்கான ஈமோஜி" "ஈமோஜி பலகத்தைக் காட்டும் கைமுறை Alt விசை" "இயல்புநிலை" - %s பயன்பாட்டிற்கு வரவேற்கிறோம்\" + %s பயன்பாட்டிற்கு வரவேற்கிறோம்\" "ஸ்வைப் உள்ளீடு மூலம்" "தொடங்குக" - "அடுத்த கட்டம்" - %s ஆப்ஸை அமைக்கிறது\" - %s ஆப்ஸை இயக்கவும்\" - "மொழி & உள்ளீட்டு அமைப்புகளில் \"%s\" ஆப்ஸைத் தேர்வு செய்யவும். இதனால், சாதனத்தில் ஆப்ஸை இயக்கலாம்." - "மொழி & உள்ளீட்டு அமைப்புகளில் %s ஏற்கனவே இயக்கப்பட்டுள்ளதால் இப்படிமுறை முடிந்தது. அடுத்த படிமுறைக்குச் செல்லவும்!" + %s ஆப்ஸை அமைக்கிறது\" + %s ஆப்ஸை இயக்கவும்\" + "மொழி & உள்ளீட்டு அமைப்புகளில் \"%s\" ஆப்ஸைத் தேர்வு செய்யவும். இதனால், சாதனத்தில் ஆப்ஸை இயக்கலாம்." "அமைப்புகளில் இயக்கு" - %s க்கு மாறவும்\" - "அடுத்து, உங்கள் செயலில் உள்ள உரை உள்ளீட்டு முறையாக \"%s\" பயன்பாட்டைத் தேர்ந்தெடுக்கவும்." + %s க்கு மாறவும்\" + "அடுத்து, உங்கள் செயலில் உள்ள உரை உள்ளீட்டு முறையாக \"%s\" பயன்பாட்டைத் தேர்ந்தெடுக்கவும்." "உள்ளீட்டு முறைகளை மாற்றவும்" "வாழ்த்துகள், தயாராகிவிட்டீர்கள்!" - "%s ஆப்ஸ் மூலம் உங்களுக்கு விருப்பமான எல்லா ஆப்ஸ்களிலும் நீங்கள் உள்ளிடலாம்." + "%s ஆப்ஸ் மூலம் உங்களுக்கு விருப்பமான எல்லா ஆப்ஸ்களிலும் நீங்கள் உள்ளிடலாம்." "முடிந்தது" "ஆப்ஸ் ஐகானைக் காட்டு" "துவக்கியில் ஆப்ஸ் ஐகானைக் காட்டும்" - "துணை அகராதிகள்" + "துணை அகராதிகள்" "அகராதி கிடைக்கிறது" - "அகராதிகள் எதுவும் இல்லை" "இறுதியாகப் புதுப்பித்தது" "அமைப்பு" "நீக்கு" - "%1$s பதிப்பு" - "சேர்" + "%1$s பதிப்பு" "அகராதியில் சேர்" "ஷார்ட்கட்:" "மொழி:" "வார்த்தையை உள்ளிடவும்" "விருப்பத்திற்குரிய ஷார்ட்கட்" "வார்த்தையைத் திருத்து" - "பயனர் அகராதியில் எந்தச் சொற்களும் இல்லை. சொல்லைச் சேர்க்க, சேர் (+) எனும் பொத்தானைத் தட்டவும்." "எல்லா மொழிகளுக்கும்" "மேலும் மொழிகள்…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" diff --git a/app/src/main/res/values-te/strings.xml b/app/src/main/res/values-te/strings.xml index c5bb08c13..15d418a2d 100644 --- a/app/src/main/res/values-te/strings.xml +++ b/app/src/main/res/values-te/strings.xml @@ -16,7 +16,7 @@ "విభజన కీబోర్డ్‌ను ప్రారంభించు" "ఇతర ఇన్‌పుట్ పద్ధతులకు మారండి" "భాష మార్పు కీ" - "%sమిసె" + "%sమిసె" "సిస్టమ్ డిఫాల్ట్" "సూచనలు మరియు సవరణల కోసం పరిచయాల నుండి పేర్లను ఉపయోగించు" "వ్యక్తిగతీకరించబడిన సూచనలు" @@ -49,20 +49,9 @@ "స్పానిష్ (యుఎస్)" "హింగ్లీష్" "సెర్బియన్ (లాటిన్)" - "ఆంగ్లం (యుకె) (%s)" - "ఆంగ్లం (యుఎస్) (%s)" - "స్పానిష్ (యుఎస్) (%s)" - "హింగ్లీష్ (%s)" - "సెర్బియన్ (%s)" - "%s (సాంప్రదాయకం)" - "%s (కాంపాక్ట్)" - "భాష లేదు (ఆల్ఫాబెట్)" - "ఆల్ఫాబెట్ (QWERTY)" - "ఆల్ఫాబెట్ (QWERTZ)" - "ఆల్ఫాబెట్ (AZERTY)" - "ఆల్ఫాబెట్ (డ్వోరక్)" - "ఆల్ఫాబెట్ (కోల్‌మాక్)" - "ఆల్ఫాబెట్ (PC)" + "%s (సాంప్రదాయకం)" + "%s (కాంపాక్ట్)" + "భాష లేదు" "ఎమోజి" "జోడించండి" "తీసివేయి" @@ -75,38 +64,33 @@ "భౌతిక కీబోర్డ్ కోసం ఎమోజి" "భౌతిక Alt కీ ఎమోజి ఫలకాన్ని చూపుతుంది" "డిఫాల్ట్" - %sకు స్వాగతం\" + %sకు స్వాగతం\" "సంజ్ఞ టైపింగ్‌తో" "ప్రారంభించండి" - "తర్వాత దశ" - %sని సెటప్ చేయడం\" - %sని ప్రారంభించండి\" - "దయచేసి మీ భాషలు & ఇన్‌పుట్ సెట్టింగ్‌ల్లో \"%s\" తనిఖీ చేయండి. ఇది మీ పరికరంలో అమలు కావడానికి దీన్ని ప్రామాణీకరిస్తుంది." - "%s ఇప్పటికే మీ భాషలు & ఇన్‌పుట్ సెట్టింగ్‌ల్లో ప్రారంభించబడింది, కనుక ఈ దశ పూర్తయింది. తర్వాత దశకు వెళ్లండి!" + %sని సెటప్ చేయడం\" + %sని ప్రారంభించండి\" + "దయచేసి మీ భాషలు & ఇన్‌పుట్ సెట్టింగ్‌ల్లో \"%s\" తనిఖీ చేయండి. ఇది మీ పరికరంలో అమలు కావడానికి దీన్ని ప్రామాణీకరిస్తుంది." "సెట్టింగ్‌ల్లో ప్రారంభించండి" - %sకు మారండి\" - "తర్వాత, \"%s\"ని మీ సక్రియ వచన-ఇన్‌పుట్ పద్ధతిగా ఎంచుకోండి." + %sకు మారండి\" + "తర్వాత, \"%s\"ని మీ సక్రియ వచన-ఇన్‌పుట్ పద్ధతిగా ఎంచుకోండి." "ఇన్‌పుట్ పద్ధతులను మార్చు" "అభినందనలు, మీరు అంతా పూర్తి చేసారు!" - "ఇప్పుడు మీరు %sతో మీకు ఇష్టమైన అన్ని అనువర్తనాల్లో టైప్ చేయవచ్చు." + "ఇప్పుడు మీరు %sతో మీకు ఇష్టమైన అన్ని అనువర్తనాల్లో టైప్ చేయవచ్చు." "పూర్తయింది" "యాప్‌ చిహ్నాన్ని చూపు" "లాంచర్‌లో యాప్‌ చిహ్నాన్ని ప్రదర్శించు" - "ఇతర నిఘంటువులు" + "ఇతర నిఘంటువులు" "నిఘంటువు అందుబాటులో ఉంది" - "నిఘంటువులు ఏవీ అందుబాటులో లేవు" "చివరిగా నవీకరించబడినది" "సెట్టింగ్‌లు" "తొలగించు" - "వెర్షన్ %1$s" - "జోడించు" + "వెర్షన్ %1$s" "నిఘంటువుకి జోడించు" "షార్ట్‌కట్:" "భాష:" "పదాన్ని టైప్ చేయండి" "ఐచ్ఛిక షార్ట్‌కట్" "పదాన్ని సవరించు" - "మీరు వినియోగదారు నిఘంటువులో పదాలు ఏవీ కలిగి లేరు. పదాన్ని జోడించడానికి, జోడించు (+) బటన్‌ను నొక్కండి." "అన్ని భాషల కోసం" "మరిన్ని భాషలు…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" diff --git a/app/src/main/res/values-th/strings.xml b/app/src/main/res/values-th/strings.xml index bf1ff89b4..4ef357d02 100644 --- a/app/src/main/res/values-th/strings.xml +++ b/app/src/main/res/values-th/strings.xml @@ -17,7 +17,7 @@ "เปิดใช้แป้นพิมพ์แยก" "ใช้วิธีการป้อนข้อมูลอื่น" "แป้นสลับภาษา" - "%s มิลลิวิ" + "%s มิลลิวิ" "ค่าเริ่มต้นของระบบ" "ใช้ชื่อจากรายชื่อติดต่อสำหรับคำแนะนำและการแก้ไข" "คำแนะนำในแบบของคุณ" @@ -50,20 +50,9 @@ "สเปน (สหรัฐอเมริกา)" "ภาษาอังกฤษผสมกับฮินดู" "เซอร์เบีย (ละติน)" - "อังกฤษ (สหราชอาณาจักร) (%s)" - "อังกฤษ (สหรัฐอเมริกา) (%s)" - "สเปน (สหรัฐอเมริกา) (%s)" - "ภาษาอังกฤษผสมกับฮินดู (%s)" - "เซอร์เบีย (%s)" - "%s (ดั้งเดิม)" - "%s (แบบกะทัดรัด)" - "ไม่มีภาษา (ตัวอักษรละติน)" - "ตัวอักษร (QWERTY)" - "ตัวอักษร (QWERTZ)" - "ตัวอักษร (AZERTY)" - "ตัวอักษร (Dvorak)" - "ตัวอักษร (Colemak)" - "ตัวอักษร (PC)" + "%s (ดั้งเดิม)" + "%s (แบบกะทัดรัด)" + "ไม่มีภาษา" "อีโมจิ" "เพิ่ม" "ลบ" @@ -76,38 +65,33 @@ "อีโมจิสำหรับแป้นพิมพ์บนเครื่อง" "แป้น Alt บนเครื่องแสดงชุดอีโมจิ" "ค่าเริ่มต้น" - "ยินดีต้อนรับสู่ %s" + "ยินดีต้อนรับสู่ %s" "พร้อมการป้อนข้อมูลด้วยท่าทาง" "เริ่มต้นใช้งาน" - "ขั้นตอนถัดไป" - "การตั้งค่า %s" - "เปิดใช้งาน %s" - "โปรดตรวจสอบ \"%s\" ในการตั้งค่าภาษาและการป้อนข้อมูลของคุณ ซึ่งจะอนุญาตให้แอปทำงานบนอุปกรณ์ของคุณ" - "%s เปิดใช้ในการตั้งค่าภาษาและการป้อนข้อมูลของคุณอยู่แล้ว ขั้นตอนนี้จึงเสร็จสิ้นแล้ว ไปยังขั้นตอนถัดไปเลย!" + "การตั้งค่า %s" + "เปิดใช้งาน %s" + "โปรดตรวจสอบ \"%s\" ในการตั้งค่าภาษาและการป้อนข้อมูลของคุณ ซึ่งจะอนุญาตให้แอปทำงานบนอุปกรณ์ของคุณ" "เปิดใช้งานในการตั้งค่า" - "สลับไปใช้ %s" - "ถัดไป เลือก \"%s\" เป็นวิธีการป้อนข้อความที่ใช้งานของคุณ" + "สลับไปใช้ %s" + "ถัดไป เลือก \"%s\" เป็นวิธีการป้อนข้อความที่ใช้งานของคุณ" "สลับวิธีการป้อนข้อมูล" "ยินดีด้วย คุณพร้อมใช้งานแล้ว!" - "ตอนนี้คุณสามารถพิมพ์ข้อมูลลงในแอปที่ชื่นชอบทั้งหมดด้วย %s" + "ตอนนี้คุณสามารถพิมพ์ข้อมูลลงในแอปที่ชื่นชอบทั้งหมดด้วย %s" "เสร็จสิ้น" "แสดงไอคอนแอป" "แสดงไอคอนแอปพลิเคชันในตัวเรียกใช้งาน" - "พจนานุกรมส่วนเสริม" + "พจนานุกรมส่วนเสริม" "มีพจนานุกรมให้ใช้งาน" - "ไม่มีพจนานุกรม" "ปรับปรุงแก้ไขครั้งล่าสุด" "การตั้งค่า" "ลบ" - "เวอร์ชัน %1$s" - "เพิ่ม" + "เวอร์ชัน %1$s" "เพิ่มในพจนานุกรม" "ทางลัด:" "ภาษา:" "พิมพ์คำ" "ทางลัดที่ไม่บังคับ" "แก้ไขคำ" - "คุณยังไม่มีคำในพจนานุกรมผู้ใช้ หากต้องการเพิ่มคำ ให้แตะปุ่มเพิ่ม (+)" "สำหรับทุกภาษา" "ภาษาเพิ่มเติม…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" diff --git a/app/src/main/res/values-tl/strings.xml b/app/src/main/res/values-tl/strings.xml index 8060d0790..f36b6fb24 100644 --- a/app/src/main/res/values-tl/strings.xml +++ b/app/src/main/res/values-tl/strings.xml @@ -17,7 +17,7 @@ "I-enable ang split keyboard" "Lipat iba paraan ng input" "Key ng panlipat ng wika" - "%sms" + "%sms" "Default ng system" "Gamitin ang pangalan mula sa Contact para sa mungkahi/pagtatama." "Personalized na mungkahi" @@ -50,20 +50,9 @@ "Spanish (US)" "Hinglish" "Serbian (Latin)" - "English (UK) (%s)" - "English (US) (%s)" - "Spanish (US) (%s)" - "Hinglish (%s)" - "Serbian (%s)" - "%s (Traditional)" - "%s (Compact)" - "Walang wika (Alpabeto)" - "Alpabeto (QWERTY)" - "Alpabeto (QWERTZ)" - "Alpabeto (AZERTY)" - "Alpabeto (Dvorak)" - "Alpabeto (Colemak)" - "Alpabeto (PC)" + "%s (Traditional)" + "%s (Compact)" + "Walang wika" "Emoji" "Idagdag" "Alisin" @@ -76,38 +65,33 @@ "Emoji para sa pisikal na keyboard" "Ipinapakita ng pisikal na Alt key ang emoji palette" "Default" - "Maligayang pagdating sa %s" + "Maligayang pagdating sa %s" "gamit ang Gesture na Pagta-type" "Magsimula" - "Susunod na hakbang" - "Sine-set up ang %s" - "Paganahin ang %s" - "Pakitingnan ang \"%s\" sa iyong Mga setting ng wika at input. Papahintulutan nitong gumana ito sa iyong device." - "Naka-enable na ang %s sa iyong Mga setting ng wika at input, kaya tapos na ang hakbang na ito. Magpatuloy sa susunod!" + "Sine-set up ang %s" + "Paganahin ang %s" + "Pakitingnan ang \"%s\" sa iyong Mga setting ng wika at input. Papahintulutan nitong gumana ito sa iyong device." "I-enable sa Mga Setting" - "Lumipat sa %s" - "Susunod, piliin ang \"%s\" bilang iyong aktibong pamamaraan ng pag-input ng teksto." + "Lumipat sa %s" + "Susunod, piliin ang \"%s\" bilang iyong aktibong pamamaraan ng pag-input ng teksto." "Magpalit ng pamamaraan ng pag-input" "Binabati kita, handa ka na!" - "Ngayon, mata-type mo na ang lahat ng paborito mong apps gamit ang %s." + "Ngayon, mata-type mo na ang lahat ng paborito mong apps gamit ang %s." "Tapos na" "Ipakita ang icon ng app" "Ipakita ang icon ng application sa launcher" - "Mga add-on na diksyunaryo" + "Mga add-on na diksyunaryo" "Available ang diksyunaryo" - "Walang mga diksyunaryo" "Huling na-update" "Mga Setting" "I-delete" - "Bersyon %1$s" - "Idagdag" + "Bersyon %1$s" "Idagdag sa diksyunaryo" "Shortcut:" "Wika:" "Mag-type ng salita" "Opsyonal na shortcut" "I-edit ang salita" - "Wala kang anumang salita sa diksyunaryo ng user. Para magdagdag ng salita, i-tap ang button na Magdagdag (+)." "Para sa lahat ng wika" "Higit pang mga wika…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 59a3f92b3..447eb28d8 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -16,7 +16,7 @@ "Bölünmüş klavyeyi etkinleştir" "Diğer giriş yöntemine geç" "Dil değiştirme tuşu" - "%s ms" + "%s ms" "Sistem varsayılanı" "Öneri ve düzeltmeler için Kişiler\'deki adları kullan" "Kişisel öneriler" @@ -49,20 +49,9 @@ "İspanyolca (ABD)" "Hingilizce" "Sırpça (Latin alfabesi)" - İngilizce (İngiltere) (%s) - İngilizce (ABD) (%s) - İspanyolca (ABD) (%s) - Hingilizce (%s) - Sırpça (%s) - %s (Geleneksel) - %s (Kompakt) - "Dil yok (Alfabe)" - "Alfabe (QWERTY)" - "Alfabe (QWERTZ)" - "Alfabe (AZERTY)" - "Alfabe (Dvorak)" - "Alfabe (Colemak)" - "Alfabe (PC)" + %s (Geleneksel) + %s (Kompakt) + "Dil yok" "Emoji" "Ekle" "Kaldır" @@ -75,38 +64,33 @@ "Fiziksel klavye için emoji" "Fiziksel Alt tuşu, emoji paletini gösterir" "Varsayılan" - %s uygulamasına hoş geldiniz + %s uygulamasına hoş geldiniz "Hareketle Yazmayı içerir" "Başlayın" - "Sonraki adım" - %s uygulamasını kurma - %s uygulamasını etkinleştirin - Lütfen \"%s\" uygulamasını Dil ve giriş ayarlarınızda işaretleyin. Bu, uygulamaya cihazınızda çalışma yetkisi verecektir. - %s, Dil ve giriş ayarlarınızda önceden etkinleştirildiği için bu adım tamamlandı. Bir sonraki adıma ilerleyin! + %s uygulamasını kurma + %s uygulamasını etkinleştirin + Lütfen \"%s\" uygulamasını Dil ve giriş ayarlarınızda işaretleyin. Bu, uygulamaya cihazınızda çalışma yetkisi verecektir. "Ayarlarda etkinleştir" - %s uygulamasına geçin - Sonra, \"%s\" uygulamasını etkin metin giriş yönteminiz olarak seçin. + %s uygulamasına geçin + Sonra, \"%s\" uygulamasını etkin metin giriş yönteminiz olarak seçin. "Giriş yöntemini değiştir" Tebrikler, artık hazırsın! - Artık %s ile tüm favori uygulamalarınızda yazabilirsiniz. + Artık %s ile tüm favori uygulamalarınızda yazabilirsiniz. "Tamamlandı" "Uygulama simgesini göster" "Uygulama simgesini başlatıcıda gösterir" - "Ek sözlükler" + "Ek sözlükler" "Sözlük mevcut" - "Kullanılabilir sözlük yok" "Son güncelleme tarihi" "Ayarlar" "Sil" - Sürüm %1$s - "Ekle" + Sürüm %1$s "Sözlüğe ekle" "Kısayol:" "Dil:" Bir kelime yaz "İsteğe bağlı kısayol" "Kelimeyi düzenle" - Kullanıcı sözlüğünde kelime yok. Kelime eklemek için Ekle (+) düğmesine dokun. "Tüm diller için" "Diğer diller…" " ABCÇDEFGĞHIİJKLMNOÖPQRSŞTUÜVWXYZ" @@ -122,11 +106,10 @@ HeliBoard yazım denetleyicisi ayarları Klavye yükseklik ölçeği Kadırarak silme - Alfabe (Workman) Tuş kenarlıkları Otomatik gündüz/gece modu HeliBoard yazım denetleyicisi - %sdak. + %sdak. Öneriler Emoji tuşu Pano geçmişini etkinleştir @@ -137,9 +120,8 @@ Tuş ipuçlarını göster Uzun basma ipuçlarını göster Boşluk tuşuyla giriş yöntemini değiştir - %s (Akkhor) + %s (Akkhor) Bir kerede metnin daha büyük bölümlerini seçmek ve silmek için silme tuşundan hızlıca kaydırın - Alfabe (Colemak Mod-DH) Görünüm sistem ayarlarını takip edecektir HeliBoard ayarları Giriş @@ -194,7 +176,6 @@ Araç çubuğu tuşlarını seç Pano Panoyu temizle - Düzen adını ayarla İşlevsel tuşlar İşlevsel tuşlar (Semboller) İşlevsel tuşlar (Daha fazla sembol) @@ -216,7 +197,6 @@ Para birimlerini özelleştir Yalnızca ana renkleri göster Tüm renkleri göster - Önizleme için tıkla Ana ve en fazla 6 ikincil para birimi sembolünü boşlukla ayırarak ayarla Anahtar boşluklarını daralt Sayısal tuş takımı için sembol tuşuna uzun bas @@ -261,7 +241,7 @@ Özel düzen ekle Semboller Dil seç - %s (Genişletilmiş) + %s (Genişletilmiş) Uyumlu formatta bir dosya seç. Formatlarla ilgili bilgi %s mevcuttur. Dosyayı yükle Panoya kopyala @@ -301,7 +281,6 @@ Kum Kullanıcı tanımlı (gece) Rengi otomatik olarak seç - Yükleme mevcut temanın üzerine yazılacak Kapat Ayarları açmak için dile dokun Hareketle yazma kitaplığını yükle @@ -311,7 +290,6 @@ \nUyarı: Harici kodun yüklenmesi güvenlik riski oluşturabilir. Yalnızca güvenilir bir kaynaktan gelen kitaplığı kullan. Açılır tuş sırasını seç İpucu kaynağını seç - Kaitag (%s) Emoji Sözlüğü değiştir Sürüm @@ -331,7 +309,7 @@ Dosya okunamıyor Açık Yuvarlatılmış - %s (Probhat) + %s (Probhat) Sol Sayfa yukarı Kelime sola @@ -345,9 +323,8 @@ İşlevsel ipuçlarını göster Sabitlenmiş araç çubuğu tuşlarını seç Uzun basıldığında araç çubuğu tuşunu sabitle - Alfabe (Bépo) - %s (Sebeolsik 390) - %s (Sebeolsik Final) + %s (Sebeolsik 390) + %s (Sebeolsik Final) Stil Koyu Okyanus @@ -361,7 +338,7 @@ Araç çubuğu Gereksiz açılır pencereleri kaldır Sayısal tuş takımını aç kapa - %s (Öğrenci) + %s (Öğrenci) Mevcut düzeni kopyala Eklemek için bir sözlük seç .dict biçimindeki sözlükler %s indirilebilir. Hata: Seçilen dosya geçerli bir sözlük dosyası değil @@ -377,7 +354,6 @@ Mansi Bağlantı tespiti Diğer uygulamaların önerileri devre dışı bırakma isteklerini göz ardı et (sorunlara neden olabilir) - Mansi (%s) Görünüm Kaydet yada dosyadan yükle. Uyarı: geri yükleme mevcut verilerin üzerine yazacaktır "Sözlük olmadan yalnızca daha önce girdiğin metin için öneriler alırsın.<br> diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 61365d311..1b1f33881 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -17,7 +17,7 @@ "Увімкнути розділену клавіатуру" Зміна методів введення "Клавіша зміни мови" - %s мс. + %s мс. Типово "Показувати виправлення на основі імен зі списку контактів" "Персональні пропозиції" @@ -50,20 +50,9 @@ "Іспанська (США)" Гінґліш Сербська (латиниця) - Англійська (Велика Британія) (%s) - Англійська (США) (%s) - Іспанська (США) (%s) - Гінґліш (%s) - Сербська (%s) - %s (Традиційна) - %s (Компактна) - Стандартна (латиниця) - "Латиниця (QWERTY)" - "Латиниця (QWERTZ)" - "Латиниця (AZERTY)" - "Латиниця (Dvorak)" - "Латиниця (Colemak)" - "Латиниця (ПК)" + %s (Традиційна) + %s (Компактна) + Стандартна Емоджі Додати Видалити @@ -76,38 +65,33 @@ Смайли для фізичної клавіатури Фізична клавіша Alt показує усі доступні емоджі Типово - Вітаємо в%s + Вітаємо в%s з функцією «Ввід жестами» Розпочати - Наступний крок - Налаштування%s - Увімкнути%s - Перевірте застосунок \\%s у налаштуваннях «Мова та введення». Це дозволить йому працювати на вашому пристрої. - Застосунок %s уже увімкнено в налаштуваннях «Мова та введення». Переходьте до наступного кроку! + Налаштування%s + Увімкнути%s + Перевірте застосунок \\%s у налаштуваннях «Мова та введення». Це дозволить йому працювати на вашому пристрої. Увімкнути в налаштуваннях - Перемкнути на%s - Виберіть \\%s поточним методом введення. + Перемкнути на%s + Виберіть \\%s поточним методом введення. Змінити метод введення Вітаємо, налаштування завершено! - Тепер ви можете писати в усіх улюблених застосунках за допомогою %s. + Тепер ви можете писати в усіх улюблених застосунках за допомогою %s. Завершено Показувати піктограму програми Відображати піктограму програми нв лаунчері - Додаткові словники + Додаткові словники Словник доступний - Словники недоступні Останнє оновлення Налаштування Видалити - Версія %1$s - Додати + Версія %1$s Додати в словник "Ярлик:" "Мова:" Введіть слово "Необов’язковий ярлик" Редагувати слово - У словнику користувача нічого немає. Щоб додати слово, торкніться кнопки «Додати» (+). Для всіх мов "Інші мови…" " АБВГҐДЕЄЖЗИІЇЙКЛМНОПРСТУФХЦЧШЩЬЮЯ" @@ -120,7 +104,7 @@ Кольори теми (темна тема) Використати тему системи Введення - %s (Аккгор) + %s (Аккгор) Автопробіл після знаків пунктуації Налаштування перевірки правопису HeliBoard Виправлення @@ -130,7 +114,7 @@ Різне Клавіша емоджі Без обмежень - %s хв. + %s хв. Увімкнути історію буфера обміну Якщо вимкнено, клавіша буфера обміну вставляє вміст, якщо він є Час зберігання історії @@ -142,7 +126,6 @@ Користувацька Користувацька (темна) Автоматичний вибір кольору - Натисніть, щоб переглянути Виберіть кольори для тексту та фону Фон клавіатури Текст клавіш @@ -169,7 +152,6 @@ Показувати підказки клавіш Змінювати метод введення клавішею пробіл Довге натискання клавіші пробіл виводить меню вибору способу введення - Алфавіт (Workman) Перевірка правопису HeliBoard Збільшені клавіші Видаляти ковзанням @@ -191,7 +173,6 @@ Завжди показувати рядок цифр Контури клавіш Додаткові клавіші - Алфавіт (Colemak Mod-DH) Конфіденційність автовиправлення Скасовувати "Повторити" @@ -263,11 +244,9 @@ Показати функціональні підказки Показувати підказки, якщо тривале натискання клавіші запускає додаткові функції Кайтазька - Кайтазька (%s) Використовувати особистий словник для зберігання вивчених слів Ігнорувати запити інших застосунків про вимкнення пропозицій (може викликати проблеми) Більше автокорекції - Алфавіт (Бепо) Натисніть, щоб відредагувати базову розкладку Символи телефону Числа @@ -281,13 +260,12 @@ Завантажити файл Неможливо прочитати файл Копіювати поточну розкладку - Вказати ім\'я розкладки Справді видалити власну розкладку %s? Помилка розкладки: %s - %s (Пробгат) - %s (Себольсік 390) - %s (Себольсік Фінальна) - %s (Студентська) + %s (Пробгат) + %s (Себольсік 390) + %s (Себольсік Фінальна) + %s (Студентська) Виберіть файл у сумісному форматі. Інформація про формати доступна %s. Додати власну розкладку Встановити зображення для денного чи нічного режиму? @@ -340,7 +318,6 @@ При натисканні точки або пунктуації буде використано середню пропозицію Закрити буфер обміну Завантажити - Завантаження перезапише поточну тему Емоджі Запропонувати вміст буфера обміну Показати нещодавно скопійований вміст буфера обміну як пропозицію @@ -363,8 +340,7 @@ Додати найпоширеніші варіанти (типово) Видалити спливні клавіші, які є в базовій розкладці Мансійська - %s (Розширена) - Мансійська (%s) + %s (Розширена) Ця установка показує всі кольори, які використовуються всередині програми. Список кольорів може змінюватись. Стандартний колір є випадковим, і імена не будуть переведені. Показати більше кольорів Видалити зайві спливні вікна @@ -404,10 +380,9 @@ Вібрація в режимі «Не турбувати» Відстань розділення (альбомна) Даргинська (Урахі) - Урахінський (%s) Розділена клавіатура Увімкнути розділену клавіатуру (альбомну) - %s (Фонетика) + %s (Фонетика) Автовиправлення комбінації клавіш Якщо увімкнено, комбінації клавіш можуть бути розгорнуті за допомогою автокорекції Встановити фонове зображення (альбомна) diff --git a/app/src/main/res/values-ur/strings.xml b/app/src/main/res/values-ur/strings.xml index d74673cf3..a7180b748 100644 --- a/app/src/main/res/values-ur/strings.xml +++ b/app/src/main/res/values-ur/strings.xml @@ -16,7 +16,7 @@ "الگ ہونے والا کی بورڈ فعال کریں" "دیگر اندراج طریقوں پر سوئچ کریں" "زبان سوئچ کرنے کی کلید" - "%sملی سیکنڈ" + "%sملی سیکنڈ" "سسٹم ڈیفالٹ" "تجاویز اور اصلاحات کیلئے رابطوں سے ناموں کی تجویز کریں" "ذاتی نوعیت کی تجاویز" @@ -49,20 +49,9 @@ "ہسپانوی (امریکہ)" "ہنگلش" "سربیائی (لاطینی)" - "انگریزی (برطانیہ) (%s)" - "انگریزی (امریکہ) (%s)" - "ہسپانوی (امریکہ) (%s)" - "ہنگلش (%s)" - "سربیائی (%s)" - "%s (روایتی)" - "%s (کمپیکٹ)" - "کوئی زبان نہیں (الفابیٹ)" - "‏حروف تہجی (QWERTY)" - "‏حروف تہجی (QWERTZ)" - "‏حروف تہجی (AZERTY)" - "‏حروف تہجی (Dvorak)" - "‏حروف تہجی (Colemak)" - "‏حروف تہجی (PC)" + "%s (روایتی)" + "%s (کمپیکٹ)" + "کوئی زبان نہیں" "Emoji" "شامل کریں" "ہٹائیں" @@ -75,38 +64,33 @@ "‏فزیکل کی بورڈ کیلئے Emoji" "‏فزیکل Alt کی کے ذریعے emoji پیلٹ نظر آتا ہے" "ڈیفالٹ" - %s میں خوش آمدید\" + %s میں خوش آمدید\" "اشارہ ٹائپنگ کے ساتھ" "شروع کریں" - "اگلا مرحلہ" - %s ترتیب دینا\" - %s کو فعال کریں\" - "براہ کرم \"%s\" کو اپنی زبانوں اور ان پٹ ترتیبات میں چیک کریں۔ اس سے اس کو آپ کے آلہ پر چلنے کی اجازت مل جائے گی۔" - "‏%s پہلے ہی آپ کی زبانوں ‎اور‎ ان پٹ ترتیبات میں فعال ہے، لہذا یہ مرحلہ مکمل ہو گیا ہے۔ اگلے پر چلتے ہیں!" + %s ترتیب دینا\" + %s کو فعال کریں\" + "براہ کرم \"%s\" کو اپنی زبانوں اور ان پٹ ترتیبات میں چیک کریں۔ اس سے اس کو آپ کے آلہ پر چلنے کی اجازت مل جائے گی۔" "ترتیبات میں فعال کریں" - %s پر سوئچ کریں\" - "آگے، \"%s\" کو اپنے فعال متنی اندراج کے طریقہ کے بطور منتخب کریں۔" + %s پر سوئچ کریں\" + "آگے، \"%s\" کو اپنے فعال متنی اندراج کے طریقہ کے بطور منتخب کریں۔" "اندراج کے طریقے سوئچ کریں" "مبارک ہو، آپ بالکل تیار ہیں!" - "اب آپ %s کے ساتھ اپنی سبھی پسندیدہ ایپس میں ٹائپ کر سکتے ہیں۔" + "اب آپ %s کے ساتھ اپنی سبھی پسندیدہ ایپس میں ٹائپ کر سکتے ہیں۔" "مکمل ہو گیا" "ایپ آئیکن دکھائیں" "لانچر میں ایپلیکیشن آئیکن کو ڈسپلے کریں" - "اضافی لغات" + "اضافی لغات" "لغت دستیاب ہے" - "کوئی لغت دستیاب نہیں" "آخری بار اپ ڈیٹ کردہ" "ترتیبات" "حذف کریں" - "ورژن %1$s" - "شامل کریں" + "ورژن %1$s" "لغت میں شامل کریں" "شارٹ کٹ:" "زبان:" "ایک لفظ ٹائپ کریں" "اختیاری شارٹ کٹ" "لفظ میں ترمیم کریں" - "صارف لغت میں آپ کے پاس کوئی الفاظ نہيں ہیں۔ کوئی لفظ شامل کرنے کیلئے شامل کریں (+) بٹن تھپتھپائیں۔" "سبھی زبانوں کیلئے" "مزید زبانیں…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" diff --git a/app/src/main/res/values-uz/strings.xml b/app/src/main/res/values-uz/strings.xml index 4c05577a1..030f47c59 100644 --- a/app/src/main/res/values-uz/strings.xml +++ b/app/src/main/res/values-uz/strings.xml @@ -16,7 +16,7 @@ "Ikkiga ajratiladigan klaviaturani yoqish" "Boshqa usullarga o‘tish" "Tilni almashtirish tugmasi" - "%s ms" + "%s ms" "Tizim standarti" "Kontaktlar ro‘yxatidagi ismlar asosida tuzatmalarni taklif qilish" "Takliflarni moslashtirish" @@ -49,20 +49,9 @@ "Ispan (AQSH)" "Hinglish" "Serb (Lotin)" - Ingliz (Buyuk Britaniya) (%s) - Ingliz (AQSH) (%s) - Ispan (AQSH) (%s) - Hinglish (%s) - Serb (%s) - %s (An’anaviy) - %s(Ixcham) - "Til aniqlanmadi (lotin)" - "Lotin (QWERTY)" - "Lotin (QWERTZ)" - "Lotin (AZERTY)" - "Lotin (Dvorak)" - "Lotin (Colemak)" - "Lotin (shaxsiy kompyuter)" + %s (An’anaviy) + %s(Ixcham) + "Til aniqlanmadi" "Kulgichlar" "Qo‘shish" "Olib tashlash" @@ -75,38 +64,33 @@ "Tashqi klaviatura uchun kulgichlar" "Jismoniy klaviaturadagi Alt tugmasi emojilarni ochadi" "Standart" - %s ilovasiga xush kelibsiz! + %s ilovasiga xush kelibsiz! "qo‘l uzmasdan yozish" "Boshladik" - "Keyingi qadam" - %s sozlanmoqda - Yoqish %s - Matn kiritishda foydalanish uchun “Tillar va matn kiritish” sozlamalarida “%s” bandiga belgi qo‘ying. - %s ilovasi allaqachon “Tillar va matn kiritish” sozlamalarida yoqilgan, shuning uchun keyingi qadamga o‘tish mumkin! + %s sozlanmoqda + Yoqish %s + Matn kiritishda foydalanish uchun “Tillar va matn kiritish” sozlamalarida “%s” bandiga belgi qo‘ying. "Sozlamalardan yoqish" - %s ga o‘zgartirish - Endi, joriy matn kiritish usuli sifatida “%s” ilovasini tanlang. + %s ga o‘zgartirish + Endi, joriy matn kiritish usuli sifatida “%s” ilovasini tanlang. "Matn kiritish usulini o‘zgartirish" "Tabriklaymiz, hammasi tayyor!" - Endi, matn kiritish uchun %s ilovasidan foydalanishingiz mumkin. + Endi, matn kiritish uchun %s ilovasidan foydalanishingiz mumkin. "Tugallandi" "Ilova ikonkasini chiqarish" "Launcherga ilova ikonkasini chiqarish" - "Qo‘shimcha lug‘atlar" + "Qo‘shimcha lug‘atlar" "Lug‘at mavjud" - "Lug‘at mavjud emas" "So‘nggi marta yangilandi" "Sozlamalar" "O‘chirish" - %1$s versiya - "Qo‘shish" + %1$s versiya "Lug‘atga kiritish" "Qisqartma:" "Til:" "So‘zni kiriting" "Ibora uchun qisqartma (ixtiyoriy)" "So‘zni tahrirlash" - "Shaxsiy lug‘atingizda hech narsa yo‘q. Unga so‘zlarni qo‘shish uchun “Qo‘shish” (+) tugmasidan foydalaning." "Barcha tillar uchun" "Ko‘proq tillar…" " ABDEFGHIJKLMNOPQRSTUVXYZO‘G‘SHCH" @@ -114,7 +98,7 @@ Emoji kaliti "Tizimdagi mavjud tillar" "Matn kiritish usulini tanlang" - %smin. + %smin. Cheklanmagan Bufer tarixini yoqish Agar o\'chirilgan bo\'lsa, vaqtinchalik bufer tugmasi mavjud bo\'lsa, almashish buferidagi kontentni joylashtiradi @@ -138,9 +122,7 @@ Yangi so\'zni kiritishda tinish belgilaridan keyin avtomatik ravishda bo\'sh joy qo\'yish Majburiy inkognito rejimi Tinish belgilaridan keyin avtomatik bo\'shliq qo‘yish - %s (Akkhor) - Alfavit (Colemak Mod-DH) - Alfavit (Workman) + %s (Akkhor) Kiritish Qo\'shimcha kalitlar HeliBoard Sozlamalari diff --git a/app/src/main/res/values-v28/platform-theme.xml b/app/src/main/res/values-v28/platform-theme.xml new file mode 100644 index 000000000..77a73ae9e --- /dev/null +++ b/app/src/main/res/values-v28/platform-theme.xml @@ -0,0 +1,17 @@ + + + + + + diff --git a/app/src/main/res/values-v31/platform-theme.xml b/app/src/main/res/values-v31/platform-theme.xml index 4c40353c6..6f6ade775 100644 --- a/app/src/main/res/values-v31/platform-theme.xml +++ b/app/src/main/res/values-v31/platform-theme.xml @@ -5,12 +5,11 @@ - - diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index 3b4bc737c..96fc958fa 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -17,7 +17,7 @@ "Bật chia bàn phím" "Phương thức nhập khác" "Phím chuyển đổi ngôn ngữ" - "%s mili giây" + "%s mili giây" "Theo mặc định của hệ thống" "Sử dụng tên từ Danh bạ cho các đề xuất và chỉnh sửa" "Đề xuất được cá nhân hóa" @@ -50,20 +50,9 @@ "Tiếng Tây Ban Nha (Mỹ)" "Tiếng Anh-Hindi" "Tiếng Serbia (La tinh)" - "Tiếng Anh (Anh) (%s)" - "Tiếng Anh (Mỹ) (%s)" - "Tiếng Tây Ban Nha (Mỹ) (%s)" - "Tiếng Anh-Hindi (%s)" - "Tiếng Serbia (%s)" - "%s (Truyền thống)" - "%s (Viết tắt)" - "Không ngôn ngữ nào (Bảng chữ cái)" - "Bảng chữ cái (QWERTY)" - "Bảng chữ cái (QWERTZ)" - "Bảng chữ cái (AZERTY)" - "Bảng chữ cái (Dvorak)" - "Bảng chữ cái (Colemak)" - "Bảng chữ cái (PC)" + "%s (Truyền thống)" + "%s (Viết tắt)" + "Không ngôn ngữ nào" "Biểu tượng cảm xúc" "Thêm" "Xóa" @@ -76,38 +65,33 @@ "Biểu tượng cảm xúc cho bàn phím vật lý" "Phím Alt thực hiển thị bảng biểu tượng cảm xúc" "Mặc định" - "Chào mừng bạn đến với %s" + "Chào mừng bạn đến với %s" "với Nhập bằng cử chỉ" "Bắt đầu" - "Bước tiếp theo" - "Thiết lập %s" - "Bật %s" - "Hãy chọn \"%s\" trong cài đặt Ngôn ngữ và phương thức nhập. Thao tác này sẽ cho phép ứng dụng chạy trên thiết bị của bạn." - "%s đã được bật trong cài đặt Ngôn ngữ và phương thức nhập, do đó bước này đã hoàn tất. Hãy chuyển sang bước tiếp theo!" + "Thiết lập %s" + "Bật %s" + "Hãy chọn \"%s\" trong cài đặt Ngôn ngữ và phương thức nhập. Thao tác này sẽ cho phép ứng dụng chạy trên thiết bị của bạn." "Bật trong Cài đặt" - "Chuyển sang %s" - "Tiếp theo, chọn \"%s\" làm phương thức nhập văn bản hoạt động của bạn." + "Chuyển sang %s" + "Tiếp theo, chọn \"%s\" làm phương thức nhập văn bản hoạt động của bạn." "Chuyển phương thức nhập" "Xin chúc mừng, bạn đã cài đặt xong!" - "Bây giờ bạn có thể nhập vào tất cả ứng dụng yêu thích của mình với %s." + "Bây giờ bạn có thể nhập vào tất cả ứng dụng yêu thích của mình với %s." "Đã xong" "Hiển thị biểu tượng ứng dụng" "Hiển thị biểu tượng ứng dụng trong trình chạy" - "Từ điển bổ sung" + "Từ điển bổ sung" "Từ điển có sẵn" - "Không có từ điển nào" "Cập nhật lần cuối" "Cài đặt" "Xóa" - "Phiên bản %1$s" - "Thêm" + "Phiên bản %1$s" "Thêm vào từ điển" "Phím tắt:" "Ngôn ngữ:" "Nhập từ" "Phím tắt tùy chọn" "Chỉnh sửa từ" - "Bạn không có bất kỳ từ nào trong từ điển người dùng. Để thêm từ, hãy nhấn vào nút Thêm (+)." "Cho tất cả ngôn ngữ" "Ngôn ngữ khác…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 158233a9f..abfb208c3 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -16,7 +16,7 @@ 启用分离式键盘 "切换到其他输入法" "语言切换键" - %s 毫秒 + %s 毫秒 "系统默认值" 使用联系人中的姓名提供建议和更正 "个性化建议" @@ -49,20 +49,9 @@ "西班牙语(美国)" "印地英语" "塞尔维亚语(拉丁语布局)" - 英语(英国)(%s) - 英语(美国)(%s) - 西班牙语(美国)(%s) - 印地英语 (%s) - 塞尔维亚语 (%s) - %s(传统) - %s (紧凑型) - 无语言(字母表) - 字母表(QWERTY) - 字母表(QWERTZ) - 字母表(AZERTY) - 字母表(Dvorak) - 字母表(Colemak) - 字母表(PC) + %s(传统) + %s (紧凑型) + 无语言 "表情符号" "添加" 移除 @@ -75,38 +64,33 @@ 用于物理键盘的表情符号 物理 Alt 键显示表情符号调色板 "默认" - 欢迎使用 %s + 欢迎使用 %s 带有滑行输入 "开始" - "下一步" - 设置 %s - 启用 %s - 请检查您的语言和输入设置中的 %s。这将授权它在您的设备上运行。 - 您已在语言和输入设置中启用 %s,因此这一步已完成。下一步! + 设置 %s + 启用 %s + 请在“语言和输入法”设置中选中“%s”,授权该应用在您的设备上运行。 "在设置中启用" - 切换到 %s - 接下来,选择 %s 作为您要使用的文本输入法。 + 切换到 %s + 接下来,请选择“%s”作为您要使用的文本输入法。 "切换输入法" "恭喜,您已完成了设置!" - 现在,您可以在您喜欢的所有应用中使用 %s 输入内容了。 + 现在,您可以在您喜欢的所有应用中使用 %s 输入内容了。 完成了 "显示应用图标" "在启动器中显示应用图标" - 附加词典 + 附加词典 词典可供下载 - 没有可供下载的词典 最后更新时间 "设置" "删除" - 版本 %1$s - "添加" + 版本 %1$s 添加到词典 "快捷键:" "语言:" 输入单词 可选快捷键 编辑单词 - 用户词典中没有任何单词。要添加单词,请点击添加(+)按钮。 对于所有语言 "更多语言…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" @@ -123,7 +107,7 @@ 显示长按提示 始终显示数字行 显示按键提示 - %s 分钟 + %s 分钟 滑动删除 表情符号键 如果禁用,剪贴板键将粘贴剪贴板内容(如果有的话) @@ -131,8 +115,7 @@ 单词输入时自动在标点符号后插入空格 拼写检查 拼写检查设置 - %s (Akkhor) - 字母表(Workman) + %s (Akkhor) 禁用新单词学习 更多键 数字行 @@ -145,7 +128,6 @@ 长按空格键将提示输入法选择菜单 使用空格键更改输入法 键盘高度比例 - 字母表(Colemak Mod-DH) 自动更正置信度 "使用系统语言" "选择输入法" @@ -164,14 +146,13 @@ 滑行输入时看到建议的单词 始终立即开始 滑行输入轨迹寿命 - %s (Sebeolsik Final) + %s (Sebeolsik Final) 错误:所选文件不是有效的词典文件 风格 彩色导航栏 浅色 沙滩 紫罗兰 - 加载将覆盖当前主题 工具栏 自定义货币 黑色 @@ -197,7 +178,7 @@ 数字行 - 语言 + @string/subtype_locale 建议条文本 分离距离 @@ -235,8 +216,8 @@ 配色 配色(夜间) 关闭剪贴板历史 - %s (Sebeolsik 390) - %s(扩展) + %s (Sebeolsik 390) + %s(扩展) 词典 是否确定要替换用户添加的词典“%1$s”?\n \n当前词典: \n%2$s \n \n新词典: \n%3$s 替换词典 @@ -307,11 +288,9 @@ 森林 靛蓝 功能键背景 - %s (Probhat) - 凯塔格语 (%s) + %s (Probhat) 凯塔格语 保存到文件 - 设置布局名称 确定要删除自定义布局 %s? 符号(阿拉伯语) 用户自定义 @@ -320,7 +299,7 @@ 切换到主键盘后… 在表情符号视图中选择表情符号 选择剪贴板历史条目 - 在符号视图中按回车键或空格键 + 在符号视图输入内容后按回车键或空格键 从文件添加词典 这将禁用未固定工具栏键的其他长按操作 添加非常常见的变体(默认) @@ -331,11 +310,9 @@ 添加一个单词 移除基础布局上已存在的弹出键 移除多余弹出 - 曼西语 (%s) - %s (Student) + %s (Student) 曼西语 符号 - 点击预览 为文本和背景选择颜色 键盘背景 按键文本 @@ -357,7 +334,6 @@ 在滑行输入过程中移动预览 快速输入冷却 未知库文件。是否确定是从可信来源获得并且是“%s”的? - 字母表(Bépo) 点击语言以打开设置 隐藏功能的描述 自动显示工具栏 @@ -402,10 +378,9 @@ 删除 确定重置所有自定义图标? 在勿扰模式时振动 - %s(注音) + %s(注音) 覆盖表情符号版本 达尔格瓦语 (Urakhi) - Urakhi (%s) 自动更正快捷方式 从文件设置自定义字体 如果未设置,将使用纵向图片 @@ -432,5 +407,28 @@ 您可以在 %s 中查找和分享布局。 您可以在 %s 中查找和分享颜色。 自定义子类型 - %s (Baishakhi) + %s (Baishakhi) + 输入 URL 和电子邮件地址时,用顶级域替换句点键弹出 + 显示顶级域弹出键 + 在数字键盘输入内容后按回车键或空格键 + 数字行(基本) + Web 编辑字段(主要存在于浏览器中)是导致“始终显示建议”设置出现问题的一个非常常见的原因 + 不要总是显示对 Web 编辑字段的建议 + 空格 + 手势输入单词前自动插入空格 + 手势输入单词后自动插入空格 + 按下 Shift 键不自动插入空格 + 按 Shift 键移除待插入的自动空格 + 退格键恢复自动更正 + 选择建议后自动插入空格 + 时间戳键的格式 + 索托语 + 达巴尼语 + 根据字体大小缩放表情符号键大小 + 备份已还原 + 查找应用名称 + 使用已安装应用的名称进行建议和更正 + 中性 + 默认表情符号肤色 + %1$s(%2$s) diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml index eeeef8578..0624097d5 100644 --- a/app/src/main/res/values-zh-rHK/strings.xml +++ b/app/src/main/res/values-zh-rHK/strings.xml @@ -17,7 +17,7 @@ "啟用分離式鍵盤" "切換至其他輸入法" "語言切換鍵" - "%s 毫秒" + "%s 毫秒" "系統預設" "使用「聯絡人」的名稱提供建議與修正" "個人化建議" @@ -50,20 +50,9 @@ "西班牙文 (美國)" "印度英文" "塞爾維亞文 (拉丁文)" - "英文 (英國) (%s)" - "英文 (美國) (%s)" - "西班牙文 (美國) (%s)" - "印度英文 (%s)" - "塞爾維亞文 (%s)" - "%s (傳統)" - "%s (精簡版)" - "無語言 (字母)" - "字母 (QWERTY)" - "字母 (QWERTZ)" - "字母 (AZERTY)" - "字母 (Dvorak)" - "字母 (Colemak)" - "字母 (PC)" + "%s (傳統)" + "%s (精簡版)" + "無語言" "Emoji" "新增" "移除" @@ -76,43 +65,38 @@ "實體鍵盤上使用表情圖案" "以實體 Alt 鍵顯示表情圖案選項" "預設" - "歡迎使用「%s」" + "歡迎使用「%s」" "配備手勢輸入功能" "開始" - "下一步" - "設定「%s」" - "啟用「%s」" - "請在「語言和輸入」設定中勾選「%s」。這將允許裝置執行此應用程式。" - "您已在「語言和輸入」設定中啟用「%s」。因此這個步驟已完成,請繼續執行下一個步驟!" + "設定「%s」" + "啟用「%s」" + "請在「語言和輸入」設定中勾選「%s」。這將允許裝置執行此應用程式。" "在設定中啟用" - "切換至「%s」" - "接著,請選取「%s」作為目前使用的文字輸入方法。" + "切換至「%s」" + "接著,請選取「%s」作為目前使用的文字輸入方法。" "切換輸入方法" "恭喜,一切就緒!" - "現在,您可以在所有最愛的應用程式中使用「%s」輸入文字。" + "現在,您可以在所有最愛的應用程式中使用「%s」輸入文字。" "完成" "顯示應用程式圖示" "在啟動器中顯示圖示" - "附加字典" + "附加字典" "可使用字典" - "沒有可用的字典" "上次更新日期" "設定" "刪除" - "版本 %1$s" - "新增" + "版本 %1$s" "加入字典" "快速鍵:" "語言:" "輸入字詞" "自選快速鍵" "編輯字詞" - "您的用戶字典中沒有任何字詞。如要新增字詞,請輕按 [新增] (+) 按鈕。" "所有語言" "更多語言…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" 實驗功能 - %s分鐘 + %s分鐘 拼字檢查 拼字檢查設定 Emoji diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 0e8c451a8..fbf818d83 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -1,10 +1,9 @@ - + - +--> "查詢聯絡人姓名" "按鍵時震動" "按鍵聲音" @@ -17,7 +16,7 @@ "啟用分離式鍵盤" "切換到其他輸入法" "語言切換鍵" - "%s 毫秒" + "%s 毫秒" "系統預設" "根據「聯絡人」名稱提供建議與修正" "個人化建議" @@ -50,20 +49,9 @@ "西班牙文 (美國)" "印度英文" "塞爾維亞文 (拉丁文)" - "英文 (英國) (%s)" - "英文 (美國) (%s)" - "西班牙文 (美國) (%s)" - "印度英文 (%s)" - "塞爾維亞文 (%s)" - "%s (傳統)" - "%s (精簡)" - "無語言 (字母)" - "字母 (QWERTY)" - "字母 (QWERTZ)" - "字母 (AZERTY)" - "字母 (Dvorak)" - "字母 (Colemak)" - "字母 (PC)" + "%s (傳統)" + "%s (精簡)" + "無語言" "表情符號" "新增" "移除" @@ -76,38 +64,33 @@ "透過實體鍵盤啟用表情符號" "按下實體 Alt 鍵即顯示表情符號面板" "預設" - "歡迎使用 %s" + "歡迎使用 %s" "含滑行輸入功能" "開始設定" - "下一步" - "正在設定「%s」" - "啟用「%s」" - "請在 [語言與輸入設定] 中勾選 [%s],授權該應用程式在你的裝置上執行。" - "你已在 [語言與輸入設定] 中啟用 %s,因此這個步驟已經完成。請進行下一個步驟!" + "正在設定「%s」" + "啟用「%s」" + "請在 [語言與輸入設定] 中勾選 [%s],授權該應用程式在你的裝置上執行。" "在設定中啟用" - "切換至「%s」" - "接著,請選取「%s」做為目前使用的文字輸入法。" + "切換至「%s」" + "接著,請選取「%s」做為目前使用的文字輸入法。" "切換輸入法" "恭喜,你已完成設定!" - "現在,你可以在自己喜愛的所有應用程式中使用「%s」輸入文字。" + 現在您可以在所有您喜歡的應用程式中使用 %s 輸入。 "完成" "顯示應用程式圖示" "在啟動器中顯示應用程式圖示" - "外掛字典" + "外掛字典" "可用的字典" - "沒有可用的字典" "上次更新時間:" "設定" "刪除" - "版本 %1$s" - "新增" + "版本 %1$s" "加入字典" "快速鍵:" "語言:" "輸入字詞" "可選用的快速鍵" "編輯字詞" - "使用者字典中沒有任何字詞。如要新增字詞,請輕觸「新增」(+) 按鈕。" "所有語言" "更多語言…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" @@ -124,4 +107,58 @@ "搜尋" "暫停" "等待" + 樣式 + 字典 + 紫羅蘭 + 外觀 + HeliBoard 設定 + 建議 + 實驗功能 + 雜項 + 還原 + 符號 + 數字鍵盤 + 載入 + 備份 + 版面 + 符號 + Shift + 輸入 + 更正 + + 表情符號 + 顏色 + 電話 + + 數字 + + + 版本 + 淺色 + 深色 + 更深色 + 巧克力色 + 森林 + 海洋 + 粉紅色 + 使用者定義 + 棕色 + 多雲 + 黑色 + 關閉 + 圓角 + 靛藍色 + Enter + Tab + + 語言 + + + + 剪貼簿 + 權重: + 此處 + 關於 + 工具列 + Delete diff --git a/app/src/main/res/values-zu/strings.xml b/app/src/main/res/values-zu/strings.xml index a5a5827a2..61d3a2739 100644 --- a/app/src/main/res/values-zu/strings.xml +++ b/app/src/main/res/values-zu/strings.xml @@ -17,7 +17,7 @@ "Nika amandla ikhibhodi yokuhlukanisa" "Shintshela kwezinye izindlela zokungena" "Ukhiye wokushintsha ullimi" - "%sms" + "%sms" "Okuzenzakalelayo kwesistimu" "Amagama abasebenzisi kusuka Kothintana nabo bokusikisela nokulungisa" "Iziphakamiso ezenziwe okomuntu siqu" @@ -50,20 +50,9 @@ "I-Spanish (US)" "I-Hinglish" "Isi-Serbian (Latin)" - "I-English (UK) ( %s )" - "I-English (US) ( %s )" - "Isi-Spanish (US) ( %s )" - "I-Hinglish (%s)" - "Isi-Serbian (%s)" - "Isi-%s (Tradition)" - "%s (Okuqoqene ndawonye)" - "Alikho ulimi (Alfabhethi)" - "Alfabhethi (QWERTY)" - "Alfabhethi (QWERTZ)" - "Alfabhethi (I-AZERTY)" - "Alfabhethi (Dvorak)" - "Alfabhethi (Colemak)" - "Alfabhethi (PC)" + "Isi-%s (Tradition)" + "%s (Okuqoqene ndawonye)" + "Alikho ulimi" "I-Emoji" "Engeza" "Khipha" @@ -76,38 +65,33 @@ "I-Emoji wekhibhodi yangempela" "Ukhiye we-Alt woqobo ubonisa i-emoji palette" "Okuzenzakalelayo" - "Siyakwamukela ku-%s" + "Siyakwamukela ku-%s" "nokuthayipha ngokuthinta" "Qalisa" - "Isinyathelo esilandelayo" - "Kusethwa i-%s" - "Nika amandla i-%s" - "Sicela uhlole i-\"%s\" kulimi lwakho nezilungiselelo zokokufaka. Lokhu kuzoyigunyaza ukuthi isebenze kudivayisi yakho." - "I-%s isivele inikwe amandla kulimi lwakho nakuzilungiselelo zokufaka, ngakho-ke lesi sinyathelo senziwe. Qhubekela kwesilandelayo!" + "Kusethwa i-%s" + "Nika amandla i-%s" + "Sicela uhlole i-\"%s\" kulimi lwakho nezilungiselelo zokokufaka. Lokhu kuzoyigunyaza ukuthi isebenze kudivayisi yakho." "Nika amandla kuzilungiselelo" - "Shintshela ku-%s." - "Okulandelayo, khetha i-\"%s\" njengendlela yakho yokufaka umbhalo osebenzayo." + "Shintshela ku-%s." + "Okulandelayo, khetha i-\"%s\" njengendlela yakho yokufaka umbhalo osebenzayo." "Shintsha izindlela zokufaka" "Siyakuhalalisela, usumi ngomumo!" - "Manje usungathayipha ngokufaka zonke izinhlelo zokusebenza eziyizintandokazi zakho nge-%s." + "Manje usungathayipha ngokufaka zonke izinhlelo zokusebenza eziyizintandokazi zakho nge-%s." "Iqedile" "Bonisa isithonjana sohlelo lokusebenza" "Bonisa isithonjana sohlelo lokusebenza kusiqalisi" - "Izichazamazwi ezingezwayo" + "Izichazamazwi ezingezwayo" "Isichazamazwi siyatholakala" - "Azikho izachazimazwi ezitholakalayo" "Igcine ukulungiswa" "Izilungiselelo" "Susa" - "Inguqulo engu-%1$s" - "Engeza" + "Inguqulo engu-%1$s" "Faka kusichazamazwi" "Isinqamulelo:" "Ulimi:" "Thayipha igama" "Ukunqamulela okukhethekayo" "Hlela igama" - "Awunawo amagama kwisichazamazwi somsebenzisi. Ukuze ungeze igama, thepha inkinobho (+)." "Okwazo zonke izilimi" "Izilimi eziningi…" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml index 8efca7f84..ce545a89a 100644 --- a/app/src/main/res/values/attrs.xml +++ b/app/src/main/res/values/attrs.xml @@ -156,10 +156,6 @@ - - - - diff --git a/app/src/main/res/values/donottranslate.xml b/app/src/main/res/values/donottranslate.xml index 675128454..a1090ecc3 100644 --- a/app/src/main/res/values/donottranslate.xml +++ b/app/src/main/res/values/donottranslate.xml @@ -4,21 +4,7 @@ modified SPDX-License-Identifier: Apache-2.0 AND GPL-3.0-only --> - - - - en-US - en-GB - es-US - hi-Latn - mns - dru - xdq - sr-Latn - + @@ -28,11 +14,14 @@ xdq sr-Latn - Hinglish - Ма̄ньси - ХӀурухъла лугъат - Хайдаҡьан - Srpski + + + Hinglish + Ма̄ньси + ХӀурухъла лугъат + Хайдаҡьан + Srpski + %s @@ -63,19 +52,6 @@ Bépo PC - - %s (QWERTY) - %s (QWERTZ) - %s (AZERTY) - %s (Dvorak) - %s (Colemak) - %s (Colemak Mod-DH) - %s (Workman) - %s (Bépo) - %s (PC) %s (BDS) @@ -92,6 +68,7 @@ %s (1452-2) + HeliBoard 100% FOSS keyboard, based on AOSP. diff --git a/app/src/main/res/values/emoji-categories.xml b/app/src/main/res/values/emoji-categories.xml deleted file mode 100644 index 3fd482dc2..000000000 --- a/app/src/main/res/values/emoji-categories.xml +++ /dev/null @@ -1,2440 +0,0 @@ - - - - - - - - - - 1F600 - 1F603 - 1F604 - 1F601 - 1F606 - 1F605 - 1F923||24 - 1F602 - 1F642||23 - 1F643||23 - 1FAE0||32 - 1F609 - 1F60A - 1F607 - 1F970||28 - 1F60D - 1F929||26 - 1F618 - 1F617 - 263A,FE0F - 1F61A - 1F619 - 1F972||30 - 1F60B - 1F61B - 1F61C - 1F92A||26 - 1F61D - 1F911||23 - 1F917||23 - 1F92D||26 - 1FAE2||32 - 1FAE3||32 - 1F92B||26 - 1F914||23 - 1FAE1||32 - 1F910||23 - 1F928||26 - 1F610 - 1F611 - 1F636 - 1FAE5||32 - 1F636,200D,1F32B,FE0F||31 - 1F60F - 1F612 - 1F644||23 - 1F62C - 1F62E,200D,1F4A8||31 - 1F925||24 - 1FAE8||33 - 1F642,200D,2194,FE0F||34 - 1F642,200D,2195,FE0F||34 - 1F60C - 1F614 - 1F62A - 1F924||24 - 1F634 - 1FAE9||35 - 1F637 - 1F912||23 - 1F915||23 - 1F922||24 - 1F92E||26 - 1F927||24 - 1F975||28 - 1F976||28 - 1F974||28 - 1F635 - 1F635,200D,1F4AB||31 - 1F92F||26 - 1F920||24 - 1F973||28 - 1F978||30 - 1F60E - 1F913||23 - 1F9D0||26 - 1F615 - 1FAE4||32 - 1F61F - 1F641||23 - 2639,FE0F||23 - 1F62E - 1F62F - 1F632 - 1F633 - 1F97A||28 - 1F979||32 - 1F626 - 1F627 - 1F628 - 1F630 - 1F625 - 1F622 - 1F62D - 1F631 - 1F616 - 1F623 - 1F61E - 1F613 - 1F629 - 1F62B - 1F971||29 - 1F624 - 1F621 - 1F620 - 1F92C||26 - 1F608 - 1F47F - 1F480 - 2620,FE0F||23 - 1F4A9 - 1F921||24 - 1F479 - 1F47A - 1F47B - 1F47D - 1F47E - 1F916||23 - 1F63A - 1F638 - 1F639 - 1F63B - 1F63C - 1F63D - 1F640 - 1F63F - 1F63E - 1F648 - 1F649 - 1F64A - 1F48C - 1F498 - 1F49D - 1F496 - 1F497 - 1F493 - 1F49E - 1F495 - 1F49F - 2763,FE0F||23 - 1F494 - 2764,FE0F,200D,1F525||31 - 2764,FE0F,200D,1FA79||31 - 2764,FE0F - 1FA77||33 - 1F9E1||26 - 1F49B - 1F49A - 1F499 - 1FA75||33 - 1F49C - 1F90E||29 - 1F5A4||24 - 1FA76||33 - 1F90D||29 - 1F48B - 1F4AF - 1F4A2 - 1F4A5 - 1F4AB - 1F4A6 - 1F4A8 - 1F573,FE0F||23 - 1F4AC - 1F441,FE0F,200D,1F5E8,FE0F||23 - 1F5E8,FE0F||23 - 1F5EF,FE0F||23 - 1F4AD - 1F4A4 - - - - 1F44B - 1F91A||24 - 1F590,FE0F||23 - 270B - 1F596||23 - 1FAF1||32 - 1FAF2||32 - 1FAF3||32 - 1FAF4||32 - 1FAF7||33 - 1FAF8||33 - 1F44C - 1F90C||30 - 1F90F||29 - 270C,FE0F - 1F91E||24 - 1FAF0||32 - 1F91F||26 - 1F918||23 - 1F919||24 - 1F448 - 1F449 - 1F446 - 1F595||23 - 1F447 - 261D,FE0F - 1FAF5||32 - 1F44D - 1F44E - 270A - 1F44A - 1F91B||24 - 1F91C||24 - 1F44F - 1F64C - 1FAF6||32 - 1F450 - 1F932||26 - 1F91D||24 - 1F64F - 270D,FE0F||23 - 1F485 - 1F933||24 - 1F4AA - 1F9BE||29 - 1F9BF||29 - 1F9B5||28 - 1F9B6||28 - 1F442 - 1F9BB||29 - 1F443 - 1F9E0||26 - 1FAC0||30 - 1FAC1||30 - 1F9B7||28 - 1F9B4||28 - 1F440 - 1F441,FE0F||23 - 1F445 - 1F444 - 1FAE6||32 - 1F476 - 1F9D2||26 - 1F466 - 1F467 - 1F9D1||26 - 1F471 - 1F468 - 1F9D4||26 - 1F9D4,200D,2642,FE0F||31 - 1F9D4,200D,2640,FE0F||31 - 1F468,200D,1F9B0||28 - 1F468,200D,1F9B1||28 - 1F468,200D,1F9B3||28 - 1F468,200D,1F9B2||28 - 1F469 - 1F469,200D,1F9B0||28 - 1F9D1,200D,1F9B0||30 - 1F469,200D,1F9B1||28 - 1F9D1,200D,1F9B1||30 - 1F469,200D,1F9B3||28 - 1F9D1,200D,1F9B3||30 - 1F469,200D,1F9B2||28 - 1F9D1,200D,1F9B2||30 - 1F471,200D,2640,FE0F||25 - 1F471,200D,2642,FE0F||25 - 1F9D3||26 - 1F474 - 1F475 - 1F64D - 1F64D,200D,2642,FE0F||25 - 1F64D,200D,2640,FE0F||25 - 1F64E - 1F64E,200D,2642,FE0F||25 - 1F64E,200D,2640,FE0F||25 - 1F645 - 1F645,200D,2642,FE0F||25 - 1F645,200D,2640,FE0F||25 - 1F646 - 1F646,200D,2642,FE0F||25 - 1F646,200D,2640,FE0F||25 - 1F481 - 1F481,200D,2642,FE0F||25 - 1F481,200D,2640,FE0F||25 - 1F64B - 1F64B,200D,2642,FE0F||25 - 1F64B,200D,2640,FE0F||25 - 1F9CF||29 - 1F9CF,200D,2642,FE0F||29 - 1F9CF,200D,2640,FE0F||29 - 1F647 - 1F647,200D,2642,FE0F||25 - 1F647,200D,2640,FE0F||25 - 1F926||24 - 1F926,200D,2642,FE0F||25 - 1F926,200D,2640,FE0F||25 - 1F937||24 - 1F937,200D,2642,FE0F||25 - 1F937,200D,2640,FE0F||25 - 1F9D1,200D,2695,FE0F||30 - 1F468,200D,2695,FE0F||25 - 1F469,200D,2695,FE0F||25 - 1F9D1,200D,1F393||30 - 1F468,200D,1F393||25 - 1F469,200D,1F393||25 - 1F9D1,200D,1F3EB||30 - 1F468,200D,1F3EB||25 - 1F469,200D,1F3EB||25 - 1F9D1,200D,2696,FE0F||30 - 1F468,200D,2696,FE0F||25 - 1F469,200D,2696,FE0F||25 - 1F9D1,200D,1F33E||30 - 1F468,200D,1F33E||25 - 1F469,200D,1F33E||25 - 1F9D1,200D,1F373||30 - 1F468,200D,1F373||25 - 1F469,200D,1F373||25 - 1F9D1,200D,1F527||30 - 1F468,200D,1F527||25 - 1F469,200D,1F527||25 - 1F9D1,200D,1F3ED||30 - 1F468,200D,1F3ED||25 - 1F469,200D,1F3ED||25 - 1F9D1,200D,1F4BC||30 - 1F468,200D,1F4BC||25 - 1F469,200D,1F4BC||25 - 1F9D1,200D,1F52C||30 - 1F468,200D,1F52C||25 - 1F469,200D,1F52C||25 - 1F9D1,200D,1F4BB||30 - 1F468,200D,1F4BB||25 - 1F469,200D,1F4BB||25 - 1F9D1,200D,1F3A4||30 - 1F468,200D,1F3A4||25 - 1F469,200D,1F3A4||25 - 1F9D1,200D,1F3A8||30 - 1F468,200D,1F3A8||25 - 1F469,200D,1F3A8||25 - 1F9D1,200D,2708,FE0F||30 - 1F468,200D,2708,FE0F||25 - 1F469,200D,2708,FE0F||25 - 1F9D1,200D,1F680||30 - 1F468,200D,1F680||25 - 1F469,200D,1F680||25 - 1F9D1,200D,1F692||30 - 1F468,200D,1F692||25 - 1F469,200D,1F692||25 - 1F46E - 1F46E,200D,2642,FE0F||25 - 1F46E,200D,2640,FE0F||25 - 1F575,FE0F||23 - 1F575,FE0F,200D,2642,FE0F||25 - 1F575,FE0F,200D,2640,FE0F||25 - 1F482 - 1F482,200D,2642,FE0F||25 - 1F482,200D,2640,FE0F||25 - 1F977||30 - 1F477 - 1F477,200D,2642,FE0F||25 - 1F477,200D,2640,FE0F||25 - 1FAC5||32 - 1F934||24 - 1F478 - 1F473 - 1F473,200D,2642,FE0F||25 - 1F473,200D,2640,FE0F||25 - 1F472 - 1F9D5||26 - 1F935||24 - 1F935,200D,2642,FE0F||30 - 1F935,200D,2640,FE0F||30 - 1F470 - 1F470,200D,2642,FE0F||30 - 1F470,200D,2640,FE0F||30 - 1F930||24 - 1FAC3||32 - 1FAC4||32 - 1F931||26 - 1F469,200D,1F37C||30 - 1F468,200D,1F37C||30 - 1F9D1,200D,1F37C||30 - 1F47C - 1F385 - 1F936||24 - 1F9D1,200D,1F384||30 - 1F9B8||28 - 1F9B8,200D,2642,FE0F||28 - 1F9B8,200D,2640,FE0F||28 - 1F9B9||28 - 1F9B9,200D,2642,FE0F||28 - 1F9B9,200D,2640,FE0F||28 - 1F9D9||26 - 1F9D9,200D,2642,FE0F||26 - 1F9D9,200D,2640,FE0F||26 - 1F9DA||26 - 1F9DA,200D,2642,FE0F||26 - 1F9DA,200D,2640,FE0F||26 - 1F9DB||26 - 1F9DB,200D,2642,FE0F||26 - 1F9DB,200D,2640,FE0F||26 - 1F9DC||26 - 1F9DC,200D,2642,FE0F||26 - 1F9DC,200D,2640,FE0F||26 - 1F9DD||26 - 1F9DD,200D,2642,FE0F||26 - 1F9DD,200D,2640,FE0F||26 - 1F9DE||26 - 1F9DE,200D,2642,FE0F||26 - 1F9DE,200D,2640,FE0F||26 - 1F9DF||26 - 1F9DF,200D,2642,FE0F||26 - 1F9DF,200D,2640,FE0F||26 - 1F9CC||32 - 1F486 - 1F486,200D,2642,FE0F||25 - 1F486,200D,2640,FE0F||25 - 1F487 - 1F487,200D,2642,FE0F||25 - 1F487,200D,2640,FE0F||25 - 1F6B6 - 1F6B6,200D,2642,FE0F||25 - 1F6B6,200D,2640,FE0F||25 - 1F6B6,200D,27A1,FE0F||34 - 1F6B6,200D,2640,FE0F,200D,27A1,FE0F||34 - 1F6B6,200D,2642,FE0F,200D,27A1,FE0F||34 - 1F9CD||29 - 1F9CD,200D,2642,FE0F||29 - 1F9CD,200D,2640,FE0F||29 - 1F9CE||29 - 1F9CE,200D,2642,FE0F||29 - 1F9CE,200D,2640,FE0F||29 - 1F9CE,200D,27A1,FE0F||34 - 1F9CE,200D,2640,FE0F,200D,27A1,FE0F||34 - 1F9CE,200D,2642,FE0F,200D,27A1,FE0F||34 - 1F9D1,200D,1F9AF||30 - 1F9D1,200D,1F9AF,200D,27A1,FE0F||34 - 1F468,200D,1F9AF||29 - 1F468,200D,1F9AF,200D,27A1,FE0F||34 - 1F469,200D,1F9AF||29 - 1F469,200D,1F9AF,200D,27A1,FE0F||34 - 1F9D1,200D,1F9BC||30 - 1F9D1,200D,1F9BC,200D,27A1,FE0F||34 - 1F468,200D,1F9BC||29 - 1F468,200D,1F9BC,200D,27A1,FE0F||34 - 1F469,200D,1F9BC||29 - 1F469,200D,1F9BC,200D,27A1,FE0F||34 - 1F9D1,200D,1F9BD||30 - 1F9D1,200D,1F9BD,200D,27A1,FE0F||34 - 1F468,200D,1F9BD||29 - 1F468,200D,1F9BD,200D,27A1,FE0F||34 - 1F469,200D,1F9BD||29 - 1F469,200D,1F9BD,200D,27A1,FE0F||34 - 1F3C3 - 1F3C3,200D,2642,FE0F||25 - 1F3C3,200D,2640,FE0F||25 - 1F3C3,200D,27A1,FE0F||34 - 1F3C3,200D,2640,FE0F,200D,27A1,FE0F||34 - 1F3C3,200D,2642,FE0F,200D,27A1,FE0F||34 - 1F483 - 1F57A||24 - 1F574,FE0F||23 - 1F46F - 1F46F,200D,2642,FE0F||25 - 1F46F,200D,2640,FE0F||25 - 1F9D6||26 - 1F9D6,200D,2642,FE0F||26 - 1F9D6,200D,2640,FE0F||26 - 1F9D7||26 - 1F9D7,200D,2642,FE0F||26 - 1F9D7,200D,2640,FE0F||26 - 1F93A||24 - 1F3C7 - 26F7,FE0F||23 - 1F3C2 - 1F3CC,FE0F||23 - 1F3CC,FE0F,200D,2642,FE0F||25 - 1F3CC,FE0F,200D,2640,FE0F||25 - 1F3C4 - 1F3C4,200D,2642,FE0F||25 - 1F3C4,200D,2640,FE0F||25 - 1F6A3 - 1F6A3,200D,2642,FE0F||25 - 1F6A3,200D,2640,FE0F||25 - 1F3CA - 1F3CA,200D,2642,FE0F||25 - 1F3CA,200D,2640,FE0F||25 - 26F9,FE0F||23 - 26F9,FE0F,200D,2642,FE0F||25 - 26F9,FE0F,200D,2640,FE0F||25 - 1F3CB,FE0F||23 - 1F3CB,FE0F,200D,2642,FE0F||25 - 1F3CB,FE0F,200D,2640,FE0F||25 - 1F6B4 - 1F6B4,200D,2642,FE0F||25 - 1F6B4,200D,2640,FE0F||25 - 1F6B5 - 1F6B5,200D,2642,FE0F||25 - 1F6B5,200D,2640,FE0F||25 - 1F938||24 - 1F938,200D,2642,FE0F||25 - 1F938,200D,2640,FE0F||25 - 1F93C||24 - 1F93C,200D,2642,FE0F||25 - 1F93C,200D,2640,FE0F||25 - 1F93D||24 - 1F93D,200D,2642,FE0F||25 - 1F93D,200D,2640,FE0F||25 - 1F93E||24 - 1F93E,200D,2642,FE0F||25 - 1F93E,200D,2640,FE0F||25 - 1F939||24 - 1F939,200D,2642,FE0F||25 - 1F939,200D,2640,FE0F||25 - 1F9D8||26 - 1F9D8,200D,2642,FE0F||26 - 1F9D8,200D,2640,FE0F||26 - 1F6C0 - 1F6CC||23 - 1F9D1,200D,1F91D,200D,1F9D1||29 - 1F46D - 1F46B - 1F46C - 1F48F - 1F469,200D,2764,FE0F,200D,1F48B,200D,1F468||26 - 1F468,200D,2764,FE0F,200D,1F48B,200D,1F468||23 - 1F469,200D,2764,FE0F,200D,1F48B,200D,1F469||23 - 1F491 - 1F469,200D,2764,FE0F,200D,1F468||26 - 1F468,200D,2764,FE0F,200D,1F468||23 - 1F469,200D,2764,FE0F,200D,1F469||23 - 1F468,200D,1F469,200D,1F466||25 - 1F468,200D,1F469,200D,1F467||23 - 1F468,200D,1F469,200D,1F467,200D,1F466||23 - 1F468,200D,1F469,200D,1F466,200D,1F466||23 - 1F468,200D,1F469,200D,1F467,200D,1F467||23 - 1F468,200D,1F468,200D,1F466||23 - 1F468,200D,1F468,200D,1F467||23 - 1F468,200D,1F468,200D,1F467,200D,1F466||23 - 1F468,200D,1F468,200D,1F466,200D,1F466||23 - 1F468,200D,1F468,200D,1F467,200D,1F467||23 - 1F469,200D,1F469,200D,1F466||23 - 1F469,200D,1F469,200D,1F467||23 - 1F469,200D,1F469,200D,1F467,200D,1F466||23 - 1F469,200D,1F469,200D,1F466,200D,1F466||23 - 1F469,200D,1F469,200D,1F467,200D,1F467||23 - 1F468,200D,1F466||25 - 1F468,200D,1F466,200D,1F466||25 - 1F468,200D,1F467||25 - 1F468,200D,1F467,200D,1F466||25 - 1F468,200D,1F467,200D,1F467||25 - 1F469,200D,1F466||25 - 1F469,200D,1F466,200D,1F466||25 - 1F469,200D,1F467||25 - 1F469,200D,1F467,200D,1F466||25 - 1F469,200D,1F467,200D,1F467||25 - 1F5E3,FE0F||23 - 1F464 - 1F465 - 1FAC2||30 - 1F46A - 1F9D1,200D,1F9D1,200D,1F9D2||34 - 1F9D1,200D,1F9D1,200D,1F9D2,200D,1F9D2||34 - 1F9D1,200D,1F9D2||34 - 1F9D1,200D,1F9D2,200D,1F9D2||34 - 1F463 - 1FAC6||35 - - - - 1F44B,1F3FB||24;1F44B,1F3FC||24;1F44B,1F3FD||24;1F44B,1F3FE||24;1F44B,1F3FF||24 - 1F91A,1F3FB||24;1F91A,1F3FC||24;1F91A,1F3FD||24;1F91A,1F3FE||24;1F91A,1F3FF||24 - 1F590,1F3FB||24;1F590,1F3FC||24;1F590,1F3FD||24;1F590,1F3FE||24;1F590,1F3FF||24 - 270B,1F3FB||24;270B,1F3FC||24;270B,1F3FD||24;270B,1F3FE||24;270B,1F3FF||24 - 1F596,1F3FB||24;1F596,1F3FC||24;1F596,1F3FD||24;1F596,1F3FE||24;1F596,1F3FF||24 - 1FAF1,1F3FB||32;1FAF1,1F3FC||32;1FAF1,1F3FD||32;1FAF1,1F3FE||32;1FAF1,1F3FF||32 - 1FAF2,1F3FB||32;1FAF2,1F3FC||32;1FAF2,1F3FD||32;1FAF2,1F3FE||32;1FAF2,1F3FF||32 - 1FAF3,1F3FB||32;1FAF3,1F3FC||32;1FAF3,1F3FD||32;1FAF3,1F3FE||32;1FAF3,1F3FF||32 - 1FAF4,1F3FB||32;1FAF4,1F3FC||32;1FAF4,1F3FD||32;1FAF4,1F3FE||32;1FAF4,1F3FF||32 - 1FAF7,1F3FB||33;1FAF7,1F3FC||33;1FAF7,1F3FD||33;1FAF7,1F3FE||33;1FAF7,1F3FF||33 - 1FAF8,1F3FB||33;1FAF8,1F3FC||33;1FAF8,1F3FD||33;1FAF8,1F3FE||33;1FAF8,1F3FF||33 - 1F44C,1F3FB||24;1F44C,1F3FC||24;1F44C,1F3FD||24;1F44C,1F3FE||24;1F44C,1F3FF||24 - 1F90C,1F3FB||30;1F90C,1F3FC||30;1F90C,1F3FD||30;1F90C,1F3FE||30;1F90C,1F3FF||30 - 1F90F,1F3FB||29;1F90F,1F3FC||29;1F90F,1F3FD||29;1F90F,1F3FE||29;1F90F,1F3FF||29 - 270C,1F3FB||24;270C,1F3FC||24;270C,1F3FD||24;270C,1F3FE||24;270C,1F3FF||24 - 1F91E,1F3FB||24;1F91E,1F3FC||24;1F91E,1F3FD||24;1F91E,1F3FE||24;1F91E,1F3FF||24 - 1FAF0,1F3FB||32;1FAF0,1F3FC||32;1FAF0,1F3FD||32;1FAF0,1F3FE||32;1FAF0,1F3FF||32 - 1F91F,1F3FB||26;1F91F,1F3FC||26;1F91F,1F3FD||26;1F91F,1F3FE||26;1F91F,1F3FF||26 - 1F918,1F3FB||24;1F918,1F3FC||24;1F918,1F3FD||24;1F918,1F3FE||24;1F918,1F3FF||24 - 1F919,1F3FB||24;1F919,1F3FC||24;1F919,1F3FD||24;1F919,1F3FE||24;1F919,1F3FF||24 - 1F448,1F3FB||24;1F448,1F3FC||24;1F448,1F3FD||24;1F448,1F3FE||24;1F448,1F3FF||24 - 1F449,1F3FB||24;1F449,1F3FC||24;1F449,1F3FD||24;1F449,1F3FE||24;1F449,1F3FF||24 - 1F446,1F3FB||24;1F446,1F3FC||24;1F446,1F3FD||24;1F446,1F3FE||24;1F446,1F3FF||24 - 1F595,1F3FB||24;1F595,1F3FC||24;1F595,1F3FD||24;1F595,1F3FE||24;1F595,1F3FF||24 - 1F447,1F3FB||24;1F447,1F3FC||24;1F447,1F3FD||24;1F447,1F3FE||24;1F447,1F3FF||24 - 261D,1F3FB||24;261D,1F3FC||24;261D,1F3FD||24;261D,1F3FE||24;261D,1F3FF||24 - 1FAF5,1F3FB||32;1FAF5,1F3FC||32;1FAF5,1F3FD||32;1FAF5,1F3FE||32;1FAF5,1F3FF||32 - 1F44D,1F3FB||24;1F44D,1F3FC||24;1F44D,1F3FD||24;1F44D,1F3FE||24;1F44D,1F3FF||24 - 1F44E,1F3FB||24;1F44E,1F3FC||24;1F44E,1F3FD||24;1F44E,1F3FE||24;1F44E,1F3FF||24 - 270A,1F3FB||24;270A,1F3FC||24;270A,1F3FD||24;270A,1F3FE||24;270A,1F3FF||24 - 1F44A,1F3FB||24;1F44A,1F3FC||24;1F44A,1F3FD||24;1F44A,1F3FE||24;1F44A,1F3FF||24 - 1F91B,1F3FB||24;1F91B,1F3FC||24;1F91B,1F3FD||24;1F91B,1F3FE||24;1F91B,1F3FF||24 - 1F91C,1F3FB||24;1F91C,1F3FC||24;1F91C,1F3FD||24;1F91C,1F3FE||24;1F91C,1F3FF||24 - 1F44F,1F3FB||24;1F44F,1F3FC||24;1F44F,1F3FD||24;1F44F,1F3FE||24;1F44F,1F3FF||24 - 1F64C,1F3FB||24;1F64C,1F3FC||24;1F64C,1F3FD||24;1F64C,1F3FE||24;1F64C,1F3FF||24 - 1FAF6,1F3FB||32;1FAF6,1F3FC||32;1FAF6,1F3FD||32;1FAF6,1F3FE||32;1FAF6,1F3FF||32 - 1F450,1F3FB||24;1F450,1F3FC||24;1F450,1F3FD||24;1F450,1F3FE||24;1F450,1F3FF||24 - 1F932,1F3FB||26;1F932,1F3FC||26;1F932,1F3FD||26;1F932,1F3FE||26;1F932,1F3FF||26 - 1F91D,1F3FB||25;1F91D,1F3FC||25;1F91D,1F3FD||25;1F91D,1F3FE||25;1F91D,1F3FF||25 - 1F64F,1F3FB||24;1F64F,1F3FC||24;1F64F,1F3FD||24;1F64F,1F3FE||24;1F64F,1F3FF||24 - 270D,1F3FB||24;270D,1F3FC||24;270D,1F3FD||24;270D,1F3FE||24;270D,1F3FF||24 - 1F485,1F3FB||24;1F485,1F3FC||24;1F485,1F3FD||24;1F485,1F3FE||24;1F485,1F3FF||24 - 1F933,1F3FB||24;1F933,1F3FC||24;1F933,1F3FD||24;1F933,1F3FE||24;1F933,1F3FF||24 - 1F4AA,1F3FB||24;1F4AA,1F3FC||24;1F4AA,1F3FD||24;1F4AA,1F3FE||24;1F4AA,1F3FF||24 - - - 1F9B5,1F3FB||28;1F9B5,1F3FC||28;1F9B5,1F3FD||28;1F9B5,1F3FE||28;1F9B5,1F3FF||28 - 1F9B6,1F3FB||28;1F9B6,1F3FC||28;1F9B6,1F3FD||28;1F9B6,1F3FE||28;1F9B6,1F3FF||28 - 1F442,1F3FB||24;1F442,1F3FC||24;1F442,1F3FD||24;1F442,1F3FE||24;1F442,1F3FF||24 - 1F9BB,1F3FB||29;1F9BB,1F3FC||29;1F9BB,1F3FD||29;1F9BB,1F3FE||29;1F9BB,1F3FF||29 - 1F443,1F3FB||24;1F443,1F3FC||24;1F443,1F3FD||24;1F443,1F3FE||24;1F443,1F3FF||24 - - - - - - - - - - - 1F476,1F3FB||24;1F476,1F3FC||24;1F476,1F3FD||24;1F476,1F3FE||24;1F476,1F3FF||24 - 1F9D2,1F3FB||26;1F9D2,1F3FC||26;1F9D2,1F3FD||26;1F9D2,1F3FE||26;1F9D2,1F3FF||26 - 1F466,1F3FB||24;1F466,1F3FC||24;1F466,1F3FD||24;1F466,1F3FE||24;1F466,1F3FF||24 - 1F467,1F3FB||24;1F467,1F3FC||24;1F467,1F3FD||24;1F467,1F3FE||24;1F467,1F3FF||24 - 1F9D1,1F3FB||26;1F9D1,1F3FC||26;1F9D1,1F3FD||26;1F9D1,1F3FE||26;1F9D1,1F3FF||26 - 1F471,1F3FB||24;1F471,1F3FC||24;1F471,1F3FD||24;1F471,1F3FE||24;1F471,1F3FF||24 - 1F468,1F3FB||24;1F468,1F3FC||24;1F468,1F3FD||24;1F468,1F3FE||24;1F468,1F3FF||24 - 1F9D4,1F3FB||26;1F9D4,1F3FC||26;1F9D4,1F3FD||26;1F9D4,1F3FE||26;1F9D4,1F3FF||26 - 1F9D4,1F3FB,200D,2642,FE0F||31;1F9D4,1F3FC,200D,2642,FE0F||31;1F9D4,1F3FD,200D,2642,FE0F||31;1F9D4,1F3FE,200D,2642,FE0F||31;1F9D4,1F3FF,200D,2642,FE0F||31 - 1F9D4,1F3FB,200D,2640,FE0F||31;1F9D4,1F3FC,200D,2640,FE0F||31;1F9D4,1F3FD,200D,2640,FE0F||31;1F9D4,1F3FE,200D,2640,FE0F||31;1F9D4,1F3FF,200D,2640,FE0F||31 - 1F468,1F3FB,200D,1F9B0||28;1F468,1F3FC,200D,1F9B0||28;1F468,1F3FD,200D,1F9B0||28;1F468,1F3FE,200D,1F9B0||28;1F468,1F3FF,200D,1F9B0||28 - 1F468,1F3FB,200D,1F9B1||28;1F468,1F3FC,200D,1F9B1||28;1F468,1F3FD,200D,1F9B1||28;1F468,1F3FE,200D,1F9B1||28;1F468,1F3FF,200D,1F9B1||28 - 1F468,1F3FB,200D,1F9B3||28;1F468,1F3FC,200D,1F9B3||28;1F468,1F3FD,200D,1F9B3||28;1F468,1F3FE,200D,1F9B3||28;1F468,1F3FF,200D,1F9B3||28 - 1F468,1F3FB,200D,1F9B2||28;1F468,1F3FC,200D,1F9B2||28;1F468,1F3FD,200D,1F9B2||28;1F468,1F3FE,200D,1F9B2||28;1F468,1F3FF,200D,1F9B2||28 - 1F469,1F3FB||24;1F469,1F3FC||24;1F469,1F3FD||24;1F469,1F3FE||24;1F469,1F3FF||24 - 1F469,1F3FB,200D,1F9B0||28;1F469,1F3FC,200D,1F9B0||28;1F469,1F3FD,200D,1F9B0||28;1F469,1F3FE,200D,1F9B0||28;1F469,1F3FF,200D,1F9B0||28 - 1F9D1,1F3FB,200D,1F9B0||30;1F9D1,1F3FC,200D,1F9B0||30;1F9D1,1F3FD,200D,1F9B0||30;1F9D1,1F3FE,200D,1F9B0||30;1F9D1,1F3FF,200D,1F9B0||30 - 1F469,1F3FB,200D,1F9B1||28;1F469,1F3FC,200D,1F9B1||28;1F469,1F3FD,200D,1F9B1||28;1F469,1F3FE,200D,1F9B1||28;1F469,1F3FF,200D,1F9B1||28 - 1F9D1,1F3FB,200D,1F9B1||30;1F9D1,1F3FC,200D,1F9B1||30;1F9D1,1F3FD,200D,1F9B1||30;1F9D1,1F3FE,200D,1F9B1||30;1F9D1,1F3FF,200D,1F9B1||30 - 1F469,1F3FB,200D,1F9B3||28;1F469,1F3FC,200D,1F9B3||28;1F469,1F3FD,200D,1F9B3||28;1F469,1F3FE,200D,1F9B3||28;1F469,1F3FF,200D,1F9B3||28 - 1F9D1,1F3FB,200D,1F9B3||30;1F9D1,1F3FC,200D,1F9B3||30;1F9D1,1F3FD,200D,1F9B3||30;1F9D1,1F3FE,200D,1F9B3||30;1F9D1,1F3FF,200D,1F9B3||30 - 1F469,1F3FB,200D,1F9B2||28;1F469,1F3FC,200D,1F9B2||28;1F469,1F3FD,200D,1F9B2||28;1F469,1F3FE,200D,1F9B2||28;1F469,1F3FF,200D,1F9B2||28 - 1F9D1,1F3FB,200D,1F9B2||30;1F9D1,1F3FC,200D,1F9B2||30;1F9D1,1F3FD,200D,1F9B2||30;1F9D1,1F3FE,200D,1F9B2||30;1F9D1,1F3FF,200D,1F9B2||30 - 1F471,1F3FB,200D,2640,FE0F||25;1F471,1F3FC,200D,2640,FE0F||25;1F471,1F3FD,200D,2640,FE0F||25;1F471,1F3FE,200D,2640,FE0F||25;1F471,1F3FF,200D,2640,FE0F||25 - 1F471,1F3FB,200D,2642,FE0F||25;1F471,1F3FC,200D,2642,FE0F||25;1F471,1F3FD,200D,2642,FE0F||25;1F471,1F3FE,200D,2642,FE0F||25;1F471,1F3FF,200D,2642,FE0F||25 - 1F9D3,1F3FB||26;1F9D3,1F3FC||26;1F9D3,1F3FD||26;1F9D3,1F3FE||26;1F9D3,1F3FF||26 - 1F474,1F3FB||24;1F474,1F3FC||24;1F474,1F3FD||24;1F474,1F3FE||24;1F474,1F3FF||24 - 1F475,1F3FB||24;1F475,1F3FC||24;1F475,1F3FD||24;1F475,1F3FE||24;1F475,1F3FF||24 - 1F64D,1F3FB||24;1F64D,1F3FC||24;1F64D,1F3FD||24;1F64D,1F3FE||24;1F64D,1F3FF||24 - 1F64D,1F3FB,200D,2642,FE0F||25;1F64D,1F3FC,200D,2642,FE0F||25;1F64D,1F3FD,200D,2642,FE0F||25;1F64D,1F3FE,200D,2642,FE0F||25;1F64D,1F3FF,200D,2642,FE0F||25 - 1F64D,1F3FB,200D,2640,FE0F||25;1F64D,1F3FC,200D,2640,FE0F||25;1F64D,1F3FD,200D,2640,FE0F||25;1F64D,1F3FE,200D,2640,FE0F||25;1F64D,1F3FF,200D,2640,FE0F||25 - 1F64E,1F3FB||24;1F64E,1F3FC||24;1F64E,1F3FD||24;1F64E,1F3FE||24;1F64E,1F3FF||24 - 1F64E,1F3FB,200D,2642,FE0F||25;1F64E,1F3FC,200D,2642,FE0F||25;1F64E,1F3FD,200D,2642,FE0F||25;1F64E,1F3FE,200D,2642,FE0F||25;1F64E,1F3FF,200D,2642,FE0F||25 - 1F64E,1F3FB,200D,2640,FE0F||25;1F64E,1F3FC,200D,2640,FE0F||25;1F64E,1F3FD,200D,2640,FE0F||25;1F64E,1F3FE,200D,2640,FE0F||25;1F64E,1F3FF,200D,2640,FE0F||25 - 1F645,1F3FB||24;1F645,1F3FC||24;1F645,1F3FD||24;1F645,1F3FE||24;1F645,1F3FF||24 - 1F645,1F3FB,200D,2642,FE0F||25;1F645,1F3FC,200D,2642,FE0F||25;1F645,1F3FD,200D,2642,FE0F||25;1F645,1F3FE,200D,2642,FE0F||25;1F645,1F3FF,200D,2642,FE0F||25 - 1F645,1F3FB,200D,2640,FE0F||25;1F645,1F3FC,200D,2640,FE0F||25;1F645,1F3FD,200D,2640,FE0F||25;1F645,1F3FE,200D,2640,FE0F||25;1F645,1F3FF,200D,2640,FE0F||25 - 1F646,1F3FB||24;1F646,1F3FC||24;1F646,1F3FD||24;1F646,1F3FE||24;1F646,1F3FF||24 - 1F646,1F3FB,200D,2642,FE0F||25;1F646,1F3FC,200D,2642,FE0F||25;1F646,1F3FD,200D,2642,FE0F||25;1F646,1F3FE,200D,2642,FE0F||25;1F646,1F3FF,200D,2642,FE0F||25 - 1F646,1F3FB,200D,2640,FE0F||25;1F646,1F3FC,200D,2640,FE0F||25;1F646,1F3FD,200D,2640,FE0F||25;1F646,1F3FE,200D,2640,FE0F||25;1F646,1F3FF,200D,2640,FE0F||25 - 1F481,1F3FB||24;1F481,1F3FC||24;1F481,1F3FD||24;1F481,1F3FE||24;1F481,1F3FF||24 - 1F481,1F3FB,200D,2642,FE0F||25;1F481,1F3FC,200D,2642,FE0F||25;1F481,1F3FD,200D,2642,FE0F||25;1F481,1F3FE,200D,2642,FE0F||25;1F481,1F3FF,200D,2642,FE0F||25 - 1F481,1F3FB,200D,2640,FE0F||25;1F481,1F3FC,200D,2640,FE0F||25;1F481,1F3FD,200D,2640,FE0F||25;1F481,1F3FE,200D,2640,FE0F||25;1F481,1F3FF,200D,2640,FE0F||25 - 1F64B,1F3FB||24;1F64B,1F3FC||24;1F64B,1F3FD||24;1F64B,1F3FE||24;1F64B,1F3FF||24 - 1F64B,1F3FB,200D,2642,FE0F||25;1F64B,1F3FC,200D,2642,FE0F||25;1F64B,1F3FD,200D,2642,FE0F||25;1F64B,1F3FE,200D,2642,FE0F||25;1F64B,1F3FF,200D,2642,FE0F||25 - 1F64B,1F3FB,200D,2640,FE0F||25;1F64B,1F3FC,200D,2640,FE0F||25;1F64B,1F3FD,200D,2640,FE0F||25;1F64B,1F3FE,200D,2640,FE0F||25;1F64B,1F3FF,200D,2640,FE0F||25 - 1F9CF,1F3FB||29;1F9CF,1F3FC||29;1F9CF,1F3FD||29;1F9CF,1F3FE||29;1F9CF,1F3FF||29 - 1F9CF,1F3FB,200D,2642,FE0F||29;1F9CF,1F3FC,200D,2642,FE0F||29;1F9CF,1F3FD,200D,2642,FE0F||29;1F9CF,1F3FE,200D,2642,FE0F||29;1F9CF,1F3FF,200D,2642,FE0F||29 - 1F9CF,1F3FB,200D,2640,FE0F||29;1F9CF,1F3FC,200D,2640,FE0F||29;1F9CF,1F3FD,200D,2640,FE0F||29;1F9CF,1F3FE,200D,2640,FE0F||29;1F9CF,1F3FF,200D,2640,FE0F||29 - 1F647,1F3FB||24;1F647,1F3FC||24;1F647,1F3FD||24;1F647,1F3FE||24;1F647,1F3FF||24 - 1F647,1F3FB,200D,2642,FE0F||25;1F647,1F3FC,200D,2642,FE0F||25;1F647,1F3FD,200D,2642,FE0F||25;1F647,1F3FE,200D,2642,FE0F||25;1F647,1F3FF,200D,2642,FE0F||25 - 1F647,1F3FB,200D,2640,FE0F||25;1F647,1F3FC,200D,2640,FE0F||25;1F647,1F3FD,200D,2640,FE0F||25;1F647,1F3FE,200D,2640,FE0F||25;1F647,1F3FF,200D,2640,FE0F||25 - 1F926,1F3FB||24;1F926,1F3FC||24;1F926,1F3FD||24;1F926,1F3FE||24;1F926,1F3FF||24 - 1F926,1F3FB,200D,2642,FE0F||25;1F926,1F3FC,200D,2642,FE0F||25;1F926,1F3FD,200D,2642,FE0F||25;1F926,1F3FE,200D,2642,FE0F||25;1F926,1F3FF,200D,2642,FE0F||25 - 1F926,1F3FB,200D,2640,FE0F||25;1F926,1F3FC,200D,2640,FE0F||25;1F926,1F3FD,200D,2640,FE0F||25;1F926,1F3FE,200D,2640,FE0F||25;1F926,1F3FF,200D,2640,FE0F||25 - 1F937,1F3FB||24;1F937,1F3FC||24;1F937,1F3FD||24;1F937,1F3FE||24;1F937,1F3FF||24 - 1F937,1F3FB,200D,2642,FE0F||25;1F937,1F3FC,200D,2642,FE0F||25;1F937,1F3FD,200D,2642,FE0F||25;1F937,1F3FE,200D,2642,FE0F||25;1F937,1F3FF,200D,2642,FE0F||25 - 1F937,1F3FB,200D,2640,FE0F||25;1F937,1F3FC,200D,2640,FE0F||25;1F937,1F3FD,200D,2640,FE0F||25;1F937,1F3FE,200D,2640,FE0F||25;1F937,1F3FF,200D,2640,FE0F||25 - 1F9D1,1F3FB,200D,2695,FE0F||30;1F9D1,1F3FC,200D,2695,FE0F||30;1F9D1,1F3FD,200D,2695,FE0F||30;1F9D1,1F3FE,200D,2695,FE0F||30;1F9D1,1F3FF,200D,2695,FE0F||30 - 1F468,1F3FB,200D,2695,FE0F||25;1F468,1F3FC,200D,2695,FE0F||25;1F468,1F3FD,200D,2695,FE0F||25;1F468,1F3FE,200D,2695,FE0F||25;1F468,1F3FF,200D,2695,FE0F||25 - 1F469,1F3FB,200D,2695,FE0F||25;1F469,1F3FC,200D,2695,FE0F||25;1F469,1F3FD,200D,2695,FE0F||25;1F469,1F3FE,200D,2695,FE0F||25;1F469,1F3FF,200D,2695,FE0F||25 - 1F9D1,1F3FB,200D,1F393||30;1F9D1,1F3FC,200D,1F393||30;1F9D1,1F3FD,200D,1F393||30;1F9D1,1F3FE,200D,1F393||30;1F9D1,1F3FF,200D,1F393||30 - 1F468,1F3FB,200D,1F393||25;1F468,1F3FC,200D,1F393||25;1F468,1F3FD,200D,1F393||25;1F468,1F3FE,200D,1F393||25;1F468,1F3FF,200D,1F393||25 - 1F469,1F3FB,200D,1F393||25;1F469,1F3FC,200D,1F393||25;1F469,1F3FD,200D,1F393||25;1F469,1F3FE,200D,1F393||25;1F469,1F3FF,200D,1F393||25 - 1F9D1,1F3FB,200D,1F3EB||30;1F9D1,1F3FC,200D,1F3EB||30;1F9D1,1F3FD,200D,1F3EB||30;1F9D1,1F3FE,200D,1F3EB||30;1F9D1,1F3FF,200D,1F3EB||30 - 1F468,1F3FB,200D,1F3EB||25;1F468,1F3FC,200D,1F3EB||25;1F468,1F3FD,200D,1F3EB||25;1F468,1F3FE,200D,1F3EB||25;1F468,1F3FF,200D,1F3EB||25 - 1F469,1F3FB,200D,1F3EB||25;1F469,1F3FC,200D,1F3EB||25;1F469,1F3FD,200D,1F3EB||25;1F469,1F3FE,200D,1F3EB||25;1F469,1F3FF,200D,1F3EB||25 - 1F9D1,1F3FB,200D,2696,FE0F||30;1F9D1,1F3FC,200D,2696,FE0F||30;1F9D1,1F3FD,200D,2696,FE0F||30;1F9D1,1F3FE,200D,2696,FE0F||30;1F9D1,1F3FF,200D,2696,FE0F||30 - 1F468,1F3FB,200D,2696,FE0F||25;1F468,1F3FC,200D,2696,FE0F||25;1F468,1F3FD,200D,2696,FE0F||25;1F468,1F3FE,200D,2696,FE0F||25;1F468,1F3FF,200D,2696,FE0F||25 - 1F469,1F3FB,200D,2696,FE0F||25;1F469,1F3FC,200D,2696,FE0F||25;1F469,1F3FD,200D,2696,FE0F||25;1F469,1F3FE,200D,2696,FE0F||25;1F469,1F3FF,200D,2696,FE0F||25 - 1F9D1,1F3FB,200D,1F33E||30;1F9D1,1F3FC,200D,1F33E||30;1F9D1,1F3FD,200D,1F33E||30;1F9D1,1F3FE,200D,1F33E||30;1F9D1,1F3FF,200D,1F33E||30 - 1F468,1F3FB,200D,1F33E||25;1F468,1F3FC,200D,1F33E||25;1F468,1F3FD,200D,1F33E||25;1F468,1F3FE,200D,1F33E||25;1F468,1F3FF,200D,1F33E||25 - 1F469,1F3FB,200D,1F33E||25;1F469,1F3FC,200D,1F33E||25;1F469,1F3FD,200D,1F33E||25;1F469,1F3FE,200D,1F33E||25;1F469,1F3FF,200D,1F33E||25 - 1F9D1,1F3FB,200D,1F373||30;1F9D1,1F3FC,200D,1F373||30;1F9D1,1F3FD,200D,1F373||30;1F9D1,1F3FE,200D,1F373||30;1F9D1,1F3FF,200D,1F373||30 - 1F468,1F3FB,200D,1F373||25;1F468,1F3FC,200D,1F373||25;1F468,1F3FD,200D,1F373||25;1F468,1F3FE,200D,1F373||25;1F468,1F3FF,200D,1F373||25 - 1F469,1F3FB,200D,1F373||25;1F469,1F3FC,200D,1F373||25;1F469,1F3FD,200D,1F373||25;1F469,1F3FE,200D,1F373||25;1F469,1F3FF,200D,1F373||25 - 1F9D1,1F3FB,200D,1F527||30;1F9D1,1F3FC,200D,1F527||30;1F9D1,1F3FD,200D,1F527||30;1F9D1,1F3FE,200D,1F527||30;1F9D1,1F3FF,200D,1F527||30 - 1F468,1F3FB,200D,1F527||25;1F468,1F3FC,200D,1F527||25;1F468,1F3FD,200D,1F527||25;1F468,1F3FE,200D,1F527||25;1F468,1F3FF,200D,1F527||25 - 1F469,1F3FB,200D,1F527||25;1F469,1F3FC,200D,1F527||25;1F469,1F3FD,200D,1F527||25;1F469,1F3FE,200D,1F527||25;1F469,1F3FF,200D,1F527||25 - 1F9D1,1F3FB,200D,1F3ED||30;1F9D1,1F3FC,200D,1F3ED||30;1F9D1,1F3FD,200D,1F3ED||30;1F9D1,1F3FE,200D,1F3ED||30;1F9D1,1F3FF,200D,1F3ED||30 - 1F468,1F3FB,200D,1F3ED||25;1F468,1F3FC,200D,1F3ED||25;1F468,1F3FD,200D,1F3ED||25;1F468,1F3FE,200D,1F3ED||25;1F468,1F3FF,200D,1F3ED||25 - 1F469,1F3FB,200D,1F3ED||25;1F469,1F3FC,200D,1F3ED||25;1F469,1F3FD,200D,1F3ED||25;1F469,1F3FE,200D,1F3ED||25;1F469,1F3FF,200D,1F3ED||25 - 1F9D1,1F3FB,200D,1F4BC||30;1F9D1,1F3FC,200D,1F4BC||30;1F9D1,1F3FD,200D,1F4BC||30;1F9D1,1F3FE,200D,1F4BC||30;1F9D1,1F3FF,200D,1F4BC||30 - 1F468,1F3FB,200D,1F4BC||25;1F468,1F3FC,200D,1F4BC||25;1F468,1F3FD,200D,1F4BC||25;1F468,1F3FE,200D,1F4BC||25;1F468,1F3FF,200D,1F4BC||25 - 1F469,1F3FB,200D,1F4BC||25;1F469,1F3FC,200D,1F4BC||25;1F469,1F3FD,200D,1F4BC||25;1F469,1F3FE,200D,1F4BC||25;1F469,1F3FF,200D,1F4BC||25 - 1F9D1,1F3FB,200D,1F52C||30;1F9D1,1F3FC,200D,1F52C||30;1F9D1,1F3FD,200D,1F52C||30;1F9D1,1F3FE,200D,1F52C||30;1F9D1,1F3FF,200D,1F52C||30 - 1F468,1F3FB,200D,1F52C||25;1F468,1F3FC,200D,1F52C||25;1F468,1F3FD,200D,1F52C||25;1F468,1F3FE,200D,1F52C||25;1F468,1F3FF,200D,1F52C||25 - 1F469,1F3FB,200D,1F52C||25;1F469,1F3FC,200D,1F52C||25;1F469,1F3FD,200D,1F52C||25;1F469,1F3FE,200D,1F52C||25;1F469,1F3FF,200D,1F52C||25 - 1F9D1,1F3FB,200D,1F4BB||30;1F9D1,1F3FC,200D,1F4BB||30;1F9D1,1F3FD,200D,1F4BB||30;1F9D1,1F3FE,200D,1F4BB||30;1F9D1,1F3FF,200D,1F4BB||30 - 1F468,1F3FB,200D,1F4BB||25;1F468,1F3FC,200D,1F4BB||25;1F468,1F3FD,200D,1F4BB||25;1F468,1F3FE,200D,1F4BB||25;1F468,1F3FF,200D,1F4BB||25 - 1F469,1F3FB,200D,1F4BB||25;1F469,1F3FC,200D,1F4BB||25;1F469,1F3FD,200D,1F4BB||25;1F469,1F3FE,200D,1F4BB||25;1F469,1F3FF,200D,1F4BB||25 - 1F9D1,1F3FB,200D,1F3A4||30;1F9D1,1F3FC,200D,1F3A4||30;1F9D1,1F3FD,200D,1F3A4||30;1F9D1,1F3FE,200D,1F3A4||30;1F9D1,1F3FF,200D,1F3A4||30 - 1F468,1F3FB,200D,1F3A4||25;1F468,1F3FC,200D,1F3A4||25;1F468,1F3FD,200D,1F3A4||25;1F468,1F3FE,200D,1F3A4||25;1F468,1F3FF,200D,1F3A4||25 - 1F469,1F3FB,200D,1F3A4||25;1F469,1F3FC,200D,1F3A4||25;1F469,1F3FD,200D,1F3A4||25;1F469,1F3FE,200D,1F3A4||25;1F469,1F3FF,200D,1F3A4||25 - 1F9D1,1F3FB,200D,1F3A8||30;1F9D1,1F3FC,200D,1F3A8||30;1F9D1,1F3FD,200D,1F3A8||30;1F9D1,1F3FE,200D,1F3A8||30;1F9D1,1F3FF,200D,1F3A8||30 - 1F468,1F3FB,200D,1F3A8||25;1F468,1F3FC,200D,1F3A8||25;1F468,1F3FD,200D,1F3A8||25;1F468,1F3FE,200D,1F3A8||25;1F468,1F3FF,200D,1F3A8||25 - 1F469,1F3FB,200D,1F3A8||25;1F469,1F3FC,200D,1F3A8||25;1F469,1F3FD,200D,1F3A8||25;1F469,1F3FE,200D,1F3A8||25;1F469,1F3FF,200D,1F3A8||25 - 1F9D1,1F3FB,200D,2708,FE0F||30;1F9D1,1F3FC,200D,2708,FE0F||30;1F9D1,1F3FD,200D,2708,FE0F||30;1F9D1,1F3FE,200D,2708,FE0F||30;1F9D1,1F3FF,200D,2708,FE0F||30 - 1F468,1F3FB,200D,2708,FE0F||25;1F468,1F3FC,200D,2708,FE0F||25;1F468,1F3FD,200D,2708,FE0F||25;1F468,1F3FE,200D,2708,FE0F||25;1F468,1F3FF,200D,2708,FE0F||25 - 1F469,1F3FB,200D,2708,FE0F||25;1F469,1F3FC,200D,2708,FE0F||25;1F469,1F3FD,200D,2708,FE0F||25;1F469,1F3FE,200D,2708,FE0F||25;1F469,1F3FF,200D,2708,FE0F||25 - 1F9D1,1F3FB,200D,1F680||30;1F9D1,1F3FC,200D,1F680||30;1F9D1,1F3FD,200D,1F680||30;1F9D1,1F3FE,200D,1F680||30;1F9D1,1F3FF,200D,1F680||30 - 1F468,1F3FB,200D,1F680||25;1F468,1F3FC,200D,1F680||25;1F468,1F3FD,200D,1F680||25;1F468,1F3FE,200D,1F680||25;1F468,1F3FF,200D,1F680||25 - 1F469,1F3FB,200D,1F680||25;1F469,1F3FC,200D,1F680||25;1F469,1F3FD,200D,1F680||25;1F469,1F3FE,200D,1F680||25;1F469,1F3FF,200D,1F680||25 - 1F9D1,1F3FB,200D,1F692||30;1F9D1,1F3FC,200D,1F692||30;1F9D1,1F3FD,200D,1F692||30;1F9D1,1F3FE,200D,1F692||30;1F9D1,1F3FF,200D,1F692||30 - 1F468,1F3FB,200D,1F692||25;1F468,1F3FC,200D,1F692||25;1F468,1F3FD,200D,1F692||25;1F468,1F3FE,200D,1F692||25;1F468,1F3FF,200D,1F692||25 - 1F469,1F3FB,200D,1F692||25;1F469,1F3FC,200D,1F692||25;1F469,1F3FD,200D,1F692||25;1F469,1F3FE,200D,1F692||25;1F469,1F3FF,200D,1F692||25 - 1F46E,1F3FB||24;1F46E,1F3FC||24;1F46E,1F3FD||24;1F46E,1F3FE||24;1F46E,1F3FF||24 - 1F46E,1F3FB,200D,2642,FE0F||25;1F46E,1F3FC,200D,2642,FE0F||25;1F46E,1F3FD,200D,2642,FE0F||25;1F46E,1F3FE,200D,2642,FE0F||25;1F46E,1F3FF,200D,2642,FE0F||25 - 1F46E,1F3FB,200D,2640,FE0F||25;1F46E,1F3FC,200D,2640,FE0F||25;1F46E,1F3FD,200D,2640,FE0F||25;1F46E,1F3FE,200D,2640,FE0F||25;1F46E,1F3FF,200D,2640,FE0F||25 - 1F575,1F3FB||24;1F575,1F3FC||24;1F575,1F3FD||24;1F575,1F3FE||24;1F575,1F3FF||24 - 1F575,1F3FB,200D,2642,FE0F||25;1F575,1F3FC,200D,2642,FE0F||25;1F575,1F3FD,200D,2642,FE0F||25;1F575,1F3FE,200D,2642,FE0F||25;1F575,1F3FF,200D,2642,FE0F||25 - 1F575,1F3FB,200D,2640,FE0F||25;1F575,1F3FC,200D,2640,FE0F||25;1F575,1F3FD,200D,2640,FE0F||25;1F575,1F3FE,200D,2640,FE0F||25;1F575,1F3FF,200D,2640,FE0F||25 - 1F482,1F3FB||24;1F482,1F3FC||24;1F482,1F3FD||24;1F482,1F3FE||24;1F482,1F3FF||24 - 1F482,1F3FB,200D,2642,FE0F||25;1F482,1F3FC,200D,2642,FE0F||25;1F482,1F3FD,200D,2642,FE0F||25;1F482,1F3FE,200D,2642,FE0F||25;1F482,1F3FF,200D,2642,FE0F||25 - 1F482,1F3FB,200D,2640,FE0F||25;1F482,1F3FC,200D,2640,FE0F||25;1F482,1F3FD,200D,2640,FE0F||25;1F482,1F3FE,200D,2640,FE0F||25;1F482,1F3FF,200D,2640,FE0F||25 - 1F977,1F3FB||30;1F977,1F3FC||30;1F977,1F3FD||30;1F977,1F3FE||30;1F977,1F3FF||30 - 1F477,1F3FB||24;1F477,1F3FC||24;1F477,1F3FD||24;1F477,1F3FE||24;1F477,1F3FF||24 - 1F477,1F3FB,200D,2642,FE0F||25;1F477,1F3FC,200D,2642,FE0F||25;1F477,1F3FD,200D,2642,FE0F||25;1F477,1F3FE,200D,2642,FE0F||25;1F477,1F3FF,200D,2642,FE0F||25 - 1F477,1F3FB,200D,2640,FE0F||25;1F477,1F3FC,200D,2640,FE0F||25;1F477,1F3FD,200D,2640,FE0F||25;1F477,1F3FE,200D,2640,FE0F||25;1F477,1F3FF,200D,2640,FE0F||25 - 1FAC5,1F3FB||32;1FAC5,1F3FC||32;1FAC5,1F3FD||32;1FAC5,1F3FE||32;1FAC5,1F3FF||32 - 1F934,1F3FB||24;1F934,1F3FC||24;1F934,1F3FD||24;1F934,1F3FE||24;1F934,1F3FF||24 - 1F478,1F3FB||24;1F478,1F3FC||24;1F478,1F3FD||24;1F478,1F3FE||24;1F478,1F3FF||24 - 1F473,1F3FB||24;1F473,1F3FC||24;1F473,1F3FD||24;1F473,1F3FE||24;1F473,1F3FF||24 - 1F473,1F3FB,200D,2642,FE0F||25;1F473,1F3FC,200D,2642,FE0F||25;1F473,1F3FD,200D,2642,FE0F||25;1F473,1F3FE,200D,2642,FE0F||25;1F473,1F3FF,200D,2642,FE0F||25 - 1F473,1F3FB,200D,2640,FE0F||25;1F473,1F3FC,200D,2640,FE0F||25;1F473,1F3FD,200D,2640,FE0F||25;1F473,1F3FE,200D,2640,FE0F||25;1F473,1F3FF,200D,2640,FE0F||25 - 1F472,1F3FB||24;1F472,1F3FC||24;1F472,1F3FD||24;1F472,1F3FE||24;1F472,1F3FF||24 - 1F9D5,1F3FB||26;1F9D5,1F3FC||26;1F9D5,1F3FD||26;1F9D5,1F3FE||26;1F9D5,1F3FF||26 - 1F935,1F3FB||24;1F935,1F3FC||24;1F935,1F3FD||24;1F935,1F3FE||24;1F935,1F3FF||24 - 1F935,1F3FB,200D,2642,FE0F||30;1F935,1F3FC,200D,2642,FE0F||30;1F935,1F3FD,200D,2642,FE0F||30;1F935,1F3FE,200D,2642,FE0F||30;1F935,1F3FF,200D,2642,FE0F||30 - 1F935,1F3FB,200D,2640,FE0F||30;1F935,1F3FC,200D,2640,FE0F||30;1F935,1F3FD,200D,2640,FE0F||30;1F935,1F3FE,200D,2640,FE0F||30;1F935,1F3FF,200D,2640,FE0F||30 - 1F470,1F3FB||24;1F470,1F3FC||24;1F470,1F3FD||24;1F470,1F3FE||24;1F470,1F3FF||24 - 1F470,1F3FB,200D,2642,FE0F||30;1F470,1F3FC,200D,2642,FE0F||30;1F470,1F3FD,200D,2642,FE0F||30;1F470,1F3FE,200D,2642,FE0F||30;1F470,1F3FF,200D,2642,FE0F||30 - 1F470,1F3FB,200D,2640,FE0F||30;1F470,1F3FC,200D,2640,FE0F||30;1F470,1F3FD,200D,2640,FE0F||30;1F470,1F3FE,200D,2640,FE0F||30;1F470,1F3FF,200D,2640,FE0F||30 - 1F930,1F3FB||24;1F930,1F3FC||24;1F930,1F3FD||24;1F930,1F3FE||24;1F930,1F3FF||24 - 1FAC3,1F3FB||32;1FAC3,1F3FC||32;1FAC3,1F3FD||32;1FAC3,1F3FE||32;1FAC3,1F3FF||32 - 1FAC4,1F3FB||32;1FAC4,1F3FC||32;1FAC4,1F3FD||32;1FAC4,1F3FE||32;1FAC4,1F3FF||32 - 1F931,1F3FB||26;1F931,1F3FC||26;1F931,1F3FD||26;1F931,1F3FE||26;1F931,1F3FF||26 - 1F469,1F3FB,200D,1F37C||30;1F469,1F3FC,200D,1F37C||30;1F469,1F3FD,200D,1F37C||30;1F469,1F3FE,200D,1F37C||30;1F469,1F3FF,200D,1F37C||30 - 1F468,1F3FB,200D,1F37C||30;1F468,1F3FC,200D,1F37C||30;1F468,1F3FD,200D,1F37C||30;1F468,1F3FE,200D,1F37C||30;1F468,1F3FF,200D,1F37C||30 - 1F9D1,1F3FB,200D,1F37C||30;1F9D1,1F3FC,200D,1F37C||30;1F9D1,1F3FD,200D,1F37C||30;1F9D1,1F3FE,200D,1F37C||30;1F9D1,1F3FF,200D,1F37C||30 - 1F47C,1F3FB||24;1F47C,1F3FC||24;1F47C,1F3FD||24;1F47C,1F3FE||24;1F47C,1F3FF||24 - 1F385,1F3FB||24;1F385,1F3FC||24;1F385,1F3FD||24;1F385,1F3FE||24;1F385,1F3FF||24 - 1F936,1F3FB||24;1F936,1F3FC||24;1F936,1F3FD||24;1F936,1F3FE||24;1F936,1F3FF||24 - 1F9D1,1F3FB,200D,1F384||30;1F9D1,1F3FC,200D,1F384||30;1F9D1,1F3FD,200D,1F384||30;1F9D1,1F3FE,200D,1F384||30;1F9D1,1F3FF,200D,1F384||30 - 1F9B8,1F3FB||28;1F9B8,1F3FC||28;1F9B8,1F3FD||28;1F9B8,1F3FE||28;1F9B8,1F3FF||28 - 1F9B8,1F3FB,200D,2642,FE0F||28;1F9B8,1F3FC,200D,2642,FE0F||28;1F9B8,1F3FD,200D,2642,FE0F||28;1F9B8,1F3FE,200D,2642,FE0F||28;1F9B8,1F3FF,200D,2642,FE0F||28 - 1F9B8,1F3FB,200D,2640,FE0F||28;1F9B8,1F3FC,200D,2640,FE0F||28;1F9B8,1F3FD,200D,2640,FE0F||28;1F9B8,1F3FE,200D,2640,FE0F||28;1F9B8,1F3FF,200D,2640,FE0F||28 - 1F9B9,1F3FB||28;1F9B9,1F3FC||28;1F9B9,1F3FD||28;1F9B9,1F3FE||28;1F9B9,1F3FF||28 - 1F9B9,1F3FB,200D,2642,FE0F||28;1F9B9,1F3FC,200D,2642,FE0F||28;1F9B9,1F3FD,200D,2642,FE0F||28;1F9B9,1F3FE,200D,2642,FE0F||28;1F9B9,1F3FF,200D,2642,FE0F||28 - 1F9B9,1F3FB,200D,2640,FE0F||28;1F9B9,1F3FC,200D,2640,FE0F||28;1F9B9,1F3FD,200D,2640,FE0F||28;1F9B9,1F3FE,200D,2640,FE0F||28;1F9B9,1F3FF,200D,2640,FE0F||28 - 1F9D9,1F3FB||26;1F9D9,1F3FC||26;1F9D9,1F3FD||26;1F9D9,1F3FE||26;1F9D9,1F3FF||26 - 1F9D9,1F3FB,200D,2642,FE0F||26;1F9D9,1F3FC,200D,2642,FE0F||26;1F9D9,1F3FD,200D,2642,FE0F||26;1F9D9,1F3FE,200D,2642,FE0F||26;1F9D9,1F3FF,200D,2642,FE0F||26 - 1F9D9,1F3FB,200D,2640,FE0F||26;1F9D9,1F3FC,200D,2640,FE0F||26;1F9D9,1F3FD,200D,2640,FE0F||26;1F9D9,1F3FE,200D,2640,FE0F||26;1F9D9,1F3FF,200D,2640,FE0F||26 - 1F9DA,1F3FB||26;1F9DA,1F3FC||26;1F9DA,1F3FD||26;1F9DA,1F3FE||26;1F9DA,1F3FF||26 - 1F9DA,1F3FB,200D,2642,FE0F||26;1F9DA,1F3FC,200D,2642,FE0F||26;1F9DA,1F3FD,200D,2642,FE0F||26;1F9DA,1F3FE,200D,2642,FE0F||26;1F9DA,1F3FF,200D,2642,FE0F||26 - 1F9DA,1F3FB,200D,2640,FE0F||26;1F9DA,1F3FC,200D,2640,FE0F||26;1F9DA,1F3FD,200D,2640,FE0F||26;1F9DA,1F3FE,200D,2640,FE0F||26;1F9DA,1F3FF,200D,2640,FE0F||26 - 1F9DB,1F3FB||26;1F9DB,1F3FC||26;1F9DB,1F3FD||26;1F9DB,1F3FE||26;1F9DB,1F3FF||26 - 1F9DB,1F3FB,200D,2642,FE0F||26;1F9DB,1F3FC,200D,2642,FE0F||26;1F9DB,1F3FD,200D,2642,FE0F||26;1F9DB,1F3FE,200D,2642,FE0F||26;1F9DB,1F3FF,200D,2642,FE0F||26 - 1F9DB,1F3FB,200D,2640,FE0F||26;1F9DB,1F3FC,200D,2640,FE0F||26;1F9DB,1F3FD,200D,2640,FE0F||26;1F9DB,1F3FE,200D,2640,FE0F||26;1F9DB,1F3FF,200D,2640,FE0F||26 - 1F9DC,1F3FB||26;1F9DC,1F3FC||26;1F9DC,1F3FD||26;1F9DC,1F3FE||26;1F9DC,1F3FF||26 - 1F9DC,1F3FB,200D,2642,FE0F||26;1F9DC,1F3FC,200D,2642,FE0F||26;1F9DC,1F3FD,200D,2642,FE0F||26;1F9DC,1F3FE,200D,2642,FE0F||26;1F9DC,1F3FF,200D,2642,FE0F||26 - 1F9DC,1F3FB,200D,2640,FE0F||26;1F9DC,1F3FC,200D,2640,FE0F||26;1F9DC,1F3FD,200D,2640,FE0F||26;1F9DC,1F3FE,200D,2640,FE0F||26;1F9DC,1F3FF,200D,2640,FE0F||26 - 1F9DD,1F3FB||26;1F9DD,1F3FC||26;1F9DD,1F3FD||26;1F9DD,1F3FE||26;1F9DD,1F3FF||26 - 1F9DD,1F3FB,200D,2642,FE0F||26;1F9DD,1F3FC,200D,2642,FE0F||26;1F9DD,1F3FD,200D,2642,FE0F||26;1F9DD,1F3FE,200D,2642,FE0F||26;1F9DD,1F3FF,200D,2642,FE0F||26 - 1F9DD,1F3FB,200D,2640,FE0F||26;1F9DD,1F3FC,200D,2640,FE0F||26;1F9DD,1F3FD,200D,2640,FE0F||26;1F9DD,1F3FE,200D,2640,FE0F||26;1F9DD,1F3FF,200D,2640,FE0F||26 - - - - - - - - 1F486,1F3FB||24;1F486,1F3FC||24;1F486,1F3FD||24;1F486,1F3FE||24;1F486,1F3FF||24 - 1F486,1F3FB,200D,2642,FE0F||25;1F486,1F3FC,200D,2642,FE0F||25;1F486,1F3FD,200D,2642,FE0F||25;1F486,1F3FE,200D,2642,FE0F||25;1F486,1F3FF,200D,2642,FE0F||25 - 1F486,1F3FB,200D,2640,FE0F||25;1F486,1F3FC,200D,2640,FE0F||25;1F486,1F3FD,200D,2640,FE0F||25;1F486,1F3FE,200D,2640,FE0F||25;1F486,1F3FF,200D,2640,FE0F||25 - 1F487,1F3FB||24;1F487,1F3FC||24;1F487,1F3FD||24;1F487,1F3FE||24;1F487,1F3FF||24 - 1F487,1F3FB,200D,2642,FE0F||25;1F487,1F3FC,200D,2642,FE0F||25;1F487,1F3FD,200D,2642,FE0F||25;1F487,1F3FE,200D,2642,FE0F||25;1F487,1F3FF,200D,2642,FE0F||25 - 1F487,1F3FB,200D,2640,FE0F||25;1F487,1F3FC,200D,2640,FE0F||25;1F487,1F3FD,200D,2640,FE0F||25;1F487,1F3FE,200D,2640,FE0F||25;1F487,1F3FF,200D,2640,FE0F||25 - 1F6B6,1F3FB||24;1F6B6,1F3FC||24;1F6B6,1F3FD||24;1F6B6,1F3FE||24;1F6B6,1F3FF||24 - 1F6B6,1F3FB,200D,2642,FE0F||25;1F6B6,1F3FC,200D,2642,FE0F||25;1F6B6,1F3FD,200D,2642,FE0F||25;1F6B6,1F3FE,200D,2642,FE0F||25;1F6B6,1F3FF,200D,2642,FE0F||25 - 1F6B6,1F3FB,200D,2640,FE0F||25;1F6B6,1F3FC,200D,2640,FE0F||25;1F6B6,1F3FD,200D,2640,FE0F||25;1F6B6,1F3FE,200D,2640,FE0F||25;1F6B6,1F3FF,200D,2640,FE0F||25 - 1F6B6,1F3FB,200D,27A1,FE0F||34;1F6B6,1F3FC,200D,27A1,FE0F||34;1F6B6,1F3FD,200D,27A1,FE0F||34;1F6B6,1F3FE,200D,27A1,FE0F||34;1F6B6,1F3FF,200D,27A1,FE0F||34 - 1F6B6,1F3FB,200D,2640,FE0F,200D,27A1,FE0F||34;1F6B6,1F3FC,200D,2640,FE0F,200D,27A1,FE0F||34;1F6B6,1F3FD,200D,2640,FE0F,200D,27A1,FE0F||34;1F6B6,1F3FE,200D,2640,FE0F,200D,27A1,FE0F||34;1F6B6,1F3FF,200D,2640,FE0F,200D,27A1,FE0F||34 - 1F6B6,1F3FB,200D,2642,FE0F,200D,27A1,FE0F||34;1F6B6,1F3FC,200D,2642,FE0F,200D,27A1,FE0F||34;1F6B6,1F3FD,200D,2642,FE0F,200D,27A1,FE0F||34;1F6B6,1F3FE,200D,2642,FE0F,200D,27A1,FE0F||34;1F6B6,1F3FF,200D,2642,FE0F,200D,27A1,FE0F||34 - 1F9CD,1F3FB||29;1F9CD,1F3FC||29;1F9CD,1F3FD||29;1F9CD,1F3FE||29;1F9CD,1F3FF||29 - 1F9CD,1F3FB,200D,2642,FE0F||29;1F9CD,1F3FC,200D,2642,FE0F||29;1F9CD,1F3FD,200D,2642,FE0F||29;1F9CD,1F3FE,200D,2642,FE0F||29;1F9CD,1F3FF,200D,2642,FE0F||29 - 1F9CD,1F3FB,200D,2640,FE0F||29;1F9CD,1F3FC,200D,2640,FE0F||29;1F9CD,1F3FD,200D,2640,FE0F||29;1F9CD,1F3FE,200D,2640,FE0F||29;1F9CD,1F3FF,200D,2640,FE0F||29 - 1F9CE,1F3FB||29;1F9CE,1F3FC||29;1F9CE,1F3FD||29;1F9CE,1F3FE||29;1F9CE,1F3FF||29 - 1F9CE,1F3FB,200D,2642,FE0F||29;1F9CE,1F3FC,200D,2642,FE0F||29;1F9CE,1F3FD,200D,2642,FE0F||29;1F9CE,1F3FE,200D,2642,FE0F||29;1F9CE,1F3FF,200D,2642,FE0F||29 - 1F9CE,1F3FB,200D,2640,FE0F||29;1F9CE,1F3FC,200D,2640,FE0F||29;1F9CE,1F3FD,200D,2640,FE0F||29;1F9CE,1F3FE,200D,2640,FE0F||29;1F9CE,1F3FF,200D,2640,FE0F||29 - 1F9CE,1F3FB,200D,27A1,FE0F||34;1F9CE,1F3FC,200D,27A1,FE0F||34;1F9CE,1F3FD,200D,27A1,FE0F||34;1F9CE,1F3FE,200D,27A1,FE0F||34;1F9CE,1F3FF,200D,27A1,FE0F||34 - 1F9CE,1F3FB,200D,2640,FE0F,200D,27A1,FE0F||34;1F9CE,1F3FC,200D,2640,FE0F,200D,27A1,FE0F||34;1F9CE,1F3FD,200D,2640,FE0F,200D,27A1,FE0F||34;1F9CE,1F3FE,200D,2640,FE0F,200D,27A1,FE0F||34;1F9CE,1F3FF,200D,2640,FE0F,200D,27A1,FE0F||34 - 1F9CE,1F3FB,200D,2642,FE0F,200D,27A1,FE0F||34;1F9CE,1F3FC,200D,2642,FE0F,200D,27A1,FE0F||34;1F9CE,1F3FD,200D,2642,FE0F,200D,27A1,FE0F||34;1F9CE,1F3FE,200D,2642,FE0F,200D,27A1,FE0F||34;1F9CE,1F3FF,200D,2642,FE0F,200D,27A1,FE0F||34 - 1F9D1,1F3FB,200D,1F9AF||30;1F9D1,1F3FC,200D,1F9AF||30;1F9D1,1F3FD,200D,1F9AF||30;1F9D1,1F3FE,200D,1F9AF||30;1F9D1,1F3FF,200D,1F9AF||30 - 1F9D1,1F3FB,200D,1F9AF,200D,27A1,FE0F||34;1F9D1,1F3FC,200D,1F9AF,200D,27A1,FE0F||34;1F9D1,1F3FD,200D,1F9AF,200D,27A1,FE0F||34;1F9D1,1F3FE,200D,1F9AF,200D,27A1,FE0F||34;1F9D1,1F3FF,200D,1F9AF,200D,27A1,FE0F||34 - 1F468,1F3FB,200D,1F9AF||29;1F468,1F3FC,200D,1F9AF||29;1F468,1F3FD,200D,1F9AF||29;1F468,1F3FE,200D,1F9AF||29;1F468,1F3FF,200D,1F9AF||29 - 1F468,1F3FB,200D,1F9AF,200D,27A1,FE0F||34;1F468,1F3FC,200D,1F9AF,200D,27A1,FE0F||34;1F468,1F3FD,200D,1F9AF,200D,27A1,FE0F||34;1F468,1F3FE,200D,1F9AF,200D,27A1,FE0F||34;1F468,1F3FF,200D,1F9AF,200D,27A1,FE0F||34 - 1F469,1F3FB,200D,1F9AF||29;1F469,1F3FC,200D,1F9AF||29;1F469,1F3FD,200D,1F9AF||29;1F469,1F3FE,200D,1F9AF||29;1F469,1F3FF,200D,1F9AF||29 - 1F469,1F3FB,200D,1F9AF,200D,27A1,FE0F||34;1F469,1F3FC,200D,1F9AF,200D,27A1,FE0F||34;1F469,1F3FD,200D,1F9AF,200D,27A1,FE0F||34;1F469,1F3FE,200D,1F9AF,200D,27A1,FE0F||34;1F469,1F3FF,200D,1F9AF,200D,27A1,FE0F||34 - 1F9D1,1F3FB,200D,1F9BC||30;1F9D1,1F3FC,200D,1F9BC||30;1F9D1,1F3FD,200D,1F9BC||30;1F9D1,1F3FE,200D,1F9BC||30;1F9D1,1F3FF,200D,1F9BC||30 - 1F9D1,1F3FB,200D,1F9BC,200D,27A1,FE0F||34;1F9D1,1F3FC,200D,1F9BC,200D,27A1,FE0F||34;1F9D1,1F3FD,200D,1F9BC,200D,27A1,FE0F||34;1F9D1,1F3FE,200D,1F9BC,200D,27A1,FE0F||34;1F9D1,1F3FF,200D,1F9BC,200D,27A1,FE0F||34 - 1F468,1F3FB,200D,1F9BC||29;1F468,1F3FC,200D,1F9BC||29;1F468,1F3FD,200D,1F9BC||29;1F468,1F3FE,200D,1F9BC||29;1F468,1F3FF,200D,1F9BC||29 - 1F468,1F3FB,200D,1F9BC,200D,27A1,FE0F||34;1F468,1F3FC,200D,1F9BC,200D,27A1,FE0F||34;1F468,1F3FD,200D,1F9BC,200D,27A1,FE0F||34;1F468,1F3FE,200D,1F9BC,200D,27A1,FE0F||34;1F468,1F3FF,200D,1F9BC,200D,27A1,FE0F||34 - 1F469,1F3FB,200D,1F9BC||29;1F469,1F3FC,200D,1F9BC||29;1F469,1F3FD,200D,1F9BC||29;1F469,1F3FE,200D,1F9BC||29;1F469,1F3FF,200D,1F9BC||29 - 1F469,1F3FB,200D,1F9BC,200D,27A1,FE0F||34;1F469,1F3FC,200D,1F9BC,200D,27A1,FE0F||34;1F469,1F3FD,200D,1F9BC,200D,27A1,FE0F||34;1F469,1F3FE,200D,1F9BC,200D,27A1,FE0F||34;1F469,1F3FF,200D,1F9BC,200D,27A1,FE0F||34 - 1F9D1,1F3FB,200D,1F9BD||30;1F9D1,1F3FC,200D,1F9BD||30;1F9D1,1F3FD,200D,1F9BD||30;1F9D1,1F3FE,200D,1F9BD||30;1F9D1,1F3FF,200D,1F9BD||30 - 1F9D1,1F3FB,200D,1F9BD,200D,27A1,FE0F||34;1F9D1,1F3FC,200D,1F9BD,200D,27A1,FE0F||34;1F9D1,1F3FD,200D,1F9BD,200D,27A1,FE0F||34;1F9D1,1F3FE,200D,1F9BD,200D,27A1,FE0F||34;1F9D1,1F3FF,200D,1F9BD,200D,27A1,FE0F||34 - 1F468,1F3FB,200D,1F9BD||29;1F468,1F3FC,200D,1F9BD||29;1F468,1F3FD,200D,1F9BD||29;1F468,1F3FE,200D,1F9BD||29;1F468,1F3FF,200D,1F9BD||29 - 1F468,1F3FB,200D,1F9BD,200D,27A1,FE0F||34;1F468,1F3FC,200D,1F9BD,200D,27A1,FE0F||34;1F468,1F3FD,200D,1F9BD,200D,27A1,FE0F||34;1F468,1F3FE,200D,1F9BD,200D,27A1,FE0F||34;1F468,1F3FF,200D,1F9BD,200D,27A1,FE0F||34 - 1F469,1F3FB,200D,1F9BD||29;1F469,1F3FC,200D,1F9BD||29;1F469,1F3FD,200D,1F9BD||29;1F469,1F3FE,200D,1F9BD||29;1F469,1F3FF,200D,1F9BD||29 - 1F469,1F3FB,200D,1F9BD,200D,27A1,FE0F||34;1F469,1F3FC,200D,1F9BD,200D,27A1,FE0F||34;1F469,1F3FD,200D,1F9BD,200D,27A1,FE0F||34;1F469,1F3FE,200D,1F9BD,200D,27A1,FE0F||34;1F469,1F3FF,200D,1F9BD,200D,27A1,FE0F||34 - 1F3C3,1F3FB||24;1F3C3,1F3FC||24;1F3C3,1F3FD||24;1F3C3,1F3FE||24;1F3C3,1F3FF||24 - 1F3C3,1F3FB,200D,2642,FE0F||25;1F3C3,1F3FC,200D,2642,FE0F||25;1F3C3,1F3FD,200D,2642,FE0F||25;1F3C3,1F3FE,200D,2642,FE0F||25;1F3C3,1F3FF,200D,2642,FE0F||25 - 1F3C3,1F3FB,200D,2640,FE0F||25;1F3C3,1F3FC,200D,2640,FE0F||25;1F3C3,1F3FD,200D,2640,FE0F||25;1F3C3,1F3FE,200D,2640,FE0F||25;1F3C3,1F3FF,200D,2640,FE0F||25 - 1F3C3,1F3FB,200D,27A1,FE0F||34;1F3C3,1F3FC,200D,27A1,FE0F||34;1F3C3,1F3FD,200D,27A1,FE0F||34;1F3C3,1F3FE,200D,27A1,FE0F||34;1F3C3,1F3FF,200D,27A1,FE0F||34 - 1F3C3,1F3FB,200D,2640,FE0F,200D,27A1,FE0F||34;1F3C3,1F3FC,200D,2640,FE0F,200D,27A1,FE0F||34;1F3C3,1F3FD,200D,2640,FE0F,200D,27A1,FE0F||34;1F3C3,1F3FE,200D,2640,FE0F,200D,27A1,FE0F||34;1F3C3,1F3FF,200D,2640,FE0F,200D,27A1,FE0F||34 - 1F3C3,1F3FB,200D,2642,FE0F,200D,27A1,FE0F||34;1F3C3,1F3FC,200D,2642,FE0F,200D,27A1,FE0F||34;1F3C3,1F3FD,200D,2642,FE0F,200D,27A1,FE0F||34;1F3C3,1F3FE,200D,2642,FE0F,200D,27A1,FE0F||34;1F3C3,1F3FF,200D,2642,FE0F,200D,27A1,FE0F||34 - 1F483,1F3FB||24;1F483,1F3FC||24;1F483,1F3FD||24;1F483,1F3FE||24;1F483,1F3FF||24 - 1F57A,1F3FB||24;1F57A,1F3FC||24;1F57A,1F3FD||24;1F57A,1F3FE||24;1F57A,1F3FF||24 - 1F574,1F3FB||26;1F574,1F3FC||26;1F574,1F3FD||26;1F574,1F3FE||26;1F574,1F3FF||26 - - - - 1F9D6,1F3FB||26;1F9D6,1F3FC||26;1F9D6,1F3FD||26;1F9D6,1F3FE||26;1F9D6,1F3FF||26 - 1F9D6,1F3FB,200D,2642,FE0F||26;1F9D6,1F3FC,200D,2642,FE0F||26;1F9D6,1F3FD,200D,2642,FE0F||26;1F9D6,1F3FE,200D,2642,FE0F||26;1F9D6,1F3FF,200D,2642,FE0F||26 - 1F9D6,1F3FB,200D,2640,FE0F||26;1F9D6,1F3FC,200D,2640,FE0F||26;1F9D6,1F3FD,200D,2640,FE0F||26;1F9D6,1F3FE,200D,2640,FE0F||26;1F9D6,1F3FF,200D,2640,FE0F||26 - 1F9D7,1F3FB||26;1F9D7,1F3FC||26;1F9D7,1F3FD||26;1F9D7,1F3FE||26;1F9D7,1F3FF||26 - 1F9D7,1F3FB,200D,2642,FE0F||26;1F9D7,1F3FC,200D,2642,FE0F||26;1F9D7,1F3FD,200D,2642,FE0F||26;1F9D7,1F3FE,200D,2642,FE0F||26;1F9D7,1F3FF,200D,2642,FE0F||26 - 1F9D7,1F3FB,200D,2640,FE0F||26;1F9D7,1F3FC,200D,2640,FE0F||26;1F9D7,1F3FD,200D,2640,FE0F||26;1F9D7,1F3FE,200D,2640,FE0F||26;1F9D7,1F3FF,200D,2640,FE0F||26 - - 1F3C7,1F3FB||26;1F3C7,1F3FC||26;1F3C7,1F3FD||26;1F3C7,1F3FE||26;1F3C7,1F3FF||26 - - 1F3C2,1F3FB||26;1F3C2,1F3FC||26;1F3C2,1F3FD||26;1F3C2,1F3FE||26;1F3C2,1F3FF||26 - 1F3CC,1F3FB||26;1F3CC,1F3FC||26;1F3CC,1F3FD||26;1F3CC,1F3FE||26;1F3CC,1F3FF||26 - 1F3CC,1F3FB,200D,2642,FE0F||26;1F3CC,1F3FC,200D,2642,FE0F||26;1F3CC,1F3FD,200D,2642,FE0F||26;1F3CC,1F3FE,200D,2642,FE0F||26;1F3CC,1F3FF,200D,2642,FE0F||26 - 1F3CC,1F3FB,200D,2640,FE0F||26;1F3CC,1F3FC,200D,2640,FE0F||26;1F3CC,1F3FD,200D,2640,FE0F||26;1F3CC,1F3FE,200D,2640,FE0F||26;1F3CC,1F3FF,200D,2640,FE0F||26 - 1F3C4,1F3FB||24;1F3C4,1F3FC||24;1F3C4,1F3FD||24;1F3C4,1F3FE||24;1F3C4,1F3FF||24 - 1F3C4,1F3FB,200D,2642,FE0F||25;1F3C4,1F3FC,200D,2642,FE0F||25;1F3C4,1F3FD,200D,2642,FE0F||25;1F3C4,1F3FE,200D,2642,FE0F||25;1F3C4,1F3FF,200D,2642,FE0F||25 - 1F3C4,1F3FB,200D,2640,FE0F||25;1F3C4,1F3FC,200D,2640,FE0F||25;1F3C4,1F3FD,200D,2640,FE0F||25;1F3C4,1F3FE,200D,2640,FE0F||25;1F3C4,1F3FF,200D,2640,FE0F||25 - 1F6A3,1F3FB||24;1F6A3,1F3FC||24;1F6A3,1F3FD||24;1F6A3,1F3FE||24;1F6A3,1F3FF||24 - 1F6A3,1F3FB,200D,2642,FE0F||25;1F6A3,1F3FC,200D,2642,FE0F||25;1F6A3,1F3FD,200D,2642,FE0F||25;1F6A3,1F3FE,200D,2642,FE0F||25;1F6A3,1F3FF,200D,2642,FE0F||25 - 1F6A3,1F3FB,200D,2640,FE0F||25;1F6A3,1F3FC,200D,2640,FE0F||25;1F6A3,1F3FD,200D,2640,FE0F||25;1F6A3,1F3FE,200D,2640,FE0F||25;1F6A3,1F3FF,200D,2640,FE0F||25 - 1F3CA,1F3FB||24;1F3CA,1F3FC||24;1F3CA,1F3FD||24;1F3CA,1F3FE||24;1F3CA,1F3FF||24 - 1F3CA,1F3FB,200D,2642,FE0F||25;1F3CA,1F3FC,200D,2642,FE0F||25;1F3CA,1F3FD,200D,2642,FE0F||25;1F3CA,1F3FE,200D,2642,FE0F||25;1F3CA,1F3FF,200D,2642,FE0F||25 - 1F3CA,1F3FB,200D,2640,FE0F||25;1F3CA,1F3FC,200D,2640,FE0F||25;1F3CA,1F3FD,200D,2640,FE0F||25;1F3CA,1F3FE,200D,2640,FE0F||25;1F3CA,1F3FF,200D,2640,FE0F||25 - 26F9,1F3FB||24;26F9,1F3FC||24;26F9,1F3FD||24;26F9,1F3FE||24;26F9,1F3FF||24 - 26F9,1F3FB,200D,2642,FE0F||25;26F9,1F3FC,200D,2642,FE0F||25;26F9,1F3FD,200D,2642,FE0F||25;26F9,1F3FE,200D,2642,FE0F||25;26F9,1F3FF,200D,2642,FE0F||25 - 26F9,1F3FB,200D,2640,FE0F||25;26F9,1F3FC,200D,2640,FE0F||25;26F9,1F3FD,200D,2640,FE0F||25;26F9,1F3FE,200D,2640,FE0F||25;26F9,1F3FF,200D,2640,FE0F||25 - 1F3CB,1F3FB||24;1F3CB,1F3FC||24;1F3CB,1F3FD||24;1F3CB,1F3FE||24;1F3CB,1F3FF||24 - 1F3CB,1F3FB,200D,2642,FE0F||25;1F3CB,1F3FC,200D,2642,FE0F||25;1F3CB,1F3FD,200D,2642,FE0F||25;1F3CB,1F3FE,200D,2642,FE0F||25;1F3CB,1F3FF,200D,2642,FE0F||25 - 1F3CB,1F3FB,200D,2640,FE0F||25;1F3CB,1F3FC,200D,2640,FE0F||25;1F3CB,1F3FD,200D,2640,FE0F||25;1F3CB,1F3FE,200D,2640,FE0F||25;1F3CB,1F3FF,200D,2640,FE0F||25 - 1F6B4,1F3FB||24;1F6B4,1F3FC||24;1F6B4,1F3FD||24;1F6B4,1F3FE||24;1F6B4,1F3FF||24 - 1F6B4,1F3FB,200D,2642,FE0F||25;1F6B4,1F3FC,200D,2642,FE0F||25;1F6B4,1F3FD,200D,2642,FE0F||25;1F6B4,1F3FE,200D,2642,FE0F||25;1F6B4,1F3FF,200D,2642,FE0F||25 - 1F6B4,1F3FB,200D,2640,FE0F||25;1F6B4,1F3FC,200D,2640,FE0F||25;1F6B4,1F3FD,200D,2640,FE0F||25;1F6B4,1F3FE,200D,2640,FE0F||25;1F6B4,1F3FF,200D,2640,FE0F||25 - 1F6B5,1F3FB||24;1F6B5,1F3FC||24;1F6B5,1F3FD||24;1F6B5,1F3FE||24;1F6B5,1F3FF||24 - 1F6B5,1F3FB,200D,2642,FE0F||25;1F6B5,1F3FC,200D,2642,FE0F||25;1F6B5,1F3FD,200D,2642,FE0F||25;1F6B5,1F3FE,200D,2642,FE0F||25;1F6B5,1F3FF,200D,2642,FE0F||25 - 1F6B5,1F3FB,200D,2640,FE0F||25;1F6B5,1F3FC,200D,2640,FE0F||25;1F6B5,1F3FD,200D,2640,FE0F||25;1F6B5,1F3FE,200D,2640,FE0F||25;1F6B5,1F3FF,200D,2640,FE0F||25 - 1F938,1F3FB||24;1F938,1F3FC||24;1F938,1F3FD||24;1F938,1F3FE||24;1F938,1F3FF||24 - 1F938,1F3FB,200D,2642,FE0F||25;1F938,1F3FC,200D,2642,FE0F||25;1F938,1F3FD,200D,2642,FE0F||25;1F938,1F3FE,200D,2642,FE0F||25;1F938,1F3FF,200D,2642,FE0F||25 - 1F938,1F3FB,200D,2640,FE0F||25;1F938,1F3FC,200D,2640,FE0F||25;1F938,1F3FD,200D,2640,FE0F||25;1F938,1F3FE,200D,2640,FE0F||25;1F938,1F3FF,200D,2640,FE0F||25 - - - - 1F93D,1F3FB||24;1F93D,1F3FC||24;1F93D,1F3FD||24;1F93D,1F3FE||24;1F93D,1F3FF||24 - 1F93D,1F3FB,200D,2642,FE0F||25;1F93D,1F3FC,200D,2642,FE0F||25;1F93D,1F3FD,200D,2642,FE0F||25;1F93D,1F3FE,200D,2642,FE0F||25;1F93D,1F3FF,200D,2642,FE0F||25 - 1F93D,1F3FB,200D,2640,FE0F||25;1F93D,1F3FC,200D,2640,FE0F||25;1F93D,1F3FD,200D,2640,FE0F||25;1F93D,1F3FE,200D,2640,FE0F||25;1F93D,1F3FF,200D,2640,FE0F||25 - 1F93E,1F3FB||24;1F93E,1F3FC||24;1F93E,1F3FD||24;1F93E,1F3FE||24;1F93E,1F3FF||24 - 1F93E,1F3FB,200D,2642,FE0F||25;1F93E,1F3FC,200D,2642,FE0F||25;1F93E,1F3FD,200D,2642,FE0F||25;1F93E,1F3FE,200D,2642,FE0F||25;1F93E,1F3FF,200D,2642,FE0F||25 - 1F93E,1F3FB,200D,2640,FE0F||25;1F93E,1F3FC,200D,2640,FE0F||25;1F93E,1F3FD,200D,2640,FE0F||25;1F93E,1F3FE,200D,2640,FE0F||25;1F93E,1F3FF,200D,2640,FE0F||25 - 1F939,1F3FB||24;1F939,1F3FC||24;1F939,1F3FD||24;1F939,1F3FE||24;1F939,1F3FF||24 - 1F939,1F3FB,200D,2642,FE0F||25;1F939,1F3FC,200D,2642,FE0F||25;1F939,1F3FD,200D,2642,FE0F||25;1F939,1F3FE,200D,2642,FE0F||25;1F939,1F3FF,200D,2642,FE0F||25 - 1F939,1F3FB,200D,2640,FE0F||25;1F939,1F3FC,200D,2640,FE0F||25;1F939,1F3FD,200D,2640,FE0F||25;1F939,1F3FE,200D,2640,FE0F||25;1F939,1F3FF,200D,2640,FE0F||25 - 1F9D8,1F3FB||26;1F9D8,1F3FC||26;1F9D8,1F3FD||26;1F9D8,1F3FE||26;1F9D8,1F3FF||26 - 1F9D8,1F3FB,200D,2642,FE0F||26;1F9D8,1F3FC,200D,2642,FE0F||26;1F9D8,1F3FD,200D,2642,FE0F||26;1F9D8,1F3FE,200D,2642,FE0F||26;1F9D8,1F3FF,200D,2642,FE0F||26 - 1F9D8,1F3FB,200D,2640,FE0F||26;1F9D8,1F3FC,200D,2640,FE0F||26;1F9D8,1F3FD,200D,2640,FE0F||26;1F9D8,1F3FE,200D,2640,FE0F||26;1F9D8,1F3FF,200D,2640,FE0F||26 - 1F6C0,1F3FB||24;1F6C0,1F3FC||24;1F6C0,1F3FD||24;1F6C0,1F3FE||24;1F6C0,1F3FF||24 - 1F6CC,1F3FB||26;1F6CC,1F3FC||26;1F6CC,1F3FD||26;1F6CC,1F3FE||26;1F6CC,1F3FF||26 - - 1F46D,1F3FB||29;1F46D,1F3FC||29;1F46D,1F3FD||29;1F46D,1F3FE||29;1F46D,1F3FF||29 - 1F46B,1F3FB||29;1F46B,1F3FC||29;1F46B,1F3FD||29;1F46B,1F3FE||29;1F46B,1F3FF||29 - 1F46C,1F3FB||29;1F46C,1F3FC||29;1F46C,1F3FD||29;1F46C,1F3FE||29;1F46C,1F3FF||29 - 1F48F,1F3FB||31;1F48F,1F3FC||31;1F48F,1F3FD||31;1F48F,1F3FE||31;1F48F,1F3FF||31 - - - - 1F491,1F3FB||31;1F491,1F3FC||31;1F491,1F3FD||31;1F491,1F3FE||31;1F491,1F3FF||31 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1F435 - 1F412 - 1F98D||24 - 1F9A7||29 - 1F436 - 1F415 - 1F9AE||29 - 1F415,200D,1F9BA||29 - 1F429 - 1F43A - 1F98A||24 - 1F99D||28 - 1F431 - 1F408 - 1F408,200D,2B1B||30 - 1F981||23 - 1F42F - 1F405 - 1F406 - 1F434 - 1FACE||33 - 1FACF||33 - 1F40E - 1F984||23 - 1F993||26 - 1F98C||24 - 1F9AC||30 - 1F42E - 1F402 - 1F403 - 1F404 - 1F437 - 1F416 - 1F417 - 1F43D - 1F40F - 1F411 - 1F410 - 1F42A - 1F42B - 1F999||28 - 1F992||26 - 1F418 - 1F9A3||30 - 1F98F||24 - 1F99B||28 - 1F42D - 1F401 - 1F400 - 1F439 - 1F430 - 1F407 - 1F43F,FE0F||23 - 1F9AB||30 - 1F994||26 - 1F987||24 - 1F43B - 1F43B,200D,2744,FE0F||30 - 1F428 - 1F43C - 1F9A5||29 - 1F9A6||29 - 1F9A8||29 - 1F998||28 - 1F9A1||28 - 1F43E - 1F983||23 - 1F414 - 1F413 - 1F423 - 1F424 - 1F425 - 1F426 - 1F427 - 1F54A,FE0F||23 - 1F985||24 - 1F986||24 - 1F9A2||28 - 1F989||24 - 1F9A4||30 - 1FAB6||30 - 1F9A9||29 - 1F99A||28 - 1F99C||28 - 1FABD||33 - 1F426,200D,2B1B||33 - 1FABF||33 - 1F426,200D,1F525||34 - 1F438 - 1F40A - 1F422 - 1F98E||24 - 1F40D - 1F432 - 1F409 - 1F995||26 - 1F996||26 - 1F433 - 1F40B - 1F42C - 1F9AD||30 - 1F41F - 1F420 - 1F421 - 1F988||24 - 1F419 - 1F41A - 1FAB8||32 - 1FABC||33 - 1F980||23 - 1F99E||28 - 1F990||24 - 1F991||24 - 1F9AA||29 - 1F40C - 1F98B||24 - 1F41B - 1F41C - 1F41D - 1FAB2||30 - 1F41E - 1F997||26 - 1FAB3||30 - 1F577,FE0F||23 - 1F578,FE0F||23 - 1F982||23 - 1F99F||28 - 1FAB0||30 - 1FAB1||30 - 1F9A0||28 - 1F490 - 1F338 - 1F4AE - 1FAB7||32 - 1F3F5,FE0F||23 - 1F339 - 1F940||24 - 1F33A - 1F33B - 1F33C - 1F337 - 1FABB||33 - 1F331 - 1FAB4||30 - 1F332 - 1F333 - 1F334 - 1F335 - 1F33E - 1F33F - 2618,FE0F||23 - 1F340 - 1F341 - 1F342 - 1F343 - 1FAB9||32 - 1FABA||32 - 1F344 - 1FABE||35 - - - - 1F347 - 1F348 - 1F349 - 1F34A - 1F34B - 1F34B,200D,1F7E9||34 - 1F34C - 1F34D - 1F96D||28 - 1F34E - 1F34F - 1F350 - 1F351 - 1F352 - 1F353 - 1FAD0||30 - 1F95D||24 - 1F345 - 1FAD2||30 - 1F965||26 - 1F951||24 - 1F346 - 1F954||24 - 1F955||24 - 1F33D - 1F336,FE0F||23 - 1FAD1||30 - 1F952||24 - 1F96C||28 - 1F966||26 - 1F9C4||29 - 1F9C5||29 - 1F95C||24 - 1FAD8||32 - 1F330 - 1FADA||33 - 1FADB||33 - 1F344,200D,1F7EB||34 - 1FADC||35 - 1F35E - 1F950||24 - 1F956||24 - 1FAD3||30 - 1F968||26 - 1F96F||28 - 1F95E||24 - 1F9C7||29 - 1F9C0||23 - 1F356 - 1F357 - 1F969||26 - 1F953||24 - 1F354 - 1F35F - 1F355 - 1F32D||23 - 1F96A||26 - 1F32E||23 - 1F32F||23 - 1FAD4||30 - 1F959||24 - 1F9C6||29 - 1F95A||24 - 1F373 - 1F958||24 - 1F372 - 1FAD5||30 - 1F963||26 - 1F957||24 - 1F37F||23 - 1F9C8||29 - 1F9C2||28 - 1F96B||26 - 1F371 - 1F358 - 1F359 - 1F35A - 1F35B - 1F35C - 1F35D - 1F360 - 1F362 - 1F363 - 1F364 - 1F365 - 1F96E||28 - 1F361 - 1F95F||26 - 1F960||26 - 1F961||26 - 1F366 - 1F367 - 1F368 - 1F369 - 1F36A - 1F382 - 1F370 - 1F9C1||28 - 1F967||26 - 1F36B - 1F36C - 1F36D - 1F36E - 1F36F - 1F37C - 1F95B||24 - 2615 - 1FAD6||30 - 1F375 - 1F376 - 1F37E||23 - 1F377 - 1F378 - 1F379 - 1F37A - 1F37B - 1F942||24 - 1F943||24 - 1FAD7||32 - 1F964||26 - 1F9CB||30 - 1F9C3||29 - 1F9C9||29 - 1F9CA||29 - 1F962||26 - 1F37D,FE0F||23 - 1F374 - 1F944||24 - 1F52A - 1FAD9||32 - 1F3FA||23 - - - - 1F30D - 1F30E - 1F30F - 1F310 - 1F5FA,FE0F||23 - 1F5FE - 1F9ED||28 - 1F3D4,FE0F||23 - 26F0,FE0F||23 - 1F30B - 1F5FB - 1F3D5,FE0F||23 - 1F3D6,FE0F||23 - 1F3DC,FE0F||23 - 1F3DD,FE0F||23 - 1F3DE,FE0F||23 - 1F3DF,FE0F||23 - 1F3DB,FE0F||23 - 1F3D7,FE0F||23 - 1F9F1||28 - 1FAA8||30 - 1FAB5||30 - 1F6D6||30 - 1F3D8,FE0F||23 - 1F3DA,FE0F||23 - 1F3E0 - 1F3E1 - 1F3E2 - 1F3E3 - 1F3E4 - 1F3E5 - 1F3E6 - 1F3E8 - 1F3E9 - 1F3EA - 1F3EB - 1F3EC - 1F3ED - 1F3EF - 1F3F0 - 1F492 - 1F5FC - 1F5FD - 26EA - 1F54C||23 - 1F6D5||29 - 1F54D||23 - 26E9,FE0F||23 - 1F54B||23 - 26F2 - 26FA - 1F301 - 1F303 - 1F3D9,FE0F||23 - 1F304 - 1F305 - 1F306 - 1F307 - 1F309 - 2668,FE0F - 1F3A0 - 1F6DD||32 - 1F3A1 - 1F3A2 - 1F488 - 1F3AA - 1F682 - 1F683 - 1F684 - 1F685 - 1F686 - 1F687 - 1F688 - 1F689 - 1F68A - 1F69D - 1F69E - 1F68B - 1F68C - 1F68D - 1F68E - 1F690 - 1F691 - 1F692 - 1F693 - 1F694 - 1F695 - 1F696 - 1F697 - 1F698 - 1F699 - 1F6FB||30 - 1F69A - 1F69B - 1F69C - 1F3CE,FE0F||23 - 1F3CD,FE0F||23 - 1F6F5||24 - 1F9BD||29 - 1F9BC||29 - 1F6FA||29 - 1F6B2 - 1F6F4||24 - 1F6F9||28 - 1F6FC||30 - 1F68F - 1F6E3,FE0F||23 - 1F6E4,FE0F||23 - 1F6E2,FE0F||23 - 26FD - 1F6DE||32 - 1F6A8 - 1F6A5 - 1F6A6 - 1F6D1||24 - 1F6A7 - 2693 - 1F6DF||32 - 26F5 - 1F6F6||24 - 1F6A4 - 1F6F3,FE0F||23 - 26F4,FE0F||23 - 1F6E5,FE0F||23 - 1F6A2 - 2708,FE0F - 1F6E9,FE0F||23 - 1F6EB||23 - 1F6EC||23 - 1FA82||29 - 1F4BA - 1F681 - 1F69F - 1F6A0 - 1F6A1 - 1F6F0,FE0F||23 - 1F680 - 1F6F8||26 - 1F6CE,FE0F||23 - 1F9F3||28 - 231B - 23F3 - 231A - 23F0 - 23F1,FE0F||23 - 23F2,FE0F||23 - 1F570,FE0F||23 - 1F55B - 1F567 - 1F550 - 1F55C - 1F551 - 1F55D - 1F552 - 1F55E - 1F553 - 1F55F - 1F554 - 1F560 - 1F555 - 1F561 - 1F556 - 1F562 - 1F557 - 1F563 - 1F558 - 1F564 - 1F559 - 1F565 - 1F55A - 1F566 - 1F311 - 1F312 - 1F313 - 1F314 - 1F315 - 1F316 - 1F317 - 1F318 - 1F319 - 1F31A - 1F31B - 1F31C - 1F321,FE0F||23 - 2600,FE0F - 1F31D - 1F31E - 1FA90||29 - 2B50 - 1F31F - 1F320 - 1F30C - 2601,FE0F - 26C5 - 26C8,FE0F||23 - 1F324,FE0F||23 - 1F325,FE0F||23 - 1F326,FE0F||23 - 1F327,FE0F||23 - 1F328,FE0F||23 - 1F329,FE0F||23 - 1F32A,FE0F||23 - 1F32B,FE0F||23 - 1F32C,FE0F||23 - 1F300 - 1F308 - 1F302 - 2602,FE0F||23 - 2614 - 26F1,FE0F||23 - 26A1 - 2744,FE0F - 2603,FE0F||23 - 26C4 - 2604,FE0F||23 - 1F525 - 1F4A7 - 1F30A - - - - 1F383 - 1F384 - 1F386 - 1F387 - 1F9E8||28 - 2728 - 1F388 - 1F389 - 1F38A - 1F38B - 1F38D - 1F38E - 1F38F - 1F390 - 1F391 - 1F9E7||28 - 1F380 - 1F381 - 1F397,FE0F||23 - 1F39F,FE0F||23 - 1F3AB - 1F396,FE0F||23 - 1F3C6 - 1F3C5||23 - 1F947||24 - 1F948||24 - 1F949||24 - 26BD - 26BE - 1F94E||28 - 1F3C0 - 1F3D0||23 - 1F3C8 - 1F3C9 - 1F3BE - 1F94F||28 - 1F3B3 - 1F3CF||23 - 1F3D1||23 - 1F3D2||23 - 1F94D||28 - 1F3D3||23 - 1F3F8||23 - 1F94A||24 - 1F94B||24 - 1F945||24 - 26F3 - 26F8,FE0F||23 - 1F3A3 - 1F93F||29 - 1F3BD - 1F3BF - 1F6F7||26 - 1F94C||26 - 1F3AF - 1FA80||29 - 1FA81||29 - 1F52B - 1F3B1 - 1F52E - 1FA84||30 - 1F3AE - 1F579,FE0F||23 - 1F3B0 - 1F3B2 - 1F9E9||28 - 1F9F8||28 - 1FA85||30 - 1FAA9||32 - 1FA86||30 - 2660,FE0F - 2665,FE0F - 2666,FE0F - 2663,FE0F - 265F,FE0F||28 - 1F0CF - 1F004 - 1F3B4 - 1F3AD - 1F5BC,FE0F||23 - 1F3A8 - 1F9F5||28 - 1FAA1||30 - 1F9F6||28 - 1FAA2||30 - - - - 1F453 - 1F576,FE0F||23 - 1F97D||28 - 1F97C||28 - 1F9BA||29 - 1F454 - 1F455 - 1F456 - 1F9E3||26 - 1F9E4||26 - 1F9E5||26 - 1F9E6||26 - 1F457 - 1F458 - 1F97B||29 - 1FA71||29 - 1FA72||29 - 1FA73||29 - 1F459 - 1F45A - 1FAAD||33 - 1F45B - 1F45C - 1F45D - 1F6CD,FE0F||23 - 1F392 - 1FA74||30 - 1F45E - 1F45F - 1F97E||28 - 1F97F||28 - 1F460 - 1F461 - 1FA70||29 - 1F462 - 1FAAE||33 - 1F451 - 1F452 - 1F3A9 - 1F393 - 1F9E2||26 - 1FA96||30 - 26D1,FE0F||23 - 1F4FF||23 - 1F484 - 1F48D - 1F48E - 1F507 - 1F508 - 1F509 - 1F50A - 1F4E2 - 1F4E3 - 1F4EF - 1F514 - 1F515 - 1F3BC - 1F3B5 - 1F3B6 - 1F399,FE0F||23 - 1F39A,FE0F||23 - 1F39B,FE0F||23 - 1F3A4 - 1F3A7 - 1F4FB - 1F3B7 - 1FA97||30 - 1F3B8 - 1F3B9 - 1F3BA - 1F3BB - 1FA95||29 - 1F941||24 - 1FA98||30 - 1FA87||33 - 1FA88||33 - 1FA89||35 - 1F4F1 - 1F4F2 - 260E,FE0F - 1F4DE - 1F4DF - 1F4E0 - 1F50B - 1FAAB||32 - 1F50C - 1F4BB - 1F5A5,FE0F||23 - 1F5A8,FE0F||23 - 2328,FE0F||23 - 1F5B1,FE0F||23 - 1F5B2,FE0F||23 - 1F4BD - 1F4BE - 1F4BF - 1F4C0 - 1F9EE||28 - 1F3A5 - 1F39E,FE0F||23 - 1F4FD,FE0F||23 - 1F3AC - 1F4FA - 1F4F7 - 1F4F8||23 - 1F4F9 - 1F4FC - 1F50D - 1F50E - 1F56F,FE0F||23 - 1F4A1 - 1F526 - 1F3EE - 1FA94||29 - 1F4D4 - 1F4D5 - 1F4D6 - 1F4D7 - 1F4D8 - 1F4D9 - 1F4DA - 1F4D3 - 1F4D2 - 1F4C3 - 1F4DC - 1F4C4 - 1F4F0 - 1F5DE,FE0F||23 - 1F4D1 - 1F516 - 1F3F7,FE0F||23 - 1F4B0 - 1FA99||30 - 1F4B4 - 1F4B5 - 1F4B6 - 1F4B7 - 1F4B8 - 1F4B3 - 1F9FE||28 - 1F4B9 - 2709,FE0F - 1F4E7 - 1F4E8 - 1F4E9 - 1F4E4 - 1F4E5 - 1F4E6 - 1F4EB - 1F4EA - 1F4EC - 1F4ED - 1F4EE - 1F5F3,FE0F||23 - 270F,FE0F - 2712,FE0F - 1F58B,FE0F||23 - 1F58A,FE0F||23 - 1F58C,FE0F||23 - 1F58D,FE0F||23 - 1F4DD - 1F4BC - 1F4C1 - 1F4C2 - 1F5C2,FE0F||23 - 1F4C5 - 1F4C6 - 1F5D2,FE0F||23 - 1F5D3,FE0F||23 - 1F4C7 - 1F4C8 - 1F4C9 - 1F4CA - 1F4CB - 1F4CC - 1F4CD - 1F4CE - 1F587,FE0F||23 - 1F4CF - 1F4D0 - 2702,FE0F - 1F5C3,FE0F||23 - 1F5C4,FE0F||23 - 1F5D1,FE0F||23 - 1F512 - 1F513 - 1F50F - 1F510 - 1F511 - 1F5DD,FE0F||23 - 1F528 - 1FA93||29 - 26CF,FE0F||23 - 2692,FE0F||23 - 1F6E0,FE0F||23 - 1F5E1,FE0F||23 - 2694,FE0F||23 - 1F4A3 - 1FA83||30 - 1F3F9||23 - 1F6E1,FE0F||23 - 1FA9A||30 - 1F527 - 1FA9B||30 - 1F529 - 2699,FE0F||23 - 1F5DC,FE0F||23 - 2696,FE0F||23 - 1F9AF||29 - 1F517 - 26D3,FE0F,200D,1F4A5||34 - 26D3,FE0F||23 - 1FA9D||30 - 1F9F0||28 - 1F9F2||28 - 1FA9C||30 - 1FA8F||35 - 2697,FE0F||23 - 1F9EA||28 - 1F9EB||28 - 1F9EC||28 - 1F52C - 1F52D - 1F4E1 - 1F489 - 1FA78||29 - 1F48A - 1FA79||29 - 1FA7C||32 - 1FA7A||29 - 1FA7B||32 - 1F6AA - 1F6D7||30 - 1FA9E||30 - 1FA9F||30 - 1F6CF,FE0F||23 - 1F6CB,FE0F||23 - 1FA91||29 - 1F6BD - 1FAA0||30 - 1F6BF - 1F6C1 - 1FAA4||30 - 1FA92||29 - 1F9F4||28 - 1F9F7||28 - 1F9F9||28 - 1F9FA||28 - 1F9FB||28 - 1FAA3||30 - 1F9FC||28 - 1FAE7||32 - 1FAA5||30 - 1F9FD||28 - 1F9EF||28 - 1F6D2||24 - 1F6AC - 26B0,FE0F||23 - 1FAA6||30 - 26B1,FE0F||23 - 1F9FF||28 - 1FAAC||32 - 1F5FF - 1FAA7||30 - 1FAAA||32 - - - - 1F3E7 - 1F6AE - 1F6B0 - 267F - 1F6B9 - 1F6BA - 1F6BB - 1F6BC - 1F6BE - 1F6C2 - 1F6C3 - 1F6C4 - 1F6C5 - 26A0,FE0F - 1F6B8 - 26D4 - 1F6AB - 1F6B3 - 1F6AD - 1F6AF - 1F6B1 - 1F6B7 - 1F4F5 - 1F51E - 2622,FE0F||23 - 2623,FE0F||23 - 2B06,FE0F - 2197,FE0F - 27A1,FE0F - 2198,FE0F - 2B07,FE0F - 2199,FE0F - 2B05,FE0F - 2196,FE0F - 2195,FE0F - 2194,FE0F - 21A9,FE0F - 21AA,FE0F - 2934,FE0F - 2935,FE0F - 1F503 - 1F504 - 1F519 - 1F51A - 1F51B - 1F51C - 1F51D - 1F6D0||23 - 269B,FE0F||23 - 1F549,FE0F||23 - 2721,FE0F||23 - 2638,FE0F||23 - 262F,FE0F||23 - 271D,FE0F||23 - 2626,FE0F||23 - 262A,FE0F||23 - 262E,FE0F||23 - 1F54E||23 - 1F52F - 1FAAF||33 - 2648 - 2649 - 264A - 264B - 264C - 264D - 264E - 264F - 2650 - 2651 - 2652 - 2653 - 26CE - 1F500 - 1F501 - 1F502 - 25B6,FE0F - 23E9 - 23ED,FE0F||23 - 23EF,FE0F||23 - 25C0,FE0F - 23EA - 23EE,FE0F||23 - 1F53C - 23EB - 1F53D - 23EC - 23F8,FE0F||23 - 23F9,FE0F||23 - 23FA,FE0F||23 - 23CF,FE0F||23 - 1F3A6 - 1F505 - 1F506 - 1F4F6 - 1F6DC||33 - 1F4F3 - 1F4F4 - 2640,FE0F||25 - 2642,FE0F||25 - 26A7,FE0F||30 - 2716,FE0F - 2795 - 2796 - 2797 - 1F7F0||32 - 267E,FE0F||28 - 203C,FE0F - 2049,FE0F - 2753 - 2754 - 2755 - 2757 - 3030,FE0F - 1F4B1 - 1F4B2 - 2695,FE0F||25 - 267B,FE0F - 269C,FE0F||23 - 1F531 - 1F4DB - 1F530 - 2B55 - 2705 - 2611,FE0F - 2714,FE0F - 274C - 274E - 27B0 - 27BF - 303D,FE0F - 2733,FE0F - 2734,FE0F - 2747,FE0F - A9,FE0F - AE,FE0F - 2122,FE0F - 1FADF||35 - 1F1E6 - 1F1E7 - 1F1E8 - 1F1E9 - 1F1EA - 1F1EB - 1F1EC - 1F1ED - 1F1EE - 1F1EF - 1F1F0 - 1F1F1 - 1F1F2 - 1F1F3 - 1F1F4 - 1F1F5 - 1F1F6 - 1F1F7 - 1F1F8 - 1F1F9 - 1F1FA - 1F1FB - 1F1FC - 1F1FD - 1F1FE - 1F1FF - 23,FE0F,20E3 - 2A,FE0F,20E3||23 - 30,FE0F,20E3 - 31,FE0F,20E3 - 32,FE0F,20E3 - 33,FE0F,20E3 - 34,FE0F,20E3 - 35,FE0F,20E3 - 36,FE0F,20E3 - 37,FE0F,20E3 - 38,FE0F,20E3 - 39,FE0F,20E3 - 1F51F - 1F520 - 1F521 - 1F522 - 1F523 - 1F524 - 1F170,FE0F - 1F18E - 1F171,FE0F - 1F191 - 1F192 - 1F193 - 2139,FE0F - 1F194 - 24C2,FE0F - 1F195 - 1F196 - 1F17E,FE0F - 1F197 - 1F17F,FE0F - 1F198 - 1F199 - 1F19A - 1F201 - 1F202,FE0F - 1F237,FE0F - 1F236 - 1F22F - 1F250 - 1F239 - 1F21A - 1F232 - 1F251 - 1F238 - 1F234 - 1F233 - 3297,FE0F - 3299,FE0F - 1F23A - 1F235 - 1F534 - 1F7E0||29 - 1F7E1||29 - 1F7E2||29 - 1F535 - 1F7E3||29 - 1F7E4||29 - 26AB - 26AA - 1F7E5||29 - 1F7E7||29 - 1F7E8||29 - 1F7E9||29 - 1F7E6||29 - 1F7EA||29 - 1F7EB||29 - 2B1B - 2B1C - 25FC,FE0F - 25FB,FE0F - 25FE - 25FD - 25AA,FE0F - 25AB,FE0F - 1F536 - 1F537 - 1F538 - 1F539 - 1F53A - 1F53B - 1F4A0 - 1F518 - 1F533 - 1F532 - - - - 1F3C1 - 1F6A9 - 1F38C - 1F3F4||23 - 1F3F3,FE0F||23 - 1F3F3,FE0F,200D,1F308||25 - 1F3F3,FE0F,200D,26A7,FE0F||30 - 1F3F4,200D,2620,FE0F||28 - 1F1E6,1F1E8||24 - 1F1E6,1F1E9 - 1F1E6,1F1EA - 1F1E6,1F1EB - 1F1E6,1F1EC - 1F1E6,1F1EE - 1F1E6,1F1F1 - 1F1E6,1F1F2 - 1F1E6,1F1F4 - 1F1E6,1F1F6||24 - 1F1E6,1F1F7 - 1F1E6,1F1F8 - 1F1E6,1F1F9 - 1F1E6,1F1FA - 1F1E6,1F1FC - 1F1E6,1F1FD - 1F1E6,1F1FF - 1F1E7,1F1E6 - 1F1E7,1F1E7 - 1F1E7,1F1E9 - 1F1E7,1F1EA - 1F1E7,1F1EB - 1F1E7,1F1EC - 1F1E7,1F1ED - 1F1E7,1F1EE - 1F1E7,1F1EF - 1F1E7,1F1F1||29 - 1F1E7,1F1F2 - 1F1E7,1F1F3 - 1F1E7,1F1F4 - 1F1E7,1F1F6||29 - 1F1E7,1F1F7 - 1F1E7,1F1F8 - 1F1E7,1F1F9 - 1F1E7,1F1FB||24 - 1F1E7,1F1FC - 1F1E7,1F1FE - 1F1E7,1F1FF - 1F1E8,1F1E6 - 1F1E8,1F1E8 - 1F1E8,1F1E9 - 1F1E8,1F1EB - 1F1E8,1F1EC - 1F1E8,1F1ED - 1F1E8,1F1EE - 1F1E8,1F1F0 - 1F1E8,1F1F1 - 1F1E8,1F1F2 - 1F1E8,1F1F3 - 1F1E8,1F1F4 - 1F1E8,1F1F5||24 - 1F1E8,1F1F6||35 - 1F1E8,1F1F7 - 1F1E8,1F1FA - 1F1E8,1F1FB - 1F1E8,1F1FC - 1F1E8,1F1FD - 1F1E8,1F1FE - 1F1E8,1F1FF - 1F1E9,1F1EA - 1F1E9,1F1EC||30 - 1F1E9,1F1EF - 1F1E9,1F1F0 - 1F1E9,1F1F2 - 1F1E9,1F1F4 - 1F1E9,1F1FF - 1F1EA,1F1E6||30 - 1F1EA,1F1E8 - 1F1EA,1F1EA - 1F1EA,1F1EC - 1F1EA,1F1ED||30 - 1F1EA,1F1F7 - 1F1EA,1F1F8 - 1F1EA,1F1F9 - 1F1EA,1F1FA - 1F1EB,1F1EE - 1F1EB,1F1EF - 1F1EB,1F1F0||30 - 1F1EB,1F1F2 - 1F1EB,1F1F4 - 1F1EB,1F1F7 - 1F1EC,1F1E6 - 1F1EC,1F1E7 - 1F1EC,1F1E9 - 1F1EC,1F1EA - 1F1EC,1F1EB||30 - 1F1EC,1F1EC - 1F1EC,1F1ED - 1F1EC,1F1EE - 1F1EC,1F1F1 - 1F1EC,1F1F2 - 1F1EC,1F1F3 - 1F1EC,1F1F5||30 - 1F1EC,1F1F6 - 1F1EC,1F1F7 - 1F1EC,1F1F8||30 - 1F1EC,1F1F9 - 1F1EC,1F1FA - 1F1EC,1F1FC - 1F1EC,1F1FE - 1F1ED,1F1F0 - 1F1ED,1F1F2||24 - 1F1ED,1F1F3 - 1F1ED,1F1F7 - 1F1ED,1F1F9 - 1F1ED,1F1FA - 1F1EE,1F1E8||24 - 1F1EE,1F1E9 - 1F1EE,1F1EA - 1F1EE,1F1F1 - 1F1EE,1F1F2 - 1F1EE,1F1F3 - 1F1EE,1F1F4 - 1F1EE,1F1F6 - 1F1EE,1F1F7 - 1F1EE,1F1F8 - 1F1EE,1F1F9 - 1F1EF,1F1EA - 1F1EF,1F1F2 - 1F1EF,1F1F4 - 1F1EF,1F1F5 - 1F1F0,1F1EA - 1F1F0,1F1EC - 1F1F0,1F1ED - 1F1F0,1F1EE - 1F1F0,1F1F2 - 1F1F0,1F1F3 - 1F1F0,1F1F5 - 1F1F0,1F1F7 - 1F1F0,1F1FC - 1F1F0,1F1FE - 1F1F0,1F1FF - 1F1F1,1F1E6 - 1F1F1,1F1E7 - 1F1F1,1F1E8 - 1F1F1,1F1EE - 1F1F1,1F1F0 - 1F1F1,1F1F7 - 1F1F1,1F1F8 - 1F1F1,1F1F9 - 1F1F1,1F1FA - 1F1F1,1F1FB - 1F1F1,1F1FE - 1F1F2,1F1E6 - 1F1F2,1F1E8 - 1F1F2,1F1E9 - 1F1F2,1F1EA - 1F1F2,1F1EB||30 - 1F1F2,1F1EC - 1F1F2,1F1ED - 1F1F2,1F1F0 - 1F1F2,1F1F1 - 1F1F2,1F1F2 - 1F1F2,1F1F3 - 1F1F2,1F1F4 - 1F1F2,1F1F5 - 1F1F2,1F1F6||29 - 1F1F2,1F1F7 - 1F1F2,1F1F8 - 1F1F2,1F1F9 - 1F1F2,1F1FA - 1F1F2,1F1FB - 1F1F2,1F1FC - 1F1F2,1F1FD - 1F1F2,1F1FE - 1F1F2,1F1FF - 1F1F3,1F1E6 - 1F1F3,1F1E8||30 - 1F1F3,1F1EA - 1F1F3,1F1EB - 1F1F3,1F1EC - 1F1F3,1F1EE - 1F1F3,1F1F1 - 1F1F3,1F1F4 - 1F1F3,1F1F5 - 1F1F3,1F1F7 - 1F1F3,1F1FA - 1F1F3,1F1FF - 1F1F4,1F1F2 - 1F1F5,1F1E6 - 1F1F5,1F1EA - 1F1F5,1F1EB - 1F1F5,1F1EC - 1F1F5,1F1ED - 1F1F5,1F1F0 - 1F1F5,1F1F1 - 1F1F5,1F1F2||30 - 1F1F5,1F1F3 - 1F1F5,1F1F7 - 1F1F5,1F1F8 - 1F1F5,1F1F9 - 1F1F5,1F1FC - 1F1F5,1F1FE - 1F1F6,1F1E6 - 1F1F7,1F1EA||29 - 1F1F7,1F1F4 - 1F1F7,1F1F8 - 1F1F7,1F1FA - 1F1F7,1F1FC - 1F1F8,1F1E6 - 1F1F8,1F1E7 - 1F1F8,1F1E8 - 1F1F8,1F1E9 - 1F1F8,1F1EA - 1F1F8,1F1EC - 1F1F8,1F1ED||24 - 1F1F8,1F1EE - 1F1F8,1F1EF||24 - 1F1F8,1F1F0 - 1F1F8,1F1F1 - 1F1F8,1F1F2 - 1F1F8,1F1F3 - 1F1F8,1F1F4 - 1F1F8,1F1F7 - 1F1F8,1F1F8 - 1F1F8,1F1F9 - 1F1F8,1F1FB - 1F1F8,1F1FD - 1F1F8,1F1FE - 1F1F8,1F1FF - 1F1F9,1F1E6||24 - 1F1F9,1F1E8 - 1F1F9,1F1E9 - 1F1F9,1F1EB||29 - 1F1F9,1F1EC - 1F1F9,1F1ED - 1F1F9,1F1EF - 1F1F9,1F1F0 - 1F1F9,1F1F1 - 1F1F9,1F1F2 - 1F1F9,1F1F3 - 1F1F9,1F1F4 - 1F1F9,1F1F7 - 1F1F9,1F1F9 - 1F1F9,1F1FB - 1F1F9,1F1FC - 1F1F9,1F1FF - 1F1FA,1F1E6 - 1F1FA,1F1EC - 1F1FA,1F1F2||24 - 1F1FA,1F1F3||26 - 1F1FA,1F1F8 - 1F1FA,1F1FE - 1F1FA,1F1FF - 1F1FB,1F1E6 - 1F1FB,1F1E8 - 1F1FB,1F1EA - 1F1FB,1F1EC - 1F1FB,1F1EE - 1F1FB,1F1F3 - 1F1FB,1F1FA - 1F1FC,1F1EB||30 - 1F1FC,1F1F8 - 1F1FD,1F1F0||29 - 1F1FE,1F1EA - 1F1FE,1F1F9||30 - 1F1FF,1F1E6 - 1F1FF,1F1F2 - 1F1FF,1F1FC - 1F3F4,E0067,E0062,E0065,E006E,E0067,E007F||26 - 1F3F4,E0067,E0062,E0073,E0063,E0074,E007F||26 - 1F3F4,E0067,E0062,E0077,E006C,E0073,E007F||26 - - - - - - 30 - 31 - - - - :-) - ;-) - :-( - :-! - :-$ - B-) - =-O - :-P - :O - :-* - :-D - :\'( - :-\\ - O:-) - :-[ - (╯° - □°) - ╯︵ - ┻━┻ - ¯\\_ - (ツ) - _/¯ - ┬─┬ - ︵ /( - .□.\\ - - - - diff --git a/app/src/main/res/values/platform-theme.xml b/app/src/main/res/values/platform-theme.xml index 432d20715..2942b101f 100644 --- a/app/src/main/res/values/platform-theme.xml +++ b/app/src/main/res/values/platform-theme.xml @@ -6,11 +6,21 @@ --> - + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 903b3cbd7..90f8972ff 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -5,13 +5,12 @@ SPDX-License-Identifier: Apache-2.0 AND GPL-3.0-only --> - HeliBoard HeliBoard Spell Checker HeliBoard Settings - HeliBoard Spell Checker Settings + HeliBoard Spell Checker Settings Vibrate on keypress @@ -38,6 +37,8 @@ Clipboard history Corrections + + Space Suggestions @@ -65,9 +66,9 @@ Emoji key - %s ms + %s ms - %s min + %s min System default @@ -76,6 +77,10 @@ Look up contact names Use names from Contacts for suggestions and corrections + + Look up app names + + Use names of installed apps for suggestions and corrections Personalized suggestions @@ -104,6 +109,10 @@ Always show suggestions Ignore other apps’ request to disable suggestions (may cause issues) + + Don’t always show suggestions for web edit fields + + Web edit fields (mostly found in browsers) are a very common cause for issues with the always show suggestions setting Block offensive words @@ -122,6 +131,8 @@ Auto-correct shortcuts When enabled shortcuts might be expanded by autocorrect + + Backspace reverts autocorrect Off @@ -188,6 +199,10 @@ Backup Restore + + Backup restored + + Format for timestamp key Multilingual typing @@ -205,10 +220,20 @@ Load library Delete library - + Autospace after punctuation - + Automatically insert space after punctuation when typing a new word + + Autospace after picking a suggestion + + Autospace before gesture typing a word + + Autospace after gesture typing a word + + No autospace when pressing shift + + Shift removes pending autospace Show more letters with diacritics in popup @@ -249,9 +274,13 @@ Select hint source Select popup key order + + Show TLD popup keys + + Replace period key popups with top level domains when typing URLs and email addresses Number row - Language + @string/subtype_locale Language (priority) Layout Symbols @@ -324,6 +353,12 @@ Keyboard font scale Emoji view font scale + + Scale emoji key size with font size + + Default emoji skin tone + + Neutral Custom text on space bar @@ -337,158 +372,45 @@ Spanish (US) + + Serbian (Latin) Hinglish Mansi Kaitag - - Serbian (Latin) - - English (UK) (%s) - - English (US) (%s) - - Spanish (US) (%s) - - Hinglish (%s) - - %s (Extended) - - Mansi (%s) + + Dagbani + + Sesotho Dargwa (Urakhi) - Urakhi (%s) - Kaitag (%s) - - Serbian (%s) + + %1$s (%2$s) + + %s (Extended) - %s (Traditional) - - %s (Akkhor) - - %s (Probhat) - - %s (Baishakhi) - - %s (Compact) - - %s (Phonetic) - - %s (Sebeolsik 390) - - %s (Sebeolsik Final) - - %s (Student) + %s (Traditional) + + %s (Akkhor) + + %s (Probhat) + + %s (Baishakhi) + + %s (Compact) + + %s (Phonetic) + + %s (Sebeolsik 390) + + %s (Sebeolsik Final) + + %s (Student) - No language (Alphabet) - - Alphabet (QWERTY) - - Alphabet (QWERTZ) - - Alphabet (AZERTY) - - Alphabet (Dvorak) - - Alphabet (Colemak) - - Alphabet (Colemak Mod-DH) - - Alphabet (Workman) - - Alphabet (Bépo) - Alphabet (PC) +language, hence "No language". --> + No language Emoji @@ -515,10 +437,8 @@ disposition rather than other common dispositions for Latin languages. --> Copy to Clipboard Cannot read file - + Copy existing layout - - Set layout name Really delete custom layout %s? @@ -555,6 +475,8 @@ disposition rather than other common dispositions for Latin languages. --> Numpad (landscape) Number row + + Number row (basic) Emoji bottom row @@ -577,6 +499,8 @@ disposition rather than other common dispositions for Latin languages. --> Selecting clipboard history entry Pressing enter or space after other keys in symbols view + + Pressing enter or space after other keys in numpad Set image for day or night mode? @@ -597,34 +521,30 @@ disposition rather than other common dispositions for Latin languages. --> Physical Alt key shows the emoji palette Default - - "Welcome to %s" + + "Welcome to %s" with Gesture Typing Get started - - Next step - - "Setting up %s" - - "Enable %s" - - "Please check \"%s\" in your Languages & input settings. This will authorize it to run on your device." - - "%s is already enabled in your Languages & input settings, so this step is done. On to the next one!" + + "Setting up %s" + + "Enable %s" + + "Please check \"%s\" in your Languages & input settings. This will authorize it to run on your device." Enable in Settings - - "Switch to %s" - - "Next, select \"%s\" as your active text-input method." + + "Switch to %s" + + "Next, select \"%s\" as your active text-input method." Switch input methods "Congratulations, you're all set!" - - Now you can type in all your favorite apps with %s. + + Now you can type in all your favorite apps with %s. Configure the keyboard @@ -633,8 +553,8 @@ disposition rather than other common dispositions for Latin languages. --> Show app icon Display application icon in the launcher - - Add-on dictionaries + + Add-on dictionaries Dictionaries @@ -668,26 +588,22 @@ New dictionary: "%s (experimental)" "Error: Selected file is not a valid dictionary file" - + "The selected file is for %1$s, but %2$s was expected. Still use it for %2$s?" "Error: script not compatible with this keyboard" - + "Still use" "Error loading dictionary file" Dictionary available - - No dictionaries available Last updated Delete - - Version %1$s - - Add + + Version %s Add to dictionary @@ -702,8 +618,6 @@ New dictionary: Optional shortcut Edit word - - You don\'t have any words in the user dictionary. To add a word, tap the Add (+) button. For all languages @@ -777,13 +691,9 @@ New dictionary: Show more colors Show all colors - - Loading will overwrite the current theme This setting exposes all colors that are used internally. The list of colors may change at any time. The default color is random, and the names will not be translated. - - Click for preview - + Select colors for text and backgrounds Keyboard background @@ -825,8 +735,8 @@ New dictionary: GNU General Public License v3.0 Close - - "Use system languages" + + "Use system languages" Tap the language to open settings diff --git a/app/src/main/res/values/themes-holo_base.xml b/app/src/main/res/values/themes-holo_base.xml index 4a8c11ced..f57f237fa 100644 --- a/app/src/main/res/values/themes-holo_base.xml +++ b/app/src/main/res/values/themes-holo_base.xml @@ -68,10 +68,6 @@ name="EmojiPalettesView.HoloBase" parent="MainKeyboardView.HoloBase" > - true - @drawable/emoji_category_tab_selected_holo_white - @drawable/emoji_category_tab_unselected_holo_dark - @color/highlight_color_holo_white @color/emoji_tab_page_indicator_background_holo @drawable/ic_emoji_recents @drawable/ic_emoji_smileys_emotion diff --git a/app/src/main/res/values/themes-lxx-base.xml b/app/src/main/res/values/themes-lxx-base.xml index 40897ca9a..745966275 100644 --- a/app/src/main/res/values/themes-lxx-base.xml +++ b/app/src/main/res/values/themes-lxx-base.xml @@ -54,8 +54,6 @@ name="EmojiPalettesView.LXX_Base" parent="MainKeyboardView.LXX_Base" > - false - @color/highlight_color_lxx_light @color/emoji_tab_page_indicator_background_lxx_base @drawable/ic_emoji_recents_lxx @drawable/ic_emoji_smileys_emotion_lxx diff --git a/app/src/main/res/values/themes-rounded-base.xml b/app/src/main/res/values/themes-rounded-base.xml index 05091c99e..a99077eac 100644 --- a/app/src/main/res/values/themes-rounded-base.xml +++ b/app/src/main/res/values/themes-rounded-base.xml @@ -61,8 +61,6 @@ name="EmojiPalettesView.Rounded_Base" parent="MainKeyboardView.Rounded_Base" > - false - @color/highlight_color_lxx_light @color/emoji_tab_page_indicator_background_lxx_base @drawable/ic_emoji_recents_rounded @drawable/ic_emoji_smileys_emotion_rounded diff --git a/app/src/main/res/xml/method.xml b/app/src/main/res/xml/method.xml index 2733268ba..eca4e9c02 100644 --- a/app/src/main/res/xml/method.xml +++ b/app/src/main/res/xml/method.xml @@ -11,10 +11,12 @@ @@ -126,412 +141,475 @@ android:supportsInlineSuggestions="true" tools:targetApi="r"> + + + + + + + + This isn't based on the final specification. + Was disabled because there is no LM yet, and this layout does not offer anything different. --> + + + - + + + + + This isn't based on the final specification. --> + This isn't based on the final specification. --> + + android:label="@string/subtype_generic_extended" + android:subtypeId="0x49dc95e4" + android:imeSubtypeLocale="uk" + android:languageTag="uk" + android:imeSubtypeMode="keyboard" + android:imeSubtypeExtraValue="KeyboardLayoutSet=MAIN:ukrainian_extended,EmojiCapable" + android:isAsciiCapable="false" + /> + + This isn't based on the final specification. --> + diff --git a/app/src/test/java/helium314/keyboard/Shadows.kt b/app/src/test/java/helium314/keyboard/Shadows.kt index 6d5295fdb..532a20f57 100644 --- a/app/src/test/java/helium314/keyboard/Shadows.kt +++ b/app/src/test/java/helium314/keyboard/Shadows.kt @@ -28,7 +28,7 @@ object ShadowLocaleManagerCompat { class ShadowInputMethodManager2 : ShadowInputMethodManager() { @Implementation override fun getInputMethodList() = listOf( - if (BuildConfig.BUILD_TYPE == "debug") + if (BuildConfig.BUILD_TYPE == "debug" || BuildConfig.BUILD_TYPE == "debugNoMinify") InputMethodInfo("helium314.keyboard.debug", "LatinIME", "HeliBoard debug", null) else InputMethodInfo("helium314.keyboard", "LatinIME", "HeliBoard", null), ) diff --git a/app/src/test/java/helium314/keyboard/SubtypeTest.kt b/app/src/test/java/helium314/keyboard/SubtypeTest.kt new file mode 100644 index 000000000..a101c07d9 --- /dev/null +++ b/app/src/test/java/helium314/keyboard/SubtypeTest.kt @@ -0,0 +1,75 @@ +package helium314.keyboard + +import helium314.keyboard.keyboard.KeyboardId +import helium314.keyboard.keyboard.KeyboardLayoutSet +import helium314.keyboard.keyboard.internal.KeyboardParams +import helium314.keyboard.keyboard.internal.keyboard_parser.POPUP_KEYS_NORMAL +import helium314.keyboard.keyboard.internal.keyboard_parser.addLocaleKeyTextsToParams +import helium314.keyboard.latin.LatinIME +import helium314.keyboard.latin.common.LocaleUtils.constructLocale +import helium314.keyboard.latin.settings.Settings +import helium314.keyboard.latin.settings.SettingsSubtype.Companion.toSettingsSubtype +import helium314.keyboard.latin.utils.LayoutType +import helium314.keyboard.latin.utils.POPUP_KEYS_LAYOUT +import helium314.keyboard.latin.utils.SubtypeSettings +import helium314.keyboard.latin.utils.SubtypeUtilsAdditional +import helium314.keyboard.latin.utils.prefs +import org.junit.runner.RunWith +import org.robolectric.Robolectric +import org.robolectric.RobolectricTestRunner +import org.robolectric.annotation.Config +import org.robolectric.shadows.ShadowLog +import kotlin.test.BeforeTest +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue + +@RunWith(RobolectricTestRunner::class) +@Config(shadows = [ + ShadowInputMethodManager2::class +]) +class SubtypeTest { + private lateinit var latinIME: LatinIME + private lateinit var params: KeyboardParams + + @BeforeTest fun setUp() { + latinIME = Robolectric.setupService(LatinIME::class.java) + ShadowLog.setupLogging() + ShadowLog.stream = System.out + params = KeyboardParams() + params.mId = KeyboardLayoutSet.getFakeKeyboardId(KeyboardId.ELEMENT_ALPHABET) + params.mPopupKeyTypes.add(POPUP_KEYS_LAYOUT) + addLocaleKeyTextsToParams(latinIME, params, POPUP_KEYS_NORMAL) + } + + @Test fun emptyAdditionalSubtypesResultsInEmptyList() { + // avoid issues where empty string results in additional subtype for undefined locale + val prefs = latinIME.prefs() + prefs.edit().putString(Settings.PREF_ADDITIONAL_SUBTYPES, "").apply() + assertTrue(SubtypeSettings.getAdditionalSubtypes().isEmpty()) + val from = SubtypeSettings.getResourceSubtypesForLocale("es".constructLocale()).first() + + // no change, and "changed" subtype actually is resource subtype -> still expect empty list + SubtypeUtilsAdditional.changeAdditionalSubtype(from.toSettingsSubtype(), from.toSettingsSubtype(), latinIME) + assertEquals(emptyList(), SubtypeSettings.getAdditionalSubtypes().map { it.toSettingsSubtype() }) + } + + @Test fun subtypeStaysEnabledOnEdits() { + val prefs = latinIME.prefs() + prefs.edit().putString(Settings.PREF_ADDITIONAL_SUBTYPES, "").apply() // clear it for convenience + + // edit enabled resource subtype + val from = SubtypeSettings.getResourceSubtypesForLocale("es".constructLocale()).first() + SubtypeSettings.addEnabledSubtype(prefs, from) + val to = from.toSettingsSubtype().withLayout(LayoutType.SYMBOLS, "symbols_arabic") + SubtypeUtilsAdditional.changeAdditionalSubtype(from.toSettingsSubtype(), to, latinIME) + assertEquals(to, SubtypeSettings.getEnabledSubtypes(false).single().toSettingsSubtype()) + + // change the new subtype to effectively be the same as original resource subtype + val toNew = to.withoutLayout(LayoutType.SYMBOLS) + assertEquals(from.toSettingsSubtype(), toNew) + SubtypeUtilsAdditional.changeAdditionalSubtype(to, toNew, latinIME) + assertEquals(emptyList(), SubtypeSettings.getAdditionalSubtypes().map { it.toSettingsSubtype() }) + assertEquals(from.toSettingsSubtype(), SubtypeSettings.getEnabledSubtypes(false).single().toSettingsSubtype()) + } +} diff --git a/app/src/test/java/helium314/keyboard/latin/InputLogicTest.kt b/app/src/test/java/helium314/keyboard/latin/InputLogicTest.kt index 4a430ab5d..afef5bbf0 100644 --- a/app/src/test/java/helium314/keyboard/latin/InputLogicTest.kt +++ b/app/src/test/java/helium314/keyboard/latin/InputLogicTest.kt @@ -23,6 +23,7 @@ import helium314.keyboard.latin.inputlogic.InputLogic import helium314.keyboard.latin.inputlogic.SpaceState import helium314.keyboard.latin.settings.Settings import helium314.keyboard.latin.utils.ScriptUtils +import helium314.keyboard.latin.utils.getTimestamp import helium314.keyboard.latin.utils.prefs import org.junit.runner.RunWith import org.mockito.Mockito @@ -151,6 +152,24 @@ class InputLogicTest { assertEquals(4, cursor) } + // see issue 1447 + @Test fun separatorAfterHangul() { + reset() + currentScript = ScriptUtils.SCRIPT_HANGUL + chainInput("ㅛ.") + assertEquals("ㅛ.", text) + } + + // see issue 1551 (debug only) + @Test fun deleteHangul() { + reset() + currentScript = ScriptUtils.SCRIPT_HANGUL + setText("ㅛㅛ ") + functionalKeyPress(KeyCode.DELETE) + functionalKeyPress(KeyCode.DELETE) + functionalKeyPress(KeyCode.DELETE) + } + @Test fun separatorUnselectsWord() { reset() setText("hello") @@ -203,13 +222,7 @@ class InputLogicTest { assertEquals("example.net", composingText) } - // fails because - // period is not handled with handleSeparatorEvent in this case - // pickSuggestion sets phantom space state - // insertAutomaticSpaceIfOptionsAndTextAllow allows the space - // todo: fix it either in some of those functions, or by finally improving URL detection in a reasonable (and performant) way @Test fun noAutospaceInUrlFieldWhenPickingSuggestion() { - if (BuildConfig.BUILD_TYPE == "runTests") return reset() setInputType(InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_URI) chainInput("exam") @@ -262,6 +275,7 @@ class InputLogicTest { reset() latinIME.prefs().edit { putBoolean(Settings.PREF_URL_DETECTION, true) } latinIME.prefs().edit { putBoolean(Settings.PREF_AUTOSPACE_AFTER_PUNCTUATION, true) } + latinIME.prefs().edit { putBoolean(Settings.PREF_SHIFT_REMOVES_AUTOSPACE, true) } input("bla") input('.') functionalKeyPress(KeyCode.SHIFT) // should remove the phantom space (in addition to normal effect) @@ -644,13 +658,20 @@ class InputLogicTest { @Test fun `revert autocorrect on delete`() { reset() + setInputType(InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_FLAG_AUTO_CORRECT) chainInput("hullo") getAutocorrectedWithSpaceAfter("hello", "hullo") + assertEquals("hello ", text) functionalKeyPress(KeyCode.DELETE) assertEquals("hullo", text) - // todo: now we want some way to disable revert on backspace, either per setting or something else - // need to avoid getting into the mLastComposedWord.canRevertCommit() part of handleBackspaceEvent + reset() + setInputType(InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_FLAG_AUTO_CORRECT) + latinIME.prefs().edit { putBoolean(Settings.PREF_BACKSPACE_REVERTS_AUTOCORRECT, false) } + chainInput("hullo") + getAutocorrectedWithSpaceAfter("hello", "hullo") + functionalKeyPress(KeyCode.DELETE) + assertEquals("hello", text) } @Test fun `remove glide typing word on delete`() { @@ -664,6 +685,13 @@ class InputLogicTest { // need to avoid getting into the mWordComposer.isBatchMode() part of handleBackspaceEvent } + @Test fun timestamp() { + reset() + chainInput("hello") + functionalKeyPress(KeyCode.TIMESTAMP) + assertEquals("hello" + getTimestamp(latinIME), text) + } + // ------- helper functions --------- // should be called before every test, so the same state is guaranteed @@ -808,7 +836,7 @@ class InputLogicTest { val info = SuggestedWordInfo(suggestion, "", 0, 0, null, 0, 0) val typedInfo = SuggestedWordInfo(typedWord, "", 0, 0, null, 0, 0) val sw = SuggestedWords(ArrayList(listOf(typedInfo, info)), null, typedInfo, false, true, false, 0, 0) - latinIME.mInputLogic.setSuggestedWords(sw) + latinIME.mInputLogic.setSuggestedWords(sw) // this prepares for autocorrect input(' ') checkConnectionConsistency() } @@ -851,17 +879,17 @@ class InputLogicTest { private fun handleMessages() { while (messages.isNotEmpty()) { latinIME.mHandler.handleMessage(messages.first()) - messages.removeFirst() + messages.removeAt(0) } while (delayedMessages.isNotEmpty()) { val msg = delayedMessages.first() if (msg.what != 2) // MSG_UPDATE_SUGGESTION_STRIP, we want to ignore it because it's irrelevant and has a 500 ms timeout latinIME.mHandler.handleMessage(delayedMessages.first()) - delayedMessages.removeFirst() + delayedMessages.removeAt(0) // delayed messages may post further messages, handle before next delayed message while (messages.isNotEmpty()) { latinIME.mHandler.handleMessage(messages.first()) - messages.removeFirst() + messages.removeAt(0) } } assertEquals(0, messages.size) diff --git a/app/src/test/java/helium314/keyboard/latin/StringUtilsTest.kt b/app/src/test/java/helium314/keyboard/latin/StringUtilsTest.kt index e2bf6adbf..c7339d047 100644 --- a/app/src/test/java/helium314/keyboard/latin/StringUtilsTest.kt +++ b/app/src/test/java/helium314/keyboard/latin/StringUtilsTest.kt @@ -1,12 +1,23 @@ // SPDX-License-Identifier: GPL-3.0-only package helium314.keyboard.latin +import androidx.test.core.app.ApplicationProvider +import helium314.keyboard.ShadowInputMethodManager2 import helium314.keyboard.latin.common.StringUtils import helium314.keyboard.latin.common.getFullEmojiAtEnd +import helium314.keyboard.latin.common.nonWordCodePointAndNoSpaceBeforeCursor +import helium314.keyboard.latin.settings.SpacingAndPunctuations +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import org.robolectric.annotation.Config import kotlin.test.Test import kotlin.test.assertEquals // todo: actually this test could/should be significantly expanded... +@RunWith(RobolectricTestRunner::class) +@Config(shadows = [ + ShadowInputMethodManager2::class, +]) class StringUtilsTest { @Test fun `not inside double quotes without quotes`() { assert(!StringUtils.isInsideDoubleQuoteOrAfterDigit("hello yes")) @@ -41,6 +52,14 @@ class StringUtilsTest { assert(StringUtils.isInsideDoubleQuoteOrAfterDigit("hello \"yes\", \"h")) } + @Test fun `non-word codepoints and no space`() { + val sp = SpacingAndPunctuations(ApplicationProvider.getApplicationContext().resources, false) + assert(!nonWordCodePointAndNoSpaceBeforeCursor("this is", sp)) + assert(!nonWordCodePointAndNoSpaceBeforeCursor("this ", sp)) + assert(!nonWordCodePointAndNoSpaceBeforeCursor("th.is ", sp)) + assert(nonWordCodePointAndNoSpaceBeforeCursor("th.is", sp)) + } + @Test fun detectEmojisAtEnd() { assertEquals("", getFullEmojiAtEnd("\uD83C\uDF83 ")) assertEquals("", getFullEmojiAtEnd("a")) diff --git a/build.gradle.kts b/build.gradle.kts index b4ff5ee4e..f1a3cec26 100755 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,13 +1,13 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - val kotlinVersion = "2.1.10" + val kotlinVersion = "2.1.21" repositories { mavenCentral() google() } dependencies { - classpath("com.android.tools.build:gradle:8.7.3") + classpath("com.android.tools.build:gradle:8.9.2") classpath(kotlin("gradle-plugin", version = kotlinVersion)) // NOTE: Do not place your application dependencies here; they belong diff --git a/fastlane/metadata/android/ar/changelogs/3004.txt b/fastlane/metadata/android/ar/changelogs/3004.txt new file mode 100644 index 000000000..cb1eb5fde --- /dev/null +++ b/fastlane/metadata/android/ar/changelogs/3004.txt @@ -0,0 +1,11 @@ +* إضافة تخطيطات: Hija'i العربية، العبرية 1452-2، الهندية الصوتية، دارغوا (أوراخي)، بايشاخي، الكرديش +* تحديث بعض التخطيطات +* الدعم الجمع بين اللهجات +* مفتاح شريط أدوات لوحة المفاتيح +* إضافة منبثقات .com +* السماح لضبط الخط المخصص +* إضافة إعداد مقياس الخط +* تحسين تبديل اللغة التلقائي +* إعدادات الإصلاح +* أضف إعدادات لمزيد من ضبط حشوة لوحة المفاتيح، والمساحة التلقائية، والتصحيح التلقائي، و صف الأرقام +* المزيد من الميزات والإصلاحات diff --git a/fastlane/metadata/android/ar/changelogs/3005.txt b/fastlane/metadata/android/ar/changelogs/3005.txt new file mode 100644 index 000000000..cb1eb5fde --- /dev/null +++ b/fastlane/metadata/android/ar/changelogs/3005.txt @@ -0,0 +1,11 @@ +* إضافة تخطيطات: Hija'i العربية، العبرية 1452-2، الهندية الصوتية، دارغوا (أوراخي)، بايشاخي، الكرديش +* تحديث بعض التخطيطات +* الدعم الجمع بين اللهجات +* مفتاح شريط أدوات لوحة المفاتيح +* إضافة منبثقات .com +* السماح لضبط الخط المخصص +* إضافة إعداد مقياس الخط +* تحسين تبديل اللغة التلقائي +* إعدادات الإصلاح +* أضف إعدادات لمزيد من ضبط حشوة لوحة المفاتيح، والمساحة التلقائية، والتصحيح التلقائي، و صف الأرقام +* المزيد من الميزات والإصلاحات diff --git a/fastlane/metadata/android/ar/changelogs/3006.txt b/fastlane/metadata/android/ar/changelogs/3006.txt new file mode 100644 index 000000000..cb1eb5fde --- /dev/null +++ b/fastlane/metadata/android/ar/changelogs/3006.txt @@ -0,0 +1,11 @@ +* إضافة تخطيطات: Hija'i العربية، العبرية 1452-2، الهندية الصوتية، دارغوا (أوراخي)، بايشاخي، الكرديش +* تحديث بعض التخطيطات +* الدعم الجمع بين اللهجات +* مفتاح شريط أدوات لوحة المفاتيح +* إضافة منبثقات .com +* السماح لضبط الخط المخصص +* إضافة إعداد مقياس الخط +* تحسين تبديل اللغة التلقائي +* إعدادات الإصلاح +* أضف إعدادات لمزيد من ضبط حشوة لوحة المفاتيح، والمساحة التلقائية، والتصحيح التلقائي، و صف الأرقام +* المزيد من الميزات والإصلاحات diff --git a/fastlane/metadata/android/ar/changelogs/3007.txt b/fastlane/metadata/android/ar/changelogs/3007.txt new file mode 100644 index 000000000..cb1eb5fde --- /dev/null +++ b/fastlane/metadata/android/ar/changelogs/3007.txt @@ -0,0 +1,11 @@ +* إضافة تخطيطات: Hija'i العربية، العبرية 1452-2، الهندية الصوتية، دارغوا (أوراخي)، بايشاخي، الكرديش +* تحديث بعض التخطيطات +* الدعم الجمع بين اللهجات +* مفتاح شريط أدوات لوحة المفاتيح +* إضافة منبثقات .com +* السماح لضبط الخط المخصص +* إضافة إعداد مقياس الخط +* تحسين تبديل اللغة التلقائي +* إعدادات الإصلاح +* أضف إعدادات لمزيد من ضبط حشوة لوحة المفاتيح، والمساحة التلقائية، والتصحيح التلقائي، و صف الأرقام +* المزيد من الميزات والإصلاحات diff --git a/fastlane/metadata/android/ar/changelogs/3008.txt b/fastlane/metadata/android/ar/changelogs/3008.txt new file mode 100644 index 000000000..cb1eb5fde --- /dev/null +++ b/fastlane/metadata/android/ar/changelogs/3008.txt @@ -0,0 +1,11 @@ +* إضافة تخطيطات: Hija'i العربية، العبرية 1452-2، الهندية الصوتية، دارغوا (أوراخي)، بايشاخي، الكرديش +* تحديث بعض التخطيطات +* الدعم الجمع بين اللهجات +* مفتاح شريط أدوات لوحة المفاتيح +* إضافة منبثقات .com +* السماح لضبط الخط المخصص +* إضافة إعداد مقياس الخط +* تحسين تبديل اللغة التلقائي +* إعدادات الإصلاح +* أضف إعدادات لمزيد من ضبط حشوة لوحة المفاتيح، والمساحة التلقائية، والتصحيح التلقائي، و صف الأرقام +* المزيد من الميزات والإصلاحات diff --git a/fastlane/metadata/android/ar/full_description.txt b/fastlane/metadata/android/ar/full_description.txt index dd46f57e0..27b361ad9 100644 --- a/fastlane/metadata/android/ar/full_description.txt +++ b/fastlane/metadata/android/ar/full_description.txt @@ -5,7 +5,7 @@ HeliBoard هو عبارة عن لوحة مفاتيح مفتوحة المصدر

    • أضف قواميس للاقتراحات والتدقيق الإملائي
      • -
      • قم ببناء قاموس خاص بك، أو احصل عليه هنا، أو في القسم التجريبي (قد تختلف الجودة)
      • +
      • قم ببناء قاموس خاص بك، أو احصل عليه هنا، أو في القسم التجريبي (قد تختلف الجودة)
      • يمكن استخدام قواميس إضافية للرموز التعبيرية أو الرموز العلمية لتقديم اقتراحات (على غرار "البحث عن الرموز التعبيرية")
      • لاحظ أنه بالنسبة للتخطيطات الكورية، تعمل الاقتراحات فقط باستخدام هذا القاموس، والأدوات الموجودة في مستودع القاموس غير قادرين على إنشاء قواميس صالحة للعمل
      diff --git a/fastlane/metadata/android/bg/full_description.txt b/fastlane/metadata/android/bg/full_description.txt new file mode 100644 index 000000000..0670c31dd --- /dev/null +++ b/fastlane/metadata/android/bg/full_description.txt @@ -0,0 +1,30 @@ +HeliBoard е клавиатура с отворен код, базирана на AOSP / OpenBoard, която е съобразена с поверителността.. +Не използва разрешение за интернет и по този начин е 100% офлайн. + +Възможности: +
        +
      • Добавяне на речници за предложения и проверка на правописа
      • +
          +
        • създайте си сами или ги вземете тук или в секцията експериментални (качеството може да варира)
        • +
        • допълнителни речници за емотикони или научни символи могат да се използват за предоставяне на предложения (подобно на "търсене на емотикони")
        • +
        • имайте предвид, че за корейските клавиатурни подредби предложенията работят само с този речник – инструментите в хранилището с речници не могат да създават работещи речници
        • +
        +
      • Персонализиране на темите на клавиатурата (стил, цветове и фонова снимка)
      • +
          +
        • може да следва дневната/нощната настройка на системата при Android 10+ (и на някои версии на Android 9)
        • +
        • може да следва динамичните цветове за Android 12+
        • +
        +
      • Персонализиране на клавиатурните подредби (достъпно само при изключена опция използване на системните езици)
      • +
      • Персонализиране на специални подредби, като символни, цифрови или функционални клавиши
      • +
      • Многоезично въвеждане
      • +
      • Плъзгащо се въвеждане (само със затворен код библиотека ☹️)
      • +
          +
        • библиотеката не е включена в приложението, тъй като няма налична съвместима библиотека с отворен код
        • +
        • може да бъде извлечена от пакетите GApps ("swypelibs") или изтеглена оттук (кликнете върху файла и след това „raw“ или малкия бутон за изтегляне)
        • +
        +
      • История на клипборда
      • +
      • Режим с една ръка
      • +
      • Разделена клавиатура (достъпна само при достатъчно голям екран)
      • +
      • Цифрова панел
      • +
      • Архивиране и възстановяване на настройките и научените думи / данни от историята
      • +
      diff --git a/fastlane/metadata/android/bn/full_description.txt b/fastlane/metadata/android/bn/full_description.txt index cd1f98e23..4912bc372 100644 --- a/fastlane/metadata/android/bn/full_description.txt +++ b/fastlane/metadata/android/bn/full_description.txt @@ -1,4 +1,4 @@ -হেলিবোর্ড গোপনীয়তা-সচেতন ওপেন সোর্স কিবোর্ড যার উৎস অ্যান্ড্রয়েড ওপেন সোর্স প্রজেক্ট এবং ওপেনবোর্ড। বাংলা (বাংলাদেশ) ভাষার জন্য এতে ইউনিজয় লেআউট যুক্ত আছে। +হেলিবোর্ড গোপনীয়তা-সচেতন ওপেন সোর্স কিবোর্ড যার উৎস অ্যান্ড্রয়েড ওপেন সোর্স প্রজেক্ট এবং ওপেনবোর্ড। বাংলা ভাষার জন্য এতে ইউনিজয়, প্রভাত, অক্ষর, ইনস্ক্রিপ্ট, বৈশাখী লেআউট যুক্ত আছে। এটি ইন্টারনেটের অনুমতি ব্যবহার করে না, তাই ১০০% অফলাইন। সুবিধা: diff --git a/fastlane/metadata/android/ca/changelogs/3004.txt b/fastlane/metadata/android/ca/changelogs/3004.txt new file mode 100644 index 000000000..4f0c8df16 --- /dev/null +++ b/fastlane/metadata/android/ca/changelogs/3004.txt @@ -0,0 +1,11 @@ +* Afeg. dissenys: àrab Hija'i, hebreu 1452-2, fonètica hindi, Dargwa (Urakhi), Baishakhi, kurd +* Actu. dissenys +* Suport per combinar accents +* Tecla dividida de la barra d'eines del teclat +* Afeg. finestres emergents .com +* Permet configurar lletra personalitzada +* Afeg. la configuració d'escala de lletra +* Millorar el canvi automàtic d'idioma +* Revisada configuració +* Afeg. paràmetres per ajustar més el farciment del teclat, l'espai automàtic, la correcció automàtica, la fila de nombres +* Més… diff --git a/fastlane/metadata/android/ca/changelogs/3005.txt b/fastlane/metadata/android/ca/changelogs/3005.txt new file mode 100644 index 000000000..4f0c8df16 --- /dev/null +++ b/fastlane/metadata/android/ca/changelogs/3005.txt @@ -0,0 +1,11 @@ +* Afeg. dissenys: àrab Hija'i, hebreu 1452-2, fonètica hindi, Dargwa (Urakhi), Baishakhi, kurd +* Actu. dissenys +* Suport per combinar accents +* Tecla dividida de la barra d'eines del teclat +* Afeg. finestres emergents .com +* Permet configurar lletra personalitzada +* Afeg. la configuració d'escala de lletra +* Millorar el canvi automàtic d'idioma +* Revisada configuració +* Afeg. paràmetres per ajustar més el farciment del teclat, l'espai automàtic, la correcció automàtica, la fila de nombres +* Més… diff --git a/fastlane/metadata/android/ca/changelogs/3006.txt b/fastlane/metadata/android/ca/changelogs/3006.txt new file mode 100644 index 000000000..4f0c8df16 --- /dev/null +++ b/fastlane/metadata/android/ca/changelogs/3006.txt @@ -0,0 +1,11 @@ +* Afeg. dissenys: àrab Hija'i, hebreu 1452-2, fonètica hindi, Dargwa (Urakhi), Baishakhi, kurd +* Actu. dissenys +* Suport per combinar accents +* Tecla dividida de la barra d'eines del teclat +* Afeg. finestres emergents .com +* Permet configurar lletra personalitzada +* Afeg. la configuració d'escala de lletra +* Millorar el canvi automàtic d'idioma +* Revisada configuració +* Afeg. paràmetres per ajustar més el farciment del teclat, l'espai automàtic, la correcció automàtica, la fila de nombres +* Més… diff --git a/fastlane/metadata/android/ca/changelogs/3007.txt b/fastlane/metadata/android/ca/changelogs/3007.txt new file mode 100644 index 000000000..4f0c8df16 --- /dev/null +++ b/fastlane/metadata/android/ca/changelogs/3007.txt @@ -0,0 +1,11 @@ +* Afeg. dissenys: àrab Hija'i, hebreu 1452-2, fonètica hindi, Dargwa (Urakhi), Baishakhi, kurd +* Actu. dissenys +* Suport per combinar accents +* Tecla dividida de la barra d'eines del teclat +* Afeg. finestres emergents .com +* Permet configurar lletra personalitzada +* Afeg. la configuració d'escala de lletra +* Millorar el canvi automàtic d'idioma +* Revisada configuració +* Afeg. paràmetres per ajustar més el farciment del teclat, l'espai automàtic, la correcció automàtica, la fila de nombres +* Més… diff --git a/fastlane/metadata/android/ca/changelogs/3008.txt b/fastlane/metadata/android/ca/changelogs/3008.txt new file mode 100644 index 000000000..4f0c8df16 --- /dev/null +++ b/fastlane/metadata/android/ca/changelogs/3008.txt @@ -0,0 +1,11 @@ +* Afeg. dissenys: àrab Hija'i, hebreu 1452-2, fonètica hindi, Dargwa (Urakhi), Baishakhi, kurd +* Actu. dissenys +* Suport per combinar accents +* Tecla dividida de la barra d'eines del teclat +* Afeg. finestres emergents .com +* Permet configurar lletra personalitzada +* Afeg. la configuració d'escala de lletra +* Millorar el canvi automàtic d'idioma +* Revisada configuració +* Afeg. paràmetres per ajustar més el farciment del teclat, l'espai automàtic, la correcció automàtica, la fila de nombres +* Més… diff --git a/fastlane/metadata/android/ca/changelogs/3100.txt b/fastlane/metadata/android/ca/changelogs/3100.txt new file mode 100644 index 000000000..c10c63c18 --- /dev/null +++ b/fastlane/metadata/android/ca/changelogs/3100.txt @@ -0,0 +1,10 @@ +* opcional suggerir noms de les apps instal·lades +* lliscar per canviar les categs. d'emojis +* mostrar toast en restaurar la còpia de seg. +* botó i icona de la barra d'eines més grans +* fer la coma accessible a les finestres emergents de TLD +* afegir config. per a tema predet. dels emojis +* afegir codis de tecla per a les tecles alt i ctrl esq. i dreta +* afegir etiqueta «timestamp» per fer eixa tecla accessible +* etiquetes de tecla especials per a finestres emergents en dissenys senzills +* etc diff --git a/fastlane/metadata/android/ca/changelogs/3101.txt b/fastlane/metadata/android/ca/changelogs/3101.txt new file mode 100644 index 000000000..2219eeda7 --- /dev/null +++ b/fastlane/metadata/android/ca/changelogs/3101.txt @@ -0,0 +1,9 @@ +* opcional suggerir noms de les apps instal·lades +* lliscar per canviar les categs. d'emojis +* mostrar toast en restaurar la còpia de seg. +* fer la coma accessible a les finestres emergents de TLD +* afegir config. per a tema predet. dels emojis +* afegir codis de tecla per a les tecles alt i ctrl esq. i dreta +* afegir etiqueta «timestamp» per fer eixa tecla accessible +* etiquetes de tecla especials per a finestres emergents en dissenys senzills +* etc diff --git a/fastlane/metadata/android/cs-CZ/changelogs/1001.txt b/fastlane/metadata/android/cs-CZ/changelogs/1001.txt index 77ee5b7e7..5d370b14a 100644 --- a/fastlane/metadata/android/cs-CZ/changelogs/1001.txt +++ b/fastlane/metadata/android/cs-CZ/changelogs/1001.txt @@ -1,20 +1,7 @@ -* nová ikona od @FabianOvrWrt s přispěním @the-eclectic-dyslexic (#517, #592) -* více přizpůsobitelný trackpad s mezerníkem a přepínačem jazyků od @arcarum (#486) -* přidání % do rozložení symbolů pro posun (#568, #428) -* zlepšení chování, když je klávesa přepínače jazyka nastavena na přepínání jazyka i klávesnice -* při přidávání slovníku zobrazit odkazy na existující slovníky -* přidat rozložení Kaitag od @alkaitagi (#519) -* přidat rozložení Probhat od @fahimscirex (#489) -* volitelné obrácení pořadí panelu nástrojů pro jazyky RTL od @codokie (#557, #574) -* umožnit přizpůsobení speciálních rozvržení (numpad, telefon, ...) -* stále experimentální, protože základní rozvržení se mohou změnit -* aktualizován spellchecker.xml tak, aby zahrnoval lokality, kde jsou k dispozici slovníky, ale nejsou součástí aplikace -* aktualizace překladů (děkujeme všem překladatelům!) -* aktualizace ndk podle @Syphyr (#560) -* aktualizace kódu automatického doplňování inline od @arcarum (#595) -* oprava problému s dialogovým oknem s klíčem na panelu nástrojů (#505) -* oprava problému s tureckým rozložením (#508) -* oprava špatných stavů přepínačů při otáčení na obrazovce přizpůsobení barev (#563) -* oprava problému s nenačítáním posledních emotikonů (#527) -* oprava problému s nezobrazováním čísel v některých polích (#585) -* některé drobné opravy +* new icon by @FabianOvrWrt with contributions from @the-eclectic-dyslexic (#517, #592) +* more customizable space bar trackpad and language switch by @arcarum (#486) +* add % to shift symbols layout (#568, #428) +* improve behavior when language switch key is set to switch both language and keyboard +* show links to existing dictionaries when adding a dictionary +* add Kaitag layout by @alkaitagi (#519) +* add Probhat layout by @fahimscirex (#489) diff --git a/fastlane/metadata/android/cs-CZ/changelogs/1003.txt b/fastlane/metadata/android/cs-CZ/changelogs/1003.txt index 29569aee4..b6ad64140 100644 --- a/fastlane/metadata/android/cs-CZ/changelogs/1003.txt +++ b/fastlane/metadata/android/cs-CZ/changelogs/1003.txt @@ -1,9 +1,9 @@ -* změna ikon pro automatickou opravu a výběr všech kláves na panelu nástrojů od @codokie (#524, #651) -* přidání čuvašského rozložení od @tenextractor (#677) -* přidání klávesy pro řezání na panelu nástrojů od @codokie (#678) -* aktualizovat rozložení Probhat od @fahimscirex (#628) -* zobrazit ikony panelu nástrojů v dialogovém okně klíče panelu nástrojů -* přidat tlačítko zavřít v historii schránky od @codokie (#403, #649) -* přidat ruské (studentské) rozložení od @Zolax9 (#640) -* volitelný numerický blok při dlouhém stisku klávesy se symboly (#588) -* drobné opravy a vylepšení, včetně #632, #637, #638 od @RHJihan +* change icons for autocorrect and select all toolbar keys by @codokie (#524, #651) +* add Chuvash layout by @tenextractor (#677) +* add cut toolbar key by @codokie (#678) +* update Probhat layout by @fahimscirex (#628) +* show toolbar icons in toolbar key dialog +* add close button in clipboard history by @codokie (#403, #649) +* add Russian (Student) layout by @Zolax9 (#640) +* make numpad on symbols key long press optional (#588) +* minor fixes and improvements, including #632, #637, #638 by @RHJihan diff --git a/fastlane/metadata/android/cs-CZ/changelogs/2000.txt b/fastlane/metadata/android/cs-CZ/changelogs/2000.txt new file mode 100644 index 000000000..bd1ce4e3b --- /dev/null +++ b/fastlane/metadata/android/cs-CZ/changelogs/2000.txt @@ -0,0 +1,10 @@ +* add basic support for modifier keys +* add long press functions to more toolbar keys +* and more clipboard history toolbar keys +* make clipboard history toolbar customizable +* allow customizing all colors +* add setting to always show word to be enterd as middle suggestion +* add caps lock indicator +* add Piedmontese, Eastern Mari, Mansi, extended layouts for Kannada and Hungarian +* fix cut off text in key preview popup on some devices +* further fixes and improvements, see release notes diff --git a/fastlane/metadata/android/cs-CZ/changelogs/2001.txt b/fastlane/metadata/android/cs-CZ/changelogs/2001.txt new file mode 100644 index 000000000..65c72100a --- /dev/null +++ b/fastlane/metadata/android/cs-CZ/changelogs/2001.txt @@ -0,0 +1,11 @@ +* allow customizing functional key layouts +* slightly adjust symbols and more symbols layouts +* add options to auto-show/hide toolbar +* add toast notification when copying text +* separate language switch key behavior from enablement +* add comma key popups for number and phone layouts +* make long-press pinning in toolbar optional +* move toolbar settings to a separate section +* add tab key +* understand ctrl, toolbar and other key labels in layouts +* minor fixes and improvements diff --git a/fastlane/metadata/android/cs-CZ/changelogs/2002.txt b/fastlane/metadata/android/cs-CZ/changelogs/2002.txt new file mode 100644 index 000000000..751dfe142 --- /dev/null +++ b/fastlane/metadata/android/cs-CZ/changelogs/2002.txt @@ -0,0 +1,4 @@ +* add emoji toolbar key, by @codokie (#845, #837) +* improvements regarding duplicated letters (#225 and maybe others) +* avoid positioning cursor inside emojis (#859) +* minor fixes for recently added features diff --git a/fastlane/metadata/android/cs-CZ/changelogs/2003.txt b/fastlane/metadata/android/cs-CZ/changelogs/2003.txt new file mode 100644 index 000000000..9bf1f6ba0 --- /dev/null +++ b/fastlane/metadata/android/cs-CZ/changelogs/2003.txt @@ -0,0 +1,11 @@ +* customizable functional key layout +* slightly adjust symbols and more symbols layouts +* basic support for alt, ctrl, fn, meta keys +* extend toolbar (long-press functionality, optional long-press pinning, auto-show/hide, better clipboard toolbar, ...) +* add tab key +* add caps lock indicator +* add layouts for some languages +* add toolbar keys as keyboard keys +* allow customizing all colors +* toast notification when copying text +* bug fixes and further improvements, see full release notes diff --git a/fastlane/metadata/android/cs-CZ/changelogs/2100.txt b/fastlane/metadata/android/cs-CZ/changelogs/2100.txt new file mode 100644 index 000000000..1bcb32256 --- /dev/null +++ b/fastlane/metadata/android/cs-CZ/changelogs/2100.txt @@ -0,0 +1,8 @@ +* fix broken functional key layout for tablets +* only show language switch key when there is something to switch to +* make default colors for "all colors" setting random instead of gray +* allow customizing start lag for gestures during typing, by @devycarol +* allow customizing currency keys +* reduce long-press time for shift -> caps lock, by @devycarol +* extend superscript popups in number row and symbols layout, by @b02860de585071a2 +* minor fixes and improvements diff --git a/fastlane/metadata/android/cs-CZ/changelogs/2200.txt b/fastlane/metadata/android/cs-CZ/changelogs/2200.txt new file mode 100644 index 000000000..133274e98 --- /dev/null +++ b/fastlane/metadata/android/cs-CZ/changelogs/2200.txt @@ -0,0 +1,11 @@ +* add ability for saving / exporting custom themes +* make arrow keys on keyboard repeatable +* more cursor toolbar keys (page up/down(/start/end, word left/right) +* add paste key +* improve key swipe behavior +* add space swipe setting to toggle numpad +* add clipboard suggestion for recently copied text +* de-select text on pressing select keys again +* tune some colors in settings for Android 12+ +* adjust language dependent popup keys +* minor fixes and improvements diff --git a/fastlane/metadata/android/cs-CZ/changelogs/2201.txt b/fastlane/metadata/android/cs-CZ/changelogs/2201.txt new file mode 100644 index 000000000..7c8756ed5 --- /dev/null +++ b/fastlane/metadata/android/cs-CZ/changelogs/2201.txt @@ -0,0 +1,2 @@ +* add visual options for gesture typing, by @devycarol (#944) +* update some icons, by @BlackyHawky (#977) diff --git a/fastlane/metadata/android/cs-CZ/changelogs/2300.txt b/fastlane/metadata/android/cs-CZ/changelogs/2300.txt new file mode 100644 index 000000000..71c590ce2 --- /dev/null +++ b/fastlane/metadata/android/cs-CZ/changelogs/2300.txt @@ -0,0 +1,9 @@ +* Allow customizing number row, toolbar codes, icons, spacebar text, bottom row for emoji and clipboard views +* Decouple icon style from keyboard style +* Disable remove redundant popups by default (and add a small fix) +* Less aggressive addition of words to personal dictionary +* No vibration in do not disturb mode +* Improve performance when copying large texta +* Fix partially broken punctuation popups +* Fix some of the issues where text is duplicated +* Minor things and more bug fixes diff --git a/fastlane/metadata/android/cs-CZ/changelogs/2301.txt b/fastlane/metadata/android/cs-CZ/changelogs/2301.txt new file mode 100644 index 000000000..71c590ce2 --- /dev/null +++ b/fastlane/metadata/android/cs-CZ/changelogs/2301.txt @@ -0,0 +1,9 @@ +* Allow customizing number row, toolbar codes, icons, spacebar text, bottom row for emoji and clipboard views +* Decouple icon style from keyboard style +* Disable remove redundant popups by default (and add a small fix) +* Less aggressive addition of words to personal dictionary +* No vibration in do not disturb mode +* Improve performance when copying large texta +* Fix partially broken punctuation popups +* Fix some of the issues where text is duplicated +* Minor things and more bug fixes diff --git a/fastlane/metadata/android/cs-CZ/changelogs/3004.txt b/fastlane/metadata/android/cs-CZ/changelogs/3004.txt new file mode 100644 index 000000000..7b5a3f128 --- /dev/null +++ b/fastlane/metadata/android/cs-CZ/changelogs/3004.txt @@ -0,0 +1,11 @@ +* přidána rozvržení: arabština hidžá'í, hebrejština 1452-2, fonetické hindu, dargwa (urakhi), baishakhi, kurdština +* aktualizace některých rozvržení +* podpora kombinování přízvuků +* klávesa pro rozdělení klávesnice +* přidána nabídka .com +* možnost nastavení vlastního písma +* přidáno nastavení měřítka písma +* zlepšeno automatické přepínání jazyků +* přepracována nastavení +* přidána nastavení pro lepší nastavení odsazení, automatické mezery, automatické opravy, číselné řady +* další funkce a opravy diff --git a/fastlane/metadata/android/cs-CZ/changelogs/3005.txt b/fastlane/metadata/android/cs-CZ/changelogs/3005.txt new file mode 100644 index 000000000..7b5a3f128 --- /dev/null +++ b/fastlane/metadata/android/cs-CZ/changelogs/3005.txt @@ -0,0 +1,11 @@ +* přidána rozvržení: arabština hidžá'í, hebrejština 1452-2, fonetické hindu, dargwa (urakhi), baishakhi, kurdština +* aktualizace některých rozvržení +* podpora kombinování přízvuků +* klávesa pro rozdělení klávesnice +* přidána nabídka .com +* možnost nastavení vlastního písma +* přidáno nastavení měřítka písma +* zlepšeno automatické přepínání jazyků +* přepracována nastavení +* přidána nastavení pro lepší nastavení odsazení, automatické mezery, automatické opravy, číselné řady +* další funkce a opravy diff --git a/fastlane/metadata/android/cs-CZ/changelogs/3006.txt b/fastlane/metadata/android/cs-CZ/changelogs/3006.txt new file mode 100644 index 000000000..7b5a3f128 --- /dev/null +++ b/fastlane/metadata/android/cs-CZ/changelogs/3006.txt @@ -0,0 +1,11 @@ +* přidána rozvržení: arabština hidžá'í, hebrejština 1452-2, fonetické hindu, dargwa (urakhi), baishakhi, kurdština +* aktualizace některých rozvržení +* podpora kombinování přízvuků +* klávesa pro rozdělení klávesnice +* přidána nabídka .com +* možnost nastavení vlastního písma +* přidáno nastavení měřítka písma +* zlepšeno automatické přepínání jazyků +* přepracována nastavení +* přidána nastavení pro lepší nastavení odsazení, automatické mezery, automatické opravy, číselné řady +* další funkce a opravy diff --git a/fastlane/metadata/android/cs-CZ/changelogs/3007.txt b/fastlane/metadata/android/cs-CZ/changelogs/3007.txt new file mode 100644 index 000000000..7b5a3f128 --- /dev/null +++ b/fastlane/metadata/android/cs-CZ/changelogs/3007.txt @@ -0,0 +1,11 @@ +* přidána rozvržení: arabština hidžá'í, hebrejština 1452-2, fonetické hindu, dargwa (urakhi), baishakhi, kurdština +* aktualizace některých rozvržení +* podpora kombinování přízvuků +* klávesa pro rozdělení klávesnice +* přidána nabídka .com +* možnost nastavení vlastního písma +* přidáno nastavení měřítka písma +* zlepšeno automatické přepínání jazyků +* přepracována nastavení +* přidána nastavení pro lepší nastavení odsazení, automatické mezery, automatické opravy, číselné řady +* další funkce a opravy diff --git a/fastlane/metadata/android/cs-CZ/changelogs/3008.txt b/fastlane/metadata/android/cs-CZ/changelogs/3008.txt new file mode 100644 index 000000000..7b5a3f128 --- /dev/null +++ b/fastlane/metadata/android/cs-CZ/changelogs/3008.txt @@ -0,0 +1,11 @@ +* přidána rozvržení: arabština hidžá'í, hebrejština 1452-2, fonetické hindu, dargwa (urakhi), baishakhi, kurdština +* aktualizace některých rozvržení +* podpora kombinování přízvuků +* klávesa pro rozdělení klávesnice +* přidána nabídka .com +* možnost nastavení vlastního písma +* přidáno nastavení měřítka písma +* zlepšeno automatické přepínání jazyků +* přepracována nastavení +* přidána nastavení pro lepší nastavení odsazení, automatické mezery, automatické opravy, číselné řady +* další funkce a opravy diff --git a/fastlane/metadata/android/cs-CZ/changelogs/3100.txt b/fastlane/metadata/android/cs-CZ/changelogs/3100.txt new file mode 100644 index 000000000..f91fb9dd6 --- /dev/null +++ b/fastlane/metadata/android/cs-CZ/changelogs/3100.txt @@ -0,0 +1,10 @@ +* navrhování názvů nainstalovaných aplikací +* přepnutí kategorie emoji přejetím +* zobr. oznámení po obnovení zálohy +* větší tlačítko a ikona na panelu nástrojů +* zpřístupnění čárky ve vysk. klávesách při zobrazení vysk. kl. TLD +* přidáno nastavení vých. odstínu pleti emodži +* přidány kódy kláves pro levý a pravý Alt a Ctrl +* přidán popisek klávesy „časové razítko“ pro přístupnější klávesu čas. razítka +* oprava spec. popisků kláves pro vysk. kl. v jednoduchých rozl. +* drobné opravy a vylepšení diff --git a/fastlane/metadata/android/cs-CZ/changelogs/3101.txt b/fastlane/metadata/android/cs-CZ/changelogs/3101.txt new file mode 100644 index 000000000..11ff7b94a --- /dev/null +++ b/fastlane/metadata/android/cs-CZ/changelogs/3101.txt @@ -0,0 +1,9 @@ +* navrhování názvů nainstalovaných aplikací +* přepnutí kategorie emoji přejetím +* zobr. oznámení po obnovení zálohy +* zpřístupnění čárky ve vysk. klávesách při zobrazení vysk. kl. TLD +* přidáno nastavení vých. odstínu pleti emodži +* přidány kódy kláves pro levý a pravý Alt a Ctrl +* přidán popisek klávesy „časové razítko“ pro přístupnější klávesu čas. razítka +* oprava spec. popisků kláves pro vysk. kl. v jednoduchých rozl. +* drobné opravy a vylepšení diff --git a/fastlane/metadata/android/cs-CZ/full_description.txt b/fastlane/metadata/android/cs-CZ/full_description.txt new file mode 100644 index 000000000..78bdc2dc0 --- /dev/null +++ b/fastlane/metadata/android/cs-CZ/full_description.txt @@ -0,0 +1,30 @@ +HeliBoard je open-source klávesnice zaměřená na soukromí, založená na AOSP / OpenBoard. +Nepoužívá internet, a je tedy 100% offline. + +Funkce: +
        +
      • Přidávejte slovníky pro návrhy a kontrolu pravopisu
      • +
          +
        • vytvořte si vlastní, nebo si je stáhněte zde, nebo v experimentální sekci (kvalita se může lišit)
        • +
        • další slovníky pro emotikony nebo vědecké symboly lze použít k poskytování návrhů (podobně jako „vyhledávání emoji“)
        • +
        • upozorňujeme, že pro korejské rozložení fungují návrhy pouze s tímto slovníkem, nástroje v repozitáři se slovníky nedokážou vytvořit funkční slovníky
        • +
        +
      • Přizpůsobte si vzhled klávesnice (styl, barvy a obrázek na pozadí)
      • +
          +
        • dokáže se přizpůsobit dennímu/nočnímu nastavení v Androidu 10+ (a na některých verzích Androidu 9)
        • +
        • dokáže se přizpůsobit dynamickým barvám v Androidu 12+
        • +
        +
      • Přizpůsobte si rozložení klávesnice (dostupné pouze při vypnuté volbě používat systémové jazyky)
      • +
      • Přizpůsobte si speciální rozložení, jako jsou symboly, čísla nebo rozložení funkčních kláves
      • +
      • Vícejazyčné psaní
      • +
      • Psaní jedním tahem (pouze s proprietární knihovnou ☹️)
      • +
          +
        • knihovna není součástí aplikace, protože není dostupná žádná kompatibilní open source verze
        • +
        • lze ji extrahovat z balíků GApps („swypelibs“) nebo stáhnout zde (klikněte na soubor a pak na „raw“ nebo malé tlačítko pro stažení)
        • +
        +
      • Historie schránky
      • +
      • Režim ovládání jednou rukou
      • +
      • Rozdělená klávesnice (dostupná pouze pokud je obrazovka dostatečně velká)
      • +
      • Numerická klávesnice
      • +
      • Záloha a obnova nastavení a naučených slov / historie
      • +
      diff --git a/fastlane/metadata/android/de-DE/changelogs/3004.txt b/fastlane/metadata/android/de-DE/changelogs/3004.txt new file mode 100644 index 000000000..6f8a7103e --- /dev/null +++ b/fastlane/metadata/android/de-DE/changelogs/3004.txt @@ -0,0 +1,11 @@ +* Layouts hinzugefügt: Arabisch Hija'i, Hebräisch 1452-2, Hindi Phonetic, Dargwa (Urakhi), Baishakhi, Kurdisch +* einige Layouts aktualisiert +* Unterstützung der Kombination von Akzenten +* geteilte Tastatursymbolleisten-Taste +* Hinzufügen von .com-Popups +* Einstellung einer benutzerdefinierten Schriftart ermöglicht +* Einstellung des Schriftgrades hinzugefügt +* Verbesserung der automatischen Sprachumschaltung +* Überarbeitung der Einstellungen +* Einstellungen für mehr Tuning von Tastaturauffüllung, Auto-Leerzeichen, Auto-Korrektur, Zahlenreihe hinzugefügt +* weitere Funktionen und Korrekturen diff --git a/fastlane/metadata/android/de-DE/full_description.txt b/fastlane/metadata/android/de-DE/full_description.txt index 670b10bee..afb8c27e7 100644 --- a/fastlane/metadata/android/de-DE/full_description.txt +++ b/fastlane/metadata/android/de-DE/full_description.txt @@ -5,7 +5,7 @@ Features:
      • Wörterbücher für Vorschläge und Rechtschreibprüfung hinzufügen
        • -
        • Erstelle deine eigenen oder hole sie dir hier oder im experimentellen Bereich (Qualität kann variieren)
        • +
        • Erstelle deine eigenen oder hole sie dir hier oder im experimentellen Bereich (Qualität kann variieren)
        • Zusätzliche Wörterbücher für Emojis oder wissenschaftliche Symbole können zur Bereitstellung von Vorschlägen genutzt werden (ähnlich wie bei der „Emoji-Suche“)
        • Beachte, dass die Vorschläge für koreanische Layouts nur mit diesem Wörterbuch funktionieren, die Werkzeuge im Wörterbuch-Repository können keine funktionierenden Wörterbücher erstellen
        diff --git a/fastlane/metadata/android/en-US/changelogs/3004.txt b/fastlane/metadata/android/en-US/changelogs/3004.txt new file mode 100644 index 000000000..ce0395033 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/3004.txt @@ -0,0 +1,11 @@ +* add layouts: Arabic Hija'i, Hebrew 1452-2, Hindi Phonetic, Dargwa (Urakhi), Baishakhi, Kurdish +* update some layouts +* support combining accents +* split keyboard toolbar key +* add .com popups +* allow setting custom font +* add font scale setting +* improve automatic language switching +* overhaul settings +* add settings for more tuning of keyboard padding, auto-space, auto-correction, number row +* more features and fixes diff --git a/fastlane/metadata/android/en-US/changelogs/3005.txt b/fastlane/metadata/android/en-US/changelogs/3005.txt new file mode 100644 index 000000000..ce0395033 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/3005.txt @@ -0,0 +1,11 @@ +* add layouts: Arabic Hija'i, Hebrew 1452-2, Hindi Phonetic, Dargwa (Urakhi), Baishakhi, Kurdish +* update some layouts +* support combining accents +* split keyboard toolbar key +* add .com popups +* allow setting custom font +* add font scale setting +* improve automatic language switching +* overhaul settings +* add settings for more tuning of keyboard padding, auto-space, auto-correction, number row +* more features and fixes diff --git a/fastlane/metadata/android/en-US/changelogs/3006.txt b/fastlane/metadata/android/en-US/changelogs/3006.txt new file mode 100644 index 000000000..ce0395033 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/3006.txt @@ -0,0 +1,11 @@ +* add layouts: Arabic Hija'i, Hebrew 1452-2, Hindi Phonetic, Dargwa (Urakhi), Baishakhi, Kurdish +* update some layouts +* support combining accents +* split keyboard toolbar key +* add .com popups +* allow setting custom font +* add font scale setting +* improve automatic language switching +* overhaul settings +* add settings for more tuning of keyboard padding, auto-space, auto-correction, number row +* more features and fixes diff --git a/fastlane/metadata/android/en-US/changelogs/3007.txt b/fastlane/metadata/android/en-US/changelogs/3007.txt new file mode 100644 index 000000000..ce0395033 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/3007.txt @@ -0,0 +1,11 @@ +* add layouts: Arabic Hija'i, Hebrew 1452-2, Hindi Phonetic, Dargwa (Urakhi), Baishakhi, Kurdish +* update some layouts +* support combining accents +* split keyboard toolbar key +* add .com popups +* allow setting custom font +* add font scale setting +* improve automatic language switching +* overhaul settings +* add settings for more tuning of keyboard padding, auto-space, auto-correction, number row +* more features and fixes diff --git a/fastlane/metadata/android/en-US/changelogs/3008.txt b/fastlane/metadata/android/en-US/changelogs/3008.txt new file mode 100644 index 000000000..ce0395033 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/3008.txt @@ -0,0 +1,11 @@ +* add layouts: Arabic Hija'i, Hebrew 1452-2, Hindi Phonetic, Dargwa (Urakhi), Baishakhi, Kurdish +* update some layouts +* support combining accents +* split keyboard toolbar key +* add .com popups +* allow setting custom font +* add font scale setting +* improve automatic language switching +* overhaul settings +* add settings for more tuning of keyboard padding, auto-space, auto-correction, number row +* more features and fixes diff --git a/fastlane/metadata/android/en-US/changelogs/3100.txt b/fastlane/metadata/android/en-US/changelogs/3100.txt new file mode 100644 index 000000000..f4d90dce4 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/3100.txt @@ -0,0 +1,10 @@ +* optionally suggest names of installed apps +* swipe to switch emoji categories +* display toast after restoring backup +* larger toolbar button and icon +* make comma accessible in popups when showing TLD popups +* add setting for default emoji skin tone +* add keycodes for left and right alt and ctrl keys +* add key label "timestamp" for more accessible timestamp key +* understand special key labels for popups in simple layouts +* minor fixes and improvements diff --git a/fastlane/metadata/android/en-US/changelogs/3101.txt b/fastlane/metadata/android/en-US/changelogs/3101.txt new file mode 100644 index 000000000..758e259b0 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/3101.txt @@ -0,0 +1,9 @@ +* optionally suggest names of installed apps +* swipe to switch emoji categories +* display toast after restoring backup +* make comma accessible in popups when showing TLD popups +* add setting for default emoji skin tone +* add keycodes for left and right alt and ctrl keys +* add key label "timestamp" for more accessible timestamp key +* understand special key labels for popups in simple layouts +* minor fixes and improvements diff --git a/fastlane/metadata/android/et/changelogs/3004.txt b/fastlane/metadata/android/et/changelogs/3004.txt new file mode 100644 index 000000000..f9be70240 --- /dev/null +++ b/fastlane/metadata/android/et/changelogs/3004.txt @@ -0,0 +1,11 @@ +* uued klahvipaigustused: araabia hija'i, heebrea 1452-2, hindi foneetiline, dargi (Urahhi), baišaki, kurdi +* mõnede klahvipaigustuste täiendused +* aktsentide kombineerimise tugi +* nupp klahvistiku poolitamiseks +* lisandusid .com hüpikaknad +* oma kirjatüübi valikuvõimalus +* kirjatüübi skaleerimise võimalus +* improve automatic language switching +* seadistuste kohendus +* lisaseadistused klahvide vaheruumi, tühikute lisamise, autokorrektsiooni ja ridade arvu jaoks +* pisitäiendused ja parandused diff --git a/fastlane/metadata/android/et/changelogs/3005.txt b/fastlane/metadata/android/et/changelogs/3005.txt new file mode 100644 index 000000000..f9be70240 --- /dev/null +++ b/fastlane/metadata/android/et/changelogs/3005.txt @@ -0,0 +1,11 @@ +* uued klahvipaigustused: araabia hija'i, heebrea 1452-2, hindi foneetiline, dargi (Urahhi), baišaki, kurdi +* mõnede klahvipaigustuste täiendused +* aktsentide kombineerimise tugi +* nupp klahvistiku poolitamiseks +* lisandusid .com hüpikaknad +* oma kirjatüübi valikuvõimalus +* kirjatüübi skaleerimise võimalus +* improve automatic language switching +* seadistuste kohendus +* lisaseadistused klahvide vaheruumi, tühikute lisamise, autokorrektsiooni ja ridade arvu jaoks +* pisitäiendused ja parandused diff --git a/fastlane/metadata/android/et/changelogs/3006.txt b/fastlane/metadata/android/et/changelogs/3006.txt new file mode 100644 index 000000000..f9be70240 --- /dev/null +++ b/fastlane/metadata/android/et/changelogs/3006.txt @@ -0,0 +1,11 @@ +* uued klahvipaigustused: araabia hija'i, heebrea 1452-2, hindi foneetiline, dargi (Urahhi), baišaki, kurdi +* mõnede klahvipaigustuste täiendused +* aktsentide kombineerimise tugi +* nupp klahvistiku poolitamiseks +* lisandusid .com hüpikaknad +* oma kirjatüübi valikuvõimalus +* kirjatüübi skaleerimise võimalus +* improve automatic language switching +* seadistuste kohendus +* lisaseadistused klahvide vaheruumi, tühikute lisamise, autokorrektsiooni ja ridade arvu jaoks +* pisitäiendused ja parandused diff --git a/fastlane/metadata/android/et/changelogs/3007.txt b/fastlane/metadata/android/et/changelogs/3007.txt new file mode 100644 index 000000000..f9be70240 --- /dev/null +++ b/fastlane/metadata/android/et/changelogs/3007.txt @@ -0,0 +1,11 @@ +* uued klahvipaigustused: araabia hija'i, heebrea 1452-2, hindi foneetiline, dargi (Urahhi), baišaki, kurdi +* mõnede klahvipaigustuste täiendused +* aktsentide kombineerimise tugi +* nupp klahvistiku poolitamiseks +* lisandusid .com hüpikaknad +* oma kirjatüübi valikuvõimalus +* kirjatüübi skaleerimise võimalus +* improve automatic language switching +* seadistuste kohendus +* lisaseadistused klahvide vaheruumi, tühikute lisamise, autokorrektsiooni ja ridade arvu jaoks +* pisitäiendused ja parandused diff --git a/fastlane/metadata/android/et/changelogs/3008.txt b/fastlane/metadata/android/et/changelogs/3008.txt new file mode 100644 index 000000000..f9be70240 --- /dev/null +++ b/fastlane/metadata/android/et/changelogs/3008.txt @@ -0,0 +1,11 @@ +* uued klahvipaigustused: araabia hija'i, heebrea 1452-2, hindi foneetiline, dargi (Urahhi), baišaki, kurdi +* mõnede klahvipaigustuste täiendused +* aktsentide kombineerimise tugi +* nupp klahvistiku poolitamiseks +* lisandusid .com hüpikaknad +* oma kirjatüübi valikuvõimalus +* kirjatüübi skaleerimise võimalus +* improve automatic language switching +* seadistuste kohendus +* lisaseadistused klahvide vaheruumi, tühikute lisamise, autokorrektsiooni ja ridade arvu jaoks +* pisitäiendused ja parandused diff --git a/fastlane/metadata/android/et/changelogs/3100.txt b/fastlane/metadata/android/et/changelogs/3100.txt new file mode 100644 index 000000000..d8c5eeab6 --- /dev/null +++ b/fastlane/metadata/android/et/changelogs/3100.txt @@ -0,0 +1,10 @@ +* paigaldatud rakenduste nimede soovitamine (kui tahad) +* emojide kategooriate vahetamine viibates +* süsteemne teade peale varukoopiast taastamist +* suurem tööriistariba nupp ja ikoon +* koma on kasutatav ülataseme domeenide hüpikakendes +* emojide taust on nüüd seadistatav +* koodid vasaku ja parema alt ja ctrl klahvi jaoks +* ajatempli klahv on paremini märgitud +* eriklahvide sildid hüpikakende jaoks lihtsate paigutuste puhul +* pisiparandused ja täiendused diff --git a/fastlane/metadata/android/et/changelogs/3101.txt b/fastlane/metadata/android/et/changelogs/3101.txt new file mode 100644 index 000000000..96559f7a7 --- /dev/null +++ b/fastlane/metadata/android/et/changelogs/3101.txt @@ -0,0 +1,9 @@ +* paigaldatud rakenduste nimede soovitamine (kui tahad) +* emojide kategooriate vahetamine viibates +* süsteemne teade peale varukoopiast taastamist +* koma on kasutatav ülataseme domeenide hüpikakendes +* emojide taust on nüüd seadistatav +* koodid vasaku ja parema alt ja ctrl klahvi jaoks +* ajatempli klahv on paremini märgitud +* eriklahvide sildid hüpikakende jaoks lihtsate paigutuste puhul +* pisiparandused ja täiendused diff --git a/fastlane/metadata/android/fr-FR/changelogs/1001.txt b/fastlane/metadata/android/fr-FR/changelogs/1001.txt new file mode 100644 index 000000000..2167c1f09 --- /dev/null +++ b/fastlane/metadata/android/fr-FR/changelogs/1001.txt @@ -0,0 +1,20 @@ +* nouvel icône de @FabianOvrWrt avec la contribution de @the-eclectic-dyslexic (#517, #592) +* plus de customisation de la barre espace du pavé tactile +* ajout du % pour les mises en page des symboles shift (#568, #428) +* amélioration du comportement quand la touche de changement de langue est définie pour changer à la fois la langue et le clavier +* afficher les liens aux dictionnaires existants quand un dctionnaire est ajouté +* ajout de la disposition de clavier Kaïtag par @alkaitagi (#519) +* ajout de la disposition de clavier Probhat par @fahimscirex (#489) +* ordre inversé optionnel de la barre d'outils pour les langues RTL par @codokie (#557, #574) +* autorisation de customisation de mises en page particulières (pavé numérique, téléphone, ...) + * en cours d'expérimentation, car les schémas de base peuvent changer +* mise à jour de spellchecker.xml pour inclure les lieux où les dictionnaires sont disponibles, mais n'est pas inclus dans l'application +* mise à jour des traductions (merci aux traducteur·rices !) +* amélioration du ndk par @Syphyr (#560) +* amélioration du code de remplissage automatique en ligne par @arcarum (#595) +* problème corrigé avec la fenêtre de la touche de la barre d'outils (#505) +* problème corrigé avec la disposition turque (#508) +* correction des mauvais switch states lors de la rotation dans l'écran de personnalisation des couleurs (#563) +* problème corrigé avec les récents émojis qui ne chargent pas (#527) +* problème corrigé avec les numbers qui ne s'affichent pas dans certains champs (#585) +* quelques petites corrections diff --git a/fastlane/metadata/android/fr-FR/changelogs/1003.txt b/fastlane/metadata/android/fr-FR/changelogs/1003.txt new file mode 100644 index 000000000..7481b7f68 --- /dev/null +++ b/fastlane/metadata/android/fr-FR/changelogs/1003.txt @@ -0,0 +1,9 @@ +* changement des icônes pour l'autocorrection et la sélection de toutes les touches de la barre d'outils par @codokie (#524, #651) +* ajout de la disposition de clavier Tchouvache par @tenextractor (#677) +* ajout de la touche pour couper dans la barre d'outils par @codokie (#678) +* mise à jour de la disposition de clavier Probhat par @fahimscirex (#628) +* affichage des icônes de la barre d'outils dans la fenêtre des touches +* ajout d'un bouton pour fermer dans l'historique du presse-papier par @codokie (#403, #649) +* ajout de la disposition russe (student) par @Zolax9 (#640) +* rendre les appuis longs sur les symboles du pavé numérique optionnels +* corrections et améliorations mineures, en incluant #632, #637, #638 par @RHJihan diff --git a/fastlane/metadata/android/fr-FR/changelogs/1004.txt b/fastlane/metadata/android/fr-FR/changelogs/1004.txt new file mode 100644 index 000000000..7d2651e5c --- /dev/null +++ b/fastlane/metadata/android/fr-FR/changelogs/1004.txt @@ -0,0 +1,7 @@ +- mise à jour de la disposition de clavier cyrillique serbe par @markokocic (#704, #705) +- mise à jour de la disposition de clavier estonienne par @tenextractor (#693) +- correction des entrées dupliquées dans l'historique du presse-papier par @codokie (#616, #680) +- ajouter uniquement les entrées de texte dans l'historique du presse-papier par @codokie (#711) +- meilleures images dans les métadatas par @RHJihan (#713) +- réglage correct de la couleur des icônes dans la fenêtre de sélection de la barre d'outils par @codokie (#715, #716) +- autres corrections (#684, #723 and more) diff --git a/fastlane/metadata/android/fr-FR/changelogs/2000.txt b/fastlane/metadata/android/fr-FR/changelogs/2000.txt new file mode 100644 index 000000000..4b3941704 --- /dev/null +++ b/fastlane/metadata/android/fr-FR/changelogs/2000.txt @@ -0,0 +1,10 @@ +* ajout d'une aide de base pour les modifier keys +* ajout de fonctions d'appuis longs à plus de touches de la barre d'outils +* et plus de touches de la barre d'outils pour l'historique du presse-papier +* rendre la barre d'outils de l'historique du presse-papier personnalisable +* autoriser la customisation de toutes les couleurs +* ajout d'un paramètre pour toujours afficher le mot qui doit être entré en tant que suggestion du milieu +* ajout d'un indicateur de touche majuscule enfoncée +* ajout des dispositions de clavier piémontais, mari de l'est et mansi pour le kannada et l'hongrois +* Correction du texte coupé dans la popup de prévisualisation sur certains appareils +* corrections et améliorations plus lointaines, voir notes de publication diff --git a/fastlane/metadata/android/it-IT/changelogs/3004.txt b/fastlane/metadata/android/it-IT/changelogs/3004.txt new file mode 100644 index 000000000..16cb2ba25 --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/3004.txt @@ -0,0 +1,11 @@ +* layout aggiunti: Arabo Hija'i, Ebraico 1452-2, Hindi fonetico, Dargwa (Urakhi), Baishakhi, Curdo +* alcuni layout aggiornati +* supporto agli accenti combinati +* pulsante 'Tastiera divisa' nella barra degli strumenti +* popup .com aggiunto +* font personalizzato per i tasti +* aggiustamento dimensione per i tasti +* modalità multilingua migliorata +* impostazioni ridisegnate +* aggiunte alcune opzioni per spaziatura automatica, correzione testo e riga dei numeri +* altre funzionalità, migliorie e bugfix diff --git a/fastlane/metadata/android/it-IT/changelogs/3005.txt b/fastlane/metadata/android/it-IT/changelogs/3005.txt new file mode 100644 index 000000000..16cb2ba25 --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/3005.txt @@ -0,0 +1,11 @@ +* layout aggiunti: Arabo Hija'i, Ebraico 1452-2, Hindi fonetico, Dargwa (Urakhi), Baishakhi, Curdo +* alcuni layout aggiornati +* supporto agli accenti combinati +* pulsante 'Tastiera divisa' nella barra degli strumenti +* popup .com aggiunto +* font personalizzato per i tasti +* aggiustamento dimensione per i tasti +* modalità multilingua migliorata +* impostazioni ridisegnate +* aggiunte alcune opzioni per spaziatura automatica, correzione testo e riga dei numeri +* altre funzionalità, migliorie e bugfix diff --git a/fastlane/metadata/android/it-IT/changelogs/3006.txt b/fastlane/metadata/android/it-IT/changelogs/3006.txt new file mode 100644 index 000000000..16cb2ba25 --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/3006.txt @@ -0,0 +1,11 @@ +* layout aggiunti: Arabo Hija'i, Ebraico 1452-2, Hindi fonetico, Dargwa (Urakhi), Baishakhi, Curdo +* alcuni layout aggiornati +* supporto agli accenti combinati +* pulsante 'Tastiera divisa' nella barra degli strumenti +* popup .com aggiunto +* font personalizzato per i tasti +* aggiustamento dimensione per i tasti +* modalità multilingua migliorata +* impostazioni ridisegnate +* aggiunte alcune opzioni per spaziatura automatica, correzione testo e riga dei numeri +* altre funzionalità, migliorie e bugfix diff --git a/fastlane/metadata/android/it-IT/changelogs/3007.txt b/fastlane/metadata/android/it-IT/changelogs/3007.txt new file mode 100644 index 000000000..16cb2ba25 --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/3007.txt @@ -0,0 +1,11 @@ +* layout aggiunti: Arabo Hija'i, Ebraico 1452-2, Hindi fonetico, Dargwa (Urakhi), Baishakhi, Curdo +* alcuni layout aggiornati +* supporto agli accenti combinati +* pulsante 'Tastiera divisa' nella barra degli strumenti +* popup .com aggiunto +* font personalizzato per i tasti +* aggiustamento dimensione per i tasti +* modalità multilingua migliorata +* impostazioni ridisegnate +* aggiunte alcune opzioni per spaziatura automatica, correzione testo e riga dei numeri +* altre funzionalità, migliorie e bugfix diff --git a/fastlane/metadata/android/it-IT/changelogs/3008.txt b/fastlane/metadata/android/it-IT/changelogs/3008.txt new file mode 100644 index 000000000..16cb2ba25 --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/3008.txt @@ -0,0 +1,11 @@ +* layout aggiunti: Arabo Hija'i, Ebraico 1452-2, Hindi fonetico, Dargwa (Urakhi), Baishakhi, Curdo +* alcuni layout aggiornati +* supporto agli accenti combinati +* pulsante 'Tastiera divisa' nella barra degli strumenti +* popup .com aggiunto +* font personalizzato per i tasti +* aggiustamento dimensione per i tasti +* modalità multilingua migliorata +* impostazioni ridisegnate +* aggiunte alcune opzioni per spaziatura automatica, correzione testo e riga dei numeri +* altre funzionalità, migliorie e bugfix diff --git a/fastlane/metadata/android/iw-IL/changelogs/3004.txt b/fastlane/metadata/android/iw-IL/changelogs/3004.txt new file mode 100644 index 000000000..674053177 --- /dev/null +++ b/fastlane/metadata/android/iw-IL/changelogs/3004.txt @@ -0,0 +1,11 @@ +* הוספת פריסות: ערבית (הג'אי), עברית 1452-2, הינדית פונטית, דארגווה (אוראקי), באישאקי,כורדית +* עדכון מספר פריסות +* תמיכה בשילוב סימנים דיאקריטיים +* מקש סרגל הכלים למקלדת מפוצלת +* הוספת סיומות .com לחלון צץ +* אפשרות לבחירת גופן מותאם +* הוספת הגדרת סדר-גודל הגופן +* שיפור המעבר האוטומטי בין שפות +* שיפור ההגדרות +* הוספת הגדרות לכיוונון נוסף של שולי המקלדת, רווח אוטומטי, תיקון אוטומטי, שורת המספרים +* תכולות ותיקונים נוספים diff --git a/fastlane/metadata/android/iw-IL/changelogs/3005.txt b/fastlane/metadata/android/iw-IL/changelogs/3005.txt new file mode 100644 index 000000000..674053177 --- /dev/null +++ b/fastlane/metadata/android/iw-IL/changelogs/3005.txt @@ -0,0 +1,11 @@ +* הוספת פריסות: ערבית (הג'אי), עברית 1452-2, הינדית פונטית, דארגווה (אוראקי), באישאקי,כורדית +* עדכון מספר פריסות +* תמיכה בשילוב סימנים דיאקריטיים +* מקש סרגל הכלים למקלדת מפוצלת +* הוספת סיומות .com לחלון צץ +* אפשרות לבחירת גופן מותאם +* הוספת הגדרת סדר-גודל הגופן +* שיפור המעבר האוטומטי בין שפות +* שיפור ההגדרות +* הוספת הגדרות לכיוונון נוסף של שולי המקלדת, רווח אוטומטי, תיקון אוטומטי, שורת המספרים +* תכולות ותיקונים נוספים diff --git a/fastlane/metadata/android/iw-IL/changelogs/3006.txt b/fastlane/metadata/android/iw-IL/changelogs/3006.txt new file mode 100644 index 000000000..674053177 --- /dev/null +++ b/fastlane/metadata/android/iw-IL/changelogs/3006.txt @@ -0,0 +1,11 @@ +* הוספת פריסות: ערבית (הג'אי), עברית 1452-2, הינדית פונטית, דארגווה (אוראקי), באישאקי,כורדית +* עדכון מספר פריסות +* תמיכה בשילוב סימנים דיאקריטיים +* מקש סרגל הכלים למקלדת מפוצלת +* הוספת סיומות .com לחלון צץ +* אפשרות לבחירת גופן מותאם +* הוספת הגדרת סדר-גודל הגופן +* שיפור המעבר האוטומטי בין שפות +* שיפור ההגדרות +* הוספת הגדרות לכיוונון נוסף של שולי המקלדת, רווח אוטומטי, תיקון אוטומטי, שורת המספרים +* תכולות ותיקונים נוספים diff --git a/fastlane/metadata/android/iw-IL/changelogs/3007.txt b/fastlane/metadata/android/iw-IL/changelogs/3007.txt new file mode 100644 index 000000000..674053177 --- /dev/null +++ b/fastlane/metadata/android/iw-IL/changelogs/3007.txt @@ -0,0 +1,11 @@ +* הוספת פריסות: ערבית (הג'אי), עברית 1452-2, הינדית פונטית, דארגווה (אוראקי), באישאקי,כורדית +* עדכון מספר פריסות +* תמיכה בשילוב סימנים דיאקריטיים +* מקש סרגל הכלים למקלדת מפוצלת +* הוספת סיומות .com לחלון צץ +* אפשרות לבחירת גופן מותאם +* הוספת הגדרת סדר-גודל הגופן +* שיפור המעבר האוטומטי בין שפות +* שיפור ההגדרות +* הוספת הגדרות לכיוונון נוסף של שולי המקלדת, רווח אוטומטי, תיקון אוטומטי, שורת המספרים +* תכולות ותיקונים נוספים diff --git a/fastlane/metadata/android/iw-IL/changelogs/3008.txt b/fastlane/metadata/android/iw-IL/changelogs/3008.txt new file mode 100644 index 000000000..674053177 --- /dev/null +++ b/fastlane/metadata/android/iw-IL/changelogs/3008.txt @@ -0,0 +1,11 @@ +* הוספת פריסות: ערבית (הג'אי), עברית 1452-2, הינדית פונטית, דארגווה (אוראקי), באישאקי,כורדית +* עדכון מספר פריסות +* תמיכה בשילוב סימנים דיאקריטיים +* מקש סרגל הכלים למקלדת מפוצלת +* הוספת סיומות .com לחלון צץ +* אפשרות לבחירת גופן מותאם +* הוספת הגדרת סדר-גודל הגופן +* שיפור המעבר האוטומטי בין שפות +* שיפור ההגדרות +* הוספת הגדרות לכיוונון נוסף של שולי המקלדת, רווח אוטומטי, תיקון אוטומטי, שורת המספרים +* תכולות ותיקונים נוספים diff --git a/fastlane/metadata/android/iw-IL/changelogs/3100.txt b/fastlane/metadata/android/iw-IL/changelogs/3100.txt new file mode 100644 index 000000000..0a2d1445d --- /dev/null +++ b/fastlane/metadata/android/iw-IL/changelogs/3100.txt @@ -0,0 +1,10 @@ +* אפשרות להצעת שמות של יישומים מותקנים +* החלקה למעבר בין קטגוריות אמוג'י +* הצגת הודעה לאחר שחזור גיבוי +* כפתור וסמלי toolbar גדולים יותר +* לאפשר גישה לפסיק בחלוניות צצות בעת הצגת חלוניות צצות TLD +* הוספת אפשרות לגוון-עור ברירת-מחדל לאמוג'ים +* הוספת keycodes למקשי alt ימני ושמאלי ולמקש ctrl +* הוספת תווית מפתח "timestamp" למפתח נגיש יותר של חתימת זמן +* הבנת תוויות מקשים מיוחדים לחלוניות צצות בפריסות פשוטות +* תיקונים ושיפורים שוליים diff --git a/fastlane/metadata/android/iw-IL/changelogs/3101.txt b/fastlane/metadata/android/iw-IL/changelogs/3101.txt new file mode 100644 index 000000000..4e17a2c15 --- /dev/null +++ b/fastlane/metadata/android/iw-IL/changelogs/3101.txt @@ -0,0 +1,9 @@ +* אפשרות להצעת שמות של יישומים מותקנים +* החלקה למעבר בין קטגוריות אמוג'י +* הצגת הודעה לאחר שחזור גיבוי +* לאפשר גישה לפסיק בחלוניות צצות בעת הצגת חלוניות צצות TLD +* הוספת אפשרות לגוון-עור ברירת-מחדל לאמוג'ים +* הוספת keycodes למקשי alt ימני ושמאלי ולמקש ctrl +* הוספת תווית מפתח "timestamp" למפתח נגיש יותר של חתימת זמן +* הבנת תוויות מקשים מיוחדים לחלוניות צצות בפריסות פשוטות +* תיקונים ושיפורים שוליים diff --git a/fastlane/metadata/android/lv/changelogs/2002.txt b/fastlane/metadata/android/lv/changelogs/2002.txt new file mode 100644 index 000000000..e2d5bc579 --- /dev/null +++ b/fastlane/metadata/android/lv/changelogs/2002.txt @@ -0,0 +1,4 @@ +* pievienots emocijzīmju rīkjoslas taustiņš, autors @codokie (#845, #837) +* uzlabojumi, kas saistīti ar dublētiem burtiem (#225 un, iespējams, citi) +* izvairās novietot kursoru emocijzīmju iekšpusē (#859) +* nelieli labojumi nesen pievienotajām funkcijām diff --git a/fastlane/metadata/android/lv/changelogs/2201.txt b/fastlane/metadata/android/lv/changelogs/2201.txt new file mode 100644 index 000000000..cb2f7ae9d --- /dev/null +++ b/fastlane/metadata/android/lv/changelogs/2201.txt @@ -0,0 +1,2 @@ +* pievienoti žestu rakstīšanas vizuālie iestatījumi, autors @devycarol (#944) +* atjauninātas dažas ikonas, autors @BlackyHawky (#977) diff --git a/fastlane/metadata/android/lv/short_description.txt b/fastlane/metadata/android/lv/short_description.txt new file mode 100644 index 000000000..711d5026b --- /dev/null +++ b/fastlane/metadata/android/lv/short_description.txt @@ -0,0 +1 @@ +Pielāgojama atvērtā pirmkoda tastatūra diff --git a/fastlane/metadata/android/lv/title.txt b/fastlane/metadata/android/lv/title.txt new file mode 100644 index 000000000..e9841ace0 --- /dev/null +++ b/fastlane/metadata/android/lv/title.txt @@ -0,0 +1 @@ +HeliBoard diff --git a/fastlane/metadata/android/nl-NL/changelogs/3004.txt b/fastlane/metadata/android/nl-NL/changelogs/3004.txt new file mode 100644 index 000000000..6256f8aeb --- /dev/null +++ b/fastlane/metadata/android/nl-NL/changelogs/3004.txt @@ -0,0 +1,11 @@ +* lay-outs toevoegen: Arabisch Hija'i, Hebreeuws 1452-2, Hindi Fonetisch, Dargwa (Urakhi), Baishakhi, Koerdisch +* Update enkele lay-outs +* Ondersteuning voor het combineren van accenten +* Gesplitste toetsenbordwerkbalktoets +* voeg .com pop-ups toe +* Toestaan instellen van aangepast lettertype +* Instelling voor lettertypeschaal toevoegen +* automatische taalomschakeling verbeteren +* Revisie instellingen +* Voeg instellingen toe voor meer afstemming van toetsenbordopvulling, automatische spatie, autocorrectie, cijferrij +* Meer functies en fixes diff --git a/fastlane/metadata/android/nl-NL/changelogs/3005.txt b/fastlane/metadata/android/nl-NL/changelogs/3005.txt new file mode 100644 index 000000000..6256f8aeb --- /dev/null +++ b/fastlane/metadata/android/nl-NL/changelogs/3005.txt @@ -0,0 +1,11 @@ +* lay-outs toevoegen: Arabisch Hija'i, Hebreeuws 1452-2, Hindi Fonetisch, Dargwa (Urakhi), Baishakhi, Koerdisch +* Update enkele lay-outs +* Ondersteuning voor het combineren van accenten +* Gesplitste toetsenbordwerkbalktoets +* voeg .com pop-ups toe +* Toestaan instellen van aangepast lettertype +* Instelling voor lettertypeschaal toevoegen +* automatische taalomschakeling verbeteren +* Revisie instellingen +* Voeg instellingen toe voor meer afstemming van toetsenbordopvulling, automatische spatie, autocorrectie, cijferrij +* Meer functies en fixes diff --git a/fastlane/metadata/android/nl-NL/changelogs/3006.txt b/fastlane/metadata/android/nl-NL/changelogs/3006.txt new file mode 100644 index 000000000..6256f8aeb --- /dev/null +++ b/fastlane/metadata/android/nl-NL/changelogs/3006.txt @@ -0,0 +1,11 @@ +* lay-outs toevoegen: Arabisch Hija'i, Hebreeuws 1452-2, Hindi Fonetisch, Dargwa (Urakhi), Baishakhi, Koerdisch +* Update enkele lay-outs +* Ondersteuning voor het combineren van accenten +* Gesplitste toetsenbordwerkbalktoets +* voeg .com pop-ups toe +* Toestaan instellen van aangepast lettertype +* Instelling voor lettertypeschaal toevoegen +* automatische taalomschakeling verbeteren +* Revisie instellingen +* Voeg instellingen toe voor meer afstemming van toetsenbordopvulling, automatische spatie, autocorrectie, cijferrij +* Meer functies en fixes diff --git a/fastlane/metadata/android/nl-NL/changelogs/3007.txt b/fastlane/metadata/android/nl-NL/changelogs/3007.txt new file mode 100644 index 000000000..6256f8aeb --- /dev/null +++ b/fastlane/metadata/android/nl-NL/changelogs/3007.txt @@ -0,0 +1,11 @@ +* lay-outs toevoegen: Arabisch Hija'i, Hebreeuws 1452-2, Hindi Fonetisch, Dargwa (Urakhi), Baishakhi, Koerdisch +* Update enkele lay-outs +* Ondersteuning voor het combineren van accenten +* Gesplitste toetsenbordwerkbalktoets +* voeg .com pop-ups toe +* Toestaan instellen van aangepast lettertype +* Instelling voor lettertypeschaal toevoegen +* automatische taalomschakeling verbeteren +* Revisie instellingen +* Voeg instellingen toe voor meer afstemming van toetsenbordopvulling, automatische spatie, autocorrectie, cijferrij +* Meer functies en fixes diff --git a/fastlane/metadata/android/nl-NL/changelogs/3008.txt b/fastlane/metadata/android/nl-NL/changelogs/3008.txt new file mode 100644 index 000000000..6256f8aeb --- /dev/null +++ b/fastlane/metadata/android/nl-NL/changelogs/3008.txt @@ -0,0 +1,11 @@ +* lay-outs toevoegen: Arabisch Hija'i, Hebreeuws 1452-2, Hindi Fonetisch, Dargwa (Urakhi), Baishakhi, Koerdisch +* Update enkele lay-outs +* Ondersteuning voor het combineren van accenten +* Gesplitste toetsenbordwerkbalktoets +* voeg .com pop-ups toe +* Toestaan instellen van aangepast lettertype +* Instelling voor lettertypeschaal toevoegen +* automatische taalomschakeling verbeteren +* Revisie instellingen +* Voeg instellingen toe voor meer afstemming van toetsenbordopvulling, automatische spatie, autocorrectie, cijferrij +* Meer functies en fixes diff --git a/fastlane/metadata/android/nl-NL/changelogs/3100.txt b/fastlane/metadata/android/nl-NL/changelogs/3100.txt new file mode 100644 index 000000000..5a93279a1 --- /dev/null +++ b/fastlane/metadata/android/nl-NL/changelogs/3100.txt @@ -0,0 +1,10 @@ +* Stel optioneel namen van geïnstalleerde apps voor +* Veeg om van emoji-categorie te wisselen +* Sla op na het herstellen van de back-up +* Grotere werkbalkknop en -pictogram +* komma toegankelijk maken in pop-ups bij het tonen van TLD-pop-ups +* Instelling toevoegen voor standaard emoji-huidskleur +* Voeg keycodes toe voor linker en rechter alt- en ctrl-toetsen +* Voeg sleutellabel "Timestamp" toe voor een meer toegankelijke tijdstempelsleutel +* Begrijp speciale sleutellabels voor pop-ups in eenvoudige lay-outs +* Kleine fixes en verbeteringen diff --git a/fastlane/metadata/android/nl-NL/changelogs/3101.txt b/fastlane/metadata/android/nl-NL/changelogs/3101.txt new file mode 100644 index 000000000..401cf5321 --- /dev/null +++ b/fastlane/metadata/android/nl-NL/changelogs/3101.txt @@ -0,0 +1,9 @@ +* Stel optioneel namen van geïnstalleerde apps voor +* Veeg om van emoji-categorie te wisselen +* Sla op na het herstellen van de back-up +* komma toegankelijk maken in pop-ups bij het tonen van TLD-pop-ups +* Instelling toevoegen voor standaard emoji-huidskleur +* Voeg keycodes toe voor linker en rechter alt- en ctrl-toetsen +* Voeg sleutellabel "Timestamp" toe voor een meer toegankelijke tijdstempelsleutel +* Begrijp speciale sleutellabels voor pop-ups in eenvoudige lay-outs +* Kleine fixes en verbeteringen diff --git a/fastlane/metadata/android/ru-RU/changelogs/2300.txt b/fastlane/metadata/android/ru-RU/changelogs/2300.txt index 31b2a9c92..753d53fbb 100644 --- a/fastlane/metadata/android/ru-RU/changelogs/2300.txt +++ b/fastlane/metadata/android/ru-RU/changelogs/2300.txt @@ -1,9 +1,9 @@ -* Настройка строки цифр, кодов панели инструментов, иконок, текста панели пробела, нижней строки для эмодзи и виджетов буфера обмена -* Отделение стиля иконок от стиля клавиатуры -* Выключение по умолчанию удаления избыточных всплывающих окон (и добавление небольшого исправления) -* Менее агрессивное добавление слов в личный словарь -* Нет вибрации в режиме Не беспокоить -* Улучшение производительности при копировании большого текста -* Исправление частично сломанных всплывающих окон с пунктуацией -* Исправление некоторых проблем, при которых текст дублируется -* Незначительные улучшения и исправления большего количества ошибок +* настройка строки цифр, кодов панели инструментов, иконок, текста панели пробела, нижней строки для эмодзи и виджетов буфера обмена +* отделение стиля иконок от стиля клавиатуры +* выключение по умолчанию удаления избыточных всплывающих окон (и добавление небольшого исправления) +* менее агрессивное добавление слов в личный словарь +* нет вибрации в режиме Не беспокоить +* улучшение производительности при копировании большого текста +* исправление частично сломанных всплывающих окон с пунктуацией +* исправление некоторых проблем, при которых текст дублируется +* незначительные улучшения и исправления большего количества ошибок diff --git a/fastlane/metadata/android/ru-RU/changelogs/2301.txt b/fastlane/metadata/android/ru-RU/changelogs/2301.txt index 31b2a9c92..a486efe6a 100644 --- a/fastlane/metadata/android/ru-RU/changelogs/2301.txt +++ b/fastlane/metadata/android/ru-RU/changelogs/2301.txt @@ -1,9 +1,9 @@ -* Настройка строки цифр, кодов панели инструментов, иконок, текста панели пробела, нижней строки для эмодзи и виджетов буфера обмена -* Отделение стиля иконок от стиля клавиатуры -* Выключение по умолчанию удаления избыточных всплывающих окон (и добавление небольшого исправления) -* Менее агрессивное добавление слов в личный словарь -* Нет вибрации в режиме Не беспокоить -* Улучшение производительности при копировании большого текста -* Исправление частично сломанных всплывающих окон с пунктуацией -* Исправление некоторых проблем, при которых текст дублируется -* Незначительные улучшения и исправления большего количества ошибок +* настройка строки цифр, кодов панели инструментов, иконок, текста панели пробела, нижней строки для эмодзи и виджетов буфера обмена +* итделение стиля иконок от стиля клавиатуры +* выключение по умолчанию удаления избыточных всплывающих окон (и добавление небольшого исправления) +* менее агрессивное добавление слов в личный словарь +* нет вибрации в режиме Не беспокоить +* улучшение производительности при копировании большого текста +* исправление частично сломанных всплывающих окон с пунктуацией +* исправление некоторых проблем, при которых текст дублируется +* незначительные улучшения и исправления большего количества ошибок diff --git a/fastlane/metadata/android/ru-RU/changelogs/3004.txt b/fastlane/metadata/android/ru-RU/changelogs/3004.txt new file mode 100644 index 000000000..e10bf5b39 --- /dev/null +++ b/fastlane/metadata/android/ru-RU/changelogs/3004.txt @@ -0,0 +1,11 @@ +* добавлены раскладки: арабская Хиджаи, иврит 1452-2, хинди (фонетическая), даргинская (Урахи), байшахи, курдская +* обновлены некоторые раскладки +* реализована поддержка объединённых акцентов +* клавиша панели инструментов клавиатуры разделена +* добавлены всплывающие окна .com +* добавлена возможность выбора пользовательского шрифта +* добавлена настройка масштаба шрифта +* улучшено автоматическое переключение языков +* проведена переработка настроек +* добавлены настройки для более тонкой регулировки отступов клавиатуры, авто-пробела, автоисправления, цифрового ряда +* добавлены новые функции и исправления diff --git a/fastlane/metadata/android/ru-RU/changelogs/3005.txt b/fastlane/metadata/android/ru-RU/changelogs/3005.txt new file mode 100644 index 000000000..e10bf5b39 --- /dev/null +++ b/fastlane/metadata/android/ru-RU/changelogs/3005.txt @@ -0,0 +1,11 @@ +* добавлены раскладки: арабская Хиджаи, иврит 1452-2, хинди (фонетическая), даргинская (Урахи), байшахи, курдская +* обновлены некоторые раскладки +* реализована поддержка объединённых акцентов +* клавиша панели инструментов клавиатуры разделена +* добавлены всплывающие окна .com +* добавлена возможность выбора пользовательского шрифта +* добавлена настройка масштаба шрифта +* улучшено автоматическое переключение языков +* проведена переработка настроек +* добавлены настройки для более тонкой регулировки отступов клавиатуры, авто-пробела, автоисправления, цифрового ряда +* добавлены новые функции и исправления diff --git a/fastlane/metadata/android/ru-RU/changelogs/3006.txt b/fastlane/metadata/android/ru-RU/changelogs/3006.txt new file mode 100644 index 000000000..e10bf5b39 --- /dev/null +++ b/fastlane/metadata/android/ru-RU/changelogs/3006.txt @@ -0,0 +1,11 @@ +* добавлены раскладки: арабская Хиджаи, иврит 1452-2, хинди (фонетическая), даргинская (Урахи), байшахи, курдская +* обновлены некоторые раскладки +* реализована поддержка объединённых акцентов +* клавиша панели инструментов клавиатуры разделена +* добавлены всплывающие окна .com +* добавлена возможность выбора пользовательского шрифта +* добавлена настройка масштаба шрифта +* улучшено автоматическое переключение языков +* проведена переработка настроек +* добавлены настройки для более тонкой регулировки отступов клавиатуры, авто-пробела, автоисправления, цифрового ряда +* добавлены новые функции и исправления diff --git a/fastlane/metadata/android/ru-RU/changelogs/3007.txt b/fastlane/metadata/android/ru-RU/changelogs/3007.txt new file mode 100644 index 000000000..e10bf5b39 --- /dev/null +++ b/fastlane/metadata/android/ru-RU/changelogs/3007.txt @@ -0,0 +1,11 @@ +* добавлены раскладки: арабская Хиджаи, иврит 1452-2, хинди (фонетическая), даргинская (Урахи), байшахи, курдская +* обновлены некоторые раскладки +* реализована поддержка объединённых акцентов +* клавиша панели инструментов клавиатуры разделена +* добавлены всплывающие окна .com +* добавлена возможность выбора пользовательского шрифта +* добавлена настройка масштаба шрифта +* улучшено автоматическое переключение языков +* проведена переработка настроек +* добавлены настройки для более тонкой регулировки отступов клавиатуры, авто-пробела, автоисправления, цифрового ряда +* добавлены новые функции и исправления diff --git a/fastlane/metadata/android/ru-RU/changelogs/3008.txt b/fastlane/metadata/android/ru-RU/changelogs/3008.txt new file mode 100644 index 000000000..e10bf5b39 --- /dev/null +++ b/fastlane/metadata/android/ru-RU/changelogs/3008.txt @@ -0,0 +1,11 @@ +* добавлены раскладки: арабская Хиджаи, иврит 1452-2, хинди (фонетическая), даргинская (Урахи), байшахи, курдская +* обновлены некоторые раскладки +* реализована поддержка объединённых акцентов +* клавиша панели инструментов клавиатуры разделена +* добавлены всплывающие окна .com +* добавлена возможность выбора пользовательского шрифта +* добавлена настройка масштаба шрифта +* улучшено автоматическое переключение языков +* проведена переработка настроек +* добавлены настройки для более тонкой регулировки отступов клавиатуры, авто-пробела, автоисправления, цифрового ряда +* добавлены новые функции и исправления diff --git a/fastlane/metadata/android/ru-RU/changelogs/3100.txt b/fastlane/metadata/android/ru-RU/changelogs/3100.txt new file mode 100644 index 000000000..b85cca42e --- /dev/null +++ b/fastlane/metadata/android/ru-RU/changelogs/3100.txt @@ -0,0 +1,10 @@ +* при необходимости предлагаются названия установленных приложений +* возможность переключения категорий эмодзи с помощью свайпа +* отображение уведомления после восстановления из резервной копии +* увеличены кнопка и значок панели инструментов +* запятая теперь доступна во всплывающих окнах при отображении TLD +* добавлена настройка для выбора стандартного оттенка кожи эмодзи +* добавлены коды клавиш для левого и правого Alt и Ctrl +* добавлена метка клавиши "timestamp" для более удобного доступа к клавише временной метки +* реализовано распознавание специальных меток клавиш для всплывающих окон в простых раскладках +* мелкие исправления и улучшения diff --git a/fastlane/metadata/android/ru-RU/changelogs/3101.txt b/fastlane/metadata/android/ru-RU/changelogs/3101.txt new file mode 100644 index 000000000..7a9313620 --- /dev/null +++ b/fastlane/metadata/android/ru-RU/changelogs/3101.txt @@ -0,0 +1,9 @@ +* при необходимости предлагаются названия установленных приложений +* возможность переключения категорий эмодзи с помощью свайпа +* отображение уведомления после восстановления из резервной копии +* запятая теперь доступна во всплывающих окнах при отображении TLD +* добавлена настройка для выбора стандартного оттенка кожи эмодзи +* добавлены коды клавиш для левого и правого Alt и Ctrl +* добавлена метка клавиши "timestamp" для более удобного доступа к клавише временной метки +* реализовано распознавание специальных меток клавиш для всплывающих окон в простых раскладках +* мелкие исправления и улучшения diff --git a/fastlane/metadata/android/ru-RU/full_description.txt b/fastlane/metadata/android/ru-RU/full_description.txt index 80c31b125..8d9c085e1 100644 --- a/fastlane/metadata/android/ru-RU/full_description.txt +++ b/fastlane/metadata/android/ru-RU/full_description.txt @@ -15,11 +15,12 @@ HeliBoard это клавиатура с открытым исходным ко
      • Может следовать динамическим цветам для Android 12+
    • Настроить раскладки клавиатуры (доступно только при отключении использования системных языков)
    • +
    • Настроить специальные расскладки такие как, символьная, числовая, или функциональная раскладка
    • Многоязычный набор текста
    • Скользящий ввод текста (только с закрытой библиотекой ☹️)
      • Библиотека не включена в приложение, поскольку не совместима с открытым исходным кодом.
      • -
      • Можно извлечь из пакетов GApps (swypelibs) или загрузить здесь
      • +
      • Можно извлечь из пакетов GApps (swypelibs) или загрузить здесь (нажмите на файле на маленькую кнопку Скачать)
    • История буфера обмена
    • Режим одной руки
    • diff --git a/gradle.properties b/gradle.properties index 0a59d79e3..11b104c21 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,2 +1,3 @@ android.useAndroidX=true -org.gradle.jvmargs=-Xmx1024m \ No newline at end of file +org.gradle.configuration-cache=true +org.gradle.jvmargs=-Xmx1024m diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index d64cd4917..2c3521197 100755 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 68e8816d7..eb1a55be0 100755 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionSha256Sum=d725d707bfabd4dfdc958c624003b3c80accc03f7037b5122c4b1d0ef15cecab -distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip +distributionSha256Sum=f397b287023acdba1e9f6fc5ea72d22dd63669d59ed4a289a29b1a76eee151c6 +distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index 1aa94a426..f5feea6d6 100755 --- a/gradlew +++ b/gradlew @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -55,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -84,7 +86,8 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum diff --git a/gradlew.bat b/gradlew.bat index 7101f8e46..9b42019c7 100755 --- a/gradlew.bat +++ b/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## diff --git a/layouts.md b/layouts.md index 2af0f5624..d03b20f98 100644 --- a/layouts.md +++ b/layouts.md @@ -1,8 +1,8 @@ # A compilation of information about the layout formats usable in this app. There are two distinct formats: -* the _simple_ format is a text file with one key label per line, and two consecutive line breaks indicating a switch to the next row, [example](app/src/main/assets/layouts/qwerty.txt) -* the _json_ format taken from [FlorisBoard](https://github.com/florisboard/florisboard/blob/master/CONTRIBUTING.md#adding-the-layout), but only "normal" keys are supported (i.e. no action keys and similar), [example](app/src/main/assets/layouts/azerty.json) +* the _simple_ format is a text file with one key label per line, and two consecutive line breaks indicating a switch to the next row, [example](app/src/main/assets/layouts/main/qwerty.txt) +* the _json_ format taken from [FlorisBoard](https://github.com/florisboard/florisboard/blob/master/CONTRIBUTING.md#adding-the-layout), but only "normal" keys are supported (i.e. no action keys and similar), [example](app/src/main/assets/layouts/main/azerty.json) You can add both directly in the app, see the related [FAQ](https://github.com/Helium314/HeliBoard/wiki/Customization#layouts). @@ -34,7 +34,7 @@ If the layout has exactly 2 keys in the bottom row, these keys will replace comm * `text_key`: normal key, default * `auto_text_key`: used in FlorisBoard for a key that changes text case when shift is enabled, HeliBoard does that anyway unless disabled with a _labelFlag_ * `multi_text_key`: key with an array of code points, e.g. `{ "$": "multi_text_key", "codePoints": [2509, 2480], "label": "্র" }` - * there are also selector classes, which allow to change keys conditionally, see the [dvorak layout](https://github.com/Helium314/HeliBoard/blob/main/app/src/main/assets/layouts/dvorak.json) for an example: + * there are also selector classes, which allow to change keys conditionally, see the [dvorak layout](app/src/main/assets/layouts/main/dvorak.json) for an example: * `case_selector`: keys for `lower` and `upper` (both mandatory), similar to `shift_state_selector` * `shift_state_selector`: keys for `unshifted`, `shifted`, `shiftedManual`, `shiftedAutomatic`, `capsLock`, `manualOrLocked`, `default` (all optional) * `variation_selector`: keys for input types `datetime`, `time`, `date`, `password`, `normal`, `uri`, `email`, `default` (all optional) @@ -89,7 +89,7 @@ Usually the label is what is displayed on the key. However, there are some speci * _symbol_alpha_: toggle alpha / symbol keyboard * _numpad_: toggle numpad layout * _emoji_: switch to emoji view - * _com_: display common TLDs (.com and similar, currently not localized) + * _com_: display common TLDs (.com and similar, localized) * _language_switch_: language switch key * _action_: the action (enter) key * _delete_: delete key @@ -103,7 +103,7 @@ Usually the label is what is displayed on the key. However, there are some speci * In case a label clashes with text you want to add, put a `\` in front of the text you want, e.g. `\space` will write the label `space` instead of adding a space bar. * Note that you need to escape the `\` in json files by adding a second `\`. * If you want different key label and input text, set the label to [label]|[text], e.g. `aa|bb` will show `aa`, but pressing the key will input `bb`. -You can also specify special key codes like `a|!code/key_action_previous`, but it's cleaner to use a json layout and specify the code explicitly. Note that when specifying a code in the label, and a code in a json layout, the code in the label will be ignored. +You can also specify special key codes like `a|!code/key_action_previous` or `abc|!code/-10043`, but it's cleaner to use a json layout and specify the code explicitly. Note that when specifying a code in the label, and a code in a json layout, the code in the label will be ignored. * It's also possible to specify an icon, like `!icon/previous_key|!code/key_action_previous`. * You can find available icon names in [KeyboardIconsSet](/app/src/main/java/helium314/keyboard/keyboard/internal/KeyboardIconsSet.kt). You can also use toolbar key icons using the uppercase name of the [toolbar key](/app/src/main/java/helium314/keyboard/latin/utils/ToolbarUtils.kt#L109), e.g. `!icon/redo` @@ -122,10 +122,10 @@ You can also specify special key codes like `a|!code/key_action_previous`, but i * Use `%` to mark all preceding keys as "_Language (important)_" instead. Keys after `%` will still be in the "_Language_" group. * The `punctuation` key is typically the period key. `popup_keys` set here override the default. * `[labels]` may contain non-default labels for the following keys `symbol`, `alphabet`, `shift_symbol`, `shift_symbol_tablet`, `comma`, `period`, `question` - * `[number_row]` may contain a custom number row (1-9 and 0 separated by space). You should also add the language to `numberRowLocales` in [`PreferencesSettingsFragment`](app/src/main/java/helium314/keyboard/latin/settings/PreferencesSettingsFragment.java) so the user can opt into having a localized number row. + * `[number_row]` may contain a custom number row (1-9 and 0 separated by space). * `[extra_keys]` are typically keys shown in the default layout of the language. This is currently only used for latin layouts to avoid duplicating layouts for just adding few keys on the right side. The layout name need to end with `+`, but the `+` is removed when looking up the actual layout. * If you add a new language for which Android does not have a display name, it will be displayed using the language tag - * Avoiding this currently is more complicated than necessary: add the language tag to [LocaleUtils.getLocaleDisplayNameInSystemLocale](/app/src/main/java/helium314/keyboard/latin/common/LocaleUtils.kt#L181) to have an exception, and add a string named `subtype_` to [`strings.xml`](/app/src/main/res/values/strings.xml). Further you may need to add a `subtype_in_root_locale_` to [donottranslate.xml](/app/src/main/res/values/donottranslate.xml), and add the language tag to `subtype_locale_exception_keys` and `subtype_locale_displayed_in_root_locale`. + * To fix this, add the language to [`strings.xml`](/app/src/main/res/values/strings.xml) (common names are `subtype_`), and then in [LocaleUtils.localizedDisplayName](/app/src/main/java/helium314/keyboard/latin/common/LocaleUtils.kt#L179) add an `overrideRedId` for the language tag. For overriding the language name displayed on space bar, you need to add the language tag to `subtype_locale_displayed_in_root_locale`, and the name to `subtype_locale_displayed_in_root_locale_display_names` in [donottranslate.xml](/app/src/main/res/values/donottranslate.xml). * If a newly added language does not use latin script, please update the default scripts method `Locale.script` in [ScriptUtils](app/src/main/java/helium314/keyboard/latin/utils/ScriptUtils.kt) ## Functional key layouts diff --git a/tools/make-emoji-keys/build.gradle b/tools/make-emoji-keys/build.gradle index dde20660e..c621ce362 100644 --- a/tools/make-emoji-keys/build.gradle +++ b/tools/make-emoji-keys/build.gradle @@ -19,13 +19,13 @@ jar { task makeEmoji(type: JavaExec, dependsOn: ['jar']) { main = '-jar' args jar.archiveFile.get() - args '-res' + args '-assets' args project.rootProject.project('app').projectDir.path + File.separator + 'src' + - File.separator + 'main' + File.separator + 'res' + File.separator + 'main' + File.separator + 'assets' + File.separator + 'emoji' } dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib:2.0.21" + implementation "org.jetbrains.kotlin:kotlin-stdlib:2.1.10" } java { diff --git a/tools/make-emoji-keys/src/main/kotlin/com/majeur/inputmethod/tools/emoji/EmojiCategoriesResource.kt b/tools/make-emoji-keys/src/main/kotlin/com/majeur/inputmethod/tools/emoji/EmojiCategoriesResource.kt deleted file mode 100644 index 223a93a92..000000000 --- a/tools/make-emoji-keys/src/main/kotlin/com/majeur/inputmethod/tools/emoji/EmojiCategoriesResource.kt +++ /dev/null @@ -1,155 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-only - -package com.majeur.inputmethod.tools.emoji - -import com.majeur.inputmethod.tools.emoji.model.EmojiData -import com.majeur.inputmethod.tools.emoji.model.EmojiGroup -import java.io.* -import java.nio.charset.Charset -import java.util.jar.JarFile - -class EmojiCategoriesResource(private val jarFile: JarFile) { - - fun writeToAndroidRes(outDir: String?, emojiData: EmojiData, supportData: Map) { - val template = JarUtils.getAndroidResTemplateResource(jarFile) - val resourceDir = template.substring(0, template.lastIndexOf('/')) - var ps: PrintStream? = null - var lnr: LineNumberReader? = null - try { - ps = if (outDir == null) { - System.out - } else { - val outDir = File(outDir, resourceDir) - val outputFile = File(outDir, - ANDROID_RES_TEMPLATE.replace(".tmpl", ".xml")) - outDir.mkdirs() - println("Building android resource file into ${outputFile.absoluteFile}") - PrintStream(outputFile, Charset.forName("UTF-8")) - } - lnr = LineNumberReader(InputStreamReader(JarUtils.openResource(template), Charset.forName("UTF-8"))) - inflateTemplate(lnr, ps!!, emojiData, supportData) - } catch (e: IOException) { - throw RuntimeException(e) - } finally { - JarUtils.close(lnr) - JarUtils.close(ps) - } - } - - @Throws(IOException::class) - private fun inflateTemplate(reader: LineNumberReader, out: PrintStream, - emojis: EmojiData, supportData: Map) { - reader.lines().forEach { - when { - it.contains(MARK_UNICODE_VER) -> - out.println(it.replace(MARK_UNICODE_VER, emojis.unicodeVersion)) - it.contains(MARK_API_LEVEL) -> - out.println(it.replace(MARK_API_LEVEL, supportData.values.maxOrNull().toString())) - it.contains(MARK_SMILEYS_AND_EMOTION) -> - dumpEmojiSpecs(out, emojis, supportData,EmojiGroup.SMILEYS_AND_EMOTION) - it.contains(MARK_PEOPLE_AND_BODY) -> - dumpEmojiSpecs(out, emojis, supportData,EmojiGroup.PEOPLE_AND_BODY) - it.contains(MARK_ANIMALS_AND_NATURE) -> - dumpEmojiSpecs(out, emojis, supportData,EmojiGroup.ANIMALS_AND_NATURE) - it.contains(MARK_FOOD_AND_DRINK) -> - dumpEmojiSpecs(out, emojis, supportData,EmojiGroup.FOOD_AND_DRINK) - it.contains(MARK_TRAVEL_AND_PLACES) -> - dumpEmojiSpecs(out, emojis, supportData,EmojiGroup.TRAVEL_AND_PLACES) - it.contains(MARK_ACTIVITIES) -> - dumpEmojiSpecs(out, emojis, supportData,EmojiGroup.ACTIVITIES) - it.contains(MARK_OBJECTS) -> - dumpEmojiSpecs(out, emojis, supportData,EmojiGroup.OBJECTS) - it.contains(MARK_SYMBOLS) -> - dumpEmojiSpecs(out, emojis, supportData,EmojiGroup.SYMBOLS) - it.contains(MARK_FLAGS) -> - dumpEmojiSpecs(out, emojis, supportData,EmojiGroup.FLAGS) - it.contains(MARK_PEOPLE_AND_BODY_MORE) -> - dumpEmojiSpecsVariant(out, emojis, supportData,EmojiGroup.PEOPLE_AND_BODY) - else -> out.println(it) - } - } - } - - private fun dumpEmojiSpecs(out: PrintStream, emojiData: EmojiData, supportData: Map, - group: EmojiGroup) { - emojiData[group].forEach { emoji -> - val minApi = getMinApi(emoji.codes, supportData) - if (minApi < 0) { - // We have no clue of which android version supports this emoji, - // so we ignore it. - printCompatNotFound(emoji.codes) - return@forEach - } - val text = makeEmojiKey(emoji.codes, minApi) - out.println(" $text") - } - } - - private fun dumpEmojiSpecsVariant(out: PrintStream, emojiData: EmojiData, supportData: Map, - group: EmojiGroup) { - emojiData[group].forEach { baseEmoji -> - val minApi = getMinApi(baseEmoji.codes, supportData) - if (minApi < 0) { - // Same thing, we already encountered it when dumping base emoji, - // ignoring this one silently. - return@forEach - } - - val text = baseEmoji.variants.filter { emoji -> - if (getMinApi(emoji.codes, supportData) < 0) { - // Again - printCompatNotFound(emoji.codes) - return@filter false - } - true - }.map { emoji -> - // Not very efficient, minApi is accessed twice, - // but hey, we are making tooling here - makeEmojiKey(emoji.codes, getMinApi(emoji.codes, supportData)) - }.filter { key -> - key.isNotBlank() - }.joinToString(separator = ";") - - if (text.isNotBlank()) out.println(" $text") - else out.println(" ") - } - } - - private fun makeEmojiKey(codes: IntArray, minApi: Int): String { - val cps = codes - .joinToString(separator = ",") { - it.toString(radix = 16) - .uppercase() - } - return if (minApi > 21) "$cps||$minApi" else cps - } - - private fun getMinApi(codes: IntArray, supportData: Map): Int { - val hash = codes - .joinToString(separator = "") - .hashCode() - return supportData[hash] ?: -1 - } - - private fun printCompatNotFound(codes: IntArray) { - val formattedCps = codes.joinToString(" ") { "U+" + it.toString(radix = 16).uppercase() } - println(" - No android compatibility found for emoji $formattedCps, ignoring...") - } - - companion object { - private const val ANDROID_RES_TEMPLATE = "emoji-categories.tmpl" - private const val MARK_UNICODE_VER = "@UNICODE_VERSION@" - private const val MARK_API_LEVEL = "@ANDROID_API_LEVEL@" - private const val MARK_SMILEYS_AND_EMOTION = "@SMILEYS_AND_EMOTION@" - private const val MARK_PEOPLE_AND_BODY = "@PEOPLE_AND_BODY@" - private const val MARK_PEOPLE_AND_BODY_MORE = "@PEOPLE_AND_BODY MORE@" - private const val MARK_ANIMALS_AND_NATURE = "@ANIMALS_AND_NATURE@" - private const val MARK_FOOD_AND_DRINK = "@FOOD_AND_DRINKS@" - private const val MARK_TRAVEL_AND_PLACES = "@TRAVEL_AND_PLACES@" - private const val MARK_ACTIVITIES = "@ACTIVITIES@" - private const val MARK_OBJECTS = "@OBJECTS@" - private const val MARK_SYMBOLS = "@SYMBOLS@" - private const val MARK_FLAGS = "@FLAGS@" - } - -} \ No newline at end of file diff --git a/tools/make-emoji-keys/src/main/kotlin/com/majeur/inputmethod/tools/emoji/MakeEmojiKeys.kt b/tools/make-emoji-keys/src/main/kotlin/com/majeur/inputmethod/tools/emoji/MakeEmojiKeys.kt index 7dd2975af..f76223a63 100644 --- a/tools/make-emoji-keys/src/main/kotlin/com/majeur/inputmethod/tools/emoji/MakeEmojiKeys.kt +++ b/tools/make-emoji-keys/src/main/kotlin/com/majeur/inputmethod/tools/emoji/MakeEmojiKeys.kt @@ -2,6 +2,11 @@ package com.majeur.inputmethod.tools.emoji +import com.majeur.inputmethod.tools.emoji.model.EmojiData +import com.majeur.inputmethod.tools.emoji.model.EmojiGroup +import com.majeur.inputmethod.tools.emoji.model.EmojiSpec +import java.io.File +import java.nio.charset.Charset import java.util.* import kotlin.system.exitProcess @@ -9,9 +14,9 @@ class MakeEmojiKeys { class Options(argsArray: Array) { - private val OPTION_RES = "-res" + private val OPTION_ASSETS = "-assets" - var resPath: String? = null + var assetPath: String? = null init { val args = listOf(*argsArray).toMutableList() @@ -19,8 +24,8 @@ class MakeEmojiKeys { try { while (args.isNotEmpty()) { arg = args.removeFirst() - if (arg == OPTION_RES) { - resPath = args.removeFirst() + if (arg == OPTION_ASSETS) { + assetPath = args.removeFirst() } else { usage("Unknown option: $arg") } @@ -32,7 +37,7 @@ class MakeEmojiKeys { fun usage(message: String?) { message?.let { System.err.println(it) } - System.err.println("usage: make-emoji-keys $OPTION_RES ") + System.err.println("usage: make-emoji-keys $OPTION_ASSETS ") exitProcess(1) } } @@ -51,8 +56,52 @@ class MakeEmojiKeys { parser2.parse(JarUtils.getEmojiSupportResource(jar)) val supportData = parser2.getParsedData() - EmojiCategoriesResource(jar).writeToAndroidRes(options.resPath, emojis, supportData) + if (options.assetPath != null) { + writeMinApiLevels(options.assetPath!!, emojis, supportData) + writeEmojis(options.assetPath!!, emojis) + } } + private fun writeMinApiLevels(outDir: String, emojiData: EmojiData, supportData: Map) { + val minApiLevels = mutableMapOf>() + fun addMinLevel(emoji: EmojiSpec) { + val minApi = getMinApi(emoji.codes, supportData) + if (minApi < 0) + throw Exception("unknown min SDK for ${emoji.name}") + if (minApi > 21) + minApiLevels.getOrPut(minApi) { mutableSetOf() }.add(emoji.text) + } + + EmojiGroup.entries.filterNot { it == EmojiGroup.COMPONENT }.forEach { group -> + emojiData[group].forEach { emoji -> + addMinLevel(emoji) + emoji.variants.forEach { addMinLevel(it) } + } + } + if (minApiLevels.any { it.value.any { it.contains(" ") } }) + throw Exception("emoji contains space") + val text = minApiLevels.map { "${it.key} ${it.value.joinToString(" ")}" } + .sorted().joinToString("\n") + File(outDir, "minApi.txt").writeText(text, Charset.forName("UTF-8")) + } + + private fun writeEmojis(outDir: String, emojiData: EmojiData) { + // each category gets a file, one main emoji per line, followed by popups + EmojiGroup.entries.filterNot { it == EmojiGroup.COMPONENT } + .forEach { writeEmojiGroup(File(outDir, it.name + ".txt"), emojiData[it]) } + } + + private fun writeEmojiGroup(outFile: File, emojis: List) { + val text = emojis.map { emoji -> + if (emoji.variants.isEmpty()) emoji.text + else "${emoji.text} ${emoji.variants.joinToString(" ") { it.text }}" + }.joinToString("\n") + outFile.writeText(text, Charset.forName("UTF-8")) + } + + private fun getMinApi(codes: IntArray, supportData: Map): Int { + val hash = codes.joinToString("").hashCode() + return supportData[hash] ?: -1 + } } } \ No newline at end of file diff --git a/tools/make-emoji-keys/src/main/kotlin/com/majeur/inputmethod/tools/emoji/model/EmojiData.kt b/tools/make-emoji-keys/src/main/kotlin/com/majeur/inputmethod/tools/emoji/model/EmojiData.kt index 48636a364..e8fe8f868 100644 --- a/tools/make-emoji-keys/src/main/kotlin/com/majeur/inputmethod/tools/emoji/model/EmojiData.kt +++ b/tools/make-emoji-keys/src/main/kotlin/com/majeur/inputmethod/tools/emoji/model/EmojiData.kt @@ -2,6 +2,8 @@ package com.majeur.inputmethod.tools.emoji.model +import kotlin.collections.mutableSetOf + class EmojiData { var unicodeVersion = "" @@ -61,25 +63,21 @@ class EmojiData { insertEmoji(group, intArrayOf(CP_REGIONAL_INDICATOR_SYMBOL_LETTER_Z), 2.0f, "regional indicator symbol letter z") } - if (hasMultipleSkinModifiers(emoji.codes)) { - // For now Openboard implementation is not robust enough to handle such complicated sequences. - // Emoji palettes get polluted with too much emoji variations, so we'll ignore them. - return false - } - - return true + // Some multi-skin-tone variants use a different base code than their non-multi-skin-tone counterparts, + // so they don't get grouped. We drop them here, to prevent each variant from being displayed separately. + return ! hasMultipleSkinModifiers(emoji.codes) } private fun hasMultipleSkinModifiers(codes: IntArray): Boolean { - var count = 0 + val tones = mutableSetOf() codes.forEach { when (it) { CP_LIGHT_SKIN_TONE, CP_MEDIUM_LIGHT_SKIN_TONE, CP_MEDIUM_SKIN_TONE, CP_MEDIUM_DARK_SKIN_TONE, CP_DARK_SKIN_TONE -> - count += 1 + tones.add(it) } } - return count > 1 + return tones.size > 1 } private fun onEmojiVariantInserted(group: EmojiGroup, baseSpec: EmojiSpec, emojiSpec: EmojiSpec): Boolean { @@ -99,25 +97,24 @@ class EmojiData { val baseCodePoints3 = emoji.codes.toMutableList() .apply { set(emoji.codes.indexOf(componentCode), CP_VARIANT_SELECTOR) }.toIntArray() - val base = emojiGroups[group]?.firstOrNull { it.codes contentEquals baseCodePoints } - ?: emojiGroups[group]?.firstOrNull { it.codes contentEquals baseCodePoints2 } - ?: emojiGroups[group]?.firstOrNull { it.codes contentEquals baseCodePoints3 } - - // We keep track the component modifier of this emoji - if (base != null) emoji.component = componentCode - - return base + return emojiGroups[group]?.firstOrNull { it.codes contentEquals baseCodePoints } + ?: emojiGroups[group]?.firstOrNull { it.codes contentEquals baseCodePoints2 } + ?: emojiGroups[group]?.firstOrNull { it.codes contentEquals baseCodePoints3 } } private fun withoutComponentCodes(codes: IntArray) : Pair { + var res = codes + var tone = CP_NUL codes.forEach { code -> when (code) { CP_LIGHT_SKIN_TONE, CP_MEDIUM_LIGHT_SKIN_TONE, CP_MEDIUM_SKIN_TONE, - CP_MEDIUM_DARK_SKIN_TONE, CP_DARK_SKIN_TONE -> - return codes.asList().minus(code).toIntArray() to code + CP_MEDIUM_DARK_SKIN_TONE, CP_DARK_SKIN_TONE -> { + res = res.asList().minus(code).toIntArray() + tone = code + } } } - return codes to CP_NUL + return res to tone } companion object { @@ -169,4 +166,4 @@ class EmojiData { } -} \ No newline at end of file +} diff --git a/tools/make-emoji-keys/src/main/kotlin/com/majeur/inputmethod/tools/emoji/model/EmojiSpec.kt b/tools/make-emoji-keys/src/main/kotlin/com/majeur/inputmethod/tools/emoji/model/EmojiSpec.kt index 7c892a25e..f0081b2f5 100644 --- a/tools/make-emoji-keys/src/main/kotlin/com/majeur/inputmethod/tools/emoji/model/EmojiSpec.kt +++ b/tools/make-emoji-keys/src/main/kotlin/com/majeur/inputmethod/tools/emoji/model/EmojiSpec.kt @@ -2,12 +2,8 @@ package com.majeur.inputmethod.tools.emoji.model -import com.majeur.inputmethod.tools.emoji.model.EmojiData.Companion.CP_NUL - data class EmojiSpec(val codes: IntArray, val unicodeVer: Float, val name: String) { - var component = CP_NUL - val variants by lazy { mutableListOf() } override fun toString() = name @@ -19,5 +15,7 @@ data class EmojiSpec(val codes: IntArray, val unicodeVer: Float, val name: Strin return codes contentEquals other.codes } + val text get() = codes.joinToString("") { Character.toString(it) } + override fun hashCode() = codes.contentHashCode() -} \ No newline at end of file +} diff --git a/tools/make-emoji-keys/src/main/resources/values/emoji-categories.tmpl b/tools/make-emoji-keys/src/main/resources/values/emoji-categories.tmpl deleted file mode 100644 index 8e04989d8..000000000 --- a/tools/make-emoji-keys/src/main/resources/values/emoji-categories.tmpl +++ /dev/null @@ -1,132 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 30 - 31 - - - - :-) - ;-) - :-( - :-! - :-$ - B-) - =-O - :-P - :O - :-* - :-D - :\'( - :-\\ - O:-) - :-[ - (╯° - □°) - ╯︵ - ┻━┻ - ¯\\_ - (ツ) - _/¯ - ┬─┬ - ︵ /( - .□.\\ - - - - diff --git a/tools/release.py b/tools/release.py index 783dfbeea..daadc0aa5 100755 --- a/tools/release.py +++ b/tools/release.py @@ -65,25 +65,21 @@ def update_dict_list(): for line in lines: line = line.strip() if line.startswith("#"): - if line == "# Dictionaries": - mode = 1 - elif line == "# Experimental dictionaries": - mode = 2 - else: - mode = 0 - if mode == 0 or not line.startswith("*"): + mode = 0 + if line.startswith("# Dictionaries"): + mode = 1 + if mode == 0 or not line.startswith("|") or line.startswith("| Language |") or line.startswith("| --- |"): continue - dict_name = line.split("]")[1].split("(")[1].split(")")[0].split("/")[-1].split(".dict")[0] + split = line.split("|") + dict_name = split[2].split("]")[1].split("(")[1].split(")")[0].split("/")[-1].split(".dict")[0] (dict_type, locale) = dict_name.split("_", 1) if "_" in locale: sp = locale.split("_") locale = sp[0] for s in sp[1:]: locale = locale + "_" + s.upper() - if mode == 2: - dicts.append(f"{dict_type},{locale},exp\n") - else: - dicts.append(f"{dict_type},{locale},\n") + exp = "exp" if split[3].strip() == "yes" else "" + dicts.append(f"{dict_type},{locale},{exp}\n") target_file = "app/src/main/assets/dictionaries_in_dict_repo.csv" with open(target_file, 'w') as f: f.writelines(dicts)