chore(windows): Merge branch 'master' into chore/windows-setup-notes

This commit is contained in:
Marc Durdin 2021-11-29 16:09:36 +11:00
commit e296eb8a67
318 changed files with 22852 additions and 4292 deletions

View file

@ -1,5 +1,6 @@
[flake8]
max-line-length = 120
indent-size = 2
ignore =
E402, # module level import not at top of file
W504, # line break after binary operator

3
.gitignore vendored
View file

@ -108,6 +108,9 @@
# /engine/keyman32/
/windows/src/engine/keyman32/Keyman32.opensdf
/windows/src/engine/keyman32/*.obj
/windows/src/engine/keyman32/*.cod
/windows/src/engine/keyman32/*.pdb
# /engine/keymanx64/
/windows/src/engine/keymanx64/x64

View file

@ -50,7 +50,7 @@ This project and everyone participating in it is governed by the [Keyman Code of
Keyman is a complex project that spans six different platforms, with many a variety of components on each platform. We have chosen to host the Keyman project in the [keymanapp/keyman](https://github.com/keymanapp/keyman) monorepo, but [keyboard layouts](https://github.com/keymanapp/keyboards) and [lexical models](https://github.com/keymanapp/lexical-models) are stored in their own repositories.
* Issues relating to the Keyman apps and their interactions with operating systems or other apps should be opened in the Keyman repo
* For keyboard-specific or model-specific issues, open issues in the corresponding respository.
* For keyboard-specific or model-specific issues, open issues in the corresponding repository.
* The Keyman websites are also hosted in their own repositories. Contributions, including issues and pull requests can be opened against these repositories also.
* Product documentation for the Keyman app is hosted in the Keyman app repository, and replicated to the help.keyman.com repository.
@ -216,7 +216,7 @@ The labels are loosely grouped by their purpose, but it's not required that ever
| `feat` | [search][search-feat] | Feature requests. |
| `bug` | [search][search-bug] | Confirmed bugs or reports that are very likely to be bugs. |
| `chore` | [search][search-chore] | Minor updates to Keyman. |
| `question` | [search][search-question] | Questions more than bug reports or feature requests (e.g. how do I do X). [**Usually better on the Keyman Community**][https://community.software.sil.org/c/keyman] |
| `question` | [search][search-question] | Questions more than bug reports or feature requests (e.g. how do I do X). [**Usually better on the Keyman Community**](https://community.software.sil.org/c/keyman) |
| `spec` | [search][search-spec] | Issues which are specifications for a large scale feature. |
| `docs` | [search][search-docs] | Related to any type of documentation. |

View file

@ -1,5 +1,141 @@
# Keyman Version History
## 15.0.156 alpha 2021-11-26
* fix(windows): fix loadkeyboardoptions core memory error (#5959)
## 15.0.155 alpha 2021-11-24
* fix(web): reset scroll anchor on touchend (#5919)
* fix(web): shorten setFocusTimer() (#5946)
* fix(web): clear longpress timeout if user does a flick up (#5952)
## 15.0.154 alpha 2021-11-22
* fix(web): simplify hide transition (#5910)
* fix(web): inline osk keytip position (#5938)
* feat(mac): i18n, support localization of Keyman for Mac (#5869)
* chore(linux): Remove unused test methods (#5954)
* chore(linux): Run ibus-keyman tests as part of the build (#5889)
## 15.0.153 alpha 2021-11-20
* fix(web): resolve unhandled exception in promise (#5902)
## 15.0.152 alpha 2021-11-19
* fix(common/core): Update decxstr to check all characters while decrementing (#5842)
## 15.0.151 alpha 2021-11-18
* fix(developer): use correct tike icon (#5925)
* fix(android/engine): Support for U_xxxx_yyyy subkeys (#5913)
* fix(mac): use xcframework to support m1 (#5933)
* fix(developer): move web osk beneath text area (#5937)
## 15.0.150 alpha 2021-11-17
* fix(web): remove canvas use for iOS compatibility (#5915)
## 15.0.149 alpha 2021-11-17
* chore(developer): Update jszip version (#5770)
* chore(common): Check in crowdin strings for Fulfulde Nigeria (#5841)
## 15.0.148 alpha 2021-11-16
* chore(common): Check in crowdin strings for Mandara (Wandala) (#5857)
* chore(linux): Update method comments (#5883)
## 15.0.147 alpha 2021-11-15
* chore(android,linux,windows): Check in crowdin strings for Bura-Pabir (#5839)
* chore: add keyman-local.com to iis https setup (#5892)
* fix(web): avoid error if timerid not valid (#5908)
## 15.0.146 alpha 2021-11-14
* feat(developer): support for U_xxxx_yyyy (#5894)
## 15.0.145 alpha 2021-11-13
* fix(developer): crash exporting OSK on European keyboard (#5893)
* feat(developer): validate .kps files during compile (#5895)
## 15.0.144 alpha 2021-11-12
* fix(android/engine): Truncate language name in list (#5878)
* fix(android/app): Check KMP file exists before attempting to extract (#5849)
* fix(web): Check parent element is defined before assigning (#5874)
* fix(android/app): Revert test code (#5899)
## 15.0.143 alpha 2021-11-11
* fix(developer): handle shortcut keys in debugger (#5776)
## 15.0.142 alpha 2021-11-08
* chore(linux): Cleanup (#5886)
* chore(linux): cleanup defunct tests (#5885)
* chore(linux): fix failing ibus-keyman tests (#5884)
## 15.0.141 alpha 2021-11-05
* chore(linux): Add integration tests for ibus-keyman (#5881)
## 15.0.140 alpha 2021-11-03
* feat(android): Allow uninstall of sil_euro_latin keyboard (#5838)
* chore(common/core): Compile test keyboards to .kmp (#5864)
## 15.0.139 alpha 2021-11-02
* chore(common/core): refactor kmx unit tests (#5862)
* chore(linux): Extract keycode_to_vk[] to separate header file (#5863)
## 15.0.138 alpha 2021-10-29
* chore(linux): Set correct version number on ibus component (#5859)
* chore(common/core): generate kmp.json (#5860)
## 15.0.137 alpha 2021-10-28
* chore(common): Don't check for conventional commit for fixups (#5858)
## 15.0.136 alpha 2021-10-23
* chore(android/engine): Address globe key TODO (#5836)
## 15.0.135 alpha 2021-10-20
* docs(windows): add note to caps-lock-stores test (#5837)
## 15.0.134 alpha 2021-10-19
* docs(windows): add install apps from anywhere instructions (#5829)
## 15.0.133 alpha 2021-10-16
* chore(common): Check in crowdin strings for Hausa (#5768)
## 15.0.132 alpha 2021-10-15
* feat(windows): manual keyboard caps tests (#5808)
## 15.0.131 alpha 2021-10-13
* chore(windows): Add obj cod and pdb to gitignore (#5826)
## 15.0.130 alpha 2021-10-11
* fix(common/core): incxstr checks all character while incrementing (#5712)
## 15.0.129 alpha 2021-10-08
* chore: Create CODE_OF_CONDUCT.md (#5819)
* chore: Add CONTRIBUTING documentation (#5821)
* chore: Add link to SIL (#5823)
## 15.0.128 alpha 2021-10-07
* fix(ios): move sentry settings responsibility to build agent (#5805)

View file

@ -26,3 +26,4 @@ Keyman is an open source project distributed under the [MIT license](LICENSE.md)
* [Keyboards](https://keyman.com/keyboards)
* [Documentation](https://help.keyman.com/)
* [Online Keyboard](https://keymanweb.com/)
* [SIL Language Technology - software.sil.org](https://software.sil.org/)

View file

@ -1 +1 @@
15.0.129
15.0.157

View file

@ -32,6 +32,7 @@ import com.tavultesoft.kmea.KMHelpFileActivity;
import com.tavultesoft.kmea.KMManager;
import com.tavultesoft.kmea.KMKeyboardDownloaderActivity;
import com.tavultesoft.kmea.data.Keyboard;
import com.tavultesoft.kmea.data.KeyboardController;
import com.tavultesoft.kmea.util.FileUtils;
import com.tavultesoft.kmea.util.FileProviderUtils;
import com.tavultesoft.kmea.util.KMLog;
@ -113,9 +114,8 @@ public final class KeyboardSettingsActivity extends AppCompatActivity {
hashMap.put(iconKey, icon);
infoList.add(hashMap);
// If not default keyboard, display uninstall keyboard
if (!(kbID.equalsIgnoreCase(KMManager.KMDefault_KeyboardID) &&
languageID.equalsIgnoreCase(KMManager.KMDefault_LanguageID))) {
// As long as more than 1 keyboard installed, display uninstall keyboard
if (KeyboardController.getInstance().get().size() > 1 && KMManager.canRemoveKeyboard()) {
hashMap = new HashMap<>();
hashMap.put(titleKey, getString(R.string.uninstall_keyboard));
hashMap.put(subtitleKey, "");

View file

@ -65,6 +65,11 @@ public class PackageActivity extends AppCompatActivity implements
Bundle bundle = getIntent().getExtras();
if (bundle != null) {
kmpFile = new File(bundle.getString("kmpFile"));
if (!kmpFile.exists()) {
KMLog.LogError(TAG, kmpFile.getAbsolutePath() + " not found. Unable to extract");
showErrorToast(context, getString(R.string.failed_to_extract));
return;
}
installMode = (KmpInstallMode) bundle.getSerializable("installMode");
if(installMode == null) installMode = KmpInstallMode.Full;
lastInstallMode = installMode;
@ -230,6 +235,7 @@ public class PackageActivity extends AppCompatActivity implements
setResult(1);
cleanup();
finish();
MainActivity.cleanupPackageInstall();
}
/**

View file

@ -0,0 +1,154 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Context: Menu Action -->
<string name="action_share" comment="Menu action to send text content to another app">Tǝra</string>
<!-- Context: Menu Action -->
<string name="action_web" comment="Menu action to open Keyman browser">Web Brauza</string>
<!-- Context: Menu Action -->
<string name="action_text_size" comment="Menu action to adjust text size">Olkur Rubutu</string>
<!-- Context: Menu Action -->
<string name="action_overflow" comment="Show additional menu items">Na damwa</string>
<!-- Context: Menu Action -->
<string name="action_clear_text" comment="Menu action to erase text">Cicimta Rubutu</string>
<!-- Context: Menu Action -->
<string name="action_info" comment="Menu action to display Keyman help page">Labar</string>
<!-- Context: Menu Action -->
<string name="action_settings" comment="Menu action to open Settings menu">Setiyeri</string>
<!-- Context: Menu Action -->
<string name="action_install_updates" comment="Menu notification that keyboard or dictionary updates available">Hara instal ar su na bǝlin</string>
<!-- Context: Title -->
<string name="title_version" comment="Title of Keyman for Android version">Jili: %1$s</string>
<!-- Context: Text label when old Chrome version installed -->
<string name="text_require_chrome_57" comment="Banner text when old version of Chrome is installed"> Keyman akwa bara jili ar Chrome version 57 wala na bǝlinari.</string>
<!-- Context: Button label -->
<string name="button_update_chrome" comment="Prompt to upgrade Chrome in the Play Store">Jaktǝ bǝlinkur ar Chrome</string>
<!-- Context: Textfield prompt (&#8230; is the ellipsis character "...") -->
<string name="textview_hint" comment="Prompt to start typing">Balditǝ hara taipin azi&#8230;</string>
<!-- Context: Splash screen (version/copyright info currently disabled -->
<!-- Context: Splash screen (version/copyright info currently disabled -->
<!-- Context: Text Size dialog -->
<string name="text_size" comment="Current text size (number)">Olkur rubutu: %1$d</string>
<!-- Context: Text Size dialog -->
<string name="ic_text_size_up" comment="Make text bigger">Jaktǝ olkur rubutu</string>
<!-- Context: Text Size dialog -->
<string name="ic_text_size_down" comment="Make text smaller">Kǝmta olkur rubutu</string>
<!-- Context: Clear Text dialog -->
<string name="all_text_will_be_cleared" comment="Erase all the text">\nShanga rubutuni mda ata cijimta ɗa\n</string>
<!-- Context: Get Started menu -->
<string name="get_started" comment="Menu for getting started">Baɗita kulini</string>
<!-- Context: Get Started menu -->
<string name="add_a_keyboard" comment="Menu item to add a keyboard">Jaktǝ keyboard na ar hulfur mnya nga</string>
<!-- Context: Get Started menu -->
<string name="enable_system_keyboard" comment="Menu item to enable Keyman as system keyboard">Vu ka Keyman nzi keyboard na ar shanga sistem ni</string>
<!-- Context: Get Started menu -->
<string name="set_keyman_as_default" comment="Menu item to set Keyman as default system keyboard">Hara seti ar Keyman katsa nzi default keyboard nga</string>
<!-- Context: Get Started menu -->
<string name="more_info" comment="Open the Keyman for Android help page">Labar na damwa</string>
<!-- Context: Get Started menu -->
<string name="show_get_started" comment="Show the &quot;Get Started&quot; menu on startup">Ncangtǝ \"%1$s\" sakatǝ akwa kǝladzi</string>
<!-- Context: Android Storage Permission -->
<string name="request_storage_permission" comment="Request storage permission to access keyboard packages"> Kamnyar hara instal ar keyboard packajyeri, zhar Keyman katsa wutǝ su na akwa sur ɗuwa labar na aɗi akwa na\'ura ni wa.</string>
<!-- Context: Android Storage Permission -->
<string name="storage_permission_denied" comment="Keyboard package installation may fail since Android storage permission not granted"> Mdǝkǝ ngkatǝ bara wutǝ su na akwa sur ɗuwa su. Ata tsoktǝ ngǝla ka instal keyboard package</string>
<!-- Context: Keyman Settings menu -->
<string name="keyman_settings" comment="Settings menu title">Setiyeri</string>
<!-- Context: Keyman Settings menu -->
<plurals name="installed_languages">
<item quantity="one">Hulfur mnya natǝ mdǝ hara Instal ɗa (%1$d)</item>
<item quantity="other">Hulfur mnya natǝ mdǝ hara Instal ɗa (%1$d)</item>
</plurals>
<!-- Context: Keyman Settings menu -->
<string name="install_keyboard_or_dictionary" comment="Menu item to install keyboard or dictionary">Hara instal ar Keyboard wal Dictionary</string>
<!-- Context: Keyman Settings menu -->
<string name="change_display_language" comment="Menu action to change interface language">Ncangtǝ hulfur mnya</string>
<!-- Context: Keyman Settings menu -->
<string name="adjust_keyboard_height" comment="Menu action to adjust keyboard height">Jakta wala kǝmta saɓǝlkur keyboard</string>
<!-- Context: Keyman Settings menu -->
<string name="spacebar_caption" comment="Menu action to set the spacebar caption">Rubutu na ar Spesba</string>
<!-- Context: Keyman Settings menu / Spacebar caption -->
<string name="spacebar_caption_keyboard" comment="Spacebar caption option - keyboard">Keyboard</string>
<!-- Context: Keyman Settings menu / Spacebar caption -->
<string name="spacebar_caption_language" comment="Spacebar caption option - language">Hulfur mnya</string>
<!-- Context: Keyman Settings menu / Spacebar caption -->
<string name="spacebar_caption_language_keyboard" comment="Spacebar caption option - language + keyboard">Hulfur mnya + Keyboard</string>
<!-- Context: Keyman Settings menu / Spacebar caption -->
<string name="spacebar_caption_blank" comment="Spacebar caption option - blank">Kula rubutu ata</string>
<!-- Context: Keyman Settings menu / Spacebar caption hint -->
<string name="spacebar_caption_hint_keyboard" comment="Spacebar caption hint - keyboard">Ncangtǝ thlǝma keyboard ni ata spesba</string>
<!-- Context: Keyman Settings menu / Spacebar caption hint -->
<string name="spacebar_caption_hint_language" comment="Spacebar caption hint - language">Ncangtǝ thlǝma hulfur mnya ni ata spesba</string>
<!-- Context: Keyman Settings menu / Spacebar caption hint -->
<string name="spacebar_caption_hint_language_keyboard" comment="Spacebar caption hint - language + keyboard">Ncantǝ thlǝma hulfur mnya ka keyboard ni ata spesba</string>
<!-- Context: Keyman Settings menu / Spacebar caption hint -->
<string name="spacebar_caption_hint_blank" comment="Spacebar caption hint - blank">Aɗe ncangtǝ rubutǝni ata spesba wa</string>
<!-- Context: Keyman Settings menu -->
<string name="show_banner" comment="text suggestions banner">Kǝlara saka kara ncangtǝ banner</string>
<!-- Context: Keyman Settings menu -->
<string name="show_banner_on" comment="Description when toggle is on">Mda ata sǝ hara kǝthlǝr kari</string>
<!-- Context: Keyman Settings menu -->
<string name="show_banner_off" comment="Description when toggle is off">Ma tsi-tsiyari, mda ata ncangta saka tǝ mdǝ vu ka tsa predictive text hara</string>
<!-- Context: Keyman Settings menu -->
<string name="show_send_crash_report" comment="permission for sending crash reports">Zhari ka thleng labar ar suna hili atar netwok</string>
<!-- Context: Keyman Settings menu -->
<string name="show_send_crash_report_on" comment="Description when toggle is on">Ma kǝla-kǝlari, mda ata thleng labar suna hili</string>
<!-- Context: Keyman Settings menu -->
<string name="show_send_crash_report_off" comment="Description when toggle is off">Ma tsi-tsiyari, labar suna hili mda aɗeta thlenga wa</string>
<!-- Context: Keyman Settings "Install Keyboard or Dictionary" menu -->
<string name="install_from_keyman_dot_com" comment="Install package from Keyman server">Hara instal ni akwa keyman.com</string>
<!-- Context: Keyman Settings "Install Keyboard or Dictionary" menu -->
<string name="install_from_local_file" comment="Install package file from local device">Hara instal ni akwa fail natǝ gǝ ɗuwari</string>
<!-- Context: Keyman Settings "Install Keyboard or Dictionary" menu -->
<string name="install_from_other_device" comment="Scan QR Code">Hara instal akwa na\'ura na damwa</string>
<!-- Context: Keyman Settings "Install Keyboard or Dictionary" menu -->
<string name="add_languages_to_installed_keyboard" comment="Install additional languages from a keyboard package">Jaktǝ hulfur mnyayeri kamnyar hara instal ar keyboard</string>
<!-- Context: Keyman Settings "Install Keyboard or Dictionary" menu -->
<string name="add_language_subtext" comment="Additional information for adding another language">(akwa package ar keyboard)</string>
<!-- Context: Select Package and Select Languages menu -->
<string name="title_select_keyboard_package_list" comment="Select a keyboard package to add languages">Carɓǝla Keyboard Package</string>
<!-- Context: Select Package and Select Languages menu -->
<string name="title_select_languages_for_package" comment="Select language names from the keyboard package">Carɓǝla hulfur mnyayeri ala %1$s</string>
<!-- Context: Select Package and Select Languages menu -->
<string name="added_language_to_keyboard" comment="Notification that a language name is added to a keyboard">Hulfur mnya natǝ mdǝ jakta %1$s ka mzhitǝ %2$s</string>
<!-- Context: Select Package and Select Languages menu -->
<string name="all_languages_installed" comment="Text when all languages from a keyboard package have been installed">Hulfur mnyayeri natǝ mdǝku kurtǝ ka hara instal ɗa</string>
<!-- Context: Adjust Keyboard Height menu -->
<string name="drag_the_keyboard" comment="First line of adjusting keyboard height">Ndǝkǝr keyboard kamnyar jaktǝ wala kǝmta saɓǝlkur ni</string>
<!-- Context: Adjust Keyboard Height menu -->
<string name="rotate_the_device" comment="Second line of adjusting keyboard height">Shinar waya wala hansetu ni kamnyar katsa nzi thlat-thlata wala peri-periari</string>
<!-- Context: Adjust Keyboard Height menu -->
<string name="reset_to_defaults" comment="Button to reset to default heights">Kalaktǝni katsa ni tsu apa tǝ mdǝ nam ni</string>
<!-- Context: Keyman Web Browser -->
<string name="hint_text" comment="Prompt to type in the browser search bar">Paka wala hara taip ar URL</string>
<!-- Context: Keyman Web Browser -->
<string name="title_bookmarks" comment="Title for bookmarks">Bukmakyeri</string>
<!-- Context: Keyman Web Browser -->
<string name="no_bookmarks" comment="Text when bookmark list is empty">Bukmakyeri aɗiwa</string>
<!-- Context: Keyman Web Browser -->
<string name="add_bookmark" comment="Confirmation to add bookmark">Jaktǝ Bukmak</string>
<!-- Context: Keyman Web Browser -->
<string name="hint_title" comment="Page title for saved bookmark">Kǝra ndǝr</string>
<!-- Context: Keyman Web Browser -->
<string name="hint_url" comment="Page URL for saved bookmark">Url</string>
<!-- Context: KMP Package strings -->
<string name="title_package_failed_to_install" comment="Error dialog title when package failed to install">Instal ar Package %1$s aɗi hara wa</string>
<!-- Context: KMP Package strings -->
<string name="downloading_keyboard_package" comment="Confirmation to download keyboard package filename">Akwa hara Download ar keyboard package\n%1$s&#8230;</string>
<!-- Context: KMP Package strings -->
<string name="failed_to_extract" comment="Notification that keyboard package failed to unzip">Ngǝla ta kǝsǝɓǝla</string>
<!-- Context: KMP Package strings -->
<string name="install_keyboard_package" comment="Title to install keyboard package">Hara istal ar Keyboard</string>
<!-- Context: KMP Package strings -->
<string name="install_predictive_text_package" comment="Title to install dictionary package">Hara instal ar Dictionary</string>
<!-- Context: KMP Package strings -->
<string name="not_valid_package_file" comment="Notification when invalid package file cannot be installed">%1$s aɗi package fayil ar Keyman na jiri wa.\n%2$s\"</string>
<!-- Context: KMP Package strings -->
<string name="no_new_touch_keyboards_to_install" comment="Notification when no touch-optimized keyboards can be installed">Keyboard Package aɗika keyboardyeri natǝ mdǝ nama katsa kǝthlǝ mdǝ tsukwa ka tsi natǝ mda ata hara instal ni</string>
<!-- Context: KMP Package strings -->
<string name="no_new_predictive_text_to_install" comment="Notification when no dictionaries can be installed">Predictive text na bǝlin aɗiwa natǝ mda ata hara instal ni</string>
<!-- Context: KMP Package strings -->
<string name="no_targets_to_install" comment="Notification when a package doesn't contain keyboards or dictionaries">Keyboardyeri wala predictive text aɗiwa natǝ mda ata hara instal ɗa</string>
<!-- Context: KMP Package strings -->
<string name="no_associated_languages" comment="Notification when a keyboard package doesn't contain languages">Keyboard package aɗika hulfur mnyayeri natǝ kǝ kǝɓa kari natǝ mda ata hara instal wa</string>
<!-- Context: KMP Package strings -->
<string name="invalid_metadata" comment="kmp.json metadata file is invalid or missing in package">Metadata aɗi kalkal wa/ku sha akwa package</string>
</resources>

View file

@ -0,0 +1,154 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Context: Menu Action -->
<string name="action_share" comment="Menu action to send text content to another app">Sendu</string>
<!-- Context: Menu Action -->
<string name="action_web" comment="Menu action to open Keyman browser">Lenguru burawza</string>
<!-- Context: Menu Action -->
<string name="action_text_size" comment="Menu action to adjust text size">Maunugo ɓaleeri</string>
<!-- Context: Menu Action -->
<string name="action_overflow" comment="Show additional menu items">Ɓeddaari</string>
<!-- Context: Menu Action -->
<string name="action_clear_text" comment="Menu action to erase text">Woggu ɓaleeri</string>
<!-- Context: Menu Action -->
<string name="action_info" comment="Menu action to display Keyman help page">Bayanu</string>
<!-- Context: Menu Action -->
<string name="action_settings" comment="Menu action to open Settings menu">Wo`innol</string>
<!-- Context: Menu Action -->
<string name="action_install_updates" comment="Menu notification that keyboard or dictionary updates available">Kesitiggo</string>
<!-- Context: Title -->
<string name="title_version" comment="Title of Keyman for Android version">Nonde: %1$s</string>
<!-- Context: Text label when old Chrome version installed -->
<string name="text_require_chrome_57" comment="Banner text when old version of Chrome is installed">Keyman ɗo mari haaje nonde Chrome 57 ko ko ɓuri kestiggo.</string>
<!-- Context: Button label -->
<string name="button_update_chrome" comment="Prompt to upgrade Chrome in the Play Store">Kesitu Chrome</string>
<!-- Context: Textfield prompt (&#8230; is the ellipsis character "...") -->
<string name="textview_hint" comment="Prompt to start typing">Fuɗɗu windugo haa ɗow&#8230;</string>
<!-- Context: Splash screen (version/copyright info currently disabled -->
<!-- Context: Splash screen (version/copyright info currently disabled -->
<!-- Context: Text Size dialog -->
<string name="text_size" comment="Current text size (number)">Mawnugo ɓaleeri: %1$d</string>
<!-- Context: Text Size dialog -->
<string name="ic_text_size_up" comment="Make text bigger">Mawnugo ɓaleeri dow</string>
<!-- Context: Text Size dialog -->
<string name="ic_text_size_down" comment="Make text smaller">Mawnugo ɓaleeri les</string>
<!-- Context: Clear Text dialog -->
<string name="all_text_will_be_cleared" comment="Erase all the text">\nBindi man fuu woggan\n</string>
<!-- Context: Get Started menu -->
<string name="get_started" comment="Menu for getting started">Fuɗɗu</string>
<!-- Context: Get Started menu -->
<string name="add_a_keyboard" comment="Menu item to add a keyboard">Waatu kibod jee ɗemngal ma</string>
<!-- Context: Get Started menu -->
<string name="enable_system_keyboard" comment="Menu item to enable Keyman as system keyboard">Waatu Keyman dow kibod komputa</string>
<!-- Context: Get Started menu -->
<string name="set_keyman_as_default" comment="Menu item to set Keyman as default system keyboard">Waatu Keyman dow kibod a` naftirta</string>
<!-- Context: Get Started menu -->
<string name="more_info" comment="Open the Keyman for Android help page">Ɓeddol bayanu</string>
<!-- Context: Get Started menu -->
<string name="show_get_started" comment="Show the &quot;Get Started&quot; menu on startup">Hollu \"%1$s\" dow fuɗɗoode</string>
<!-- Context: Android Storage Permission -->
<string name="request_storage_permission" comment="Request storage permission to access keyboard packages"> Ngam a` waata kuuje kibod, accu laawol Keyman jannga kuuje resol jee yaasi.</string>
<!-- Context: Android Storage Permission -->
<string name="storage_permission_denied" comment="Keyboard package installation may fail since Android storage permission not granted"> Laawol babal resugo sali. Salan resugo kuuje kibod</string>
<!-- Context: Keyman Settings menu -->
<string name="keyman_settings" comment="Settings menu title">Wo`innol</string>
<!-- Context: Keyman Settings menu -->
<plurals name="installed_languages">
<item quantity="one">Installed languages (%1$d)</item>
<item quantity="other">Installed languages (%1$d)</item>
</plurals>
<!-- Context: Keyman Settings menu -->
<string name="install_keyboard_or_dictionary" comment="Menu item to install keyboard or dictionary">Wa`unu Kibod ko bo deftere ma`ana</string>
<!-- Context: Keyman Settings menu -->
<string name="change_display_language" comment="Menu action to change interface language">Hollu ɗemngal</string>
<!-- Context: Keyman Settings menu -->
<string name="adjust_keyboard_height" comment="Menu action to adjust keyboard height">A` wo`inna juutugo kibod</string>
<!-- Context: Keyman Settings menu -->
<string name="spacebar_caption" comment="Menu action to set the spacebar caption">Kapshon tappirɗe babal</string>
<!-- Context: Keyman Settings menu / Spacebar caption -->
<string name="spacebar_caption_keyboard" comment="Spacebar caption option - keyboard">Kibod</string>
<!-- Context: Keyman Settings menu / Spacebar caption -->
<string name="spacebar_caption_language" comment="Spacebar caption option - language">Ɗemngal</string>
<!-- Context: Keyman Settings menu / Spacebar caption -->
<string name="spacebar_caption_language_keyboard" comment="Spacebar caption option - language + keyboard">Ɗemngal + Kibod</string>
<!-- Context: Keyman Settings menu / Spacebar caption -->
<string name="spacebar_caption_blank" comment="Spacebar caption option - blank">Walaa kooɗume</string>
<!-- Context: Keyman Settings menu / Spacebar caption hint -->
<string name="spacebar_caption_hint_keyboard" comment="Spacebar caption hint - keyboard">Hollu inde kibod ha tappirɗe babal</string>
<!-- Context: Keyman Settings menu / Spacebar caption hint -->
<string name="spacebar_caption_hint_language" comment="Spacebar caption hint - language">Hollu inde ɗemngal haa tappirɗe babal</string>
<!-- Context: Keyman Settings menu / Spacebar caption hint -->
<string name="spacebar_caption_hint_language_keyboard" comment="Spacebar caption hint - language + keyboard">Ɗemngal bee kibod dow tappirɗe babal</string>
<!-- Context: Keyman Settings menu / Spacebar caption hint -->
<string name="spacebar_caption_hint_blank" comment="Spacebar caption hint - blank">Taa hollu kapshon dow tappirɗe babal</string>
<!-- Context: Keyman Settings menu -->
<string name="show_banner" comment="text suggestions banner">Koonday holla bana</string>
<!-- Context: Keyman Settings menu -->
<string name="show_banner_on" comment="Description when toggle is on">Ɗum waɗan</string>
<!-- Context: Keyman Settings menu -->
<string name="show_banner_off" comment="Description when toggle is off">To ɗo nyifi, holla tan to ɓaleere sappol hokkaama</string>
<!-- Context: Keyman Settings menu -->
<string name="show_send_crash_report" comment="permission for sending crash reports">Koonday fuu yaara wullandu wonnugo dow netwok</string>
<!-- Context: Keyman Settings menu -->
<string name="show_send_crash_report_on" comment="Description when toggle is on">To ɗo maɓɓiti, wullandu wonnugo yerɓan</string>
<!-- Context: Keyman Settings menu -->
<string name="show_send_crash_report_off" comment="Description when toggle is off">To ɗo nyifi, wullandu wonnugo yerɓataake</string>
<!-- Context: Keyman Settings "Install Keyboard or Dictionary" menu -->
<string name="install_from_keyman_dot_com" comment="Install package from Keyman server">A` wa`inna diga dow keyman.com</string>
<!-- Context: Keyman Settings "Install Keyboard or Dictionary" menu -->
<string name="install_from_local_file" comment="Install package file from local device">A` wa`inna dow fayel nder komputa</string>
<!-- Context: Keyman Settings "Install Keyboard or Dictionary" menu -->
<string name="install_from_other_device" comment="Scan QR Code">A` wa`inna diga na`ura feere</string>
<!-- Context: Keyman Settings "Install Keyboard or Dictionary" menu -->
<string name="add_languages_to_installed_keyboard" comment="Install additional languages from a keyboard package">A` waata ɗemngal ngam a` wa`inna kibod</string>
<!-- Context: Keyman Settings "Install Keyboard or Dictionary" menu -->
<string name="add_language_subtext" comment="Additional information for adding another language">(Diga kuuje kibod)</string>
<!-- Context: Select Package and Select Languages menu -->
<string name="title_select_keyboard_package_list" comment="Select a keyboard package to add languages">A` supta kuuje Kibod</string>
<!-- Context: Select Package and Select Languages menu -->
<string name="title_select_languages_for_package" comment="Select language names from the keyboard package">A` supta ɗemngal jee %1$s</string>
<!-- Context: Select Package and Select Languages menu -->
<string name="added_language_to_keyboard" comment="Notification that a language name is added to a keyboard">Ɗemngal ko wa`inni %1$s yahugo %2$s</string>
<!-- Context: Select Package and Select Languages menu -->
<string name="all_languages_installed" comment="Text when all languages from a keyboard package have been installed">Ɗemngal man fuu arti wa`inni</string>
<!-- Context: Adjust Keyboard Height menu -->
<string name="drag_the_keyboard" comment="First line of adjusting keyboard height">Dasa kibod man ngam de`itina juutugo</string>
<!-- Context: Adjust Keyboard Height menu -->
<string name="rotate_the_device" comment="Second line of adjusting keyboard height">Waylutu na`ura man ngam a` de`itina dow bee les</string>
<!-- Context: Adjust Keyboard Height menu -->
<string name="reset_to_defaults" comment="Button to reset to default heights">Lornu ɗum ko naftirta tum</string>
<!-- Context: Keyman Web Browser -->
<string name="hint_text" comment="Prompt to type in the browser search bar">A` tefa ko a` winda URL</string>
<!-- Context: Keyman Web Browser -->
<string name="title_bookmarks" comment="Title for bookmarks">Bukmaks</string>
<!-- Context: Keyman Web Browser -->
<string name="no_bookmarks" comment="Text when bookmark list is empty">Walaa Bukmaks</string>
<!-- Context: Keyman Web Browser -->
<string name="add_bookmark" comment="Confirmation to add bookmark">A` waata Bukmak</string>
<!-- Context: Keyman Web Browser -->
<string name="hint_title" comment="Page title for saved bookmark">Inde</string>
<!-- Context: Keyman Web Browser -->
<string name="hint_url" comment="Page URL for saved bookmark">Url</string>
<!-- Context: KMP Package strings -->
<string name="title_package_failed_to_install" comment="Error dialog title when package failed to install">Kuuje man %1$s saldori wa`ugo</string>
<!-- Context: KMP Package strings -->
<string name="downloading_keyboard_package" comment="Confirmation to download keyboard package filename">Jippina kuuje kibod\n%1$s&#8230;</string>
<!-- Context: KMP Package strings -->
<string name="failed_to_extract" comment="Notification that keyboard package failed to unzip">Saldori nastingo</string>
<!-- Context: KMP Package strings -->
<string name="install_keyboard_package" comment="Title to install keyboard package">Wa`unu kibod</string>
<!-- Context: KMP Package strings -->
<string name="install_predictive_text_package" comment="Title to install dictionary package">Wa`unu deftere ma`ana kalimaji</string>
<!-- Context: KMP Package strings -->
<string name="not_valid_package_file" comment="Notification when invalid package file cannot be installed">%1$s naaɗum kuuje fayel Keyman boɗɗum ba.\n%2$s\"</string>
<!-- Context: KMP Package strings -->
<string name="no_new_touch_keyboards_to_install" comment="Notification when no touch-optimized keyboards can be installed">Kuuje kibod walaa ko meema waɗu optimaizin kibod ngam wa`a</string>
<!-- Context: KMP Package strings -->
<string name="no_new_predictive_text_to_install" comment="Notification when no dictionaries can be installed">Walaa ɓaleere kesum ko wa`inta</string>
<!-- Context: KMP Package strings -->
<string name="no_targets_to_install" comment="Notification when a package doesn't contain keyboards or dictionaries">Walaa kibod ko ɓaleere ko wa`inta</string>
<!-- Context: KMP Package strings -->
<string name="no_associated_languages" comment="Notification when a keyboard package doesn't contain languages">Kibod walaa ɗemngal feere ko wondi man ngam wa`inna</string>
<!-- Context: KMP Package strings -->
<string name="invalid_metadata" comment="kmp.json metadata file is invalid or missing in package">Naa ɗum dayday/metadata man majji nder pakej</string>
</resources>

View file

@ -0,0 +1,154 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Context: Menu Action -->
<string name="action_share" comment="Menu action to send text content to another app">Raba</string>
<!-- Context: Menu Action -->
<string name="action_web" comment="Menu action to open Keyman browser">Manhajar binciko abubuwa a yanar gizo</string>
<!-- Context: Menu Action -->
<string name="action_text_size" comment="Menu action to adjust text size">Girman rubutu</string>
<!-- Context: Menu Action -->
<string name="action_overflow" comment="Show additional menu items">Ƙari</string>
<!-- Context: Menu Action -->
<string name="action_clear_text" comment="Menu action to erase text">Goge Rubutu</string>
<!-- Context: Menu Action -->
<string name="action_info" comment="Menu action to display Keyman help page">Bayani</string>
<!-- Context: Menu Action -->
<string name="action_settings" comment="Menu action to open Settings menu">Saiti</string>
<!-- Context: Menu Action -->
<string name="action_install_updates" comment="Menu notification that keyboard or dictionary updates available">Shigar da Sabuntawa</string>
<!-- Context: Title -->
<string name="title_version" comment="Title of Keyman for Android version">Nau\'i: %1$s</string>
<!-- Context: Text label when old Chrome version installed -->
<string name="text_require_chrome_57" comment="Banner text when old version of Chrome is installed">Keyman na buƙatar manhajar Chrome na\'ui na 57 ko sabuwa.</string>
<!-- Context: Button label -->
<string name="button_update_chrome" comment="Prompt to upgrade Chrome in the Play Store">Sabunta Chrome</string>
<!-- Context: Textfield prompt (&#8230; is the ellipsis character "...") -->
<string name="textview_hint" comment="Prompt to start typing">Fara rubutu anan&#8230;</string>
<!-- Context: Splash screen (version/copyright info currently disabled -->
<!-- Context: Splash screen (version/copyright info currently disabled -->
<!-- Context: Text Size dialog -->
<string name="text_size" comment="Current text size (number)">Girman Rubutu: %1$d</string>
<!-- Context: Text Size dialog -->
<string name="ic_text_size_up" comment="Make text bigger">Girman Rubutu sama</string>
<!-- Context: Text Size dialog -->
<string name="ic_text_size_down" comment="Make text smaller">Girman Rubutu ƙasa</string>
<!-- Context: Clear Text dialog -->
<string name="all_text_will_be_cleared" comment="Erase all the text">\nZa a goge dukkan rubutu\n</string>
<!-- Context: Get Started menu -->
<string name="get_started" comment="Menu for getting started">Farawa</string>
<!-- Context: Get Started menu -->
<string name="add_a_keyboard" comment="Menu item to add a keyboard">Saka madannan yarenka</string>
<!-- Context: Get Started menu -->
<string name="enable_system_keyboard" comment="Menu item to enable Keyman as system keyboard">Barin Keyman a matsayin madannin system-wide</string>
<!-- Context: Get Started menu -->
<string name="set_keyman_as_default" comment="Menu item to set Keyman as default system keyboard">Saita Keyman a matsayin madanni na zaɓi</string>
<!-- Context: Get Started menu -->
<string name="more_info" comment="Open the Keyman for Android help page">Ƙarin bayani</string>
<!-- Context: Get Started menu -->
<string name="show_get_started" comment="Show the &quot;Get Started&quot; menu on startup">Nuna \"%1$s\" farawa</string>
<!-- Context: Android Storage Permission -->
<string name="request_storage_permission" comment="Request storage permission to access keyboard packages">Domin shigar da ƙunshin madannin, a bari Keyman ya bayar da damar karanta ma\'adanar waje.</string>
<!-- Context: Android Storage Permission -->
<string name="storage_permission_denied" comment="Keyboard package installation may fail since Android storage permission not granted">Ba a sami damar izinin ajiya ba. Zai iya hana shigar da ƙunshin madannin</string>
<!-- Context: Keyman Settings menu -->
<string name="keyman_settings" comment="Settings menu title">Saiti</string>
<!-- Context: Keyman Settings menu -->
<plurals name="installed_languages">
<item quantity="one">Yarukan da aka shigar (%1$d)</item>
<item quantity="other">Yarukan da aka shigar (%1$d)</item>
</plurals>
<!-- Context: Keyman Settings menu -->
<string name="install_keyboard_or_dictionary" comment="Menu item to install keyboard or dictionary">Shigar da Madannin ko Ƙamus</string>
<!-- Context: Keyman Settings menu -->
<string name="change_display_language" comment="Menu action to change interface language">Yaren da ake amfani</string>
<!-- Context: Keyman Settings menu -->
<string name="adjust_keyboard_height" comment="Menu action to adjust keyboard height">Daidaita tsayin madannai</string>
<!-- Context: Keyman Settings menu -->
<string name="spacebar_caption" comment="Menu action to set the spacebar caption">Madannin bada tazara</string>
<!-- Context: Keyman Settings menu / Spacebar caption -->
<string name="spacebar_caption_keyboard" comment="Spacebar caption option - keyboard">Madanni</string>
<!-- Context: Keyman Settings menu / Spacebar caption -->
<string name="spacebar_caption_language" comment="Spacebar caption option - language">Yare</string>
<!-- Context: Keyman Settings menu / Spacebar caption -->
<string name="spacebar_caption_language_keyboard" comment="Spacebar caption option - language + keyboard">Yare + Madanni</string>
<!-- Context: Keyman Settings menu / Spacebar caption -->
<string name="spacebar_caption_blank" comment="Spacebar caption option - blank">Babu komai</string>
<!-- Context: Keyman Settings menu / Spacebar caption hint -->
<string name="spacebar_caption_hint_keyboard" comment="Spacebar caption hint - keyboard">Nuna sunan madanni akan madannin bada tazara</string>
<!-- Context: Keyman Settings menu / Spacebar caption hint -->
<string name="spacebar_caption_hint_language" comment="Spacebar caption hint - language">Nuna sunan yare akan madannin bada tazara</string>
<!-- Context: Keyman Settings menu / Spacebar caption hint -->
<string name="spacebar_caption_hint_language_keyboard" comment="Spacebar caption hint - language + keyboard">Yare da madannin kan madannin bada tazara</string>
<!-- Context: Keyman Settings menu / Spacebar caption hint -->
<string name="spacebar_caption_hint_blank" comment="Spacebar caption hint - blank">Kada a nuna komai akan madannin bada tazara</string>
<!-- Context: Keyman Settings menu -->
<string name="show_banner" comment="text suggestions banner">Nuna banner koyaushe</string>
<!-- Context: Keyman Settings menu -->
<string name="show_banner_on" comment="Description when toggle is on">Da za a aiwatar</string>
<!-- Context: Keyman Settings menu -->
<string name="show_banner_off" comment="Description when toggle is off">Idan a kashe, rubutun hasashe ne kaɗai za a iya gani</string>
<!-- Context: Keyman Settings menu -->
<string name="show_send_crash_report" comment="permission for sending crash reports">Bada izinin tura rahoton wata matsala kan yanar gizo</string>
<!-- Context: Keyman Settings menu -->
<string name="show_send_crash_report_on" comment="Description when toggle is on">Lokacin aka kunna, za a aika rahotannin matsalar</string>
<!-- Context: Keyman Settings menu -->
<string name="show_send_crash_report_off" comment="Description when toggle is off">Yayin da yake a kashe, ba za a iya aika rahotonnin matsalar ba</string>
<!-- Context: Keyman Settings "Install Keyboard or Dictionary" menu -->
<string name="install_from_keyman_dot_com" comment="Install package from Keyman server">Shigar daga keyman.com</string>
<!-- Context: Keyman Settings "Install Keyboard or Dictionary" menu -->
<string name="install_from_local_file" comment="Install package file from local device">Shigar daga lokal fayil</string>
<!-- Context: Keyman Settings "Install Keyboard or Dictionary" menu -->
<string name="install_from_other_device" comment="Scan QR Code">Shigar daga wata na\'urar</string>
<!-- Context: Keyman Settings "Install Keyboard or Dictionary" menu -->
<string name="add_languages_to_installed_keyboard" comment="Install additional languages from a keyboard package">Ƙara harsuna ga madannan da aka shigar</string>
<!-- Context: Keyman Settings "Install Keyboard or Dictionary" menu -->
<string name="add_language_subtext" comment="Additional information for adding another language">(daga ƙunshin madanni)</string>
<!-- Context: Select Package and Select Languages menu -->
<string name="title_select_keyboard_package_list" comment="Select a keyboard package to add languages">Zaɓi Ƙunshin Madanni</string>
<!-- Context: Select Package and Select Languages menu -->
<string name="title_select_languages_for_package" comment="Select language names from the keyboard package">Zaɓi harsuna domin %1$s</string>
<!-- Context: Select Package and Select Languages menu -->
<string name="added_language_to_keyboard" comment="Notification that a language name is added to a keyboard">An ƙara harshe %1$s zuwa %2$s</string>
<!-- Context: Select Package and Select Languages menu -->
<string name="all_languages_installed" comment="Text when all languages from a keyboard package have been installed">An riga da an shigar da dukkanin yarukan</string>
<!-- Context: Adjust Keyboard Height menu -->
<string name="drag_the_keyboard" comment="First line of adjusting keyboard height">Danne madanni domin sake girman</string>
<!-- Context: Adjust Keyboard Height menu -->
<string name="rotate_the_device" comment="Second line of adjusting keyboard height">Juya na\'urar domin daidaita hoto da gyara shi</string>
<!-- Context: Adjust Keyboard Height menu -->
<string name="reset_to_defaults" comment="Button to reset to default heights">Gyara saiti zuwa yadda ya dace</string>
<!-- Context: Keyman Web Browser -->
<string name="hint_text" comment="Prompt to type in the browser search bar">Bincika ko rubuta URL</string>
<!-- Context: Keyman Web Browser -->
<string name="title_bookmarks" comment="Title for bookmarks">Alamomi</string>
<!-- Context: Keyman Web Browser -->
<string name="no_bookmarks" comment="Text when bookmark list is empty">Babu alamomi</string>
<!-- Context: Keyman Web Browser -->
<string name="add_bookmark" comment="Confirmation to add bookmark">Sanya alama</string>
<!-- Context: Keyman Web Browser -->
<string name="hint_title" comment="Page title for saved bookmark">Suna</string>
<!-- Context: Keyman Web Browser -->
<string name="hint_url" comment="Page URL for saved bookmark">Url</string>
<!-- Context: KMP Package strings -->
<string name="title_package_failed_to_install" comment="Error dialog title when package failed to install">An kasa shigar da %1$s ƙunshin</string>
<!-- Context: KMP Package strings -->
<string name="downloading_keyboard_package" comment="Confirmation to download keyboard package filename">Saukar da ƙunshin madanni \n%1$s&#8230;</string>
<!-- Context: KMP Package strings -->
<string name="failed_to_extract" comment="Notification that keyboard package failed to unzip">An kasa cirewa</string>
<!-- Context: KMP Package strings -->
<string name="install_keyboard_package" comment="Title to install keyboard package">Shigar da madanni</string>
<!-- Context: KMP Package strings -->
<string name="install_predictive_text_package" comment="Title to install dictionary package">Shigar da Ƙamus</string>
<!-- Context: KMP Package strings -->
<string name="not_valid_package_file" comment="Notification when invalid package file cannot be installed">%1$s ƙunshin fayil ɗin Keyman ba mai inganci bane.\n%2$s\"</string>
<!-- Context: KMP Package strings -->
<string name="no_new_touch_keyboards_to_install" comment="Notification when no touch-optimized keyboards can be installed">Ƙunshin madannin ba shi da ingantaccen wajen taɓa madannan da aka inganta da za a shigar</string>
<!-- Context: KMP Package strings -->
<string name="no_new_predictive_text_to_install" comment="Notification when no dictionaries can be installed">Babu wani sabon rubutun hasashe da aka shigar</string>
<!-- Context: KMP Package strings -->
<string name="no_targets_to_install" comment="Notification when a package doesn't contain keyboards or dictionaries">Babu madannai ko rubutun hasashe da aka shigar</string>
<!-- Context: KMP Package strings -->
<string name="no_associated_languages" comment="Notification when a keyboard package doesn't contain languages">Ƙunshin madannan bashi da wani yaren da ke da alaƙa da za a shigar</string>
<!-- Context: KMP Package strings -->
<string name="invalid_metadata" comment="kmp.json metadata file is invalid or missing in package">Rasa inagancin/ɓacewar metadata cikin ƙunshin</string>
</resources>

View file

@ -0,0 +1,154 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Context: Menu Action -->
<string name="action_share" comment="Menu action to send text content to another app">Digahe</string>
<!-- Context: Menu Action -->
<string name="action_web" comment="Menu action to open Keyman browser">Web Browser</string>
<!-- Context: Menu Action -->
<string name="action_text_size" comment="Menu action to adjust text size">Ƴaikire Text</string>
<!-- Context: Menu Action -->
<string name="action_overflow" comment="Show additional menu items">Farfe adaliya</string>
<!-- Context: Menu Action -->
<string name="action_clear_text" comment="Menu action to erase text">Gaggahe Text</string>
<!-- Context: Menu Action -->
<string name="action_info" comment="Menu action to display Keyman help page">Labare</string>
<!-- Context: Menu Action -->
<string name="action_settings" comment="Menu action to open Settings menu">Saitine</string>
<!-- Context: Menu Action -->
<string name="action_install_updates" comment="Menu notification that keyboard or dictionary updates available">Femhe Updates</string>
<!-- Context: Title -->
<string name="title_version" comment="Title of Keyman for Android version">Version: %1$s</string>
<!-- Context: Text label when old Chrome version installed -->
<string name="text_require_chrome_57" comment="Banner text when old version of Chrome is installed"> Keyman requires Chrome version 57 mtu daula ne.</string>
<!-- Context: Button label -->
<string name="button_update_chrome" comment="Prompt to upgrade Chrome in the Play Store">Maga Update Chrome</string>
<!-- Context: Textfield prompt (&#8230; is the ellipsis character "...") -->
<string name="textview_hint" comment="Prompt to start typing">Fantuhe vinda ahuna&#8230;</string>
<!-- Context: Splash screen (version/copyright info currently disabled -->
<!-- Context: Splash screen (version/copyright info currently disabled -->
<!-- Context: Text Size dialog -->
<string name="text_size" comment="Current text size (number)">Ƴaikire Text: %1$d</string>
<!-- Context: Text Size dialog -->
<string name="ic_text_size_up" comment="Make text bigger">Ƴaikire Text at irane</string>
<!-- Context: Text Size dialog -->
<string name="ic_text_size_down" comment="Make text smaller">Ƴaikire Text am ɗyilane</string>
<!-- Context: Clear Text dialog -->
<string name="all_text_will_be_cleared" comment="Erase all the text">\nBaɗumma text a de gagga nde\n</string>
<!-- Context: Get Started menu -->
<string name="get_started" comment="Menu for getting started">Fantuhe</string>
<!-- Context: Get Started menu -->
<string name="add_a_keyboard" comment="Menu item to add a keyboard">Farfe keyboard gé naza nare ŋa</string>
<!-- Context: Get Started menu -->
<string name="enable_system_keyboard" comment="Menu item to enable Keyman as system keyboard">Magave Keyman gé system-wide keyboard</string>
<!-- Context: Get Started menu -->
<string name="set_keyman_as_default" comment="Menu item to set Keyman as default system keyboard">Magahe saitin Keyman gé default keyboard</string>
<!-- Context: Get Started menu -->
<string name="more_info" comment="Open the Keyman for Android help page">Farfe labare adaliya</string>
<!-- Context: Get Started menu -->
<string name="show_get_started" comment="Show the &quot;Get Started&quot; menu on startup">Mara \"%1$s\" at fantuhe ne</string>
<!-- Context: Android Storage Permission -->
<string name="request_storage_permission" comment="Request storage permission to access keyboard packages">Gé femhe keyboard pakeji, ɗyanɗya Keyman permission gé magahe karatu external storage.</string>
<!-- Context: Android Storage Permission -->
<string name="storage_permission_denied" comment="Keyboard package installation may fail since Android storage permission not granted"> Storage permission magavka. Matake a de magavka femhe keyboard pakeji ŋanna</string>
<!-- Context: Keyman Settings menu -->
<string name="keyman_settings" comment="Settings menu title">Saitine</string>
<!-- Context: Keyman Settings menu -->
<plurals name="installed_languages">
<item quantity="one">Naraha na an fa na (%1$d)</item>
<item quantity="other">Naraha na an fa na (%1$d)</item>
</plurals>
<!-- Context: Keyman Settings menu -->
<string name="install_keyboard_or_dictionary" comment="Menu item to install keyboard or dictionary">Femhe Keyboard mtu Dictionary</string>
<!-- Context: Keyman Settings menu -->
<string name="change_display_language" comment="Menu action to change interface language">Mara-nare</string>
<!-- Context: Keyman Settings menu -->
<string name="adjust_keyboard_height" comment="Menu action to adjust keyboard height">Mbeɗanahe tsa keyboard</string>
<!-- Context: Keyman Settings menu -->
<string name="spacebar_caption" comment="Menu action to set the spacebar caption">Spacebar caption</string>
<!-- Context: Keyman Settings menu / Spacebar caption -->
<string name="spacebar_caption_keyboard" comment="Spacebar caption option - keyboard">Keyboard</string>
<!-- Context: Keyman Settings menu / Spacebar caption -->
<string name="spacebar_caption_language" comment="Spacebar caption option - language">Nare</string>
<!-- Context: Keyman Settings menu / Spacebar caption -->
<string name="spacebar_caption_language_keyboard" comment="Spacebar caption option - language + keyboard">Nare + Keyboard</string>
<!-- Context: Keyman Settings menu / Spacebar caption -->
<string name="spacebar_caption_blank" comment="Spacebar caption option - blank">Blank</string>
<!-- Context: Keyman Settings menu / Spacebar caption hint -->
<string name="spacebar_caption_hint_keyboard" comment="Spacebar caption hint - keyboard">Mara zhera keyboard at spacebar</string>
<!-- Context: Keyman Settings menu / Spacebar caption hint -->
<string name="spacebar_caption_hint_language" comment="Spacebar caption hint - language">Mara zhera nare at spacebar</string>
<!-- Context: Keyman Settings menu / Spacebar caption hint -->
<string name="spacebar_caption_hint_language_keyboard" comment="Spacebar caption hint - language + keyboard">Nare antara keyboard at spacebar</string>
<!-- Context: Keyman Settings menu / Spacebar caption hint -->
<string name="spacebar_caption_hint_blank" comment="Spacebar caption hint - blank">Ɓáaka mara caption at spacebar</string>
<!-- Context: Keyman Settings menu -->
<string name="show_banner" comment="text suggestions banner">Ba kullume mam-mara banner</string>
<!-- Context: Keyman Settings menu -->
<string name="show_banner_on" comment="Description when toggle is on">Gé fantu maga slera anikwa</string>
<!-- Context: Keyman Settings menu -->
<string name="show_banner_off" comment="Description when toggle is off">Ma seke an já, a mara ba predictive text ŋane a magave</string>
<!-- Context: Keyman Settings menu -->
<string name="show_send_crash_report" comment="permission for sending crash reports">Ɓilana-ɓila basha jare badza aɗaba network</string>
<!-- Context: Keyman Settings menu -->
<string name="show_send_crash_report_on" comment="Description when toggle is on">Ma seke an kunna, anuga vela basha jare badza ŋanna</string>
<!-- Context: Keyman Settings menu -->
<string name="show_send_crash_report_off" comment="Description when toggle is off">Ma seke an já, ɓáaka vela basha jare badza ŋanna</string>
<!-- Context: Keyman Settings "Install Keyboard or Dictionary" menu -->
<string name="install_from_keyman_dot_com" comment="Install package from Keyman server">A femhe a sawam keyman.com</string>
<!-- Context: Keyman Settings "Install Keyboard or Dictionary" menu -->
<string name="install_from_local_file" comment="Install package file from local device">A femhe a sawam local file</string>
<!-- Context: Keyman Settings "Install Keyboard or Dictionary" menu -->
<string name="install_from_other_device" comment="Scan QR Code">A femhe a sawam umbulé gé nawura</string>
<!-- Context: Keyman Settings "Install Keyboard or Dictionary" menu -->
<string name="add_languages_to_installed_keyboard" comment="Install additional languages from a keyboard package">Farfe naraha gé femhe keyboard</string>
<!-- Context: Keyman Settings "Install Keyboard or Dictionary" menu -->
<string name="add_language_subtext" comment="Additional information for adding another language">(a sawam keyboard pakeji)</string>
<!-- Context: Select Package and Select Languages menu -->
<string name="title_select_keyboard_package_list" comment="Select a keyboard package to add languages">Ksa Keyboard Pakeji</string>
<!-- Context: Select Package and Select Languages menu -->
<string name="title_select_languages_for_package" comment="Select language names from the keyboard package">Ksa naraha gé %1$s</string>
<!-- Context: Select Package and Select Languages menu -->
<string name="added_language_to_keyboard" comment="Notification that a language name is added to a keyboard">Nare na farfe nde ŋanna %1$s to %2$s</string>
<!-- Context: Select Package and Select Languages menu -->
<string name="all_languages_installed" comment="Text when all languages from a keyboard package have been installed">Baɗumma naraha na an fa amikwa ŋanna</string>
<!-- Context: Adjust Keyboard Height menu -->
<string name="drag_the_keyboard" comment="First line of adjusting keyboard height">Piya keyboard gé fare tsa ne adaliya</string>
<!-- Context: Adjust Keyboard Height menu -->
<string name="rotate_the_device" comment="Second line of adjusting keyboard height">Mbeɗanahe nja nawura ŋanna gé portrait antara landscape</string>
<!-- Context: Adjust Keyboard Height menu -->
<string name="reset_to_defaults" comment="Button to reset to default heights">Reset to Defaults</string>
<!-- Context: Keyman Web Browser -->
<string name="hint_text" comment="Prompt to type in the browser search bar">Ɗatsa mtu vinda URL</string>
<!-- Context: Keyman Web Browser -->
<string name="title_bookmarks" comment="Title for bookmarks">Bookmarks</string>
<!-- Context: Keyman Web Browser -->
<string name="no_bookmarks" comment="Text when bookmark list is empty">Ɓáaka Bookmarks</string>
<!-- Context: Keyman Web Browser -->
<string name="add_bookmark" comment="Confirmation to add bookmark">Farfe Bookmark</string>
<!-- Context: Keyman Web Browser -->
<string name="hint_title" comment="Page title for saved bookmark">Irane gé duksá</string>
<!-- Context: Keyman Web Browser -->
<string name="hint_url" comment="Page URL for saved bookmark">Url</string>
<!-- Context: KMP Package strings -->
<string name="title_package_failed_to_install" comment="Error dialog title when package failed to install">Pakeji %1$s kwalla-kwale magave gé femhe</string>
<!-- Context: KMP Package strings -->
<string name="downloading_keyboard_package" comment="Confirmation to download keyboard package filename">Tsukwanahe keyboard pakeji\n%1$s&#8230;</string>
<!-- Context: KMP Package strings -->
<string name="failed_to_extract" comment="Notification that keyboard package failed to unzip">Magavka tiɗase ashigashe</string>
<!-- Context: KMP Package strings -->
<string name="install_keyboard_package" comment="Title to install keyboard package">Femhe Keyboard</string>
<!-- Context: KMP Package strings -->
<string name="install_predictive_text_package" comment="Title to install dictionary package">Femhe Dictionary</string>
<!-- Context: KMP Package strings -->
<string name="not_valid_package_file" comment="Notification when invalid package file cannot be installed">%1$s ŋanenka kalkale Keyman pakeji file.\n%2$s\"</string>
<!-- Context: KMP Package strings -->
<string name="no_new_touch_keyboards_to_install" comment="Notification when no touch-optimized keyboards can be installed">Keyboard pakeji ɓáaka elva geja keyboards gé femhe</string>
<!-- Context: KMP Package strings -->
<string name="no_new_predictive_text_to_install" comment="Notification when no dictionaries can be installed">Ɓáaka daula predictive text gé femhe</string>
<!-- Context: KMP Package strings -->
<string name="no_targets_to_install" comment="Notification when a package doesn't contain keyboards or dictionaries">Ɓáaka keyboards mtu predictive text gé femhe</string>
<!-- Context: KMP Package strings -->
<string name="no_associated_languages" comment="Notification when a keyboard package doesn't contain languages">Keyboard pakeji ɓáaka naraha harzhe gé femhe</string>
<!-- Context: KMP Package strings -->
<string name="invalid_metadata" comment="kmp.json metadata file is invalid or missing in package">Kalkalenka/Missing metadata am pakeji</string>
</resources>

View file

@ -118,8 +118,7 @@
//window.console.log('onStateChange change: ' + change);
// Refresh KMW OSK
var kmw=window['keyman'];
kmw['correctOSKTextSize']();
keyman.correctOSKTextSize();
fragmentToggle = (fragmentToggle + 1) % 100;
if(change != 'configured') { // doesn't change the display; only initiates suggestions.

View file

@ -41,12 +41,16 @@ public class DisplayLanguages {
new DisplayLanguageType(unspecifiedLocale, context.getString(R.string.default_locale)),
new DisplayLanguageType("am-ET", "አማርኛ (Amharic)"),
new DisplayLanguageType("az-AZ", "Azərbaycanca (Azəricə)"),
new DisplayLanguageType("bwr-NT", "Bura-Pabir"),
new DisplayLanguageType("ff-NG", "Ɗemngal Fulfulde"),
new DisplayLanguageType("en", "English"),
new DisplayLanguageType("es-419", "Español (Spanish - Latin America)"),
new DisplayLanguageType("fr-FR", "French"),
new DisplayLanguageType("ha-HG", "Hausa"),
new DisplayLanguageType("in-ID", "Indonesian"),
new DisplayLanguageType("de-DE", "German"),
new DisplayLanguageType("km-KH", "Khmer"),
new DisplayLanguageType("mfi-NG", "Mandara (Wandala)"),
new DisplayLanguageType("ann", "Obolo"),
new DisplayLanguageType("ff-ZA", "Pulaar-Fulfulde"), // or Fulah
new DisplayLanguageType("shu-latn", "Shuwa (Latin)"),

View file

@ -676,18 +676,30 @@ final class KMKeyboard extends WebView {
}
}
// Extract Unicode numbers (\\uxxxx) from a layer to character string.
// Ignores empty strings and layer names
// Returns: String
/**
* Extract Unicode numbers (\\u_xxxx_yyyy) from a layer to character string.
* Ignores empty strings and layer names
* Refer to web/source/osk/oskKey.ts
* @param ktext Unicode string in the format \\uxxxx_yyyy
* @return String to display on subkey
*/
protected String convertKeyText(String ktext) {
String title = "";
String[] values = ktext.split("\\\\u");
int length = values.length;
for (int j = 0; j < length; j++) {
if (!values[j].isEmpty() && !values[j].contains("-")) {
int c = Integer.parseInt(values[j], 16);
// TODO: \\uxxxxxx will need to be handled with title.codePointAt(c)
title += String.valueOf((char) c);
// Split U_xxxx_yyyy
String[] codePoints = values[j].split("_");
for (String codePoint : codePoints) {
int codePointValue = Integer.parseInt(codePoint, 16);
if ((0x0 <= codePointValue && codePointValue <= 0x1F) || (0x80 <= codePointValue && codePointValue <= 0x9F)
|| (codePointValue > 0x10FFFF)) {
continue;
} else {
title += new String(Character.toChars(codePointValue));
}
}
}
}
return title;

View file

@ -2109,9 +2109,6 @@ public final class KMManager {
} else {
// clear globeKeyState
globeKeyState = GlobeKeyState.GLOBE_KEY_STATE_UP;
// TODO: This should not be allowed because !shouldAllowSetKeyboard (#5570)
switchToNextKeyboard(context);
}
}

View file

@ -136,8 +136,8 @@ public final class KeyboardPickerActivity extends BaseActivity {
listView.setOnItemLongClickListener(new OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, final int position, long id) {
// Prevent the default keyboard from being removed
if (position > 0 && canRemoveKeyboard) {
// As long as more than 1 keyboard installed, display uninstall keyboard
if (KeyboardController.getInstance().get().size() > 1 && canRemoveKeyboard) {
PopupMenu popup = new PopupMenu(context, view);
popup.getMenuInflater().inflate(R.menu.popup, popup.getMenu());
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@ -370,11 +370,8 @@ public final class KeyboardPickerActivity extends BaseActivity {
protected static boolean removeKeyboard(Context context, int position) {
boolean result = false;
// Prevent the first keyboard (index 0) from being removed
if (position > 0) {
KeyboardController.getInstance().remove(position);
result = KeyboardController.getInstance().save(context);
}
KeyboardController.getInstance().remove(position);
result = KeyboardController.getInstance().save(context);
notifyKeyboardsUpdate(context);

View file

@ -321,7 +321,7 @@ public class KeyboardController {
* @param index
*/
public void remove(int index) {
// Check initialized, and disallow removing default keyboard
// Check initialized
if (!isInitialized) {
return;
}

View file

@ -12,6 +12,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_toStartOf="@id/imageButton1"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:orientation="vertical" >
@ -22,6 +23,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:ellipsize="end"
android:singleLine="true"
android:textSize="16sp"
android:textStyle="bold" />

View file

@ -0,0 +1,153 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Device type -->
<!-- Application name (Keyman Engine for Android) -->
<!-- Context: Title for list -->
<plurals name="title_keyboards">
<item quantity="one">Keyboard</item>
<item quantity="other">Keyboardyeri</item>
</plurals>
<!-- Context: Title for list -->
<string name="title_add_keyboard" comment="Add a new keyboard">Jaktǝ keyboard na bǝlin</string>
<!-- Context: Title for list -->
<string name="title_languages_settings" comment="List of installed languages">Hulfur mnyayeri natǝ mdǝkǝ hara installari</string>
<!-- Context: Title for list -->
<string name="title_language_settings" comment="Keyman Settings for a language">%1$s Setiyeri</string>
<!-- Context: Button label -->
<string name="label_add" comment="Button to add an item">Jakta</string>
<!-- Context: Button label -->
<string name="label_back" comment="Button to go back">Bwahili</string>
<!-- Context: Button label -->
<string name="label_cancel" comment="Button to cancel an action">Awo</string>
<!-- Context: Button label -->
<string name="label_close" comment="Close a dialog">Harta</string>
<!-- Context: Button label -->
<string name="label_close_keyman" comment="Close the Keyman application">Hartǝ Keyman</string>
<!-- Context: Button label -->
<string name="label_forward" comment="Button to go forward">Lǝkǝma</string>
<!-- Context: Button label -->
<string name="label_next_input_method" comment="Switch to next input method (replaces label_close_keyman)">Lakur vu su wala hara rubutu na damwa</string>
<!-- Context: Button label -->
<string name="label_download" comment="Button to confirm downloading an item">Dawunlodi</string>
<!-- Context: Button label -->
<string name="label_install" comment="Confirmation to install a package">Hara instal</string>
<!-- Context: Button label -->
<string name="label_later" comment="Do an action at a later time">Danzi</string>
<!-- Context: Button label -->
<string name="label_next" comment="Go to the next screen">Lǝkǝma</string>
<!-- Context: Button label -->
<string name="label_ok" comment="Button to acknowledge a dialog">OK</string>
<!-- Context: Button label -->
<string name="label_update" comment="Dialog button to update a resource">Jakǝngkǝr su na bǝlin</string>
<!-- Context: Keyboard Updates -->
<string name="cannot_connect" comment="Error message when network connection fails">Aɗa tsoktǝ kǝɓa ka sava ar Keyman wa!</string>
<!-- Context: Keyboard Updates -->
<string name="confirm_delete_keyboard" comment="Confirmation to delete a keyboard">Ga ata bara kara cijimta keyboard ngǝni ya?</string>
<!-- Context: Keyboard Updates -->
<string name="confirm_download_keyboard" comment="Confirmation to download a keyboard update">Ga ata bara kara hara dawunlodi ar jili keyboard ngǝni na bǝlin ni ya?</string>
<!-- Context: Keyboard Updates -->
<string name="confirm_update" comment="Confirmation to update several resources">Ga ata bara kara wutǝ su na bǝlin na ar keyboardyeri ka dictionariyeri ya kulini?</string>
<!-- Context: Keyboard Updates -->
<string name="keyboard_updates_channel">Jakǝngkǝr bǝlinkur ar kariyeri</string>
<!-- Context: Keyboard Updates -->
<string name="keyboard_updates_available" comment="Notification when resource updates are available">Kariyeri na bǝlin aɗi</string>
<!-- Context: Keyboard Updates -->
<string name="update_available" comment="Currently installed version of a resource with an available update">%1$s (Suayeri na bǝlin aɗi)</string>
<!-- Context: Keyboard Updates -->
<string name="keyboard_update_message" comment="language name: keyboard name"> Suayeri na bǝlin aɗi na ar keyboard %1$s: %2$s </string>
<!-- Context: Keyboard Updates -->
<string name="dictionary_update_message">Suayeri na bǝlin aɗi na ar dictionary %1$s: %2$s </string>
<!-- Context: Keyboard Info and Keyboard Settings -->
<string name="keyboard_version" comment="Label for keyboard version">Jili keyboard</string>
<!-- Context: Keyboard Info and Keyboard Settings -->
<string name="help_link" comment="Label for help link">Vi wutǝ dlara</string>
<!-- Context: Keyboard Info and Keyboard Settings -->
<string name="uninstall_keyboard" comment="Label for uninstalling keyboard">Kǝlɓǝla keyboard</string>
<!-- Context: Keyboard Info and Keyboard Settings -->
<string name="keyboard_picker_new_keyboard" comment="Mark a language name that's newly installed in keyboard list">[new] %1$s</string>
<!-- Context: Keyboard Info and Keyboard Settings -->
<string name="keyboard_qr_code" comment="QR Code description"> Kǝtǝ fwator kod ngǝni kamnyar hara lodi ar \nkeyboard ata na\'ura laga</string>
<!-- Context: Keyboard Help welcome.htm title -->
<string name="welcome_package" comment="Title to welcome.htm page (name and version)">Maraba ka si akwa %1$s</string>
<!-- Context: Keyboard app doesn't include FileProvider library needed to view help file -->
<string name="fileprovider_undefined" comment="FileProvider library needed to view help file"> Mda akwa bara library na ar FileProvider kamnyar ka mdǝ wutǝ fayil ar dlara: %1$s</string>
<!-- Context: Fatal keyboard error. Will load default keyboard -->
<string name="fatal_keyboard_error" comment="Fatal keyboard error (keyboard ID::packageID for language). Will load default keyboard"> Dametǝdzi na ar Fatal akwa keyboard ka %1$s:%2$s ala %3$s hulfur mnya. Akwa hara lodi ar default keyboard.</string>
<!-- Context: Fatal keyboard error. -->
<string name="fatal_keyboard_error_short" comment="Error in keyboard (keyboard ID::packageID for language)."> Dametǝdzi akwa keyboard %1$s:%2$s na ar %3$s hulfur mnya.</string>
<!-- Context: Query for associated dictionary -->
<string name="query_associated_model" comment="Check if there's an available dictionary to download">Akwa pakǝ dictionary na kǝɓa kari kamnyar katsa hara dawunlodi ni</string>
<!-- Context: Model Updates -->
<string name="confirm_download_model" comment="Confirmation to download a dictionary update">Ga ata bara kara hara dawunlodi ar jili dictionary na ngǝni na bǝlin ni ya?</string>
<!-- Context: No associated dictionary found -->
<string name="no_associated_model" comment="Confirmation there's no available dictionary to download">Dictionary aɗiwa natǝ mda ata hara dawunlodir ni</string>
<!-- Context: Model Updates -->
<string name="catalog_unavailable" comment="Notification that the cloud resource catalog can't be updated">Katalogu na ar kariyeri ni aɗiwa</string>
<!-- Context: Background download messages-->
<string name="catalog_download_start_in_background" comment="Notification that the resource catalog update will begin">Jakǝngkǝr bǝlinkur kataloguni ku kurtǝ ka baɗita akwa bakgrawund</string>
<!-- Context: Background download messages-->
<string name="catalog_download_is_running_in_background" comment="Notification that the resource catalog update is still downloading"> Katalogu ni akwa hara dawunlodi harba kulini; usa, jaktǝ ngkǝrtǝ bu damzi rakka!</string>
<!-- Context: Background download messages-->
<string name="progress_message_checking_resource_is_running" comment="Progress notification that the check for a resource is still running ">Akwa pakǝ kariyeri</string>
<!-- Context: Background download messages-->
<string name="keyboard_download_start_in_background" comment="Notification that a keyboard download has started">Dawunlodi ar keyboard ku baɗita akwa Bakgurawund</string>
<!-- Context: Background download messages-->
<string name="keyboard_download_is_running_in_background" comment="Notification that a keyboard download is still running">Keyboard natǝ mdǝ carɓǝla ni ku kurtǝ ka baɗitǝ dawunlodi; usa, jaktǝ ngkǝrtǝ bu ɗanzi rakka!</string>
<!-- Context: Background download messages-->
<string name="keyboard_download_finished" comment="Notification that a keyboard download has finished">Dawunlodi ar keyboard kǝ kuri!</string>
<!-- Context: Background download messages-->
<string name="dictionary_download_start_in_background" comment="Notification that a dictionary download has started">Dawunlodi ar dictionary ku baɗita akwa Bakgurawund</string>
<!-- Context: Background download messages-->
<string name="dictionary_download_is_running_in_background" comment="Notification that a dictionary download is still running">Dictionary natǝ mdǝ carɓǝla ni ku kurtǝ ka baɗitǝ dawunlodi; usa, jaktǝ ngkǝrtǝ bu ɗanzi rakka!</string>
<!-- Context: Background download messages-->
<string name="dictionary_download_finished" comment="Notification that a dictionary download has finished">Dawunlodi ar dictionary kǝ kuri.</string>
<!-- Context: Background download messages -->
<string name="download_failed" comment="Notification that a download failed">Dawunlodi aɗi hara wa</string>
<!-- Context: Background download messages -->
<string name="failed_to_retrieve_file" comment="Failed to retrieve downloaded file">Kǝ ngǝlar ta kǝlɓǝla fayil ar dawunlodi</string>
<!-- Context: General Updates -->
<string name="update_check_unavailable" comment="Error message when a Keyman server can't be reached">Ngǝlari ta kǝɓa ka sava!</string>
<!-- Context: General Updates -->
<string name="update_check_current" comment="Notification that all resources are up to date">"Shanga kariyeri ni da bǝlin!"</string>
<!-- Context: General Updates -->
<string name="update_failed" comment="Notification that a resource update failed">Pal wala hang ta pal akwa kariyeri ni ngǝla ta nzi bǝlin!</string>
<!-- Context: General Updates -->
<string name="update_success" comment="Notification that a resource update successfully updated">Kariyeri kǝ kurtǝ ka nzi bǝlin!</string>
<!-- Context: Model Info -->
<string name="model_version" comment="Title for a dictionary version">Jili ar dictionary</string>
<!-- Context: Model Info -->
<string name="uninstall_model" comment="Label to uninstall a dictionary">Kǝlɓǝla dictionary</string>
<!-- Context: Model Info -->
<string name="confirm_delete_model" comment="Confirmation to delete a dictionary">Ga ata bara kara cijimta dictionary ngǝni ya?</string>
<!-- Context: Language Settings Keyboard install strings -->
<string name="keyboard_install_toast" comment="Notification when a keyboard is installed">%1$s keyboard ku hara instal</string>
<!-- Context: Language Settings menu strings -->
<string name="enable_corrections" comment="Enable corrections from the suggestion banner">Vu ka tsa namtǝdzi</string>
<!-- Context: Language Settings menu strings -->
<string name="enable_predictions" comment="Enable predictions from the suggestion banner">Vu katsa hamta sauri su natǝ asi</string>
<!-- Context: Language Settings menu strings -->
<string name="model_label">Dictionari</string>
<!-- Context: Language Settings menu substring - Check for available dictionary -->
<string name="check_available_model" comment="Check for available dictionary">Pakǝ dictionari na aɗi</string>
<!-- Context: Language Settings menu strings -->
<string name="model_info_header" comment="Dictionary name">Dictionary: %1$s</string>
<!-- Context: Language Settings menu strings -->
<string name="model_picker_header" comment="Dictionaries for a specified language">%1$s dictionariyeri</string>
<!-- Context: Language Settings menu strings -->
<!-- Context: Language Settings menu strings -->
<string name="model_install_toast" comment="Notification when a dictionary is installed">Dictionari ku hara instal</string>
<!-- Context: Language Settings menu strings -->
<plurals name="keyboard_count">
<item quantity="one">(%1$d keyboard)</item>
<item quantity="other">(%1$d keyboardyeri)</item>
</plurals>
<!-- Context: "Change Display Language" menu -->
<string name="default_locale" comment="Use the device's current locale">Default Locale</string>
<!-- Context: Content descriptions -->
<!-- Context: Content descriptions -->
<!-- Context: Popup menu labels -->
<string name="label_delete" comment="Confirmation to delete an item">Cijimta</string>
<!-- Context: Shared preferences name -->
<!-- Context: Other strings -->
<string name="help_bubble_text">Tsukwa vi ngǝni kamnyar pali keyboard ni</string>
</resources>

View file

@ -0,0 +1,153 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Device type -->
<!-- Application name (Keyman Engine for Android) -->
<!-- Context: Title for list -->
<plurals name="title_keyboards">
<item quantity="one">Keyboard</item>
<item quantity="other">Keyboards</item>
</plurals>
<!-- Context: Title for list -->
<string name="title_add_keyboard" comment="Add a new keyboard">Ɓeddu kibod kesum</string>
<!-- Context: Title for list -->
<string name="title_languages_settings" comment="List of installed languages">Ɗemngal ko wa`inni</string>
<!-- Context: Title for list -->
<string name="title_language_settings" comment="Keyman Settings for a language">%1$s Settin</string>
<!-- Context: Button label -->
<string name="label_add" comment="Button to add an item">Ɓeddu</string>
<!-- Context: Button label -->
<string name="label_back" comment="Button to go back">Ɓaawo</string>
<!-- Context: Button label -->
<string name="label_cancel" comment="Button to cancel an action">Wurtu</string>
<!-- Context: Button label -->
<string name="label_close" comment="Close a dialog">Maɓɓu</string>
<!-- Context: Button label -->
<string name="label_close_keyman" comment="Close the Keyman application">Maɓɓu Keyman</string>
<!-- Context: Button label -->
<string name="label_forward" comment="Button to go forward">Yeeso</string>
<!-- Context: Button label -->
<string name="label_next_input_method" comment="Switch to next input method (replaces label_close_keyman)">Laawol waatugo jee yeeso</string>
<!-- Context: Button label -->
<string name="label_download" comment="Button to confirm downloading an item">Jippunu</string>
<!-- Context: Button label -->
<string name="label_install" comment="Confirmation to install a package">Wa`unu</string>
<!-- Context: Button label -->
<string name="label_later" comment="Do an action at a later time">Yeeso</string>
<!-- Context: Button label -->
<string name="label_next" comment="Go to the next screen">Yeeso</string>
<!-- Context: Button label -->
<string name="label_ok" comment="Button to acknowledge a dialog">OK</string>
<!-- Context: Button label -->
<string name="label_update" comment="Dialog button to update a resource">Kesutu</string>
<!-- Context: Keyboard Updates -->
<string name="cannot_connect" comment="Error message when network connection fails">Nastata dow sava Keyman </string>
<!-- Context: Keyboard Updates -->
<string name="confirm_delete_keyboard" comment="Confirmation to delete a keyboard">A` yiɗan woggugo kibod ɗo na?</string>
<!-- Context: Keyboard Updates -->
<string name="confirm_download_keyboard" comment="Confirmation to download a keyboard update">A` yiɗan jippingo kibod kesum ɗo na?</string>
<!-- Context: Keyboard Updates -->
<string name="confirm_update" comment="Confirmation to update several resources">A` yiɗan kesutuggo Kibod ɗo bee defetere ma`ana kalimaji jotta?</string>
<!-- Context: Keyboard Updates -->
<string name="keyboard_updates_channel">Kare kesutuggo</string>
<!-- Context: Keyboard Updates -->
<string name="keyboard_updates_available" comment="Notification when resource updates are available">Kare kesutiggu ɗo feesi</string>
<!-- Context: Keyboard Updates -->
<string name="update_available" comment="Currently installed version of a resource with an available update">%1$s (Kesutuggo ɗo feesi)</string>
<!-- Context: Keyboard Updates -->
<string name="keyboard_update_message" comment="language name: keyboard name"> Kesutuggo ɗo feesi jee kibod %1$s: %2$s </string>
<!-- Context: Keyboard Updates -->
<string name="dictionary_update_message">Kesutuggo deftere ma`ana kalimaji ɗo feesi %1$s: %2$s </string>
<!-- Context: Keyboard Info and Keyboard Settings -->
<string name="keyboard_version" comment="Label for keyboard version">Nonde kibod</string>
<!-- Context: Keyboard Info and Keyboard Settings -->
<string name="help_link" comment="Label for help link">Lenguru mballa</string>
<!-- Context: Keyboard Info and Keyboard Settings -->
<string name="uninstall_keyboard" comment="Label for uninstalling keyboard">A` itta kibod</string>
<!-- Context: Keyboard Info and Keyboard Settings -->
<string name="keyboard_picker_new_keyboard" comment="Mark a language name that's newly installed in keyboard list">[new] %1$s</string>
<!-- Context: Keyboard Info and Keyboard Settings -->
<string name="keyboard_qr_code" comment="QR Code description"> A` waɗa sikanin lamba ɗo ngam a` wa`inna \nkibod man dow na`ura feere </string>
<!-- Context: Keyboard Help welcome.htm title -->
<string name="welcome_package" comment="Title to welcome.htm page (name and version)">Jaɓɓaama tow %1$s</string>
<!-- Context: Keyboard app doesn't include FileProvider library needed to view help file -->
<string name="fileprovider_undefined" comment="FileProvider library needed to view help file"> Babal fayel ɗo mari haaje laarugo fayel mballa: %1$s </string>
<!-- Context: Fatal keyboard error. Will load default keyboard -->
<string name="fatal_keyboard_error" comment="Fatal keyboard error (keyboard ID::packageID for language). Will load default keyboard"> Kibod man wari bee masala bee %1$s:%2$s jee %3$s ɗemngal. Ɗo nastina kibod ko naftirta. </string>
<!-- Context: Fatal keyboard error. -->
<string name="fatal_keyboard_error_short" comment="Error in keyboard (keyboard ID::packageID for language)."> Masala nder kibod %1$s:%2$s jee %3$s ɗemngal. </string>
<!-- Context: Query for associated dictionary -->
<string name="query_associated_model" comment="Check if there's an available dictionary to download">Ɗo tefa deftere ma`ana kalimaji ngam jippina</string>
<!-- Context: Model Updates -->
<string name="confirm_download_model" comment="Confirmation to download a dictionary update">A` yiɗan jippingo deftere ma`ana kalimaji ɗo kesum na? </string>
<!-- Context: No associated dictionary found -->
<string name="no_associated_model" comment="Confirmation there's no available dictionary to download">Walaa deftere ma`ana kalimaji ko jippinta</string>
<!-- Context: Model Updates -->
<string name="catalog_unavailable" comment="Notification that the cloud resource catalog can't be updated">Limngal kare kuuɗe man feesay</string>
<!-- Context: Background download messages-->
<string name="catalog_download_start_in_background" comment="Notification that the resource catalog update will begin">Kesutuggo limngal kare kuuɗe man fuɗɗaama ha ɓaawo</string>
<!-- Context: Background download messages-->
<string name="catalog_download_is_running_in_background" comment="Notification that the resource catalog update is still downloading"> Limngal kare kuuɗe man ɗo jippa; usseni a` meeta warugo nder wakkati seɗɗa! </string>
<!-- Context: Background download messages-->
<string name="progress_message_checking_resource_is_running" comment="Progress notification that the check for a resource is still running ">Ɗo tefa kare kuuɗe</string>
<!-- Context: Background download messages-->
<string name="keyboard_download_start_in_background" comment="Notification that a keyboard download has started">Kibod man ɗo jippa haa ɓaawo</string>
<!-- Context: Background download messages-->
<string name="keyboard_download_is_running_in_background" comment="Notification that a keyboard download is still running">Kibod ko supti man arti ɗo jippa; usseni a` lorta nder wakkati seɗɗa!</string>
<!-- Context: Background download messages-->
<string name="keyboard_download_finished" comment="Notification that a keyboard download has finished">Kibod man timmini jippugo!</string>
<!-- Context: Background download messages-->
<string name="dictionary_download_start_in_background" comment="Notification that a dictionary download has started">Jippingo deftere ma`ana kalimaji man fuɗɗi haa ɓaawo</string>
<!-- Context: Background download messages-->
<string name="dictionary_download_is_running_in_background" comment="Notification that a dictionary download is still running">Deftere ma`ana kalimaji ko supti man arti ɗo jippa; usseni a` lorta nder wakkati seɗɗa!</string>
<!-- Context: Background download messages-->
<string name="dictionary_download_finished" comment="Notification that a dictionary download has finished">Jippingo deftere ma`ana kalimaji man timmini.</string>
<!-- Context: Background download messages -->
<string name="download_failed" comment="Notification that a download failed">Jippingo man sali</string>
<!-- Context: Background download messages -->
<string name="failed_to_retrieve_file" comment="Failed to retrieve downloaded file">Sali wurtungo fayel ko jippi</string>
<!-- Context: General Updates -->
<string name="update_check_unavailable" comment="Error message when a Keyman server can't be reached">Saldori nastugo nder sava!</string>
<!-- Context: General Updates -->
<string name="update_check_current" comment="Notification that all resources are up to date">"Kare kuuɗe man fuu kesum on!"</string>
<!-- Context: General Updates -->
<string name="update_failed" comment="Notification that a resource update failed">Gootel ko ko ɓuri dow kare kuuɗe man sali kesituggo!</string>
<!-- Context: General Updates -->
<string name="update_success" comment="Notification that a resource update successfully updated">Kare kuuɗe man kesiti!</string>
<!-- Context: Model Info -->
<string name="model_version" comment="Title for a dictionary version">Nonde deftere ma`ana kalimaji</string>
<!-- Context: Model Info -->
<string name="uninstall_model" comment="Label to uninstall a dictionary">A` itta deftere ma`ana kalimaji</string>
<!-- Context: Model Info -->
<string name="confirm_delete_model" comment="Confirmation to delete a dictionary">A` yiɗan woggugo deftere ma`ana kalimaji ɗo na?</string>
<!-- Context: Language Settings Keyboard install strings -->
<string name="keyboard_install_toast" comment="Notification when a keyboard is installed">%1$s Kibod man wa`innaa ma</string>
<!-- Context: Language Settings menu strings -->
<string name="enable_corrections" comment="Enable corrections from the suggestion banner">Accu wo`inningo</string>
<!-- Context: Language Settings menu strings -->
<string name="enable_predictions" comment="Enable predictions from the suggestion banner">Accu tammunde</string>
<!-- Context: Language Settings menu strings -->
<string name="model_label">Deftere ma`ana kalimaji</string>
<!-- Context: Language Settings menu substring - Check for available dictionary -->
<string name="check_available_model" comment="Check for available dictionary">Tefu deftere ma`ana kalimaji ko ɗon</string>
<!-- Context: Language Settings menu strings -->
<string name="model_info_header" comment="Dictionary name">Deftere ma`ana kalimaji: %1$s</string>
<!-- Context: Language Settings menu strings -->
<string name="model_picker_header" comment="Dictionaries for a specified language">%1$s deftere ma`anaaji</string>
<!-- Context: Language Settings menu strings -->
<!-- Context: Language Settings menu strings -->
<string name="model_install_toast" comment="Notification when a dictionary is installed">Deftere ma`ana kalimaji man wa`i</string>
<!-- Context: Language Settings menu strings -->
<plurals name="keyboard_count">
<item quantity="one">(%1$d keyboard)</item>
<item quantity="other">(%1$d keyboards)</item>
</plurals>
<!-- Context: "Change Display Language" menu -->
<string name="default_locale" comment="Use the device's current locale">Difolt lokel</string>
<!-- Context: Content descriptions -->
<!-- Context: Content descriptions -->
<!-- Context: Popup menu labels -->
<string name="label_delete" comment="Confirmation to delete an item">Woggu</string>
<!-- Context: Shared preferences name -->
<!-- Context: Other strings -->
<string name="help_bubble_text">A` meema haa ɗo ngam a` wayla kibod</string>
</resources>

View file

@ -0,0 +1,153 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Device type -->
<!-- Application name (Keyman Engine for Android) -->
<!-- Context: Title for list -->
<plurals name="title_keyboards">
<item quantity="one">Madanni</item>
<item quantity="other">Madannai</item>
</plurals>
<!-- Context: Title for list -->
<string name="title_add_keyboard" comment="Add a new keyboard">Ƙara sabon madanni</string>
<!-- Context: Title for list -->
<string name="title_languages_settings" comment="List of installed languages">Harsunan da aka shigar</string>
<!-- Context: Title for list -->
<string name="title_language_settings" comment="Keyman Settings for a language">Saitunan %1$s</string>
<!-- Context: Button label -->
<string name="label_add" comment="Button to add an item">Ƙara</string>
<!-- Context: Button label -->
<string name="label_back" comment="Button to go back">Baya</string>
<!-- Context: Button label -->
<string name="label_cancel" comment="Button to cancel an action">Sokewa</string>
<!-- Context: Button label -->
<string name="label_close" comment="Close a dialog">Rufewa</string>
<!-- Context: Button label -->
<string name="label_close_keyman" comment="Close the Keyman application">Rufe Keyman</string>
<!-- Context: Button label -->
<string name="label_forward" comment="Button to go forward">Gaba</string>
<!-- Context: Button label -->
<string name="label_next_input_method" comment="Switch to next input method (replaces label_close_keyman)">Hanyar Shiga na Gaba</string>
<!-- Context: Button label -->
<string name="label_download" comment="Button to confirm downloading an item">Saukewa</string>
<!-- Context: Button label -->
<string name="label_install" comment="Confirmation to install a package">Shigarwa</string>
<!-- Context: Button label -->
<string name="label_later" comment="Do an action at a later time">Daga baya</string>
<!-- Context: Button label -->
<string name="label_next" comment="Go to the next screen">Na gaba</string>
<!-- Context: Button label -->
<string name="label_ok" comment="Button to acknowledge a dialog">OK</string>
<!-- Context: Button label -->
<string name="label_update" comment="Dialog button to update a resource">Sabuntawa</string>
<!-- Context: Keyboard Updates -->
<string name="cannot_connect" comment="Error message when network connection fails">Kasa shiga rumbun bayanan keyman!</string>
<!-- Context: Keyboard Updates -->
<string name="confirm_delete_keyboard" comment="Confirmation to delete a keyboard">Ana son goge wannan madannin?</string>
<!-- Context: Keyboard Updates -->
<string name="confirm_download_keyboard" comment="Confirmation to download a keyboard update">Ana son sauke sabon nau\'in wannan madannin?</string>
<!-- Context: Keyboard Updates -->
<string name="confirm_update" comment="Confirmation to update several resources">Ana son sabunta madannai da ƙamus a yanzu?</string>
<!-- Context: Keyboard Updates -->
<string name="keyboard_updates_channel">Sabunta Abubuwa</string>
<!-- Context: Keyboard Updates -->
<string name="keyboard_updates_available" comment="Notification when resource updates are available">Abubuwan da aka sabunta sun samu</string>
<!-- Context: Keyboard Updates -->
<string name="update_available" comment="Currently installed version of a resource with an available update">%1$s (Akwai Sabuntawa)</string>
<!-- Context: Keyboard Updates -->
<string name="keyboard_update_message" comment="language name: keyboard name">An sabunta sabida madannin %1$s: %2$s </string>
<!-- Context: Keyboard Updates -->
<string name="dictionary_update_message">An sabunta sabida ƙamus ɗin %1$s: %2$s </string>
<!-- Context: Keyboard Info and Keyboard Settings -->
<string name="keyboard_version" comment="Label for keyboard version">Nau\'in madanni</string>
<!-- Context: Keyboard Info and Keyboard Settings -->
<string name="help_link" comment="Label for help link">Link ɗin taimako</string>
<!-- Context: Keyboard Info and Keyboard Settings -->
<string name="uninstall_keyboard" comment="Label for uninstalling keyboard">Madannan da aka cire</string>
<!-- Context: Keyboard Info and Keyboard Settings -->
<string name="keyboard_picker_new_keyboard" comment="Mark a language name that's newly installed in keyboard list">[sabo] %1$s</string>
<!-- Context: Keyboard Info and Keyboard Settings -->
<string name="keyboard_qr_code" comment="QR Code description">Duba wannan lambar domin shigar da wannan\nmadanni akan wata na\'urar</string>
<!-- Context: Keyboard Help welcome.htm title -->
<string name="welcome_package" comment="Title to welcome.htm page (name and version)">Barka da zuwa %1$s</string>
<!-- Context: Keyboard app doesn't include FileProvider library needed to view help file -->
<string name="fileprovider_undefined" comment="FileProvider library needed to view help file">Ana buƙatar wajen karatu na FileProvider domin duba fayil ɗin taimako: %1$s</string>
<!-- Context: Fatal keyboard error. Will load default keyboard -->
<string name="fatal_keyboard_error" comment="Fatal keyboard error (keyboard ID::packageID for language). Will load default keyboard">Matsalar madanni da %1$s:%2$s domin %3$s yaruka. Saukar da madanni mai kyau.</string>
<!-- Context: Fatal keyboard error. -->
<string name="fatal_keyboard_error_short" comment="Error in keyboard (keyboard ID::packageID for language).">Kuskure a yaren %1$s:%2$s for %3$s madanni.</string>
<!-- Context: Query for associated dictionary -->
<string name="query_associated_model" comment="Check if there's an available dictionary to download">Duba ƙamus mai alaƙa domin a sauke</string>
<!-- Context: Model Updates -->
<string name="confirm_download_model" comment="Confirmation to download a dictionary update">Ana son sauke sabon nau\'in wannan ƙamus?</string>
<!-- Context: No associated dictionary found -->
<string name="no_associated_model" comment="Confirmation there's no available dictionary to download">Babu ƙamus ɗin da za a sauke</string>
<!-- Context: Model Updates -->
<string name="catalog_unavailable" comment="Notification that the cloud resource catalog can't be updated">Babu cikakkun jerin abubuwansa</string>
<!-- Context: Background download messages-->
<string name="catalog_download_start_in_background" comment="Notification that the resource catalog update will begin">An fara sabunta cikkakkun jerin ta bayan fage</string>
<!-- Context: Background download messages-->
<string name="catalog_download_is_running_in_background" comment="Notification that the resource catalog update is still downloading">Har yanzu cikakken jerin na sauka; yi haƙuri ƙara gwadawa na ɗan lokaci!</string>
<!-- Context: Background download messages-->
<string name="progress_message_checking_resource_is_running" comment="Progress notification that the check for a resource is still running ">Duba abubuwa</string>
<!-- Context: Background download messages-->
<string name="keyboard_download_start_in_background" comment="Notification that a keyboard download has started">An fara saukar da madanni a bayan fage</string>
<!-- Context: Background download messages-->
<string name="keyboard_download_is_running_in_background" comment="Notification that a keyboard download is still running">Madannin da aka zaɓa na sauka; yi haƙuri a sake gwadawa cikin ɗan lokaci!</string>
<!-- Context: Background download messages-->
<string name="keyboard_download_finished" comment="Notification that a keyboard download has finished">An kammala sauke madannin!</string>
<!-- Context: Background download messages-->
<string name="dictionary_download_start_in_background" comment="Notification that a dictionary download has started">An fara sauke ƙamus ta Bayan fage</string>
<!-- Context: Background download messages-->
<string name="dictionary_download_is_running_in_background" comment="Notification that a dictionary download is still running">Ƙamus ɗin da aka zaɓa an riga da an sauke shi; yi haƙuri a kuma gwadawa na ɗan lokaci!</string>
<!-- Context: Background download messages-->
<string name="dictionary_download_finished" comment="Notification that a dictionary download has finished">An kammala sauke ƙamus ɗin.</string>
<!-- Context: Background download messages -->
<string name="download_failed" comment="Notification that a download failed">An kasa saukewa</string>
<!-- Context: Background download messages -->
<string name="failed_to_retrieve_file" comment="Failed to retrieve downloaded file">Ba a yi nasarar dawo da fayil ɗin da aka sauke ba</string>
<!-- Context: General Updates -->
<string name="update_check_unavailable" comment="Error message when a Keyman server can't be reached">An kasa samun damar shiga rumbun bayanai!</string>
<!-- Context: General Updates -->
<string name="update_check_current" comment="Notification that all resources are up to date">"An sabunta dukkanin abubuwan!"</string>
<!-- Context: General Updates -->
<string name="update_failed" comment="Notification that a resource update failed">Ƙarin wani abin ya ƙi sabuntuwa!</string>
<!-- Context: General Updates -->
<string name="update_success" comment="Notification that a resource update successfully updated">An yi nasarar sabunta abubuwan!</string>
<!-- Context: Model Info -->
<string name="model_version" comment="Title for a dictionary version">Nau\'in ƙamus</string>
<!-- Context: Model Info -->
<string name="uninstall_model" comment="Label to uninstall a dictionary">Ƙamus ɗin da aka cire</string>
<!-- Context: Model Info -->
<string name="confirm_delete_model" comment="Confirmation to delete a dictionary">Ana son a goge wannan ƙamus ɗin?</string>
<!-- Context: Language Settings Keyboard install strings -->
<string name="keyboard_install_toast" comment="Notification when a keyboard is installed">An shigar da madannin %1$s</string>
<!-- Context: Language Settings menu strings -->
<string name="enable_corrections" comment="Enable corrections from the suggestion banner">Damar gyare-gyare</string>
<!-- Context: Language Settings menu strings -->
<string name="enable_predictions" comment="Enable predictions from the suggestion banner">Damar hasashe</string>
<!-- Context: Language Settings menu strings -->
<string name="model_label">Ƙamus</string>
<!-- Context: Language Settings menu substring - Check for available dictionary -->
<string name="check_available_model" comment="Check for available dictionary">Bincika ƙamus ɗin da ke akwai</string>
<!-- Context: Language Settings menu strings -->
<string name="model_info_header" comment="Dictionary name">Ƙamus: %1$s</string>
<!-- Context: Language Settings menu strings -->
<string name="model_picker_header" comment="Dictionaries for a specified language">%1$s ƙamus</string>
<!-- Context: Language Settings menu strings -->
<!-- Context: Language Settings menu strings -->
<string name="model_install_toast" comment="Notification when a dictionary is installed">An shigar da ƙamus</string>
<!-- Context: Language Settings menu strings -->
<plurals name="keyboard_count">
<item quantity="one">(%1$d madanni)</item>
<item quantity="other">(%1$d madannai)</item>
</plurals>
<!-- Context: "Change Display Language" menu -->
<string name="default_locale" comment="Use the device's current locale">Default Locale</string>
<!-- Context: Content descriptions -->
<!-- Context: Content descriptions -->
<!-- Context: Popup menu labels -->
<string name="label_delete" comment="Confirmation to delete an item">Goge</string>
<!-- Context: Shared preferences name -->
<!-- Context: Other strings -->
<string name="help_bubble_text">Danna nan domin canza madannai</string>
</resources>

View file

@ -0,0 +1,153 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Device type -->
<!-- Application name (Keyman Engine for Android) -->
<!-- Context: Title for list -->
<plurals name="title_keyboards">
<item quantity="one">Keyboard</item>
<item quantity="other">Keyboards</item>
</plurals>
<!-- Context: Title for list -->
<string name="title_add_keyboard" comment="Add a new keyboard">Farfe daula Keyboard</string>
<!-- Context: Title for list -->
<string name="title_languages_settings" comment="List of installed languages">Naraha na an fa</string>
<!-- Context: Title for list -->
<string name="title_language_settings" comment="Keyman Settings for a language">%1$s Saitin</string>
<!-- Context: Button label -->
<string name="label_add" comment="Button to add an item">Farfe</string>
<!-- Context: Button label -->
<string name="label_back" comment="Button to go back">Fitsanahe aliye</string>
<!-- Context: Button label -->
<string name="label_cancel" comment="Button to cancel an action">Tsanahe</string>
<!-- Context: Button label -->
<string name="label_close" comment="Close a dialog">Hiɗante</string>
<!-- Context: Button label -->
<string name="label_close_keyman" comment="Close the Keyman application">Hiɗante-hiɗa Keyman</string>
<!-- Context: Button label -->
<string name="label_forward" comment="Button to go forward">Fare a de katafke</string>
<!-- Context: Button label -->
<string name="label_next_input_method" comment="Switch to next input method (replaces label_close_keyman)">Next Input Method</string>
<!-- Context: Button label -->
<string name="label_download" comment="Button to confirm downloading an item">Tsukwanahe</string>
<!-- Context: Button label -->
<string name="label_install" comment="Confirmation to install a package">Femfe</string>
<!-- Context: Button label -->
<string name="label_later" comment="Do an action at a later time">Aliyane</string>
<!-- Context: Button label -->
<string name="label_next" comment="Go to the next screen">Dem katafke</string>
<!-- Context: Button label -->
<string name="label_ok" comment="Button to acknowledge a dialog">Bastuwa</string>
<!-- Context: Button label -->
<string name="label_update" comment="Dialog button to update a resource">Update</string>
<!-- Context: Keyboard Updates -->
<string name="cannot_connect" comment="Error message when network connection fails">A tá magavka jemhe an Keyman server!</string>
<!-- Context: Keyboard Updates -->
<string name="confirm_delete_keyboard" comment="Confirmation to delete a keyboard">Ká kátáhe gaggahe una gé keyboard?</string>
<!-- Context: Keyboard Updates -->
<string name="confirm_download_keyboard" comment="Confirmation to download a keyboard update">Ká kátáhe tsukwanahe daula version una gé keyboard?</string>
<!-- Context: Keyboard Updates -->
<string name="confirm_update" comment="Confirmation to update several resources">Ká kátáhe magahe update keyboards antara dictionaries akina?</string>
<!-- Context: Keyboard Updates -->
<string name="keyboard_updates_channel">Resource Updates</string>
<!-- Context: Keyboard Updates -->
<string name="keyboard_updates_available" comment="Notification when resource updates are available">Resource Updates Aŋkwa na</string>
<!-- Context: Keyboard Updates -->
<string name="update_available" comment="Currently installed version of a resource with an available update">%1$s (Update Aŋkwa na)</string>
<!-- Context: Keyboard Updates -->
<string name="keyboard_update_message" comment="language name: keyboard name"> Updates a keyboard na aŋkwa na %1$s: %2$s </string>
<!-- Context: Keyboard Updates -->
<string name="dictionary_update_message">Updates a dictionary na aŋkwa na%1$s: %2$s </string>
<!-- Context: Keyboard Info and Keyboard Settings -->
<string name="keyboard_version" comment="Label for keyboard version">Keyboard version</string>
<!-- Context: Keyboard Info and Keyboard Settings -->
<string name="help_link" comment="Label for help link">Link mla</string>
<!-- Context: Keyboard Info and Keyboard Settings -->
<string name="uninstall_keyboard" comment="Label for uninstalling keyboard">Tiɗase keyboard</string>
<!-- Context: Keyboard Info and Keyboard Settings -->
<string name="keyboard_picker_new_keyboard" comment="Mark a language name that's newly installed in keyboard list">[new] %1$s</string>
<!-- Context: Keyboard Info and Keyboard Settings -->
<string name="keyboard_qr_code" comment="QR Code description">Ksa fatawe una gé code gé femhe una \nkeyboard am nawura umbulé</string>
<!-- Context: Keyboard Help welcome.htm title -->
<string name="welcome_package" comment="Title to welcome.htm page (name and version)">Use gé sawa aza huna %1$s</string>
<!-- Context: Keyboard app doesn't include FileProvider library needed to view help file -->
<string name="fileprovider_undefined" comment="FileProvider library needed to view help file"> FileProvider library a kátá zhara file mla: %1$s</string>
<!-- Context: Fatal keyboard error. Will load default keyboard -->
<string name="fatal_keyboard_error" comment="Fatal keyboard error (keyboard ID::packageID for language). Will load default keyboard"> Kuskure Fatal keyboard antara%1$s:%2$s gé %3$s nare. femhe nde default keyboard.</string>
<!-- Context: Fatal keyboard error. -->
<string name="fatal_keyboard_error_short" comment="Error in keyboard (keyboard ID::packageID for language)."> Kuskure am keyboard %1$s:%2$s for %3$s nare.</string>
<!-- Context: Query for associated dictionary -->
<string name="query_associated_model" comment="Check if there's an available dictionary to download">Zharanahe dictionary harzhe gé tsukwanahe</string>
<!-- Context: Model Updates -->
<string name="confirm_download_model" comment="Confirmation to download a dictionary update">Ká kátáhe tsukwanahe daula version gé una gé dictionary?</string>
<!-- Context: No associated dictionary found -->
<string name="no_associated_model" comment="Confirmation there's no available dictionary to download">Ɓáaka dictionary gé tsukwanahe</string>
<!-- Context: Model Updates -->
<string name="catalog_unavailable" comment="Notification that the cloud resource catalog can't be updated">Ɓáaka resource catalog ŋanna amikwa</string>
<!-- Context: Background download messages-->
<string name="catalog_download_start_in_background" comment="Notification that the resource catalog update will begin">Catalog update fantufe am táne</string>
<!-- Context: Background download messages-->
<string name="catalog_download_is_running_in_background" comment="Notification that the resource catalog update is still downloading"> Catalog ŋanna aŋkwa ba njane tsukwa; tazlaŋa gwadana-gwada adaliya!</string>
<!-- Context: Background download messages-->
<string name="progress_message_checking_resource_is_running" comment="Progress notification that the check for a resource is still running ">Zharana-zhara resource</string>
<!-- Context: Background download messages-->
<string name="keyboard_download_start_in_background" comment="Notification that a keyboard download has started">Tsukwanahe keyboard a fantuhe am táne</string>
<!-- Context: Background download messages-->
<string name="keyboard_download_is_running_in_background" comment="Notification that a keyboard download is still running">Keyboard na a ksa nde ŋanna aŋkwa tsukwa; tazlaŋa gwadana-gwada adaliya!</string>
<!-- Context: Background download messages-->
<string name="keyboard_download_finished" comment="Notification that a keyboard download has finished">Zlawzle Keyboard ŋanna a tsukwa!</string>
<!-- Context: Background download messages-->
<string name="dictionary_download_start_in_background" comment="Notification that a dictionary download has started">Tsukwanahe dictionary fantuhe am táne</string>
<!-- Context: Background download messages-->
<string name="dictionary_download_is_running_in_background" comment="Notification that a dictionary download is still running">Dictionary na a ksa nde ŋanna aŋkwa tsukwa; tazlaŋa gwadana-gwada adaliya!</string>
<!-- Context: Background download messages-->
<string name="dictionary_download_finished" comment="Notification that a dictionary download has finished">Zlawzle Dictionary ŋanna a tsukwa.</string>
<!-- Context: Background download messages -->
<string name="download_failed" comment="Notification that a download failed">Kwalla-kwale tsukwa</string>
<!-- Context: Background download messages -->
<string name="failed_to_retrieve_file" comment="Failed to retrieve downloaded file">Kwalla-kwale sanhe file na a tsukwana nde ŋanna</string>
<!-- Context: General Updates -->
<string name="update_check_unavailable" comment="Error message when a Keyman server can't be reached">Kwalla-kwale sha server!</string>
<!-- Context: General Updates -->
<string name="update_check_current" comment="Notification that all resources are up to date">"Baɗumma resources ŋanna ba kalkale a dem vatena!"</string>
<!-- Context: General Updates -->
<string name="update_failed" comment="Notification that a resource update failed">Pállé mtu jawje resources kwalla-kwale maga update!</string>
<!-- Context: General Updates -->
<string name="update_success" comment="Notification that a resource update successfully updated">Resources updated ba shagera!</string>
<!-- Context: Model Info -->
<string name="model_version" comment="Title for a dictionary version">Dictionary version</string>
<!-- Context: Model Info -->
<string name="uninstall_model" comment="Label to uninstall a dictionary">Tiɗase-tiɗe dictionary</string>
<!-- Context: Model Info -->
<string name="confirm_delete_model" comment="Confirmation to delete a dictionary">Ká kátáhe gaggahe una gé dictionary?</string>
<!-- Context: Language Settings Keyboard install strings -->
<string name="keyboard_install_toast" comment="Notification when a keyboard is installed">%1$s keyboard an fa</string>
<!-- Context: Language Settings menu strings -->
<string name="enable_corrections" comment="Enable corrections from the suggestion banner">Magave kaɓa kuskure</string>
<!-- Context: Language Settings menu strings -->
<string name="enable_predictions" comment="Enable predictions from the suggestion banner">Magave predictions</string>
<!-- Context: Language Settings menu strings -->
<string name="model_label">Dictionary</string>
<!-- Context: Language Settings menu substring - Check for available dictionary -->
<string name="check_available_model" comment="Check for available dictionary">Zharana-zhara dictionary na aŋkwa na</string>
<!-- Context: Language Settings menu strings -->
<string name="model_info_header" comment="Dictionary name">Dictionary: %1$s</string>
<!-- Context: Language Settings menu strings -->
<string name="model_picker_header" comment="Dictionaries for a specified language">%1$s dictionaries</string>
<!-- Context: Language Settings menu strings -->
<!-- Context: Language Settings menu strings -->
<string name="model_install_toast" comment="Notification when a dictionary is installed">Dictionary an fa</string>
<!-- Context: Language Settings menu strings -->
<plurals name="keyboard_count">
<item quantity="one">(%1$d keyboard)</item>
<item quantity="other">(%1$d keyboards)</item>
</plurals>
<!-- Context: "Change Display Language" menu -->
<string name="default_locale" comment="Use the device's current locale">Default Locale</string>
<!-- Context: Content descriptions -->
<!-- Context: Content descriptions -->
<!-- Context: Popup menu labels -->
<string name="label_delete" comment="Confirmation to delete an item">Gaggahe</string>
<!-- Context: Shared preferences name -->
<!-- Context: Other strings -->
<string name="help_bubble_text">Piyana-piya mátána gé mbeɗa keyboard</string>
</resources>

View file

@ -28,7 +28,7 @@ Step 5)
The bottom of the keyboard settings menu displays an option to uninstall the keyboard.
Select 'Uninstall keyboard' to get a prompt to delete the keyboard.
**Note:** The default 'SIL EuroLatin' keyboard for English cannot be removed.
**Note:** Two or more keyboards need to be installed in order to display this option of uninstalling a keyboard.
![](../android_images/settings-khmer-info-ap.png)

View file

@ -11,3 +11,9 @@ VERSION.md
shellHelperFunctions.sh
src/rust/keyman_keyboard_processor/target/
# The following files/subdirs are generated by autotools when building ibus-keyman.
# They can be removed after we convert ibus-keyman to use meson.
.deps/
.dirstamp
*.o

View file

@ -659,6 +659,12 @@ typedef struct {
km_kbp_option_item const * default_options;
} km_kbp_keyboard_attrs;
typedef struct {
km_kbp_virtual_key key;
uint32_t modifier_flag;
} km_kbp_keyboard_key;
#define KM_KBP_KEYBOARD_KEY_LIST_END { 0, 0 }
/*
```
### `km_kbp_keyboard_load`
@ -725,6 +731,43 @@ km_kbp_status
km_kbp_keyboard_get_attrs(km_kbp_keyboard const *keyboard,
km_kbp_keyboard_attrs const **out);
/*
```
### `km_kbp_keyboard_get_key_list`
##### Description:
Returns the unordered full set of modifier+virtual keys that are handled by the
keyboard. The matching dispose call needs to be called to free the memory.
##### Return status:
- `KM_KBP_STATUS_OK`: On success.
- `KM_KBP_STATUS_INVALID_ARGUMENT`: If non-optional parameters are null.
##### Parameters:
- __keyboard__: A pointer to the opaque keyboard object to be queried.
- __out__: A pointer to an array of `km_kbp_keyboard_key` structures,
terminated by `KM_KBP_KEYBOARD_KEY_LIST_END`.
```c
*/
KMN_API
km_kbp_status
km_kbp_keyboard_get_key_list(km_kbp_keyboard const *keyboard,
km_kbp_keyboard_key **out);
/*
```
### `km_kbp_keyboard_key_list_dispose`
##### Description:
Free the allocated memory belonging to a keyboard key list previously
returned by `km_kbp_keyboard_get_key_list`.
##### Parameters:
- __keyboard__: A pointer to the keyboard key list to be
disposed of.
```c
*/
void km_kbp_keyboard_key_list_dispose(km_kbp_keyboard_key *key_list);
/*
```
### State

View file

@ -81,3 +81,20 @@ km_kbp_keyboard_get_attrs(km_kbp_keyboard const *keyboard,
*out = &keyboard->keyboard();
return KM_KBP_STATUS_OK;
}
km_kbp_status
km_kbp_keyboard_get_key_list(km_kbp_keyboard const *keyboard,
km_kbp_keyboard_key **out)
{
assert(keyboard); assert(out);
if (!keyboard || !out)
return KM_KBP_STATUS_INVALID_ARGUMENT;
*out = keyboard->get_key_list();
return KM_KBP_STATUS_OK;
}
void km_kbp_keyboard_key_list_dispose(km_kbp_keyboard_key *key_list)
{
delete[] key_list;
}

View file

@ -0,0 +1,128 @@
#include "kmx_processevent.h"
using namespace km::kbp;
using namespace kmx;
/* This array is lifted from preservedkeymap.cpp */
const struct
{
KMX_DWORD key;
KMX_BOOL shift;
} USCharMap[] = {
{ VK_SPACE, FALSE }, // 20 ' '
{ '1', TRUE }, // 21 '!'
{ VK_QUOTE, TRUE }, // 22 '"'
{ '3', TRUE }, // 23 '#'
{ '4', TRUE }, // 24 '$'
{ '5', TRUE }, // 25 '%'
{ '7', TRUE }, // 26 '&'
{ VK_QUOTE, FALSE }, // 27 '''
{ '9', TRUE }, // 28 '('
{ '0', TRUE }, // 29 ')'
{ '8', TRUE }, // 2A '*'
{ VK_EQUAL, TRUE }, // 2B '+'
{ VK_COMMA, FALSE }, // 2C ','
{ VK_HYPHEN, FALSE }, // 2D '-'
{ VK_PERIOD, FALSE }, // 2E '.'
{ VK_SLASH, FALSE }, // 2F '/'
{ '0', FALSE }, // 30 '0'
{ '1', FALSE }, // 31 '1'
{ '2', FALSE }, // 32 '2'
{ '3', FALSE }, // 33 '3'
{ '4', FALSE }, // 34 '4'
{ '5', FALSE }, // 35 '5'
{ '6', FALSE }, // 36 '6'
{ '7', FALSE }, // 37 '7'
{ '8', FALSE }, // 38 '8'
{ '9', FALSE }, // 39 '9'
{ VK_COLON, TRUE }, // 3A ':'
{ VK_COLON, FALSE }, // 3B ';'
{ VK_COMMA, TRUE }, // 3C '<'
{ VK_EQUAL, FALSE }, // 3D '='
{ VK_PERIOD, TRUE }, // 3E '>'
{ VK_SLASH, TRUE }, // 3F '?'
{ '2', TRUE }, // 40 '@'
{ 'A', TRUE }, // 41 'A'
{ 'B', TRUE }, // 42 'B'
{ 'C', TRUE }, // 43 'C'
{ 'D', TRUE }, // 44 'D'
{ 'E', TRUE }, // 45 'E'
{ 'F', TRUE }, // 46 'F'
{ 'G', TRUE }, // 47 'G'
{ 'H', TRUE }, // 48 'H'
{ 'I', TRUE }, // 49 'I'
{ 'J', TRUE }, // 4A 'J'
{ 'K', TRUE }, // 4B 'K'
{ 'L', TRUE }, // 4C 'L'
{ 'M', TRUE }, // 4D 'M'
{ 'N', TRUE }, // 4E 'N'
{ 'O', TRUE }, // 4F 'O'
{ 'P', TRUE }, // 50 'P'
{ 'Q', TRUE }, // 51 'Q'
{ 'R', TRUE }, // 52 'R'
{ 'S', TRUE }, // 53 'S'
{ 'T', TRUE }, // 54 'T'
{ 'U', TRUE }, // 55 'U'
{ 'V', TRUE }, // 56 'V'
{ 'W', TRUE }, // 57 'W'
{ 'X', TRUE }, // 58 'X'
{ 'Y', TRUE }, // 59 'Y'
{ 'Z', TRUE }, // 5A 'Z'
{ VK_LBRKT, FALSE }, // 5B '['
{ VK_BKSLASH, FALSE }, // 5C '\'
{ VK_RBRKT, FALSE }, // 5D ']'
{ '6', TRUE }, // 5E '^'
{ VK_HYPHEN, TRUE }, // 5F '_'
{ VK_ACCENT, FALSE }, // 60 '`'
{ 'A', FALSE }, // 61 'a'
{ 'B', FALSE }, // 62 'b'
{ 'C', FALSE }, // 63 'c'
{ 'D', FALSE }, // 64 'd'
{ 'E', FALSE }, // 65 'e'
{ 'F', FALSE }, // 66 'f'
{ 'G', FALSE }, // 67 'g'
{ 'H', FALSE }, // 68 'h'
{ 'I', FALSE }, // 69 'i'
{ 'J', FALSE }, // 6A 'j'
{ 'K', FALSE }, // 6B 'k'
{ 'L', FALSE }, // 6C 'l'
{ 'M', FALSE }, // 6D 'm'
{ 'N', FALSE }, // 6E 'n'
{ 'O', FALSE }, // 6F 'o'
{ 'P', FALSE }, // 70 'p'
{ 'Q', FALSE }, // 71 'q'
{ 'R', FALSE }, // 72 'r'
{ 'S', FALSE }, // 73 's'
{ 'T', FALSE }, // 74 't'
{ 'U', FALSE }, // 75 'u'
{ 'V', FALSE }, // 76 'v'
{ 'W', FALSE }, // 77 'w'
{ 'X', FALSE }, // 78 'x'
{ 'Y', FALSE }, // 79 'y'
{ 'Z', FALSE }, // 7A 'z'
{ VK_LBRKT, TRUE }, // 7B '{'
{ VK_BKSLASH, TRUE }, // 7C '|'
{ VK_RBRKT, TRUE }, // 7D '}'
{ VK_ACCENT, TRUE } // 7E '~'
};
KMX_BOOL km::kbp::kmx::MapUSCharToVK(KMX_WORD ch, PKMX_WORD puKey, PKMX_DWORD puShiftFlags) {
assert(puKey != NULL);
assert(puShiftFlags != NULL);
if (ch >= 0x20 && ch < 0x7F) {
*puKey = USCharMap[ch - 0x20].key;
*puShiftFlags = ISVIRTUALKEY | (USCharMap[ch - 0x20].shift ? K_SHIFTFLAG : 0);
return TRUE;
}
return FALSE;
}

View file

@ -0,0 +1,36 @@
#pragma once
#include "kmx_base.h"
namespace km {
namespace kbp {
namespace kmx {
#define VK_SPACE 0x20
#define VK_COLON 0xBA
#define VK_EQUAL 0xBB
#define VK_COMMA 0xBC
#define VK_HYPHEN 0xBD
#define VK_PERIOD 0xBE
#define VK_SLASH 0xBF
#define VK_ACCENT 0xC0
#define VK_LBRKT 0xDB
#define VK_BKSLASH 0xDC
#define VK_RBRKT 0xDD
#define VK_QUOTE 0xDE
#define VK_xDF 0xDF
/**
* This maps an ASCII character corresponding to a US EN key cap to a
* Virtual Key and correctly sets the Shift BIT in the ShiftFlag DWORD.
*
* @param ch The character to be mapped
* @param puKey [in,out] Converted virtual key if ch was a ASCII character
* @param puShiftFlags [in,out] K_SHIFTFLAG BIT will be maybe modified as result of conversion
* @return KMX_BOOL True if conversion occurred
*/
KMX_BOOL MapUSCharToVK(KMX_WORD ch, PKMX_WORD puKey, PKMX_DWORD puShiftFlags);
} // namespace kmx
} // namespace kbp
} // namespace km

View file

@ -3,6 +3,7 @@
Authors: mcdurdin
*/
#include "kmx_processevent.h"
#include <assert.h>
using namespace km::kbp;
using namespace kmx;
@ -18,6 +19,37 @@ KMX_BOOL KMX_ProcessEvent::Load(km_kbp_path_name KeyboardName)
return TRUE;
}
const int km::kbp::kmx::CODE__SIZE[] = {
-1, // undefined 0x00
1, // CODE_ANY 0x01
2, // CODE_INDEX 0x02
0, // CODE_CONTEXT 0x03
0, // CODE_NUL 0x04
1, // CODE_USE 0x05
0, // CODE_RETURN 0x06
0, // CODE_BEEP 0x07
1, // CODE_DEADKEY 0x08
-1, // unused 0x09
2, // CODE_EXTENDED 0x0A
-1, // CODE_EXTENDEDEND 0x0B (unused)
1, // CODE_SWITCH 0x0C
-1, // CODE_KEY 0x0D (never used)
0, // CODE_CLEARCONTEXT 0x0E
1, // CODE_CALL 0x0F
-1, // UC_SENTINEL_EXTENDEDEND 0x10 (not valid with UC_SENTINEL)
1, // CODE_CONTEXTEX 0x11
1, // CODE_NOTANY 0x12
2, // CODE_SETOPT 0x13
3, // CODE_IFOPT 0x14
1, // CODE_SAVEOPT 0x15
1, // CODE_RESETOPT 0x16
3, // CODE_IFSYSTEMSTORE 0x17
2 // CODE_SETSYSTEMSTORE 0x18
};
// Ensure that all CODE_### sizes are defined
static_assert(sizeof(CODE__SIZE) / sizeof(CODE__SIZE[0]) == (CODE_LASTCODE + 1), "Size of array CODE__SIZE not correct");
const unsigned long CRCTable[256] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
@ -51,8 +83,7 @@ const unsigned long CRCTable[256] = {
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
};
/*
* This routine calculates the CRC for a block of data using the
* table lookup method. It accepts an original value for the crc,

View file

@ -42,9 +42,11 @@ namespace kmx {
#define VERSION_80 0x00000800
#define VERSION_90 0x00000900
#define VERSION_100 0x00000A00
#define VERSION_140 0x00000E00
#define VERSION_150 0x00000F00
#define VERSION_MIN VERSION_50
#define VERSION_MAX VERSION_100
#define VERSION_MAX VERSION_150
//
// Backspace types
@ -273,6 +275,9 @@ typedef COMP_STORE *PCOMP_STORE;
typedef COMP_KEY *PCOMP_KEY;
typedef COMP_GROUP *PCOMP_GROUP;
extern const int CODE__SIZE[];
#define CODE__SIZE_MAX 5
#define KEYBOARDFILEHEADER_SIZE 64
#define KEYBOARDFILESTORE_SIZE 12
#define KEYBOARDFILEGROUP_SIZE 24

View file

@ -764,7 +764,7 @@ KMX_Environment const *KMX_ProcessEvent::GetEnvironment() const {
return &m_environment;
}
LPINTKEYBOARDINFO KMX_ProcessEvent::GetKeyboard() {
INTKEYBOARDINFO const *KMX_ProcessEvent::GetKeyboard() const {
return &m_keyboard;
}

View file

@ -8,8 +8,10 @@
#include "kmx_base.h"
#include "kmx_file.h"
#include "kmx_context.h"
#include "kmx_conversion.h"
#include "kmx_actions.h"
#include "kmx_xstring.h"
#include "kmx_actions.h"
#include "kmx_options.h"
#include "kmx_environment.h"
#include "kmx_debugger.h"
@ -98,7 +100,7 @@ public:
KMX_Options const *GetOptions() const;
KMX_Environment *GetEnvironment();
KMX_Environment const *GetEnvironment() const;
LPINTKEYBOARDINFO GetKeyboard();
INTKEYBOARDINFO const *GetKeyboard() const;
};
inline KMX_BOOL KMX_ProcessEvent::IsCapsLockOn(KMX_DWORD modifiers) {

View file

@ -1,6 +1,7 @@
#include <keyman/keyboardprocessor.h>
#include "state.hpp"
#include "kmx/kmx_processor.hpp"
#include <map>
using namespace km::kbp;
using namespace kmx;
@ -194,3 +195,48 @@ constexpr km_kbp_attr const engine_attrs = {
km_kbp_attr const & kmx_processor::attributes() const {
return engine_attrs;
}
km_kbp_keyboard_key * kmx_processor::get_key_list() const {
// Iterate through the groups and get the rules with virtual keys
// and store the key along with the modifer.
const uint32_t group_cnt = _kmx.GetKeyboard()->Keyboard->cxGroupArray;
const LPGROUP group_array = _kmx.GetKeyboard()->Keyboard->dpGroupArray;
GROUP *p_group;
std::map<std::pair<km_kbp_virtual_key,uint32_t>, uint32_t> map_rules;
km_kbp_virtual_key v_key;
uint32_t modifier_flag;
// Use hash map to get the unique list
for(auto i = decltype(group_cnt){0}; i < group_cnt; i++)
{
p_group = &group_array[i];
if(p_group->fUsingKeys)
{
for(auto j = decltype(p_group->cxKeyArray){0}; j < p_group->cxKeyArray; j++)
{
v_key = p_group->dpKeyArray[j].Key;
modifier_flag = p_group->dpKeyArray[j].ShiftFlags;
if(modifier_flag == 0) {
// This must be a ASCII character corresponding US Keyboard key cap
if(!MapUSCharToVK(v_key, &v_key, &modifier_flag)) continue;
}
map_rules[std::make_pair(v_key,modifier_flag)] = (modifier_flag & K_MODIFIERFLAG); // Clear kmx special flags
}
}
}
// Now convert to the keyboard key array
km_kbp_keyboard_key *rules = new km_kbp_keyboard_key[map_rules.size() + 1];
std::map<std::pair<km_kbp_virtual_key,uint32_t>, uint32_t>::iterator it = map_rules.begin();
int n = 0;
while (it != map_rules.end()){
auto pair = it->first;
rules[n].key = pair.first;
rules[n].modifier_flag = it->second;
it++;
n++;
}
// Insert list termination
rules[n] = KM_KBP_KEYBOARD_KEY_LIST_END;
return rules;
}

View file

@ -48,6 +48,14 @@ namespace kbp
std::u16string const & key,
std::u16string const & value
) override;
/**
* Get the list of keys belonging to the keyboard rules.
*
* @return km_kbp_keyboard_key*
*/
km_kbp_keyboard_key * get_key_list() const override;
};
} // namespace kbp

View file

@ -9,8 +9,6 @@
#include "kmx_processevent.h"
#include "utfcodec.hpp"
using namespace km::kbp;
using namespace kmx;
@ -116,49 +114,53 @@ km_kbp_cp *km::kbp::kmx::u16tok(km_kbp_cp *p, km_kbp_cp ch, km_kbp_cp **ctx) {
*
* xstrlen calculates the length of a string, ignoring some special chars.
*/
PKMX_WCHAR km::kbp::kmx::incxstr(PKMX_WCHAR p) {
PKMX_WCHAR km::kbp::kmx::incxstr(PKMX_WCHAR p)
{
if(*p == 0) return p;
if(*p != UC_SENTINEL)
{
if(*p >= 0xD800 && *p <= 0xDBFF && *(p+1) >= 0xDC00 && *(p+1) <= 0xDFFF) return p+2;
return p+1;
if (*p == 0)
return p;
if (*p != UC_SENTINEL) {
if (*p >= 0xD800 && *p <= 0xDBFF && *(p + 1) >= 0xDC00 && *(p + 1) <= 0xDFFF)
return p + 2;
return p + 1;
}
// UC_SENTINEL(FFFF) with UC_SENTINEL_EXTENDEDEND(0x10) == variable length
if (*(p + 1) == CODE_EXTENDED) {
p += 2;
while (*p && *p != UC_SENTINEL_EXTENDEDEND)
p++;
if (*p == 0) return p;
return p + 1;
}
p+=2;
switch(*(p-1))
{
case CODE_ANY: return p+1;
case CODE_NOTANY: return p+1;
case CODE_INDEX: return p+2;
case CODE_USE: return p+1;
case CODE_DEADKEY: return p+1;
case CODE_EXTENDED: p += 2; while(*p && *p != UC_SENTINEL_EXTENDEDEND) p++; return p+1;
case CODE_CLEARCONTEXT: return p+1;
case CODE_CALL: return p+1;
case CODE_CONTEXTEX: return p+1;
case CODE_IFOPT: return p+3;
case CODE_IFSYSTEMSTORE: return p+3;
case CODE_SETOPT: return p+2;
case CODE_SETSYSTEMSTORE: return p+2;
case CODE_RESETOPT: return p+1;
case CODE_SAVEOPT: return p+1;
default: return p;
if (*(p + 1) > CODE_LASTCODE || CODE__SIZE[*(p + 1)] == -1) {
return p + 1;
}
int deltaptr = 2 + CODE__SIZE[*(p + 1)];
// check for \0 between UC_SENTINEL(FFFF) and next printable character
for (int i = 0; i < deltaptr; i++) {
if (*p == 0)
return p;
p++;
}
return p;
}
PKMX_WCHAR km::kbp::kmx::decxstr(PKMX_WCHAR p, PKMX_WCHAR pStart)
{
PKMX_WCHAR q;
if(p <= pStart) {
return NULL;
}
p--;
if(*p == UC_SENTINEL_EXTENDEDEND)
{
if(*p == UC_SENTINEL_EXTENDEDEND) {
int n = 0;
while(*p != UC_SENTINEL && n < 10) { p--; n++; }
while (p >= pStart && *p != UC_SENTINEL && n < 10) {
p--; n++; }
if(p < pStart) {
// May be a malformed virtual key
@ -167,49 +169,26 @@ PKMX_WCHAR km::kbp::kmx::decxstr(PKMX_WCHAR p, PKMX_WCHAR pStart)
return p;
}
if(p == pStart) return p; // Don't allow test before pStart
if (p == pStart) {
// Don't allow test before pStart
return p;
}
if(*p >= 0xDC00 && *p <= 0xDFFF && *(p-1) >= 0xD800 && *(p-1) <= 0xDBFF)
{
if(*p >= 0xDC00 && *p <= 0xDFFF && *(p-1) >= 0xD800 && *(p-1) <= 0xDBFF) {
return p-1;
}
else if(*(p-1) == UC_SENTINEL) return p-1;
else if(p > pStart+1 && *(p-2) == UC_SENTINEL)
{
switch(*(p-1))
{
case CODE_ANY:
case CODE_NOTANY:
case CODE_USE:
case CODE_DEADKEY:
case CODE_CLEARCONTEXT:
case CODE_CALL:
case CODE_CONTEXTEX:
case CODE_RESETOPT:
case CODE_SAVEOPT:
return p-2;
}
// Look for a UC_SENTINEL to jump to
// note: If we are pointing to the middle of a UC_SENTINEL CODE_x, then we won't treat it as valid,
// and will just go back a single wchar
q = p;
for (int i = 0; i < CODE__SIZE_MAX && q >= pStart; i++, q--) {
// *q == UC_SENTINEL && *(q + 1) is within CODE__SIZE && next CODE_ right of UC_SENTINEL ( looked up in CODE__SIZE+1) has value i
if (*q == UC_SENTINEL && *(q + 1) <= CODE_LASTCODE && CODE__SIZE[*(q + 1)] + 1 == i)
return q;
}
else if(p > pStart+2 && *(p-3) == UC_SENTINEL)
{
switch(*(p-2))
{
case CODE_INDEX:
case CODE_SETOPT:
case CODE_SETSYSTEMSTORE:
return p-3;
}
}
else if(p > pStart+3 && *(p-4) == UC_SENTINEL)
{
switch(*(p-3))
{
case CODE_IFOPT:
case CODE_IFSYSTEMSTORE: // I3432
return p-4;
}
}
return p;
return p;
}
int km::kbp::kmx::xstrlen_ignoreifopt(PKMX_WCHAR p)
@ -262,7 +241,6 @@ PKMX_WCHAR km::kbp::kmx::strtowstr(PKMX_CHAR in)
return result;
}
PKMX_CHAR km::kbp::kmx::wstrtostr(PKMX_WCHAR in)
{
PKMX_CHAR result;

View file

@ -35,6 +35,8 @@ int u16icmp(const km_kbp_cp *p, const km_kbp_cp *q);
int u16ncmp(const km_kbp_cp *p, const km_kbp_cp *q, size_t count);
km_kbp_cp *u16tok(km_kbp_cp *p, km_kbp_cp ch, km_kbp_cp **ctx);
//KMX_BOOL MapUSCharToVK(KMX_WORD ch, PKMX_WORD puKey, PKMX_DWORD puShiftFlags);
} // namespace kmx
} // namespace kbp
} // namespace km

View file

@ -78,6 +78,7 @@ lib = library('kmnkbp0',
'kmx/kmx_actions.cpp',
'kmx/kmx_capslock.cpp',
'kmx/kmx_context.cpp',
'kmx/kmx_conversion.cpp',
'kmx/kmx_debug.cpp',
'kmx/kmx_debugger.cpp',
'kmx/kmx_environment.cpp',

View file

@ -182,6 +182,10 @@ namespace km {
return engine_attrs;
}
km_kbp_keyboard_key * mock_processor::get_key_list() const {
km_kbp_keyboard_key* key_list = new km_kbp_keyboard_key(KM_KBP_KEYBOARD_KEY_LIST_END);
return key_list;
}
km_kbp_status mock_processor::validate() const { return KM_KBP_STATUS_OK; }
km_kbp_status null_processor::validate() const { return KM_KBP_STATUS_INVALID_ARGUMENT; }

View file

@ -50,6 +50,9 @@ namespace kbp
std::u16string const & key,
std::u16string const & value
) override;
km_kbp_keyboard_key * get_key_list() const override;
};
class null_processor : public mock_processor {

View file

@ -60,6 +60,9 @@ namespace kbp
std::u16string const & value
) = 0;
virtual km_kbp_keyboard_key *
get_key_list() const = 0;
friend json & operator << (json &j, abstract_processor const &opts);
};

View file

@ -74,6 +74,10 @@ namespace km {
return engine_attrs;
}
km_kbp_keyboard_key * rust_mock_processor::get_key_list() const {
km_kbp_keyboard_key* key_list = new km_kbp_keyboard_key(KM_KBP_KEYBOARD_KEY_LIST_END);
return key_list;
}
km_kbp_status rust_mock_processor::validate() const { return KM_KBP_STATUS_OK; }
km_kbp_status rust_null_processor::validate() const { return KM_KBP_STATUS_INVALID_ARGUMENT; }

View file

@ -47,6 +47,9 @@ namespace kbp
std::u16string const & key,
std::u16string const & value
) override;
km_kbp_keyboard_key * get_key_list() const override;
};
class rust_null_processor : public rust_mock_processor {

View file

@ -21,8 +21,4 @@ if get_option('default_library') != 'static'
endif
endif
subdir('unit/json')
subdir('unit/utftest')
subdir('unit/kmnkbd')
subdir('unit/kmx')
subdir('unit/rust_mock')
subdir('unit')

View file

@ -23,13 +23,17 @@ int main(int, char *[])
{
km_kbp_keyboard * test_kb = nullptr;
km_kbp_keyboard_attrs const * kb_attrs = nullptr;
km_kbp_keyboard_key * kb_key_list = nullptr;
try_status(km_kbp_keyboard_load(test_kb_path.c_str(), &test_kb));
try_status(km_kbp_keyboard_get_attrs(test_kb, &kb_attrs));
try_status(km_kbp_keyboard_get_key_list(test_kb,&kb_key_list));
if (kb_attrs->folder_path != test_kb_path.parent())
return __LINE__;
km_kbp_keyboard_dispose(test_kb);
km_kbp_keyboard_key_list_dispose(kb_key_list);
return 0;
}

View file

@ -2,7 +2,6 @@
# Description: Cross platform build script to compile libkmnkbp API unit tests.
# Create Date: 19 Oct 2018
# Authors: Tim Eves (TSE)
# History: 19 Oct 2018 - TSE - Added test for context API functions.
#
defns=['-DKMN_KBP_STATIC']
@ -12,6 +11,7 @@ tests = [
['options-api', 'options_api.cpp'],
['state-api', 'state_api.cpp'],
['debug-api', 'debug_api.cpp'],
['kmx_xstring', 'test_kmx_xstring.cpp'],
]
foreach t : tests

File diff suppressed because it is too large Load diff

View file

@ -6,14 +6,14 @@ c 4. Two deadkeys in a row in context dk(4a) dk(4b) + BKSP = nul
c 5. One char and two deadkeys in context 'a' dk(5a) dk(5b) 'b' + BKSP = 'a'
c 6. One char and two deadkeys and one char and two deadkeys in context 'a' dk(6a) dk(6b) 'b' dk(6c) dk(6d) + BKSP = 'a'
c keys: [K_1][K_BKSP][K_2][K_BKSP][K_3][K_BKSP][K_4][K_BKSP][K_5][K_BKSP][K_6][K_BKSP]
c expected: 12aa
c context: 1234
c expected: 78aa
c context: 7890
store(&VERSION) '9.0'
begin unicode > use(main)
group(main) using keys
group(main) using keys
+ '1' > dk(1)
+ '2' > 'a' dk(2)

View file

@ -1,416 +0,0 @@
{
"system": {
"keymanDeveloperVersion": "10.0.1099.0",
"fileVersion": "7.0"
},
"options": {
"readmeFile": "kmx.cpp"
},
"info": {
"name": {
"description": "Test Keyboards"
},
"version": {
"description": "0.0"
},
"copyright": {
"description": "\u00A9 2018 SIL International"
},
"author": {
"description": ""
}
},
"files": [
{
"name": "kmp.json",
"description": "Package information (JSON)"
}
],
"keyboards": [
{
"name": "000 - null keyboard",
"id": "000 - null keyboard",
"version": "0.0",
"languages": [
{
"name": "Undetermined",
"id": "und"
}
]
},
{
"name": "001 - basic input UnicodeI",
"id": "001 - basic input UnicodeI",
"version": "0.0",
"languages": [
{
"name": "Undetermined",
"id": "und"
}
]
},
{
"name": "002 - basic input Unicode",
"id": "002 - basic input Unicode",
"version": "0.0",
"languages": [
{
"name": "Undetermined",
"id": "und"
}
]
},
{
"name": "003 - nul",
"id": "003 - nul",
"version": "0.0",
"languages": [
{
"name": "Undetermined",
"id": "und"
}
]
},
{
"name": "004 - basic input (shift 2)",
"id": "004 - basic input (shift 2)",
"version": "0.0",
"languages": [
{
"name": "Undetermined",
"id": "und"
}
]
},
{
"name": "005 - nul with initial context",
"id": "005 - nul with initial context",
"version": "0.0",
"languages": [
{
"name": "Undetermined",
"id": "und"
}
]
},
{
"name": "006 - vkey input (shift ctrl)",
"id": "006 - vkey input (shift ctrl)",
"version": "0.0",
"languages": [
{
"name": "Undetermined",
"id": "und"
}
]
},
{
"name": "007 - vkey input (ctrl alt)",
"id": "007 - vkey input (ctrl alt)",
"version": "0.0",
"languages": [
{
"name": "Undetermined",
"id": "und"
}
]
},
{
"name": "008 - vkey input (ctrl alt 2)",
"id": "008 - vkey input (ctrl alt 2)",
"version": "0.0",
"languages": [
{
"name": "Undetermined",
"id": "und"
}
]
},
{
"name": "012 - ralt",
"id": "012 - ralt",
"version": "0.0",
"languages": [
{
"name": "Undetermined",
"id": "und"
}
]
},
{
"name": "013 - deadkeys",
"id": "013 - deadkeys",
"version": "0.0",
"languages": [
{
"name": "Undetermined",
"id": "und"
}
]
},
{
"name": "014 - groups and virtual keys",
"id": "014 - groups and virtual keys",
"version": "0.0",
"languages": [
{
"name": "Undetermined",
"id": "und"
}
]
},
{
"name": "015 - ralt 2",
"id": "015 - ralt 2",
"version": "0.0",
"languages": [
{
"name": "Undetermined",
"id": "und"
}
]
},
{
"name": "017 - space mnemonic kbd",
"id": "017 - space mnemonic kbd",
"version": "0.0",
"languages": [
{
"name": "Undetermined",
"id": "und"
}
]
},
{
"name": "018 - nul testing",
"id": "018 - nul testing",
"version": "0.0",
"languages": [
{
"name": "Undetermined",
"id": "und"
}
]
},
{
"name": "019 - multiple deadkeys",
"id": "019 - multiple deadkeys",
"version": "0.0",
"languages": [
{
"name": "Undetermined",
"id": "und"
}
]
},
{
"name": "020 - deadkeys and backspace",
"id": "020 - deadkeys and backspace",
"version": "0.0",
"languages": [
{
"name": "Undetermined",
"id": "und"
}
]
},
{
"name": "021 - options",
"id": "021 - options",
"version": "0.0",
"languages": [
{
"name": "Undetermined",
"id": "und"
}
]
},
{
"name": "022 - options with preset",
"id": "022 - options with preset",
"version": "0.0",
"languages": [
{
"name": "Undetermined",
"id": "und"
}
]
},
{
"name": "023 - options with save",
"id": "023 - options with save",
"version": "0.0",
"languages": [
{
"name": "Undetermined",
"id": "und"
}
]
},
{
"name": "024 - options with save and preset",
"id": "024 - options with save and preset",
"version": "0.0",
"languages": [
{
"name": "Undetermined",
"id": "und"
}
]
},
{
"name": "025 - options with reset",
"id": "025 - options with reset",
"version": "0.0",
"languages": [
{
"name": "Undetermined",
"id": "und"
}
]
},
{
"name": "026 - system stores",
"id": "026 - system stores",
"version": "0.0",
"languages": [
{
"name": "Undetermined",
"id": "und"
}
]
},
{
"name": "027 - system stores 2",
"id": "027 - system stores 2",
"version": "0.0",
"languages": [
{
"name": "Undetermined",
"id": "und"
}
]
},
{
"name": "028 - smp",
"id": "028 - smp",
"version": "0.0",
"languages": [
{
"name": "Undetermined",
"id": "und"
}
]
},
{
"name": "029 - beep",
"id": "029 - beep",
"version": "0.0",
"languages": [
{
"name": "Undetermined",
"id": "und"
}
]
},
{
"name": "030 - multiple groups",
"id": "030 - multiple groups",
"version": "0.0",
"languages": [
{
"name": "Undetermined",
"id": "und"
}
]
},
{
"name": "031 - caps lock",
"id": "031 - caps lock",
"version": "0.0",
"languages": [
{
"name": "Undetermined",
"id": "und"
}
]
},
{
"name": "032 - caps control",
"id": "032 - caps control",
"version": "0.0",
"languages": [
{
"name": "Undetermined",
"id": "und"
}
]
},
{
"name": "033 - caps always off",
"id": "033 - caps always off",
"version": "0.0",
"languages": [
{
"name": "Undetermined",
"id": "und"
}
]
},
{
"name": "038 - punctkeys",
"id": "038 - punctkeys",
"version": "0.0",
"languages": [
{
"name": "Undetermined",
"id": "und"
}
]
},
{
"name": "039 - generic ctrlalt",
"id": "039 - generic ctrlalt",
"version": "0.0",
"languages": [
{
"name": "Undetermined",
"id": "und"
}
]
},
{
"name": "040 - long context",
"id": "040 - long context",
"version": "0.0",
"languages": [
{
"name": "Undetermined",
"id": "und"
}
]
},
{
"name": "041 - long context and deadkeys",
"id": "041 - long context and deadkeys",
"version": "0.0",
"languages": [
{
"name": "Undetermined",
"id": "und"
}
]
},
{
"name": "042 - long context and split deadkeys",
"id": "042 - long context and split deadkeys",
"version": "0.0",
"languages": [
{
"name": "Undetermined",
"id": "und"
}
]
}
]
}

View file

@ -0,0 +1,32 @@
{
"system": {
"keymanDeveloperVersion": "10.0.1099.0",
"fileVersion": "7.0"
},
"options": {
"readmeFile": "kmx.cpp"
},
"info": {
"name": {
"description": "Test Keyboards"
},
"version": {
"description": "0.0"
},
"copyright": {
"description": "\u00A9 2018 SIL International"
},
"author": {
"description": ""
}
},
"files": [
{
"name": "kmp.json",
"description": "Package information (JSON)"
}
],
"keyboards": [
@keyboards@
]
}

View file

@ -27,159 +27,73 @@
#include "../test_assert.h"
#include "../test_color.h"
namespace
{
#include "kmx_test_source.hpp"
namespace {
bool g_beep_found = false;
bool g_caps_lock_on = false;
struct key_event {
km_kbp_virtual_key vk;
uint16_t modifier_state;
};
typedef enum {
KOT_INPUT,
KOT_OUTPUT,
KOT_SAVED
} kmx_option_type;
struct kmx_option {
kmx_option_type type;
std::u16string key, value, saved_value;
};
using kmx_options = std::vector<kmx_option>;
int load_source(const km::kbp::path &, std::string &, std::u16string &,
std::u16string &, kmx_options &, bool &);
std::string string_to_hex(const std::u16string& input);
km_kbp_option_item test_env_opts[] =
{
KM_KBP_OPTIONS_END
};
// String trim functions from https://stackoverflow.com/a/217605/1836776
// trim from start (in place)
static inline void ltrim(std::string &s) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int ch) {
return !std::isspace(ch);
}));
}
std::string
string_to_hex(const std::u16string &input) {
std::ostringstream result;
result << std::setfill('0') << std::hex << std::uppercase;
// trim from end (in place)
static inline void rtrim(std::string &s) {
s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) {
return !std::isspace(ch);
}).base(), s.end());
}
// trim from both ends (in place)
static inline void trim(std::string &s) {
ltrim(s);
rtrim(s);
}
key_event char_to_event(char ch) {
assert(ch >= 32 && ch <= 127);
return {
km::kbp::kmx::s_char_to_vkey[(int)ch - 32].vk,
(uint16_t)(km::kbp::kmx::s_char_to_vkey[(int)ch - 32].shifted ? KM_KBP_MODIFIER_SHIFT : 0)
};
}
uint16_t get_modifier(std::string const m) {
for (int i = 0; km::kbp::kmx::s_modifier_names[i].name; i++) {
if (m == km::kbp::kmx::s_modifier_names[i].name) {
return km::kbp::kmx::s_modifier_names[i].modifier;
for (size_t i = 0; i < input.length(); i++) {
unsigned int ch = input[i];
if (i < input.length() - 1 && Uni_IsSurrogate1(input[i]) && Uni_IsSurrogate2(input[i + 1])) {
ch = Uni_SurrogateToUTF32(input[i], input[i + 1]);
i++;
}
result << "U+" << std::setw(4) << ch << " ";
}
return 0;
return result.str();
}
km_kbp_virtual_key get_vk(std::string const & vk) {
for (int i = 1; i < 256; i++) {
if (vk == km::kbp::kmx::s_key_names[i]) {
return i;
}
}
return 0;
}
key_event vkey_to_event(std::string const & vk_event) {
// vkey format is MODIFIER MODIFIER K_NAME
//std::cout << "VK=" << vk_event << std::endl;
std::stringstream f(vk_event);
std::string s;
uint16_t modifier_state = 0;
km_kbp_virtual_key vk = 0;
while(std::getline(f, s, ' ')) {
uint16_t modifier = get_modifier(s);
if (modifier != 0) {
modifier_state |= modifier;
}
else {
vk = get_vk(s);
break;
}
}
// The string should be empty at this point
assert(!std::getline(f, s, ' '));
assert(vk != 0);
return {
vk,
modifier_state
};
}
key_event next_key(std::string &keys) {
// Parse the next element of the string, chop it off, and return it
if (keys.length() == 0) return { 0, 0 };
char ch = keys[0];
if (ch == '[') {
if (keys.length() > 1 && keys[1] == '[') {
keys.erase(0, 2);
return char_to_event(ch);
}
auto n = keys.find(']');
assert(n != std::string::npos);
auto vkey = keys.substr(1, n - 1);
keys.erase(0, n+1);
return vkey_to_event(vkey);
}
else {
keys.erase(0, 1);
return char_to_event(ch);
}
}
void apply_action(km_kbp_state const *, km_kbp_action_item const & act, std::u16string & text_store, std::vector<km_kbp_context_item> & context, kmx_options &options) {
switch (act.type)
{
void
apply_action(
km_kbp_state const *,
km_kbp_action_item const &act,
std::u16string &text_store,
std::vector<km_kbp_context_item> &context,
km::tests::kmx_options &options,
km::tests::KmxTestSource &test_source) {
switch (act.type) {
case KM_KBP_IT_END:
assert(false);
break;
case KM_KBP_IT_ALERT:
g_beep_found = true;
//std::cout << "beep" << std::endl;
// std::cout << "beep" << std::endl;
break;
case KM_KBP_IT_CHAR:
context.push_back(km_kbp_context_item{KM_KBP_CT_CHAR, {0,}, {act.character}});
context.push_back(km_kbp_context_item{
KM_KBP_CT_CHAR,
{
0,
},
{act.character}});
if (Uni_IsSMP(act.character)) {
text_store.push_back(Uni_UTF32ToSurrogate1(act.character));
text_store.push_back(Uni_UTF32ToSurrogate2(act.character));
}
else {
} else {
text_store.push_back(act.character);
}
//std::cout << "char(" << act.character << ") size=" << cp->size() << std::endl;
// std::cout << "char(" << act.character << ") size=" << cp->size() << std::endl;
break;
case KM_KBP_IT_MARKER:
//std::cout << "deadkey(" << act.marker << ")" << std::endl;
context.push_back(km_kbp_context_item{KM_KBP_CT_MARKER, {0,}, {(uint32_t)act.marker}});
// std::cout << "deadkey(" << act.marker << ")" << std::endl;
context.push_back(km_kbp_context_item{
KM_KBP_CT_MARKER,
{
0,
},
{(uint32_t)act.marker}});
break;
case KM_KBP_IT_BACK:
// It is valid for a backspace to be received with an empty text store
@ -188,18 +102,17 @@ void apply_action(km_kbp_state const *, km_kbp_action_item const & act, std::u16
// processing at start of a text store, e.g. delete from a previous cell
// in a table. Or, if Keyman has a cached context, then there may be
// additional text in the text store that Keyman can't see.
if(act.backspace.expected_type == KM_KBP_BT_MARKER) {
if (act.backspace.expected_type == KM_KBP_BT_MARKER) {
assert(!context.empty());
assert(context.back().type == KM_KBP_CT_MARKER);
context.pop_back();
}
else if (text_store.length() > 0) {
} else if (text_store.length() > 0) {
assert(!context.empty() && !text_store.empty());
km_kbp_usv ch = text_store.back();
text_store.pop_back();
if(text_store.length() > 0 && Uni_IsSurrogate2(ch)) {
if (text_store.length() > 0 && Uni_IsSurrogate2(ch)) {
auto ch1 = text_store.back();
if(Uni_IsSurrogate1(ch1)) {
if (Uni_IsSurrogate1(ch1)) {
// We'll only pop the next character off it is actually a
// surrogate pair
ch = Uni_SurrogateToUTF32(ch1, ch);
@ -213,30 +126,24 @@ void apply_action(km_kbp_state const *, km_kbp_action_item const & act, std::u16
context.pop_back();
}
break;
case KM_KBP_IT_PERSIST_OPT:
{
bool found = false;
for (auto it = options.begin(); it != options.end(); it++) {
if (it->type == KOT_SAVED) {
if (it->key.compare(act.option->key) == 0) {
found = true;
it->saved_value = act.option->value;
break;
}
case KM_KBP_IT_PERSIST_OPT: {
bool found = false;
for (auto it = options.begin(); it != options.end(); it++) {
if (it->type == km::tests::KOT_SAVED) {
if (it->key.compare(act.option->key) == 0) {
found = true;
it->saved_value = act.option->value;
break;
}
}
std::cout << "action: option "
<< (act.option->scope == KM_KBP_OPT_ENVIRONMENT ? "environment " : "keyboard ")
<< act.option->key
<< "=" << act.option->value
<< " persistence requested" << std::endl;
if (!found) {
std::cout << "option "
<< act.option->key
<< " saved but no expected output found. Suggestion: update test to include saved option value." << std::endl;
}
}
break;
std::cout << "action: option " << (act.option->scope == KM_KBP_OPT_ENVIRONMENT ? "environment " : "keyboard ")
<< act.option->key << "=" << act.option->value << " persistence requested" << std::endl;
if (!found) {
std::cout << "option " << act.option->key
<< " saved but no expected output found. Suggestion: update test to include saved option value." << std::endl;
}
} break;
case KM_KBP_IT_INVALIDATE_CONTEXT:
std::cout << "action: context invalidated (markers cleared)" << std::endl;
break;
@ -245,67 +152,23 @@ void apply_action(km_kbp_state const *, km_kbp_action_item const & act, std::u16
break;
case KM_KBP_IT_CAPSLOCK:
std::cout << "action: capsLock " << act.capsLock << std::endl;
g_caps_lock_on = act.capsLock;
test_source.set_caps_lock_on(act.capsLock);
break;
default:
assert(false); // NOT SUPPORTED
assert(false); // NOT SUPPORTED
break;
}
}
int caps_lock_state() {
return g_caps_lock_on ? KM_KBP_MODIFIER_CAPS : 0;
}
void toggle_caps_lock_state() {
g_caps_lock_on = !g_caps_lock_on;
}
km_kbp_option_item *get_keyboard_options(kmx_options options) {
km_kbp_option_item *keyboard_opts = new km_kbp_option_item[options.size() + 1];
int i = 0;
for (auto it = options.begin(); it != options.end(); it++) {
if (it->type != KOT_INPUT) continue;
std::cout << "input option-key: " << it->key << std::endl;
std::u16string key = it->key;
if (key[0] == u'&') {
// environment value (aka system store)
key.erase(0, 1);
keyboard_opts[i].scope = KM_KBP_OPT_ENVIRONMENT;
}
else {
keyboard_opts[i].scope = KM_KBP_OPT_KEYBOARD;
}
km_kbp_cp *cp = new km_kbp_cp[key.length() + 1];
key.copy(cp, key.length());
cp[key.length()] = 0;
keyboard_opts[i].key = cp;
cp = new km_kbp_cp[it->value.length() + 1];
it->value.copy(cp, it->value.length());
cp[it->value.length()] = 0;
keyboard_opts[i].value = cp;
i++;
}
keyboard_opts[i] = KM_KBP_OPTIONS_END;
return keyboard_opts;
}
int run_test(const km::kbp::path &source, const km::kbp::path &compiled) {
int
run_test(const km::kbp::path &source, const km::kbp::path &compiled) {
std::string keys = "";
std::u16string expected = u"", context = u"";
kmx_options options;
km::tests::kmx_options options;
bool expected_beep = false;
km::tests::KmxTestSource test_source;
int result = load_source(source, keys, expected, context, options, expected_beep);
int result = test_source.load_source(source, keys, expected, context, options, expected_beep);
if (result != 0) return result;
std::cout << "source file = " << source << std::endl
@ -321,7 +184,7 @@ int run_test(const km::kbp::path &source, const km::kbp::path &compiled) {
// Setup keyboard options
if (options.size() > 0) {
km_kbp_option_item *keyboard_opts = get_keyboard_options(options);
km_kbp_option_item *keyboard_opts = test_source.get_keyboard_options(options);
try_status(km_kbp_state_options_update(test_state, keyboard_opts));
@ -345,20 +208,20 @@ int run_test(const km::kbp::path &source, const km::kbp::path &compiled) {
std::u16string text_store = context;
// Run through key events, applying output for each event
for (auto p = next_key(keys); p.vk != 0; p = next_key(keys)) {
for (auto p = test_source.next_key(keys); p.vk != 0; p = test_source.next_key(keys)) {
// Because a normal system tracks caps lock state itself,
// we mimic that in the tests. We assume caps lock state is
// updated on key_down before the processor receives the
// event.
if (p.vk == KM_KBP_VKEY_CAPS) {
toggle_caps_lock_state();
test_source.toggle_caps_lock_state();
}
for (auto key_down = 1; key_down >= 0; key_down--) {
try_status(km_kbp_process_event(test_state, p.vk, p.modifier_state | caps_lock_state(), key_down));
try_status(km_kbp_process_event(test_state, p.vk, p.modifier_state | test_source.caps_lock_state(), key_down));
for (auto act = km_kbp_state_action_items(test_state, nullptr); act->type != KM_KBP_IT_END; act++) {
apply_action(test_state, *act, text_store, test_context, options);
apply_action(test_state, *act, text_store, test_context, options, test_source);
}
}
@ -387,7 +250,8 @@ int run_test(const km::kbp::path &source, const km::kbp::path &compiled) {
}
// Test if the beep action was as expected
if (g_beep_found != expected_beep) return __LINE__;
if (g_beep_found != expected_beep)
return __LINE__;
// Compare final output - retrieve internal context
size_t n = 0;
@ -418,14 +282,13 @@ int run_test(const km::kbp::path &source, const km::kbp::path &compiled) {
// Test resultant options
for (auto it = options.begin(); it != options.end(); it++) {
if (it->type == KOT_OUTPUT) {
if (it->type == km::tests::KOT_OUTPUT) {
std::cout << "output option-key: " << it->key << " expected: " << it->value;
km_kbp_cp const *value;
try_status(km_kbp_state_option_lookup(test_state, KM_KBP_OPT_KEYBOARD, it->key.c_str(), &value));
std::cout << " actual: " << value << std::endl;
if (it->value.compare(value) != 0) return __LINE__;
}
else if (it->type == KOT_SAVED) {
} else if (it->type == km::tests::KOT_SAVED) {
std::cout << "persisted option-key: " << it->key << " expected: " << it->value << " actual: " << it->saved_value << std::endl;
if (it->value.compare(it->saved_value) != 0) return __LINE__;
}
@ -438,145 +301,14 @@ int run_test(const km::kbp::path &source, const km::kbp::path &compiled) {
return 0;
}
std::string string_to_hex(const std::u16string& input) {
std::ostringstream result;
result << std::setfill('0') << std::hex << std::uppercase;
for (size_t i = 0; i < input.length(); i++) {
unsigned int ch = input[i];
if(i < input.length() - 1 && Uni_IsSurrogate1(input[i]) && Uni_IsSurrogate2(input[i+1])) {
ch = Uni_SurrogateToUTF32(input[i], input[i+1]);
i++;
}
result << "U+" << std::setw(4) << ch << " ";
}
return result.str();
}
std::u16string parse_source_string(std::string const & s) {
std::u16string t;
for (auto p = s.begin(); p != s.end(); p++) {
if (*p == '\\') {
p++;
km_kbp_usv v;
assert(p != s.end());
if (*p == 'u' || *p == 'U') {
// Unicode value
p++;
size_t n;
std::string s1 = s.substr(p - s.begin(), 8);
v = std::stoul(s1, &n, 16);
// Allow deadkey_number (U+0001) characters and onward
assert(v >= 0x0001 && v <= 0x10FFFF);
p += n-1;
if (v < 0x10000) {
t += km_kbp_cp(v);
}
else {
t += km_kbp_cp(Uni_UTF32ToSurrogate1(v));
t += km_kbp_cp(Uni_UTF32ToSurrogate2(v));
}
}
else if (*p == 'd') {
// Deadkey
// TODO, not yet supported
assert(false);
}
}
else {
t += *p;
}
}
return t;
}
bool parse_option_string(std::string line, kmx_options &options, kmx_option_type type) {
auto x = line.find('=');
if (x == std::string::npos) return false;
kmx_option o;
o.type = type;
o.key = parse_source_string(line.substr(0, x));
o.value = parse_source_string(line.substr(x + 1));
options.emplace_back(o);
return true;
}
bool is_token(const std::string token, std::string &line) {
if (line.compare(0, token.length(), token) == 0) {
line = line.substr(token.length());
trim(line);
return true;
}
return false;
}
int load_source(const km::kbp::path & path, std::string & keys, std::u16string & expected, std::u16string & context, kmx_options &options, bool &expected_beep) {
const std::string s_keys = "c keys: ",
s_expected = "c expected: ",
s_context = "c context: ",
s_option = "c option: ",
s_option_expected = "c expected option: ",
s_option_saved = "c saved option: ",
s_capsLock = "c capsLock: ";
// Parse out the header statements in file.kmn that tell us (a) environment, (b) key sequence, (c) start context, (d) expected result
std::ifstream kmn(path.native());
if (!kmn.good()) {
std::cerr << "could not open file: " << path << std::endl;
return __LINE__;
}
std::string line;
while (std::getline(kmn, line)) {
trim(line);
if (!line.length()) continue;
if (line.compare(0, s_keys.length(), s_keys) == 0) {
keys = line.substr(s_keys.length());
trim(keys);
}
else if(is_token(s_expected, line)) {
if (line == "\\b") {
expected_beep = true;
}
else {
expected = parse_source_string(line);
}
}
else if (is_token(s_context, line)) {
context = parse_source_string(line);
}
else if (is_token(s_option, line)) {
if (!parse_option_string(line, options, KOT_INPUT)) return __LINE__;
}
else if (is_token(s_option_expected, line)) {
if (!parse_option_string(line, options, KOT_OUTPUT)) return __LINE__;
}
else if (is_token(s_option_saved, line)) {
if (!parse_option_string(line, options, KOT_SAVED)) return __LINE__;
}
else if (is_token(s_capsLock, line)) {
g_caps_lock_on = parse_source_string(line).compare(u"1") == 0;
}
}
if (keys == "") {
// We must at least have a key sequence to run the test
return __LINE__;
}
return 0;
}
constexpr const auto help_str = "\
constexpr const auto help_str =
"\
kmx [--color] <KMN_FILE> <KMX_FILE>\n\
help:\n\
\tKMN_FILE:\tThe source file for the keyboard under test.\n\
\tKMX_FILE:\tThe corresponding compiled kmx file produced from KMN_FILE.\n";
} // namespace
} // namespace
int error_args() {
std::cerr << "kmx: Not enough arguments." << std::endl;
@ -601,5 +333,5 @@ int main(int argc, char *argv[]) {
console_color::enabled = console_color::isaterminal() || arg_color;
km::kbp::kmx::g_debug_ToConsole = TRUE;
return run_test(argv[first_arg], argv[first_arg+1]);
return run_test(argv[first_arg], argv[first_arg + 1]);
}

View file

@ -0,0 +1,113 @@
/*
Copyright: © 2021 SIL International.
Description: Tests for key rules list generation in the kmx processor
Create Date: 15 Nov 2021
Authors: Ross Cruickshank (RC) Marc Durdin (MD), Tim Eves (TSE)
*/
#include <kmx/kmx_processevent.h>
#include "path.hpp"
#include "state.hpp"
#include <map>
#include "../test_assert.h"
#include "../test_color.h"
using namespace km::kbp::kmx;
km_kbp_option_item test_env_opts[] =
{
KM_KBP_OPTIONS_END
};
int error_args() {
std::cerr << "kmx: Not enough arguments." << std::endl;
return 1;
}
#define NO_MODIFIER_FLAGS 0
#define CHAR_CODE_LOWER_A 97
#define CHAR_CODE_LOWER_B 98
std::map<std::pair<km_kbp_virtual_key,uint32_t>, uint32_t> kb_key_expected_key_list {{{KM_KBP_VKEY_1, 0},0},
{{KM_KBP_VKEY_2, 0},0},
{{KM_KBP_VKEY_A, 0},0},
{{KM_KBP_VKEY_B, 0},0},
{{KM_KBP_VKEY_B, KM_KBP_MODIFIER_CTRL},KM_KBP_MODIFIER_CTRL},
{{KM_KBP_VKEY_C, 0},0},
{{KM_KBP_VKEY_C, KM_KBP_MODIFIER_ALT},KM_KBP_MODIFIER_ALT},
};
/**
* The purpose of this test is to verify that `km_kbp_keyboard_get_key_list`
* returns list of all the keys used for a keyboard that core as loaded.
*
* @param source_file Path to kmx keyboard file
*/
void test_key_list(const km::kbp::path &source_file){
km_kbp_keyboard * test_kb = nullptr;
km_kbp_state * test_state = nullptr;
km_kbp_keyboard_key * kb_key_list;
km::kbp::path full_path = source_file;
try_status(km_kbp_keyboard_load(full_path.native().c_str(), &test_kb));
// Setup state, environment
try_status(km_kbp_state_create(test_kb, test_env_opts, &test_state));
try_status(km_kbp_keyboard_get_key_list(test_kb,&kb_key_list));
km_kbp_keyboard_key *key_rule_it = kb_key_list;
std::map<std::pair<km_kbp_virtual_key,uint32_t>, uint32_t> map_key_list;
auto n = 0;
// Internally the list is created using a map so we should not rely on order elemnts
// in the returned array. Therefore we will put the array items back into a map to verify
// against our expected map.
for (; key_rule_it->key; ++key_rule_it) {
std::cout << "key:" << key_rule_it->key << " modifer: " << key_rule_it->modifier_flag << std::endl;
map_key_list[std::make_pair(key_rule_it->key, key_rule_it->modifier_flag)] = key_rule_it->modifier_flag;
++n;
}
assert(n==7);
std::map<std::pair<km_kbp_virtual_key,uint32_t>, uint32_t>::iterator it_expected;
std::map<std::pair<km_kbp_virtual_key,uint32_t>, uint32_t>::iterator it_key_list = map_key_list.begin();
while (it_key_list != map_key_list.end()){
it_expected = kb_key_expected_key_list.find(it_key_list->first);
assert (it_expected != kb_key_expected_key_list.end());
it_key_list++;
}
km_kbp_keyboard_key_list_dispose(kb_key_list);
km_kbp_state_dispose(test_state);
km_kbp_keyboard_dispose(test_kb);
}
int main(int argc, char *argv []) {
int first_arg = 1;
if (argc < 2) {
return error_args();
}
auto arg_color = std::string(argv[1]) == "--color";
if(arg_color) {
first_arg++;
if(argc < 3) {
return error_args();
}
}
console_color::enabled = console_color::isaterminal() || arg_color;
test_key_list(argv[first_arg]);
return 0;
}

View file

@ -0,0 +1,28 @@
c Description: Tests multiple groups. This keyboard is used to test km_kbp_keyboard_get_key_list API call
c keys: [K_1][K_2]
c expected: abc
c context:
store(&version) '10.0'
begin Unicode > use(Main)
group(Main) using keys
+ [K_1] > 'a'
'b' + [K_2] > context use(b)
'a' + [CTRL K_B] > 'b'
'a' + [ALT K_C] > 'c'
match > use(a)
group(a) using keys
+ 'a' > 'c'
+ [CTRL K_B] > 'b'
+ [K_C] > 'c'
group(b) using keys
+ 'b' > 'abc'
+ [ALT K_C] > 'e'

Binary file not shown.

View file

@ -0,0 +1,286 @@
#include <algorithm>
#include <cctype>
#include <fstream>
#include <iostream>
#include <iomanip>
#include <iterator>
#include <list>
#include <sstream>
#include <string>
#include <type_traits>
#include <kmx/kmx_processevent.h>
#include <kmx/kmx_xstring.h>
#include "path.hpp"
#include "state.hpp"
#include "utfcodec.hpp"
#include "kmx_test_source.hpp"
namespace km {
namespace tests {
KmxTestSource::KmxTestSource() {
}
// String trim functions from https://stackoverflow.com/a/217605/1836776
// trim from start (in place)
static inline void
ltrim(std::string &s) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int ch) { return !std::isspace(ch); }));
}
// trim from end (in place)
static inline void
rtrim(std::string &s) {
s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) { return !std::isspace(ch); }).base(), s.end());
}
// trim from both ends (in place)
static inline void
trim(std::string &s) {
ltrim(s);
rtrim(s);
}
std::u16string
KmxTestSource::parse_source_string(std::string const &s) {
std::u16string t;
for (auto p = s.begin(); p != s.end(); p++) {
if (*p == '\\') {
p++;
km_kbp_usv v;
assert(p != s.end());
if (*p == 'u' || *p == 'U') {
// Unicode value
p++;
size_t n;
std::string s1 = s.substr(p - s.begin(), 8);
v = std::stoul(s1, &n, 16);
// Allow deadkey_number (U+0001) characters and onward
assert(v >= 0x0001 && v <= 0x10FFFF);
p += n - 1;
if (v < 0x10000) {
t += km_kbp_cp(v);
} else {
t += km_kbp_cp(Uni_UTF32ToSurrogate1(v));
t += km_kbp_cp(Uni_UTF32ToSurrogate2(v));
}
} else if (*p == 'd') {
// Deadkey
// TODO, not yet supported
assert(false);
}
} else {
t += *p;
}
}
return t;
}
bool
KmxTestSource::parse_option_string(std::string line, kmx_options &options, kmx_option_type type) {
auto x = line.find('=');
if (x == std::string::npos)
return false;
kmx_option o;
o.type = type;
o.key = parse_source_string(line.substr(0, x));
o.value = parse_source_string(line.substr(x + 1));
options.emplace_back(o);
return true;
}
bool
KmxTestSource::is_token(const std::string token, std::string &line) {
if (line.compare(0, token.length(), token) == 0) {
line = line.substr(token.length());
trim(line);
return true;
}
return false;
}
int
KmxTestSource::load_source(
const km::kbp::path &path,
std::string &keys,
std::u16string &expected,
std::u16string &context,
kmx_options &options,
bool &expected_beep) {
const std::string s_keys = "c keys: ";
const std::string s_expected = "c expected: ";
const std::string s_context = "c context: ";
const std::string s_option = "c option: ";
const std::string s_option_expected = "c expected option: ";
const std::string s_option_saved = "c saved option: ";
const std::string s_capsLock = "c capsLock: ";
// Parse out the header statements in file.kmn that tell us (a) environment, (b) key sequence, (c) start context, (d) expected
// result
std::ifstream kmn(path.native());
if (!kmn.good()) {
std::cerr << "could not open file: " << path << std::endl;
return __LINE__;
}
std::string line;
while (std::getline(kmn, line)) {
trim(line);
if (!line.length())
continue;
if (line.compare(0, s_keys.length(), s_keys) == 0) {
keys = line.substr(s_keys.length());
trim(keys);
} else if (is_token(s_expected, line)) {
if (line == "\\b") {
expected_beep = true;
} else {
expected = parse_source_string(line);
}
} else if (is_token(s_context, line)) {
context = parse_source_string(line);
} else if (is_token(s_option, line)) {
if (!parse_option_string(line, options, KOT_INPUT))
return __LINE__;
} else if (is_token(s_option_expected, line)) {
if (!parse_option_string(line, options, KOT_OUTPUT))
return __LINE__;
} else if (is_token(s_option_saved, line)) {
if (!parse_option_string(line, options, KOT_SAVED))
return __LINE__;
} else if (is_token(s_capsLock, line)) {
_caps_lock_on = parse_source_string(line).compare(u"1") == 0;
}
}
if (keys == "") {
// We must at least have a key sequence to run the test
return __LINE__;
}
return 0;
}
km_kbp_option_item *
KmxTestSource::get_keyboard_options(kmx_options options) {
km_kbp_option_item *keyboard_opts = new km_kbp_option_item[options.size() + 1];
int i = 0;
for (auto it = options.begin(); it != options.end(); it++) {
if (it->type != KOT_INPUT)
continue;
std::cout << "input option-key: " << it->key << std::endl;
std::u16string key = it->key;
if (key[0] == u'&') {
// environment value (aka system store)
key.erase(0, 1);
keyboard_opts[i].scope = KM_KBP_OPT_ENVIRONMENT;
} else {
keyboard_opts[i].scope = KM_KBP_OPT_KEYBOARD;
}
km_kbp_cp *cp = new km_kbp_cp[key.length() + 1];
key.copy(cp, key.length());
cp[key.length()] = 0;
keyboard_opts[i].key = cp;
cp = new km_kbp_cp[it->value.length() + 1];
it->value.copy(cp, it->value.length());
cp[it->value.length()] = 0;
keyboard_opts[i].value = cp;
i++;
}
keyboard_opts[i] = KM_KBP_OPTIONS_END;
return keyboard_opts;
}
key_event
KmxTestSource::char_to_event(char ch) {
assert(ch >= 32 && ch <= 127);
return {
km::kbp::kmx::s_char_to_vkey[(int)ch - 32].vk,
(uint16_t)(km::kbp::kmx::s_char_to_vkey[(int)ch - 32].shifted ? KM_KBP_MODIFIER_SHIFT : 0)};
}
uint16_t
KmxTestSource::get_modifier(std::string const m) {
for (int i = 0; km::kbp::kmx::s_modifier_names[i].name; i++) {
if (m == km::kbp::kmx::s_modifier_names[i].name) {
return km::kbp::kmx::s_modifier_names[i].modifier;
}
}
return 0;
}
km_kbp_virtual_key
KmxTestSource::get_vk(std::string const &vk) {
for (int i = 1; i < 256; i++) {
if (vk == km::kbp::kmx::s_key_names[i]) {
return i;
}
}
return 0;
}
key_event
KmxTestSource::vkey_to_event(std::string const &vk_event) {
// vkey format is MODIFIER MODIFIER K_NAME
// std::cout << "VK=" << vk_event << std::endl;
std::stringstream f(vk_event);
std::string s;
uint16_t modifier_state = 0;
km_kbp_virtual_key vk = 0;
while (std::getline(f, s, ' ')) {
uint16_t modifier = get_modifier(s);
if (modifier != 0) {
modifier_state |= modifier;
} else {
vk = get_vk(s);
break;
}
}
// The string should be empty at this point
assert(!std::getline(f, s, ' '));
assert(vk != 0);
return {vk, modifier_state};
}
key_event
KmxTestSource::next_key(std::string &keys) {
// Parse the next element of the string, chop it off, and return it
if (keys.length() == 0)
return {0, 0};
char ch = keys[0];
if (ch == '[') {
if (keys.length() > 1 && keys[1] == '[') {
keys.erase(0, 2);
return char_to_event(ch);
}
auto n = keys.find(']');
assert(n != std::string::npos);
auto vkey = keys.substr(1, n - 1);
keys.erase(0, n + 1);
return vkey_to_event(vkey);
} else {
keys.erase(0, 1);
return char_to_event(ch);
}
}
} // namespace tests
} // namespace km

View file

@ -0,0 +1,68 @@
#ifndef __KMX_TEST_SOURCE_HPP__
#define __KMX_TEST_SOURCE_HPP__
#include "path.hpp"
namespace km {
namespace tests {
struct key_event {
km_kbp_virtual_key vk;
uint16_t modifier_state;
};
typedef enum { KOT_INPUT, KOT_OUTPUT, KOT_SAVED } kmx_option_type;
struct kmx_option {
kmx_option_type type;
std::u16string key, value, saved_value;
};
using kmx_options = std::vector<kmx_option>;
class KmxTestSource {
public:
KmxTestSource();
int load_source(
const km::kbp::path &path,
std::string &keys,
std::u16string &expected,
std::u16string &context,
kmx_options &options,
bool &expected_beep);
km_kbp_option_item *get_keyboard_options(kmx_options options);
key_event next_key(std::string &keys);
int
caps_lock_state() {
return _caps_lock_on ? KM_KBP_MODIFIER_CAPS : 0;
}
void
toggle_caps_lock_state() {
_caps_lock_on = !_caps_lock_on;
}
void set_caps_lock_on(bool caps_lock_on) {
_caps_lock_on = caps_lock_on;
}
private:
bool _caps_lock_on = false;
std::u16string parse_source_string(std::string const &s);
bool parse_option_string(std::string line, kmx_options &options, kmx_option_type type);
bool is_token(const std::string token, std::string &line);
key_event char_to_event(char ch);
uint16_t get_modifier(std::string const m);
km_kbp_virtual_key get_vk(std::string const &vk);
key_event vkey_to_event(std::string const &vk_event);
};
} // namespace tests
} // namespace km
#endif // __KMX_TEST_SOURCE_HPP__

View file

@ -7,13 +7,17 @@
if compiler.get_id() == 'emscripten'
tests_flags = ['--embed-file', join_paths(meson.current_source_dir(),'@/')]
source_path = '/'
test_path = '/'
else
tests_flags = []
test_path = meson.current_source_dir()
source_path = meson.current_source_dir()
test_path = meson.current_build_dir()
endif
kmx = executable('kmx', 'kmx.cpp',
kmx = executable('kmx',
'kmx.cpp',
'kmx_test_source.cpp',
cpp_args: defns,
include_directories: [inc, libsrc],
link_args: links + tests_flags,
@ -76,6 +80,8 @@ tests = [
if build_machine.system() == 'windows'
kmcomp = find_program('kmcomp.exe', required: false)
kmcomp_cmd = [kmcomp]
copy_cmd = [find_program('cmd.exe', required: true), '/c', 'copy']
cat_cmd = [find_program('cmd.exe', required: true), '/c', 'type']
else
kmcomp = find_program('kmcomp', required: false)
kmcomp_cmd = [kmcomp]
@ -87,6 +93,8 @@ else
kmcomp = disabler()
endif
endif
copy_cmd = [find_program('cp', required: true)]
cat_cmd = [find_program('cat', required: true)]
endif
if compiler.get_id() == 'emscripten'
@ -95,23 +103,126 @@ if compiler.get_id() == 'emscripten'
kmcomp = disabler()
endif
test_keyboards = ''
foreach kbd : tests
if test_keyboards.startswith('{')
test_keyboards += ''',
'''
endif
kbd_basename = 'k_' + kbd.underscorify().to_lower()
test_keyboards += '''{
"name": "''' + kbd_basename + '''",
"id": "''' + kbd_basename + '''",
"version": "0.0",
"languages": [
{
"name": "Undetermined",
"id": "und"
}
]
}'''
if not kmcomp.found()
configure_file(
command: copy_cmd + ['@INPUT@', '@OUTPUT@'],
input: kbd + '.kmn',
output: kbd_basename + '.kmn'
)
configure_file(
command: copy_cmd + ['@INPUT@', '@OUTPUT@'],
input: kbd + '.kmx',
output: kbd_basename + '.kmx'
)
endif
endforeach
cfg = configuration_data()
cfg.set('keyboards', test_keyboards)
configure_file(
configuration: cfg,
input: 'kmp.json.in',
output: 'kmp.json'
)
if kmcomp.found()
foreach kbd : tests
kbd_src = files(kbd + '.kmn')
kbd_obj = join_paths(meson.current_source_dir(), kbd) + '.kmx'
kbd_log = custom_target(kbd + '.kmx'.underscorify(),
output: kbd + '.log',
input: kbd_src,
command: kmcomp_cmd + ['-s', '-d', '@INPUT@', kbd_obj, '@OUTPUT@']
)
kbd_basename = 'k_' + kbd.underscorify().to_lower()
test(kbd, kmx, depends: kbd_log, args: [kbd_src, kbd_obj])
content = run_command(
cat_cmd, files(kbd + '.kmn'),
).stdout().strip()
cfg = configuration_data()
cfg.set('keyboard', kbd)
cfg.set('keyboard_underscore', kbd_basename)
cfg.set('id1', 'id_' + kbd_basename + '_1')
cfg.set('id2', 'id_' + kbd_basename + '_2')
cfg.set('id3', 'id_' + kbd_basename + '_3')
cfg.set('build_dir', meson.current_build_dir())
cfg.set('NAME', kbd)
cfg.set('CONTENT', content)
kbd_kmn = configure_file(
configuration: cfg,
input: join_paths('template', 'keyboard.kmn.in'),
output: kbd_basename + '.kmn'
)
kbd_kpj = configure_file(
configuration: cfg,
input: join_paths('template', 'keyboard.kpj.in'),
output: kbd_basename + '.kpj'
)
kbd_kps = configure_file(
configuration: cfg,
input: join_paths('template', 'keyboard.kps.in'),
output: kbd_basename + '.kps'
)
kbd_kmp = custom_target(kbd_basename + '.kmp',
input: kbd_kpj,
output: [kbd_basename + '.kmp', kbd_basename + '.kmx'],
depend_files: [kbd_kps, kbd_kmn],
depfile: kbd_basename + '.dep',
command: kmcomp_cmd + ['-s', '-d', '@INPUT@'])
kbd_src = files(join_paths(test_path, kbd_basename) + '.kmn')
kbd_obj = join_paths(test_path, kbd_basename) + '.kmx'
# kbd_log = custom_target(kbd.underscorify() + '.kmx',
# output: kbd + '.log',
# input: kbd_src,
# command: kmcomp_cmd + ['-s', '-d', '@INPUT@', kbd_obj, '@OUTPUT@']
# )
test(kbd, kmx, depends: [kbd_kmp], args: [kbd_src, kbd_obj])
endforeach
else
foreach kbd : tests
kbd_src = join_paths(test_path, kbd) + '.kmn'
kbd_obj = join_paths(test_path, kbd) + '.kmx'
kbd_src = join_paths(test_path, kbd_basename) + '.kmn'
kbd_obj = join_paths(test_path, kbd_basename) + '.kmx'
test(kbd, kmx, args: [kbd_src, kbd_obj])
endforeach
endif
# test for km_kbp_keyboard_get_key_list
key_e = executable('key_list', 'kmx_key_list.cpp',
cpp_args: defns,include_directories: [inc, libsrc],
link_args: links,
dependencies: [rust_mock_processor],
objects: lib.extract_all_objects())
test_kbd = 'kmx_key_list'
if kmcomp.found()
kbd_src = files(test_kbd + '.kmn')
kbd_obj = join_paths(meson.current_source_dir(), test_kbd) + '.kmx'
kbd_log = custom_target(test_kbd + '.kmx'.underscorify(),
output: test_kbd + '.log',
input: kbd_src,
command: kmcomp_cmd + ['-s', '-d', '@INPUT@', kbd_obj, '@OUTPUT@']
)
test('key_list', key_e, depends: kbd_log, args: [kbd_obj] )
else
kbd_obj = join_paths(meson.current_source_dir(), test_kbd) + '.kmx'
test('key_list', key_e, args: [kbd_obj] )
endif

View file

@ -0,0 +1,2 @@
store(&NAME) '@NAME@'
@CONTENT@

View file

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<KeymanDeveloperProject>
<Options>
<BuildPath>$PROJECTPATH</BuildPath>
<CompilerWarningsAsErrors>false</CompilerWarningsAsErrors>
<WarnDeprecatedCode>false</WarnDeprecatedCode>
<CheckFilenameConventions>false</CheckFilenameConventions>
<ProjectType>keyboard</ProjectType>
</Options>
<Files>
<File>
<ID>@id1@</ID>
<Filename>@keyboard_underscore@.kmn</Filename>
<Filepath>@build_dir@/@keyboard_underscore@.kmn</Filepath>
<FileVersion>1.0</FileVersion>
<FileType>.kmn</FileType>
<Details>
<Name>@keyboard@</Name>
<Copyright>Copyright (C) Keyman Team</Copyright>
</Details>
</File>
<File>
<ID>@id2@</ID>
<Filename>@keyboard_underscore@.kps</Filename>
<Filepath>@build_dir@/@keyboard_underscore@.kps</Filepath>
<FileVersion></FileVersion>
<FileType>.kps</FileType>
<Details>
<Name>@keyboard@</Name>
<Copyright>Copyright (C) Keyman Team</Copyright>
</Details>
</File>
<File>
<ID>@id3@</ID>
<Filename>@keyboard_underscore@.kmx</Filename>
<Filepath>@build_dir@/@keyboard_underscore@.kmx</Filepath>
<FileVersion></FileVersion>
<FileType>.kmx</FileType>
<ParentFileID>@id2@</ParentFileID>
</File>
</Files>
</KeymanDeveloperProject>

View file

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<Package>
<System>
<KeymanDeveloperVersion>15.0</KeymanDeveloperVersion>
<FileVersion>7.0</FileVersion>
</System>
<Options>
<ExecuteProgram></ExecuteProgram>
<ReadMeFile></ReadMeFile>
<MSIFileName></MSIFileName>
<MSIOptions></MSIOptions>
<FollowKeyboardVersion/>
</Options>
<StartMenu>
<Folder></Folder>
<Items/>
</StartMenu>
<Info>
<Name URL="">@keyboard@</Name>
<Copyright URL="">Copyright (C) Keyman Team</Copyright>
<Author URL="">Keyman Team</Author>
<Version URL=""></Version>
</Info>
<Files>
<File>
<Name>@keyboard_underscore@.kmx</Name>
<Description></Description>
<CopyLocation>0</CopyLocation>
<FileType>.kmx</FileType>
</File>
</Files>
<Keyboards>
<Keyboard>
<Name>@keyboard@</Name>
<ID>@keyboard_underscore@</ID>
<Version>1.0</Version>
<Languages>
<Language ID="en">English</Language>
</Languages>
</Keyboard>
</Keyboards>
<Strings/>
</Package>

View file

@ -0,0 +1,5 @@
subdir('json')
subdir('utftest')
subdir('kmnkbd')
subdir('kmx')
subdir('rust_mock')

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/input-processor",
"version": "15.0.129",
"version": "15.0.157",
"lockfileVersion": 2,
"requires": true,
"packages": {

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/input-processor",
"version": "15.0.129",
"version": "15.0.157",
"description": "The core text and prediction processing engine for KeymanWeb",
"repository": {
"type": "git",
@ -18,8 +18,8 @@
},
"homepage": "https://github.com/keymanapp/keyman#readme",
"devDependencies": {
"@keymanapp/lexical-model-compiler": "^15.0.129",
"@keymanapp/resources-gosh": "^15.0.129",
"@keymanapp/lexical-model-compiler": "^15.0.157",
"@keymanapp/resources-gosh": "^15.0.157",
"@types/node": "^11.9.4",
"chai": "^4.3.4",
"mocha": "^8.4.0",
@ -34,11 +34,11 @@
"mocha": "mocha"
},
"dependencies": {
"@keymanapp/keyboard-processor": "^15.0.129",
"@keymanapp/lexical-model-layer": "^15.0.129",
"@keymanapp/models-types": "^15.0.129",
"@keymanapp/web-environment": "^15.0.129",
"@keymanapp/web-utils": "^15.0.129",
"@keymanapp/keyboard-processor": "^15.0.157",
"@keymanapp/lexical-model-layer": "^15.0.157",
"@keymanapp/models-types": "^15.0.157",
"@keymanapp/web-environment": "^15.0.157",
"@keymanapp/web-utils": "^15.0.157",
"eventemitter3": "^4.0.0"
}
}

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/keyboard-processor",
"version": "15.0.129",
"version": "15.0.157",
"lockfileVersion": 2,
"requires": true,
"packages": {

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/keyboard-processor",
"version": "15.0.129",
"version": "15.0.157",
"description": "Core module for Keyman keyboard support in KeymanWeb.",
"repository": {
"type": "git",
@ -18,7 +18,7 @@
},
"homepage": "https://github.com/keymanapp/keyman#readme",
"devDependencies": {
"@keymanapp/resources-gosh": "^15.0.129",
"@keymanapp/resources-gosh": "^15.0.157",
"chai": "^4.3.4",
"mocha": "^8.4.0",
"mocha-teamcity-reporter": "^4.0.0",
@ -32,9 +32,9 @@
"mocha": "mocha"
},
"dependencies": {
"@keymanapp/models-types": "^15.0.129",
"@keymanapp/web-environment": "^15.0.129",
"@keymanapp/web-utils": "^15.0.129",
"@keymanapp/models-types": "^15.0.157",
"@keymanapp/web-environment": "^15.0.157",
"@keymanapp/web-utils": "^15.0.157",
"@types/node": "^11.9.4"
}
}

View file

@ -70,15 +70,15 @@ namespace com.keyman.text {
}
/**
* Used when a RuleBehavior represents a non-text "command" within the Engine. This will generally
* Used when a RuleBehavior represents a non-text "command" within the Engine. This will generally
* trigger events that require context reset - often by moving the caret or by moving what OutputTarget
* the caret is in. However, we let those events perform the actual context reset.
*
*
* Note: is extended by DOM-aware KeymanWeb code.
*/
public static applyCommand(Lkc: KeyEvent, outputTarget: OutputTarget): void {
// Notes for potential default-handling extensions:
//
//
// switch(code) {
// // Problem: clusters, and doing them right.
// // The commented-out code below should be a decent starting point, but clusters make it complex.
@ -142,27 +142,33 @@ namespace com.keyman.text {
// Test for fall back to U_xxxxxx key id
// For this first test, we ignore the keyCode and use the keyName
public static forUnicodeKeynames(Lkc: KeyEvent, ruleBehavior?: RuleBehavior) {
let keyName = Lkc.kName;
const keyName = Lkc.kName;
// Test for fall back to U_xxxxxx key id
// For this first test, we ignore the keyCode and use the keyName
if(!keyName || keyName.substr(0,2) != 'U_') {
return null;
}
var codePoint = parseInt(keyName.substr(2,6), 16);
if (((0x0 <= codePoint) && (codePoint <= 0x1F)) || ((0x80 <= codePoint) && (codePoint <= 0x9F))) {
// Code points [U_0000 - U_001F] and [U_0080 - U_009F] refer to Unicode C0 and C1 control codes.
// Check the codePoint number and do not allow output of these codes via U_xxxxxx shortcuts.
if(ruleBehavior) {
ruleBehavior.errorLog = ("Suppressing Unicode control code: U_00" + codePoint.toString(16));
let result = '';
const codePoints = keyName.substr(2).split('_');
for(let codePoint of codePoints) {
const codePointValue = parseInt(codePoint, 16);
if (((0x0 <= codePointValue) && (codePointValue <= 0x1F)) || ((0x80 <= codePointValue) && (codePointValue <= 0x9F))) {
// Code points [U_0000 - U_001F] and [U_0080 - U_009F] refer to Unicode C0 and C1 control codes.
// Check the codePoint number and do not allow output of these codes via U_xxxxxx shortcuts.
if(ruleBehavior) {
ruleBehavior.errorLog = ("Suppressing Unicode control code in " + keyName);
}
// We'll attempt to add valid chars
continue;
} else {
// String.fromCharCode() is inadequate to handle the entire range of Unicode
// Someday after upgrading to ES2015, can use String.fromCodePoint()
result += String.kmwFromCharCode(codePointValue);
}
return null;
} else {
// String.fromCharCode() is inadequate to handle the entire range of Unicode
// Someday after upgrading to ES2015, can use String.fromCodePoint()
return String.kmwFromCharCode(codePoint);
}
return result ? result : null;
}
// Test for otherwise unimplemented keys on the the base default & shift layers.

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/recorder-core",
"version": "15.0.129",
"version": "15.0.157",
"lockfileVersion": 2,
"requires": true,
"packages": {

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/recorder-core",
"version": "15.0.129",
"version": "15.0.157",
"description": "Core classes used to develop KeymanWeb test cases based on keystrokes",
"main": "index.js",
"scripts": {
@ -17,10 +17,10 @@
},
"homepage": "https://github.com/keymanapp/keyman#readme",
"dependencies": {
"@keymanapp/keyboard-processor": "^15.0.129",
"@keymanapp/models-types": "^15.0.129",
"@keymanapp/web-environment": "^15.0.129",
"@keymanapp/web-utils": "^15.0.129",
"@keymanapp/keyboard-processor": "^15.0.157",
"@keymanapp/models-types": "^15.0.157",
"@keymanapp/web-environment": "^15.0.157",
"@keymanapp/web-utils": "^15.0.157",
"@types/node": "^11.9.4"
},
"devDependencies": {

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/web-sentry-manager",
"version": "15.0.129",
"version": "15.0.157",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/web-sentry-manager",
"version": "15.0.129",
"version": "15.0.157",
"description": "Common setup for KeymanWeb's Sentry-based error reporting",
"main": "dist/index.js",
"scripts": {
@ -20,7 +20,7 @@
"typescript": "^3.8.3"
},
"dependencies": {
"@keymanapp/web-environment": "^15.0.129",
"@keymanapp/web-environment": "^15.0.157",
"@sentry/browser": "^5.27.4"
}
}

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/web-utils",
"version": "15.0.129",
"version": "15.0.157",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/web-utils",
"version": "15.0.129",
"version": "15.0.157",
"description": "Common utility functions used throughout other Keyman packages",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
@ -20,8 +20,8 @@
},
"homepage": "https://github.com/keymanapp/keyman#readme",
"devDependencies": {
"@keymanapp/resources-gosh": "^15.0.129",
"@keymanapp/web-environment": "^15.0.129",
"@keymanapp/resources-gosh": "^15.0.157",
"@keymanapp/web-environment": "^15.0.157",
"@types/node": "^14.0.5",
"typescript": "^3.8.3"
}

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/models-templates",
"version": "15.0.129",
"version": "15.0.157",
"lockfileVersion": 2,
"requires": true,
"packages": {

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/models-templates",
"version": "15.0.129",
"version": "15.0.157",
"description": "Backing model implementations (templates) for Keyman's modelling layer",
"keywords": [
"lm",
@ -42,8 +42,8 @@
"url": "https://github.com/keymanapp/keyman/issues"
},
"devDependencies": {
"@keymanapp/models-types": "^15.0.129",
"@keymanapp/web-utils": "^15.0.129",
"@keymanapp/models-types": "^15.0.157",
"@keymanapp/web-utils": "^15.0.157",
"@types/chai": "^4.2.11",
"@types/mocha": "^7.0.2",
"@types/node": "^14.0.4",
@ -52,6 +52,6 @@
"typescript": "^3.8.3"
},
"dependencies": {
"@keymanapp/models-wordbreakers": "^15.0.129"
"@keymanapp/models-wordbreakers": "^15.0.157"
}
}

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/models-types",
"version": "15.0.129",
"version": "15.0.157",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/models-types",
"version": "15.0.129",
"version": "15.0.157",
"description": "Type definitions in used in the modeling (lexical model/predictive text) component of Keyman.",
"types": "./index.d.ts",
"scripts": {

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/models-wordbreakers",
"version": "15.0.129",
"version": "15.0.157",
"lockfileVersion": 2,
"requires": true,
"packages": {

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/models-wordbreakers",
"version": "15.0.129",
"version": "15.0.157",
"description": "Word breakers bundled in the modeling layer",
"keywords": [
"lexical model",
@ -40,7 +40,7 @@
"url": "https://github.com/keymanapp/keyman/issues"
},
"devDependencies": {
"@keymanapp/models-types": "^15.0.129",
"@keymanapp/models-types": "^15.0.157",
"@types/chai": "^4.2.11",
"@types/mocha": "^7.0.2",
"chai": "^4.3.4",

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/lexical-model-layer",
"version": "15.0.129",
"version": "15.0.157",
"lockfileVersion": 2,
"requires": true,
"packages": {

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/lexical-model-layer",
"version": "15.0.129",
"version": "15.0.157",
"description": "Keyman/Predictive Text integration layer",
"main": "build/index.js",
"scripts": {
@ -21,8 +21,8 @@
},
"homepage": "https://github.com/keymanapp/keyman#readme",
"devDependencies": {
"@keymanapp/models-types": "^15.0.129",
"@keymanapp/resources-gosh": "^15.0.129",
"@keymanapp/models-types": "^15.0.157",
"@keymanapp/resources-gosh": "^15.0.157",
"@types/node": "^10.17.21",
"chai": "^4.3.4",
"karma": "^6.3.4",
@ -46,10 +46,10 @@
"typescript": "^3.8.3"
},
"dependencies": {
"@keymanapp/models-templates": "^15.0.129",
"@keymanapp/models-wordbreakers": "^15.0.129",
"@keymanapp/web-environment": "^15.0.129",
"@keymanapp/web-utils": "^15.0.129",
"@keymanapp/models-templates": "^15.0.157",
"@keymanapp/models-wordbreakers": "^15.0.157",
"@keymanapp/web-environment": "^15.0.157",
"@keymanapp/web-utils": "^15.0.157",
"es6-shim": "^0.35.5",
"string.prototype.codepointat": "^0.2.1",
"string.prototype.startswith": "^0.2.0"

View file

@ -0,0 +1,6 @@
# kps.xsd
Master version: https://github.com/keymanapp/api.keyman.com/blob/master/schemas/kps/7.0/kps.xsd
## 2021-07-19 7.0
* Initial version 7.0

213
common/schemas/kps/kps.xsd Normal file
View file

@ -0,0 +1,213 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
.kps file schema, version 7.0
Copyright (C) SIL International
Supports KPS files for Keyman Developer 7+
Expects FileVersion 7.0
-->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Package">
<xs:complexType>
<xs:all>
<xs:element minOccurs="1" maxOccurs="1" name="System">
<xs:complexType>
<xs:all>
<xs:element minOccurs="1" maxOccurs="1" name="KeymanDeveloperVersion" type="km-version" />
<xs:element minOccurs="1" maxOccurs="1" name="FileVersion" type="km-version" />
</xs:all>
</xs:complexType>
</xs:element>
<xs:element minOccurs="0" maxOccurs="1" name="Options">
<xs:complexType>
<xs:all>
<xs:element minOccurs="0" maxOccurs="1" name="ExecuteProgram" type="xs:string" />
<xs:element minOccurs="0" maxOccurs="1" name="ReadMeFile" type="xs:string" />
<xs:element minOccurs="0" maxOccurs="1" name="GraphicFile" type="xs:string" />
<xs:element minOccurs="0" maxOccurs="1" name="MSIFileName" type="xs:string" />
<xs:element minOccurs="0" maxOccurs="1" name="MSIOptions" type="xs:string" />
<xs:element minOccurs="0" maxOccurs="1" name="FollowKeyboardVersion" type="km-empty" />
</xs:all>
</xs:complexType>
</xs:element>
<xs:element minOccurs="0" maxOccurs="1" name="StartMenu">
<xs:complexType>
<xs:all>
<xs:element minOccurs="0" maxOccurs="1" name="Folder" type="xs:string" />
<xs:element minOccurs="0" maxOccurs="1" name="AddUninstallEntry" type="km-empty" />
<xs:element minOccurs="0" maxOccurs="1" name="Items">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" name="Item">
<xs:complexType>
<xs:all>
<xs:element minOccurs="0" maxOccurs="1" name="Name" type="xs:string" />
<xs:element minOccurs="0" maxOccurs="1" name="FileName" type="xs:string" />
<xs:element minOccurs="0" maxOccurs="1" name="Arguments" type="xs:string" />
<xs:element minOccurs="0" maxOccurs="1" name="Icon" type="xs:string" />
<xs:element minOccurs="0" maxOccurs="1" name="Location" type="km-start-menu-location" />
</xs:all>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:all>
</xs:complexType>
</xs:element>
<xs:element minOccurs="0" maxOccurs="1" name="Info">
<xs:complexType>
<xs:all>
<xs:element minOccurs="0" maxOccurs="1" name="Name" type="km-info" />
<xs:element minOccurs="0" maxOccurs="1" name="Version" type="km-info" />
<xs:element minOccurs="0" maxOccurs="1" name="Copyright" type="km-info" />
<xs:element minOccurs="0" maxOccurs="1" name="Author" type="km-info" />
<xs:element minOccurs="0" maxOccurs="1" name="WebSite" type="km-info" />
</xs:all>
</xs:complexType>
</xs:element>
<xs:element minOccurs="0" maxOccurs="1" name="Files">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" name="File">
<xs:complexType>
<xs:all>
<xs:element minOccurs="0" maxOccurs="1" name="Name" type="xs:string" />
<xs:element minOccurs="0" maxOccurs="1" name="Description" type="xs:string" />
<xs:element minOccurs="0" maxOccurs="1" name="CopyLocation" type="km-file-copy-location" />
<xs:element minOccurs="0" maxOccurs="1" name="FileType" type="xs:string" />
</xs:all>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element minOccurs="0" maxOccurs="1" name="Keyboards">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" name="Keyboard">
<xs:complexType>
<xs:all>
<xs:element minOccurs="0" maxOccurs="1" name="Name" type="xs:string" />
<xs:element minOccurs="0" maxOccurs="1" name="ID" type="xs:string" />
<xs:element minOccurs="0" maxOccurs="1" name="Version" type="xs:string" />
<xs:element minOccurs="0" maxOccurs="1" name="RTL" type="xs:string" />
<xs:element minOccurs="0" maxOccurs="1" name="OSKFont" type="xs:string" />
<xs:element minOccurs="0" maxOccurs="1" name="DisplayFont" type="xs:string" />
<xs:element minOccurs="0" maxOccurs="1" name="Languages" type="km-keyboard-languages" />
</xs:all>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element minOccurs="0" maxOccurs="1" name="LexicalModels">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" name="LexicalModel">
<xs:complexType>
<xs:all>
<xs:element minOccurs="0" maxOccurs="1" name="Name" type="xs:string" />
<xs:element minOccurs="0" maxOccurs="1" name="ID" type="xs:string" />
<xs:element minOccurs="0" maxOccurs="1" name="Version" type="xs:string" />
<xs:element minOccurs="0" maxOccurs="1" name="RTL" type="xs:string" />
<xs:element minOccurs="0" maxOccurs="1" name="Languages" type="km-keyboard-languages" />
</xs:all>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element minOccurs="0" maxOccurs="1" name="Strings">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" name="String">
<xs:complexType>
<xs:attribute name="Name" type="xs:string" />
<xs:attribute name="Value" type="xs:string" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<!-- Deprecated elements: we won't validate as processors ignore them -->
<xs:element minOccurs="0" maxOccurs="1" name="Buttons" type="km-any" />
<xs:element minOccurs="0" maxOccurs="1" name="Registry" type="km-any" />
</xs:all>
</xs:complexType>
</xs:element>
<xs:complexType name="km-empty">
<xs:sequence/>
</xs:complexType>
<xs:complexType name="km-any">
<xs:sequence>
<xs:any minOccurs="0" maxOccurs="unbounded" processContents="skip" />
</xs:sequence>
</xs:complexType>
<xs:simpleType name="km-version">
<xs:restriction base="xs:string">
<xs:pattern value="(\d+\.)+(\d+)"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="km-info">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="URL" type="xs:anyURI" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:simpleType name="km-file-copy-location">
<xs:restriction base="xs:integer">
<xs:minInclusive value="0" />
<xs:maxInclusive value="3"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="km-start-menu-location">
<xs:restriction base="xs:string">
<xs:pattern value="psmelStartMenu|psmelDesktop"></xs:pattern>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="km-keyboard-languages">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" name="Language">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="ID" type="xs:string" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:schema>

1
common/test/keyboards/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
*/build/

View file

@ -0,0 +1,6 @@
U_xxxx_yyyy_2858 Change History
====================
1.0 (2021-11-11)
----------------
* Created by

View file

@ -1,6 +1,6 @@
The MIT License (MIT)
©
© 2021
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View file

@ -1,17 +1,19 @@
caps_lock_shift_frees_caps keyboard
U_xxxx_yyyy_2858 keyboard
==============
©
Version 1.0
Description
-----------
caps_lock_shift_frees_caps generated from template
U_xxxx_yyyy_2858 generated from template
Links
-----
https://github.com/keymanapp/keyman/issues/2858
Copyright
---------
See [LICENSE.md](LICENSE.md)
Supported Platforms
-------------------

View file

@ -0,0 +1,93 @@
Copyright 2012 Google Inc. All Rights Reserved.
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

View file

@ -2,7 +2,8 @@
<html lang="en">
<head>
<meta charset="utf-8">
<title>caps_lock_shift_frees_caps</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>U_xxxx_yyyy_2858</title>
<style type="text/css">
p { font: 10pt Tahoma; }
h1 { font: bold 16pt Tahoma; color: #4444cc; margin-bottom: 2px }
@ -11,10 +12,10 @@
</head>
<body>
<h1>caps_lock_shift_frees_caps</h1>
<h1>U_xxxx_yyyy_2858</h1>
<p>
caps_lock_shift_frees_caps 1.0 generated from template.
U_xxxx_yyyy_2858 1.0 generated from template.
</p>
<p>©</p>

View file

@ -0,0 +1,678 @@
{
"tablet": {
"font": "Tahoma",
"layer": [
{
"id": "default",
"row": [
{
"id": 1,
"key": [
{
"id": "K_Q",
"text": "q"
},
{
"id": "K_W",
"text": "w"
},
{
"id": "K_E",
"text": "e"
},
{
"id": "K_R",
"text": "r"
},
{
"id": "K_T",
"text": "t"
},
{
"id": "K_Y",
"text": "y"
},
{
"id": "K_U",
"text": "u"
},
{
"id": "K_I",
"text": "i"
},
{
"id": "K_O",
"text": "o"
},
{
"id": "K_P",
"text": "p"
}
]
},
{
"id": 2,
"key": [
{
"id": "U_1234_1340",
"text": "ሴፀ",
"pad": 70
},
{
"id": "U_10300_10301_10302",
"text": "𐌀𐌁𐌂",
"sk": [
{
"text": "",
"id": "U_10302_10303_10304"
}
]
},
{
"id": "U_1235_1341",
"text": "",
"sk": [
{
"text": "",
"id": "U_1342_1343"
}
]
},
{
"id": "K_F",
"text": "f"
},
{
"id": "K_G",
"text": "g"
},
{
"id": "K_H",
"text": "h"
},
{
"id": "K_J",
"text": "j"
},
{
"id": "K_K",
"text": "k"
},
{
"id": "K_L",
"text": "l"
},
{
"id": "T_new_54",
"text": "",
"width": "10",
"sp": "10"
}
]
},
{
"id": 3,
"key": [
{
"id": "K_SHIFT",
"text": "*Shift*",
"width": "110",
"sp": "1",
"nextlayer": "shift"
},
{
"id": "K_Z",
"text": "z"
},
{
"id": "K_X",
"text": "x"
},
{
"id": "K_C",
"text": "c"
},
{
"id": "K_V",
"text": "v"
},
{
"id": "K_B",
"text": "b"
},
{
"id": "K_N",
"text": "n"
},
{
"id": "K_M",
"text": "m"
},
{
"id": "K_PERIOD",
"text": ".",
"sk": [
{
"text": ",",
"id": "K_COMMA"
},
{
"text": "!",
"id": "K_1",
"layer": "shift"
},
{
"text": "?",
"id": "K_SLASH",
"layer": "shift"
},
{
"text": "'",
"id": "K_QUOTE"
},
{
"text": "\"",
"id": "K_QUOTE",
"layer": "shift"
},
{
"text": "\\",
"id": "K_BKSLASH"
},
{
"text": ":",
"id": "K_COLON",
"layer": "shift"
},
{
"text": ";",
"id": "K_COLON"
}
]
},
{
"id": "K_BKSP",
"text": "*BkSp*",
"width": "90",
"sp": "1"
}
]
},
{
"id": 4,
"key": [
{
"id": "K_NUMLOCK",
"text": "*123*",
"width": "140",
"sp": "1",
"nextlayer": "numeric"
},
{
"id": "K_LOPT",
"text": "*Menu*",
"width": "120",
"sp": "1"
},
{
"id": "K_SPACE",
"text": "",
"width": "630",
"sp": "0"
},
{
"id": "K_ENTER",
"text": "*Enter*",
"width": "140",
"sp": "1"
}
]
}
]
},
{
"id": "shift",
"row": [
{
"id": 1,
"key": [
{
"id": "K_Q",
"text": "Q"
},
{
"id": "K_W",
"text": "W"
},
{
"id": "K_E",
"text": "E"
},
{
"id": "K_R",
"text": "R"
},
{
"id": "K_T",
"text": "T"
},
{
"id": "K_Y",
"text": "Y"
},
{
"id": "K_U",
"text": "U"
},
{
"id": "K_I",
"text": "I"
},
{
"id": "K_O",
"text": "O"
},
{
"id": "K_P",
"text": "P"
}
]
},
{
"id": 2,
"key": [
{
"id": "K_A",
"text": "A",
"pad": 70
},
{
"id": "K_S",
"text": "S"
},
{
"id": "K_D",
"text": "D"
},
{
"id": "K_F",
"text": "F"
},
{
"id": "K_G",
"text": "G"
},
{
"id": "K_H",
"text": "H"
},
{
"id": "K_J",
"text": "J"
},
{
"id": "K_K",
"text": "K"
},
{
"id": "K_L",
"text": "L"
},
{
"sp": "10",
"width": "10"
}
]
},
{
"id": 3,
"key": [
{
"id": "K_SHIFT",
"text": "*Shift*",
"width": "110",
"sp": "2",
"nextlayer": "default"
},
{
"id": "K_Z",
"text": "Z"
},
{
"id": "K_X",
"text": "X"
},
{
"id": "K_C",
"text": "C"
},
{
"id": "K_V",
"text": "V"
},
{
"id": "K_B",
"text": "B"
},
{
"id": "K_N",
"text": "N"
},
{
"id": "K_M",
"text": "M"
},
{
"id": "K_PERIOD",
"text": ".",
"layer": "default",
"sk": [
{
"text": ",",
"id": "K_COMMA",
"layer": "default"
},
{
"text": "!",
"id": "K_1",
"layer": "shift"
},
{
"text": "?",
"id": "K_SLASH",
"layer": "shift"
},
{
"text": "'",
"id": "K_QUOTE",
"layer": "default"
},
{
"text": "\"",
"id": "K_QUOTE",
"layer": "shift"
},
{
"text": "\\",
"id": "K_BKSLASH",
"layer": "default"
},
{
"text": ":",
"id": "K_COLON",
"layer": "shift"
},
{
"text": ";",
"id": "K_COLON",
"layer": "default"
}
]
},
{
"id": "K_BKSP",
"text": "*BkSp*",
"width": "90",
"sp": "1"
}
]
},
{
"id": 4,
"key": [
{
"id": "K_NUMLOCK",
"text": "*123*",
"width": "140",
"sp": "1",
"nextlayer": "numeric"
},
{
"id": "K_LOPT",
"text": "*Menu*",
"width": "120",
"sp": "1"
},
{
"id": "K_SPACE",
"text": "",
"width": "630",
"sp": "0"
},
{
"id": "K_ENTER",
"text": "*Enter*",
"width": "140",
"sp": "1"
}
]
}
]
},
{
"id": "numeric",
"row": [
{
"id": 1,
"key": [
{
"id": "K_1",
"text": "1"
},
{
"id": "K_2",
"text": "2"
},
{
"id": "K_3",
"text": "3"
},
{
"id": "K_4",
"text": "4"
},
{
"id": "K_5",
"text": "5"
},
{
"id": "K_6",
"text": "6"
},
{
"id": "K_7",
"text": "7"
},
{
"id": "K_8",
"text": "8"
},
{
"id": "K_9",
"text": "9"
},
{
"id": "K_0",
"text": "0"
}
]
},
{
"id": 2,
"key": [
{
"id": "K_4",
"text": "$",
"layer": "shift",
"pad": 70
},
{
"id": "K_2",
"text": "@",
"layer": "shift"
},
{
"id": "K_3",
"text": "#",
"layer": "shift"
},
{
"id": "K_5",
"text": "%",
"layer": "shift"
},
{
"id": "K_7",
"text": "&",
"layer": "shift"
},
{
"id": "K_HYPHEN",
"text": "_",
"layer": "shift"
},
{
"id": "K_EQUAL",
"text": "=",
"layer": "default"
},
{
"id": "K_BKSLASH",
"text": "|",
"layer": "shift"
},
{
"id": "K_BKSLASH",
"text": "\\",
"layer": "default"
},
{
"text": "",
"width": "10",
"sp": "10"
}
]
},
{
"id": 3,
"key": [
{
"id": "K_SHIFT",
"text": "*Shift*",
"width": "110",
"sp": "1"
},
{
"id": "K_LBRKT",
"text": "[",
"sk": [
{
"id": "U_00AB",
"text": "«"
},
{
"id": "K_COMMA",
"text": "<",
"layer": "shift"
},
{
"id": "K_LBRKT",
"text": "{",
"layer": "shift"
}
]
},
{
"id": "K_9",
"text": "(",
"layer": "shift"
},
{
"id": "K_0",
"text": ")",
"layer": "shift"
},
{
"id": "K_RBRKT",
"text": "]",
"sk": [
{
"id": "U_00BB",
"text": "»"
},
{
"id": "K_PERIOD",
"text": ">",
"layer": "shift"
},
{
"id": "K_RBRKT",
"text": "}",
"layer": "shift"
}
]
},
{
"id": "K_EQUAL",
"text": "+",
"layer": "shift"
},
{
"id": "K_HYPHEN",
"text": "-",
"layer": "default"
},
{
"id": "K_8",
"text": "*",
"layer": "shift"
},
{
"id": "K_SLASH",
"text": "/",
"layer": "default"
},
{
"id": "K_BKSP",
"text": "*BkSp*",
"width": "90",
"sp": "1"
}
]
},
{
"id": 4,
"key": [
{
"id": "K_LOWER",
"text": "*abc*",
"width": "140",
"sp": "1",
"nextlayer": "default"
},
{
"id": "K_LOPT",
"text": "*Menu*",
"width": "120",
"sp": "1"
},
{
"id": "K_SPACE",
"text": "",
"width": "630",
"sp": "0"
},
{
"id": "K_ENTER",
"text": "*Enter*",
"width": "140",
"sp": "1"
}
]
}
]
}
],
"displayUnderlying": false
}
}

View file

@ -0,0 +1,13 @@
c u_xxxx_yyyy_2858 generated from template at 2021-11-11 12:27:04
c with name "U_xxxx_yyyy_2858"
store(&VERSION) '15.0'
store(&NAME) 'U_xxxx_yyyy_2858'
store(&COPYRIGHT) '©'
store(&KEYBOARDVERSION) '1.0'
store(&TARGETS) 'any'
store(&VISUALKEYBOARD) 'u_xxxx_yyyy_2858.kvks'
store(&LAYOUTFILE) 'u_xxxx_yyyy_2858.keyman-touch-layout'
begin Unicode > use(main)
group(main) using keys

View file

@ -0,0 +1,81 @@
<?xml version="1.0" encoding="utf-8"?>
<Package>
<System>
<KeymanDeveloperVersion>15.0.146.0</KeymanDeveloperVersion>
<FileVersion>7.0</FileVersion>
</System>
<Options>
<ExecuteProgram></ExecuteProgram>
<ReadMeFile>readme.htm</ReadMeFile>
<MSIFileName></MSIFileName>
<MSIOptions></MSIOptions>
<FollowKeyboardVersion/>
</Options>
<StartMenu>
<Folder></Folder>
<Items/>
</StartMenu>
<Info>
<Name URL="">U_xxxx_yyyy_2858</Name>
<Copyright URL="">©</Copyright>
<Author URL=""></Author>
<Version URL=""></Version>
</Info>
<Files>
<File>
<Name>..\build\u_xxxx_yyyy_2858.kmx</Name>
<Description></Description>
<CopyLocation>0</CopyLocation>
<FileType>.kmx</FileType>
</File>
<File>
<Name>..\build\u_xxxx_yyyy_2858.js</Name>
<Description></Description>
<CopyLocation>0</CopyLocation>
<FileType>.js</FileType>
</File>
<File>
<Name>..\build\u_xxxx_yyyy_2858.kvk</Name>
<Description></Description>
<CopyLocation>0</CopyLocation>
<FileType>.kvk</FileType>
</File>
<File>
<Name>welcome.htm</Name>
<Description></Description>
<CopyLocation>0</CopyLocation>
<FileType>.htm</FileType>
</File>
<File>
<Name>readme.htm</Name>
<Description></Description>
<CopyLocation>0</CopyLocation>
<FileType>.htm</FileType>
</File>
<File>
<Name>NotoSansOldItalic-Regular.ttf</Name>
<Description>Font Noto Sans Old Italic Regular</Description>
<CopyLocation>0</CopyLocation>
<FileType>.ttf</FileType>
</File>
<File>
<Name>OFL.txt</Name>
<Description>File OFL.txt</Description>
<CopyLocation>0</CopyLocation>
<FileType>.txt</FileType>
</File>
</Files>
<Keyboards>
<Keyboard>
<Name>U_xxxx_yyyy_2858</Name>
<ID>u_xxxx_yyyy_2858</ID>
<Version>1.0</Version>
<OSKFont>NotoSansOldItalic-Regular.ttf</OSKFont>
<DisplayFont>NotoSansOldItalic-Regular.ttf</DisplayFont>
<Languages>
<Language ID="en">English</Language>
</Languages>
</Keyboard>
</Keyboards>
<Strings/>
</Package>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<visualkeyboard>
<header>
<version>10.0</version>
<kbdname>u_xxxx_yyyy_2858</kbdname>
<flags/>
</header>
</visualkeyboard>

View file

@ -0,0 +1,26 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Start Using U_xxxx_yyyy_2858</title>
<style type="text/css">
p { font: 10pt Tahoma; }
h1 { font: bold 16pt Tahoma; color: #4444cc; margin-bottom: 2px }
h2 { font: bold 12pt Tahoma; color: #4444cc; }
</style>
</head>
<body>
<h1>Start Using U_xxxx_yyyy_2858</h1>
<p>
U_xxxx_yyyy_2858 1.0 generated from template.
</p>
<h1>Keyboard Layout</h1>
<!-- Insert Keyboard Layout Images or HTML here -->
</body>
</html>

View file

@ -0,0 +1,7 @@
{
"license": "mit",
"languages": [
],
"description": "U_xxxx_yyyy_2858 generated from template"
}

View file

@ -0,0 +1,102 @@
<?xml version="1.0" encoding="utf-8"?>
<KeymanDeveloperProject>
<Options>
<BuildPath>$PROJECTPATH\build</BuildPath>
<CompilerWarningsAsErrors>True</CompilerWarningsAsErrors>
<WarnDeprecatedCode>True</WarnDeprecatedCode>
<CheckFilenameConventions>True</CheckFilenameConventions>
<ProjectType>keyboard</ProjectType>
</Options>
<Files>
<File>
<ID>id_7e810b4833243057b00c8d803899b99f</ID>
<Filename>u_xxxx_yyyy_2858.kmn</Filename>
<Filepath>source\u_xxxx_yyyy_2858.kmn</Filepath>
<FileVersion>1.0</FileVersion>
<FileType>.kmn</FileType>
<Details>
<Name>U_xxxx_yyyy_2858</Name>
<Copyright>©</Copyright>
</Details>
</File>
<File>
<ID>id_e45c659d6b3f6aa669e8d9488bf2602d</ID>
<Filename>u_xxxx_yyyy_2858.kps</Filename>
<Filepath>source\u_xxxx_yyyy_2858.kps</Filepath>
<FileVersion></FileVersion>
<FileType>.kps</FileType>
<Details>
<Name>U_xxxx_yyyy_2858</Name>
<Copyright>©</Copyright>
</Details>
</File>
<File>
<ID>id_ede98e4633e239f933cbfd1f4e1b766c</ID>
<Filename>HISTORY.md</Filename>
<Filepath>HISTORY.md</Filepath>
<FileVersion></FileVersion>
<FileType>.md</FileType>
</File>
<File>
<ID>id_53e892b8b41cc4caece1cfd5ef21d6e7</ID>
<Filename>LICENSE.md</Filename>
<Filepath>LICENSE.md</Filepath>
<FileVersion></FileVersion>
<FileType>.md</FileType>
</File>
<File>
<ID>id_0730bb7c2e8f9ea2438b52e419dd86c9</ID>
<Filename>README.md</Filename>
<Filepath>README.md</Filepath>
<FileVersion></FileVersion>
<FileType>.md</FileType>
</File>
<File>
<ID>id_10a5cd9d0c42cd03b9838916f6f0bd3d</ID>
<Filename>u_xxxx_yyyy_2858.keyboard_info</Filename>
<Filepath>u_xxxx_yyyy_2858.keyboard_info</Filepath>
<FileVersion></FileVersion>
<FileType>.keyboard_info</FileType>
</File>
<File>
<ID>id_a1200478ad69b7f058fdce369fb1d960</ID>
<Filename>u_xxxx_yyyy_2858.kmx</Filename>
<Filepath>source\..\build\u_xxxx_yyyy_2858.kmx</Filepath>
<FileVersion></FileVersion>
<FileType>.kmx</FileType>
<ParentFileID>id_e45c659d6b3f6aa669e8d9488bf2602d</ParentFileID>
</File>
<File>
<ID>id_e3aacd883345f12f694ac409407de6da</ID>
<Filename>u_xxxx_yyyy_2858.js</Filename>
<Filepath>source\..\build\u_xxxx_yyyy_2858.js</Filepath>
<FileVersion></FileVersion>
<FileType>.js</FileType>
<ParentFileID>id_e45c659d6b3f6aa669e8d9488bf2602d</ParentFileID>
</File>
<File>
<ID>id_6c1c142b76341666d0679b0979b76793</ID>
<Filename>u_xxxx_yyyy_2858.kvk</Filename>
<Filepath>source\..\build\u_xxxx_yyyy_2858.kvk</Filepath>
<FileVersion></FileVersion>
<FileType>.kvk</FileType>
<ParentFileID>id_e45c659d6b3f6aa669e8d9488bf2602d</ParentFileID>
</File>
<File>
<ID>id_356e5d149c1e539356d72698c1e401a6</ID>
<Filename>welcome.htm</Filename>
<Filepath>source\welcome.htm</Filepath>
<FileVersion></FileVersion>
<FileType>.htm</FileType>
<ParentFileID>id_e45c659d6b3f6aa669e8d9488bf2602d</ParentFileID>
</File>
<File>
<ID>id_8da344c4cea6f467013357fe099006f5</ID>
<Filename>readme.htm</Filename>
<Filepath>source\readme.htm</Filepath>
<FileVersion></FileVersion>
<FileType>.htm</FileType>
<ParentFileID>id_e45c659d6b3f6aa669e8d9488bf2602d</ParentFileID>
</File>
</Files>
</KeymanDeveloperProject>

View file

@ -95,6 +95,31 @@ files:
type: gettext
update_option: update_as_unapproved
# macOS files
- source: /mac/Keyman4MacIM/Keyman4MacIM/KMAboutWindow/en.lproj/KMAboutWindowController.strings
dest: /mac/app/KMAboutWindowController.strings
translation: /mac/Keyman4MacIM/Keyman4MacIM/KMAboutWindow/%osx_code%/%original_file_name%
- source: /mac/Keyman4MacIM/Keyman4MacIM/KMConfiguration/en.lproj/preferences.strings
dest: /mac/app/preferences.strings
translation: /mac/Keyman4MacIM/Keyman4MacIM/KMConfiguration/%osx_code%/%original_file_name%
- source: /mac/Keyman4MacIM/Keyman4MacIM/KMInfoWindow/en.lproj/KMInfoWindowController.strings
dest: /mac/app/KMInfoWindowController.strings
translation: /mac/Keyman4MacIM/Keyman4MacIM/KMInfoWindow/%osx_code%/%original_file_name%
- source: /mac/Keyman4MacIM/Keyman4MacIM/KMKeyboardHelpWindow/en.lproj/KMKeyboardHelpWindowController.strings
dest: /mac/app/KMKeyboardHelpWindowController.strings
translation: /mac/Keyman4MacIM/Keyman4MacIM/KMKeyboardHelpWindow/%osx_code%/%original_file_name%
- source: /mac/Keyman4MacIM/Keyman4MacIM/en.lproj/Localizable.strings
dest: /mac/app/Localizable.strings
translation: /mac/Keyman4MacIM/Keyman4MacIM/%osx_code%/%original_file_name%
- source: /mac/Keyman4MacIM/Keyman4MacIM/en.lproj/MainMenu.strings
dest: /mac/app/MainMenu.strings
translation: /mac/Keyman4MacIM/Keyman4MacIM/%osx_code%/%original_file_name%
# crowdin parameters descriptions:

View file

@ -1,12 +1,12 @@
{
"name": "@keymanapp/lexical-model-compiler",
"version": "15.0.129",
"version": "15.0.157",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@keymanapp/lexical-model-compiler",
"version": "15.0.50",
"version": "15.0.121",
"license": "MIT",
"dependencies": {
"commander": "^3.0.0",
@ -23,7 +23,7 @@
"@types/node": "^10.14.6",
"@types/xml2js": "^0.4.5",
"chalk": "^2.4.2",
"jszip": "^2.5.0"
"jszip": "^3.7.0"
},
"engines": {
"node": ">=12.0.0"
@ -227,14 +227,107 @@
}
},
"node_modules/jszip": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/jszip/-/jszip-2.5.0.tgz",
"integrity": "sha1-dET9hVHd8+XacZj+oMkbyDCMwnQ=",
"version": "3.7.1",
"resolved": "https://registry.npmjs.org/jszip/-/jszip-3.7.1.tgz",
"integrity": "sha512-ghL0tz1XG9ZEmRMcEN2vt7xabrDdqHHeykgARpmZ0BiIctWxM47Vt63ZO2dnp4QYt/xJVLLy5Zv1l/xRdh2byg==",
"dev": true,
"dependencies": {
"pako": "~0.2.5"
"lie": "~3.3.0",
"pako": "~1.0.2",
"readable-stream": "~2.3.6",
"set-immediate-shim": "~1.0.1"
}
},
"node_modules/jszip/node_modules/core-util-is": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
"dev": true
},
"node_modules/jszip/node_modules/immediate": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
"integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=",
"dev": true
},
"node_modules/jszip/node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"dev": true
},
"node_modules/jszip/node_modules/isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
"dev": true
},
"node_modules/jszip/node_modules/lie": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz",
"integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==",
"dev": true,
"dependencies": {
"immediate": "~3.0.5"
}
},
"node_modules/jszip/node_modules/pako": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
"integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==",
"dev": true
},
"node_modules/jszip/node_modules/process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
"dev": true
},
"node_modules/jszip/node_modules/readable-stream": {
"version": "2.3.7",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
"integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
"dev": true,
"dependencies": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
"isarray": "~1.0.0",
"process-nextick-args": "~2.0.0",
"safe-buffer": "~5.1.1",
"string_decoder": "~1.1.1",
"util-deprecate": "~1.0.1"
}
},
"node_modules/jszip/node_modules/safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
"dev": true
},
"node_modules/jszip/node_modules/set-immediate-shim": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz",
"integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/jszip/node_modules/string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"dev": true,
"dependencies": {
"safe-buffer": "~5.1.0"
}
},
"node_modules/jszip/node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
"dev": true
},
"node_modules/object-inspect": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz",
@ -260,12 +353,6 @@
"node": ">= 0.8"
}
},
"node_modules/pako": {
"version": "0.2.9",
"resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz",
"integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=",
"dev": true
},
"node_modules/sax": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
@ -498,12 +585,104 @@
}
},
"jszip": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/jszip/-/jszip-2.5.0.tgz",
"integrity": "sha1-dET9hVHd8+XacZj+oMkbyDCMwnQ=",
"version": "3.7.1",
"resolved": "https://registry.npmjs.org/jszip/-/jszip-3.7.1.tgz",
"integrity": "sha512-ghL0tz1XG9ZEmRMcEN2vt7xabrDdqHHeykgARpmZ0BiIctWxM47Vt63ZO2dnp4QYt/xJVLLy5Zv1l/xRdh2byg==",
"dev": true,
"requires": {
"pako": "~0.2.5"
"lie": "~3.3.0",
"pako": "~1.0.2",
"readable-stream": "~2.3.6",
"set-immediate-shim": "~1.0.1"
},
"dependencies": {
"core-util-is": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
"dev": true
},
"immediate": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
"integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=",
"dev": true
},
"inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"dev": true
},
"isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
"dev": true
},
"lie": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz",
"integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==",
"dev": true,
"requires": {
"immediate": "~3.0.5"
}
},
"pako": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
"integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==",
"dev": true
},
"process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
"dev": true
},
"readable-stream": {
"version": "2.3.7",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
"integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
"dev": true,
"requires": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
"isarray": "~1.0.0",
"process-nextick-args": "~2.0.0",
"safe-buffer": "~5.1.1",
"string_decoder": "~1.1.1",
"util-deprecate": "~1.0.1"
}
},
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
"dev": true
},
"set-immediate-shim": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz",
"integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=",
"dev": true
},
"string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"dev": true,
"requires": {
"safe-buffer": "~5.1.0"
}
},
"util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
"dev": true
}
}
},
"object-inspect": {
@ -525,12 +704,6 @@
"es-abstract": "^1.5.1"
}
},
"pako": {
"version": "0.2.9",
"resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz",
"integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=",
"dev": true
},
"sax": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/lexical-model-compiler",
"version": "15.0.129",
"version": "15.0.157",
"description": "Keyman Developer lexical model compiler",
"keywords": [
"keyboard",
@ -37,21 +37,21 @@
"node": ">=12.0.0"
},
"dependencies": {
"@keymanapp/models-types": "^15.0.129",
"@keymanapp/models-types": "^15.0.157",
"commander": "^3.0.0",
"typescript": "^3.8.3",
"xml2js": "^0.4.19"
},
"devDependencies": {
"@keymanapp/models-templates": "^15.0.129",
"@keymanapp/models-wordbreakers": "^15.0.129",
"@keymanapp/models-templates": "^15.0.157",
"@keymanapp/models-wordbreakers": "^15.0.157",
"@types/chai": "^4.1.7",
"@types/mocha": "^5.2.7",
"@types/node": "^10.14.6",
"@types/xml2js": "^0.4.5",
"chai": "^4.3.4",
"chalk": "^2.4.2",
"jszip": "^2.5.0",
"jszip": "^3.7.0",
"mocha": "^8.4.0",
"ts-node": "^9.1.1"
},

View file

@ -1,262 +0,0 @@
// Definitions by: mzeiher <https://github.com/mzeiher>, forabi <https://github.com/forabi>, eddieantonio <https://github.com/eddieantonio>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 2.3
/// <reference types="node" />
interface JSZipSupport {
arraybuffer: boolean;
uint8array: boolean;
blob: boolean;
nodebuffer: boolean;
}
type Compression = 'STORE' | 'DEFLATE';
interface Metadata {
percent: number;
currentFile: string;
}
type OnUpdateCallback = (metadata: Metadata) => void;
interface InputByType {
base64: string;
string: string;
text: string;
binarystring: string;
array: number[];
uint8array: Uint8Array;
arraybuffer: ArrayBuffer;
blob: Blob;
stream: NodeJS.ReadableStream;
}
interface OutputByType {
base64: string;
text: string;
binarystring: string;
array: number[];
uint8array: Uint8Array;
arraybuffer: ArrayBuffer;
blob: Blob;
nodebuffer: Buffer;
}
type InputFileFormat = InputByType[keyof InputByType];
type InputType = keyof InputByType;
type OutputType = keyof OutputByType;
interface JSZipObject {
name: string;
dir: boolean;
date: Date;
comment: string;
/** The UNIX permissions of the file, if any. */
unixPermissions: number | string | null;
/** The UNIX permissions of the file, if any. */
dosPermissions: number | null;
options: JSZipObjectOptions;
/**
* Prepare the content in the asked type.
* @param type the type of the result.
* @param onUpdate a function to call on each internal update.
* @return Promise the promise of the result.
*/
async<T extends OutputType>(type: T, onUpdate?: OnUpdateCallback): Promise<OutputByType[T]>;
nodeStream(type?: 'nodestream', onUpdate?: OnUpdateCallback): NodeJS.ReadableStream;
}
interface JSZipFileOptions {
/** Set to `true` if the data is `base64` encoded. For example image data from a `<canvas>` element. Plain text and HTML do not need this option. */
base64?: boolean;
/**
* Set to `true` if the data should be treated as raw content, `false` if this is a text. If `base64` is used,
* this defaults to `true`, if the data is not a `string`, this will be set to `true`.
*/
binary?: boolean;
/**
* The last modification date, defaults to the current date.
*/
date?: Date;
compression?: string;
comment?: string;
/** Set to `true` if (and only if) the input is a "binary string" and has already been prepared with a `0xFF` mask. */
optimizedBinaryString?: boolean;
/** Set to `true` if folders in the file path should be automatically created, otherwise there will only be virtual folders that represent the path to the file. */
createFolders?: boolean;
/** Set to `true` if this is a directory and content should be ignored. */
dir?: boolean;
/** 6 bits number. The DOS permissions of the file, if any. */
dosPermissions?: number | null;
/**
* 16 bits number. The UNIX permissions of the file, if any.
* Also accepts a `string` representing the octal value: `"644"`, `"755"`, etc.
*/
unixPermissions?: number | string | null;
}
interface JSZipObjectOptions {
compression: Compression;
}
interface JSZipGeneratorOptions<T extends OutputType = OutputType> {
/**
* @deprecated https://github.com/Stuk/jszip/blob/9ab3ed85da96700f32f50e01b87f2a4bde010390/lib/object.js#L738
*/
base64?: boolean;
compression?: Compression;
compressionOptions?: null | {
level: number;
};
type?: T;
comment?: string;
/**
* mime-type for the generated file.
* Useful when you need to generate a file with a different extension, ie: .ods.
* @default 'application/zip'
*/
mimeType?: string;
encodeFileName?(filename: string): string;
/** Stream the files and create file descriptors */
streamFiles?: boolean;
/** DOS (default) or UNIX */
platform?: 'DOS' | 'UNIX';
}
interface JSZipLoadOptions {
base64?: boolean;
checkCRC32?: boolean;
optimizedBinaryString?: boolean;
createFolders?: boolean;
decodeFileName?(filenameBytes: Uint8Array): string;
}
interface JSZip {
files: {[key: string]: JSZipObject};
/**
* Get a file from the archive
*
* @param Path relative path to file
* @return File matching path, null if no file found
*/
file(path: string): JSZipObject;
/**
* Get files matching a RegExp from archive
*
* @param path RegExp to match
* @return Return all matching files or an empty array
*/
file(path: RegExp): JSZipObject[];
/**
* Add a file to the archive
*
* @param path Relative path to file
* @param data Content of the file
* @param options Optional information about the file
* @return JSZip object
*/
file<T extends InputType>(path: string, data: InputByType[T] | Promise<InputByType[T]>, options?: JSZipFileOptions): this;
file<T extends InputType>(path: string, data: null, options?: JSZipFileOptions & { dir: true }): this;
/**
* Returns an new JSZip instance with the given folder as root
*
* @param name Name of the folder
* @return New JSZip object with the given folder as root or null
*/
folder(name: string): JSZip;
/**
* Returns new JSZip instances with the matching folders as root
*
* @param name RegExp to match
* @return New array of JSZipFile objects which match the RegExp
*/
folder(name: RegExp): JSZipObject[];
/**
* Call a callback function for each entry at this folder level.
*
* @param callback function
*/
forEach(callback: (relativePath: string, file: JSZipObject) => void): void;
/**
* Get all files which match the given filter function
*
* @param predicate Filter function
* @return Array of matched elements
*/
filter(predicate: (relativePath: string, file: JSZipObject) => boolean): JSZipObject[];
/**
* Removes the file or folder from the archive
*
* @param path Relative path of file or folder
* @return Returns the JSZip instance
*/
remove(path: string): JSZip;
/**
* Generate the complete zip file
* @param {Object} options the options to generate the zip file :
* - base64, (deprecated, use type instead) true to generate base64.
* - compression, "STORE" by default.
* - type, "base64" by default. Values are : string, base64, uint8array, arraybuffer, blob.
* @return {String|Uint8Array|ArrayBuffer|Buffer|Blob} the zip file
*/
generate<T extends OutputType>(options?: JSZipGeneratorOptions<T>, onUpdate?: OnUpdateCallback): Promise<OutputByType[T]>;
/**
* Generates a new archive asynchronously
*
* @param options Optional options for the generator
* @param onUpdate The optional function called on each internal update with the metadata.
* @return A Node.js `ReadableStream`
*/
generateNodeStream(options?: JSZipGeneratorOptions<'nodebuffer'>, onUpdate?: OnUpdateCallback): NodeJS.ReadableStream;
/**
* Deserialize zip file asynchronously
*
* @param data Serialized zip file
* @param options Options for deserializing
* @return Returns promise
*/
loadAsync(data: InputFileFormat, options?: JSZipLoadOptions): Promise<JSZip>;
support: JSZipSupport;
external: {
Promise: PromiseConstructorLike;
};
version: string;
}
interface JSZipStatic extends JSZip {
/**
* Create JSZip instance
*/
(): JSZip;
/**
* Create JSZip instance
* If no parameters given an empty zip archive will be created
*
* @param data Serialized zip archive
* @param options Description of the serialized zip archive
*/
new (data?: InputFileFormat, options?: JSZipLoadOptions): this;
}
declare let JSZipModuleObject: JSZipStatic;
declare module "jszip" {
export = JSZipModuleObject;
}

Some files were not shown because too many files have changed in this diff Show more