diff --git a/ios/engine/KMEI/KeymanEngine/az.lproj/Localizable.strings b/ios/engine/KMEI/KeymanEngine/az.lproj/Localizable.strings
index e028de1bb2..acad880cc4 100644
--- a/ios/engine/KMEI/KeymanEngine/az.lproj/Localizable.strings
+++ b/ios/engine/KMEI/KeymanEngine/az.lproj/Localizable.strings
@@ -1,32 +1,32 @@
/* A descriptive message used for errors when the app is already busy downloading */
-"alert-download-error-busy" = "Onsuz da yükləməklə məşğuldur.";
+"alert-download-error-busy" = "Artıq endirilir.";
/* A descriptive message used when a download fails */
-"alert-download-error-detail" = "Yükləmə və ya quraşdırma zamanı xəta baş verdi.";
+"alert-download-error-detail" = "Endirmə və ya quraşdırma zamanı xəta baş verdi.";
/* Title for a "download failed" alert */
-"alert-download-error-title" = "Yükləmə xətası";
+"alert-download-error-title" = "Endirmə xətası";
/* Title for a general alert about errors */
"alert-error-title" = "Xəta";
/* A descriptive message used when no internet connection is detected */
-"alert-no-connection-detail" = "Keyman serverinə çata bilmədi. Zəhmət olmasa bir az sonra yenə cəhd edin.";
+"alert-no-connection-detail" = "Keyman serverinə çata bilmədi. Zəhmət olmasa daha sonra yenidən sınayın.";
/* Title for a "no connection" alert */
-"alert-no-connection-title" = "Əlaqə xətası";
+"alert-no-connection-title" = "Bağlantı xətası";
/* Short text for a 'back' navigational command. Used to return to the previous screen */
"command-back" = "Geri";
/* Short text for a 'cancel' command. Used to back out of a menu or install process without making changes */
-"command-cancel" = "Ləğv etmək";
+"command-cancel" = "İmtina";
/* Short text for a 'done' command. Used to back out of settings menus after changes have been made */
-"command-done" = "Bitdi";
+"command-done" = "Hazırdır";
/* Short text for an 'install' command. Used to confirm installation of a package. */
-"command-install" = "Yüklemek";
+"command-install" = "Quraşdır";
/* Short text for a 'next' navigational command. Used to advance to the next screen */
"command-next" = "Növbəti";
@@ -38,25 +38,25 @@
"command-uninstall" = "Sil";
/* Text for the command to uninstall a keyboard */
-"command-uninstall-keyboard" = "Klaviaturanı silin";
+"command-uninstall-keyboard" = "Klaviaturanı sil";
/* Confirmation text to display before uninstalling a keyboard */
"command-uninstall-keyboard-confirm" = "Bu klaviaturanı silmək istəyirsiniz?";
/* Text for the command to uninstall a lexical model */
-"command-uninstall-lexical-model" = "Lüğəti silmək";
+"command-uninstall-lexical-model" = "Lüğəti sil";
/* Confirmation text to display before uninstalling a lexical model */
"command-uninstall-lexical-model-confirm" = "Bu lüğəti silmək istəyirsiniz?";
/* Text for error when an installed file is unexpectedly missing */
-"error-missing-file" = "Lazımi bir fayl tapılmadı.";
+"error-missing-file" = "Tələb olunan fayl tapıla bilmədi.";
/* Text for error when an installed file is unexpectedly missing */
-"error-missing-file-critical" = "Həlledici bir fayl tapılmadı. Tətbiqi yenidən quraşdırmağa cəhd edin.";
+"error-missing-file-critical" = "Kritik fayl tapıla bilmədi. Tətbiqi yenidən quraşdırmağı sınayın.";
/* Text for errors in data received from search queries */
-"error-query-decoding" = "Server hazırda texniki çətinliklərlə üzləşir";
+"error-query-decoding" = "Hal-hazırda server texniki çətinliklər yaşayır";
/* A descriptive message used when a download fails */
"error-query-general" = "Serverlə əlaqə qurma xətası";
@@ -65,7 +65,7 @@
"error-query-no-data" = "Server cavab vermədi";
/* Text for general errors where not much information is known */
-"error-unknown" = "Gözlənilməz bir səhv baş verdi";
+"error-unknown" = "Gözlənilməz bir xəta baş verdi";
/* Text for error when updating a resource: cannot download because no source is available */
"error-update-no-link" = "Bu paket üçün yeniləmə mənbəyi mövcud deyil";
@@ -89,7 +89,7 @@
"installer-label-package-info" = "Paket məlumatı";
/* Label used for the language-selection tab with the package installation prompt on phones. */
-"installer-label-select-languages" = "Dil (lər) seçin";
+"installer-label-select-languages" = "Dil(lər)i seçin";
/* Label used with a package's version, as seen within the package installation prompt. Example: "Version: 14.0.0" */
"installer-label-version" = "Versiya: %@";
@@ -98,22 +98,22 @@
"installer-section-available-languages" = "Mövcud Dillər";
/* Text for the help popup for changing keyboards with the globe key */
-"keyboard-help-change" = "Klaviaturanı dəyişdirmək üçün buraya vurun";
+"keyboard-help-change" = "Klaviaturanı dəyişdirmək üçün buraya toxunun";
/* Text for the command to exit the Keyman keyboard in favor of other keyboards installed on the system */
-"keyboard-menu-exit" = "Bağlamaq %@";
+"keyboard-menu-exit" = "%@ bağla";
/* Error installing a Keyman package - could not allocate a location to install it */
-"kmp-error-file-system" = "Paketin quraşdırılması zamanı səhv - fayl sistemi xətası";
+"kmp-error-file-system" = "Paket quraşdırma xətası - fayl sistem xətası";
/* Error installing a Keyman package - could not copy package files */
-"kmp-error-file-copying" = "Paketin quraşdırılması zamanı səhv - tələb olunan faylları köçürə bilmədi";
+"kmp-error-file-copying" = "Paket quraşdırma xətası - tələb olunan fayllar kopyalana bilmədi";
/* Error opening a Keyman package - package is not valid */
-"kmp-error-invalid" = "Paketin faylı pozulub.";
+"kmp-error-invalid" = "Paketin faylı zədəlidir.";
/* Error installing a Keyman package - expected resource (keyboard or dictionary) is missing */
-"kmp-error-missing-resource" = "Bu paketdə tələb olunan klaviatura və ya lüğət yoxdur.";
+"kmp-error-missing-resource" = "Bu paket tələb olunan klaviatura və ya lüğəti ehtiva etmir.";
/* Error opening a Keyman package - cannot parse contents */
"kmp-error-no-metadata" = "Bu paket düzgün qurulmamışdır - məzmunu bilinmir.";
@@ -134,16 +134,16 @@
"menu-langsettings-section-settings" = "Dil parametrləri";
/* Title for the language-specific settings menus */
-"menu-langsettings-title" = "%@ Parametrlər";
+"menu-langsettings-title" = "%@ Parametrləri";
/* Label for the toggle that enables corrections that is displayed within a language-specific settings menu */
-"menu-langsettings-toggle-correct" = "Düzəlişləri aktivləşdirmək";
+"menu-langsettings-toggle-correct" = "Düzəlişləri fəallaşdır";
/* Label for the toggle that enables predictions that is displayed within a language-specific settings menu */
-"menu-langsettings-toggle-predict" = "Proqnozları aktivləşdirmək";
+"menu-langsettings-toggle-predict" = "Təxminləri fəallaşdır";
/* 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" = "Bu lüğəti qurmaq istərdinizmi?";
+"menu-lexical-model-install-message" = "Bu lüğəti quraşdırmaq istəyirsiniz?";
/* 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$@";
@@ -152,55 +152,55 @@
"menu-lexical-model-none-message" = "Heç bir lüğət yoxdur";
/* Title for the lexical model menu, a submenu of the language-specific settings menus */
-"menu-lexical-model-title" = "%@ Lüğətlər";
+"menu-lexical-model-title" = "%@ Lüğətləri";
/* Title for the keyboard picker */
"menu-picker-title" = "Klaviaturalar";
/* Primary text for the Settings menu option to report keyboard crashes */
-"menu-settings-error-report" = "Xəta Bildirilməsinə icazə verin";
+"menu-settings-error-report" = "Xəta bildirməyə icazə ver";
/* Secondary text for the Settings menu option to report keyboard crashes */
-"menu-settings-error-report-description" = "\"Tam giriş\" tələb edə bilər";
+"menu-settings-error-report-description" = "\"Tam müraciət\" tələb edə bilər";
/* Primary text for the Settings menu local-file package installation option */
"menu-settings-install-from-file" = "Fayldan quraşdırın";
/* Secondary text for the Settings menu local-file package installation option */
-"menu-settings-install-from-file-description" = ".Kmp faylları axtarmaq";
+"menu-settings-install-from-file-description" = ".kmp fayllarını axtar";
/* Primary text for the Settings menu option that displays the iOS system menu options for the app's keyboard */
"menu-settings-system-keyboard-menu" = "Sistem Klaviatura Parametrləri";
/* Label for the "Show Banner" toggle on the main settings screen */
-"menu-settings-show-banner" = "Banner göstərmək";
+"menu-settings-show-banner" = "Banneri göstər";
/* Label for the "Get Started" automatic display toggle seen in the Settings menu */
-"menu-settings-startup-get-started" = "Başlanğıcda 'Başlayın' göstərmək";
+"menu-settings-startup-get-started" = "Başlanğıcda 'Başlayın' göstər";
/* Title for the main Settings menu */
"menu-settings-title" = "Keyman Parametrləri";
/* Short text for notification: download failure for keyboard */
-"notification-download-failure-keyboard" = "Klaviatura yüklənmədi";
+"notification-download-failure-keyboard" = "Klaviatura endirilmədi";
/* Short text for notification: download failure for lexical model */
-"notification-download-failure-lexical-model" = "Lüğət yüklənmədi";
+"notification-download-failure-lexical-model" = "Lüğət endirilmədi";
/* Short text for notification: download success for keyboard */
"notification-download-success-keyboard" = "Klaviatura uğurla endirildi";
/* Short text for notification: download success for lexical model */
-"notification-download-success-lexical-model" = "Leksik model uğurla yükləndi";
+"notification-download-success-lexical-model" = "Leksik model uğurla endirildi";
/* Short text for notification: downloading a keyboard */
-"notification-downloading-keyboard" = "Klaviatura yüklənir \\ U2026";
+"notification-downloading-keyboard" = "Klaviatura endirilir\U2026";
/* Short text for notification: downloading a lexical model */
-"notification-downloading-lexical-model" = "Lüğət yüklənir \U2026";
+"notification-downloading-lexical-model" = "Lüğət endirilir\U2026";
/* Short text for notification: an update is available */
-"notification-update-available" = "Yeniləmə mümkündür";
+"notification-update-available" = "Yeniləmə mövcuddur";
/* Short text for notification: currently updating */
"notification-update-processing" = "Yenilənir\U2026";
@@ -209,4 +209,4 @@
"success-install" = "Uğurla quraşdırıldı.";
/* A title to use in alerts indicating 'success' at whatever task the user requested */
-"success-title" = "Uğur";
+"success-title" = "Uğurlu";
diff --git a/ios/engine/KMEI/KeymanEngine/az.lproj/Localizable.stringsdict b/ios/engine/KMEI/KeymanEngine/az.lproj/Localizable.stringsdict
index ada8429d49..53cf61217e 100644
--- a/ios/engine/KMEI/KeymanEngine/az.lproj/Localizable.stringsdict
+++ b/ios/engine/KMEI/KeymanEngine/az.lproj/Localizable.stringsdict
@@ -13,9 +13,9 @@
NSStringFormatValueTypeKey
u
one
- %u lüğət quraşdırılıb
+ %u lüğət quraşdırıldı
other
- %u lüğətlər quraşdırıldı
+ %u lüğət quraşdırıldı
notification-update-failed
diff --git a/ios/keyman/Keyman/Keyman/GetStartedViewController/GetStartedViewController.swift b/ios/keyman/Keyman/Keyman/GetStartedViewController/GetStartedViewController.swift
index dcdd3e553b..074fa0fe9c 100644
--- a/ios/keyman/Keyman/Keyman/GetStartedViewController/GetStartedViewController.swift
+++ b/ios/keyman/Keyman/Keyman/GetStartedViewController/GetStartedViewController.swift
@@ -28,6 +28,7 @@ class GetStartedViewController: UIViewController, UITableViewDelegate, UITableVi
NotificationCenter.default.addObserver(self, selector: #selector(self.refreshTable),
name: UIApplication.didBecomeActiveNotification, object: nil)
+ navItem.title = NSLocalizedString("menu-get-started", comment: "")
tableView.isScrollEnabled = false
let icon = UIImageView(image: #imageLiteral(resourceName: "887-notepad.png"))
diff --git a/ios/keyman/Keyman/Keyman/az.lproj/Localizable.strings b/ios/keyman/Keyman/Keyman/az.lproj/Localizable.strings
index 4859b4cc9a..2fe811295e 100644
--- a/ios/keyman/Keyman/Keyman/az.lproj/Localizable.strings
+++ b/ios/keyman/Keyman/Keyman/az.lproj/Localizable.strings
@@ -1,5 +1,5 @@
/* Title for the bookmarks menu within the embedded browser */
-"browser-bookmarks-add-title" = "Əlfəcin əlavə etmək";
+"browser-bookmarks-add-title" = "Əlfəcin əlavə et";
/* Title for the bookmarks menu within the embedded browser */
"browser-bookmarks-none" = "Əlfəcin yoxdur";
@@ -17,7 +17,7 @@
"error-opening-page" = "Səhifə açıla bilmir";
/* Long-form used when installing a font in order to display a language properly. */
-"font-install-description" = "Bütün tətbiqlərinizdə %@ görüntüsünü düzgün görünmək üçün Quraşdır'a toxunun";
+"font-install-description" = "Bütün tətbiqlərinizdə %@ in düzgün görünməsi üçün \"Quraşdır\"a toxunun";
/* The name of the iOS Settings menu option for keyboards */
"ios-settings-keyboards" = "Klaviaturalar";
@@ -30,13 +30,13 @@ underneath the app's name within the app-specific keyboard menu.) */
"language-for-font" = "%@ Şrift";
/* Used for 'add' options within menus */
-"menu-add" = "Əlavə etmək";
+"menu-add" = "Əlavə et";
/* 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" = "Ləğv etmək";
+"menu-cancel" = "İmtina";
/* Menu option that erases all previously-typed text. */
"menu-clear-text" = "Mətni təmizlə";
@@ -51,13 +51,13 @@ underneath the app's name within the app-specific keyboard menu.) */
"menu-more" = "Daha çox";
/* Menu option used to edit keyboard and dictionary settings */
-"menu-settings" = "Parametrlər";
+"menu-settings" = "Tənzimləmələr";
/* Menu option that displays the iOS Share menu */
"menu-share" = "Paylaş";
/* Menu option that displays an embedded web browser. */
-"menu-show-browser" = "Brauzer";
+"menu-show-browser" = "Səyyah";
/* Menu option used to control in-app font size. */
"menu-text-size" = "Mətn ölçüsü";
@@ -66,16 +66,16 @@ underneath the app's name within the app-specific keyboard menu.) */
"text-size-label" = "Mətn ölçüsü:%i";
/* Text to indicate that a user should set a toggle within iOS Settings to 'active'. */
-"toggle-to-enable" = "%@ İşə salmaq";
+"toggle-to-enable" = "Fəallaşdır: %@";
/* First option on the Get Started tutorial - Add a keyboard for your language */
-"tutorial-add-keyboard" = "Sizin diliniz üçün klaviaturanı əlavə edin";
+"tutorial-add-keyboard" = "Diliniz üçün klaviatura əlavə edin";
/* Third option on the Get Started tutorial - Displays app help. */
"tutorial-show-help" = "Ətraflı məlumat";
/* Second option on the Get Started tutorial - Set up Keyman as system-wide keyboard */
-"tutorial-system-keyboard" = "Keyman ümumsistem klaviatura kimi işə salmaq";
+"tutorial-system-keyboard" = "\"Keyman\"ı geniş sistem klaviaturası kimi quraşdırın";
/* Used to display app version (as in \"Version: 1.0.2\" */
-"version-label" = "Versiya %@";
+"version-label" = "Versiya: %@";
diff --git a/linux/keyman-config/keyman_config/handle_install.py b/linux/keyman-config/keyman_config/handle_install.py
index 87541df3da..f332ef6717 100644
--- a/linux/keyman-config/keyman_config/handle_install.py
+++ b/linux/keyman-config/keyman_config/handle_install.py
@@ -5,6 +5,7 @@ from urllib.parse import parse_qs, urlparse
from keyman_config import KeymanComUrl, __tier__
from keyman_config.install_window import InstallKmpWindow
from keyman_config.get_kmp import get_download_folder, download_kmp_file
+from zipfile import is_zipfile
def download_and_install_package(url):
@@ -42,6 +43,10 @@ def download_and_install_package(url):
logging.critical("Invalid URL: " + url)
return
+ if not is_zipfile(packageFile):
+ logging.critical("Not a valid KMP package: " + url)
+ return
+
if packageFile and not _install_package(packageFile, bcp47):
logging.log(severity, "Can't find file " + url)
diff --git a/linux/keyman-config/keyman_config/view_installed.py b/linux/keyman-config/keyman_config/view_installed.py
index 8fa650eb3b..97d6caa577 100755
--- a/linux/keyman-config/keyman_config/view_installed.py
+++ b/linux/keyman-config/keyman_config/view_installed.py
@@ -22,6 +22,7 @@ from keyman_config.install_window import InstallKmpWindow, find_keyman_image
from keyman_config.uninstall_kmp import uninstall_kmp
from keyman_config.accelerators import bind_accelerator, init_accel
from keyman_config.get_kmp import user_keyboard_dir
+from gi.overrides.GLib import GError
class ViewInstalledWindowBase(Gtk.Window):
@@ -228,19 +229,26 @@ class ViewInstalledWindow(ViewInstalledWindowBase):
welcome_file = os.path.join(path, "welcome.htm")
options_file = os.path.join(path, "options.htm")
- icofile = os.path.join(path, kmpdata['packageID'] + bmppng)
+ icofile_name = os.path.join(path, kmpdata['packageID'] + bmppng)
if not os.path.isfile(welcome_file):
welcome_file = None
if not os.path.isfile(options_file):
options_file = None
- if not os.path.isfile(icofile):
- icofile = os.path.join(path, kmpdata['keyboardID'] + bmppng)
- if not os.path.isfile(icofile):
- icofile = find_keyman_image("icon_kmp.png")
+ if not os.path.isfile(icofile_name):
+ icofile_name = os.path.join(path, kmpdata['keyboardID'] + bmppng)
+ if not os.path.isfile(icofile_name):
+ icofile_name = find_keyman_image("icon_kmp.png")
+
+ try:
+ icofile = GdkPixbuf.Pixbuf.new_from_file_at_size(icofile_name, 16, 16)
+ except GError:
+ _, value, _ = sys.exc_info()
+ logging.info("Error reading icon file %s: %s" % (icofile_name, value.message))
+ icofile = None
store.append([
- GdkPixbuf.Pixbuf.new_from_file_at_size(icofile, 16, 16),
+ icofile,
kmpdata['name'],
kmpdata['version'],
kmpdata['packageID'],
diff --git a/linux/keyman-config/km-package-install b/linux/keyman-config/km-package-install
index 8178e12faa..87f0860d24 100755
--- a/linux/keyman-config/km-package-install
+++ b/linux/keyman-config/km-package-install
@@ -9,6 +9,7 @@ from keyman_config.uninstall_kmp import uninstall_kmp
import datetime
import time
+from zipfile import is_zipfile
def get_languages():
@@ -120,7 +121,7 @@ def main():
if args.file:
name, ext = os.path.splitext(args.file)
- if ext != ".kmp":
+ if ext != ".kmp" or not is_zipfile(args.file):
logging.error("km-package-install: Input file %s is not a kmp file.", args.file)
logging.error("km-package-install -f ")
sys.exit(2)
diff --git a/linux/keyman-config/tests/test_gnome_keyboards_util.py b/linux/keyman-config/tests/test_gnome_keyboards_util.py
index 67bf01b74e..ad6d116fbe 100644
--- a/linux/keyman-config/tests/test_gnome_keyboards_util.py
+++ b/linux/keyman-config/tests/test_gnome_keyboards_util.py
@@ -71,14 +71,14 @@ class GnomeKeyboardsUtilTests(unittest.TestCase):
self.MockSettingsClass.return_value.set_value.assert_called_once_with(
"sources", keyboards)
- @patch('keyman_config.install_kmp.os.system')
+ @patch('keyman_config.os.system')
def test_IsGnomeShell_RunningGnomeShell(self, mockSystem):
# Setup
mockSystem.return_value = 0
# Execute/Verify
self.assertEqual(is_gnome_shell(), True)
- @patch('keyman_config.install_kmp.os.system')
+ @patch('keyman_config.os.system')
def test_IsGnomeShell_NotRunningGnomeShell(self, mockSystem):
# Setup
mockSystem.return_value = 1
diff --git a/linux/keyman-config/tests/test_handle_install.py b/linux/keyman-config/tests/test_handle_install.py
index 981e38a41e..4e78bbeeb6 100644
--- a/linux/keyman-config/tests/test_handle_install.py
+++ b/linux/keyman-config/tests/test_handle_install.py
@@ -8,53 +8,79 @@ from keyman_config.handle_install import download_and_install_package
class HandleInstallTests(unittest.TestCase):
+ @patch('keyman_config.handle_install.is_zipfile')
@patch('keyman_config.handle_install._install_package')
- def test_downloadAndInstallPackage_file(self, installPackageMethod):
+ def test_downloadAndInstallPackage_file(self, installPackageMethod, mockIsZipfile):
+ # Setup
+ mockIsZipfile.return_value = True
+
# Execute
download_and_install_package('/tmp/keyboard/sil_euro_latin.kmp')
# Verify
installPackageMethod.assert_called_with('/tmp/keyboard/sil_euro_latin.kmp', '')
+ @patch('keyman_config.handle_install.is_zipfile')
@patch('keyman_config.handle_install._install_package')
- def test_downloadAndInstallPackage_fileUrl(self, installPackageMethod):
+ def test_downloadAndInstallPackage_fileUrl(self, installPackageMethod, mockIsZipfile):
+ # Setup
+ mockIsZipfile.return_value = True
+
# Execute
download_and_install_package('file:///tmp/keyboard/sil_euro_latin.kmp')
# Verify
installPackageMethod.assert_called_with('/tmp/keyboard/sil_euro_latin.kmp', '')
+ @patch('keyman_config.handle_install.is_zipfile')
@patch('keyman_config.handle_install._install_package')
- def test_downloadAndInstallPackage_fileUrlWithBcp47(self, installPackageMethod):
+ def test_downloadAndInstallPackage_fileUrlWithBcp47(self, installPackageMethod,
+ mockIsZipfile):
+ # Setup
+ mockIsZipfile.return_value = True
+
# Execute
download_and_install_package('file:///tmp/keyboard/sil_euro_latin.kmp?bcp47=dyo')
# Verify
installPackageMethod.assert_called_with('/tmp/keyboard/sil_euro_latin.kmp', 'dyo')
+ @patch('keyman_config.handle_install.is_zipfile')
@patch('keyman_config.handle_install._install_package')
- def test_downloadAndInstallPackage_fileUrlWithBcp47AndVersion(self, installPackageMethod):
+ def test_downloadAndInstallPackage_fileUrlWithBcp47AndVersion(self, installPackageMethod,
+ mockIsZipfile):
+ # Setup
+ mockIsZipfile.return_value = True
+
# Execute
download_and_install_package('file:///tmp/keyboard/sil_euro_latin.kmp?bcp47=dyo&version=1')
# Verify
installPackageMethod.assert_called_with('/tmp/keyboard/sil_euro_latin.kmp', 'dyo')
+ @patch('keyman_config.handle_install.is_zipfile')
@patch('keyman_config.handle_install._install_package')
- def test_downloadAndInstallPackage_InvalidUrl(self, installPackageMethod):
+ def test_downloadAndInstallPackage_InvalidUrl(self, installPackageMethod, mockIsZipfile):
+ # Setup
+ mockIsZipfile.return_value = True
+
# Execute
download_and_install_package('http://localhost/keyboard/sil_euro_latin.kmp')
# Verify
installPackageMethod.assert_not_called()
+ @patch('keyman_config.handle_install.is_zipfile')
@patch('keyman_config.handle_install._install_package')
@patch('keyman_config.get_kmp.download_kmp_file')
def test_downloadAndInstallPackage_invalidUrl(self, downloadKmpFileMethod,
- installPackageMethod):
+ installPackageMethod, mockIsZipfile):
for url in ['foo://download/keyboard/sil_euro_latin', 'keyman://keyboard/sil_euro_latin',
'keyman://download/sil_euro_latin', 'keyman://download/keyboard/']:
with self.subTest(url=url):
+ # Setup
+ mockIsZipfile.return_value = True
+
# Execute
download_and_install_package(url)
@@ -62,15 +88,18 @@ class HandleInstallTests(unittest.TestCase):
downloadKmpFileMethod.assert_not_called()
installPackageMethod.assert_not_called()
+ @patch('keyman_config.handle_install.is_zipfile')
@patch('keyman_config.handle_install._install_package')
@patch('keyman_config.get_kmp.keyman_cache_dir')
@patch('keyman_config.handle_install.download_kmp_file')
def test_downloadAndInstallPackage_keymanUrl(self, downloadKmpFileMethod,
- keymanCacheDirMethod, installPackageMethod):
+ keymanCacheDirMethod, installPackageMethod,
+ mockIsZipfile):
# Setup
mockPackagePath = '/tmp/sil_euro_latin'
keymanCacheDirMethod.return_value = '/tmp'
downloadKmpFileMethod.return_value = mockPackagePath
+ mockIsZipfile.return_value = True
# Execute
download_and_install_package('keyman://download/keyboard/sil_euro_latin')
@@ -81,16 +110,18 @@ class HandleInstallTests(unittest.TestCase):
mockPackagePath)
installPackageMethod.assert_called_with(mockPackagePath, '')
+ @patch('keyman_config.handle_install.is_zipfile')
@patch('keyman_config.handle_install._install_package')
@patch('keyman_config.get_kmp.keyman_cache_dir')
@patch('keyman_config.handle_install.download_kmp_file')
def test_downloadAndInstallPackage_keymanUrlWithBcp47(self, downloadKmpFileMethod,
keymanCacheDirMethod,
- installPackageMethod):
+ installPackageMethod, mockIsZipfile):
# Setup
mockPackagePath = '/tmp/sil_euro_latin'
keymanCacheDirMethod.return_value = '/tmp'
downloadKmpFileMethod.return_value = mockPackagePath
+ mockIsZipfile.return_value = True
# Execute
download_and_install_package('keyman://download/keyboard/sil_euro_latin?bcp47=de')
diff --git a/oem/firstvoices/ios/FirstVoices.xcodeproj/project.pbxproj b/oem/firstvoices/ios/FirstVoices.xcodeproj/project.pbxproj
index d0f19881fc..5a9af24f09 100644
--- a/oem/firstvoices/ios/FirstVoices.xcodeproj/project.pbxproj
+++ b/oem/firstvoices/ios/FirstVoices.xcodeproj/project.pbxproj
@@ -12,8 +12,6 @@
37150F74231637EA00C73C6A /* Reachability.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 37150F6F231637EA00C73C6A /* Reachability.framework */; };
37150F75231637EA00C73C6A /* Zip.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 37150F70231637EA00C73C6A /* Zip.framework */; };
37150F76231637EA00C73C6A /* XCGLogger.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 37150F71231637EA00C73C6A /* XCGLogger.framework */; };
- 3729344024613C9900C5428C /* ObjcExceptionBridging.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 37150F6E231637EA00C73C6A /* ObjcExceptionBridging.framework */; };
- 3729344124613CA700C5428C /* XCGLogger.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 37150F71231637EA00C73C6A /* XCGLogger.framework */; };
3729344224613CB600C5428C /* Sentry.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 372A4B9C245E904A001C1F80 /* Sentry.framework */; };
3729344324613CC200C5428C /* Zip.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 37150F70231637EA00C73C6A /* Zip.framework */; };
372A4B9D245E904A001C1F80 /* Sentry.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 372A4B9C245E904A001C1F80 /* Sentry.framework */; };
@@ -664,6 +662,7 @@
CODE_SIGN_STYLE = Manual;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = D7TR486TEH;
+ "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Carthage/Build/iOS",
@@ -694,6 +693,7 @@
CODE_SIGN_IDENTITY = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
DEVELOPMENT_TEAM = D7TR486TEH;
+ "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Carthage/Build/iOS",
@@ -721,6 +721,7 @@
CODE_SIGN_STYLE = Manual;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = D7TR486TEH;
+ "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Carthage/Build/iOS",
@@ -752,6 +753,7 @@
CODE_SIGN_IDENTITY = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
DEVELOPMENT_TEAM = D7TR486TEH;
+ "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Carthage/Build/iOS",
diff --git a/oem/firstvoices/ios/build_common.sh b/oem/firstvoices/ios/build_common.sh
index 38795147e3..a054caf556 100755
--- a/oem/firstvoices/ios/build_common.sh
+++ b/oem/firstvoices/ios/build_common.sh
@@ -125,6 +125,7 @@ else
fi
KEYMAN_ENGINE_FRAMEWORK_SRC="$KMEI_BUILD_DIR/build/Build/Products/$CONFIG-$PLATFORM_TARGET/KeymanEngine.framework"
+KEYMAN_ENGINE_SIM_FRAMEWORK_SRC="$KMEI_BUILD_DIR/build/Build/Products/$CONFIG-iphonesimulator/KeymanEngine.framework"
KEYMAN_ENGINE_FRAMEWORK_DST=./
if [ $DO_UPDATE = true ]; then
@@ -217,6 +218,10 @@ else
fi
if [ $DO_SIMULATOR_TARGET == true ]; then
+ echo "Replacing .framework with Simulator-compatible version"
+ # Replace the previous framework copy in case the main build was for release.
+ cp -Rf "$KEYMAN_ENGINE_SIM_FRAMEWORK_SRC" "$KEYMAN_ENGINE_FRAMEWORK_DST"
+
echo "Preparing .app file as Simulator-targeted build artifact."
xcodebuild CODE_SIGN_ENTITLEMENTS="" CODE_SIGNING_ALLOWED="NO" CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO \
$XCODEFLAGS_EXT -scheme "$TARGET" \
diff --git a/windows/src/desktop/kmshell/locale/az-AZ/strings.xml b/windows/src/desktop/kmshell/locale/az-AZ/strings.xml
index bf05cfd882..2b9d68af82 100644
--- a/windows/src/desktop/kmshell/locale/az-AZ/strings.xml
+++ b/windows/src/desktop/kmshell/locale/az-AZ/strings.xml
@@ -31,11 +31,11 @@
- Ləğv etmək
+ İmtina
- Bağlamaq
+ Bağla
@@ -43,7 +43,7 @@
- Ləğv etmək
+ İmtina
@@ -51,11 +51,11 @@
- Keyman hələ də çalışır. Dil klaviaturanızı istənilən vaxt istifadə etmək üçün bu işarəni vurun
+ Keyman hələ də işləyir. Dil klaviaturanızı istənilən vaxt istifadə etmək üçün bu nişana klikləyin
- Keyman artıq çalışır. Dil klaviaturanızı istifadə etmək üçün sistem bildiriş sahəsindəki Keyman simgesini vurun
+ Keyman artıq işləyir. Dil klaviaturanızı istifadə etmək üçün sistem bildiriş sahəsindəki Keyman nişanına klikləyin
@@ -67,7 +67,7 @@
- Klaviatura tərtibləri
+ Klaviatura düzülüşləri
@@ -79,7 +79,7 @@
- O
+ S
@@ -87,7 +87,7 @@
- H
+ Q
@@ -95,15 +95,15 @@
- S
+ D
- Əlaqə saxlayın
+ Əlaqədə qalın
- T
+ Ə
@@ -115,7 +115,7 @@
- Klaviatura versiyası
+ Klaviatura versiyası:
@@ -123,7 +123,7 @@
- Veb səhifə:
+ Veb sayt:
@@ -135,11 +135,11 @@
- Klaviatura tərtibləri:
+ Klaviatura düzülüşləri:
- Klaviatura tərtibləri:
+ Klaviatura düzülüşü:
@@ -155,11 +155,11 @@
- Fixed (Mövqə)
+ Sabit (Mövqe)
- Windows tərtibatına uyğunlaşdırıldı (Yadda salıcı)
+ Windows düzülüşünə gətirildi (Xatırladıcı)
@@ -171,43 +171,43 @@
- Dil əlavə etmək
+ Dil əlavə et
- Ekran klaviaturasında:
+ Ekran klaviaturası:
- Fərdiləşdirilən
+ Özəl
- Qurulmuş
+ Quraşdırılmış
- Qurulmamış
+ Quraşdırılmamış
- Sənədləşməsi
+ Sənədləşdirmə:
- Qurulmuş
+ Quraşdırılmış
- Qurulmamış
+ Quraşdırılmamış
- Mesaj
+ Mesaj:
- Müəllif hüquqları:
+ Müəllif hüququ:
@@ -215,11 +215,11 @@
- Klaviaturanı quraşdırmaq
+ Klaviaturanı quraşdır...
- Klaviatura yüklənir...
+ Klaviaturanı endir...
@@ -227,24 +227,24 @@
- Quraşdırılmış klaviatura yoxdur. Keyman veb saytından klaviatura düzeni qurmaq üçün Klaviaturanı Yüklə düyməsini vurun.
+ Qurulu heç bir klaviaturanız yoxdur. Keyman veb saytından klaviatura düzülüşünü quraşdırmaq üçün Klaviatura Endir düyməsini klikləyin.
- Yalnız bir idarəedicisinizsə \'%1$s\' klaviaturasını silə bilərsiniz
+ Əgər administratorsunuzsa, \"%1$s\" klaviaturasını silə bilərsiniz
- Klaviaturanı paylaşmaq
+ Klaviaturanı paylaş
- Bu klaviaturanı başqa bir cihaza yükləmək üçün bu kodu tarayın
+ Bu klaviaturanı başqa bir cihazda yükləmək üçün bu kodu skan edin və ya
- onlayn paylaşmaq
+ onlayn paylaşın
@@ -256,35 +256,35 @@
- Başlamaq
+ Açılış
- Ekran klaviaturasında
+ Ekran klaviaturası
- Genişləndirilmiş
+ Qabaqcıl
- Klaviatura qısa yol düymələri klaviatura aktivləşdirməsini dəyişir
+ Klaviatura qısayol düymələri klaviatura aktivləşdirməsini dəyişdirir
- Ctrl + Alt ilə AltGr simulyasiya edin
+ Ctrl + Alt ilə \"AltGr\"i simulyasiya edin
- Donanım açar düymələrini düz açarlar kimi qəbul edin
+ Aparat təminatı özəl düymələrinə düz düymələr kimi davran
- Eyham mesajlarını göstərin
+ Məsləhət mesajlarını göstər
- Səhvləri avtomatik olaraq keyman.com saytına bildirmək
+ Xətaları avtomatik olaraq keyman.com-da bildir
@@ -641,11 +641,11 @@
- İngilis dili
+ Azərbaycanca (Azəricə)
- İngilis dili
+ Azərbaycanca (Azerbaijani)