Merge branch 'master' into fix/web/popup-positioning

This commit is contained in:
Marc Durdin 2021-10-05 17:41:49 +11:00 • committed by GitHub
commit dbd9787a7a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
255 changed files with 10139 additions and 1156 deletions

View file

@ -64,4 +64,4 @@ labels:
- label: 'cherry-pick'
matcher:
title: '🍒'
title: '(🍒|:cherries:)'

View file

@ -12,7 +12,7 @@ jobs:
repo-token: "${{ secrets.GITHUB_TOKEN }}"
- name: Update labels based on PR title
id: labeler
uses: fuxingloh/multi-labeler@8afa186ed03230c98fe24ebf9fe35093072ad46e
uses: fuxingloh/multi-labeler@8afa186ed03230c98fe24ebf9fe35093072ad46e # v1.4.0
with:
github-token: ${{secrets.GITHUB_TOKEN}}
config-path: .github/multi-labeler.yml

View file

@ -1,5 +1,84 @@
# Keyman Version History
## 15.0.124 alpha 2021-10-04
* fix(web): support variable stores with predictive text (#5749)
* fix(windows): handle edge cases using default language (#5709)
* fix(linux): Don't crash with non-keyboard package file (#5755)
* fix(linux): Don't crash displaying keyboard details (#5758)
## 15.0.123 alpha 2021-10-01
* fix(common): Fix cherry-pick labeling (#5782)
* chore(ios,android,windows): Update crowdin strings for Amharic (#5722)
## 15.0.122 alpha 2021-09-30
* fix(developer): move ampersand to shift+7 on touch (#5746)
* feat(windows): Keyman Core integration (#5443)
* chore(windows): Keyman Core UI and Settings (#5769)
* fix(linux): Fix debian package script (#5771)
* docs(mac): Add note about installing with homebrew (#5767)
## 15.0.121 alpha 2021-09-29
* fix(developer): remove empty touch rows on save (#5720)
* chore(common): Check in crowdin strings for Shuwa Latin (#5734)
* chore(windows): fix broken links in help (#5765)
## 15.0.120 alpha 2021-09-28
* fix: help.keyman.com script file cleanup (#5751)
* chore(common): Enhance cherry-pick labeling (#5759)
## 15.0.119 alpha 2021-09-24
* chore(common): support forked repos when triggering test builds (#5738)
## 15.0.118 alpha 2021-09-23
* chore(deps): bump ansi-regex from 5.0.0 to 5.0.1 in /resources/build/version (#5741)
* refactor(web): active element management in relation to OSK display control ️ (#5644)
* refactor(web): osk activation and visibility modeling ️ (#5661)
* chore(android/app): Remove runConfigruations.xml file (#5743)
* feat(web): new OSK type - the inlined OSK (#5665)
* chore(web): inline osk test page (#5728)
* feat(web): enables mouse interactivity for the predictive banner (#5739)
* fix(mac): add support for M1 processor (#5701)
## 15.0.117 alpha 2021-09-22
* fix(developer): run kmlmc from Keyman source path (#5727)
## 15.0.116 alpha 2021-09-21
* fix(common/core): insure list pntr is incremented (#5669)
* chore(common): Check in crowdin strings for Simplified Chinese (#5681)
* fix(web): Null check for calculating globe key position (#5724)
## 15.0.115 alpha 2021-09-20
* chore(common/core): cleanup version headers (#5719)
* refactor(web): OSK modularization - specialized OSKView classes ️ (#5633)
* feat(developer): track changes to option values better in debugger (#5696)
* fix(developer): support chiral modifiers in debugger (#5697)
## 15.0.114 alpha 2021-09-17
* feat(developer): Debugger platform option (#5640)
* feat(developer): Debugger keyboard options (#5647)
* fix(developer): add version info to Core (#5711)
* fix(common/core/web): layer reset on physical keystroke after OSK interaction (#5641)
* fix(ios): prevents installation of packages without JS (#5698)
## 15.0.113 alpha 2021-09-16
* fix(ios): version-tagging for errors logged from the system keyboard (#5693)
* fix(web): spacebar caption when functional layer differs from display layer (#5688)
* refactor(web): OSK modularization - view components, layout cleanup ️ (#5619)
* refactor(web): OSK modularization - common-path code -> OSKView ️ (#5620)
* fix(common/core/web): Remove empty rows in OSK (#5699)
## 15.0.112 alpha 2021-09-14
* chore(common): Update to Unicode 14.0 (#5686)

View file

@ -1 +1 @@
15.0.113
15.0.125

View file

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="com.android.tools.idea.compose.preview.runconfiguration.ComposePreviewRunConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
</set>
</option>
</component>
</project>

View file

@ -1,10 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.tavultesoft.kmapro">
<uses-permission android:name="android.permission.INTERNET" />
<!-- Keyman Engine removes INTERNET permission, so add it back -->
<uses-permission android:name="android.permission.INTERNET" tools:node="replace" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.VIBRATE" />

View file

@ -18,6 +18,10 @@
<string name="action_install_updates" comment="Menu notification that keyboard or dictionary updates available">ማሻሻያዎችን ይጫኑ</string>
<!-- Context: Title -->
<string name="title_version" comment="Title of Keyman for Android 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">ኪይማን የክሮም ስሪትን 57 ወይም አዲስ ይፈልጋል።</string>
<!-- Context: Button label -->
<string name="button_update_chrome" comment="Prompt to upgrade Chrome in the Play Store">ክሮምን ማዘመን</string>
<!-- Context: Textfield prompt (&#8230; is the ellipsis character "...") -->
<string name="textview_hint" comment="Prompt to start typing">እዚህ ጋር መጻፍ ይጀምሩ &#8230;</string>
<!-- Context: Splash screen (version/copyright info currently disabled -->
@ -37,11 +41,11 @@
<!-- Context: Get Started menu -->
<string name="enable_system_keyboard" comment="Menu item to enable Keyman as system keyboard">ኪይማኑን ለሲስተም ኪቦርድ እንዲሆን ያድርጉ</string>
<!-- Context: Get Started menu -->
<string name="set_keyman_as_default" comment="Menu item to set Keyman as default system keyboard">ኪማኑን መደበና የፊደል ገበታ ይሰይሙ</string>
<string name="set_keyman_as_default" comment="Menu item to set Keyman as default system keyboard">ኪማኑን መደበኛ የፊደል ገበታ ይሰይሙ</string>
<!-- Context: Get Started menu -->
<string name="more_info" comment="Open the Keyman for Android help page">ተጨማሪ መረጃ</string>
<!-- Context: Get Started menu -->
<string name="show_get_started" comment="Show the &quot;Get Started&quot; menu on startup">በሚነሳበት ሰአት ይታይ\"%1$s\"</string>
<string name="show_get_started" comment="Show the &quot;Get Started&quot; menu on startup">በሚነሳበት ሰአት ይታይ \"%1$s\"</string>
<!-- Context: Android Storage Permission -->
<string name="request_storage_permission" comment="Request storage permission to access keyboard packages">የፊደል ገበታውን ሰሌዳ ጥቅሎችን ለመጫን ለኪይማኑ ውጫዊ ማከማቻ ለማንበብ ፈቃድ ይስጡት።</string>
<!-- Context: Android Storage Permission -->
@ -50,13 +54,33 @@
<string name="keyman_settings" comment="Settings menu title">አደረጃጀት</string>
<!-- Context: Keyman Settings menu -->
<plurals name="installed_languages">
<item quantity="one">የተጫኑ ቋንዎች (%1$d)</item>
<item quantity="one">የተጫኑ ቋንቋዎች (%1$d)</item>
<item quantity="other">የተጫኑ ቋንዎች (%1$d)</item>
</plurals>
<!-- Context: Keyman Settings menu -->
<string name="install_keyboard_or_dictionary" comment="Menu item to install keyboard or dictionary">የተጫነ የፊደል ገበታ ወይም መዝገበ ቃላት</string>
<!-- Context: Keyman Settings menu -->
<string name="change_display_language" comment="Menu action to change interface language">የኪማኑን የገጽታ ቋንቋ ይቀይሩ</string>
<string name="change_display_language" comment="Menu action to change interface language">የገጽታ ቋንቋ</string>
<!-- Context: Keyman Settings menu -->
<string name="adjust_keyboard_height" comment="Menu action to adjust keyboard height">የቋንቋ ገበታውን ቁመት ማስተካከል</string>
<!-- Context: Keyman Settings menu -->
<string name="spacebar_caption" comment="Menu action to set the spacebar caption">የስፔስባሩ መግለጫ ጽሁፍ</string>
<!-- Context: Keyman Settings menu / Spacebar caption -->
<string name="spacebar_caption_keyboard" comment="Spacebar caption option - keyboard">የፊደል ገበታ</string>
<!-- Context: Keyman Settings menu / Spacebar caption -->
<string name="spacebar_caption_language" comment="Spacebar caption option - language">ቋንቋ</string>
<!-- Context: Keyman Settings menu / Spacebar caption -->
<string name="spacebar_caption_language_keyboard" comment="Spacebar caption option - language + keyboard">ቋንቋና የፊደል ገበታ</string>
<!-- Context: Keyman Settings menu / Spacebar caption -->
<string name="spacebar_caption_blank" comment="Spacebar caption option - blank">ባዶ</string>
<!-- Context: Keyman Settings menu / Spacebar caption hint -->
<string name="spacebar_caption_hint_keyboard" comment="Spacebar caption hint - keyboard">የፊደል ገበታ ሰሌዳውን በስፔስ ባሩ ላይ አሳይ</string>
<!-- Context: Keyman Settings menu / Spacebar caption hint -->
<string name="spacebar_caption_hint_language" comment="Spacebar caption hint - language">የቋንቋውን ስም በስፔስ ባሩ ላይ አሳይ</string>
<!-- Context: Keyman Settings menu / Spacebar caption hint -->
<string name="spacebar_caption_hint_language_keyboard" comment="Spacebar caption hint - language + keyboard">ቋንቋና የፊደል ገበታውን በስፔስ ባሩ ላይ</string>
<!-- Context: Keyman Settings menu / Spacebar caption hint -->
<string name="spacebar_caption_hint_blank" comment="Spacebar caption hint - blank">የስፔስባሩ መግለጫ ጽሁፍ አታሳይ</string>
<!-- Context: Keyman Settings menu -->
<string name="show_banner" comment="text suggestions banner">ሁልጊዜ ባነሩን አሳይ</string>
<!-- Context: Keyman Settings menu -->
@ -87,6 +111,12 @@
<string name="added_language_to_keyboard" comment="Notification that a language name is added to a keyboard">%1$s የተጨመረ ቋንቋ %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">ሁሉም ቋንቋዎች ቀደም ሲል ተጭኗል</string>
<!-- Context: Adjust Keyboard Height menu -->
<string name="drag_the_keyboard" comment="First line of adjusting keyboard height">የፊደል ገበታ ሰሌዳውን በመጎተት ቁመቱን አስተካክል</string>
<!-- Context: Adjust Keyboard Height menu -->
<string name="rotate_the_device" comment="Second line of adjusting keyboard height">ዲቫይሱን በማሽከርከር ፖርትሬቱንና ላንድስኬፑን አስተካክል</string>
<!-- Context: Adjust Keyboard Height menu -->
<string name="reset_to_defaults" comment="Button to reset to default heights">ወደ ቀደመው ሴቲንግ መልስ</string>
<!-- Context: Keyman Web Browser -->
<string name="hint_text" comment="Prompt to type in the browser search bar">ፈልግ ወይም URL ጻፍ</string>
<!-- Context: Keyman Web Browser -->

View file

@ -0,0 +1,156 @@
<?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">Gassuma</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">Kubural katub</string>
<!-- Context: Menu Action -->
<string name="action_overflow" comment="Show additional menu items">Ziyada</string>
<!-- Context: Menu Action -->
<string name="action_clear_text" comment="Menu action to erase text">Sulal katub</string>
<!-- Context: Menu Action -->
<string name="action_info" comment="Menu action to display Keyman help page">Khabar</string>
<!-- Context: Menu Action -->
<string name="action_settings" comment="Menu action to open Settings menu">Miwasa</string>
<!-- Context: Menu Action -->
<string name="action_install_updates" comment="Menu notification that keyboard or dictionary updates available">Dys shu\'ul aljudad</string>
<!-- Context: Title -->
<string name="title_version" comment="Title of Keyman for Android version">Nafar: %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 bidor nafar hana Chrome 57 walla jadida.</string>
<!-- Context: Button label -->
<string name="button_update_chrome" comment="Prompt to upgrade Chrome in the Play Store">Saww Chrome eibga jadid</string>
<!-- Context: Textfield prompt (&#8230; is the ellipsis character "...") -->
<string name="textview_hint" comment="Prompt to start typing">Abda katub jai&#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)">Kubural katub: %1$d</string>
<!-- Context: Text Size dialog -->
<string name="ic_text_size_up" comment="Make text bigger">Zydal kubural katub</string>
<!-- Context: Text Size dialog -->
<string name="ic_text_size_down" comment="Make text smaller">Angusal kubural katub</string>
<!-- Context: Clear Text dialog -->
<string name="all_text_will_be_cleared" comment="Erase all the text">\nAlkatub chatta binchanna\n</string>
<!-- Context: Get Started menu -->
<string name="get_started" comment="Menu for getting started">Badiyan</string>
<!-- Context: Get Started menu -->
<string name="add_a_keyboard" comment="Menu item to add a keyboard">Dys keyboard ley luggatak</string>
<!-- Context: Get Started menu -->
<string name="enable_system_keyboard" comment="Menu item to enable Keyman as system keyboard">Dys Keyman eibga system-wide keyboard</string>
<!-- Context: Get Started menu -->
<string name="set_keyman_as_default" comment="Menu item to set Keyman as default system keyboard">Dys Keyman eibga keyboard altannaf beya</string>
<!-- Context: Get Started menu -->
<string name="more_info" comment="Open the Keyman for Android help page">Ziyada hana khabar</string>
<!-- Context: Get Started menu -->
<string name="show_get_started" comment="Show the &quot;Get Started&quot; menu on startup">Waar \"%1$s\" fi bidaya</string>
<!-- Context: Android Storage Permission -->
<string name="request_storage_permission" comment="Request storage permission to access keyboard packages">Ley dassasan nafar hanal keyboard, ath izin ley Keyman eidis shu\'ul ley bikan tahuth shu\'ul.</string>
<!-- Context: Android Storage Permission -->
<string name="storage_permission_denied" comment="Keyboard package installation may fail since Android storage permission not granted">Dakharo izin ley bikan hatathan shu\'ul. Bikun ma nadus nafaral keyboard</string>
<!-- Context: Keyman Settings menu -->
<string name="keyman_settings" comment="Settings menu title">Miwasa</string>
<!-- Context: Keyman Settings menu -->
<plurals name="installed_languages">
<item quantity="one">Luggat altasso (%1$d)</item>
<item quantity="two">Luggat altasso (%1$d)</item>
<item quantity="few">Luggat altasso (%1$d)</item>
<item quantity="other">Luggat altasso (%1$d)</item>
</plurals>
<!-- Context: Keyman Settings menu -->
<string name="install_keyboard_or_dictionary" comment="Menu item to install keyboard or dictionary">Dyssal Keyboard walla kakkad hana kalimat</string>
<!-- Context: Keyman Settings menu -->
<string name="change_display_language" comment="Menu action to change interface language">Lugga albiwari</string>
<!-- Context: Keyman Settings menu -->
<string name="adjust_keyboard_height" comment="Menu action to adjust keyboard height">Abdul tulal keyboard</string>
<!-- Context: Keyman Settings menu -->
<string name="spacebar_caption" comment="Menu action to set the spacebar caption">Shu\'ul baynatum</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">Lugga</string>
<!-- Context: Keyman Settings menu / Spacebar caption -->
<string name="spacebar_caption_language_keyboard" comment="Spacebar caption option - language + keyboard">Lugga + Keyboard</string>
<!-- Context: Keyman Settings menu / Spacebar caption -->
<string name="spacebar_caption_blank" comment="Spacebar caption option - blank">Mafi shai</string>
<!-- Context: Keyman Settings menu / Spacebar caption hint -->
<string name="spacebar_caption_hint_keyboard" comment="Spacebar caption hint - keyboard">War usumal keyboard faougal bikanal spacebar</string>
<!-- Context: Keyman Settings menu / Spacebar caption hint -->
<string name="spacebar_caption_hint_language" comment="Spacebar caption hint - language">War usumal lugga faougal spacebar</string>
<!-- Context: Keyman Settings menu / Spacebar caption hint -->
<string name="spacebar_caption_hint_language_keyboard" comment="Spacebar caption hint - language + keyboard">Lugga bey keyboard faougal spacebar</string>
<!-- Context: Keyman Settings menu / Spacebar caption hint -->
<string name="spacebar_caption_hint_blank" comment="Spacebar caption hint - blank">Ya eiwari shaykula faougal spacebar</string>
<!-- Context: Keyman Settings menu -->
<string name="show_banner" comment="text suggestions banner">Matakula waral banner</string>
<!-- Context: Keyman Settings menu -->
<string name="show_banner_on" comment="Description when toggle is on">Ley eiwasu</string>
<!-- Context: Keyman Settings menu -->
<string name="show_banner_off" comment="Description when toggle is off">Kan maktul, bil waar eilla waqat dasso kutub abu zan</string>
<!-- Context: Keyman Settings menu -->
<string name="show_send_crash_report" comment="permission for sending crash reports">Assad ley lazzazan mashakil fyl internet</string>
<!-- Context: Keyman Settings menu -->
<string name="show_send_crash_report_on" comment="Description when toggle is on">Kan mufakka bas biluzzal mashakil ley siyada</string>
<!-- Context: Keyman Settings menu -->
<string name="show_send_crash_report_off" comment="Description when toggle is off">Kan maktul ma biluzzal mashakil</string>
<!-- Context: Keyman Settings "Install Keyboard or Dictionary" menu -->
<string name="install_from_keyman_dot_com" comment="Install package from Keyman server">Dyssa min keyman.com</string>
<!-- Context: Keyman Settings "Install Keyboard or Dictionary" menu -->
<string name="install_from_local_file" comment="Install package file from local device">Dyssa min local file</string>
<!-- Context: Keyman Settings "Install Keyboard or Dictionary" menu -->
<string name="install_from_other_device" comment="Scan QR Code">Dyssa min bikan gadey</string>
<!-- Context: Keyman Settings "Install Keyboard or Dictionary" menu -->
<string name="add_languages_to_installed_keyboard" comment="Install additional languages from a keyboard package">Zyd luggat ley keyboard aldassayta</string>
<!-- Context: Keyman Settings "Install Keyboard or Dictionary" menu -->
<string name="add_language_subtext" comment="Additional information for adding another language">(min keyboard package)</string>
<!-- Context: Select Package and Select Languages menu -->
<string name="title_select_keyboard_package_list" comment="Select a keyboard package to add languages">Azzul 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">Azzul lugga ley %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">Zydal lugga %1$s ley %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">Luggat chatta dakhalo</string>
<!-- Context: Adjust Keyboard Height menu -->
<string name="drag_the_keyboard" comment="First line of adjusting keyboard height">Ajubdal keyboard ley badalan tula</string>
<!-- Context: Adjust Keyboard Height menu -->
<string name="rotate_the_device" comment="Second line of adjusting keyboard height">Barrumal shu\'ul ley badalan shaba binshaf</string>
<!-- Context: Adjust Keyboard Height menu -->
<string name="reset_to_defaults" comment="Button to reset to default heights">Eingalab ley shaba gabul</string>
<!-- Context: Keyman Web Browser -->
<string name="hint_text" comment="Prompt to type in the browser search bar">Fattish walla aktubal 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">Mafi bookmarks</string>
<!-- Context: Keyman Web Browser -->
<string name="add_bookmark" comment="Confirmation to add bookmark">Dys bookmark</string>
<!-- Context: Keyman Web Browser -->
<string name="hint_title" comment="Page title for saved bookmark">Title</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">Package %1$s aba ma bidukhul</string>
<!-- Context: KMP Package strings -->
<string name="downloading_keyboard_package" comment="Confirmation to download keyboard package filename">Dassasan keyboard package\n%1$s&#8230;</string>
<!-- Context: KMP Package strings -->
<string name="failed_to_extract" comment="Notification that keyboard package failed to unzip">Aba ma bisulla</string>
<!-- Context: KMP Package strings -->
<string name="install_keyboard_package" comment="Title to install keyboard package">Dyssal keyboard</string>
<!-- Context: KMP Package strings -->
<string name="install_predictive_text_package" comment="Title to install dictionary package">Dyssal kakkad hana kalimat</string>
<!-- Context: KMP Package strings -->
<string name="not_valid_package_file" comment="Notification when invalid package file cannot be installed">%1$s mi Kayman Package file nadif.\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 ma leya keyboard hana lammasan ley dassasana</string>
<!-- Context: KMP Package strings -->
<string name="no_new_predictive_text_to_install" comment="Notification when no dictionaries can be installed">Mafi kalima han zan jadid ley dassasana</string>
<!-- Context: KMP Package strings -->
<string name="no_targets_to_install" comment="Notification when a package doesn't contain keyboards or dictionaries">Mafi kalima han zan jadid walla keyboards ley dassasana</string>
<!-- Context: KMP Package strings -->
<string name="no_associated_languages" comment="Notification when a keyboard package doesn't contain languages">Keyboard package ma leya lugga almulamma beya ley dassasana</string>
<!-- Context: KMP Package strings -->
<string name="invalid_metadata" comment="kmp.json metadata file is invalid or missing in package">Mafi/mi nadif metadata fyl package</string>
</resources>

View file

@ -0,0 +1,153 @@
<?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">分享</string>
<!-- Context: Menu Action -->
<string name="action_web" comment="Menu action to open Keyman browser">网页浏览器</string>
<!-- Context: Menu Action -->
<string name="action_text_size" comment="Menu action to adjust text size">文本大小</string>
<!-- Context: Menu Action -->
<string name="action_overflow" comment="Show additional menu items">更多</string>
<!-- Context: Menu Action -->
<string name="action_clear_text" comment="Menu action to erase text">清除文本</string>
<!-- Context: Menu Action -->
<string name="action_info" comment="Menu action to display Keyman help page">信息</string>
<!-- Context: Menu Action -->
<string name="action_settings" comment="Menu action to open Settings menu">设置</string>
<!-- Context: Menu Action -->
<string name="action_install_updates" comment="Menu notification that keyboard or dictionary updates available">安装更新</string>
<!-- Context: Title -->
<string name="title_version" comment="Title of Keyman for Android 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 or newer.</string>
<!-- Context: Button label -->
<string name="button_update_chrome" comment="Prompt to upgrade Chrome in the Play Store">Update Chrome</string>
<!-- Context: Textfield prompt (&#8230; is the ellipsis character "...") -->
<string name="textview_hint" comment="Prompt to start typing">开始在这里输入&#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)">文本大小: %1$d</string>
<!-- Context: Text Size dialog -->
<string name="ic_text_size_up" comment="Make text bigger">文字大小放大</string>
<!-- Context: Text Size dialog -->
<string name="ic_text_size_down" comment="Make text smaller">文本大小小化</string>
<!-- Context: Clear Text dialog -->
<string name="all_text_will_be_cleared" comment="Erase all the text">\n所有文本将被清除\n</string>
<!-- Context: Get Started menu -->
<string name="get_started" comment="Menu for getting started">开始使用</string>
<!-- Context: Get Started menu -->
<string name="add_a_keyboard" comment="Menu item to add a keyboard">为您的语言加添键盘</string>
<!-- Context: Get Started menu -->
<string name="enable_system_keyboard" comment="Menu item to enable Keyman as system keyboard">启用Keyman作为全系统键盘</string>
<!-- Context: Get Started menu -->
<string name="set_keyman_as_default" comment="Menu item to set Keyman as default system keyboard">设置Keyman键盘为默认键盘</string>
<!-- Context: Get Started menu -->
<string name="more_info" comment="Open the Keyman for Android help page">更多信息</string>
<!-- Context: Get Started menu -->
<string name="show_get_started" comment="Show the &quot;Get Started&quot; menu on startup">启动时显示 \"%1$s\"</string>
<!-- Context: Android Storage Permission -->
<string name="request_storage_permission" comment="Request storage permission to access keyboard packages"> 要安装键盘包,请给予Keyman读取外部存储的权限。</string>
<!-- Context: Android Storage Permission -->
<string name="storage_permission_denied" comment="Keyboard package installation may fail since Android storage permission not granted"> 存储权限请求被拒绝。可能无法安装键盘包</string>
<!-- Context: Keyman Settings menu -->
<string name="keyman_settings" comment="Settings menu title">设置</string>
<!-- Context: Keyman Settings menu -->
<plurals name="installed_languages">
<item quantity="other">已安装的语言 (%1$d)</item>
</plurals>
<!-- Context: Keyman Settings menu -->
<string name="install_keyboard_or_dictionary" comment="Menu item to install keyboard or dictionary">安装键盘或词典</string>
<!-- Context: Keyman Settings menu -->
<string name="change_display_language" comment="Menu action to change interface language">Display language</string>
<!-- Context: Keyman Settings menu -->
<string name="adjust_keyboard_height" comment="Menu action to adjust keyboard height">Adjust keyboard height</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">Language</string>
<!-- Context: Keyman Settings menu / Spacebar caption -->
<string name="spacebar_caption_language_keyboard" comment="Spacebar caption option - language + keyboard">Language + 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">Show keyboard name on spacebar</string>
<!-- Context: Keyman Settings menu / Spacebar caption hint -->
<string name="spacebar_caption_hint_language" comment="Spacebar caption hint - language">Show language name on spacebar</string>
<!-- Context: Keyman Settings menu / Spacebar caption hint -->
<string name="spacebar_caption_hint_language_keyboard" comment="Spacebar caption hint - language + keyboard">Language and keyboard on spacebar</string>
<!-- Context: Keyman Settings menu / Spacebar caption hint -->
<string name="spacebar_caption_hint_blank" comment="Spacebar caption hint - blank">Do not show caption on spacebar</string>
<!-- Context: Keyman Settings menu -->
<string name="show_banner" comment="text suggestions banner">总是显示标签</string>
<!-- Context: Keyman Settings menu -->
<string name="show_banner_on" comment="Description when toggle is on">尚未实现</string>
<!-- Context: Keyman Settings menu -->
<string name="show_banner_off" comment="Description when toggle is off">关闭时,仅在启用预测文本时显示</string>
<!-- Context: Keyman Settings menu -->
<string name="show_send_crash_report" comment="permission for sending crash reports">允许通过网络发送崩溃报告</string>
<!-- Context: Keyman Settings menu -->
<string name="show_send_crash_report_on" comment="Description when toggle is on">开启时,崩溃报告将被发送</string>
<!-- Context: Keyman Settings menu -->
<string name="show_send_crash_report_off" comment="Description when toggle is off">关闭时,崩溃报告将不会被发送</string>
<!-- Context: Keyman Settings "Install Keyboard or Dictionary" menu -->
<string name="install_from_keyman_dot_com" comment="Install package from Keyman server">从 keyman.com 安装</string>
<!-- Context: Keyman Settings "Install Keyboard or Dictionary" menu -->
<string name="install_from_local_file" comment="Install package file from local device">从本地文件安装</string>
<!-- Context: Keyman Settings "Install Keyboard or Dictionary" menu -->
<string name="install_from_other_device" comment="Scan QR Code">从其他设备安装</string>
<!-- Context: Keyman Settings "Install Keyboard or Dictionary" menu -->
<string name="add_languages_to_installed_keyboard" comment="Install additional languages from a keyboard package">添加语言到已安装的键盘</string>
<!-- Context: Keyman Settings "Install Keyboard or Dictionary" menu -->
<string name="add_language_subtext" comment="Additional information for adding another language">(从键盘包)</string>
<!-- Context: Select Package and Select Languages menu -->
<string name="title_select_keyboard_package_list" comment="Select a keyboard package to add languages">选择键盘包</string>
<!-- Context: Select Package and Select Languages menu -->
<string name="title_select_languages_for_package" comment="Select language names from the keyboard package">选择 %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">添加语言 %1$s 到 %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">所有语言已被安装</string>
<!-- Context: Adjust Keyboard Height menu -->
<string name="drag_the_keyboard" comment="First line of adjusting keyboard height">Drag the keyboard to resize the height</string>
<!-- Context: Adjust Keyboard Height menu -->
<string name="rotate_the_device" comment="Second line of adjusting keyboard height">Rotate the device to adjust portrait and 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">搜索或键入网址</string>
<!-- Context: Keyman Web Browser -->
<string name="title_bookmarks" comment="Title for bookmarks">书签</string>
<!-- Context: Keyman Web Browser -->
<string name="no_bookmarks" comment="Text when bookmark list is empty">无书签</string>
<!-- Context: Keyman Web Browser -->
<string name="add_bookmark" comment="Confirmation to add bookmark">添加书签</string>
<!-- Context: Keyman Web Browser -->
<string name="hint_title" comment="Page title for saved bookmark">标题</string>
<!-- Context: Keyman Web Browser -->
<string name="hint_url" comment="Page URL for saved bookmark">链接</string>
<!-- Context: KMP Package strings -->
<string name="title_package_failed_to_install" comment="Error dialog title when package failed to install">软件包 %1$s 安装失败</string>
<!-- Context: KMP Package strings -->
<string name="downloading_keyboard_package" comment="Confirmation to download keyboard package filename">正在下载键盘组件\n%1$s&#8230;</string>
<!-- Context: KMP Package strings -->
<string name="failed_to_extract" comment="Notification that keyboard package failed to unzip">提取失败</string>
<!-- Context: KMP Package strings -->
<string name="install_keyboard_package" comment="Title to install keyboard package">安装键盘</string>
<!-- Context: KMP Package strings -->
<string name="install_predictive_text_package" comment="Title to install dictionary package">安装字典</string>
<!-- Context: KMP Package strings -->
<string name="not_valid_package_file" comment="Notification when invalid package file cannot be installed">%1$s 不是一个有效的 Keyman 软件包文件。\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">键盘包没有需要安装的触摸优化键盘</string>
<!-- Context: KMP Package strings -->
<string name="no_new_predictive_text_to_install" comment="Notification when no dictionaries can be installed">没有新的预测文本可以安装</string>
<!-- Context: KMP Package strings -->
<string name="no_targets_to_install" comment="Notification when a package doesn't contain keyboards or dictionaries">没有需要安装的键盘或预测文本</string>
<!-- Context: KMP Package strings -->
<string name="no_associated_languages" comment="Notification when a keyboard package doesn't contain languages">键盘包里没有需要安装的相关语言</string>
<!-- Context: KMP Package strings -->
<string name="invalid_metadata" comment="kmp.json metadata file is invalid or missing in package">软件包中的元数据无效/丢失</string>
</resources>

View file

@ -1,10 +1,12 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.tavultesoft.kmea" >
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.tavultesoft.kmea" >
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.VIBRATE" />
<!-- Ensure these permissions aren't added by dependencies unless calling app intentionally adds them -->
<uses-permission android:name="android.permission.INTERNET" tools:node="remove" />
<application
android:theme="@style/AppTheme" >

View file

@ -48,7 +48,9 @@ public class DisplayLanguages {
new DisplayLanguageType("de-DE", "German"),
new DisplayLanguageType("km-KH", "Khmer"),
new DisplayLanguageType("ann", "Obolo"),
new DisplayLanguageType("ff-ZA", "Pulaar-Fulfulde") // or Fulah
new DisplayLanguageType("ff-ZA", "Pulaar-Fulfulde"), // or Fulah
new DisplayLanguageType("shu-latn", "Shuwa (Latin)"),
new DisplayLanguageType("zh-CN", "中文(简体) (Simplified Chinese)")
};
return languages;
}

View file

@ -23,9 +23,11 @@ import com.tavultesoft.kmea.util.FileUtils;
import com.tavultesoft.kmea.util.KMLog;
import com.tavultesoft.kmea.util.KMString;
import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.Color;
import android.graphics.Rect;
@ -125,7 +127,10 @@ final class KMKeyboard extends WebView {
// Normally, this would be true to prevent the WebView from accessing the network.
// But this needs to false for sending embedded KMW crash reports to Sentry (keymanapp/keyman#3825)
getSettings().setBlockNetworkLoads(!KMManager.getMaySendCrashReport());
if (KMManager.hasInternetPermission(context)) {
// Throws SecurityException if INTERNET permission not granted
getSettings().setBlockNetworkLoads(!KMManager.getMaySendCrashReport());
}
getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
getSettings().setSupportZoom(false);

View file

@ -16,12 +16,14 @@ import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Dialog;
import android.app.KeyguardManager;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.content.res.Configuration;
import android.graphics.Bitmap;
@ -53,6 +55,8 @@ import android.webkit.WebViewClient;
import android.widget.FrameLayout;
import android.widget.RelativeLayout;
import androidx.core.content.ContextCompat;
import io.sentry.Breadcrumb;
import io.sentry.Sentry;
import io.sentry.SentryLevel;
@ -720,27 +724,42 @@ public final class KMManager {
}
}
/**
* Query the AndroidManifest file to see if a permission is granted.
* @param permission - The manifest permission to query
* @return boolean - true if the manifest permission is granted
*/
protected static boolean hasPermission(Context context, String permission) {
// API to check permission depends on Android SDK level
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
return (context.checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED);
}
return ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED;
}
/**
* Check if KMManager has an active network connection.
* Requires Manifest.permission.ACCESS_NETWORK_STATE to be granted
* @param context - The context
* @return boolean - true if manifest permission ACCESS_NETWORK_STATE is granted and the device
* has an active network connection
*/
@SuppressLint("MissingPermission")
public static boolean hasConnection(Context context) {
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo wifiNetwork = cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
if (wifiNetwork != null && wifiNetwork.isConnected()) {
return true;
}
NetworkInfo mobileNetwork = cm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
if (mobileNetwork != null && mobileNetwork.isConnected()) {
return true;
}
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
if (activeNetwork != null && activeNetwork.isConnected()) {
return true;
if (hasPermission(context, Manifest.permission.ACCESS_NETWORK_STATE)) {
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = cm.getActiveNetworkInfo();
return networkInfo != null && networkInfo.isConnectedOrConnecting();
}
return false;
}
public static boolean hasInternetPermission(Context context) {
return hasPermission(context, Manifest.permission.INTERNET);
}
private static void copyAssets(Context context) {
AssetManager assetManager = context.getAssets();
try {

View file

@ -367,6 +367,9 @@ public class CloudRepository {
if(cacheValid && shouldUseMemCache(context)) {
return; // isn't null - checked by `shouldUseCache`.
} else if (!KMManager.hasInternetPermission(context) || !KMManager.hasConnection(context)) {
// noop if no internet permission or network connection
return;
}
// check if cache file is valid

View file

@ -24,6 +24,10 @@
<!-- Context: Button label -->
<string name="label_close_keyman" comment="Close the Keyman application">ኪይማኑን ዝጋ</string>
<!-- Context: Button label -->
<string name="label_forward" comment="Button to go forward">ወደፊት</string>
<!-- Context: Button label -->
<string name="label_next_input_method" comment="Switch to next input method (replaces label_close_keyman)">የሚቀጥለውን የመቀበያ ዘዴ</string>
<!-- Context: Button label -->
<string name="label_download" comment="Button to confirm downloading an item">ወርዷል</string>
<!-- Context: Button label -->
<string name="label_install" comment="Confirmation to install a package">ጫን</string>
@ -69,6 +73,8 @@
<string name="fileprovider_undefined" comment="FileProvider library needed to view help file">የእገዛ ፋይልን ለማየት ፋይል ፕሮቫይደሩ ቤተ መጽሐፍት ያስፈልገዋል %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">የገበታ ሰሌዳ ፋታል ችግር ዝርዝር %1$s:%2$s ለ %3$s ቋንቋ፤ መደበኛ ቋንቋ ጭኗል።</string>
<!-- Context: Fatal keyboard error. -->
<string name="fatal_keyboard_error_short" comment="Error in keyboard (keyboard ID::packageID for language).">የፊደል ገበታ ሰሌዳው ችግር %1$s:%2$s ለ %3$s ቋንቋ።</string>
<!-- Context: Query for associated dictionary -->
<string name="query_associated_model" comment="Check if there's an available dictionary to download">ተያያዥነት ያለውን መዝገበ ቃላት ለመጫን እየፈተሸ ነው።</string>
<!-- Context: Model Updates -->

View file

@ -0,0 +1,157 @@
<?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="two">Keyboards</item>
<item quantity="few">Keyboards</item>
<item quantity="other">Keyboards</item>
</plurals>
<!-- Context: Title for list -->
<string name="title_add_keyboard" comment="Add a new keyboard">Zyd Keyboard jadid</string>
<!-- Context: Title for list -->
<string name="title_languages_settings" comment="List of installed languages">Luggat al dakhalo</string>
<!-- Context: Title for list -->
<string name="title_language_settings" comment="Keyman Settings for a language">%1$s Miwasa</string>
<!-- Context: Button label -->
<string name="label_add" comment="Button to add an item">Zyd</string>
<!-- Context: Button label -->
<string name="label_back" comment="Button to go back">Wara</string>
<!-- Context: Button label -->
<string name="label_cancel" comment="Button to cancel an action">Halla</string>
<!-- Context: Button label -->
<string name="label_close" comment="Close a dialog">Sidda</string>
<!-- Context: Button label -->
<string name="label_close_keyman" comment="Close the Keyman application">Siddal Keyman</string>
<!-- Context: Button label -->
<string name="label_forward" comment="Button to go forward">Giddam</string>
<!-- Context: Button label -->
<string name="label_next_input_method" comment="Switch to next input method (replaces label_close_keyman)">Darb hana dassasan hana giddam</string>
<!-- Context: Button label -->
<string name="label_download" comment="Button to confirm downloading an item">Dyssa</string>
<!-- Context: Button label -->
<string name="label_install" comment="Confirmation to install a package">Dyssa</string>
<!-- Context: Button label -->
<string name="label_later" comment="Do an action at a later time">Addarey</string>
<!-- Context: Button label -->
<string name="label_next" comment="Go to the next screen">Giddam</string>
<!-- Context: Button label -->
<string name="label_ok" comment="Button to acknowledge a dialog">Zayn</string>
<!-- Context: Button label -->
<string name="label_update" comment="Dialog button to update a resource">Jadidiye</string>
<!-- Context: Keyboard Updates -->
<string name="cannot_connect" comment="Error message when network connection fails">Ma gudur wassal server hana Keyman!</string>
<!-- Context: Keyboard Updates -->
<string name="confirm_delete_keyboard" comment="Confirmation to delete a keyboard">Tador ta chunnal keyboard da wah?</string>
<!-- Context: Keyboard Updates -->
<string name="confirm_download_keyboard" comment="Confirmation to download a keyboard update">Tador tadissal nafar hanal keyboard da aljadid wah?</string>
<!-- Context: Keyboard Updates -->
<string name="confirm_update" comment="Confirmation to update several resources">Tador tadis shu\'ul aljudad layl keyboards wa kakkad hanal kalimat dugut wah?</string>
<!-- Context: Keyboard Updates -->
<string name="keyboard_updates_channel">Bikan shu\'ulal judad</string>
<!-- Context: Keyboard Updates -->
<string name="keyboard_updates_available" comment="Notification when resource updates are available">Shu\'ul aljudad fyl bikan fi</string>
<!-- Context: Keyboard Updates -->
<string name="update_available" comment="Currently installed version of a resource with an available update">%1$s (Shu\'ul aljudad fi)</string>
<!-- Context: Keyboard Updates -->
<string name="keyboard_update_message" comment="language name: keyboard name">Shu\'ul aljudad layl keyboard fi %1$s: %2$s </string>
<!-- Context: Keyboard Updates -->
<string name="dictionary_update_message">Shu\'ul judad layl kakkad hanal kalimat fi %1$s: %2$s </string>
<!-- Context: Keyboard Info and Keyboard Settings -->
<string name="keyboard_version" comment="Label for keyboard version">Nafaral Keyboard</string>
<!-- Context: Keyboard Info and Keyboard Settings -->
<string name="help_link" comment="Label for help link">Bikan hana mi\'awana</string>
<!-- Context: Keyboard Info and Keyboard Settings -->
<string name="uninstall_keyboard" comment="Label for uninstalling keyboard">Sulal 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">[jadid]%1$s</string>
<!-- Context: Keyboard Info and Keyboard Settings -->
<string name="keyboard_qr_code" comment="QR Code description">Waral bikan da ley shu\'ul gadey finshan dassasanal \nkeyboard</string>
<!-- Context: Keyboard Help welcome.htm title -->
<string name="welcome_package" comment="Title to welcome.htm page (name and version)">Marhaba ley %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">FilProvider library bindawar ley fakkakanal shu\'ul da: %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">Mushkila kabirey bey %1$s:%2$s layl %3$s lugga. Dassasan shabal keyboard hanal gabul.</string>
<!-- Context: Fatal keyboard error. -->
<string name="fatal_keyboard_error_short" comment="Error in keyboard (keyboard ID::packageID for language).">Mushkila fyl keyboard %1$s:%2$s layl %3$s lugga.</string>
<!-- Context: Query for associated dictionary -->
<string name="query_associated_model" comment="Check if there's an available dictionary to download">Shafiyan kakkad abu kalimat shaba da ley dassasana</string>
<!-- Context: Model Updates -->
<string name="confirm_download_model" comment="Confirmation to download a dictionary update">Tador tadis kakkad abu kalimat aljudad wah?</string>
<!-- Context: No associated dictionary found -->
<string name="no_associated_model" comment="Confirmation there's no available dictionary to download">Mafi kakkad abu kalimat ley dassasana</string>
<!-- Context: Model Updates -->
<string name="catalog_unavailable" comment="Notification that the cloud resource catalog can't be updated">Bikanal shu\'ul mafi</string>
<!-- Context: Background download messages-->
<string name="catalog_download_start_in_background" comment="Notification that the resource catalog update will begin">Bikanal dassasan aljudad anbada milabbad</string>
<!-- Context: Background download messages-->
<string name="catalog_download_is_running_in_background" comment="Notification that the resource catalog update is still downloading">Alshu\'ul bada dassasana; albarak hawul addarey shiyakay!</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 ">Shafiyan bikanal shu\'ul</string>
<!-- Context: Background download messages-->
<string name="keyboard_download_start_in_background" comment="Notification that a keyboard download has started">Bada dassasanal keyboard milabbad</string>
<!-- Context: Background download messages-->
<string name="keyboard_download_is_running_in_background" comment="Notification that a keyboard download is still running">Al keyboard al\'alzalta bada bidukhul; albarak hawula addarey!</string>
<!-- Context: Background download messages-->
<string name="keyboard_download_finished" comment="Notification that a keyboard download has finished">Al keyboard mafi dakhal!</string>
<!-- Context: Background download messages-->
<string name="dictionary_download_start_in_background" comment="Notification that a dictionary download has started">Kakkad hanal kalimat bada bidukhul milabad</string>
<!-- Context: Background download messages-->
<string name="dictionary_download_is_running_in_background" comment="Notification that a dictionary download is still running">Kakkad hanal kalimat bada bidukhul; albarak hawula addarey!</string>
<!-- Context: Background download messages-->
<string name="dictionary_download_finished" comment="Notification that a dictionary download has finished">Kakkad hanal kalimat mafi dakhal.</string>
<!-- Context: Background download messages -->
<string name="download_failed" comment="Notification that a download failed">Aba ma bidukhul</string>
<!-- Context: Background download messages -->
<string name="failed_to_retrieve_file" comment="Failed to retrieve downloaded file">Aba ma eiwari aldakhal</string>
<!-- Context: General Updates -->
<string name="update_check_unavailable" comment="Error message when a Keyman server can't be reached">Aba ma eilagil bikan albishila!</string>
<!-- Context: General Updates -->
<string name="update_check_current" comment="Notification that all resources are up to date">"Alshu'ul kurut judad!"</string>
<!-- Context: General Updates -->
<string name="update_failed" comment="Notification that a resource update failed">Wahid walla ziyada hanal shu\'ul aba ma eilbadal layl jadid!</string>
<!-- Context: General Updates -->
<string name="update_success" comment="Notification that a resource update successfully updated">Bikanal bayan wugi jadid kurut!</string>
<!-- Context: Model Info -->
<string name="model_version" comment="Title for a dictionary version">Nafar hana kakkad hanal kalimat</string>
<!-- Context: Model Info -->
<string name="uninstall_model" comment="Label to uninstall a dictionary">Sulal kakkad hanal kalimat</string>
<!-- Context: Model Info -->
<string name="confirm_delete_model" comment="Confirmation to delete a dictionary">Tador tachunnal kakkad hanal kalimat da wah?</string>
<!-- Context: Language Settings Keyboard install strings -->
<string name="keyboard_install_toast" comment="Notification when a keyboard is installed">%1$s al keyboard dakhal</string>
<!-- Context: Language Settings menu strings -->
<string name="enable_corrections" comment="Enable corrections from the suggestion banner">Abdal miwasa</string>
<!-- Context: Language Settings menu strings -->
<string name="enable_predictions" comment="Enable predictions from the suggestion banner">Dyssal zan</string>
<!-- Context: Language Settings menu strings -->
<string name="model_label">Kakkad hana kalimat</string>
<!-- Context: Language Settings menu substring - Check for available dictionary -->
<string name="check_available_model" comment="Check for available dictionary">Shyf kakkad hana kalimat alfi</string>
<!-- Context: Language Settings menu strings -->
<string name="model_info_header" comment="Dictionary name">Kakkad hana kalimat: %1$s</string>
<!-- Context: Language Settings menu strings -->
<string name="model_picker_header" comment="Dictionaries for a specified language">%1$s kakkad hana kalimat</string>
<!-- Context: Language Settings menu strings -->
<!-- Context: Language Settings menu strings -->
<string name="model_install_toast" comment="Notification when a dictionary is installed">Kakkad hana kalimat dakhal</string>
<!-- Context: Language Settings menu strings -->
<plurals name="keyboard_count">
<item quantity="one">(%1$d keyboard)</item>
<item quantity="two">(%1$d keyboard)</item>
<item quantity="few">(%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">Hana Gabul</string>
<!-- Context: Content descriptions -->
<!-- Context: Content descriptions -->
<!-- Context: Popup menu labels -->
<string name="label_delete" comment="Confirmation to delete an item">Chinna</string>
<!-- Context: Shared preferences name -->
<!-- Context: Other strings -->
<string name="help_bubble_text">Assural bikan da ley badalanal keyboard</string>
</resources>

View file

@ -0,0 +1,151 @@
<?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="other">键盘</item>
</plurals>
<!-- Context: Title for list -->
<string name="title_add_keyboard" comment="Add a new keyboard">添加新键盘</string>
<!-- Context: Title for list -->
<string name="title_languages_settings" comment="List of installed languages">已安装的语言</string>
<!-- Context: Title for list -->
<string name="title_language_settings" comment="Keyman Settings for a language">%1$s 设置</string>
<!-- Context: Button label -->
<string name="label_add" comment="Button to add an item">添加</string>
<!-- Context: Button label -->
<string name="label_back" comment="Button to go back">返回</string>
<!-- Context: Button label -->
<string name="label_cancel" comment="Button to cancel an action">取消</string>
<!-- Context: Button label -->
<string name="label_close" comment="Close a dialog">关闭</string>
<!-- Context: Button label -->
<string name="label_close_keyman" comment="Close the Keyman application">关闭 Keyman</string>
<!-- Context: Button label -->
<string name="label_forward" comment="Button to go forward">Forward</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">下载</string>
<!-- Context: Button label -->
<string name="label_install" comment="Confirmation to install a package">安装</string>
<!-- Context: Button label -->
<string name="label_later" comment="Do an action at a later time">稍后再说</string>
<!-- Context: Button label -->
<string name="label_next" comment="Go to the next screen">下一个</string>
<!-- Context: Button label -->
<string name="label_ok" comment="Button to acknowledge a dialog">确定</string>
<!-- Context: Button label -->
<string name="label_update" comment="Dialog button to update a resource">更新</string>
<!-- Context: Keyboard Updates -->
<string name="cannot_connect" comment="Error message when network connection fails">无法连接到 Keyman 服务器!</string>
<!-- Context: Keyboard Updates -->
<string name="confirm_delete_keyboard" comment="Confirmation to delete a keyboard">您想要删除此键盘吗?</string>
<!-- Context: Keyboard Updates -->
<string name="confirm_download_keyboard" comment="Confirmation to download a keyboard update">您想要下载此键盘的最新版本吗?</string>
<!-- Context: Keyboard Updates -->
<string name="confirm_update" comment="Confirmation to update several resources">您想现在更新键盘和字典吗?</string>
<!-- Context: Keyboard Updates -->
<string name="keyboard_updates_channel">资源更新</string>
<!-- Context: Keyboard Updates -->
<string name="keyboard_updates_available" comment="Notification when resource updates are available">可用的资源更新</string>
<!-- Context: Keyboard Updates -->
<string name="update_available" comment="Currently installed version of a resource with an available update">%1$s (更新可用)</string>
<!-- Context: Keyboard Updates -->
<string name="keyboard_update_message" comment="language name: keyboard name"> %1$s 键盘可用的更新: %2$s </string>
<!-- Context: Keyboard Updates -->
<string name="dictionary_update_message">%1$s 字典可用的更新: %2$s </string>
<!-- Context: Keyboard Info and Keyboard Settings -->
<string name="keyboard_version" comment="Label for keyboard version">键盘版本</string>
<!-- Context: Keyboard Info and Keyboard Settings -->
<string name="help_link" comment="Label for help link">帮助链接</string>
<!-- Context: Keyboard Info and Keyboard Settings -->
<string name="uninstall_keyboard" comment="Label for uninstalling 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"> 扫描此代码以在另一台设备上加载此\n键盘</string>
<!-- Context: Keyboard Help welcome.htm title -->
<string name="welcome_package" comment="Title to welcome.htm page (name and version)">欢迎使用 %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"> 需要文件提供者文库来查看帮助文件: %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"> %1$s键盘错误:%2$s为%3$s 语言。正在加载默认键盘。</string>
<!-- Context: Fatal keyboard error. -->
<string name="fatal_keyboard_error_short" comment="Error in keyboard (keyboard ID::packageID for language)."> Error in keyboard %1$s:%2$s for %3$s language.</string>
<!-- Context: Query for associated dictionary -->
<string name="query_associated_model" comment="Check if there's an available dictionary to download">正在检查相关字典以下载</string>
<!-- Context: Model Updates -->
<string name="confirm_download_model" comment="Confirmation to download a dictionary update">您想要下载这个字典的最新版本吗?</string>
<!-- Context: No associated dictionary found -->
<string name="no_associated_model" comment="Confirmation there's no available dictionary to download">没有可下载的字典</string>
<!-- Context: Model Updates -->
<string name="catalog_unavailable" comment="Notification that the cloud resource catalog can't be updated">资源目录不可用</string>
<!-- Context: Background download messages-->
<string name="catalog_download_start_in_background" comment="Notification that the resource catalog update will begin">目录更新已在后台开始</string>
<!-- Context: Background download messages-->
<string name="catalog_download_is_running_in_background" comment="Notification that the resource catalog update is still downloading"> 编目仍在下载,请稍后再试!</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 ">正在检查资源</string>
<!-- Context: Background download messages-->
<string name="keyboard_download_start_in_background" comment="Notification that a keyboard download has started">键盘下载已在后台开始</string>
<!-- Context: Background download messages-->
<string name="keyboard_download_is_running_in_background" comment="Notification that a keyboard download is still running">选中的键盘已在下载;请稍后再试!</string>
<!-- Context: Background download messages-->
<string name="keyboard_download_finished" comment="Notification that a keyboard download has finished">键盘下载已完成!</string>
<!-- Context: Background download messages-->
<string name="dictionary_download_start_in_background" comment="Notification that a dictionary download has started">字典下载已在后台开始</string>
<!-- Context: Background download messages-->
<string name="dictionary_download_is_running_in_background" comment="Notification that a dictionary download is still running">选中的字典已在下载;请稍后再试!</string>
<!-- Context: Background download messages-->
<string name="dictionary_download_finished" comment="Notification that a dictionary download has finished">字典下载已完成。</string>
<!-- Context: Background download messages -->
<string name="download_failed" comment="Notification that a download failed">下载失败</string>
<!-- Context: Background download messages -->
<string name="failed_to_retrieve_file" comment="Failed to retrieve downloaded file">无法检索已下载的文件</string>
<!-- Context: General Updates -->
<string name="update_check_unavailable" comment="Error message when a Keyman server can't be reached">访问服务器失败!</string>
<!-- Context: General Updates -->
<string name="update_check_current" comment="Notification that all resources are up to date">"所有资源已是最新版本!"</string>
<!-- Context: General Updates -->
<string name="update_failed" comment="Notification that a resource update failed">一个或多个资源更新失败!</string>
<!-- Context: General Updates -->
<string name="update_success" comment="Notification that a resource update successfully updated">资源更新成功!</string>
<!-- Context: Model Info -->
<string name="model_version" comment="Title for a dictionary version">字典版本</string>
<!-- Context: Model Info -->
<string name="uninstall_model" comment="Label to uninstall a dictionary">卸载字典</string>
<!-- Context: Model Info -->
<string name="confirm_delete_model" comment="Confirmation to delete a dictionary">您想要删除这个字典吗?</string>
<!-- Context: Language Settings Keyboard install strings -->
<string name="keyboard_install_toast" comment="Notification when a keyboard is installed">%1$s 键盘已安装</string>
<!-- Context: Language Settings menu strings -->
<string name="enable_corrections" comment="Enable corrections from the suggestion banner">启用校正</string>
<!-- Context: Language Settings menu strings -->
<string name="enable_predictions" comment="Enable predictions from the suggestion banner">启用预测</string>
<!-- Context: Language Settings menu strings -->
<string name="model_label">字典</string>
<!-- Context: Language Settings menu substring - Check for available dictionary -->
<string name="check_available_model" comment="Check for available dictionary">检查可用字典</string>
<!-- Context: Language Settings menu strings -->
<string name="model_info_header" comment="Dictionary name">字典: %1$s</string>
<!-- Context: Language Settings menu strings -->
<string name="model_picker_header" comment="Dictionaries for a specified language">%1$s 字典</string>
<!-- Context: Language Settings menu strings -->
<!-- Context: Language Settings menu strings -->
<string name="model_install_toast" comment="Notification when a dictionary is installed">字典已安装</string>
<!-- Context: Language Settings menu strings -->
<plurals name="keyboard_count">
<item quantity="other">(%1$d 键盘)</item>
</plurals>
<!-- Context: "Change Display Language" menu -->
<string name="default_locale" comment="Use the device's current locale">默认区域设置</string>
<!-- Context: Content descriptions -->
<!-- Context: Content descriptions -->
<!-- Context: Popup menu labels -->
<string name="label_delete" comment="Confirmation to delete an item">删除</string>
<!-- Context: Shared preferences name -->
<!-- Context: Other strings -->
<string name="help_bubble_text">点击此处更改键盘</string>
</resources>

View file

@ -70,14 +70,7 @@ cd %KEYMAN_ROOT%\common\core\desktop
set BUILDTYPE=%2
if "%3" == "--static" (
set STATIC_LIBRARY=--default-library static
shift
) else (
set STATIC_LIBRARY=
)
echo "Is static build = !STATIC_LIBRARY! (%3)"
set STATIC_LIBRARY=--default-library both
if "%3" == "build" (
echo === Calling meson build for Windows !ARCH! !BUILDTYPE! ===

View file

@ -102,10 +102,7 @@ nothing in that event.
#include <stdlib.h>
#include <keyman/keyboardprocessor_bits.h>
#include <keyman/keyboardprocessor_vkeys.h>
#define KM_KBP_LIB_CURRENT @lib_curr@
#define KM_KBP_LIB_AGE @lib_age@
#define KM_KBP_LIB_REVISION @lib_rev@
#include <keyman/keyboardprocessor_version.h>
#if defined(__cplusplus)
extern "C"

View file

@ -58,6 +58,16 @@ typedef struct {
char16_t character;
} km_kbp_state_debug_key_info;
/**
* Option event data.
*
* Used only in event type KM_KBP_DEBUG_SET_OPTION.
*/
typedef struct {
void *store; // LPSTORE
km_kbp_cp value[DEBUG_MAX_CONTEXT]; // value to be saved into the store
} km_kbp_state_debug_kmx_option_info;
/**
* KMX processor data for each event. kmx_base.h defines the types that are
* passed in here, read only. Warning: context may contain sentinel values
@ -79,6 +89,7 @@ typedef struct {
/// the debugger; the debugger uses this to determine when to
/// execute the actions when single-stepping.
uint16_t first_action;
km_kbp_state_debug_kmx_option_info option;
} km_kbp_state_debug_kmx_info;
/**
@ -106,6 +117,7 @@ enum km_kbp_debug_type {
KM_KBP_DEBUG_NOMATCH_ENTER = 8,
KM_KBP_DEBUG_NOMATCH_EXIT = 9,
KM_KBP_DEBUG_END = 10,
KM_KBP_DEBUG_SET_OPTION = 11,
};
// Flags for KM_KBP_DEBUG_GROUP_EXIT

View file

@ -0,0 +1,15 @@
#define km_kbp_version_stringify(x) km_kbp_version_to_string(x)
#define km_kbp_version_to_string(x) #x
// Product versioning
#define KM_KBP_VERSION_MAJOR @majorver@
#define KM_KBP_VERSION_MINOR @minorver@
#define KM_KBP_VERSION_PATCH @patchver@
#define KM_KBP_VERSION_STRING km_kbp_version_stringify(@majorver@ ## . ## @minorver@ ## . ## @patchver@ ## .0)
// API versioning
#define KM_KBP_LIB_CURRENT @lib_curr@
#define KM_KBP_LIB_AGE @lib_age@
#define KM_KBP_LIB_REVISION @lib_rev@

View file

@ -7,19 +7,26 @@
#
ver = lib_version.split('.')
project_ver = meson.project_version().split('.')
cfg = configuration_data()
cfg.set('lib_curr', ver[0])
cfg.set('lib_age', ver[1])
cfg.set('lib_rev', ver[2])
cfg.set('majorver', project_ver[0])
cfg.set('minorver', project_ver[1])
cfg.set('patchver', project_ver[2])
configure_file(
configuration: cfg,
input: 'keyboardprocessor.h.in',
output: 'keyboardprocessor.h',
input: 'keyboardprocessor_version.h.in',
output: 'keyboardprocessor_version.h',
)
install_headers(join_paths(meson.current_build_dir(), 'keyboardprocessor.h'),
'keyboardprocessor_vkeys.h',
install_headers('keyboardprocessor.h',
'keyboardprocessor_bits.h',
'keyboardprocessor_consts.h',
'keyboardprocessor_debug.h',
'keyboardprocessor_vkeys.h',
join_paths(meson.current_build_dir(), 'keyboardprocessor_version.h'),
subdir: 'keyman')

View file

@ -9,7 +9,8 @@ project('keyboardprocessor', 'cpp', 'c',
version: run_command(find_program('getversion.bat', 'getversion.sh')).stdout().strip(),
license: 'MIT',
default_options : ['buildtype=release',
'cpp_std=c++14'])
'cpp_std=c++14',
'b_vscrt=static_from_buildtype'])
message('meson.project_version(): ' + meson.project_version() + '\n')
compiler = meson.get_compiler('cpp')

View file

@ -25,7 +25,9 @@ km_kbp_options_list_size(km_kbp_option_item const *opts)
if (!opts) return 0;
auto n = 0;
while (opts->key) ++n;
for (; opts->key; ++opts) {
++n;
}
return n;
}

View file

@ -37,6 +37,26 @@ void KMX_DebugItems::push_item(
_items->emplace_back(item);
}
void KMX_DebugItems::push_set_option(
uint16_t first_action,
LPSTORE option_store,
KMX_WCHAR const * value
) {
_items->assert_push_entry();
km_kbp_state_debug_item item = {KM_KBP_DEBUG_SET_OPTION, 0};
item.kmx_info.first_action = first_action;
item.kmx_info.rule = nullptr;
item.kmx_info.group = nullptr;
item.kmx_info.context[0] = 0;
item.key_info.character = 0;
item.key_info.modifier_state = 0;
item.key_info.vk = 0;
item.kmx_info.store_offsets[0] = 0xFFFF;
item.kmx_info.option.store = option_store;
u16ncpy(item.kmx_info.option.value, value, DEBUG_MAX_CONTEXT - 1);
_items->emplace_back(item);
}
void KMX_DebugItems::fill_store_offsets(km_kbp_state_debug_kmx_info *info, PKMX_WORD index_stack) {
int i, n;

View file

@ -58,6 +58,11 @@ public:
PKMX_WCHAR context,
PKMX_WORD index_stack
);
void push_set_option(
uint16_t first_action,
LPSTORE option_store,
KMX_WCHAR const * value
);
};
inline

View file

@ -59,7 +59,7 @@ const unsigned long CRCTable[256] = {
* and returns the updated value.
*/
unsigned long CalculateBufferCRC(unsigned long count, KMX_BYTE *p)
static unsigned long CalculateBufferCRC(unsigned long count, KMX_BYTE *p)
{
unsigned long temp1;
unsigned long temp2;

View file

@ -142,15 +142,21 @@ void KMX_Options::Set(int nStoreToSet, std::u16string const & rValueToSet)
assert(nStoreToSet >= 0);
assert(nStoreToSet < (int) _kp->Keyboard->cxStoreArray);
LPSTORE optionStore = &_kp->Keyboard->dpStoreArray[nStoreToSet];
auto & rStoreToSetValue = _kp->KeyboardOptions[nStoreToSet].Value;
if(rStoreToSetValue)
{
delete rStoreToSetValue;
}
if(m_debug_items) {
m_debug_items->push_set_option(m_actions.Length(), optionStore, rValueToSet.c_str());
}
rStoreToSetValue = new std::u16string::value_type[rValueToSet.size()+1];
u16cpy(rStoreToSetValue, /*u16len(sp->dpString)+1,*/ rValueToSet.c_str());
_kp->Keyboard->dpStoreArray[nStoreToSet].dpString = rStoreToSetValue;
optionStore->dpString = rStoreToSetValue;
}

View file

@ -8,6 +8,7 @@
#include "option.hpp"
#include "kmx_base.h"
#include "kmx_debugger.h"
namespace km {
namespace kbp {
@ -21,13 +22,17 @@ class KMX_Options
{
private:
LPINTKEYBOARDINFO _kp;
KMX_DebugItems *m_debug_items;
KMX_Actions& m_actions;
void AddOptionsStoresFromXString(PKMX_WCHAR s);
int _GetIndex(std::u16string const &key) const;
public:
KMX_Options(LPINTKEYBOARDINFO kp) : _kp(kp) {}
KMX_Options(LPINTKEYBOARDINFO kp, KMX_Actions& actions) : _kp(kp), m_actions(actions) {
m_debug_items = nullptr;
}
~KMX_Options();
void Init(std::vector<option> &opts);
@ -39,6 +44,10 @@ public:
void Reset(abstract_processor &, int nStoreToReset);
void Save(state & state, int nStoreToSave);
void SetInternalDebugItems(KMX_DebugItems *debug_items) {
m_debug_items = debug_items;
}
STORE const * begin() const;
STORE const * end() const;
};

View file

@ -19,7 +19,7 @@ KMX_BOOL km::kbp::kmx::g_silent = FALSE;
* KMX_ProcessEvent
*/
KMX_ProcessEvent::KMX_ProcessEvent() : m_actions(&m_context), m_options(&m_keyboard) {
KMX_ProcessEvent::KMX_ProcessEvent() : m_actions(&m_context), m_options(&m_keyboard, m_actions) {
m_indexStack = new KMX_WORD[GLOBAL_ContextStackSize];
m_miniContext = new KMX_WCHAR[GLOBAL_ContextStackSize];
m_miniContextIfLen = 0;
@ -29,7 +29,7 @@ KMX_ProcessEvent::KMX_ProcessEvent() : m_actions(&m_context), m_options(&m_keybo
KMX_ProcessEvent::~KMX_ProcessEvent() {
delete[] m_indexStack;
delete[] m_miniContext;
if(m_debug_items) delete m_debug_items;
DeleteInternalDebugItems();
}
char VKeyToChar(KMX_UINT modifiers, KMX_UINT vk) {
@ -86,14 +86,11 @@ KMX_BOOL KMX_ProcessEvent::ProcessEvent(
m_kbp_state = state;
// If debugging is enabled, then ...
if(m_debug_items) {
delete m_debug_items;
m_debug_items = NULL;
}
DeleteInternalDebugItems();
state->debug_items().clear();
if(state->debug_items().is_enabled()) {
m_debug_items = new KMX_DebugItems(&state->debug_items());
CreateInternalDebugItems();
} else {
// We want to have a clean debug state even if it is not in use
state->debug_items().push_end(m_actions.Length(), 0);
@ -148,8 +145,7 @@ KMX_BOOL KMX_ProcessEvent::ProcessEvent(
m_debug_items->push_end(m_actions.Length(), fOutputKeystroke ? KM_KBP_DEBUG_FLAG_OUTPUTKEYSTROKE : 0);
// m_debug_items is just a helper class that pushes to state->debug_items(),
// so we can throw it away after we are done with it
delete m_debug_items;
m_debug_items = nullptr;
DeleteInternalDebugItems();
}
m_kbp_state = nullptr;
@ -787,3 +783,18 @@ PKMX_WCHAR KMX_ProcessEvent::GetSystemStore(LPKEYBOARD kb, KMX_DWORD SystemID)
return NULL;
}
void KMX_ProcessEvent::CreateInternalDebugItems() {
assert(m_debug_items == nullptr);
assert(m_kbp_state != nullptr);
m_debug_items = new KMX_DebugItems(&m_kbp_state->debug_items());
m_options.SetInternalDebugItems(m_debug_items);
}
void KMX_ProcessEvent::DeleteInternalDebugItems() {
if(m_debug_items) {
delete m_debug_items;
m_debug_items = nullptr;
}
m_options.SetInternalDebugItems(m_debug_items);
}

View file

@ -71,6 +71,8 @@ private:
/* Utility functions */
void DeleteInternalDebugItems();
void CreateInternalDebugItems();
PKMX_WCHAR GetSystemStore(LPKEYBOARD kb, KMX_DWORD SystemID);
/* Caps Lock and modifier management */

View file

@ -5,6 +5,7 @@
#
defns = ['-DKMN_KBP_EXPORTING']
version_res = []
if compiler.get_id() == 'gcc' or compiler.get_id() == 'clang'
warns = [
@ -46,6 +47,10 @@ if compiler.get_id() == 'msvc'
'-DUNICODE'
]
links = []
# /n = append null
# /c65001 = utf-8 file format
version_res += import('windows').compile_resources('version.rc', args:['/n','/c65001'])
endif
if compiler.get_id() == 'emscripten'
@ -82,6 +87,7 @@ lib = library('kmnkbp0',
'kmx/kmx_processor.cpp',
'kmx/kmx_xstring.cpp',
'utfcodec.cpp',
version_res,
cpp_args: defns + warns + flags,
link_args: links,
dependencies: [rust_mock_processor],

View file

@ -0,0 +1,36 @@
#include <windows.h>
#include "include/keyman/keyboardprocessor_version.h"
// Encoding: UTF8 (compile with rc /c65001)
// Use rc /n to append null to all strings
1 VERSIONINFO
FILEVERSION KM_KBP_VERSION_MAJOR, KM_KBP_VERSION_MINOR, KM_KBP_VERSION_PATCH, 0
PRODUCTVERSION KM_KBP_VERSION_MAJOR, KM_KBP_VERSION_MINOR, KM_KBP_VERSION_PATCH, 0
FILEFLAGSMASK 0x3fL
FILEFLAGS 0x0L
FILEOS VOS_NT_WINDOWS32
FILETYPE VFT_DLL
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "0C0904E4"
BEGIN
VALUE "CompanyName", "SIL International"
VALUE "FileDescription", "Keyman Core"
VALUE "FileVersion", KM_KBP_VERSION_STRING
VALUE "InternalName", "Keyman Core"
VALUE "LegalCopyright", "© SIL International"
VALUE "LegalTrademarks", ""
VALUE "OriginalFilename", "KMNKBP0-0.DLL"
VALUE "ProductName", "Keyman Core"
VALUE "ProductVersion", KM_KBP_VERSION_STRING
VALUE "Comments", ""
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0xc09, 1252
END
END

View file

@ -348,6 +348,32 @@ void test_store_offsets() {
}));
}
/**
* Test 7: set option
*/
void test_set_option() {
setup("021 - options.kmx");
DEBUG_GROUP gp = {u"Main"};
DEBUG_KEY kp1 = { '1', /*line*/16, };
DEBUG_STORE sp = {0, u"foo", u"1"};
try_status(km_kbp_state_debug_set(test_state, 1));
// '1' -> set_option
try_status(km_kbp_process_event(test_state, KM_KBP_VKEY_1, 0, 1));
assert(debug_items(test_state, {
km_kbp_state_debug_item{KM_KBP_DEBUG_BEGIN, KM_KBP_DEBUG_FLAG_UNICODE, {KM_KBP_VKEY_1, 0, '1'}},
km_kbp_state_debug_item{KM_KBP_DEBUG_GROUP_ENTER, 0, {}, {u"", &gp}},
km_kbp_state_debug_item{KM_KBP_DEBUG_RULE_ENTER, 0, {}, {u"", &gp, &kp1, {0xFFFF}}},
km_kbp_state_debug_item{KM_KBP_DEBUG_SET_OPTION, 0, {}, {u"", nullptr, nullptr, {}, 0, {&sp, u"1"}}},
km_kbp_state_debug_item{KM_KBP_DEBUG_RULE_EXIT, 0, {}, {u"", &gp, &kp1, {0xFFFF}, 0}},
km_kbp_state_debug_item{KM_KBP_DEBUG_GROUP_EXIT, 0, {}, {u"", &gp, nullptr, {}, 0}},
km_kbp_state_debug_item{KM_KBP_DEBUG_END, 0, {}, {u"", nullptr, nullptr, {}, 0}},
}));
}
constexpr const auto help_str = "\
@ -377,6 +403,7 @@ int print_sizeof() {
std::cout << "sizeof(km_kbp_state_debug_item): " << sizeof(km_kbp_state_debug_item) << std::endl;
std::cout << "sizeof(km_kbp_state_debug_key_info): " << sizeof(km_kbp_state_debug_key_info) << std::endl;
std::cout << "sizeof(km_kbp_state_debug_kmx_info): " << sizeof(km_kbp_state_debug_kmx_info) << std::endl;
std::cout << "sizeof(km_kbp_state_debug_kmx_option_info): " << sizeof(km_kbp_state_debug_kmx_option_info) << std::endl;
std::cout << "sizeof([enum] km_kbp_debug_type): " << sizeof(km_kbp_debug_type) << std::endl;
exit(1);
}
@ -408,6 +435,7 @@ int main(int argc, char *argv []) {
test_basic_rule_matches();
test_multiple_groups();
test_store_offsets();
test_set_option();
// Destroy them
teardown();

View file

@ -31,6 +31,13 @@ typedef struct tagDEBUG_KEY
KMX_WCHAR const * dpContext;
} DEBUG_KEY, *LPDEBUG_KEY;
typedef struct tagDEBUG_STORE
{
KMX_DWORD dwSystemID;
KMX_WCHAR const * dpName;
KMX_WCHAR const * dpValue;
} DEBUG_STORE, *LPDEBUG_STORE;
const char *debug_item_types[] = {
"KM_KBP_DEBUG_BEGIN", // = 0,
"//KM_KBP_DEBUG_BEGIN_ANSI", // = 1, // not supported; instead rewrite ansi keyboards to Unicode with mcompile
@ -42,12 +49,14 @@ const char *debug_item_types[] = {
"KM_KBP_DEBUG_MATCH_EXIT", // = 7,
"KM_KBP_DEBUG_NOMATCH_ENTER", // = 8,
"KM_KBP_DEBUG_NOMATCH_EXIT", // = 9,
"KM_KBP_DEBUG_END" // = 10,
"KM_KBP_DEBUG_END", // = 10,
"KM_KBP_DEBUG_SET_OPTION", // = 11
};
void print_debug_item(const char *title, km_kbp_state_debug_item const & item) {
LPGROUP gp = static_cast<LPGROUP>(item.kmx_info.group);
LPKEY rule = static_cast<LPKEY>(item.kmx_info.rule);
LPSTORE store = static_cast<LPSTORE>(item.kmx_info.option.store);
std::cout
<< "debug_item " << title << std::endl
@ -77,6 +86,12 @@ void print_debug_item(const char *title, km_kbp_state_debug_item const & item) {
std::ostream_iterator<uint16_t>(std::cout, " ")
);
std::cout << std::endl;
if(store) std::cout
<< " option.store: " << std::endl
<< " name: " << store->dpName << std::endl
<< " value: " << store->dpString << std::endl;
if(store) std::cout
<< " option.value: " << item.kmx_info.option.value << std::endl;
}
bool are_store_offsets_equal(const uint16_t (&lhs)[DEBUG_STORE_OFFSETS_SIZE], const uint16_t (&rhs)[DEBUG_STORE_OFFSETS_SIZE]) {
@ -92,6 +107,7 @@ bool operator==(
if(result) {
LPGROUP lgp = static_cast<LPGROUP>(lhs.kmx_info.group), rgp = static_cast<LPGROUP>(rhs.kmx_info.group);
LPKEY lrule = static_cast<LPKEY>(lhs.kmx_info.rule), rrule = static_cast<LPKEY>(rhs.kmx_info.rule);
LPSTORE loption_store = static_cast<LPSTORE>(lhs.kmx_info.option.store), roption_store = static_cast<LPSTORE>(rhs.kmx_info.option.store);
switch(lhs.type) {
case KM_KBP_DEBUG_BEGIN:
result = lhs.key_info.character == rhs.key_info.character &&
@ -127,6 +143,12 @@ bool operator==(
u16cmp(lhs.kmx_info.context, rhs.kmx_info.context) == 0 &&
are_store_offsets_equal(lhs.kmx_info.store_offsets, rhs.kmx_info.store_offsets);
break;
case KM_KBP_DEBUG_SET_OPTION:
assert(loption_store != nullptr && roption_store != nullptr);
result =
u16cmp(loption_store->dpName, roption_store->dpName) == 0 &&
u16cmp(lhs.kmx_info.option.value, rhs.kmx_info.option.value) == 0;
break;
default:
assert(false);
result = false;

View file

@ -9,7 +9,7 @@ defns=['-DKMN_KBP_STATIC']
tests = [
['context-api', 'context_api.cpp'],
['keyboard-api', 'keyboard_api.cpp'],
# ['options-api', 'options_api.cpp'],
['options-api', 'options_api.cpp'],
['state-api', 'state_api.cpp'],
['debug-api', 'debug_api.cpp'],
]

View file

@ -17,6 +17,7 @@
namespace
{
#if 0
km_kbp_option_item const test_env[] =
{
{u"isdummy", u"yes", 0},
@ -48,13 +49,21 @@ namespace
{u"hello", u"!", KM_KBP_OPT_UNKNOWN},
KM_KBP_OPTIONS_END
};
#endif
km_kbp_option_item const empty_options_list[] = {KM_KBP_OPTIONS_END};
km_kbp_option_item const api_mock_options[] =
{
{u"hello", u"world", KM_KBP_OPT_KEYBOARD},
{u"isdummy", u"yes", KM_KBP_OPT_ENVIRONMENT},
{u"testing", u"maybe", KM_KBP_OPT_ENVIRONMENT},
KM_KBP_OPTIONS_END
};
#if 0
km::kbp::state mock_state(test_kb, test_env);
km::kbp::state empty_state(empty_options_list, empty_options_list);
#endif
std::string get_json_doc(km_kbp_state * const state)
{
@ -69,16 +78,13 @@ namespace
#define assert_lookup_equals(k,v,s) {if (!_assert_lookup_equals(k,v,s)) return __LINE__; }
bool _assert_lookup_equals(std::u16string const key, std::u16string value, km_kbp_option_scope scope)
{
#if 0
km_kbp_cp const * ret = nullptr;
auto s = km_kbp_state_option_lookup(api_mock_options, scope,
key.c_str(),
&ret);
bool v = s == KM_KBP_STATUS_OK && ret == value;
return v;
#else
return true;
#endif
}
constexpr char const *empty_json = "\
@ -109,15 +115,20 @@ constexpr char const *mock_json = "\
}\n\
}\n\
}\n";
#endif
}
int main(int, char * [])
{
#if 0
// Simple sanity tests on an empty options.
// Simple sanity tests on an empty options and mock options with 3 items.
if (km_kbp_options_list_size(empty_options_list) != 0)
return __LINE__;
if (km_kbp_options_list_size(api_mock_options) != 3)
return __LINE__;
#if 0
km_kbp_cp const *value;
auto s = km_kbp_options_lookup(api_empty_options,
KM_KBP_OPT_ENVIRONMENT,

View file

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

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/input-processor",
"version": "15.0.113",
"version": "15.0.125",
"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.113",
"@keymanapp/resources-gosh": "^15.0.113",
"@keymanapp/lexical-model-compiler": "^15.0.125",
"@keymanapp/resources-gosh": "^15.0.125",
"@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.113",
"@keymanapp/lexical-model-layer": "^15.0.113",
"@keymanapp/models-types": "^15.0.113",
"@keymanapp/web-environment": "^15.0.113",
"@keymanapp/web-utils": "^15.0.113",
"@keymanapp/keyboard-processor": "^15.0.125",
"@keymanapp/lexical-model-layer": "^15.0.125",
"@keymanapp/models-types": "^15.0.125",
"@keymanapp/web-environment": "^15.0.125",
"@keymanapp/web-utils": "^15.0.125",
"eventemitter3": "^4.0.0"
}
}

View file

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

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/keyboard-processor",
"version": "15.0.113",
"version": "15.0.125",
"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.113",
"@keymanapp/resources-gosh": "^15.0.125",
"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.113",
"@keymanapp/web-environment": "^15.0.113",
"@keymanapp/web-utils": "^15.0.113",
"@keymanapp/models-types": "^15.0.125",
"@keymanapp/web-environment": "^15.0.125",
"@keymanapp/web-utils": "^15.0.125",
"@types/node": "^11.9.4"
}
}

View file

@ -49,7 +49,7 @@ namespace com.keyman.keyboards {
* Matches the key code as set within Keyman Developer for the layout.
* For example, K_R or U_0020. Denotes either physical keys or virtual keys with custom output,
* with no additional metadata like layer or active modifiers.
*
*
* Is used to determine the keycode for input events, rule-matching, and keystroke processing.
*/
public get baseKeyID(): string {
@ -62,20 +62,20 @@ namespace com.keyman.keyboards {
/**
* A unique identifier based on both the key ID & the 'desktop layer' to be used for the key.
*
*
* Allows diambiguation of scenarios where the same key ID is used twice within a layer, but
* with different innate modifiers. (Refer to https://github.com/keymanapp/keyman/issues/4617)
* The 'desktop layer' may be omitted if it matches the key's display layer.
*
*
* Examples, given a 'default' display layer, matching keys to Keyman keyboard language:
*
*
* ```
* "K_Q"
* "K_Q"
* + [K_Q]
* "K_Q+shift"
* + [K_Q SHIFT]
* ```
*
*
* Useful when the active layer of an input-event is already known.
*/
public get coreID(): string {
@ -84,7 +84,7 @@ namespace com.keyman.keyboards {
}
let baseID = this.id || '';
if(this.displayLayer != this.layer) {
baseID = baseID + '+' + this.layer;
}
@ -95,19 +95,19 @@ namespace com.keyman.keyboards {
/**
* A keyboard-unique identifier to be used for any display elements representing this key
* in user interfaces and/or on-screen keyboards.
*
*
* Distinguishes between otherwise-identical keys on different layers of an OSK.
* Includes identifying information about the key's display layer.
*
*
* Examples, given a 'default' display layer, matching keys to Keyman keyboard language:
*
*
* ```
* "default-K_Q"
* "default-K_Q"
* + [K_Q]
* "default-K_Q+shift"
* + [K_Q SHIFT]
* ```
*
*
* Useful when only the active keyboard is known about an input event.
*/
public get elementID(): string {
@ -544,7 +544,7 @@ namespace com.keyman.keyboards {
return;
default:
// Refer to text/codes.ts - these are Keyman-custom "keycodes" used for
// layer shifting keys. To be safe, we currently let K_TABBACK and
// layer shifting keys. To be safe, we currently let K_TABBACK and
// K_TABFWD through, though we might be able to drop them too.
let code = com.keyman.text.Codes[key.baseKeyID];
if(code > 50000 && code < 50011) {
@ -639,11 +639,11 @@ namespace com.keyman.keyboards {
* Refer to https://github.com/keymanapp/keyman/issues/254, which mentions
* KD-11 from a prior issue-tracking system from the closed-source days that
* resulted in an unintended extra empty row.
*
*
* It'll be pretty rare to see a keyboard affected by the bug, but we don't
* 100% control all keyboards out there, so it's best we make sure the edge
* case is covered.
*
*
* @param layers The layer group to be loaded for the form factor. Will be
* mutated by this operation.
*/
@ -652,15 +652,11 @@ namespace com.keyman.keyboards {
let layer=layers[n];
let rows=layer['row'];
let i: number;
for(i=rows.length; i>0; i--) {
if(rows[i-1]['key'].length > 0) {
break;
for(i=rows.length-1; i>=0; i--) {
if(!Array.isArray(rows[i]['key']) || rows[i]['key'].length == 0) {
rows.splice(i, 1)
}
}
if(i < rows.length) {
rows.splice(i-rows.length,rows.length-i);
}
}
}
@ -675,28 +671,11 @@ namespace com.keyman.keyboards {
}
// Create a separate OSK div for each OSK layer, only one of which will ever be visible
var n: number, i: number;
var layers: LayoutLayer[], layer: LayoutLayer;
var n: number;
let layerMap: {[layerId: string]: ActiveLayer} = {};
var rows: LayoutRow[];
ActiveLayout.correctLayerEmptyRowBug(layout['layer']);
layers=layout['layer'];
// ***Delete any empty rows at the end added by compiler bug...
for(n=0; n<layers.length; n++) {
layer=layers[n]; rows=layer['row'];
for(i=rows.length; i>0; i--) {
if(rows[i-1]['key'].length > 0) {
break;
}
}
if(i < rows.length) {
rows.splice(i-rows.length,rows.length-i);
}
}
// ...remove to here when compiler bug fixed ***
let layers=layout['layer'];
ActiveLayout.correctLayerEmptyRowBug(layers);
// Add class functions to the existing layout object, allowing it to act as an ActiveLayout.
let dummy = new ActiveLayout();

View file

@ -20,9 +20,14 @@ namespace com.keyman.keyboards {
CALIBRATED = 2
}
export interface VariableStoreDictionary {
[name: string]: string;
};
/**
* Acts as a wrapper class for Keyman keyboards compiled to JS, providing type information
* and keyboard-centered functionality in an object-oriented way without modifying the
* and keyboard-centered functionality in an object-oriented way without modifying the
* wrapped keyboard itself.
*/
export class Keyboard {
@ -37,7 +42,7 @@ namespace com.keyman.keyboards {
/**
* This is the object provided to KeyboardInterface.registerKeyboard - that is, the keyboard
* being wrapped.
*
*
* TODO: Make this private instead. But there are a LOT of references that must be rooted out first.
*/
public readonly scriptObject: any;
@ -71,6 +76,51 @@ namespace com.keyman.keyboards {
return this.scriptObject['KN'];
}
/**
* Cache variable store values
*
* Primarily used for predictive text to prevent variable store
* values from being changed in 'fat finger' processing.
*
* KVS is available in keyboards compiled with Keyman Developer 15
* and later versions. See #2924.
*
* @returns an object with each property referencing a variable store
*/
get variableStores(): VariableStoreDictionary {
const storeNames = this.scriptObject['KVS'];
let values = {};
if(Array.isArray(storeNames)) {
for(let store of storeNames) {
values[store] = this.scriptObject[store];
}
}
return values;
}
/**
* Restore variable store values from cache
*
* KVS is available in keyboards compiled with Keyman Developer 15
* and later versions. See #2924.
*
* @param values name-value pairs for each store value
*/
set variableStores(values: VariableStoreDictionary) {
const storeNames = this.scriptObject['KVS'];
if(Array.isArray(storeNames)) {
for(let store of storeNames) {
// If the value is not present in the cache, don't overwrite it;
// while this is not used in initial implementation, we could use
// it in future to update a single variable store value rather than
// the whole cache.
if(typeof values[store] == 'string') {
this.scriptObject[store] = values[store];
}
}
}
}
// TODO: Better typing.
private get _legacyLayoutSpec(): any {
return this.scriptObject['KV']; // used with buildDefaultLayout; layout must be constructed at runtime.
@ -99,7 +149,7 @@ namespace com.keyman.keyboards {
/**
* HTML help text, as specified by either the &kmw_helptext or &kmw_helpfile system stores.
*
*
* Reference: https://help.keyman.com/developer/language/reference/kmw_helptext,
* https://help.keyman.com/developer/language/reference/kmw_helpfile
*/
@ -121,7 +171,7 @@ namespace com.keyman.keyboards {
* Embeds a custom script for use by the OSK, which may be interactive (like with sil_euro_latin).
* Note: this must be called AFTER any contents of `helpText` have been inserted into the DOM.
* (See sil_euro_latin's source -> sil_euro_latin_js.txt)
*
*
* Reference: https://help.keyman.com/developer/language/reference/kmw_embedjs
*/
embedScript(e: any) {
@ -136,10 +186,10 @@ namespace com.keyman.keyboards {
/**
* true if this keyboard uses a (legacy) pick list (Chinese, Japanese, Korean, etc.)
*
*
* TODO: Make a property on keyboards (say, `isPickList` / `KPL`) to signal this when we
* get around to better, generalized picker-list support.
*/
*/
get isCJK(): boolean { // I3363 (Build 301)
var lg: string;
if(typeof(this.scriptObject['KLC']) != 'undefined') {
@ -147,7 +197,7 @@ namespace com.keyman.keyboards {
} else if(typeof(this.scriptObject['LanguageCode']) != 'undefined') {
lg = this.scriptObject['LanguageCode'];
}
// While some of these aren't proper BCP-47 language codes, the CJK keyboards predate our use of BCP-47.
// So, we preserve the old ISO 639-3 codes, as that's what the keyboards are matching against.
return ((lg == 'cmn') || (lg == 'jpn') || (lg == 'kor'));
@ -186,7 +236,7 @@ namespace com.keyman.keyboards {
this.scriptObject['_kmw'] = tag;
}
return tag;
return tag;
}
get explodedStores(): {[storeName: string]: text.ComplexKeyboardStore} {
@ -209,7 +259,7 @@ namespace com.keyman.keyboards {
if(this._legacyLayoutSpec == null) {
return false;
}
// Only exists in KMW 10.0+, but before that Web had no chirality support, so... return false.
let layers = this._legacyLayoutSpec['KLS'];
if(!layers) {
@ -219,18 +269,18 @@ namespace com.keyman.keyboards {
var emulationMask = modifierCodes['LCTRL'] | modifierCodes['LALT'];
var unshiftedEmulationLayer = layers[Layouts.getLayerId(emulationMask)];
var shiftedEmulationLayer = layers[Layouts.getLayerId(modifierCodes['SHIFT'] | emulationMask)];
// buildDefaultLayout ensures that these are aliased to the original modifier set being emulated.
// As a result, we can directly test for reference equality.
//
// This allows us to still return `true` after creating the layers for emulation; during keyboard
// construction, the two layers should be null for AltGr emulation to succeed.
if(unshiftedEmulationLayer != null &&
if(unshiftedEmulationLayer != null &&
unshiftedEmulationLayer != layers[Layouts.getLayerId(modifierCodes['RALT'])]) {
return false;
}
if(shiftedEmulationLayer != null &&
if(shiftedEmulationLayer != null &&
shiftedEmulationLayer != layers[Layouts.getLayerId(modifierCodes['RALT'] | modifierCodes['SHIFT'])]) {
return false;
}
@ -273,9 +323,9 @@ namespace com.keyman.keyboards {
/**
* @param {number} _PCommand event code (16,17,18) or 0
* @param {Object} _PTarget target element
* @param {number} _PData 1 or 0
* @param {number} _PData 1 or 0
* Notifies keyboard of keystroke or other event
*/
*/
notify(_PCommand: number, _PTarget: text.OutputTarget, _PData: number) { // I2187
// Good example use case - the Japanese CJK-picker keyboard
if(typeof(this.scriptObject['KNS']) == 'function') {
@ -318,7 +368,7 @@ namespace com.keyman.keyboards {
rawSpecifications = {'F':'Tahoma', 'BK': Layouts.dfltText};
}
// Regardless of success, we'll want to initialize the field that backs the property;
// Regardless of success, we'll want to initialize the field that backs the property;
// may as well cache the default layout we just built, or a 'null' if it shouldn't exist..
if(!this._layouts) {
this._layouts = {};
@ -339,7 +389,7 @@ namespace com.keyman.keyboards {
/**
* Returns an ActiveLayout object representing the keyboard's layout for this form factor. May return null if a custom desktop "help" OSK is defined, as with sil_euro_latin.
*
*
* In such cases, please use either `helpText` or `insertHelpHTML` instead.
* @param formFactor {string} The desired form factor for the layout.
*/

View file

@ -972,6 +972,9 @@ namespace com.keyman.text {
// Capture the initial state of the OutputTarget before any rules are matched.
let preInput = Mock.from(outputTarget);
// Capture the initial state of any variable stores
const cachedVariableStores = this.activeKeyboard.variableStores;
// Establishes the results object, allowing corresponding commands to set values here as appropriate.
this.ruleBehavior = new RuleBehavior();
@ -987,6 +990,12 @@ namespace com.keyman.text {
// Finalize the rule's results.
this.ruleBehavior.transcription = outputTarget.buildTranscriptionFrom(preInput, keystroke);
// We always backup the changes to variable stores to the RuleBehavior, to
// be applied during finalization, then restore them to the cached initial
// values to avoid side-effects with predictive text mocks.
this.ruleBehavior.variableStores = this.activeKeyboard.variableStores;
this.activeKeyboard.variableStores = cachedVariableStores;
// `matched` refers to whether or not the FINAL rule (from any group) matched, rather than
// whether or not ANY rule matched. If the final rule doesn't match, we trigger the key's
// default behavior (if appropriate).
@ -1001,6 +1010,19 @@ namespace com.keyman.text {
return behavior;
}
/**
* Applies the dictionary of variable store values to the active keyboard
*
* Has no effect on keyboards compiled with 14.0 or earlier; system store
* names are not exposed unless compiled with Developer 15.0 or later.
*
* @param stores A dictionary of stores which should be found in the
* keyboard
*/
applyVariableStores(stores: com.keyman.keyboards.VariableStoreDictionary): void {
this.activeKeyboard.variableStores = stores;
}
/**
* Publishes the KeyboardInterface's shorthand API names. As this assigns the current functions
* held by the longform versions, note that this should be called after replacing any of them via

View file

@ -661,6 +661,9 @@ namespace com.keyman.text {
} else {
this.layerId = 'default';
}
let baseModifierState = text.KeyboardProcessor.getModifierState(this.layerId);
this.modStateFlags = baseModifierState | keyEvent.Lstates;
}
static isModifier(Levent: KeyEvent): boolean {

View file

@ -24,6 +24,11 @@ namespace com.keyman.text {
*/
saveStore: {[name: string]: VariableStore} = {};
/**
* A set of variable stores with possible changes to be applied during finalization.
*/
variableStores: keyboards.VariableStoreDictionary = {};
/**
* Denotes a non-output default behavior; this should be evaluated later, against the true keystroke.
*/
@ -46,9 +51,9 @@ namespace com.keyman.text {
/**
* In reference to https://github.com/keymanapp/keyman/pull/4350#issuecomment-768753852:
*
* If the final group processed is a context and keystroke group (using keys),
* and there is no nomatch rule, and the keystroke is not matched in the group,
*
* If the final group processed is a context and keystroke group (using keys),
* and there is no nomatch rule, and the keystroke is not matched in the group,
* the keystroke's default behavior should trigger, regardless of whether or not any
* rules in prior groups matched.
*/
@ -78,6 +83,8 @@ namespace com.keyman.text {
}
}
processor.keyboardInterface.applyVariableStores(this.variableStores);
if(processor.keyboardInterface.variableStoreSerializer) {
for(let storeID in this.saveStore) {
processor.keyboardInterface.variableStoreSerializer.saveStore(processor.activeKeyboard.id, storeID, this.saveStore[storeID]);
@ -99,13 +106,13 @@ namespace com.keyman.text {
/**
* Merges default-related behaviors from another RuleBehavior into this one. Assumes that the current instance
* "came first" chronologically. Both RuleBehaviors must be sourced from the same keystroke.
*
*
* Intended use: merging rule-based behavior with default key behavior during scenarios like those described
* at https://github.com/keymanapp/keyman/pull/4350#issuecomment-768753852.
*
*
* This function does not attempt a "complete" merge for two fully-constructed RuleBehaviors! Things
* WILL break for unintended uses.
* @param other
* @param other
*/
mergeInDefaults(other: RuleBehavior) {
let keystroke = this.transcription.keystroke;
@ -115,7 +122,7 @@ namespace com.keyman.text {
}
this.triggersDefaultCommand = this.triggersDefaultCommand || other.triggersDefaultCommand;
let mergingMock = Mock.from(this.transcription.preInput);
mergingMock.apply(this.transcription.transform);
mergingMock.apply(other.transcription.transform);

View file

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

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/recorder-core",
"version": "15.0.113",
"version": "15.0.125",
"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.113",
"@keymanapp/models-types": "^15.0.113",
"@keymanapp/web-environment": "^15.0.113",
"@keymanapp/web-utils": "^15.0.113",
"@keymanapp/keyboard-processor": "^15.0.125",
"@keymanapp/models-types": "^15.0.125",
"@keymanapp/web-environment": "^15.0.125",
"@keymanapp/web-utils": "^15.0.125",
"@types/node": "^11.9.4"
},
"devDependencies": {

View file

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

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/web-sentry-manager",
"version": "15.0.113",
"version": "15.0.125",
"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.113",
"@keymanapp/web-environment": "^15.0.125",
"@sentry/browser": "^5.27.4"
}
}

View file

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

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/web-utils",
"version": "15.0.113",
"version": "15.0.125",
"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.113",
"@keymanapp/web-environment": "^15.0.113",
"@keymanapp/resources-gosh": "^15.0.125",
"@keymanapp/web-environment": "^15.0.125",
"@types/node": "^14.0.5",
"typescript": "^3.8.3"
}

View file

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

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/models-templates",
"version": "15.0.113",
"version": "15.0.125",
"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.113",
"@keymanapp/web-utils": "^15.0.113",
"@keymanapp/models-types": "^15.0.125",
"@keymanapp/web-utils": "^15.0.125",
"@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.113"
"@keymanapp/models-wordbreakers": "^15.0.125"
}
}

View file

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

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/models-types",
"version": "15.0.113",
"version": "15.0.125",
"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.113",
"version": "15.0.125",
"lockfileVersion": 2,
"requires": true,
"packages": {

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/models-wordbreakers",
"version": "15.0.113",
"version": "15.0.125",
"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.113",
"@keymanapp/models-types": "^15.0.125",
"@types/chai": "^4.2.11",
"@types/mocha": "^7.0.2",
"chai": "^4.3.4",

View file

@ -1,12 +1,12 @@
{
"name": "@keymanapp/lexical-model-layer",
"version": "15.0.113",
"version": "15.0.125",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@keymanapp/lexical-model-layer",
"version": "15.0.80",
"version": "15.0.104",
"license": "MIT",
"dependencies": {
"es6-shim": "^0.35.5",

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/lexical-model-layer",
"version": "15.0.113",
"version": "15.0.125",
"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.113",
"@keymanapp/resources-gosh": "^15.0.113",
"@keymanapp/models-types": "^15.0.125",
"@keymanapp/resources-gosh": "^15.0.125",
"@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.113",
"@keymanapp/models-wordbreakers": "^15.0.113",
"@keymanapp/web-environment": "^15.0.113",
"@keymanapp/web-utils": "^15.0.113",
"@keymanapp/models-templates": "^15.0.125",
"@keymanapp/models-wordbreakers": "^15.0.125",
"@keymanapp/web-environment": "^15.0.125",
"@keymanapp/web-utils": "^15.0.125",
"es6-shim": "^0.35.5",
"string.prototype.codepointat": "^0.2.1",
"string.prototype.startswith": "^0.2.0"

View file

@ -36,6 +36,7 @@ files:
android_code:
es-419: b+es+419
pap: pap
shu-latn-n: b+shu+latn
- source: /android/KMAPro/kMAPro/src/main/res/values/strings.xml
dest: /android/app/strings.xml
@ -45,6 +46,7 @@ files:
android_code:
es-419: b+es+419
pap: pap
shu-latn-n: b+shu+latn
# Windows files
# Note: we use type: android for the Windows project files

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/lexical-model-compiler",
"version": "15.0.113",
"version": "15.0.125",
"lockfileVersion": 2,
"requires": true,
"packages": {

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/lexical-model-compiler",
"version": "15.0.113",
"version": "15.0.125",
"description": "Keyman Developer lexical model compiler",
"keywords": [
"keyboard",
@ -37,14 +37,14 @@
"node": ">=12.0.0"
},
"dependencies": {
"@keymanapp/models-types": "^15.0.113",
"@keymanapp/models-types": "^15.0.125",
"commander": "^3.0.0",
"typescript": "^3.8.3",
"xml2js": "^0.4.19"
},
"devDependencies": {
"@keymanapp/models-templates": "^15.0.113",
"@keymanapp/models-wordbreakers": "^15.0.113",
"@keymanapp/models-templates": "^15.0.125",
"@keymanapp/models-wordbreakers": "^15.0.125",
"@types/chai": "^4.1.7",
"@types/mocha": "^5.2.7",
"@types/node": "^10.14.6",

14
docs/build/macos.md vendored
View file

@ -1,13 +1,15 @@
# Setup your Keyman build environment on macOS
This document describes prerequisites and tools required for building various Keyman projects on macOS. Each project will also have additional notes linked below.
## Target Projects
On macOS, you can build the following projects:
* Keyman for Android
* Keyman for iOS
* Keyman for macOS
* KeymanWeb
* Keyman for Android ([additional details](../../android/README.md))
* Keyman for iOS ([additional details](../../ios/README.md))
* Keyman for macOS ([additional details](../../mac/README.md))
* KeymanWeb ([additional details](../../web/README.md))
The following libraries can also be built:
@ -24,11 +26,13 @@ The following projects **cannot** be built on macOS:
* Minimum macOS version: macOS Catalina 10.15 or Big Sur 11.0
**Note:** to make a fully M1-compatible release build of Keyman for macOS (for the setup Applescript), Big Sur 11.0 is required, as osacompile on earlier versions does not build for arm64 (M1). The build will still work on earlier versions, but the installer won't be able to run on M1 Macs that do not have Rosetta 2 installed.
## Prerequisites
Many dependencies are only required for specific projects.
* XCode (iOS, macOS)
* XCode (iOS, macOS) 12.4 or later
* Install from App Store
* Accept the Xcode license: `sudo xcodebuild -license accept`

View file

@ -485,6 +485,9 @@
CEDFEF8E23FE43B700BECF39 /* MigrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MigrationTests.swift; sourceTree = "<group>"; };
CEE0321024C56735005BFC73 /* Packages.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Packages.swift; sourceTree = "<group>"; };
CEE0321224C58C90005BFC73 /* KeymanHosts.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeymanHosts.swift; sourceTree = "<group>"; };
CEEC467526F2F5EE009A5B7D /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/ResourceInfoView.strings"; sourceTree = "<group>"; };
CEEC467D26F2F76E009A5B7D /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = "<group>"; };
CEEC467E26F2F777009A5B7D /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.stringsdict"; sourceTree = "<group>"; };
CEEF81AD2672FBE900EE6A07 /* es-419 */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-419"; path = "es-419.lproj/ResourceInfoView.strings"; sourceTree = "<group>"; };
CEEF81B72673016900EE6A07 /* es-419 */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-419"; path = "es-419.lproj/Localizable.strings"; sourceTree = "<group>"; };
CEEF81B82673016E00EE6A07 /* es-419 */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "es-419"; path = "es-419.lproj/Localizable.stringsdict"; sourceTree = "<group>"; };
@ -1167,6 +1170,7 @@
az,
am,
"es-419",
"zh-Hans",
);
mainGroup = F243887314BBD43000A3E055;
productRefGroup = F243887F14BBD43000A3E055 /* Products */;
@ -1551,6 +1555,7 @@
CE72B3D22643AB60006821CE /* az */,
CEBD34552655117800EB2EA8 /* am */,
CEEF81B82673016E00EE6A07 /* es-419 */,
CEEC467E26F2F777009A5B7D /* zh-Hans */,
);
name = Localizable.stringsdict;
sourceTree = "<group>";
@ -1566,6 +1571,7 @@
CE72B3D32643AB65006821CE /* az */,
CEBD34542655117400EB2EA8 /* am */,
CEEF81B72673016900EE6A07 /* es-419 */,
CEEC467D26F2F76E009A5B7D /* zh-Hans */,
);
name = Localizable.strings;
sourceTree = "<group>";
@ -1582,6 +1588,7 @@
CE72B3D12643AA9D006821CE /* az */,
CEBD34532655115800EB2EA8 /* am */,
CEEF81AD2672FBE900EE6A07 /* es-419 */,
CEEC467526F2F5EE009A5B7D /* zh-Hans */,
);
name = ResourceInfoView.xib;
sourceTree = "<group>";

View file

@ -14,7 +14,7 @@ public class KeyboardKeymanPackage : TypedKeymanPackage<InstallableKeyboard> {
override internal init(metadata: KMPMetadata, folder: URL) {
super.init(metadata: metadata, folder: folder)
self.keyboards = []
if let packagedKeyboards = metadata.keyboards {
for keyboard in packagedKeyboards {
keyboard.packageId = self.id
@ -22,7 +22,7 @@ public class KeyboardKeymanPackage : TypedKeymanPackage<InstallableKeyboard> {
if(keyboard.isValid && FileManager.default.fileExists(atPath: self.sourceFolder.appendingPathComponent("\(keyboard.keyboardId).js").path)) {
keyboards.append(keyboard)
} else {
log.debug("\(keyboard.name) not valid / corresponding file not found")
SentryManager.breadcrumbAndLog("\(keyboard.name) not valid / corresponding file not found")
}
}
}

View file

@ -16,6 +16,8 @@ public enum KMPError : String, Error {
case invalidPackage = "kmp-error-invalid"
case fileSystem = "kmp-error-file-system"
case copyFiles = "kmp-error-file-copying"
case unsupportedPackage = "kmp-error-unsupported"
case doesNotExist = "kmp-error-missing"
// TODO: Consider changing the parent type so that these may take arguments that may be used
// to provide better clarity.
case wrongPackageType = "kmp-error-wrong-type"
@ -380,35 +382,37 @@ public class KeymanPackage {
* Typecast the return value to either KeyboardKeymanPackage or LexicalModelKeymanPackage for richly-typed
* information about the package's contents.
*/
static public func parse(_ folder: URL) -> KeymanPackage? {
do {
var path = folder
path.appendPathComponent(kmpFile)
if FileManager.default.fileExists(atPath: path.path) {
let data = try Data(contentsOf: path, options: .mappedIfSafe)
let decoder = JSONDecoder()
static public func parse(_ folder: URL) throws -> KeymanPackage? {
var path = folder
path.appendPathComponent(kmpFile)
if FileManager.default.fileExists(atPath: path.path) {
let data = try Data(contentsOf: path, options: .mappedIfSafe)
let decoder = JSONDecoder()
var metadata: KMPMetadata
var metadata: KMPMetadata
do {
metadata = try decoder.decode(KMPMetadata.self, from: data)
} catch {
throw KMPError.noMetadata
}
switch metadata.packageType {
case .Keyboard:
return KeyboardKeymanPackage(metadata: metadata, folder: folder)
case .LexicalModel:
return LexicalModelKeymanPackage(metadata: metadata, folder: folder)
default:
throw KMPError.invalidPackage
}
do {
metadata = try decoder.decode(KMPMetadata.self, from: data)
} catch {
throw KMPError.noMetadata
}
var package: KeymanPackage
switch metadata.packageType {
case .Keyboard:
package = KeyboardKeymanPackage(metadata: metadata, folder: folder)
case .LexicalModel:
package = LexicalModelKeymanPackage(metadata: metadata, folder: folder)
default:
throw KMPError.invalidPackage
}
if package.resources.count == 0 {
throw KMPError.unsupportedPackage
} else {
return package
}
} catch {
// It's not an app or engine error when the package itself is invalid.
// Definitely worth noting, though.
SentryManager.breadcrumbAndLog("error parsing keyman package: \(error)", sentryLevel: .error)
}
return nil
@ -417,13 +421,19 @@ public class KeymanPackage {
@available(*, deprecated, message: "Use of the completion block is unnecessary; this method now returns synchronously.")
static public func extract(fileUrl: URL, destination: URL, complete: @escaping (KeymanPackage?) -> Void) throws {
try unzipFile(fileUrl: fileUrl, destination: destination) {
complete(KeymanPackage.parse(destination))
do {
let package = try KeymanPackage.parse(destination)
complete(package)
} catch {
SentryManager.captureAndLog(error, sentryLevel: .info)
complete(nil)
}
}
}
static public func extract(fileUrl: URL, destination: URL) throws -> KeymanPackage? {
try unzipFile(fileUrl: fileUrl, destination: destination)
return KeymanPackage.parse(destination)
return try KeymanPackage.parse(destination)
}
static public func unzipFile(fileUrl: URL, destination: URL, complete: @escaping () -> Void = {}) throws {

View file

@ -24,7 +24,7 @@ public class LexicalModelKeymanPackage : TypedKeymanPackage<InstallableLexicalMo
if(model.isValid && FileManager.default.fileExists(atPath: self.sourceFolder.appendingPathComponent("\(model.lexicalModelId).model.js").path)) {
models.append(model)
} else {
log.debug("\(model.name) not valid / corresponding file not found")
SentryManager.breadcrumbAndLog("\(model.name) not valid / corresponding file not found")
}
}
}

View file

@ -625,7 +625,7 @@ public class Manager: NSObject, UIGestureRecognizerDelegate {
// MARK: - Adhoc keyboards
public func parseKbdKMP(_ folder: URL, isCustom: Bool) throws -> Void {
guard let kmp = KeymanPackage.parse(folder) as? KeyboardKeymanPackage else {
guard let kmp = try? KeymanPackage.parse(folder) as? KeyboardKeymanPackage else {
throw KMPError.wrongPackageType
}
@ -640,7 +640,7 @@ public class Manager: NSObject, UIGestureRecognizerDelegate {
// MARK: - Adhoc lexical models
static public func parseLMKMP(_ folder: URL, isCustom: Bool) throws -> Void {
guard let kmp = KeymanPackage.parse(folder) as? LexicalModelKeymanPackage else {
guard let kmp = try? KeymanPackage.parse(folder) as? LexicalModelKeymanPackage else {
throw KMPError.wrongPackageType
}

View file

@ -54,7 +54,7 @@ public class ResourceFileManager {
var backingPackages: [KeymanPackage] = []
for resource in userResources {
if let package = KeymanPackage.parse(Storage.active.resourceDir(for: resource)!) {
if let package = try? KeymanPackage.parse(Storage.active.resourceDir(for: resource)!) {
// On successful parse, just ensure that we haven't already listed the package.
if !backingPackages.contains(where: { $0.id == package.id }) {
backingPackages.append(package)
@ -86,14 +86,14 @@ public class ResourceFileManager {
public func getInstalledPackage<Resource: LanguageResource>(for resource: Resource) -> Resource.Package? {
if let packageDir = Storage.active.resourceDir(for: resource) {
return KeymanPackage.parse(packageDir) as? Resource.Package
return try? KeymanPackage.parse(packageDir) as? Resource.Package
} else {
return nil
}
}
public func getInstalledPackage(withKey key: KeymanPackage.Key) -> KeymanPackage? {
return KeymanPackage.parse(Storage.active.packageDir(forKey: key))
return try? KeymanPackage.parse(Storage.active.packageDir(forKey: key))
}
internal func packageDownloadTempPath(forKey key: KeymanPackage.Key) -> URL {
@ -183,10 +183,14 @@ public class ResourceFileManager {
var extractionFolder = cacheDirectory
extractionFolder.appendPathComponent("temp/\(archiveUrl.lastPathComponent)")
if let kmp = try KeymanPackage.extract(fileUrl: archiveUrl, destination: extractionFolder) {
return kmp
} else {
throw KMPError.invalidPackage
do {
if let package = try KeymanPackage.extract(fileUrl: archiveUrl, destination: extractionFolder) {
return package
} else {
throw KMPError.doesNotExist
}
} catch {
throw error
}
}

View file

@ -0,0 +1,2 @@
/* Class = "UILabel"; text = "Scan this code to load this keyboard on another device"; ObjectID = "z2O-MT-IoV"; */
"z2O-MT-IoV.text" = "Dyssal code da ley dassasanal keyboard faoug shu'ul gadey";

View file

@ -0,0 +1,2 @@
/* Class = "UILabel"; text = "Scan this code to load this keyboard on another device"; ObjectID = "z2O-MT-IoV"; */
"z2O-MT-IoV.text" = "扫描此代码以在另一台设备上加载此键盘";

View file

@ -49,6 +49,12 @@
/* Confirmation text to display before uninstalling a lexical model */
"command-uninstall-lexical-model-confirm" = "ይህንን መዝገበ ቃላት ልታጠፋው ትፈልጋለህ?";
/* Text for error when a keyboard cannot load properly */
"error-loading-keyboard" = "የተጠየቀው የፊደል ገበታ ሰሌዳውን ሊጫን አልተቻለም";
/* Text for error when a lexical model cannot load properly */
"error-loading-lexical-model" = "የተጠየቀው ዲክሽናሪ ሊጫን አልተቻለም";
/* Text for error when an installed file is unexpectedly missing */
"error-missing-file" = "የእርዳታ ሰነዱን ማግኘት አልተቻለም።";
@ -181,6 +187,36 @@
/* Title for the main Settings menu */
"menu-settings-title" = "የኪይማን ቅንብሮች";
/* Secondary text showing current setting for spacebar caption - blank */
"menu-settings-spacebar-hint-blank" = "የስፔስባሩ መግለጫ ጽሁፍ አታሳይ";
/* Secondary text showing current setting for spacebar caption - keyboard */
"menu-settings-spacebar-hint-keyboard" = "የፊደል ገበታ ሰሌዳውን ስም በስፔስ ባሩ ላይ አሳይ";
/* Secondary text showing current setting for spacebar caption - language */
"menu-settings-spacebar-hint-language" = "የቋንቋውን ስም በስፔስ ባሩ ላይ አሳይ";
/* Secondary text showing current setting for spacebar caption - language + keyboard */
"menu-settings-spacebar-hint-languageKeyboard" = "ቋንቋና የፊደል ገበታውን በስፔስ ባሩ ላይ";
/* Label for the "Spacebar Caption" item on the main settings screen */
"menu-settings-spacebar-text" = "የስፔስባሩ መግለጫ ጽሁፍ";
/* Title for the "Spacebar Caption" settings screen */
"menu-settings-spacebar-title" = "የስፔስባሩ መግለጫ ጽሁፍ";
/* Text showing name of spacebar caption - blank */
"menu-settings-spacebar-item-blank" = "ባዶ";
/* Text showing name of spacebar caption - keyboard */
"menu-settings-spacebar-item-keyboard" = "የፊደል ገበታ ሰሌዳ";
/* Text showing name of spacebar caption - language */
"menu-settings-spacebar-item-language" = "ቋንቋ";
/* Text showing name of spacebar caption - language + keyboard */
"menu-settings-spacebar-item-languageKeyboard" = "ቋንቋና የፊደል ገበታ";
/* Short text for notification: download failure for keyboard */
"notification-download-failure-keyboard" = "የፊደል ገበታ ሰሌዳ መውረድ አልቻለም";

View file

@ -118,12 +118,18 @@
/* Error opening a Keyman package - package is not valid */
"kmp-error-invalid" = "The package's file is corrupted.";
/* Error opening a Keyman package - it does not exist / the specified location is wrong */
"kmp-error-missing" = "The specified package does not exist.";
/* Error installing a Keyman package - expected resource (keyboard or dictionary) is missing */
"kmp-error-missing-resource" = "This package does not contain the requested keyboard or dictionary.";
/* Error opening a Keyman package - cannot parse contents */
"kmp-error-no-metadata" = "This package was not properly built - contents unknown.";
/* Error opening a Keyman package - package's contents are for desktop platforms only */
"kmp-error-unsupported" = "This package does not include support for your device.";
/* Error opening a Keyman package - package contains unexpected resource (keyboard or dictionary) type */
"kmp-error-wrong-type" = "This package does not contain the expected resource type.";

View file

@ -0,0 +1,248 @@
/* A descriptive message used for errors when the app is already busy downloading */
"alert-download-error-busy" = "Matakula bidis fiya.";
/* A descriptive message used when a download fails */
"alert-download-error-detail" = "Ligi mashakil waqat dassasana walla badiyana.";
/* Title for a "download failed" alert */
"alert-download-error-title" = "Ma gudur dassa";
/* Title for a general alert about errors */
"alert-error-title" = "Mushkila";
/* A descriptive message used when no internet connection is detected */
"alert-no-connection-detail" = "Ma gudur ligi bikan Keyman. Albarak hawul addarey.";
/* Title for a "no connection" alert */
"alert-no-connection-title" = "Internet maknus";
/* Short text for a 'back' navigational command. Used to return to the previous screen */
"command-back" = "Wara";
/* Short text for a 'cancel' command. Used to back out of a menu or install process without making changes */
"command-cancel" = "Halla";
/* Short text for a 'done' command. Used to back out of settings menus after changes have been made */
"command-done" = "Tamma";
/* Short text for an 'install' command. Used to confirm installation of a package. */
"command-install" = "Dyssa";
/* Short text for a 'next' navigational command. Used to advance to the next screen */
"command-next" = "Giddam";
/* Short text for an 'OK' command. Used for some error alerts */
"command-ok" = "Zayn";
/* Short text for confirmining 'uninstall' commands. */
"command-uninstall" = "Sulla";
/* Text for the command to uninstall a keyboard */
"command-uninstall-keyboard" = "Sulal keyboard";
/* Confirmation text to display before uninstalling a keyboard */
"command-uninstall-keyboard-confirm" = "Tador tasulal keyboard wah?";
/* Text for the command to uninstall a lexical model */
"command-uninstall-lexical-model" = "Sulal kakkad hana kalimat";
/* Confirmation text to display before uninstalling a lexical model */
"command-uninstall-lexical-model-confirm" = "Tador tasulal kakkad hanal kalimat wah?";
/* Text for error when a keyboard cannot load properly */
"error-loading-keyboard" = "Ma gudur dassa keyboard alsa'alta";
/* Text for error when a lexical model cannot load properly */
"error-loading-lexical-model" = "Ma gudur dassa kakkad hana kalimat alsa'alta";
/* Text for error when an installed file is unexpectedly missing */
"error-missing-file" = "Alshu'ul altadora mal laga.";
/* Text for error when an installed file is unexpectedly missing */
"error-missing-file-critical" = "Shu'ul muhim alwaddar. Albarak hawul dassasanal shu'ul gadey kula.";
/* Text for errors in data received from search queries */
"error-query-decoding" = "Albikan albidussu da dugut einda mashakil shiye";
/* A descriptive message used when a download fails */
"error-query-general" = "Mashakil kalam layl bikan albidussul shu'ul";
/* Text for error when a search query is unexpectedly empty */
"error-query-no-data" = "Al server ma bikhadum";
/* Text for general errors where not much information is known */
"error-unknown" = "Mashakil almana ashimanina allaga";
/* Text for error when updating a resource: cannot download because no source is available */
"error-update-no-link" = "Mafi shu'ul ley dassasal shu'ul judad fi da";
/* Text for error when updating a resource: Keyman does not know how to update the resource */
"error-update-not-managed" = "Ma biddar bidis shu'ul judad ley engine almi hana Keyman";
/* Text for the command to open the help page of a keyboard, as shown on resource information views */
"info-command-help-keyboard" = "Mi'awana faougal Keyboard";
/* Text for the command to open the help page of a lexical model, as shown on resource information views */
"info-command-help-lexical-model" = "Mi'awana faougal kakkad hanal kalimat";
/* Text label for displaying a keyboard's version, as shown on resource information views */
"info-label-version-keyboard" = "Nafaral keyboard";
/* Text label for displaying a lexical model's version, as shown on resource information views */
"info-label-version-lexical-model" = "Nafaral kakkad hana kalimat";
/* Label used for the "package info" / readme tab with the package installation prompt on phones. */
"installer-label-package-info" = "Khabar faoug shabal shu'ul da";
/* Label used for the language-selection tab with the package installation prompt on phones. */
"installer-label-select-languages" = "Azzul lugga";
/* Label used with a package's version, as seen within the package installation prompt. Example: "Version: 14.0.0" */
"installer-label-version" = "Nafar: %@";
/* Section header for languages supported by a package, as seen within the package installation prompt */
"installer-section-available-languages" = "Luggat alfi";
/* Text for the help popup for changing keyboards with the globe key */
"keyboard-help-change" = "Assural bikan da ley badalanal keybaord";
/* Text for the command to exit the Keyman keyboard in favor of other keyboards installed on the system */
"keyboard-menu-exit" = "Sidda %@";
/* Error installing a Keyman package - could not allocate a location to install it */
"kmp-error-file-system" = "Mushkila fi dassasana - alshu'ul einda mushkila";
/* Error installing a Keyman package - could not copy package files */
"kmp-error-file-copying" = "Mushkila fi dassasana - ma gudur shal shu'ul albidora";
/* Error opening a Keyman package - package is not valid */
"kmp-error-invalid" = "Alshu'ul maknus.";
/* Error installing a Keyman package - expected resource (keyboard or dictionary) is missing */
"kmp-error-missing-resource" = "Alshu'ul da ma leya gudura layl keyboard walla kakkad hanal kalimat da.";
/* Error opening a Keyman package - cannot parse contents */
"kmp-error-no-metadata" = "Ma sawwol shu'ul da zayn - shu'ul alfiya ma mil'araf.";
/* Error opening a Keyman package - package contains unexpected resource (keyboard or dictionary) type */
"kmp-error-wrong-type" = "Alshu'ul da ma leya shu'ul albinadawar minna.";
/* Title for the Installed Languages menu */
"menu-installed-languages-title" = "Luggat aldasso";
/* Section header for lexical models within a language-specific settings menu */
"menu-langsettings-label-lexical-models" = "Kakkad hana kalimat";
/* Section header for keyboards within a language-specific settings menu */
"menu-langsettings-section-keyboards" = "Keyboards";
/* Section header for the settings toggles within a language-specific settings menu */
"menu-langsettings-section-settings" = "Miwasa hanal Lugga";
/* Title for the language-specific settings menus */
"menu-langsettings-title" = "%@ Miwasa";
/* Label for the toggle that enables corrections that is displayed within a language-specific settings menu */
"menu-langsettings-toggle-correct" = "Dys ta'adil";
/* Label for the toggle that enables predictions that is displayed within a language-specific settings menu */
"menu-langsettings-toggle-predict" = "Dys zan";
/* Help message for a prompt that appears for confirming a lexical model download: language (1): lexical model (dictionary) name (2) */
"menu-lexical-model-install-message" = "Tador tadis kakkad hanal kalimat wah?";
/* Title for a prompt that appears for confirming a lexical model download: language (1): lexical model (dictionary) name (2) */
"menu-lexical-model-install-title" = "%1$@: %2$@";
/* Text for an info alert indicating that no lexical models are available */
"menu-lexical-model-none-message" = "Mafi kakkad hana kalimat";
/* Title for the lexical model menu, a submenu of the language-specific settings menus */
"menu-lexical-model-title" = "%@ Kakkad hana kalimat";
/* Title for the keyboard picker */
"menu-picker-title" = "Keyboards";
/* Primary text for the Settings menu option to report keyboard crashes */
"menu-settings-error-report" = "Assud ley gaddaran mashakil";
/* Secondary text for the Settings menu option to report keyboard crashes */
"menu-settings-error-report-description" = "Bidor 'izin kamil' leya";
/* Primary text for the Settings menu local-file package installation option */
"menu-settings-install-from-file" = "Dyssa min shu'ul";
/* Secondary text for the Settings menu local-file package installation option */
"menu-settings-install-from-file-description" = "Fattisha minal shu'ul da .kmp";
/* Primary text for the Settings menu option that displays the iOS system menu options for the app's keyboard */
"menu-settings-system-keyboard-menu" = "Miwasa hanal keyboard hanal komfita";
/* Label for the "Show Banner" toggle on the main settings screen */
"menu-settings-show-banner" = "Waaral Banner";
/* Label for the "Get Started" automatic display toggle seen in the Settings menu */
"menu-settings-startup-get-started" = "War 'Abda' min bidaya hana bas";
/* Title for the main Settings menu */
"menu-settings-title" = "Miwasa hana Keyman";
/* Secondary text showing current setting for spacebar caption - blank */
"menu-settings-spacebar-hint-blank" = "Ya eiwari shaykula faougal spacebar";
/* Secondary text showing current setting for spacebar caption - keyboard */
"menu-settings-spacebar-hint-keyboard" = "Waar usumal keyboard faougal spacebar";
/* Secondary text showing current setting for spacebar caption - language */
"menu-settings-spacebar-hint-language" = "Waar usumal lugga faougal spacebar";
/* Secondary text showing current setting for spacebar caption - language + keyboard */
"menu-settings-spacebar-hint-languageKeyboard" = "Usumal lugga bey keyboard faougal spacebar";
/* Label for the "Spacebar Caption" item on the main settings screen */
"menu-settings-spacebar-text" = "Shu'ul baynatum";
/* Title for the "Spacebar Caption" settings screen */
"menu-settings-spacebar-title" = "Shu'ul baynatum";
/* Text showing name of spacebar caption - blank */
"menu-settings-spacebar-item-blank" = "Mafi shai";
/* Text showing name of spacebar caption - keyboard */
"menu-settings-spacebar-item-keyboard" = "Keyboard";
/* Text showing name of spacebar caption - language */
"menu-settings-spacebar-item-language" = "Lugga";
/* Text showing name of spacebar caption - language + keyboard */
"menu-settings-spacebar-item-languageKeyboard" = "Lugga wa Keyboard";
/* Short text for notification: download failure for keyboard */
"notification-download-failure-keyboard" = "Ma gudur dassal Keyboard";
/* Short text for notification: download failure for lexical model */
"notification-download-failure-lexical-model" = "Ma gudur dassa kakkad hanal kalimat";
/* Short text for notification: download success for keyboard */
"notification-download-success-keyboard" = "Gudur dassal Keyboard zayn";
/* Short text for notification: download success for lexical model */
"notification-download-success-lexical-model" = "Nafar hanal Lexica dakhal nadif";
/* Short text for notification: downloading a keyboard */
"notification-downloading-keyboard" = "Dyssal keyboard min \U2026";
/* Short text for notification: downloading a lexical model */
"notification-downloading-lexical-model" = "Dyssal kakkad hanal kalimat \U2026";
/* Short text for notification: an update is available */
"notification-update-available" = "Shu'ul jadid fi";
/* Short text for notification: currently updating */
"notification-update-processing" = "Dassasanal shu'ul aljadid\U2026";
/* Text indicating success at installing new keyboards or dictionaries */
"success-install" = "Dakhal zayn.";
/* A title to use in alerts indicating 'success' at whatever task the user requested */
"success-title" = "Mubarak";

View file

@ -0,0 +1,146 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>menu-langsettings-lexical-model-count</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@count@</string>
<key>count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>u</string>
<key>one</key>
<string>%u kakkad hana kalimat dakhal</string>
<key>two</key>
<string>%u kakkad hana kalimat dakhal</string>
<key>few</key>
<string>%u kakkad hana kalimat dakhal</string>
<key>other</key>
<string>%u kakkad hana kalimat dakhal</string>
</dict>
</dict>
<key>notification-update-failed</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@count@</string>
<key>count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>u</string>
<key>one</key>
<string>%u Dassasan judad ma kan</string>
<key>two</key>
<string>%u Dassasan judad ma kan</string>
<key>few</key>
<string>%u Dassasan judad ma kan</string>
<key>other</key>
<string>%u Dassasan judad ma kan</string>
</dict>
</dict>
<key>notification-update-success</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@count@</string>
<key>count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>u</string>
<key>one</key>
<string>%u Dassasan judad kan</string>
<key>two</key>
<string>%u Dassasan judad kan</string>
<key>few</key>
<string>%u Dassasan judad kan</string>
<key>other</key>
<string>%u Dassasan judad kan</string>
</dict>
</dict>
<key>settings-keyboards-installed-count</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@count@</string>
<key>count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>u</string>
<key>one</key>
<string>%u keyboard dakhal</string>
<key>two</key>
<string>%u keyboard dakhal</string>
<key>few</key>
<string>%u keyboard dakhal</string>
<key>other</key>
<string>%u keyboards dakhal</string>
</dict>
</dict>
<key>settings-languages-installed-count</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@count@</string>
<key>count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>u</string>
<key>one</key>
<string>%u lugga dakhal</string>
<key>two</key>
<string>%u lugga dakhal</string>
<key>few</key>
<string>%u lugga dakhal</string>
<key>other</key>
<string>%u luggat dakhalo</string>
</dict>
</dict>
<key>package-default-found-keyboards</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@count@</string>
<key>count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>u</string>
<key>one</key>
<string>Ligo %u keyboard fyl package:</string>
<key>two</key>
<string>Ligo %u keyboard fyl package:</string>
<key>few</key>
<string>Ligo %u keyboard fyl package:</string>
<key>other</key>
<string>Ligo %u keyboards fyl package:</string>
</dict>
</dict>
<key>package-default-found-lexical-models</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@count@</string>
<key>count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>u</string>
<key>one</key>
<string>Ligo %u kakkad hana kalimat fyl package:</string>
<key>two</key>
<string>Ligo %u kakkad hana kalimat fyl package:</string>
<key>few</key>
<string>Ligo %u kakkad hana kalimat fyl package:</string>
<key>other</key>
<string>Ligo %u kakkad hana kalimat fyl package:</string>
</dict>
</dict>
</dict>
</plist>

View file

@ -0,0 +1,248 @@
/* A descriptive message used for errors when the app is already busy downloading */
"alert-download-error-busy" = "已经在忙着下载。";
/* A descriptive message used when a download fails */
"alert-download-error-detail" = "下载或安装过程中发生错误。";
/* Title for a "download failed" alert */
"alert-download-error-title" = "下载错误";
/* Title for a general alert about errors */
"alert-error-title" = "错误";
/* A descriptive message used when no internet connection is detected */
"alert-no-connection-detail" = "无法连接到Keyman服务器。请稍后再试。";
/* Title for a "no connection" alert */
"alert-no-connection-title" = "连接错误";
/* Short text for a 'back' navigational command. Used to return to the previous screen */
"command-back" = "返回";
/* Short text for a 'cancel' command. Used to back out of a menu or install process without making changes */
"command-cancel" = "取消";
/* Short text for a 'done' command. Used to back out of settings menus after changes have been made */
"command-done" = "完成";
/* Short text for an 'install' command. Used to confirm installation of a package. */
"command-install" = "安装";
/* Short text for a 'next' navigational command. Used to advance to the next screen */
"command-next" = "下一个";
/* Short text for an 'OK' command. Used for some error alerts */
"command-ok" = "确定";
/* Short text for confirmining 'uninstall' commands. */
"command-uninstall" = "卸载";
/* Text for the command to uninstall a keyboard */
"command-uninstall-keyboard" = "卸载键盘";
/* Confirmation text to display before uninstalling a keyboard */
"command-uninstall-keyboard-confirm" = "您想卸载此键盘吗?";
/* Text for the command to uninstall a lexical model */
"command-uninstall-lexical-model" = "卸载字典";
/* Confirmation text to display before uninstalling a lexical model */
"command-uninstall-lexical-model-confirm" = "你想要卸载这个字典吗?";
/* Text for error when a keyboard cannot load properly */
"error-loading-keyboard" = "Unable to load the requested keyboard";
/* Text for error when a lexical model cannot load properly */
"error-loading-lexical-model" = "Unable to load the requested dictionary";
/* Text for error when an installed file is unexpectedly missing */
"error-missing-file" = "找不到必需文件。";
/* Text for error when an installed file is unexpectedly missing */
"error-missing-file-critical" = "找不到关键文件。请尝试重新安装应用程序。";
/* Text for errors in data received from search queries */
"error-query-decoding" = "服务器目前遇到技术问题";
/* A descriptive message used when a download fails */
"error-query-general" = "与服务器通信出错";
/* Text for error when a search query is unexpectedly empty */
"error-query-no-data" = "服务器响应失败";
/* Text for general errors where not much information is known */
"error-unknown" = "发生意外错误";
/* Text for error when updating a resource: cannot download because no source is available */
"error-update-no-link" = "此软件包没有可用的更新源";
/* Text for error when updating a resource: Keyman does not know how to update the resource */
"error-update-not-managed" = "无法更新由Keyman引擎管理的资源";
/* Text for the command to open the help page of a keyboard, as shown on resource information views */
"info-command-help-keyboard" = "键盘帮助";
/* Text for the command to open the help page of a lexical model, as shown on resource information views */
"info-command-help-lexical-model" = "字典帮助";
/* Text label for displaying a keyboard's version, as shown on resource information views */
"info-label-version-keyboard" = "键盘版本";
/* Text label for displaying a lexical model's version, as shown on resource information views */
"info-label-version-lexical-model" = "字典版本";
/* Label used for the "package info" / readme tab with the package installation prompt on phones. */
"installer-label-package-info" = "软件包信息";
/* Label used for the language-selection tab with the package installation prompt on phones. */
"installer-label-select-languages" = "选择语言";
/* Label used with a package's version, as seen within the package installation prompt. Example: "Version: 14.0.0" */
"installer-label-version" = "版本: %@";
/* Section header for languages supported by a package, as seen within the package installation prompt */
"installer-section-available-languages" = "可用语言";
/* Text for the help popup for changing keyboards with the globe key */
"keyboard-help-change" = "点击此处更改键盘";
/* Text for the command to exit the Keyman keyboard in favor of other keyboards installed on the system */
"keyboard-menu-exit" = "关闭 %@";
/* Error installing a Keyman package - could not allocate a location to install it */
"kmp-error-file-system" = "安装软件包时发生错误 - 文件系统错误";
/* Error installing a Keyman package - could not copy package files */
"kmp-error-file-copying" = "安装软件包时发生错误 - 无法复制所需文件";
/* Error opening a Keyman package - package is not valid */
"kmp-error-invalid" = "安装包的文件已被损坏。";
/* Error installing a Keyman package - expected resource (keyboard or dictionary) is missing */
"kmp-error-missing-resource" = "此软件包不包含要求的键盘或字典。";
/* Error opening a Keyman package - cannot parse contents */
"kmp-error-no-metadata" = "此软件包未被正确构建-内容未知。";
/* Error opening a Keyman package - package contains unexpected resource (keyboard or dictionary) type */
"kmp-error-wrong-type" = "此软件包不包含预期的资源类型。";
/* Title for the Installed Languages menu */
"menu-installed-languages-title" = "已安装的语言";
/* Section header for lexical models within a language-specific settings menu */
"menu-langsettings-label-lexical-models" = "字典";
/* Section header for keyboards within a language-specific settings menu */
"menu-langsettings-section-keyboards" = "键盘";
/* Section header for the settings toggles within a language-specific settings menu */
"menu-langsettings-section-settings" = "语言设置";
/* Title for the language-specific settings menus */
"menu-langsettings-title" = "%@ 设置";
/* Label for the toggle that enables corrections that is displayed within a language-specific settings menu */
"menu-langsettings-toggle-correct" = "启用校正";
/* Label for the toggle that enables predictions that is displayed within a language-specific settings menu */
"menu-langsettings-toggle-predict" = "启用预测";
/* Help message for a prompt that appears for confirming a lexical model download: language (1): lexical model (dictionary) name (2) */
"menu-lexical-model-install-message" = "您想要安装这个字典吗?";
/* Title for a prompt that appears for confirming a lexical model download: language (1): lexical model (dictionary) name (2) */
"menu-lexical-model-install-title" = "%1$@: %2$@";
/* Text for an info alert indicating that no lexical models are available */
"menu-lexical-model-none-message" = "没有可用的字典";
/* Title for the lexical model menu, a submenu of the language-specific settings menus */
"menu-lexical-model-title" = "%@ 字典";
/* Title for the keyboard picker */
"menu-picker-title" = "键盘";
/* Primary text for the Settings menu option to report keyboard crashes */
"menu-settings-error-report" = "允许错误报告";
/* Secondary text for the Settings menu option to report keyboard crashes */
"menu-settings-error-report-description" = "可能需要“完全访问”";
/* Primary text for the Settings menu local-file package installation option */
"menu-settings-install-from-file" = "从文件安装";
/* Secondary text for the Settings menu local-file package installation option */
"menu-settings-install-from-file-description" = "浏览 .kmp 文件";
/* Primary text for the Settings menu option that displays the iOS system menu options for the app's keyboard */
"menu-settings-system-keyboard-menu" = "系统键盘设置";
/* Label for the "Show Banner" toggle on the main settings screen */
"menu-settings-show-banner" = "显示横幅";
/* Label for the "Get Started" automatic display toggle seen in the Settings menu */
"menu-settings-startup-get-started" = "启动时显示 '开始'";
/* Title for the main Settings menu */
"menu-settings-title" = "Keyman 设置";
/* Secondary text showing current setting for spacebar caption - blank */
"menu-settings-spacebar-hint-blank" = "Do not show caption on spacebar";
/* Secondary text showing current setting for spacebar caption - keyboard */
"menu-settings-spacebar-hint-keyboard" = "Show keyboard name on spacebar";
/* Secondary text showing current setting for spacebar caption - language */
"menu-settings-spacebar-hint-language" = "Show language name on spacebar";
/* Secondary text showing current setting for spacebar caption - language + keyboard */
"menu-settings-spacebar-hint-languageKeyboard" = "Show language and keyboard name on spacebar";
/* Label for the "Spacebar Caption" item on the main settings screen */
"menu-settings-spacebar-text" = "Spacebar Caption";
/* Title for the "Spacebar Caption" settings screen */
"menu-settings-spacebar-title" = "Spacebar Caption";
/* Text showing name of spacebar caption - blank */
"menu-settings-spacebar-item-blank" = "Blank";
/* Text showing name of spacebar caption - keyboard */
"menu-settings-spacebar-item-keyboard" = "Keyboard";
/* Text showing name of spacebar caption - language */
"menu-settings-spacebar-item-language" = "Language";
/* Text showing name of spacebar caption - language + keyboard */
"menu-settings-spacebar-item-languageKeyboard" = "Language and keyboard";
/* Short text for notification: download failure for keyboard */
"notification-download-failure-keyboard" = "键盘下载失败";
/* Short text for notification: download failure for lexical model */
"notification-download-failure-lexical-model" = "字典下载失败";
/* Short text for notification: download success for keyboard */
"notification-download-success-keyboard" = "键盘下载成功";
/* Short text for notification: download success for lexical model */
"notification-download-success-lexical-model" = "Lexical 模型下载成功";
/* Short text for notification: downloading a keyboard */
"notification-downloading-keyboard" = "正在下载键盘\U2026";
/* Short text for notification: downloading a lexical model */
"notification-downloading-lexical-model" = "正在下载字典\U2026";
/* Short text for notification: an update is available */
"notification-update-available" = "有可用的更新";
/* Short text for notification: currently updating */
"notification-update-processing" = "正在更新\U2026";
/* Text indicating success at installing new keyboards or dictionaries */
"success-install" = "安装成功。";
/* A title to use in alerts indicating 'success' at whatever task the user requested */
"success-title" = "成功";

View file

@ -0,0 +1,104 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>menu-langsettings-lexical-model-count</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@count@</string>
<key>count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>u</string>
<key>other</key>
<string>已安装 %u 字典</string>
</dict>
</dict>
<key>notification-update-failed</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@count@</string>
<key>count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>u</string>
<key>other</key>
<string>%u 更新失败</string>
</dict>
</dict>
<key>notification-update-success</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@count@</string>
<key>count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>u</string>
<key>other</key>
<string>%u 次更新成功</string>
</dict>
</dict>
<key>settings-keyboards-installed-count</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@count@</string>
<key>count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>u</string>
<key>other</key>
<string>%u 个键盘已安装</string>
</dict>
</dict>
<key>settings-languages-installed-count</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@count@</string>
<key>count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>u</string>
<key>other</key>
<string>%u 种语言已安装</string>
</dict>
</dict>
<key>package-default-found-keyboards</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@count@</string>
<key>count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>u</string>
<key>other</key>
<string>在安装包中找到 %u 个键盘:</string>
</dict>
</dict>
<key>package-default-found-lexical-models</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@count@</string>
<key>count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>u</string>
<key>other</key>
<string>在安装包中找到 %u 个字典:</string>
</dict>
</dict>
</dict>
</plist>

View file

@ -335,6 +335,7 @@
CEBD34392654FEB400EB2EA8 /* XCGLogger.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = XCGLogger.xcframework; path = ../../Carthage/Build/XCGLogger.xcframework; sourceTree = "<absolute>"; };
CEBD343A2654FEB400EB2EA8 /* Zip.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = Zip.xcframework; path = ../../Carthage/Build/Zip.xcframework; sourceTree = "<absolute>"; };
CEBD3458265511B700EB2EA8 /* am */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = am; path = am.lproj/Localizable.strings; sourceTree = "<group>"; };
CEEC468226F2F7BA009A5B7D /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = "<group>"; };
CEEF81B92673019600EE6A07 /* es-419 */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-419"; path = "es-419.lproj/Localizable.strings"; sourceTree = "<group>"; };
CEF4E55523E95B7B0065B9C7 /* ImageBanner.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ImageBanner.xib; sourceTree = "<group>"; };
CEF4E55823E967140065B9C7 /* ImageBannerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageBannerViewController.swift; sourceTree = "<group>"; };
@ -780,6 +781,7 @@
az,
am,
"es-419",
"zh-Hans",
);
mainGroup = 98ABADA7176935E400B62590;
productRefGroup = 98ABADB1176935E400B62590 /* Products */;
@ -1078,6 +1080,7 @@
CE72B3D62643ABB7006821CE /* az */,
CEBD3458265511B700EB2EA8 /* am */,
CEEF81B92673019600EE6A07 /* es-419 */,
CEEC468226F2F7BA009A5B7D /* zh-Hans */,
);
name = Localizable.strings;
sourceTree = "<group>";

View file

@ -65,7 +65,15 @@ class PackageBrowserViewController: UIDocumentPickerViewController, UIDocumentPi
return
}
if let package = rfm.prepareKMPInstall(from: destinationUrl, alertHost: self) {
// The package browser view has usually self-dismissed at this point and cannot
// present error message alerts. We need to find something in the view
// hierarchy that can present the error.
var alertVC: UIViewController = self
if self.view.superview == nil && self.navVC != nil {
alertVC = self.navVC!
}
if let package = rfm.prepareKMPInstall(from: destinationUrl, alertHost: alertVC) {
// These type checks are necessary due to generic constraints.
if let kbdPackage = package as? KeyboardKeymanPackage {
doPrompt(for: kbdPackage, withAssociators: [.lexicalModels])

View file

@ -0,0 +1,81 @@
/* Title for the bookmarks menu within the embedded browser */
"browser-bookmarks-add-title" = "Dys bookmark";
/* Title for the bookmarks menu within the embedded browser */
"browser-bookmarks-none" = "Mafi bookmarks";
/* Title for the bookmarks menu within the embedded browser */
"browser-bookmarks-title" = "Bookmarks";
/* Used to confirm a user's desire to install a package */
"confirm-install" = "Dyssa";
/* The label for the toggle to stop automatically showing the "Get Started" tutorial popup. */
"disable-get-started" = "Ya eilwar gadey";
/* Indicates an error opening a web page requested by a user */
"error-opening-page" = "Ma biddar bi fukka";
/* Long-form used when installing a font in order to display a language properly. */
"font-install-description" = "Lammusa ley dassasan shu'ul %@ albinshaf chatta fi altannaf beya";
/* The name of the iOS Settings menu option for keyboards */
"ios-settings-keyboards" = "Keyboards";
/* The name of the iOS Settings menu option for giving the keyboard full access. (The menu entry
underneath the app's name within the app-specific keyboard menu.) */
"ios-settings-allow-full-access" = "Atha izin kamil";
/* Short-form used when installing a font in order to display a language properly. */
"language-for-font" = "%@ Shabal kutub";
/* Used for 'add' options within menus */
"menu-add" = "Zyd";
/* Used to indicate a sequence of menu options that a user needs to copy. May be chained. Example: "Keyboards (1) > Enable Keyman (2)" */
"menu-breadcrumbing" = "%1$@ > %2$@";
/* Used to exit a menu without choosing an option */
"menu-cancel" = "Halla";
/* Menu option that erases all previously-typed text. */
"menu-clear-text" = "Sulal katub";
/* Menu option that displays a list designed to help users start using the app */
"menu-get-started" = "Abda";
/* Menu option that displays help for the app */
"menu-help" = "Khabar";
/* Menu option that displays the main screen's drop-down menu */
"menu-more" = "Ziyada";
/* Menu option used to edit keyboard and dictionary settings */
"menu-settings" = "Miwasa";
/* Menu option that displays the iOS Share menu */
"menu-share" = "Gassama";
/* Menu option that displays an embedded web browser. */
"menu-show-browser" = "Browser";
/* Menu option used to control in-app font size. */
"menu-text-size" = "Kubural katub";
/* Used to describe the current font size */
"text-size-label" = "Kubural kutub: %i";
/* Text to indicate that a user should set a toggle within iOS Settings to 'active'. */
"toggle-to-enable" = "Dyssa %@";
/* First option on the Get Started tutorial - Add a keyboard for your language */
"tutorial-add-keyboard" = "Dys keyboard ley luggatak";
/* Third option on the Get Started tutorial - Displays app help. */
"tutorial-show-help" = "Ziyada hana khabar";
/* Second option on the Get Started tutorial - Set up Keyman as system-wide keyboard */
"tutorial-system-keyboard" = "Dys Keyman shaba system-wide keyboard";
/* Used to display app version (as in \"Version: 1.0.2\" */
"version-label" = "Nafar: %@";

View file

@ -0,0 +1,81 @@
/* Title for the bookmarks menu within the embedded browser */
"browser-bookmarks-add-title" = "添加书签";
/* Title for the bookmarks menu within the embedded browser */
"browser-bookmarks-none" = "没有书签";
/* Title for the bookmarks menu within the embedded browser */
"browser-bookmarks-title" = "书签";
/* Used to confirm a user's desire to install a package */
"confirm-install" = "安装";
/* The label for the toggle to stop automatically showing the "Get Started" tutorial popup. */
"disable-get-started" = "不再显示";
/* Indicates an error opening a web page requested by a user */
"error-opening-page" = "无法打开页面";
/* Long-form used when installing a font in order to display a language properly. */
"font-install-description" = "点击安装以在您的所有应用中正确显示 %@";
/* The name of the iOS Settings menu option for keyboards */
"ios-settings-keyboards" = "键盘";
/* The name of the iOS Settings menu option for giving the keyboard full access. (The menu entry
underneath the app's name within the app-specific keyboard menu.) */
"ios-settings-allow-full-access" = "允许完全访问权限";
/* Short-form used when installing a font in order to display a language properly. */
"language-for-font" = "%@ 字体";
/* Used for 'add' options within menus */
"menu-add" = "添加";
/* Used to indicate a sequence of menu options that a user needs to copy. May be chained. Example: "Keyboards (1) > Enable Keyman (2)" */
"menu-breadcrumbing" = "%1$@ > %2$@";
/* Used to exit a menu without choosing an option */
"menu-cancel" = "取消";
/* Menu option that erases all previously-typed text. */
"menu-clear-text" = "清除文本";
/* Menu option that displays a list designed to help users start using the app */
"menu-get-started" = "开始使用";
/* Menu option that displays help for the app */
"menu-help" = "信息";
/* Menu option that displays the main screen's drop-down menu */
"menu-more" = "更多";
/* Menu option used to edit keyboard and dictionary settings */
"menu-settings" = "设置";
/* Menu option that displays the iOS Share menu */
"menu-share" = "分享";
/* Menu option that displays an embedded web browser. */
"menu-show-browser" = "浏览器";
/* Menu option used to control in-app font size. */
"menu-text-size" = "文字大小";
/* Used to describe the current font size */
"text-size-label" = "文字大小: %i";
/* Text to indicate that a user should set a toggle within iOS Settings to 'active'. */
"toggle-to-enable" = "启用 %@";
/* First option on the Get Started tutorial - Add a keyboard for your language */
"tutorial-add-keyboard" = "为您的语言添加键盘";
/* Third option on the Get Started tutorial - Displays app help. */
"tutorial-show-help" = "更多信息";
/* Second option on the Get Started tutorial - Set up Keyman as system-wide keyboard */
"tutorial-system-keyboard" = "设置Keyman为全系统键盘";
/* Used to display app version (as in \"Version: 1.0.2\" */
"version-label" = "版本: %@";

View file

@ -20,5 +20,5 @@
"ts-node",
"typescript"
],
"version": "15.0.113"
"version": "15.0.125"
}

View file

@ -65,6 +65,15 @@ class InstallKmpWindow(Gtk.Dialog):
with tempfile.TemporaryDirectory() as tmpdirname:
extract_kmp(kmpfile, tmpdirname)
info, system, options, keyboards, files = get_metadata(tmpdirname)
if not keyboards:
# Likely not a keyboard .kmp file
logging.info("%s is not a Keyman keyboard package" % kmpfile)
dialog = Gtk.MessageDialog(viewkmp, 0, Gtk.MessageType.ERROR, Gtk.ButtonsType.OK,
_("The file '{kmpfile}' is not a Keyman keyboard package!").format(kmpfile=kmpfile))
dialog.run()
dialog.destroy()
self.checkcontinue = False
return
if len(keyboards) > 0 and 'name' in keyboards[0]:
self.kbname = keyboards[0]['name']
else:

View file

@ -107,7 +107,7 @@ class KeyboardDetailsView(Gtk.Dialog):
label.set_selectable(True)
grid.attach_next_to(label, lbl_pkg_vrs, Gtk.PositionType.RIGHT, 1, 1)
if kbdata:
if kbdata and kbdata.get('description'):
lbl_pkg_desc = Gtk.Label()
lbl_pkg_desc.set_text(_("Package description: "))
lbl_pkg_desc.set_halign(Gtk.Align.END)

View file

@ -0,0 +1,331 @@
msgid ""
msgstr ""
"Project-Id-Version: keyman\n"
"Report-Msgid-Bugs-To: <support@keyman.com>\n"
"POT-Creation-Date: 2020-08-19 19:17+0200\n"
"PO-Revision-Date: 2021-09-21 07:17\n"
"Last-Translator: \n"
"Language-Team: Shuwa (Latin script)\n"
"Language: shu_latn\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=4; plural=(n%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || n%100==4 ? 3 : 0);\n"
"X-Crowdin-Project: keyman\n"
"X-Crowdin-Project-ID: 386703\n"
"X-Crowdin-Language: shu-latn-n\n"
"X-Crowdin-File: /master/linux/keyman-config.pot\n"
"X-Crowdin-File-ID: 504\n"
#: keyman_config/__init__.py:68
msgid "Neither sentry-sdk nor raven is available. Not enabling Sentry error reporting."
msgstr "Mafi sentry-sdk walla raven. Mafi mushkila hana Sentry ley eigaddur."
#: keyman_config/downloadkeyboard.py:23
msgid "Download Keyman keyboards"
msgstr "Dys keyboards hana Keyman"
#: keyman_config/downloadkeyboard.py:37 keyman_config/keyboard_details.py:49
#: keyman_config/keyboard_details.py:340 keyman_config/view_installed.py:205
msgid "_Close"
msgstr "_Sidda"
#: keyman_config/install_kmp.py:99
msgid "You do not have permissions to install the keyboard files to the shared area /usr/local/share/keyman"
msgstr "Ma layk izin ley tadissal shu'ulal keyboard layl bikan da /usr/local/share/keyman"
#: keyman_config/install_kmp.py:103
msgid "You do not have permissions to install the documentation to the shared documentation area /usr/local/share/doc/keyman"
msgstr "Ma layk izin ley tadissal kutub da ley kutub altagassuma jai /usr/local/share/doc/keyman"
#: keyman_config/install_kmp.py:107
msgid "You do not have permissions to install the font files to the shared font area /usr/local/share/fonts"
msgstr "Ma layk izin ley tadissal shabal kutub ley bikanal kutub da /usr/local/share/fonts"
#: keyman_config/install_kmp.py:179
#, python-brace-format
msgid "install_kmp.py: error: No kmp.json or kmp.inf found in {package}"
msgstr "install_kmp.py: error: No kmp.json or kmp.inf found in {package}"
#: keyman_config/install_kmp.py:246
#, python-brace-format
msgid "install_kmp.py: error: No kmp.json or kmp.inf found in {packageFile}"
msgstr "install_kmp.py: error: No kmp.json or kmp.inf found in {packageFile}"
#: keyman_config/install_window.py:54
#, python-brace-format
msgid "Installing keyboard/package {keyboardid}"
msgstr "Dassasan keyboard/package {keyboardid}"
#: keyman_config/install_window.py:72 keyman_config/install_window.py:93
msgid "Keyboard is installed already"
msgstr "Mafi al keyboard dakhal"
#: keyman_config/install_window.py:74
#, python-brace-format
msgid "The {name} keyboard is already installed at version {version}. Do you want to uninstall then reinstall it?"
msgstr "Al {name} keyboard dakhal fi shabal nafar da {version}. Tador tasulla wa gadey kula ta gulba wah?"
#: keyman_config/install_window.py:95
#, python-brace-format
msgid "The {name} keyboard is already installed with a newer version {installedversion}. Do you want to uninstall it and install the older version {version}?"
msgstr "Al {name} keyboard dakhal bey shaba nafaral jadid {installedversion}. Tador ta sulla wa ta gulub nafar hanal gabul wah {version}?"
#: keyman_config/install_window.py:128
msgid "Keyboard layouts: "
msgstr "Shabal Keyboard: "
#: keyman_config/install_window.py:147
msgid "Fonts: "
msgstr "Katub: "
#: keyman_config/install_window.py:167 keyman_config/keyboard_details.py:96
msgid "Package version: "
msgstr "Nafaral shu'ul: "
#: keyman_config/install_window.py:179
msgid "Author: "
msgstr "Nadum alwasa: "
#: keyman_config/install_window.py:197
msgid "Website: "
msgstr "Website: "
#: keyman_config/install_window.py:211
msgid "Copyright: "
msgstr "Izin: "
#: keyman_config/install_window.py:245
msgid "Details"
msgstr "Shu'ul alfiya"
#: keyman_config/install_window.py:248
msgid "README"
msgstr "README"
#: keyman_config/install_window.py:256 keyman_config/view_installed.py:200
msgid "_Install"
msgstr "_Dyssa"
#: keyman_config/install_window.py:260
msgid "_Cancel"
msgstr "_Halla"
#: keyman_config/install_window.py:305
#, python-brace-format
msgid "Keyboard {name} installed"
msgstr "Keyboard {name} aldakhal"
#: keyman_config/install_window.py:310 keyman_config/install_window.py:315
#, python-brace-format
msgid "Keyboard {name} could not be installed."
msgstr "Al keyboard {name} ma gudur dakhal."
#: keyman_config/install_window.py:311
msgid "Error Message:"
msgstr "Dalil hanal mushkila:"
#: keyman_config/install_window.py:316
msgid "Warning Message:"
msgstr "Risala hana khatr:"
#: keyman_config/keyboard_details.py:37
#, python-brace-format
msgid "{name} keyboard"
msgstr "{name} keyboard"
#: keyman_config/keyboard_details.py:53
msgid "ERROR: Keyboard metadata is damaged.\n"
"Please \"Uninstall\" and then \"Install\" the keyboard."
msgstr "MUSHKILA: Keyboard metadata tuluf. \n"
"Albarak \"Sulla\" wa gadey kula \"Dyssal\" keyboard."
#: keyman_config/keyboard_details.py:74
msgid "Package name: "
msgstr "Usumal Package: "
#: keyman_config/keyboard_details.py:85
msgid "Package id: "
msgstr "Package id: "
#: keyman_config/keyboard_details.py:108
msgid "Package description: "
msgstr "Bayan hanal Package: "
#: keyman_config/keyboard_details.py:121
msgid "Package author: "
msgstr "Usumal nadum alsawwal Package: "
#: keyman_config/keyboard_details.py:133
msgid "Package copyright: "
msgstr "Izin hanal Package: "
#: keyman_config/keyboard_details.py:174
msgid "Keyboard filename: "
msgstr "Keyboard filename: "
#: keyman_config/keyboard_details.py:187
msgid "Keyboard name: "
msgstr "Usumal Keyboard: "
#: keyman_config/keyboard_details.py:198
msgid "Keyboard id: "
msgstr "Keyboard id: "
#: keyman_config/keyboard_details.py:209
msgid "Keyboard version: "
msgstr "Nafaral Keyboard: "
#: keyman_config/keyboard_details.py:221
msgid "Keyboard author: "
msgstr "Sidal Keyboard: "
#: keyman_config/keyboard_details.py:232
msgid "Keyboard license: "
msgstr "Izin hanal Keyboard: "
#: keyman_config/keyboard_details.py:243
msgid "Keyboard description: "
msgstr "Bayan hanal Keyboard: "
#: keyman_config/keyboard_details.py:334
#, python-brace-format
msgid "Scan this code to load this keyboard\n"
"on another device or <a href='{uri}'>share online</a>"
msgstr "Dyssal shu'ul da ley shu'ul gadey walla <a href='{uri}'>kan tagassuma online</a>"
#: keyman_config/options.py:24
#, python-brace-format
msgid "{packageId} Settings"
msgstr "{packageId} Miwasa"
#: keyman_config/view_installed.py:30
msgid "Keyman Configuration"
msgstr "Miwasa hanal Keyman"
#: keyman_config/view_installed.py:60
msgid "Choose a kmp file..."
msgstr "Azzul kmp file..."
#. i18n: file type in file selection dialog
#: keyman_config/view_installed.py:65
msgid "KMP files"
msgstr "KMP files"
#. i18n: column header in table displaying installed keyboards
#: keyman_config/view_installed.py:141
msgid "Icon"
msgstr "Icon"
#. i18n: column header in table displaying installed keyboards
#: keyman_config/view_installed.py:145
msgid "Name"
msgstr "Usum"
#. i18n: column header in table displaying installed keyboards
#: keyman_config/view_installed.py:148
msgid "Version"
msgstr "Nafar"
#: keyman_config/view_installed.py:161
msgid "_Uninstall"
msgstr "_Sulla"
#: keyman_config/view_installed.py:162 keyman_config/view_installed.py:304
msgid "Uninstall keyboard"
msgstr "Sulal keyboard"
#: keyman_config/view_installed.py:167
msgid "_About"
msgstr "_Faoug"
#: keyman_config/view_installed.py:168 keyman_config/view_installed.py:306
msgid "About keyboard"
msgstr "Faougal keyboard"
#: keyman_config/view_installed.py:173
msgid "_Help"
msgstr "_Mi'awana"
#: keyman_config/view_installed.py:174 keyman_config/view_installed.py:305
msgid "Help for keyboard"
msgstr "Mi'awana layl keyboard"
#: keyman_config/view_installed.py:179
msgid "_Options"
msgstr "_Durub"
#: keyman_config/view_installed.py:180 keyman_config/view_installed.py:307
msgid "Settings for keyboard"
msgstr "Miwasa hanal keyboard"
#: keyman_config/view_installed.py:190
msgid "_Refresh"
msgstr "_Jadidiye"
#: keyman_config/view_installed.py:191
msgid "Refresh keyboard list"
msgstr "Adad hana min jadidiye hanal keyboard"
#: keyman_config/view_installed.py:195
msgid "_Download"
msgstr "_Dyssa"
#: keyman_config/view_installed.py:196
msgid "Download and install a keyboard from the Keyman website"
msgstr "Dyssal keyboard min website hana Keyman"
#: keyman_config/view_installed.py:201
msgid "Install a keyboard from a file"
msgstr "Dyssal keyboard min shu'ul gadey"
#: keyman_config/view_installed.py:206
msgid "Close window"
msgstr "Syddal bikan"
#: keyman_config/view_installed.py:278
#, python-brace-format
msgid "Uninstall keyboard {package}"
msgstr "Sulal keyboard {package}"
#: keyman_config/view_installed.py:280
#, python-brace-format
msgid "Help for keyboard {package}"
msgstr "Mi'awana layl keyboard {package}"
#: keyman_config/view_installed.py:282
#, python-brace-format
msgid "About keyboard {package}"
msgstr "Faougal keyboard {package}"
#: keyman_config/view_installed.py:284
#, python-brace-format
msgid "Settings for keyboard {package}"
msgstr "Miwasa hanal keyboard {package}"
#: keyman_config/view_installed.py:349
msgid "Uninstall keyboard package?"
msgstr "Sulal package hanal keyboard?"
#: keyman_config/view_installed.py:351
#, python-brace-format
msgid "Are you sure that you want to uninstall the {keyboard} keyboard and its fonts?"
msgstr "Tabbat tador tasulal {keyboard} keyboard bey katuba kula?"
#: keyman_config/welcome.py:22
#, python-brace-format
msgid "{name} installed"
msgstr "{name} dakhal"
#: keyman_config/welcome.py:40
msgid "Open in _Web browser"
msgstr "Fukka fi _Web browser"
#: keyman_config/welcome.py:42
msgid "Open in the default web browser to do things like printing"
msgstr "Fukka fi web browser hana gabul ley sawwiyan shu'ul shaba darabanal kakkad"
#: keyman_config/welcome.py:45
msgid "_OK"
msgstr "_Zayn"

View file

@ -0,0 +1,332 @@
msgid ""
msgstr ""
"Project-Id-Version: keyman\n"
"Report-Msgid-Bugs-To: <support@keyman.com>\n"
"POT-Creation-Date: 2020-08-19 19:17+0200\n"
"PO-Revision-Date: 2021-09-16 01:28\n"
"Last-Translator: \n"
"Language-Team: Chinese Simplified\n"
"Language: zh_CN\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Crowdin-Project: keyman\n"
"X-Crowdin-Project-ID: 386703\n"
"X-Crowdin-Language: zh-CN\n"
"X-Crowdin-File: /master/linux/keyman-config.pot\n"
"X-Crowdin-File-ID: 504\n"
#: keyman_config/__init__.py:68
msgid "Neither sentry-sdk nor raven is available. Not enabling Sentry error reporting."
msgstr "sentry-sdk和raven均不可用。无法启用 Sentry 错误报告。"
#: keyman_config/downloadkeyboard.py:23
msgid "Download Keyman keyboards"
msgstr "下载Keyman键盘"
#: keyman_config/downloadkeyboard.py:37 keyman_config/keyboard_details.py:49
#: keyman_config/keyboard_details.py:340 keyman_config/view_installed.py:205
msgid "_Close"
msgstr "_关闭"
#: keyman_config/install_kmp.py:99
msgid "You do not have permissions to install the keyboard files to the shared area /usr/local/share/keyman"
msgstr "您没有权限将键盘文件安装到共享区域/usr/local/shar/keyman"
#: keyman_config/install_kmp.py:103
msgid "You do not have permissions to install the documentation to the shared documentation area /usr/local/share/doc/keyman"
msgstr "您没有权限将文档安装到共享文档区域 /usr/local/share/doc/keyman"
#: keyman_config/install_kmp.py:107
msgid "You do not have permissions to install the font files to the shared font area /usr/local/share/fonts"
msgstr "您没有权限将字体文件安装到共享字体区域/usr/local/share/fonts"
#: keyman_config/install_kmp.py:179
#, python-brace-format
msgid "install_kmp.py: error: No kmp.json or kmp.inf found in {package}"
msgstr "install_kmp.py:错误: {package} 中找不到 kmp.json 或 kmp.inf"
#: keyman_config/install_kmp.py:246
#, python-brace-format
msgid "install_kmp.py: error: No kmp.json or kmp.inf found in {packageFile}"
msgstr "install_kmp.py:错误: {packageFile} 中找不到 kmp.json 或 kmp.inf"
#: keyman_config/install_window.py:54
#, python-brace-format
msgid "Installing keyboard/package {keyboardid}"
msgstr "正在安装键盘/软件包 {keyboardid}"
#: keyman_config/install_window.py:72 keyman_config/install_window.py:93
msgid "Keyboard is installed already"
msgstr "键盘已经安装"
#: keyman_config/install_window.py:74
#, python-brace-format
msgid "The {name} keyboard is already installed at version {version}. Do you want to uninstall then reinstall it?"
msgstr "{name} 键盘已安装在 {version} 版本上。您想要卸载后重新安装吗?"
#: keyman_config/install_window.py:95
#, python-brace-format
msgid "The {name} keyboard is already installed with a newer version {installedversion}. Do you want to uninstall it and install the older version {version}?"
msgstr "{name} 键盘已经安装了更新版本 {installedversion}。您想要卸载它并安装旧版本 {version} 吗?"
#: keyman_config/install_window.py:128
msgid "Keyboard layouts: "
msgstr "键盘布局: "
#: keyman_config/install_window.py:147
msgid "Fonts: "
msgstr "字体: "
#: keyman_config/install_window.py:167 keyman_config/keyboard_details.py:96
msgid "Package version: "
msgstr "软件包版本: "
#: keyman_config/install_window.py:179
msgid "Author: "
msgstr "作者: "
#: keyman_config/install_window.py:197
msgid "Website: "
msgstr "网站: "
#: keyman_config/install_window.py:211
msgid "Copyright: "
msgstr "版权: "
#: keyman_config/install_window.py:245
msgid "Details"
msgstr "详细信息"
#: keyman_config/install_window.py:248
msgid "README"
msgstr "README"
#: keyman_config/install_window.py:256 keyman_config/view_installed.py:200
msgid "_Install"
msgstr "_安装"
#: keyman_config/install_window.py:260
msgid "_Cancel"
msgstr "_取消"
#: keyman_config/install_window.py:305
#, python-brace-format
msgid "Keyboard {name} installed"
msgstr "{name} 键盘已安装"
#: keyman_config/install_window.py:310 keyman_config/install_window.py:315
#, python-brace-format
msgid "Keyboard {name} could not be installed."
msgstr "{name} 键盘无法安装。"
#: keyman_config/install_window.py:311
msgid "Error Message:"
msgstr "错误消息:"
#: keyman_config/install_window.py:316
msgid "Warning Message:"
msgstr "警告消息:"
#: keyman_config/keyboard_details.py:37
#, python-brace-format
msgid "{name} keyboard"
msgstr "{name} 键盘"
#: keyman_config/keyboard_details.py:53
msgid "ERROR: Keyboard metadata is damaged.\n"
"Please \"Uninstall\" and then \"Install\" the keyboard."
msgstr "错误:键盘元数据损坏。\n"
"请“卸载”,然后“安装”键盘。"
#: keyman_config/keyboard_details.py:74
msgid "Package name: "
msgstr "软件包名称: "
#: keyman_config/keyboard_details.py:85
msgid "Package id: "
msgstr "软件包ID: "
#: keyman_config/keyboard_details.py:108
msgid "Package description: "
msgstr "软件包描述: "
#: keyman_config/keyboard_details.py:121
msgid "Package author: "
msgstr "软件包作者: "
#: keyman_config/keyboard_details.py:133
msgid "Package copyright: "
msgstr "软件包版权: "
#: keyman_config/keyboard_details.py:174
msgid "Keyboard filename: "
msgstr "键盘文件名称: "
#: keyman_config/keyboard_details.py:187
msgid "Keyboard name: "
msgstr "键盘名称: "
#: keyman_config/keyboard_details.py:198
msgid "Keyboard id: "
msgstr "键盘 id: "
#: keyman_config/keyboard_details.py:209
msgid "Keyboard version: "
msgstr "键盘版本: "
#: keyman_config/keyboard_details.py:221
msgid "Keyboard author: "
msgstr "键盘作者: "
#: keyman_config/keyboard_details.py:232
msgid "Keyboard license: "
msgstr "键盘许可: "
#: keyman_config/keyboard_details.py:243
msgid "Keyboard description: "
msgstr "键盘描述: "
#: keyman_config/keyboard_details.py:334
#, python-brace-format
msgid "Scan this code to load this keyboard\n"
"on another device or <a href='{uri}'>share online</a>"
msgstr "扫描此代码在另一台设备上加载此键盘\n"
"或 <a href='{uri}'>在线分享</a>"
#: keyman_config/options.py:24
#, python-brace-format
msgid "{packageId} Settings"
msgstr "{packageId} 设置"
#: keyman_config/view_installed.py:30
msgid "Keyman Configuration"
msgstr "Keyman 配置"
#: keyman_config/view_installed.py:60
msgid "Choose a kmp file..."
msgstr "选择一个 kmp 文件..."
#. i18n: file type in file selection dialog
#: keyman_config/view_installed.py:65
msgid "KMP files"
msgstr "KMP 文件"
#. i18n: column header in table displaying installed keyboards
#: keyman_config/view_installed.py:141
msgid "Icon"
msgstr "图标"
#. i18n: column header in table displaying installed keyboards
#: keyman_config/view_installed.py:145
msgid "Name"
msgstr "名称"
#. i18n: column header in table displaying installed keyboards
#: keyman_config/view_installed.py:148
msgid "Version"
msgstr "版本"
#: keyman_config/view_installed.py:161
msgid "_Uninstall"
msgstr "_卸载"
#: keyman_config/view_installed.py:162 keyman_config/view_installed.py:304
msgid "Uninstall keyboard"
msgstr "卸载键盘"
#: keyman_config/view_installed.py:167
msgid "_About"
msgstr "_关于"
#: keyman_config/view_installed.py:168 keyman_config/view_installed.py:306
msgid "About keyboard"
msgstr "关于键盘"
#: keyman_config/view_installed.py:173
msgid "_Help"
msgstr "_帮助"
#: keyman_config/view_installed.py:174 keyman_config/view_installed.py:305
msgid "Help for keyboard"
msgstr "键盘帮助"
#: keyman_config/view_installed.py:179
msgid "_Options"
msgstr "_选项"
#: keyman_config/view_installed.py:180 keyman_config/view_installed.py:307
msgid "Settings for keyboard"
msgstr "键盘设置"
#: keyman_config/view_installed.py:190
msgid "_Refresh"
msgstr "_刷新"
#: keyman_config/view_installed.py:191
msgid "Refresh keyboard list"
msgstr "刷新键盘列表"
#: keyman_config/view_installed.py:195
msgid "_Download"
msgstr "_下载"
#: keyman_config/view_installed.py:196
msgid "Download and install a keyboard from the Keyman website"
msgstr "从Keyman网站下载并安装键盘"
#: keyman_config/view_installed.py:201
msgid "Install a keyboard from a file"
msgstr "从文件安装键盘"
#: keyman_config/view_installed.py:206
msgid "Close window"
msgstr "关闭窗口"
#: keyman_config/view_installed.py:278
#, python-brace-format
msgid "Uninstall keyboard {package}"
msgstr "卸载键盘 {package}"
#: keyman_config/view_installed.py:280
#, python-brace-format
msgid "Help for keyboard {package}"
msgstr "{package} 键盘帮助"
#: keyman_config/view_installed.py:282
#, python-brace-format
msgid "About keyboard {package}"
msgstr "关于 {package} 键盘"
#: keyman_config/view_installed.py:284
#, python-brace-format
msgid "Settings for keyboard {package}"
msgstr "{package} 键盘的设置"
#: keyman_config/view_installed.py:349
msgid "Uninstall keyboard package?"
msgstr "卸载键盘包?"
#: keyman_config/view_installed.py:351
#, python-brace-format
msgid "Are you sure that you want to uninstall the {keyboard} keyboard and its fonts?"
msgstr "您确定要卸载 {keyboard} 键盘及其字体吗?"
#: keyman_config/welcome.py:22
#, python-brace-format
msgid "{name} installed"
msgstr "{name} 已安装"
#: keyman_config/welcome.py:40
msgid "Open in _Web browser"
msgstr "在_网页浏览器中打开"
#: keyman_config/welcome.py:42
msgid "Open in the default web browser to do things like printing"
msgstr "在默认的网页浏览器中打开来做打印一类的事情。"
#: keyman_config/welcome.py:45
msgid "_OK"
msgstr "_确定"

View file

@ -31,7 +31,7 @@ for proj in ${projects}; do
downloadSource debianpackage
cd ${proj}-${version}
if [ -n $DIST ]; then
if [ -n "$DIST" ]; then
EXTRA_ARGS="--distribution $DIST --force-distribution"
fi
dch --newversion ${version}-1 ${EXTRA_ARGS} "Re-release to Debian"

2
mac/.gitignore vendored
View file

@ -12,4 +12,6 @@ Carthage/**
**/output
localenv.sh
setup/textinputsource/textinputsource
setup/textinputsource/textinputsource.arm64
setup/textinputsource/textinputsource.x86_64
setup/Install Keyman.app

View file

@ -1,5 +1,7 @@
# Keyman for macOS
## Prerequisites
See [build configuration](../docs/build/index.md) for details on how to configure your build environment.
## Keyman for macOS Development

View file

@ -32,6 +32,18 @@ Apple Disk Image (.dmg) file. It should be installed according to the following
5. Now you can start typing with the selected keyboard in any text editor or
application that uses standard macOS input methods.
---
If you're using Homebrew, you can also install Keyman with the command:
1.
```
brew install --cask keyman
```
2. Configure the macOS [security permissions](../troubleshooting/configure-security) for Keyman to run.
----
## How To - Updating Keyman for macOS
When a new version of Keyman is released, you can update by following the instructions

View file

@ -29,6 +29,13 @@ fi
osacompile -o "$SOURCEAPP" -x source/install.applescript
cp source/applet.icns "$SOURCEAPP/Contents/Resources/applet.icns"
# Add arm64 to plist so that the script is not marked as requiring Rosetta
# ... LSArchitecturePriority
# https://developer.apple.com/documentation/apple-silicon/building-a-universal-macos-binary#Specify-the-Launch-Behavior-of-Your-App
/usr/libexec/PlistBuddy -c "Add :LSArchitecturePriority array" "$SOURCEAPP/Contents/Info.plist"
/usr/libexec/PlistBuddy -c "Add :LSArchitecturePriority:0 string 'arm64'" "$SOURCEAPP/Contents/Info.plist"
/usr/libexec/PlistBuddy -c "Add :LSArchitecturePriority:1 string 'x86_64'" "$SOURCEAPP/Contents/Info.plist"
#
# Build textinputsource
#

View file

@ -0,0 +1,12 @@
# Build textinputsource for multiple architectures
textinputsource: textinputsource.x86_64 textinputsource.arm64
lipo -create -output $@ $^
textinputsource.x86_64: main.c
xcrun -sdk macosx $(CC) $^ -framework Carbon -o $@ -target x86_64-apple-macos10.12
textinputsource.arm64: main.c
xcrun -sdk macosx $(CC) $^ -framework Carbon -o $@ -target arm64-apple-macos11
clean:
-rm textinputsource textinputsource.arm64 textinputsource.x86_64

View file

@ -1,4 +1,4 @@
#!/bin/bash
set -e
set -u
gcc -framework Carbon -o textinputsource main.c
make textinputsource

View file

@ -1,8 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.firstvoices.keyboards" >
<uses-permission android:name="android.permission.INTERNET" />
<!-- Keyman Engine removes INTERNET permission, so add it back for crash reporting -->
<uses-permission android:name="android.permission.INTERNET" tools:node="replace" />
<application
android:allowBackup="true"

View file

@ -129,10 +129,10 @@ function upload_keyman_help {
exit 1
fi
rm -rf "$dstpath"
mkdir -p "$dstpath"
rm -rf "$dstpath/*"
cp -r "$helppath"/* "$dstpath/"
cp -rv "$helppath"/* "$dstpath/"
}
#

View file

@ -89,10 +89,18 @@ echo ". Get information about pull request #$PRNUM from GitHub"
prinfo=`curl -s -H "User-Agent: @keymanapp" https://api.github.com/repos/keymanapp/keyman/pulls/$PRNUM`
prbase=`echo ${prinfo} | "$JQ" -r '.base.ref'`
prhead=`echo ${prinfo} | "$JQ" -r '.head.ref'`
prbaserepo=`echo ${prinfo} | "$JQ" -r '.base.repo.html_url'`
prheadrepo=`echo ${prinfo} | "$JQ" -r '.head.repo.html_url'`
debug_echo "PRNUM: $PRNUM"
debug_echo "BASE: $prbase"
debug_echo "HEAD: $prhead"
debug_echo "BASE: $prbase ($prbaserepo)"
debug_echo "HEAD: $prhead ($prheadrepo)"
prremote=origin
if [ "$prbaserepo" != "https://github.com/keymanapp/keyman" ]; then
echo "Unknown base repository $prbaserepo."
exit 1
fi
#
# By default, TeamCity does not fetch any remote branch information
@ -104,19 +112,38 @@ echo ". Ensure our local branch is up to date"
pushd "$KEYMAN_ROOT" > /dev/null
git fetch origin > /dev/null
#
# If the repo is a fork, we need to fetch the remote as well; note that
# this only happens on a manual build as automatic trigger does not run
# on untrusted forks.
#
if [ "$prheadrepo" != "https://github.com/keymanapp/keyman" ]; then
prremote=external-rrtb
git remote add "$prremote" "$prheadrepo"
git fetch "$prremote" > /dev/null
fi
#
# Then get a list of changed files between BASE of the branch and the branch itself
# We work from origin so we don't need the branches in our local copy
#
echo ". Get list of changed files in the pull request"
prfiles=`git diff --name-only "origin/$prbase"..."origin/$prhead" || ( if [ $? == 128 ]; then echo abort; else exit $?; fi )`
prfiles=`git diff --name-only "origin/$prbase"..."$prremote/$prhead" || ( if [ $? == 128 ]; then echo abort; else exit $?; fi )`
if [ "$prfiles" == "abort" ]; then
# Don't trigger any builds, exit with success
if [ "$prremote" != "origin" ]; then
git remote remove "$prremote"
fi
echo "Remote branch origin/$prhead has gone away; probably an automatic pull request. Skipping build."
exit 0
fi
if [ "$prremote" != "origin" ]; then
git remote remove "$prremote"
fi
debug_echo "Files found: ${prfiles[*]}"
popd > /dev/null

View file

@ -159,9 +159,9 @@
"dev": true
},
"ansi-regex": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
"integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg=="
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
},
"ansi-styles": {
"version": "4.2.1",

View file

@ -1,5 +1,5 @@
{
"name": "@keymanapp/resources-gosh",
"version": "15.0.113",
"version": "15.0.125",
"lockfileVersion": 1
}

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/resources-gosh",
"version": "15.0.113",
"version": "15.0.125",
"description": "Good Ol' Shell",
"author": "Marc Durdin <marc@keyman.com> (https://github.com/mcdurdin)",
"contributors": [

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