diff --git a/.github/actions/apt-install/action.yml b/.github/actions/apt-install/action.yml new file mode 100644 index 0000000000..64cb1b91dc --- /dev/null +++ b/.github/actions/apt-install/action.yml @@ -0,0 +1,19 @@ +name: apt-install +description: | + Install debian packages with apt +inputs: + packages: + description: Packages to install + default: devscripts equivs + required: false +runs: + using: "composite" + steps: + - name: Install packages + shell: bash + run: | + export DEBIAN_FRONTEND=noninteractive + export DEBIAN_PRIORITY=critical + export DEBCONF_NOWARNINGS=yes + sudo apt-get update + sudo apt-get install -q -y ${{ inputs.packages }} diff --git a/.github/workflows/deb-packaging.yml b/.github/workflows/deb-packaging.yml new file mode 100644 index 0000000000..41334fc919 --- /dev/null +++ b/.github/workflows/deb-packaging.yml @@ -0,0 +1,279 @@ +name: "Ubuntu packaging" +on: + repository_dispatch: + types: ['deb-release-packaging:*', 'deb-pr-packaging:*'] +env: + COLOR_GREEN: "\e[32m" + GH_TOKEN: ${{ github.token }} + STATUS_CONTEXT: 'Debian Packaging' + DEBFULLNAME: 'Keyman GHA packager' + DEBEMAIL: 'support@keyman.com' + +jobs: + sourcepackage: + name: Build source package + runs-on: ubuntu-22.04 + outputs: + VERSION: ${{ steps.version_step.outputs.VERSION }} + PRERELEASE_TAG: ${{ steps.prerelease_tag.outputs.PRERELEASE_TAG }} + GIT_SHA: ${{ steps.set_status.outputs.GIT_SHA }} + steps: + - name: Checkout + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c #v3.3.0 + with: + ref: '${{ github.event.client_payload.ref }}' + + - name: Set pending status on PR builds + id: set_status + if: github.event.client_payload.isTestBuild == 'true' + shell: bash + run: | + GIT_SHA="${{ github.event.client_payload.sha }}" + echo "GIT_SHA=$GIT_SHA" >> $GITHUB_OUTPUT + gh api \ + --method POST \ + -H "Accept: application/vnd.github+json" \ + /repos/$GITHUB_REPOSITORY/statuses/$GIT_SHA \ + -f state='pending' \ + -f target_url="$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" \ + -f description='Debian packaging started' \ + -f context="$STATUS_CONTEXT" + + - name: Install devscripts + uses: ./.github/actions/apt-install + with: + packages: devscripts equivs + + - name: Install dependencies + run: | + cd linux + ./scripts/deb-packaging.sh --gha dependencies + + - name: Build source package + run: | + TIER=$(cat TIER.md) + export TIER + echo "TIER=$TIER" >> $GITHUB_ENV + cd linux + ./scripts/deb-packaging.sh --gha source + + - name: Set version as output parameter + id: version_step + shell: bash + run: | + THIS_SCRIPT="$GITHUB_WORKSPACE/.github/workflows/deb-packaging.yml" + . "resources/build/build-utils.sh" + echo "VERSION=$VERSION" >> $GITHUB_OUTPUT + + - name: Set prerelease tag as output parameter + id: prerelease_tag + shell: bash + run: | + if [ "${{ github.event.client_payload.isTestBuild }}" == "true" ]; then + PRERELEASE_TAG="~${{ github.event.client_payload.branch }}-$GITHUB_RUN_NUMBER.$GITHUB_RUN_ATTEMPT" + else + PRERELEASE_TAG="" + fi + echo "PRERELEASE_TAG=$PRERELEASE_TAG" >> $GITHUB_OUTPUT + + - name: Output which branch or PR we're building plus name of .dsc file + run: | + if [ "${{ github.event.client_payload.isTestBuild }}" == "true" ]; then + echo ":checkered_flag: **Test build of version ${{ steps.version_step.outputs.VERSION }} for ${{ github.event.client_payload.branch }}**" >> $GITHUB_STEP_SUMMARY + else + echo ":ship: **Release build of ${{ github.event.client_payload.branch }} branch (${{ github.event.client_payload.ref}}), version ${{ steps.version_step.outputs.VERSION }}**" >> $GITHUB_STEP_SUMMARY + fi + echo "" >> $GITHUB_STEP_SUMMARY + echo ":gift: Generated source package:" >> $GITHUB_STEP_SUMMARY + echo "- $(find . -name keyman_\*.dsc)" >> $GITHUB_STEP_SUMMARY + + - name: Store source package + uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + with: + name: keyman-srcpkg + path: | + keyman_* + debian/***/* + if: always() + + binary_packages: + name: Build binary packages + needs: sourcepackage + strategy: + fail-fast: true + matrix: + dist: [focal, jammy, kinetic] + arch: [amd64] + + runs-on: ubuntu-latest + steps: + - name: Download Artifacts + uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + with: + path: artifacts + + - name: Build + uses: sillsdev/gha-ubuntu-packaging@5b56c86ee78598308d864edc55a1d06b4ba36f92 # v0.3 + with: + dist: "${{ matrix.dist }}" + platform: "${{ matrix.arch }}" + source_dir: "artifacts/keyman-srcpkg" + sourcepackage: "keyman_${{ needs.sourcepackage.outputs.VERSION }}-1.dsc" + deb_fullname: $DEBFULLNAME + deb_email: $DEBEMAIL + prerelease_tag: ${{ needs.sourcepackage.outputs.PRERELEASE_TAG }} + + - name: Output resulting .deb files + run: | + echo '```' >> $GITHUB_STEP_SUMMARY + echo "$(find artifacts/ -name \*.deb)" >> $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + + - name: Store binary packages + uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + with: + name: keyman-binarypkgs + path: | + artifacts/* + !artifacts/keyman-srcpkg/ + if: always() + + deb_signing: + name: Sign source and binary packages + needs: [sourcepackage, binary_packages] + runs-on: ubuntu-latest + environment: "deploy (linux)" + if: github.event.client_payload.isTestBuild == 'false' + + steps: + - name: Sign packages + uses: sillsdev/gha-deb-signing@cd1af3dddf83787f9da20a93fc449d927a63bfbf # v0.4 + with: + src-pkg-path: "artifacts/keyman-srcpkg" + src-pkg-name: "keyman_${{ needs.sourcepackage.outputs.VERSION }}-1_source.changes" + bin-pkg-path: "artifacts/keyman-binarypkgs" + bin-pkg-name: "keyman_${{ needs.sourcepackage.outputs.VERSION }}-1${{ needs.sourcepackage.outputs.PRERELEASE_TAG }}+" + artifacts-name: "keyman-signedpkgs" + gpg-signing-key: "${{ secrets.GPG_SIGNING_KEY }}" + debsign-keyid: "${{ secrets.DEBSIGN_KEYID }}" + + upload-to-llso: + name: Upload packages to llso + needs: deb_signing + runs-on: self-hosted + environment: "deploy (linux)" + if: ${{ ! github.event.client_payload.isTestBuild }} + + steps: + - name: Download Artifacts + uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + with: + name: keyman-signedpkgs + path: artifacts + + - name: Install dput + uses: ./.github/actions/apt-install + with: + packages: dput + + - name: Setup .dput.cf + run: | + echo "${{vars.ENV_DPUT_CONFIG}}" > ~/.dput.cf + + - name: Upload + run: | + case ${{ github.event.client_payload.branch }} in + stable-*) destination='' ;; + beta) destination='-proposed' ;; + *) destination='-experimental' ;; + esac + + cd artifacts/keyman-signedpkgs + ls -R + + echo -e "::group::${COLOR_GREEN}Upload source package" + cd artifacts/keyman-srcpkg + dput -U llso:ubuntu/jammy${destination} *_source.changes + echo "::endgroup::" + + echo -e "::group::${COLOR_GREEN}Uploading binary packages" + cd ../keyman-binarypkgs + pattern="keyman_${{ needs.sourcepackage.outputs.VERSION }}.+\+(.*)[0-9]_[^.]+.changes" + for f in *.changes; do + if [[ $f =~ $pattern ]]; then + dist=${BASH_REMATCH[1]} + dput -U llso:ubuntu/${dist}${destination} $f + fi + done + echo "::endgroup::" + + api_verification: + name: Verify API for libkmnkbp0.so + needs: [sourcepackage, binary_packages] + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c #v3.3.0 + with: + ref: '${{ github.event.client_payload.ref }}' + + - name: Download Artifacts + uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + with: + path: artifacts + + - name: Install devscripts + uses: ./.github/actions/apt-install + with: + packages: devscripts equivs + + - name: Verify API + run: | + cd linux + SRC_PKG="${GITHUB_WORKSPACE}/artifacts/keyman-srcpkg/keyman_${{ needs.sourcepackage.outputs.VERSION }}-1.debian.tar.xz" \ + BIN_PKG="${GITHUB_WORKSPACE}/artifacts/keyman-binarypkgs/libkmnkbp0-0_${{ needs.sourcepackage.outputs.VERSION }}-1${{ needs.sourcepackage.outputs.PRERELEASE_TAG }}+jammy1_amd64.deb" \ + PKG_VERSION="${{ needs.sourcepackage.outputs.VERSION }}" \ + ./scripts/deb-packaging.sh --gha verify >> $GITHUB_STEP_SUMMARY + + - name: Archive .symbols file + uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + with: + name: libkmnkbp0-0.symbols + path: linux/debian/libkmnkbp0-0.symbols + if: always() + + set_status: + name: Set result status on PR builds + needs: [sourcepackage, binary_packages, deb_signing, api_verification] + runs-on: ubuntu-latest + if: ${{ always() && github.event.client_payload.isTestBuild == 'true' }} + steps: + - name: Set success + if: needs.sourcepackage.result == 'success' && needs.binary_packages.result == 'success' && (needs.deb_signing.result == 'success' || needs.deb_signing.result == 'skipped') && needs.api_verification.result == 'success' + run: | + echo "RESULT=success" >> $GITHUB_ENV + echo "MSG=Package build succeeded" >> $GITHUB_ENV + + - name: Set cancelled + if: needs.sourcepackage.result == 'cancelled' || needs.binary_packages.result == 'cancelled' || needs.deb_signing.result == 'cancelled' || needs.api_verification.result == 'cancelled' + run: | + echo "RESULT=error" >> $GITHUB_ENV + echo "MSG=Package build cancelled" >> $GITHUB_ENV + + - name: Set failure + if: needs.sourcepackage.result == 'failure' || needs.binary_packages.result == 'failure' || needs.deb_signing.result == 'failure' || needs.api_verification.result == 'failure' + run: | + echo "RESULT=failure" >> $GITHUB_ENV + echo "MSG=Package build failed" >> $GITHUB_ENV + + - name: Set final status + run: | + gh api \ + --method POST \ + -H "Accept: application/vnd.github+json" \ + /repos/$GITHUB_REPOSITORY/statuses/${{ needs.sourcepackage.outputs.GIT_SHA }} \ + -f state="$RESULT" \ + -f target_url="$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" \ + -f description="$MSG" \ + -f context="$STATUS_CONTEXT" diff --git a/HISTORY.md b/HISTORY.md index 6e60ae0f60..39cc01d6ee 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,69 @@ # Keyman Version History +## 17.0.49 alpha 2023-02-15 + +* feat(linux): Pass PR# in the event type (#8221) +* feat(linux): Implement uploading of packages in packaging GHA (#8223) +* fix(linux): Fix GHA package build (#8225) +* fix(linux): Another fix for GHA package build (#8228) + +## 17.0.48 alpha 2023-02-14 + +* fix(developer): Select BCP47 Code dialog inconsistencies (#8179) +* chore(common): automatically apply _builder_check_color (#8197) +* docs(linux): Update packaging documentation (#8202) +* chore(common): Report status if no platform needs build (#8210) +* chore(linux): Exclude autopkg tests on s390x (#8218) +* fix(linux): Fix path to symbols file in packaging GHA (#8209) + +## 17.0.47 alpha 2023-02-10 + +* fix(linux): Fix autopkgtests (#8201) +* fix(linux): Fix Verify-API step of GHA (#8199) + +## 17.0.46 alpha 2023-02-09 + +* fix(windows): add remove lang id uses correct keyboard id (#8186) +* chore(common): add `builder_term` function (#8187) +* chore(common): builder internal dependencies (#8188) +* chore(linux): Update changelog from Debian (#8192) +* feat(linux): Add debian packaging GHA (#7911) + +## 17.0.45 alpha 2023-02-08 + +* chore(ios): update certificate (#8176) +* fix(linux): Fix autopkgtests (#8181) +* chore(common): Cleanup Kannada locale (#8182) +* chore(windows): Fix Portuguese UI language name (#8184) + +## 17.0.44 alpha 2023-02-07 + +* chore(linux): Set test-helper script executable (#8178) +* chore(linux): Update debian changelog (#8156) + +## 17.0.43 alpha 2023-02-06 + +* chore(linux): Build with meson instead of autotools ️ (#8111) + +## 17.0.42 alpha 2023-02-03 + +* chore(deps): bump http-cache-semantics from 4.1.0 to 4.1.1 (#8144) +* feat(developer): check for duplicated language codes in package editor and compiler (#8151) +* chore: Fail TC build if triggering Jenkins build fails (#8152) +* chore(linux): Fix lintian warnings (#8154) +* chore(core): Update meson version (#7882) +* refactor(android/engine): Consolidate Keyboard picker intent (#8163) + +## 17.0.41 alpha 2023-02-02 + +* chore(web): main web build & test script rework to our common script format + nomenclature (#7474) +* change(web): conversion to standard filesystem layout: source -> src, intermediate + release -> build (#7513) +* change(web): conversion to standard filesystem layout: testing -> src/test/manual, unit_tests -> src/test/auto (#7515) +* change(web): conversion to standard filesystem layout: tools -> src/tools (#7556) +* chore(web): updates build product references, extracts CI test-build scripts (#7831) +* feat(common): TS-based sourcemap remapping tool (#7894) +* feat(web): implements shell scripting for CI release-build configurations (#8001) + ## 17.0.40 alpha 2023-02-01 * chore(developer): kmcmpdll debug src path (#8127) diff --git a/VERSION.md b/VERSION.md index 2a6f41d071..b38cb8f352 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -17.0.41 \ No newline at end of file +17.0.50 \ No newline at end of file diff --git a/android/KMAPro/kMAPro/src/main/res/values-kn-rIN/strings.xml b/android/KMAPro/kMAPro/src/main/res/values-kn-rIN/strings.xml index a3e30849d1..21ec6f216b 100644 --- a/android/KMAPro/kMAPro/src/main/res/values-kn-rIN/strings.xml +++ b/android/KMAPro/kMAPro/src/main/res/values-kn-rIN/strings.xml @@ -36,7 +36,7 @@ \nಎಲ್ಲಾ ಪಠ್ಯವನ್ನು ತೆರವುಗೊಳಿಸಲಾಗುತ್ತದೆ\n - ಶುರುಮಾಡಿ + ಪ್ರಾರಂಭಿಕ ಪರದೆ ನಿಮ್ಮ ಭಾಷೆಗೆ ಕೀಲಿಮಣೆಯನ್ನು ಸೇರಿಸಿ diff --git a/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java b/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java index 13a2cc1e42..b8e115f3e8 100644 --- a/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java +++ b/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java @@ -1905,21 +1905,22 @@ public final class KMManager { } public static void showKeyboardPicker(Context context, KeyboardType kbType) { - if (kbType == KeyboardType.KEYBOARD_TYPE_INAPP) { - Intent i = new Intent(context, KeyboardPickerActivity.class); - i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); - i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - i.putExtra(KMKey_DisplayKeyboardSwitcher, false); - context.startActivity(i); - } else if (kbType == KeyboardType.KEYBOARD_TYPE_SYSTEM) { - Intent i = new Intent(context, KeyboardPickerActivity.class); - i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); + if (kbType == KeyboardType.KEYBOARD_TYPE_UNDEFINED) { + KMLog.LogError(TAG, String.format("showKeyboardPicker with invalid %s", kbType.toString())); + return; + } + + Intent i = new Intent(context, KeyboardPickerActivity.class); + i.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT); // Replaces FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET + i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // Required to call startActivity() from outside of an Activity context + + if (kbType == KeyboardType.KEYBOARD_TYPE_SYSTEM) { i.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); - i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - i.putExtra(KMKey_DisplayKeyboardSwitcher, true); - context.startActivity(i); } + + i.putExtra(KMKey_DisplayKeyboardSwitcher, kbType == KeyboardType.KEYBOARD_TYPE_SYSTEM); + context.startActivity(i); } public static void setKeyboardPickerFont(Typeface typeface) { diff --git a/common/models/templates/package.json b/common/models/templates/package.json index fdaf2288e1..f7b2e1ff4f 100644 --- a/common/models/templates/package.json +++ b/common/models/templates/package.json @@ -48,7 +48,7 @@ "@types/node": "^14.0.4", "chai": "^4.3.4", "mocha": "^10.0.0", - "typescript": "^4.5.4" + "typescript": "^4.9.5" }, "dependencies": { "@keymanapp/keyman-version": "*", diff --git a/common/models/types/package.json b/common/models/types/package.json index 9cdff83231..c3005a8eb5 100644 --- a/common/models/types/package.json +++ b/common/models/types/package.json @@ -29,7 +29,7 @@ }, "homepage": "https://github.com/keymanapp/keyman/tree/master/common/models/types#readme", "devDependencies": { - "typescript": "^4.5.4" + "typescript": "^4.9.5" }, "files": [ "README.md", diff --git a/common/models/wordbreakers/package.json b/common/models/wordbreakers/package.json index 50b53275ed..ea8371e359 100644 --- a/common/models/wordbreakers/package.json +++ b/common/models/wordbreakers/package.json @@ -47,8 +47,8 @@ "@types/mocha": "^7.0.2", "chai": "^4.3.4", "mocha": "^10.0.0", - "ts-node": "^9.1.1", - "typescript": "^4.5.4" + "ts-node": "^10.9.1", + "typescript": "^4.9.5" }, "type": "module", "dependencies": { diff --git a/common/predictive-text/build.sh b/common/predictive-text/build.sh index 06900481ea..046d556b14 100755 --- a/common/predictive-text/build.sh +++ b/common/predictive-text/build.sh @@ -22,8 +22,6 @@ cd "$(dirname "$THIS_SCRIPT")" ################################ Main script ################################ -builder_check_color "$@" - # "@../models/types" \ # is just a .d.ts, so there's nothing to actually BUILD. builder_describe "Builds the lm-layer module" \ @@ -35,7 +33,7 @@ builder_describe "Builds the lm-layer module" \ "configure" \ "build" \ "test" \ - "--ci Sets ${BUILDER_TERM_START}test${BUILDER_TERM_END} action to use CI-based test configurations & reporting" + "--ci Sets $(builder_term test) action to use CI-based test configurations & reporting" builder_describe_outputs \ configure /node_modules \ diff --git a/common/predictive-text/package.json b/common/predictive-text/package.json index 716a4d5dd1..7459aada03 100644 --- a/common/predictive-text/package.json +++ b/common/predictive-text/package.json @@ -41,8 +41,8 @@ "mocha": "^10.0.0", "mocha-teamcity-reporter": "^4.0.0", "sinon": "^7.1.1", - "ts-node": "^9.1.1", - "typescript": "^4.5.4" + "ts-node": "^10.9.1", + "typescript": "^4.9.5" }, "dependencies": { "@keymanapp/models-templates": "*", diff --git a/common/predictive-text/unit_tests/test.sh b/common/predictive-text/unit_tests/test.sh index 69cdc62ede..77adb1bd58 100755 --- a/common/predictive-text/unit_tests/test.sh +++ b/common/predictive-text/unit_tests/test.sh @@ -43,7 +43,7 @@ if builder_start_action test:libraries; then # addition to fair bit of `pushd` and `popd`. pushd "$KEYMAN_ROOT/common/models/wordbreakers" echo - echo "### Running ${BUILDER_TERM_START}common/models/wordbreaker${BUILDER_TERM_END} tests" + echo "### Running $(builder_term common/models/wordbreakers) tests" # NPM doesn't seem to parse the post `--` part if specified via script variable. # So... a simple if-else will do the job for now. if builder_has_option --ci; then @@ -55,7 +55,7 @@ if builder_start_action test:libraries; then pushd "$KEYMAN_ROOT/common/models/templates" echo - echo "### Running ${BUILDER_TERM_START}common/models/templates${BUILDER_TERM_END} tests" + echo "### Running $builder_term common/models/templates) tests" if builder_has_option --ci; then npm run test -- -reporter mocha-teamcity-reporter else @@ -65,7 +65,7 @@ if builder_start_action test:libraries; then pushd "$KEYMAN_ROOT/common/models/types" echo - echo "### Running ${BUILDER_TERM_START}common/models/types${BUILDER_TERM_END} tests" + echo "### Running $builder_term common/models/types) tests" # Is not mocha-based; it's TSC-based instead, as we're just ensuring that the .d.ts # file is a proper TS declaration file. npm run test @@ -103,7 +103,7 @@ if [[ $VERSION_ENVIRONMENT == test ]] && builder_has_action test :browser; then if builder_pull_get_details; then if ! ([[ $builder_pull_title =~ \(web\) ]] || builder_pull_has_label test-browserstack); then - echo "Auto-skipping ${BUILDER_TERM_START}test:browser${BUILDER_TERM_END} for unrelated CI test build" + echo "Auto-skipping $builder_term test:browser) for unrelated CI test build" exit 0 fi fi @@ -129,7 +129,7 @@ if builder_start_action test:browser; then KARMA_INFO_LEVEL="--log-level=debug" if builder_has_option --debug; then - echo "${BUILDER_TERM_START}--ci${BUILDER_TERM_END} option set; ignoring ${BUILDER_TERM_START}--debug${BUILDER_TERM_END} option" + echo "$(builder_term --ci) option set; ignoring $(builder_term --debug) option" fi else KARMA_CONFIG="manual.conf.cjs" diff --git a/common/tools/sourcemap-path-remapper/package.json b/common/tools/sourcemap-path-remapper/package.json index 0618260011..2a46897739 100644 --- a/common/tools/sourcemap-path-remapper/package.json +++ b/common/tools/sourcemap-path-remapper/package.json @@ -23,8 +23,8 @@ "mocha": "^10.0.0", "mocha-teamcity-reporter": "^4.0.0", "sinon": "^7.1.1", - "ts-node": "^9.1.1", - "typescript": "^4.5.4" + "ts-node": "^10.9.1", + "typescript": "^4.9.5" }, "dependencies": { "convert-source-map": "^2.0.0" diff --git a/common/web/input-processor/build.sh b/common/web/input-processor/build.sh index 1095714026..0887905076 100755 --- a/common/web/input-processor/build.sh +++ b/common/web/input-processor/build.sh @@ -16,8 +16,6 @@ cd "$(dirname "$THIS_SCRIPT")" ################################ Main script ################################ -builder_check_color "$@" - # TODO: for predictive-text, we only need :headless, perhaps we should be splitting modules? # TODO: remove :tools once kmlmc is a dependency for test:module @@ -31,7 +29,7 @@ builder_describe "Builds the standalone, headless form of Keyman Engine for Web' "test" \ ":module A headless, Node-oriented version of the module useful for unit tests" \ ":tools Related tools useful for development and testing of this module" \ - "--ci Sets ${BUILDER_TERM_START}test${BUILDER_TERM_END} action to use CI-based test configurations & reporting" + "--ci Sets $(builder_term test) action to use CI-based test configurations & reporting" builder_describe_outputs \ configure /node_modules \ diff --git a/common/web/input-processor/package.json b/common/web/input-processor/package.json index 68aaf5933c..f1bf8b0260 100644 --- a/common/web/input-processor/package.json +++ b/common/web/input-processor/package.json @@ -23,8 +23,8 @@ "chai": "^4.3.4", "mocha": "^10.0.0", "mocha-teamcity-reporter": "^4.0.0", - "ts-node": "^9.1.1", - "typescript": "^4.5.4" + "ts-node": "^10.9.1", + "typescript": "^4.9.5" }, "scripts": { "tsc": "tsc", diff --git a/common/web/keyboard-processor/build.sh b/common/web/keyboard-processor/build.sh index 0fffa4cd47..712ae690c6 100755 --- a/common/web/keyboard-processor/build.sh +++ b/common/web/keyboard-processor/build.sh @@ -17,10 +17,6 @@ cd "$THIS_SCRIPT_PATH" ################################ Main script ################################ -# Ensures color var use in `builder_describe`'s argument respects the specified -# --color/--no-color option. -builder_check_color "$@" - builder_describe \ "Compiles the web-oriented utility function module." \ "@../recorder test" \ @@ -30,7 +26,7 @@ builder_describe \ clean \ build \ test \ - "--ci For use with action ${BUILDER_TERM_START}test${BUILDER_TERM_END} - emits CI-friendly test reports" + "--ci For use with action $(builder_term test) - emits CI-friendly test reports" builder_describe_outputs \ configure /node_modules \ diff --git a/common/web/keyboard-processor/package.json b/common/web/keyboard-processor/package.json index 47c5851fe6..296fbacc3e 100644 --- a/common/web/keyboard-processor/package.json +++ b/common/web/keyboard-processor/package.json @@ -21,8 +21,8 @@ "chai": "^4.3.4", "mocha": "^10.0.0", "mocha-teamcity-reporter": "^4.0.0", - "ts-node": "^9.1.1", - "typescript": "^4.5.4" + "ts-node": "^10.9.1", + "typescript": "^4.9.5" }, "scripts": { "tsc": "tsc", diff --git a/common/web/keyman-version/package.json b/common/web/keyman-version/package.json index fdb1b0c34f..2a384d1319 100644 --- a/common/web/keyman-version/package.json +++ b/common/web/keyman-version/package.json @@ -10,6 +10,6 @@ "license": "MIT", "type": "module", "devDependencies": { - "typescript": "^4.5.4" + "typescript": "^4.9.5" } } diff --git a/common/web/lm-message-types/package.json b/common/web/lm-message-types/package.json index 1941d69ab3..01e880c9b2 100644 --- a/common/web/lm-message-types/package.json +++ b/common/web/lm-message-types/package.json @@ -7,7 +7,7 @@ }, "license": "MIT", "devDependencies": { - "typescript": "^4.5.4" + "typescript": "^4.9.5" }, "files": [ "message.d.ts" diff --git a/common/web/lm-worker/package.json b/common/web/lm-worker/package.json index 27b9e61468..2a73baf5bd 100644 --- a/common/web/lm-worker/package.json +++ b/common/web/lm-worker/package.json @@ -35,8 +35,8 @@ "mocha": "^10.0.0", "mocha-teamcity-reporter": "^4.0.0", "sinon": "^7.1.1", - "ts-node": "^9.1.1", - "typescript": "^4.5.4" + "ts-node": "^10.9.1", + "typescript": "^4.9.5" }, "dependencies": { "@keymanapp/keyman-version": "*", diff --git a/common/web/recorder/package.json b/common/web/recorder/package.json index 5fb8b9ba85..ae7853695a 100644 --- a/common/web/recorder/package.json +++ b/common/web/recorder/package.json @@ -25,6 +25,6 @@ "@types/node": "^11.9.4" }, "devDependencies": { - "typescript": "^4.5.4" + "typescript": "^4.9.5" } } diff --git a/common/web/sentry-manager/package.json b/common/web/sentry-manager/package.json index 2170a6a06c..dd3ccdbaba 100644 --- a/common/web/sentry-manager/package.json +++ b/common/web/sentry-manager/package.json @@ -16,7 +16,7 @@ }, "homepage": "https://github.com/keymanapp/keyman#readme", "devDependencies": { - "typescript": "^4.5.4" + "typescript": "^4.9.5" }, "dependencies": { "@keymanapp/keyman-version": "*", diff --git a/common/web/utils/package.json b/common/web/utils/package.json index cb71a917ef..b2236cc36d 100644 --- a/common/web/utils/package.json +++ b/common/web/utils/package.json @@ -26,7 +26,7 @@ "mocha": "^10.0.0", "mocha-teamcity-reporter": "^4.0.0", "@types/node": "^14.0.5", - "typescript": "^4.5.4" + "typescript": "^4.9.5" }, "type": "module", "paths": { diff --git a/common/windows/delphi/general/BCP47Tag.pas b/common/windows/delphi/general/BCP47Tag.pas index 4da813ec43..43a6f142cc 100644 --- a/common/windows/delphi/general/BCP47Tag.pas +++ b/common/windows/delphi/general/BCP47Tag.pas @@ -124,7 +124,20 @@ var begin if not FIsValid and FIsValidated then begin - msg := '''' + OriginalTag + ''' is not a valid BCP 47 tag'; + if OriginalTag = '' then + begin + msg := 'A valid BCP 47 tag must contain at least a language subtag'; + end + else + begin + msg := '''' + OriginalTag + ''' is not a valid BCP 47 tag'; + end; + Exit(False); + end; + + if Tag = '' then + begin + msg := 'A valid BCP 47 tag must contain at least a language subtag'; Exit(False); end; diff --git a/common/windows/delphi/packages/PackageInfo.pas b/common/windows/delphi/packages/PackageInfo.pas index 81e633fe53..dd4dbcd110 100644 --- a/common/windows/delphi/packages/PackageInfo.pas +++ b/common/windows/delphi/packages/PackageInfo.pas @@ -337,6 +337,8 @@ type procedure SaveJSON(ARoot: TJSONObject); virtual; procedure LoadXML(ARoot: IXMLNode); virtual; procedure SaveXML(ARoot: IXMLNode); virtual; + function ContainsID(const id: string): Boolean; + function IndexOfID(const id: string): Integer; end; TPackageLexicalModel = class(TPackageBaseObject) @@ -2262,6 +2264,21 @@ end; { TPackageKeyboardLanguageList } +function TPackageKeyboardLanguageList.ContainsID(const id: string): Boolean; +begin + Result := IndexOfID(id) >= 0; +end; + +function TPackageKeyboardLanguageList.IndexOfID(const id: string): Integer; +var + i: Integer; +begin + for i := 0 to Count - 1 do + if SameText(Items[i].ID, id) then + Exit(i); + Result := -1; +end; + procedure TPackageKeyboardLanguageList.LoadJSON(ARoot: TJSONObject); var j: Integer; diff --git a/core/meson.build b/core/meson.build index cad35decec..5f530aae3d 100644 --- a/core/meson.build +++ b/core/meson.build @@ -12,19 +12,14 @@ project('keyboardprocessor', 'cpp', 'c', 'cpp_std=c++14', 'b_vscrt=static_from_buildtype', 'warning_level=2'], - meson_version: '>=0.45.0') + meson_version: '>=0.53.0') compiler = meson.get_compiler('cpp') lib_version = '0.0.0' -if meson.version().version_compare('>=0.46') - py = import('python') - python = py.find_installation() -else - py = import('python3') - python = py.find_python() -endif +py = import('python') +python = py.find_installation() # Once we can assume meson 0.60 we can delete this # (https://mesonbuild.com/Release-notes-for-0-60-0.html#msvc-compiler-now-assumes-utf8-source-code-by-default) diff --git a/core/src/meson.build b/core/src/meson.build index cbf2f8c6da..79f06a9706 100644 --- a/core/src/meson.build +++ b/core/src/meson.build @@ -58,18 +58,7 @@ if compiler.get_id() == 'emscripten' links = [] endif -lib = library('kmnkbp0', - 'option.cpp', - 'keyboard.cpp', - 'state.cpp', - 'km_kbp_context_api.cpp', - 'km_kbp_keyboard_api.cpp', - 'km_kbp_options_api.cpp', - 'km_kbp_state_api.cpp', - 'km_kbp_debug_api.cpp', - 'km_kbp_processevent_api.cpp', - 'jsonpp.cpp', - 'mock/mock_processor.cpp', +kmx_files = files( 'kmx/kmx_consts.cpp', 'kmx/kmx_processevent.cpp', 'kmx/kmx_actions.cpp', @@ -84,14 +73,58 @@ lib = library('kmnkbp0', 'kmx/kmx_options.cpp', 'kmx/kmx_processor.cpp', 'kmx/kmx_xstring.cpp', +) + +api_files = files( + 'km_kbp_context_api.cpp', + 'km_kbp_keyboard_api.cpp', + 'km_kbp_options_api.cpp', + 'km_kbp_state_api.cpp', + 'km_kbp_debug_api.cpp', + 'km_kbp_processevent_api.cpp', +) + +core_files = files( + 'option.cpp', + 'keyboard.cpp', + 'state.cpp', + 'jsonpp.cpp', 'utfcodec.cpp', +) + +mock_files = files( + 'mock/mock_processor.cpp', +) + +lib = library('kmnkbp0', + api_files, + core_files, + kmx_files, + mock_files, version_res, cpp_args: defns + warns + flags, link_args: links, version: lib_version, include_directories: inc, + pic: true, install: true) +if host_machine.system() == 'linux' + # on Linux we need the static lib for ibus-keyman tests + static_library('kmnkbp0-static', + api_files, + core_files, + kmx_files, + mock_files, + version_res, + cpp_args: defns + warns + flags, + link_args: links, + include_directories: inc, + pic: true, + install: false + ) +endif + headerdirs = [ '.', 'keyman' ] # subdirectories of ${prefix}/include to add to header path kmnkbp = declare_dependency(link_with: lib, include_directories: inc) diff --git a/core/tests/meson.build b/core/tests/meson.build index 3b33c1ef23..be58e6975c 100644 --- a/core/tests/meson.build +++ b/core/tests/meson.build @@ -8,7 +8,7 @@ # Note: this version of cmpfiles ignores line endings, which is better for platform independence cmpfiles = ['-c', 'import sys; a = open(sys.argv[1], \'r\').read(); b = open(sys.argv[2], \'r\').read(); exit(not (a==b))'] -stnds = join_paths(meson.source_root(), 'tests', 'standards') +stnds = join_paths(meson.current_source_dir(), 'standards') libsrc = include_directories(join_paths('../', 'src')) diff --git a/core/tests/unit/kmx/meson.build b/core/tests/unit/kmx/meson.build index 63188c764a..c347b2e8fd 100644 --- a/core/tests/unit/kmx/meson.build +++ b/core/tests/unit/kmx/meson.build @@ -25,14 +25,28 @@ else test_path = meson.current_build_dir() endif +coretest_files = files( + 'kmx_test_source.cpp', +) + kmx = executable('kmx', 'kmx.cpp', - 'kmx_test_source.cpp', + coretest_files, cpp_args: defns + warns, include_directories: [inc, libsrc], link_args: links + tests_flags, objects: lib.extract_all_objects()) +test_lib = static_library('kmnkbp-tests', + coretest_files, + cpp_args: defns + warns + flags, + include_directories: [inc, libsrc], + link_args: links + tests_flags, + objects: lib.extract_all_objects(), + pic: true, + install: false +) + tests = [ '000 - null keyboard', '001 - basic input UnicodeI', @@ -87,7 +101,7 @@ tests = [ ] if build_machine.system() == 'windows' - kmcomp = find_program(join_paths(meson.source_root(),'..','..','..','windows','bin','developer','kmcomp.exe'), 'kmcomp.exe', required: false) + kmcomp = find_program(join_paths(meson.current_source_dir(),'..','..','..','..','windows','bin','developer','kmcomp.exe'), 'kmcomp.exe', required: false) kmcomp_cmd = [kmcomp] copy_cmd = [find_program('cmd.exe', required: true), '/c', 'copy'] cat_cmd = [find_program('cmd.exe', required: true), '/c', 'type'] diff --git a/crowdin.yml b/crowdin.yml index 704e88bddf..f8b9785bc3 100644 --- a/crowdin.yml +++ b/crowdin.yml @@ -59,6 +59,7 @@ files: locale: de: de fr: fr + kn: kn - source: /windows/src/desktop/setup/locale/en/strings.xml dest: /windows/setup/strings.xml @@ -68,6 +69,7 @@ files: locale: de: de fr: fr + kn: kn # iOS files diff --git a/developer/src/common/delphi/compiler/CompilePackage.pas b/developer/src/common/delphi/compiler/CompilePackage.pas index 1e711169dd..c7c5e07123 100644 --- a/developer/src/common/delphi/compiler/CompilePackage.pas +++ b/developer/src/common/delphi/compiler/CompilePackage.pas @@ -27,7 +27,9 @@ unit CompilePackage; interface uses - kpsfile, kmpinffile, PackageInfo, + kpsfile, + kmpinffile, + PackageInfo, Keyman.Developer.System.Project.ProjectLog; function DoCompilePackage(pack: TKPSFile; AMessageEvent: TCompilePackageMessageEvent; ASilent, ACheckFilenameConventions: Boolean; const AOutputFileName: string): Boolean; // I4688 @@ -37,6 +39,7 @@ implementation uses Winapi.Windows, System.Classes, + System.Generics.Collections, System.SysUtils, System.IniFiles, System.Zip, @@ -85,6 +88,7 @@ type procedure CheckKeyboardLanguages; procedure CheckFilenameConventions; function CheckLexicalModels: Boolean; + procedure CheckForDuplicatedLanguages(const resourceType, id: string; languages: TPackageKeyboardLanguageList); end; function DoCompilePackage(pack: TKPSFile; AMessageEvent: TCompilePackageMessageEvent; ASilent, ACheckFilenameConventions: Boolean; const AOutputFileName: string): Boolean; // I4688 @@ -141,6 +145,8 @@ begin end; function TCompilePackage.CheckLexicalModels: Boolean; +var + model: TPackageLexicalModel; begin if pack.LexicalModels.Count > 0 then begin @@ -151,6 +157,12 @@ begin end; end; + for model in pack.LexicalModels do + begin + CheckForDuplicatedLanguages('model', model.id, model.Languages); + end; + + Exit(True); end; @@ -487,6 +499,7 @@ end; const SKKeyboardPackageLanguageNonCanonical = 'The keyboard %0:s has a non-canonical language tag "%1:s" (%2:s), should be "%3:s".'; SKKeyboardShouldHaveAtLeastOneLanguage = 'The keyboard %0:s has no language tags. It should have at least one language tag.'; + SKPackageShouldNotRepeatLanguages = 'The %0:s %1:s has a repeated language "%2:s".'; procedure TCompilePackage.CheckKeyboardLanguages; var @@ -496,6 +509,30 @@ begin begin if k.Languages.Count = 0 then WriteMessage(plsWarning, Format(SKKeyboardShouldHaveAtLeastOneLanguage, [k.ID])); + CheckForDuplicatedLanguages('keyboard', k.ID, k.Languages); + end; +end; + +procedure TCompilePackage.CheckForDuplicatedLanguages(const resourceType, id: string; languages: TPackageKeyboardLanguageList); +var + tags: TDictionary; + lang: TPackageKeyboardLanguage; +begin + tags := TDictionary.Create; + try + for lang in languages do + begin + if tags.ContainsKey(lang.ID.ToLower) then + begin + WriteMessage(plsWarning, Format(SKPackageShouldNotRepeatLanguages, [resourceType, id, lang.ID])); + end + else + begin + tags.Add(lang.ID.ToLower, 0); + end; + end; + finally + tags.Free; end; end; diff --git a/developer/src/kmlmc/package.json b/developer/src/kmlmc/package.json index a126590840..c6ab80198f 100644 --- a/developer/src/kmlmc/package.json +++ b/developer/src/kmlmc/package.json @@ -39,7 +39,7 @@ "@keymanapp/models-types": "*", "@keymanapp/keyman-version": "*", "commander": "^3.0.0", - "typescript": "^4.5.4", + "typescript": "^4.9.5", "xml2js": "^0.4.19" }, "devDependencies": { @@ -53,7 +53,7 @@ "chalk": "^2.4.2", "jszip": "^3.7.0", "mocha": "^10.0.0", - "ts-node": "^9.1.1" + "ts-node": "^10.9.1" }, "mocha": { "spec": "dist-tests/**/test-*.js" diff --git a/developer/src/server/package.json b/developer/src/server/package.json index 16898edaeb..dd779db1a4 100644 --- a/developer/src/server/package.json +++ b/developer/src/server/package.json @@ -35,9 +35,9 @@ "chai": "^4.3.4", "copyfiles": "^2.4.1", "mocha": "^10.0.0", - "ts-node": "^10.4.0", + "ts-node": "^10.9.1", "tsc-watch": "^4.5.0", - "typescript": "^4.5.4" + "typescript": "^4.9.5" }, "mocha": { "require": "ts-node/register", diff --git a/developer/src/server/tsconfig.json b/developer/src/server/tsconfig.json index 14932564aa..280b535dd9 100644 --- a/developer/src/server/tsconfig.json +++ b/developer/src/server/tsconfig.json @@ -3,7 +3,7 @@ "compilerOptions": { "module": "commonjs", - "target": "es2017", + "target": "es2022", "moduleResolution": "node", "sourceMap": true, "outDir": "dist/", @@ -15,7 +15,8 @@ "noImplicitAny": true, "strictBindCallApply": true, "strictFunctionTypes": true, - "noUnusedLocals": true + "noUnusedLocals": true, + "lib": ["es2022"] }, "include": [ "src/**/*.ts" diff --git a/developer/src/tike/child/UfrmPackageEditor.pas b/developer/src/tike/child/UfrmPackageEditor.pas index 22b94a4835..4b36d67170 100644 --- a/developer/src/tike/child/UfrmPackageEditor.pas +++ b/developer/src/tike/child/UfrmPackageEditor.pas @@ -314,8 +314,7 @@ type procedure EnableLexicalModelTabControls; procedure ShowEditLanguageForm(grid: TStringGrid; langs: TPackageKeyboardLanguageList; lang: TPackageKeyboardLanguage); - function ShowAddLanguageForm(grid: TStringGrid; - langs: TPackageKeyboardLanguageList): Boolean; + procedure ShowAddLanguageForm(grid: TStringGrid; langs: TPackageKeyboardLanguageList); procedure RefreshLexicalModelList; procedure UpdateQRCode; @@ -1624,6 +1623,8 @@ procedure TfrmPackageEditor.EnableControls; begin EnableStartMenuControls; EnableDetailsTabControls; + EnableKeyboardTabControls; + EnableLexicalModelTabControls; EnableCompileTabControls; end; @@ -1686,35 +1687,16 @@ end; procedure TfrmPackageEditor.cmdKeyboardAddLanguageClick(Sender: TObject); var k: TPackageKeyboard; - lang: TPackageKeyboardLanguage; - frm: TfrmSelectBCP47Language; begin k := SelectedKeyboard; Assert(Assigned(k)); - - frm := TfrmSelectBCP47Language.Create(Application.MainForm); - try - if frm.ShowModal = mrOk then - begin - lang := TPackageKeyboardLanguage.Create(pack); - lang.ID := frm.LanguageID; - lang.Name := frm.LanguageName; - k.Languages.Add(lang); - RefreshKeyboardLanguageList(k); - gridKeyboardLanguages.Row := gridKeyboardLanguages.RowCount - 1; - gridKeyboardLanguagesClick(gridKeyboardLanguages); - Modified := True; - end; - finally - frm.Free; - end; + ShowAddLanguageForm(gridKeyboardLanguages, k.Languages); end; procedure TfrmPackageEditor.cmdKeyboardEditLanguageClick(Sender: TObject); var k: TPackageKeyboard; lang: TPackageKeyboardLanguage; - frm: TfrmSelectBCP47Language; begin k := SelectedKeyboard; Assert(Assigned(k)); @@ -1722,20 +1704,7 @@ begin lang := SelectedKeyboardLanguage; Assert(Assigned(lang)); - frm := TfrmSelectBCP47Language.Create(Application.MainForm); - try - frm.LanguageID := lang.ID; - frm.LanguageName := lang.Name; - if frm.ShowModal = mrOk then - begin - lang.ID := frm.LanguageID; - lang.Name := frm.LanguageName; - RefreshKeyboardLanguageList(k); - Modified := True; - end; - finally - frm.Free; - end; + ShowEditLanguageForm(gridKeyboardLanguages, k.Languages, lang); end; procedure TfrmPackageEditor.cmdKeyboardRemoveLanguageClick(Sender: TObject); @@ -1819,16 +1788,25 @@ begin end; end; -function TfrmPackageEditor.ShowAddLanguageForm(grid: TStringGrid; langs: TPackageKeyboardLanguageList): Boolean; +procedure TfrmPackageEditor.ShowAddLanguageForm(grid: TStringGrid; langs: TPackageKeyboardLanguageList); var lang: TPackageKeyboardLanguage; frm: TfrmSelectBCP47Language; + n: Integer; begin - Result := False; frm := TfrmSelectBCP47Language.Create(Application.MainForm); try if frm.ShowModal = mrOk then begin + n := langs.IndexOfID(frm.LanguageID); + if n >= 0 then + begin + // Duplicate - we won't re-add the item, just select the existing item + grid.Row := n + 1; + EnableControls; + Exit; + end; + lang := TPackageKeyboardLanguage.Create(pack); lang.ID := frm.LanguageID; lang.Name := frm.LanguageName; @@ -1836,7 +1814,7 @@ begin RefreshLanguageList(grid, langs); grid.Row := grid.RowCount - 1; Modified := True; - Result := True; + EnableControls; end; finally frm.Free; @@ -1846,6 +1824,7 @@ end; procedure TfrmPackageEditor.ShowEditLanguageForm(grid: TStringGrid; langs: TPackageKeyboardLanguageList; lang: TPackageKeyboardLanguage); var frm: TfrmSelectBCP47Language; + n: Integer; begin frm := TfrmSelectBCP47Language.Create(Application.MainForm); try @@ -1853,9 +1832,30 @@ begin frm.LanguageName := lang.Name; if frm.ShowModal = mrOk then begin + if not SameText(frm.LanguageID, lang.ID) then + begin + // If the id has changed, check for duplicates + n := langs.IndexOfID(frm.LanguageID); + if n >= 0 then + begin + // Duplicate - we will delete the edited one and select the existing + // one + langs.Remove(lang); + RefreshLanguageList(grid, langs); + + // The index may have changed, search again + n := langs.IndexOfID(frm.LanguageID); + grid.Row := n + 1; + EnableControls; + Modified := True; + Exit; + end; + end; + lang.ID := frm.LanguageID; lang.Name := frm.LanguageName; RefreshLanguageList(grid, langs); + EnableControls; Modified := True; end; finally @@ -2005,10 +2005,7 @@ var begin lm := SelectedLexicalModel; Assert(Assigned(lm)); - - if ShowAddLanguageForm(gridLexicalModelLanguages, lm.Languages) then - gridLexicalModelLanguagesClick(gridLexicalModelLanguages); - EnableLexicalModelTabControls; + ShowAddLanguageForm(gridLexicalModelLanguages, lm.Languages); end; procedure TfrmPackageEditor.cmdLexicalModelLanguageEditClick(Sender: TObject); diff --git a/developer/src/tike/dialogs/languages/Keyman.Developer.UI.UfrmSelectBCP47Language.pas b/developer/src/tike/dialogs/languages/Keyman.Developer.UI.UfrmSelectBCP47Language.pas index 282f12bc84..9a80f0ffe1 100644 --- a/developer/src/tike/dialogs/languages/Keyman.Developer.UI.UfrmSelectBCP47Language.pas +++ b/developer/src/tike/dialogs/languages/Keyman.Developer.UI.UfrmSelectBCP47Language.pas @@ -55,6 +55,7 @@ type private tag: TBCP47Tag; FCustomLanguageName: Boolean; + procedure EnableControls; function GetLanguageID: string; function GetLanguageName: string; procedure RefreshLanguageName; @@ -106,6 +107,8 @@ begin PopulateComboBoxFromDict(cbLanguageTag, TLanguageCodeUtils.BCP47Languages); PopulateComboBoxFromDict(cbScriptTag, TLanguageCodeUtils.BCP47Scripts); PopulateComboBoxFromDict(cbRegionTag, TLanguageCodeUtils.BCP47Regions); + RefreshLanguageName; + EnableControls; end; procedure TfrmSelectBCP47Language.FormDestroy(Sender: TObject); @@ -144,11 +147,18 @@ procedure TfrmSelectBCP47Language.cmdResetLanguageNameClick(Sender: TObject); begin editLanguageName.Text := LookupLanguageName; FCustomLanguageName := False; + EnableControls; end; procedure TfrmSelectBCP47Language.editLanguageNameChange(Sender: TObject); begin FCustomLanguageName := True; + EnableControls; +end; + +procedure TfrmSelectBCP47Language.EnableControls; +begin + cmdResetLanguageName.Enabled := FCustomLanguageName; end; procedure TfrmSelectBCP47Language.cbLanguageTagChange(Sender: TObject); @@ -175,6 +185,7 @@ begin end; FCustomLanguageName := False; // Always reset when entering a language tag. RefreshLanguageName; + EnableControls; end; procedure TfrmSelectBCP47Language.cbRegionTagChange(Sender: TObject); @@ -213,6 +224,7 @@ begin begin editLanguageName.Text := LookupLanguageName; FCustomLanguageName := False; + EnableControls; end; cmdOK.Enabled := tag.IsValid(True, msg); if not cmdOK.Enabled @@ -228,12 +240,14 @@ begin cbScriptTag.Text := tag.Script; RefreshLanguageName; FCustomLanguageName := editLanguageName.Text <> LookupLanguageName; + EnableControls; end; procedure TfrmSelectBCP47Language.SetLanguageName(const Value: string); begin editLanguageName.Text := Value; FCustomLanguageName := editLanguageName.Text <> LookupLanguageName; + EnableControls; end; end. diff --git a/docs/linux/keyman-config.md b/docs/linux/keyman-config.md index c12db30c94..f050fd96ad 100644 --- a/docs/linux/keyman-config.md +++ b/docs/linux/keyman-config.md @@ -13,7 +13,8 @@ sudo apt install python3-lxml python3-magic python3-numpy python3-qrcode python3 python3-setuptools python3-pip python3-dbus ibus libglib2.0-bin liblocale-gettext-perl ``` -Either `python3-raven` or `python3-sentry-sdk` (>= 1.4) is required as well. On Ubuntu 22.04 and later run: +Either `python3-raven` or `python3-sentry-sdk` (>= 1.4) is required as well. +On Ubuntu 22.04 and later run: ```bash sudo apt install python3-sentry-sdk @@ -34,8 +35,8 @@ or install it with pip: pip3 install sentry-sdk ``` -Run the script `./createkeymandirs.sh` to create the directories for these programs to -install the packages to. +Run the script `./createkeymandirs.sh` to create the directories for these +programs to install the packages to. Also copy and compile the GSettings schema: @@ -65,7 +66,8 @@ To uninstall you can run `sudo make uninstall`. `./km-config` -This displays a configuration panel that shows the currently installed Keyman keyboard packages and can download and install additional keyboards. +This displays a configuration panel that shows the currently installed Keyman +keyboard packages and can download and install additional keyboards. #### Buttons diff --git a/docs/linux/packaging.md b/docs/linux/packaging.md index ac1c268cb7..91154934b4 100644 --- a/docs/linux/packaging.md +++ b/docs/linux/packaging.md @@ -169,38 +169,81 @@ Building packages happen in the [Keyman source tree](https://github.com/keymanap The Keyman [`linux/scripts/jenkins.sh`](https://github.com/keymanapp/keyman/blob/master/linux/scripts/jenkins.sh) -script can be used to create a source package (replace `packageName` with the name of the package, -i.e. one of keyman, kmflcomp, libkmfl, and ibus-kmfl). +script can be used to create a source package. ```bash cd linux -./scripts/jenkins.sh ${packageName} ${DEBSIGNKEY} +./scripts/jenkins.sh keyman ${DEBSIGNKEY} ``` -This creates a source package (`_-1.dsc`) and some `*.tar.?z` files in the source root directory for `keyman`. +This creates a source package (`keyman_-1.dsc`) and some `*.tar.?z` +files in the source root directory for `keyman`. ci-builder-script's [`build-package`](https://github.com/sillsdev/ci-builder-scripts/blob/master/bash/build-package) script creates the binary packages: ```bash -cd linux/${packageName} +cd $KEYMAN_ROOT ~/ci-builder-scripts/bash/build-package \ --dists "focal bionic" --arches "amd64 i386" \ --debkeyid ${DEBSIGNKEY} --build-in-place --no-upload ``` -This will create the binary package `_-1+1_.deb`. +This will create the binary package `keyman_-1+1_.deb`. To speed up package building you might want to limit the build to a single dist (e.g. `--dists "bionic"`) and arch (e.g. `--arches "amd64"`). -After building packages it might be a good idea to clean up the source tree before doing further -work: +After building packages it might be a good idea to clean up the source tree +before doing further work: ```bash git clean -dxf ``` +### Local package builds (Docker) + +It is possible to use the usual Debian/Ubuntu tools to create the package locally. +For someone who only occasionally deals with packaging it might be easier to use +the scripts that run on GitHub actions: + +#### Prerequisites for local package builds with Docker + +You'll have to create the docker image. + +- clone [gha-ubuntu-packaging](https://github.com/sillsdev/gha-ubuntu-packaging) + repo +- create the image: + + ```bash + cd /path/to/gha-ubuntu-packaging + docker build --build-arg DIST=jammy --build-arg PLATFORM=amd64 -t sillsdev/jammy . + ``` + +#### Building packages with Docker + +- create the source package + + ```bash + cd $KEYMAN_ROOT + TIER=$(cat TIER.md) + export TIER + cd linux + ./scripts/deb-packaging.sh source + ``` + + This will create the source package in $KEYMAN_ROOT directory. + +- Create the binary packages with Docker: + + ```bash + cd $KEYMAN_ROOT + docker run -v $(pwd):/source -i -t -w /source --platform=linux/amd64 \ + sillsdev/jammy keyman_*.dsc /source + ``` + + This will create the binary packages in `$KEYMAN_ROOT/artifacts`. + ## Package builds on Launchpad Package builds on Launchpad are triggered manually by running the Keyman script @@ -210,10 +253,10 @@ Package builds on Launchpad are triggered manually by running the Keyman script 1. If you don't have one, create an account at [launchpad.net](https://launchpad.net) 2. Request to join the ["Keyman for Linux"](https://launchpad.net/~keymanapp) team. -3. Create a [GPG](https://help.ubuntu.com/community/GnuPrivacyGuardHowto) key and associate it - to your launchpad account -4. Set the following environment variables in your `~/.profile` or `~/.bashrc` (so you don't have - to set them every time) +3. Create a [GPG](https://help.ubuntu.com/community/GnuPrivacyGuardHowto) key + and associate it to your launchpad account +4. Set the following environment variables in your `~/.profile` or `~/.bashrc` + (so you don't have to set them every time) ```bash export GPGKEY=[key_id] # using the `key_id` of your GPG key @@ -224,8 +267,9 @@ Package builds on Launchpad are triggered manually by running the Keyman script ### Building packages on Launchpad The `launchpad.sh` script downloads the current source code (beta or stable) from -[downloads.keyman.com](https://downloads.keyman.com/linux/stable/), creates a Debian source package -and uploads this to launchpad. Launchpad then rebuilds for the different distros and architectures. +[downloads.keyman.com](https://downloads.keyman.com/linux/stable/), creates a +Debian source package and uploads this to launchpad. Launchpad then rebuilds +for the different distros and architectures. To upload the packages to launchpad, run the following script from the `linux/` directory: @@ -239,14 +283,15 @@ To upload the packages to launchpad, run the following script from the `linux/` - `TIER=""` - alpha, beta, or stable, default from `../TIER.md` - `PROJECT=""` - only upload this package - `DIST=""` - only upload for this distribution -- `PACKAGEVERSION=""` - normally use the default so don't specify it. But if you - change packaging and run another upload you need to increment the number at the end of - `PACKAGEVERSION`. e.g. next one is `1~sil2` then `1~sil3`… +- `PACKAGEVERSION=""` - normally use the default so don't specify + it. But if you change packaging and run another upload you need to increment + the number at the end of `PACKAGEVERSION`. e.g. next one is `1~sil2` then + `1~sil3`… ### Releasing a new version -As part of releasing a new version it might be good to do some local testing first before uploading -to Launchpad: +As part of releasing a new version it might be good to do some local testing +first before uploading to Launchpad: - Run `launchpad.sh` with `UPLOAD="no"` to build the packages - Then install them on a clean VM and make sure no glaring bugs @@ -268,11 +313,12 @@ accepted. The Keyman packages are maintained on the Debian side by the [Debian Input Method Team](https://wiki.debian.org/Teams/IMEPackagingTeam). -**NOTE:** All `changelog` files should contain the exact same entry that was previously -accepted into the Debian repo (plus the new entry for the new update). This means that -when your upload got accepted into Debian (not ) you'll have to -update the `changelog` files to match what got accepted (sometimes the Debian maintainers -will create additional package versions). +**NOTE:** All `changelog` files should contain the exact same entry that was +previously accepted into the Debian repo (plus the new entry for the new +update). This means that when your upload got accepted into Debian (not +) you'll have to update the `changelog` files to match +what got accepted (sometimes the Debian maintainers will create additional +package versions). ### Prerequisites @@ -290,30 +336,41 @@ will create additional package versions). allowed_distributions = .* ``` -- subscribe to the [debian-input-method](debian-input-method@lists.debian.org) mailing list +- subscribe to the [debian-input-method](https://lists.debian.org/debian-input-method/) + mailing list -### Updating and uploading Debian package +### Updating and uploading a stable release to Debian -This is done in several steps: - -1. Download the source code from and create the source package by running - `scripts/debian.sh` -2. sign the source package (you might be able to omit this step if the source package already - got signed with the correct key in the previous step) -3. upload to mentors -4. file a RFS bug (Request For Sponsorship) against the `sponsorship-requests` pseudo-package, - cc'ing `debian-input-method`, or just send an email to the `debian-input-method` list. - -After the package got published in Debian you should update the `linux/debian/changelog` file -with the exact same information that the changelog in Debian has. - -The first three steps above and updating the changelog file can be done by running -the following script: +To do this you can run the `linux/scripts/upload-to-debian.sh` script: ```bash -linux/scripts/upload-to-debian.sh -k $DEBSIGN_KEYID --push +linux/scripts/upload-to-debian.sh -k ${DEBSIGNKEY} --push ``` +This does several steps: + +1. Download the source code from and create the source + package by running `scripts/debian.sh` +2. sign the source package +3. upload to mentors (unless `-n` is passed) +4. Create a branch with the updated `linux/debian/changelog` file based on the + stable branch +5. Cherry-pick the change on a new branch based on `master` +6. If `--push` is passed, the two branches will be pushed to GitHub + +There are a few additional manual required steps: + +1. Create a draft-PR for the change against stable branch +2. Create a draft PR for the cherry-picked change against `master` +3. file a RFS bug (Request For Sponsorship) against the `sponsorship-requests` + pseudo-package, cc'ing `debian-input-method`, or just send an email to the + `debian-input-method` list. + +After the package got published in Debian you can mark the PRs as ready +for review. This should only be done after the package got published in +Debian because the changelog file needs to contain the exact same +information that the changelog in Debian has. + ## Reference See the [Linux readme](https://github.com/keymanapp/keyman/blob/master/docs/linux/README.md) diff --git a/docs/settings/linux/extensions.json b/docs/settings/linux/extensions.json index 55b5ccd393..bd790bd97e 100644 --- a/docs/settings/linux/extensions.json +++ b/docs/settings/linux/extensions.json @@ -9,5 +9,6 @@ "timonwong.shellcheck", "maelvalais.autoconf", "webfreak.debug", + "dawidd6.debian-vscode", ] } diff --git a/ios/engine/KMEI/KeymanEngine/kn.lproj/Localizable.strings b/ios/engine/KMEI/KeymanEngine/kn.lproj/Localizable.strings index 5635331a50..ec935717de 100644 --- a/ios/engine/KMEI/KeymanEngine/kn.lproj/Localizable.strings +++ b/ios/engine/KMEI/KeymanEngine/kn.lproj/Localizable.strings @@ -191,7 +191,7 @@ "menu-settings-show-banner" = "ಬ್ಯಾನರ್ ತೋರಿಸು"; /* Label for the "Get Started" automatic display toggle seen in the Settings menu */ -"menu-settings-startup-get-started" = "ಆರಂಭದಲ್ಲಿ 'Get Started' ತೋರಿಸು"; +"menu-settings-startup-get-started" = "ಆರಂಭದಲ್ಲಿ \"ಪ್ರಾರಂಭಿಕ ಪರದೆ\" ತೋರಿಸು"; /* Title for the main Settings menu */ "menu-settings-title" = "ಕೀಮ್ಯಾನ್ ಸೆಟ್ಟಿಂಗ್‌ಗಳು"; diff --git a/ios/exportAppStore.plist b/ios/exportAppStore.plist index 585577ec2d..6393f3c4cb 100644 --- a/ios/exportAppStore.plist +++ b/ios/exportAppStore.plist @@ -7,9 +7,9 @@ teamID 3YE4W86L3G signingCertificate - 3F2AB892E24387929F51C36E7A03EF33502D341A + 05473BF50CCD4B78B304656FB4D93FDC7EE7ACD0 installerSigningCertificate - 3F2AB892E24387929F51C36E7A03EF33502D341A + 05473BF50CCD4B78B304656FB4D93FDC7EE7ACD0 provisioningProfiles Tavultesoft.Keyman diff --git a/ios/keyman/Keyman/Keyman/kn.lproj/Localizable.strings b/ios/keyman/Keyman/Keyman/kn.lproj/Localizable.strings index e2a5b724cd..fdecb30040 100644 --- a/ios/keyman/Keyman/Keyman/kn.lproj/Localizable.strings +++ b/ios/keyman/Keyman/Keyman/kn.lproj/Localizable.strings @@ -42,7 +42,7 @@ underneath the app's name within the app-specific keyboard menu.) */ "menu-clear-text" = "ಪಠ್ಯವನ್ನು ತೆರವುಗೊಳಿಸಿ"; /* Menu option that displays a list designed to help users start using the app */ -"menu-get-started" = "ಶುರುಮಾಡಿ"; +"menu-get-started" = "ಪ್ರಾರಂಭಿಕ ಪರದೆ"; /* Menu option that displays help for the app */ "menu-help" = "ಮಾಹಿತಿ"; diff --git a/linux/.gitignore b/linux/.gitignore index cf78b5ab49..bb6ad7a741 100644 --- a/linux/.gitignore +++ b/linux/.gitignore @@ -92,7 +92,6 @@ test.sh debianpackage/ *.deb *.ddeb -*.build *.buildinfo *.changes *.tar.xz diff --git a/linux/debian/changelog b/linux/debian/changelog index 90fdff22b0..3eef5dcfa7 100644 --- a/linux/debian/changelog +++ b/linux/debian/changelog @@ -1,8 +1,34 @@ -keyman (15.0.274-2) UNRELEASED; urgency=medium +keyman (16.0.138-4) unstable; urgency=medium + * Team upload + * debian/tests/control: Don't run autopkgtest on s390x + + -- Gunnar Hjalmarsson Sat, 11 Feb 2023 18:39:13 +0100 + +keyman (16.0.138-3) unstable; urgency=medium + + * debian/tests/test-build: Fix autopkgtests + + -- Eberhard Beilharz Thu, 09 Feb 2023 12:18:47 +0100 + +keyman (16.0.138-2) unstable; urgency=medium + + * Team upload + * debian/tests/control: Added missing autopkgtest dependency on + pkg-config (closes: #1030815). + + -- Gunnar Hjalmarsson Tue, 07 Feb 2023 20:34:35 +0100 + +keyman (16.0.138-1) unstable; urgency=medium + + [ Jelmer Vernooij ] * Include packaging path in Vcs-Git header. - -- Jelmer Vernooij Wed, 25 Jan 2023 23:46:54 +0000 + [ Eberhard Beilharz ] + * New upstream release. + * Re-release to Debian + + -- Eberhard Beilharz Thu, 02 Feb 2023 10:53:17 +0100 keyman (15.0.274-1) unstable; urgency=medium diff --git a/linux/debian/control b/linux/debian/control index cd14e2fc40..33f50a90dc 100644 --- a/linux/debian/control +++ b/linux/debian/control @@ -26,7 +26,7 @@ Build-Depends: python3-requests, python3-requests-cache, python3-setuptools, - meson (>= 0.45), + meson (>= 0.53), ninja-build, libgtk-3-dev, libibus-1.0-dev (>= 1.2), @@ -37,8 +37,8 @@ Build-Depends: metacity, gawk, Standards-Version: 4.6.1 -Vcs-Git: https://github.com/keymanapp/keyman.git [linux/debian] -Vcs-Browser: https://github.com/keymanapp/keyman/tree/master/linux/debian +Vcs-Git: https://github.com/keymanapp/keyman.git -b stable-16.0 [linux/debian] +Vcs-Browser: https://github.com/keymanapp/keyman/tree/stable-16.0/linux/debian Homepage: https://www.keyman.com Rules-Requires-Root: binary-targets diff --git a/linux/debian/copyright b/linux/debian/copyright index 5c7c5e9189..292f45bd75 100644 --- a/linux/debian/copyright +++ b/linux/debian/copyright @@ -4,24 +4,24 @@ Upstream-Contact: Keyman team Source: https://github.com/keymanapp/keyman Files: * -Copyright: 2018-2022 SIL International +Copyright: 2018-2023 SIL International License: MIT Files: linux/ibus-keyman/* -Copyright: 2004-2022 SIL International +Copyright: 2004-2023 SIL International License: GPL-2+ Files: linux/ibus-keyman/src/keymanutil.c linux/ibus-keyman/src/keymanutil.h linux/ibus-keyman/src/kmpdetails.c linux/ibus-keyman/src/kmpdetails.h -Copyright: 2009-2022 SIL International +Copyright: 2009-2023 SIL International License: GPL-2+ or MIT Files: linux/ibus-keyman/src/keyman-service.c linux/ibus-keyman/src/keyman-service.h linux/keyman-config/buildtools/help2md -Copyright: 2018-2022 SIL International +Copyright: 2018-2023 SIL International License: GPL-3+ Files: linux/ibus-keyman/config.rpath @@ -49,7 +49,7 @@ Files: linux/ibus-keyman/Makefile.am linux/ibus-keyman/tests/Makefile.am linux/ibus-keyman/tests/Makefile.in Copyright: 1994-2017, Free Software Foundation, Inc. - 2009-2022, SIL International + 2009-2023, SIL International License: GPL-2+ Files: linux/ibus-keyman/m4/gettext.m4 @@ -87,7 +87,7 @@ Copyright: 2008-2010, Peng Huang 2008-2013, Peng Huang 2008-2021, Red Hat, Inc. 2015-2021, Takao Fujiwara - 2021-2022, SIL International + 2021-2023, SIL International License: LGPL-2.1+ Files: linux/keyman-config/buildtools/help2man @@ -97,7 +97,7 @@ License: GPL-3+ Files: debian/com.keyman.config.appdata.xml debian/com.keyman.ibus_keyman.metainfo.xml Copyright: 2019 Daniel Glassey - 2022 SIL International + 2022-2023 SIL International License: MIT License: MIT diff --git a/linux/debian/source/lintian-overrides b/linux/debian/source/lintian-overrides deleted file mode 100644 index 18c8d38d04..0000000000 --- a/linux/debian/source/lintian-overrides +++ /dev/null @@ -1,10 +0,0 @@ -# Lintian overrides -keyman source: very-long-line-length-in-source-file CONTRIBUTING.md * -keyman source: very-long-line-length-in-source-file linux/ibus-keyman/configure * -keyman source: very-long-line-length-in-source-file linux/ibus-keyman/m4/* * -keyman source: very-long-line-length-in-source-file linux/ibus-keyman/tests/Makefile.in * -keyman source: very-long-line-length-in-source-file resources/standards-data/langtags/langtags.json * - -# Looks like /usr/libexec/ibus-engine-keyman is not recognized as binary for the man page, -# so ignore that rule -spare-manual-page diff --git a/linux/debian/tests/README.md b/linux/debian/tests/README.md index 03e4b619b5..9327defb8b 100644 --- a/linux/debian/tests/README.md +++ b/linux/debian/tests/README.md @@ -7,3 +7,28 @@ See and **NOTE:** Runtime test names are only allowed to contain decimal digits, lowercase ASCII letters, plus or minus signs, dots or slashes. + +## Manually run the tests + +- build source and binary packages (see [packaging.md](../../../docs/linux/packaging.md)) + +- install dependencies + + ```bash + sudo apt install autopkgtest qemu-system qemu-utils autodep8 + ``` + +- create environment. Several different options are available, see + [README.running-tests](https://salsa.debian.org/ci-team/autopkgtest/blob/master/doc/README.running-tests.rst) + + For example: + + ```bash + autopkgtest-buildvm-ubuntu-cloud -v --release=jammy + ``` + +- Run tests + + ```bash + autopkgtest -B *.deb keyman_*.dsc -- qemu autopkgtest-jammy-amd64.img + ``` diff --git a/linux/debian/tests/control b/linux/debian/tests/control index 32cf9dac3f..c1164c9c8e 100644 --- a/linux/debian/tests/control +++ b/linux/debian/tests/control @@ -1,2 +1,5 @@ Tests: test-build -Depends: @, build-essential +Depends: @, + build-essential, + pkg-config, +Architecture: amd64 arm64 armel armhf i386 mips64el mipsel ppc64el riscv64 diff --git a/linux/debian/tests/test-build b/linux/debian/tests/test-build index f53496e17a..db0a343849 100644 --- a/linux/debian/tests/test-build +++ b/linux/debian/tests/test-build @@ -7,22 +7,24 @@ set -e WORKDIR=$(mktemp -d) trap "rm -rf $WORKDIR" 0 INT QUIT ABRT PIPE TERM -cd $WORKDIR +cd "$WORKDIR" # Test all include files are available cat < keymantest.c #include -km_kbp_context c; +km_kbp_context* c; EOF -gcc keymantest.c `pkg-config --cflags --libs keyman_kmn_processor` +# shellcheck disable=SC2046 +gcc -c keymantest.c $(pkg-config --cflags --libs keyman_kmn_processor) echo "build 1: OK" # Test pkg-config file - include without path cat < keymantest.c #include -km_kbp_context c; +km_kbp_context* c; EOF -gcc keymantest.c `pkg-config --cflags --libs keyman_kmn_processor` +# shellcheck disable=SC2046 +gcc -c keymantest.c $(pkg-config --cflags --libs keyman_kmn_processor) echo "build 2: OK" diff --git a/linux/ibus-keyman/icons/meson.build b/linux/ibus-keyman/icons/meson.build new file mode 100644 index 0000000000..dce1d23614 --- /dev/null +++ b/linux/ibus-keyman/icons/meson.build @@ -0,0 +1,6 @@ +icons = files('default.png') + +install_data( + icons, + install_dir: '{datadir}/keyman/icons' +) diff --git a/linux/ibus-keyman/meson.build b/linux/ibus-keyman/meson.build new file mode 100644 index 0000000000..689cf5a5ec --- /dev/null +++ b/linux/ibus-keyman/meson.build @@ -0,0 +1,44 @@ +project('ibus-keyman', 'c', 'cpp', + version: run_command('cat', '../../VERSION.md', check: true).stdout().strip(), + license: 'GPL-2+', + # default_options : ['buildtype=release', + # 'cpp_std=c++14', + # 'b_vscrt=static_from_buildtype', + # 'warning_level=2'], + meson_version: '>=0.53.0') +cc = meson.get_compiler('c') +conf = configuration_data() + +ibus = dependency('ibus-1.0', version: '>= 1.2.0') +gtk = dependency('gtk+-3.0', version: '>= 2.4') +x11 = dependency('x11', version: '>= 1.6') +json_glib = dependency('json-glib-1.0', version: '>= 1.0') + +core_dir = meson.current_source_dir() / '../../core' +common_dir = meson.current_source_dir() / '../../common' + +kmnkbp_lib = cc.find_library( + 'libkmnkbp0', + dirs: [ core_dir / 'build/arch' / get_option('buildtype') / 'src' ] +) + +env = find_program('env') + +# Check if we have patched ibus (https://github.com/ibus/ibus/pull/2440) +if cc.has_header_symbol('ibus.h', 'IBUS_CAP_PREFILTER', dependencies: [ibus], required: false) + conf.set('IBUS_HAS_PREFILTER', 1) +endif + +conf.set('HAVE_CONFIG_H', 1) +configure_file(output : 'config.h', + configuration : conf) + +core_include_dirs = [ + include_directories('../../core/src'), + include_directories('../../core/src/kmx'), + include_directories('../../common/include'), +] + +subdir('icons') +subdir('src') +subdir('tests') diff --git a/linux/ibus-keyman/src/Makefile.am b/linux/ibus-keyman/src/Makefile.am index 95361020c5..ce9f72640a 100644 --- a/linux/ibus-keyman/src/Makefile.am +++ b/linux/ibus-keyman/src/Makefile.am @@ -50,11 +50,11 @@ TESTS = \ $(NULL) print_kmp_SOURCES = \ - print_kmp.c + test/print_kmp.c print_kmpdetails_SOURCES = \ kmpdetails.c \ - print_kmpdetails.c \ + test/print_kmpdetails.c \ $(NULL) print_kmpdetails_CFLAGS = \ $(AM_CFLAGS) \ diff --git a/linux/ibus-keyman/src/keyman.xml.in b/linux/ibus-keyman/src/keyman.xml.in new file mode 100644 index 0000000000..d41cc8021c --- /dev/null +++ b/linux/ibus-keyman/src/keyman.xml.in @@ -0,0 +1,17 @@ + + + org.freedesktop.IBus.Keyman + Keyman Component + @libexecdir@/ibus-engine-keyman --ibus + @VERSION@ + Keyman Team <support@keyman.com> + GPL + https://keyman.com + ibus-keyman + + /usr/share/keyman/ + /usr/local/share/keyman/ + ~/.local/share/keyman/ + + + diff --git a/linux/ibus-keyman/src/meson.build b/linux/ibus-keyman/src/meson.build new file mode 100644 index 0000000000..708c4751ea --- /dev/null +++ b/linux/ibus-keyman/src/meson.build @@ -0,0 +1,49 @@ +util_files = files( + 'keymanutil.c', + 'keymanutil.h', + 'kmpdetails.c', + 'kmpdetails.h', +) + +engine_files = files( + 'main.c', + 'engine.c', + 'engine.h', + 'keycodes.h', + 'keyman-service.c', + 'keyman-service.h', +) + +include_dirs = [ + core_include_dirs, + include_directories('..'), + include_directories(meson.current_build_dir() / '..'), +] + +deps = [ibus, gtk, x11, json_glib, kmnkbp_lib] + +prefix = get_option('prefix') +cfg = configuration_data() +cfg.set('VERSION', meson.project_version()) +cfg.set('libexecdir', prefix / get_option('libexecdir')) + +configure_file( + configuration: cfg, + input: 'keyman.xml.in', + output: 'keyman.xml' +) + +configure_file( + configuration: cfg, + input: 'keyman-version.h.in', + output: 'keyman-version.h' +) + +exe = executable( + 'ibus-engine-keyman', + sources: [engine_files, util_files], + dependencies: deps, + include_directories: include_dirs, +) + +subdir('test') diff --git a/linux/ibus-keyman/src/test/meson.build b/linux/ibus-keyman/src/test/meson.build new file mode 100644 index 0000000000..c652d8f783 --- /dev/null +++ b/linux/ibus-keyman/src/test/meson.build @@ -0,0 +1,62 @@ +keymanutil_sources = [ + 'keymanutil_tests.c', + util_files, +] + +keymanutil_deps = [ibus, gtk, x11, json_glib, kmnkbp_lib] + +test_env = [ + 'G_TEST_SRCDIR=' + meson.current_source_dir(), + 'G_TEST_BUILDDIR=' + meson.current_build_dir(), +] + +test_include_dirs = [ + include_dirs, + include_directories('..'), + include_directories(meson.current_build_dir() / '..'), +] + +executable( + 'keymanutil-tests', + sources: keymanutil_sources, + dependencies: keymanutil_deps, + include_directories : test_include_dirs +) + +test( + 'keymanutil-tests', + find_program('run-tests.sh'), + env: test_env, + protocol: 'tap', +) + +test( + 'print-kmpdetails-test', + executable( + 'print_kmpdetails', + sources: [ + 'print_kmpdetails.c', + '../kmpdetails.c' + ], + dependencies: [ json_glib ], + include_directories: test_include_dirs + ), + args: [ meson.current_source_dir() ], + env: test_env, + protocol: 'exitcode', +) + +test( + 'print-kmp-test', + executable( + 'print_kmp', + sources: [ + 'print_kmp.c', + ], + dependencies: [ json_glib ], + include_directories: test_include_dirs + ), + args: [ meson.current_source_dir() / 'kmp.json' ], + env: test_env, + protocol: 'exitcode', +) diff --git a/linux/ibus-keyman/src/print_kmp.c b/linux/ibus-keyman/src/test/print_kmp.c similarity index 100% rename from linux/ibus-keyman/src/print_kmp.c rename to linux/ibus-keyman/src/test/print_kmp.c diff --git a/linux/ibus-keyman/src/print_kmpdetails.c b/linux/ibus-keyman/src/test/print_kmpdetails.c similarity index 100% rename from linux/ibus-keyman/src/print_kmpdetails.c rename to linux/ibus-keyman/src/test/print_kmpdetails.c diff --git a/linux/ibus-keyman/src/test/run-tests.sh b/linux/ibus-keyman/src/test/run-tests.sh index 04b78a95fe..932f64b886 100755 --- a/linux/ibus-keyman/src/test/run-tests.sh +++ b/linux/ibus-keyman/src/test/run-tests.sh @@ -1,6 +1,6 @@ #!/bin/bash -SRCDIR=${top_srcdir:-$(realpath $(dirname $0)/../..)} +SRCDIR=${top_srcdir:-$(realpath "$(dirname $0)/../..")} PID_FILE=/tmp/keymanutil-tests-pids if [ -v KEYMAN_PKG_BUILD ]; then @@ -12,19 +12,20 @@ if [ -v KEYMAN_PKG_BUILD ]; then exit 0 fi + if ! which Xvfb > /dev/null || ! which Xephyr > /dev/null || ! which metacity > /dev/null; then - echo "Please install Xvfb, Xephyr and metacity before running these tests!" + echo "# Please install Xvfb, Xephyr and metacity before running these tests!" exit 1 fi function cleanup() { if [ -f $PID_FILE ]; then echo - echo "Shutting down processes..." + echo "# Shutting down processes..." bash $PID_FILE > /dev/null 2>&1 rm $PID_FILE - rm -rf $TEMP_DATA_DIR - echo "Finished shutdown of processes." + rm -rf "$TEMP_DATA_DIR" + echo "# Finished shutdown of processes." fi } @@ -32,15 +33,15 @@ echo > $PID_FILE trap cleanup EXIT SIGINT -echo "Starting Xvfb..." +echo "# Starting Xvfb..." Xvfb -screen 0 1024x768x24 :33 &> /dev/null & echo "kill -9 $!" >> $PID_FILE sleep 1 -echo "Starting Xephyr..." +echo "# Starting Xephyr..." DISPLAY=:33 Xephyr :32 -screen 1024x768 &> /dev/null & echo "kill -9 $!" >> $PID_FILE sleep 1 -echo "Starting metacity" +echo "# Starting metacity" metacity --display=:32 &> /dev/null & echo "kill -9 $!" >> $PID_FILE @@ -51,10 +52,10 @@ TEMP_DATA_DIR=$(mktemp --directory) SCHEMA_DIR=$TEMP_DATA_DIR/glib-2.0/schemas export XDG_DATA_DIRS=$TEMP_DATA_DIR:$XDG_DATA_DIRS -mkdir -p $SCHEMA_DIR -cp $SRCDIR/../keyman-config/com.keyman.gschema.xml $SCHEMA_DIR/ -glib-compile-schemas $SCHEMA_DIR +mkdir -p "$SCHEMA_DIR" +cp "$SRCDIR/../keyman-config/com.keyman.gschema.xml" "$SCHEMA_DIR/" +glib-compile-schemas "$SCHEMA_DIR" export GSETTINGS_BACKEND=memory -./keymanutil-tests $@ +${G_TEST_BUILDDIR:-.}/keymanutil-tests "$@" diff --git a/linux/ibus-keyman/tests/README.md b/linux/ibus-keyman/tests/README.md index 8088f2f534..f7537a79fd 100644 --- a/linux/ibus-keyman/tests/README.md +++ b/linux/ibus-keyman/tests/README.md @@ -13,7 +13,7 @@ The tests get run as part of building `ibus-keyman`, more specifically when runn All tests can be run with the test script: ```bash -./run-tests.sh +scripts/run-tests.sh ``` ### Run specific tests @@ -22,5 +22,5 @@ To run a single test you pass the testname (as found in `core/build/arch/*/tests/unit/kmx`). Multiple tests should be separated by space. ```bash -./run-tests.sh -- k_000___null_keyboard k_005___nul_with_initial_context +scripts/run-tests.sh -- k_000___null_keyboard k_005___nul_with_initial_context ``` diff --git a/linux/ibus-keyman/tests/ibusimcontext.c b/linux/ibus-keyman/tests/ibusimcontext.c index d35441a695..dc83cf8b97 100644 --- a/linux/ibus-keyman/tests/ibusimcontext.c +++ b/linux/ibus-keyman/tests/ibusimcontext.c @@ -28,9 +28,7 @@ // simplyfying the code a bit by replacing async calls with direct synchronous // method calls. -#ifdef HAVE_CONFIG_H #include -#endif #ifndef IBUS_HAS_PREFILTER #warning Compiling against ibus version that does not include prefilter mask patch (https://github.com/ibus/ibus/pull/2440). Output ordering guarantees will be disabled. diff --git a/linux/ibus-keyman/tests/meson.build b/linux/ibus-keyman/tests/meson.build new file mode 100644 index 0000000000..1e5db19573 --- /dev/null +++ b/linux/ibus-keyman/tests/meson.build @@ -0,0 +1,142 @@ +test_files = [ + 'ibusimcontext.c', + 'ibusimcontext.h', + 'testfixture.cpp', + 'testmodule.c', + 'testmodule.h', +] + +kmx_dir = [ + core_dir / 'build/arch' / get_option('buildtype') / 'tests/unit/kmx' +] + +kmnkbp_tests_lib = cc.find_library( + 'libkmnkbp-tests', + dirs: kmx_dir +) + +deps = [ibus, gtk, x11, json_glib, kmnkbp_lib, kmnkbp_tests_lib] + +test_env = [ + 'G_TEST_SRCDIR=' + meson.current_source_dir(), + 'G_TEST_BUILDDIR=' + meson.current_build_dir(), +] + +test_include_dirs = [ + core_include_dirs, + include_directories('../../../core/tests/unit/kmx'), + include_directories('../src'), + include_directories('..'), +] + +test_exe = executable( + 'ibus-keyman-tests', + test_files, util_files, + dependencies: deps, + include_directories: test_include_dirs, +) + +env_file = '/tmp/env.txt' +pid_file = '/tmp/ibus-keyman-test-pids' + +setup_tests = find_program('setup-tests.sh', dirs: [meson.current_source_dir() / 'scripts']) +teardown_tests = find_program('teardown-tests.sh', dirs: [meson.current_source_dir() / 'scripts']) +run_test = find_program('run-single-test.sh', dirs: [meson.current_source_dir() / 'scripts']) +find_tests = find_program('find-tests.sh', dirs: [meson.current_source_dir() / 'scripts']) + +test( + 'setup-x11', + setup_tests, + args: ['--x11', env_file, pid_file], + env: test_env, + priority: -10, + is_parallel: false, + protocol: 'exitcode' +) + +test( + 'setup-wayland', + setup_tests, + args: ['--wayland', env_file, pid_file], + env: test_env, + priority: -20, + is_parallel: false, + protocol: 'exitcode' +) + +test( + 'teardown-x11', + teardown_tests, + args: [pid_file], + priority: -19, + is_parallel: false, + protocol: 'exitcode' +) + +test( + 'teardown-wayland', + teardown_tests, + args: [pid_file], + priority: -29, + is_parallel: false, + protocol: 'exitcode' +) + +kmxtest_files = run_command( + find_tests, + kmx_dir, + check: true, +).stdout().split('\n') + +foreach kmx: kmxtest_files + filename = kmx.split('\t') + if filename[0] == '' + continue + endif + testname = filename[1].split('.kmx')[0] + test_args = [ '--tap', '-k', '--env', env_file, '--', filename] + test( + 'X11-' + testname + '__surrounding-text', + run_test, + args: [ '--x11', '--surrounding-text', test_args], + env: test_env, + depends: [test_exe], + priority: -11, + is_parallel: false, + timeout: 120, + protocol: 'tap', + ) + test( + 'X11-' + testname + '__no-surrounding-text', + run_test, + args: [ '--x11', '--no-surrounding-text', test_args], + env: test_env, + depends: [test_exe], + priority: -12, + is_parallel: false, + timeout: 120, + protocol: 'tap', + ) + test( + 'Wayland-' + testname + '__surrounding-text', + run_test, + args: [ '--wayland', '--surrounding-text', test_args], + env: test_env, + depends: [test_exe], + priority: -21, + is_parallel: false, + timeout: 120, + protocol: 'tap', + ) + test( + 'Wayland-' + testname + '__no-surrounding-text', + run_test, + args: [ '--wayland', '--no-surrounding-text', test_args], + env: test_env, + depends: [test_exe], + priority: -22, + is_parallel: false, + timeout: 120, + protocol: 'tap', + ) +endforeach diff --git a/linux/ibus-keyman/tests/scripts/find-tests.sh b/linux/ibus-keyman/tests/scripts/find-tests.sh new file mode 100755 index 0000000000..502cbab55f --- /dev/null +++ b/linux/ibus-keyman/tests/scripts/find-tests.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +set -eu +while [ -n "$1" ]; do + if [ ! -d "$1" ]; then + shift + continue + fi + pushd "$1" > /dev/null + while IFS= read -r -d '' file; do + testname=$(basename "$file" .kmx) + #shellcheck disable=SC2059 + printf "$(basename "$file")\t${testname#k_}\n" + done < <(find . -name \*.kmx -print0 | sort -z) + popd > /dev/null + exit 0 +done diff --git a/linux/ibus-keyman/tests/scripts/run-single-test.sh b/linux/ibus-keyman/tests/scripts/run-single-test.sh new file mode 100755 index 0000000000..c265c27ccd --- /dev/null +++ b/linux/ibus-keyman/tests/scripts/run-single-test.sh @@ -0,0 +1,73 @@ +#!/usr/bin/env bash +TESTDIR=${XDG_DATA_HOME:-$HOME/.local/share}/keyman/test_kmx + +. "$(dirname "$0")"/test-helper.sh + +if [ -v KEYMAN_PKG_BUILD ]; then + # During package builds we skip these tests that require to start ibus because + # ibus requires to find /var/lib/dbus/machine-id or /etc/machine-id, otherwise it fails with: + # "Bail out! IBUS-FATAL-WARNING: Unable to load /var/lib/dbus/machine-id: Failed to open file + # “/var/lib/dbus/machine-id”: No such file or directory" + echo "1..1" + echo "ok 1 - Integration tests # SKIP on package build" + exit 0 +fi + +if ! which Xvfb > /dev/null || ! which Xephyr > /dev/null || ! which metacity > /dev/null || ! which mutter > /dev/null; then + echo "Please install Xvfb, Xephyr, metacity and mutter before running these tests!" + exit 1 +fi + +function help() { + echo "Usage:" + echo " $0 [--env ] [-k] [--tap] [--surrounding-text] [--no-surrounding-text] [--wayland|--x11] [--] TEST" + echo + echo "Arguments:" + echo " --help, -h, -? Display this help" + echo " --verbose, -v Run tests verbosely" + echo " --debug debug test logging output" + echo " -k passed to GLib testing framework" + echo " --tap output in TAP format. Passed to GLib testing framework" + echo " --surrounding-text run tests with surrounding texts enabled" + echo " --no-surrounding-text run tests without support for surrounding text" + echo " --wayland run tests with Wayland" + echo " --x11 run tests with X11" + echo " --env Name of the file containing environment variables to use" + exit 0 +} + +function run_tests() { + echo "# NOTE: When the tests fail check /tmp/ibus-engine-keyman.log and /tmp/ibus-daemon.log!" + echo "" + + echo "# Starting tests..." + # Note: -k and --tap are consumed by the GLib testing framework + # shellcheck disable=SC2086 + "${G_TEST_BUILDDIR:-.}"/ibus-keyman-tests ${ARG_K-} ${ARG_TAP-} \ + ${ARG_VERBOSE-} ${ARG_DEBUG-} ${ARG_SURROUNDING_TEXT-} ${ARG_NO_SURROUNDING_TEXT-} \ + --directory "$TESTDIR" ${ARG_DISPLAY_SERVER} "$TESTFILE" + echo "# Finished tests." +} + +while (( $# )); do + case $1 in + --help|-h|-\?) help ;; + -k) ARG_K=$1 ;; + --tap) ARG_TAP=$1 ;; + --surrounding-text) ARG_SURROUNDING_TEXT=$1 ;; + --no-surrounding-text) ARG_NO_SURROUNDING_TEXT=$1 ;; + --wayland) ARG_DISPLAY_SERVER=$1 ;; + --x11) ARG_DISPLAY_SERVER=$1 ;; + --verbose|-v) ARG_VERBOSE=--verbose;; + --debug) ARG_DEBUG=--debug-log;; + --env) shift ; ARG_ENV=$1 ;; + --) shift ; TESTFILE=$1; break ;; + *) echo "Error: Unexpected argument \"$1\". Exiting." ; exit 4 ;; + esac + shift || (echo "Error: The last argument is missing a value. Exiting."; false) || exit 5 +done + +# shellcheck source=/dev/null +. "$ARG_ENV" + +run_tests diff --git a/linux/ibus-keyman/tests/scripts/run-tests.sh b/linux/ibus-keyman/tests/scripts/run-tests.sh new file mode 100755 index 0000000000..b80dd1a5f4 --- /dev/null +++ b/linux/ibus-keyman/tests/scripts/run-tests.sh @@ -0,0 +1,206 @@ +#!/usr/bin/env bash + +TOP_SRCDIR=${top_srcdir:-$(realpath "$(dirname "$0")/..")} +TESTDIR=${XDG_DATA_HOME:-$HOME/.local/share}/keyman/test_kmx + +. "$(dirname "$0")"/test-helper.sh + +if [ -v KEYMAN_PKG_BUILD ]; then + # During package builds we skip these tests that require to start ibus because + # ibus requires to find /var/lib/dbus/machine-id or /etc/machine-id, otherwise it fails with: + # "Bail out! IBUS-FATAL-WARNING: Unable to load /var/lib/dbus/machine-id: Failed to open file + # “/var/lib/dbus/machine-id”: No such file or directory" + echo "1..1" + echo "ok 1 - Integration tests # SKIP on package build" + exit 0 +fi + +if ! which Xvfb > /dev/null || ! which Xephyr > /dev/null || ! which metacity > /dev/null || ! which mutter > /dev/null; then + echo "Please install Xvfb, Xephyr, metacity and mutter before running these tests!" + exit 1 +fi + +function cleanup() { + if [ -f "$PID_FILE" ]; then + echo + echo "# Shutting down processes..." + bash "$PID_FILE" > /dev/null 2>&1 + rm "$PID_FILE" + echo "# Finished shutdown of processes." + fi +} + +function help() { + echo "Usage:" + echo " $0 [-k] [--tap] [--surrounding-text] [--no-surrounding-text] [--no-wayland] [--no-x11] [[--] TEST...]" + echo + echo "Arguments:" + echo " --help, -h, -? Display this help" + echo " --verbose, -v Run tests verbosely" + echo " --debug debug test logging output" + echo " -k passed to GLib testing framework" + echo " --tap output in TAP format. Passed to GLib testing framework" + echo " --surrounding-text run tests with surrounding texts enabled" + echo " --no-surrounding-text run tests without support for surrounding text" + echo " --no-wayland don't run tests with Wayland" + echo " --no-x11 don't run tests with X11" + echo + echo "If no TESTs are specified then all tests are run." + echo "If neither --surrounding-text nor --no-surrounding-text are specified then the tests run with both settings." + exit 0 +} + +function run_tests() { + DISPLAY_SERVER=$1 + shift + + echo > "$PID_FILE" + TEMP_DATA_DIR=$(mktemp --directory) + echo "rm -rf ${TEMP_DATA_DIR}" >> "$PID_FILE" + + COMMON_ARCH_DIR= + [ -d "${TOP_SRCDIR}"/../../core/build/arch ] && COMMON_ARCH_DIR=${TOP_SRCDIR}/../../core/build/arch + [ -d "${TOP_SRCDIR}"/../keyboardprocessor/arch ] && COMMON_ARCH_DIR=${TOP_SRCDIR}/../keyboardprocessor/arch + + if [ -d "${COMMON_ARCH_DIR}"/release ]; then + COMMON_ARCH_DIR=${COMMON_ARCH_DIR}/release + elif [ -d "${COMMON_ARCH_DIR}"/debug ]; then + COMMON_ARCH_DIR=${COMMON_ARCH_DIR}/debug + else + echo "Can't find neither ${COMMON_ARCH_DIR}/release nor ${COMMON_ARCH_DIR}/debug" + exit 2 + fi + + if [ ! -d "$TESTDIR" ] || ! [[ $(find "${TESTDIR}/" -name \*.kmx 2>/dev/null | wc -l) -gt 0 ]]; then + if [[ $(find "${COMMON_ARCH_DIR}/tests/unit/kmx/" -name \*.kmx 2>/dev/null | wc -l) -gt 0 ]]; then + mkdir -p "$(realpath --canonicalize-missing "$TESTDIR"/..)" + ln -sf "$(realpath "${COMMON_ARCH_DIR}"/tests/unit/kmx)" "$TESTDIR" + else + echo "Can't find kmx files in ${COMMON_ARCH_DIR}/tests/unit/kmx" + exit 3 + fi + fi + + echo "# NOTE: When the tests fail check /tmp/ibus-engine-keyman.log and /tmp/ibus-daemon.log!" + echo "" + + if [ "$DISPLAY_SERVER" == "wayland" ]; then + if ! can_run_wayland; then + # support for --headless got added in mutter 40.x + echo "ERROR: mutter doesn't support running headless. Can't run Wayland tests." + exit 7 + fi + echo "# Running on Wayland..." + TMPFILE=$(mktemp) + # mutter-Message: 18:56:15.422: Using Wayland display name 'wayland-1' + mutter --wayland --headless --no-x11 --virtual-monitor 1024x768 &> "$TMPFILE" & + echo "kill -9 $!" >> "$PID_FILE" + sleep 1s + export WAYLAND_DISPLAY + WAYLAND_DISPLAY=$(cat "$TMPFILE" | grep "Using Wayland display" | cut -d"'" -f2) + rm "$TMPFILE" + else + echo "# Starting Xvfb..." + Xvfb -screen 0 1024x768x24 :33 &> /dev/null & + echo "kill -9 $!" >> "$PID_FILE" + sleep 1 + echo "# Starting Xephyr..." + DISPLAY=:33 Xephyr :32 -screen 1024x768 &> /dev/null & + echo "kill -9 $!" >> "$PID_FILE" + sleep 1 + echo "# Starting metacity" + metacity --display=:32 &> /dev/null & + echo "kill -9 $!" >> "$PID_FILE" + + export DISPLAY=:32 + fi + + # Install schema to temporary directory. This removes the build dependency on the keyman package. + SCHEMA_DIR=$TEMP_DATA_DIR/glib-2.0/schemas + export XDG_DATA_DIRS=$TEMP_DATA_DIR:$XDG_DATA_DIRS + + mkdir -p "$SCHEMA_DIR" + cp "${TOP_SRCDIR}"/../keyman-config/com.keyman.gschema.xml "$SCHEMA_DIR"/ + glib-compile-schemas "$SCHEMA_DIR" + + if [ $# -gt 0 ]; then + TESTFILES=($@) + else + pushd "$TESTDIR" > /dev/null || exit + TESTFILES=(*.kmx) + popd > /dev/null || exit + fi + + export LD_LIBRARY_PATH=${COMMON_ARCH_DIR}/src:$LD_LIBRARY_PATH + + # Ubuntu 18.04 Bionic doesn't have ibus-memconf, and glib is not compiled with the keyfile + # backend enabled, so we just use the default backend. Otherwise we use the keyfile + # store which interferes less when running on a dev machine. + if [ -f /usr/libexec/ibus-memconf ]; then + export GSETTINGS_BACKEND=keyfile + IBUS_CONFIG=--config=/usr/libexec/ibus-memconf + fi + + ibus-daemon "${ARG_VERBOSE-}" --panel=disable ${IBUS_CONFIG-} &> /tmp/ibus-daemon.log & + echo "kill -9 $!" >> "$PID_FILE" + sleep 1s + + ../src/ibus-engine-keyman "${ARG_VERBOSE-}" &> /tmp/ibus-engine-keyman.log & + echo "kill -9 $!" >> "$PID_FILE" + sleep 1s + + echo "# Starting tests..." + # Note: -k and --tap are consumed by the GLib testing framework + "${G_TEST_BUILDDIR:-.}"/ibus-keyman-tests "${ARG_K-}" "${ARG_TAP-}" \ + "${ARG_VERBOSE-}" "${ARG_DEBUG-}" "${ARG_SURROUNDING_TEXT-}" "${ARG_NO_SURROUNDING_TEXT-}" \ + --directory "$TESTDIR" --"${DISPLAY_SERVER}" "${TESTFILES[@]}" + echo "# Finished tests." + + cleanup +} + +USE_WAYLAND=1 +USE_X11=1 + +while (( $# )); do + case $1 in + --help|-h|-\?) help ;; + -k) ARG_K=$1 ;; + --tap) ARG_TAP=$1 ;; + --surrounding-text) ARG_SURROUNDING_TEXT=$1 ;; + --no-surrounding-text) ARG_NO_SURROUNDING_TEXT=$1 ;; + --no-wayland) USE_WAYLAND=0;; + --no-x11) USE_X11=0;; + --verbose|-v) ARG_VERBOSE=--verbose;; + --debug) ARG_DEBUG=--debug-log;; + --) shift && break ;; + *) echo "Error: Unexpected argument \"$1\". Exiting." ; exit 4 ;; + esac + shift || (echo "Error: The last argument is missing a value. Exiting."; false) || exit 5 +done + +if ! can_run_wayland; then + # support for --headless got added in mutter 40.x + echo "# WARNING: mutter doesn't support running headless. Skipping Wayland tests." + USE_WAYLAND=0 + if [ "$USE_X11" == "0" ]; then + echo "ERROR: no tests to run. Can't run Wayland tests, and --no-x11 is specified." + exit 8 + fi +fi + +if [ "$USE_WAYLAND" == "0" ] && [ "$USE_X11" == "0" ]; then + echo "ERROR: I'll have to run somewhere. Specifying both --no-wayland and --no-x11 is not allowed." + exit 6 +fi + +echo > "$PID_FILE" +trap cleanup EXIT SIGINT + +if [ "$USE_WAYLAND" == "1" ]; then + run_tests wayland "$@" +fi + +if [ "$USE_X11" == "1" ]; then + run_tests x11 "$@" +fi diff --git a/linux/ibus-keyman/tests/scripts/setup-tests.sh b/linux/ibus-keyman/tests/scripts/setup-tests.sh new file mode 100755 index 0000000000..e48d36eba9 --- /dev/null +++ b/linux/ibus-keyman/tests/scripts/setup-tests.sh @@ -0,0 +1,111 @@ +#!/usr/bin/env bash +DISPLAY_SERVER=$1 +ENV_FILE=$2 +PID_FILE=$3 + +TOP_SRCDIR=${G_TEST_SRCDIR:-$(realpath "$(dirname "$0")/..")}/.. +TOP_BINDIR=${G_TEST_BUILDDIR:-$(realpath "$(dirname "$0/..")")}/.. +TESTDIR=${XDG_DATA_HOME:-$HOME/.local/share}/keyman/test_kmx + +. "$(dirname "$0")/"/test-helper.sh + +echo > "$ENV_FILE" + +if [ -f "$PID_FILE" ]; then + # kill previous instances + "$(dirname "$0")"/teardown-tests.sh "$PID_FILE" +fi + +echo > "$PID_FILE" +TEMP_DATA_DIR=$(mktemp --directory) +echo "rm -rf ${TEMP_DATA_DIR}" >> "$PID_FILE" + +COMMON_ARCH_DIR= +[ -d "${TOP_SRCDIR}"/../../core/build/arch ] && COMMON_ARCH_DIR=${TOP_SRCDIR}/../../core/build/arch +[ -d "${TOP_SRCDIR}"/../keyboardprocessor/arch ] && COMMON_ARCH_DIR=${TOP_SRCDIR}/../keyboardprocessor/arch + +if [ -d "${COMMON_ARCH_DIR}"/release ]; then + COMMON_ARCH_DIR=${COMMON_ARCH_DIR}/release +elif [ -d "${COMMON_ARCH_DIR}"/debug ]; then + COMMON_ARCH_DIR=${COMMON_ARCH_DIR}/debug +else + echo "Can't find neither ${COMMON_ARCH_DIR}/release nor ${COMMON_ARCH_DIR}/debug" + exit 2 +fi + +if [ ! -d "$TESTDIR" ] || ! [[ $(find "${TESTDIR}/" -name \*.kmx 2>/dev/null | wc -l) -gt 0 ]]; then + if [[ $(find "${COMMON_ARCH_DIR}/tests/unit/kmx/" -name \*.kmx 2>/dev/null | wc -l) -gt 0 ]]; then + mkdir -p "$(realpath --canonicalize-missing "$TESTDIR"/..)" + ln -sf "$(realpath "${COMMON_ARCH_DIR}"/tests/unit/kmx)" "$TESTDIR" + else + echo "Can't find kmx files in ${COMMON_ARCH_DIR}/tests/unit/kmx" + exit 3 + fi +fi + +if [ "$DISPLAY_SERVER" == "wayland" ]; then + if ! can_run_wayland; then + # support for --headless got added in mutter 40.x + echo "ERROR: mutter doesn't support running headless. Can't run Wayland tests." + exit 7 + fi + echo "Running on Wayland..." + TMPFILE=$(mktemp) + # mutter-Message: 18:56:15.422: Using Wayland display name 'wayland-1' + mutter --wayland --headless --no-x11 --virtual-monitor 1024x768 &> "$TMPFILE" & + echo "kill -9 $!" >> "$PID_FILE" + sleep 1s + export WAYLAND_DISPLAY + WAYLAND_DISPLAY=$(grep "Using Wayland display" "$TMPFILE" | cut -d"'" -f2) + rm "$TMPFILE" + echo "export WAYLAND_DISPLAY=\"$WAYLAND_DISPLAY\"" >> "$ENV_FILE" +else + echo "Starting Xvfb..." + Xvfb -screen 0 1024x768x24 :33 &> /dev/null & + echo "kill -9 $!" >> "$PID_FILE" + sleep 1 + echo "Starting Xephyr..." + DISPLAY=:33 Xephyr :32 -screen 1024x768 &> /dev/null & + echo "kill -9 $!" >> "$PID_FILE" + sleep 1 + echo "Starting metacity" + metacity --display=:32 &> /dev/null & + echo "kill -9 $!" >> "$PID_FILE" + + export DISPLAY=:32 + echo "export DISPLAY=\"$DISPLAY\"" >> "$ENV_FILE" +fi + + # Install schema to temporary directory. This removes the build dependency on the keyman package. + SCHEMA_DIR=$TEMP_DATA_DIR/glib-2.0/schemas + export XDG_DATA_DIRS=$TEMP_DATA_DIR:$XDG_DATA_DIRS + echo "export XDG_DATA_DIRS=\"$XDG_DATA_DIRS\"" >> "$ENV_FILE" + + mkdir -p "$SCHEMA_DIR" + cp "${TOP_SRCDIR}"/../keyman-config/com.keyman.gschema.xml "$SCHEMA_DIR"/ + glib-compile-schemas "$SCHEMA_DIR" + + export LD_LIBRARY_PATH=${COMMON_ARCH_DIR}/src:$LD_LIBRARY_PATH + echo "export LD_LIBRARY_PATH=\"$LD_LIBRARY_PATH\"" >> "$ENV_FILE" + + # Ubuntu 18.04 Bionic doesn't have ibus-memconf, and glib is not compiled with the keyfile + # backend enabled, so we just use the default backend. Otherwise we use the keyfile + # store which interferes less when running on a dev machine. + if [ -f /usr/libexec/ibus-memconf ]; then + export GSETTINGS_BACKEND=keyfile + echo "export GSETTINGS_BACKEND=\"$GSETTINGS_BACKEND\"" >> "$ENV_FILE" + IBUS_CONFIG=--config=/usr/libexec/ibus-memconf + fi + + ibus-daemon "${ARG_VERBOSE-}" --daemonize --panel=disable ${IBUS_CONFIG-} &> /tmp/ibus-daemon.log + echo "kill -9 $!" >> "$PID_FILE" + sleep 1s + + IBUS_ADDRESS=$(ibus address) + export IBUS_ADDRESS + + echo "export IBUS_ADDRESS=\"$IBUS_ADDRESS\"" >> "$ENV_FILE" + + "${TOP_BINDIR}"/src/ibus-engine-keyman "${ARG_VERBOSE-}" &> /tmp/ibus-engine-keyman.log & + echo "kill -9 $!" >> "$PID_FILE" + sleep 1s diff --git a/linux/ibus-keyman/tests/scripts/teardown-tests.sh b/linux/ibus-keyman/tests/scripts/teardown-tests.sh new file mode 100755 index 0000000000..489769d721 --- /dev/null +++ b/linux/ibus-keyman/tests/scripts/teardown-tests.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +PID_FILE=$1 + +echo "Shutting down processes..." +bash "$PID_FILE" > /dev/null 2>&1 +rm "$PID_FILE" +echo "Finished shutdown of processes." diff --git a/linux/ibus-keyman/tests/scripts/test-helper.sh b/linux/ibus-keyman/tests/scripts/test-helper.sh new file mode 100755 index 0000000000..92c8a7e528 --- /dev/null +++ b/linux/ibus-keyman/tests/scripts/test-helper.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +function can_run_wayland() { + local MUTTER_VERSION + MUTTER_VERSION=$(mutter --version | head -1 | cut -f2 -d' ' | cut -f1 -d'.') + if (( MUTTER_VERSION < 40 )); then + return 1 + else + return 0 + fi +} diff --git a/linux/keyman-config/locale/kn_IN.po b/linux/keyman-config/locale/kn_IN.po index e1d4aa6bcd..7745c3c745 100644 --- a/linux/keyman-config/locale/kn_IN.po +++ b/linux/keyman-config/locale/kn_IN.po @@ -3,7 +3,7 @@ msgstr "" "Project-Id-Version: keyman\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2020-08-19 19:17+0200\n" -"PO-Revision-Date: 2023-01-03 04:05\n" +"PO-Revision-Date: 2023-02-07 14:38\n" "Last-Translator: \n" "Language-Team: Kannada\n" "Language: kn_IN\n" diff --git a/linux/scripts/deb-packaging.sh b/linux/scripts/deb-packaging.sh new file mode 100755 index 0000000000..35416cc370 --- /dev/null +++ b/linux/scripts/deb-packaging.sh @@ -0,0 +1,71 @@ +#!/usr/bin/env bash +# Actions for creating a Debian source package. Used by deb-packaging.yml GHA. + +set -eu + +## START STANDARD BUILD SCRIPT INCLUDE +# adjust relative paths as necessary +THIS_SCRIPT="$(greadlink -f "${BASH_SOURCE[0]}" 2>/dev/null || readlink -f "${BASH_SOURCE[0]}")" +. "$(dirname "$THIS_SCRIPT")/../../resources/build/build-utils.sh" +## END STANDARD BUILD SCRIPT INCLUDE + +builder_describe \ + "Helper for building Debian packages." \ + "dependencies Install dependencies as found in debian/control" \ + "source+ Build source package" \ + "verify Verify API" \ + "--gha Build from GitHub Action" + +builder_parse "$@" + +cd "$REPO_ROOT/linux" + +if builder_has_option --gha; then + START_STEP="::group::${COLOR_GREEN}" + END_STEP="::endgroup::" +else + START_STEP="${COLOR_GREEN}" + END_STEP="" +fi + +if builder_start_action dependencies; then + sudo mk-build-deps --install --tool='apt-get -o Debug::pkgProblemResolver=yes --no-install-recommends --yes' debian/control + builder_finish_action success dependencies + exit 0 +fi + +if builder_start_action source; then + echo "${START_STEP}Make source package for keyman${COLOR_RESET}" + + echo "${START_STEP}reconfigure${COLOR_RESET}" + ./scripts/reconf.sh keyman + echo "${END_STEP}" + + echo "${START_STEP}Make origdist${COLOR_RESET}" + ./scripts/dist.sh origdist keyman + echo "${END_STEP}" + + echo "${START_STEP}Make deb source${COLOR_RESET}" + ./scripts/deb.sh sourcepackage keyman + echo "${END_STEP}" + + mv builddebs/* "${OUTPUT_PATH:-..}" + + builder_finish_action success source + exit 0 +fi + +if builder_start_action verify; then + tar xf "${SRC_PKG}" + if [ ! -f debian/libkmnkbp0-0.symbols ]; then + echo ":warning: Missing libkmnkbp0-0.symbols file" + else + tmpDir=$(mktemp -d) + dpkg -x "${BIN_PKG}" "$tmpDir" + cd debian + dpkg-gensymbols -v"${PKG_VERSION}" -plibkmnkbp0-0 -e"${tmpDir}"/usr/lib/x86_64-linux-gnu/libkmnkbp0.so* -Olibkmnkbp0-0.symbols -c4 + echo ":heavy_check_mark: libkmnkbp0-0 API didn't change" + fi + builder_finish_action success verify + exit 0 +fi diff --git a/linux/scripts/upload-to-debian.sh b/linux/scripts/upload-to-debian.sh index 1474b281b4..23622f86a6 100755 --- a/linux/scripts/upload-to-debian.sh +++ b/linux/scripts/upload-to-debian.sh @@ -104,7 +104,7 @@ cp debianpackage/keyman-*/debian/changelog debian/ git add debian/changelog git commit -m "chore(linux): Update debian changelog" if [ -n "$PUSH" ]; then - $NOOP git push origin chore/linux/changelog + $NOOP git push --force-with-lease origin chore/linux/changelog fi if $ISBETA; then @@ -116,7 +116,7 @@ fi git checkout -B chore/linux/cherry-pick/changelog ${CLBRANCH} git cherry-pick -x chore/linux/changelog if [ -n "$PUSH" ]; then - $NOOP git push origin chore/linux/cherry-pick/changelog + $NOOP git push --force-with-lease origin chore/linux/cherry-pick/changelog fi echo_heading "Finishing" diff --git a/package-lock.json b/package-lock.json index a20639497a..90ab9ec92d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,8 +21,8 @@ "esbuild": "^0.15.15", "mocha": "^10.0.0", "mocha-teamcity-reporter": "^4.0.0", - "ts-node": "^9.1.1", - "typescript": "^4.5.4" + "ts-node": "^10.9.1", + "typescript": "^4.9.5" } }, "common/core/web/input-processor": { @@ -45,7 +45,7 @@ "mocha": "^8.4.0", "mocha-teamcity-reporter": "^4.0.0", "ts-node": "^9.1.1", - "typescript": "^4.5.4" + "typescript": "^4.9.5" } }, "common/core/web/keyboard-processor": { @@ -64,7 +64,7 @@ "mocha": "^8.4.0", "mocha-teamcity-reporter": "^4.0.0", "ts-node": "^9.1.1", - "typescript": "^4.5.4" + "typescript": "^4.9.5" } }, "common/core/web/tools/recorder": { @@ -79,7 +79,7 @@ "@types/node": "^11.9.4" }, "devDependencies": { - "typescript": "^4.5.4" + "typescript": "^4.9.5" } }, "common/core/web/tools/sentry-manager": { @@ -91,7 +91,7 @@ "@sentry/browser": "^5.27.4" }, "devDependencies": { - "typescript": "^4.5.4" + "typescript": "^4.9.5" } }, "common/core/web/utils": { @@ -102,7 +102,7 @@ "@keymanapp/keyman-version": "*", "@keymanapp/resources-gosh": "*", "@types/node": "^14.0.5", - "typescript": "^4.5.4" + "typescript": "^4.9.5" } }, "common/models/templates": { @@ -122,7 +122,7 @@ "@types/node": "^14.0.4", "chai": "^4.3.4", "mocha": "^10.0.0", - "typescript": "^4.5.4" + "typescript": "^4.9.5" } }, "common/models/templates/node_modules/@types/node": { @@ -135,7 +135,7 @@ "name": "@keymanapp/models-types", "license": "MIT", "devDependencies": { - "typescript": "^4.5.4" + "typescript": "^4.9.5" } }, "common/models/wordbreakers": { @@ -151,8 +151,8 @@ "@types/mocha": "^7.0.2", "chai": "^4.3.4", "mocha": "^10.0.0", - "ts-node": "^9.1.1", - "typescript": "^4.5.4" + "ts-node": "^10.9.1", + "typescript": "^4.9.5" } }, "common/models/wordbreakers/node_modules/@types/node": { @@ -193,8 +193,8 @@ "mocha": "^10.0.0", "mocha-teamcity-reporter": "^4.0.0", "sinon": "^7.1.1", - "ts-node": "^9.1.1", - "typescript": "^4.5.4" + "ts-node": "^10.9.1", + "typescript": "^4.9.5" } }, "common/predictive-text/node_modules/@types/node": { @@ -216,8 +216,8 @@ "mocha": "^10.0.0", "mocha-teamcity-reporter": "^4.0.0", "sinon": "^7.1.1", - "ts-node": "^9.1.1", - "typescript": "^4.5.4" + "ts-node": "^10.9.1", + "typescript": "^4.9.5" } }, "common/tools/sourcemap-path-remapper/node_modules/@types/node": { @@ -253,8 +253,8 @@ "chai": "^4.3.4", "mocha": "^10.0.0", "mocha-teamcity-reporter": "^4.0.0", - "ts-node": "^9.1.1", - "typescript": "^4.5.4" + "ts-node": "^10.9.1", + "typescript": "^4.9.5" } }, "common/web/keyboard-processor": { @@ -271,15 +271,15 @@ "chai": "^4.3.4", "mocha": "^10.0.0", "mocha-teamcity-reporter": "^4.0.0", - "ts-node": "^9.1.1", - "typescript": "^4.5.4" + "ts-node": "^10.9.1", + "typescript": "^4.9.5" } }, "common/web/keyman-version": { "name": "@keymanapp/keyman-version", "license": "MIT", "devDependencies": { - "typescript": "^4.5.4" + "typescript": "^4.9.5" } }, "common/web/keyman-version-node": { @@ -287,7 +287,7 @@ "extraneous": true, "license": "MIT", "devDependencies": { - "typescript": "^4.5.4" + "typescript": "^4.9.5" } }, "common/web/keyman-version/node": { @@ -296,14 +296,14 @@ "license": "MIT", "devDependencies": { "@keymanapp/resources-gosh": "*", - "typescript": "^4.5.4" + "typescript": "^4.9.5" } }, "common/web/lm-message-types": { "name": "@keymanapp/lm-message-types", "license": "MIT", "devDependencies": { - "typescript": "^4.5.4" + "typescript": "^4.9.5" } }, "common/web/lm-worker": { @@ -342,8 +342,8 @@ "mocha": "^10.0.0", "mocha-teamcity-reporter": "^4.0.0", "sinon": "^7.1.1", - "ts-node": "^9.1.1", - "typescript": "^4.5.4" + "ts-node": "^10.9.1", + "typescript": "^4.9.5" } }, "common/web/lm-worker/node_modules/@types/node": { @@ -363,7 +363,7 @@ "@types/node": "^11.9.4" }, "devDependencies": { - "typescript": "^4.5.4" + "typescript": "^4.9.5" } }, "common/web/sentry-manager": { @@ -374,7 +374,7 @@ "@sentry/browser": "^5.27.4" }, "devDependencies": { - "typescript": "^4.5.4" + "typescript": "^4.9.5" } }, "common/web/utils": { @@ -387,7 +387,7 @@ "chai": "^4.3.4", "mocha": "^10.0.0", "mocha-teamcity-reporter": "^4.0.0", - "typescript": "^4.5.4" + "typescript": "^4.9.5" } }, "common/web/utils/node_modules/@types/node": { @@ -403,7 +403,7 @@ "dependencies": { "@keymanapp/models-types": "*", "commander": "^3.0.0", - "typescript": "^4.5.4", + "typescript": "^4.9.5", "xml2js": "^0.4.19" }, "bin": { @@ -456,7 +456,7 @@ "mocha": "^9.1.4", "ts-node": "^10.4.0", "tsc-watch": "^4.5.0", - "typescript": "^4.5.4" + "typescript": "^4.9.5" }, "optionalDependencies": { "hetrodo-node-hide-console-window-napi": "git+ssh://git@github.com/keymanapp/hetrodo-node-hide-console-window-napi.git#858b23036a9963b40ad6ff3c5bacd421e5839b92", @@ -470,7 +470,7 @@ "@keymanapp/keyman-version": "*", "@keymanapp/models-types": "*", "commander": "^3.0.0", - "typescript": "^4.5.4", + "typescript": "^4.9.5", "xml2js": "^0.4.19" }, "bin": { @@ -489,7 +489,7 @@ "chalk": "^2.4.2", "jszip": "^3.7.0", "mocha": "^10.0.0", - "ts-node": "^9.1.1" + "ts-node": "^10.9.1" }, "engines": { "node": ">=16.0.0" @@ -593,9 +593,9 @@ "chai": "^4.3.4", "copyfiles": "^2.4.1", "mocha": "^10.0.0", - "ts-node": "^10.4.0", + "ts-node": "^10.9.1", "tsc-watch": "^4.5.0", - "typescript": "^4.5.4" + "typescript": "^4.9.5" }, "optionalDependencies": { "hetrodo-node-hide-console-window-napi": "keymanapp/hetrodo-node-hide-console-window-napi#keyman-15.0", @@ -650,58 +650,6 @@ "node": ">=10.0.0" } }, - "developer/src/server/node_modules/ts-node": { - "version": "10.8.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.8.1.tgz", - "integrity": "sha512-Wwsnao4DQoJsN034wePSg5nZiw4YKXf56mPIAeD6wVmiv+RytNSWqc2f3fKvcUoV+Yn2+yocD71VOfQHbmVX4g==", - "dev": true, - "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } - } - }, - "developer/src/server/node_modules/ts-node/node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, "node_modules/@actions/core": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.9.1.tgz", @@ -1388,14 +1336,11 @@ "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", "dev": true }, - "node_modules/@socket.io/base64-arraybuffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@socket.io/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", - "integrity": "sha512-dOlCBKnDw4iShaIsH/bxujKTM18+2TOAsYz+KSc11Am38H4q5Xw8Bbz97ZYdrVNM+um3p7w86Bvvmcn9q+5+eQ==", - "dev": true, - "engines": { - "node": ">= 0.6.0" - } + "node_modules/@socket.io/component-emitter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", + "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==", + "dev": true }, "node_modules/@szmarczak/http-timer": { "version": "4.0.6", @@ -1459,12 +1404,6 @@ "integrity": "sha512-/ceqdqeRraGolFTcfoXNiqjyQhZzbINDngeoAq9GoHa8PPK1yNzTaxWjA6BFWp5Ua9JpXEMSS4s5i9tS0hOJtw==", "dev": true }, - "node_modules/@types/component-emitter": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.11.tgz", - "integrity": "sha512-SRXjM+tfsSlA9VuG8hGO2nft2p8zjXCK1VcC6N4NXbBbYbSia9kzCChYQajIjzIqOOOuh5Ock6MmV2oux4jDZQ==", - "dev": true - }, "node_modules/@types/connect": { "version": "3.4.35", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", @@ -1481,10 +1420,13 @@ "dev": true }, "node_modules/@types/cors": { - "version": "2.8.12", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz", - "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==", - "dev": true + "version": "2.8.13", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.13.tgz", + "integrity": "sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } }, "node_modules/@types/express": { "version": "4.17.13", @@ -1616,12 +1558,6 @@ "@types/node": "*" } }, - "node_modules/@ungap/promise-all-settled": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", - "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", - "dev": true - }, "node_modules/abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -2292,12 +2228,6 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz", "integrity": "sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==" }, - "node_modules/component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, "node_modules/compress-brotli": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/compress-brotli/-/compress-brotli-1.3.6.tgz", @@ -2697,9 +2627,9 @@ } }, "node_modules/engine.io": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.1.3.tgz", - "integrity": "sha512-rqs60YwkvWTLLnfazqgZqLa/aKo+9cueVfEi/dZ8PyGyaf8TLOxj++4QMIgeG3Gn0AhrWiFXvghsoY9L9h25GA==", + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.4.0.tgz", + "integrity": "sha512-OgxY1c/RuCSeO/rTr8DIFXx76IzUUft86R7/P7MMbbkuzeqJoTNw2lmeD91IyGz41QYleIIjWeMJGgug043sfQ==", "dev": true, "dependencies": { "@types/cookie": "^0.4.1", @@ -2711,43 +2641,19 @@ "cors": "~2.8.5", "debug": "~4.3.1", "engine.io-parser": "~5.0.3", - "ws": "~8.2.3" + "ws": "~8.11.0" }, "engines": { "node": ">=10.0.0" } }, "node_modules/engine.io-parser": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.3.tgz", - "integrity": "sha512-BtQxwF27XUNnSafQLvDi0dQ8s3i6VgzSoQMJacpIcGNrlUdfHSKbgm3jmjCVvQluGzqwujQMPAoMai3oYSTurg==", - "dev": true, - "dependencies": { - "@socket.io/base64-arraybuffer": "~1.0.2" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/engine.io/node_modules/ws": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", - "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.6.tgz", + "integrity": "sha512-tjuoZDMAdEhVnSFleYPCtdL2GXwVTGtNjoeJd9IhIG3C1xs9uwxqRNEu5WpnDZCaozwVlK/nuQhpodhXSIMaxw==", "dev": true, "engines": { "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } } }, "node_modules/ent": { @@ -3803,9 +3709,9 @@ "optional": true }, "node_modules/http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==" + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" }, "node_modules/http-errors": { "version": "1.8.1", @@ -4761,12 +4667,11 @@ } }, "node_modules/mocha": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.0.0.tgz", - "integrity": "sha512-0Wl+elVUD43Y0BqPZBzZt8Tnkw9CMUdNYnUsTfOM1vuhJVZL+kiesFYsqwBkEEuEixaiPe5ZQdqDgX2jddhmoA==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", + "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", "dev": true, "dependencies": { - "@ungap/promise-all-settled": "1.1.2", "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", "chokidar": "3.5.3", @@ -6172,36 +6077,38 @@ } }, "node_modules/socket.io": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.4.1.tgz", - "integrity": "sha512-s04vrBswdQBUmuWJuuNTmXUVJhP0cVky8bBDhdkf8y0Ptsu7fKU2LuLbts9g+pdmAdyMMn8F/9Mf1/wbtUN0fg==", + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.6.0.tgz", + "integrity": "sha512-b65bp6INPk/BMMrIgVvX12x3Q+NqlGqSlTuvKQWt0BUJ3Hyy3JangBl7fEoWZTXbOKlCqNPbQ6MbWgok/km28w==", "dev": true, "dependencies": { "accepts": "~1.3.4", "base64id": "~2.0.0", "debug": "~4.3.2", - "engine.io": "~6.1.0", - "socket.io-adapter": "~2.3.3", - "socket.io-parser": "~4.0.4" + "engine.io": "~6.4.0", + "socket.io-adapter": "~2.5.2", + "socket.io-parser": "~4.2.1" }, "engines": { "node": ">=10.0.0" } }, "node_modules/socket.io-adapter": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.3.3.tgz", - "integrity": "sha512-Qd/iwn3VskrpNO60BeRyCyr8ZWw9CPZyitW4AQwmRZ8zCiyDiL+znRnWX6tDHXnWn1sJrM1+b6Mn6wEDJJ4aYQ==", - "dev": true - }, - "node_modules/socket.io-parser": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.5.tgz", - "integrity": "sha512-sNjbT9dX63nqUFIOv95tTVm6elyIU4RvB1m8dOeZt+IgWwcWklFDOdmGcfo3zSiRsnR/3pJkjY5lfoGqEe4Eig==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz", + "integrity": "sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA==", "dev": true, "dependencies": { - "@types/component-emitter": "^1.2.10", - "component-emitter": "~1.3.0", + "ws": "~8.11.0" + } + }, + "node_modules/socket.io-parser": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.2.tgz", + "integrity": "sha512-DJtziuKypFkMMHCm2uIshOYC7QaylbtzQwiMYDuCKy3OPkjLzu4B2vAhTlqipRHHzrI0NJeBAizTK7X+6m1jVw==", + "dev": true, + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.1" }, "engines": { @@ -6234,16 +6141,6 @@ "node": ">=0.10.0" } }, - "node_modules/source-map-support": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", - "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, "node_modules/split": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", @@ -6538,29 +6435,46 @@ "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" }, "node_modules/ts-node": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz", - "integrity": "sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==", + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", "dev": true, "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", "arg": "^4.1.0", "create-require": "^1.1.0", "diff": "^4.0.1", "make-error": "^1.1.1", - "source-map-support": "^0.5.17", + "v8-compile-cache-lib": "^3.0.1", "yn": "3.1.1" }, "bin": { "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", "ts-node-script": "dist/bin-script.js", "ts-node-transpile-only": "dist/bin-transpile.js", "ts-script": "dist/bin-script-deprecated.js" }, - "engines": { - "node": ">=10.0.0" - }, "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } } }, "node_modules/ts-node/node_modules/diff": { @@ -6673,9 +6587,9 @@ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" }, "node_modules/typescript": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz", - "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==", + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -6937,9 +6851,9 @@ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "node_modules/ws": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", - "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", "engines": { "node": ">=10.0.0" }, @@ -7162,17 +7076,17 @@ "dependencies": { "@actions/core": "^1.9.1", "@actions/github": "^2.1.0", - "typescript": "^4.5.4", + "typescript": "^4.9.5", "yargs": "^15.1.0" }, "devDependencies": { "@types/node": "^13.7.0", "@types/semver": "^7.1.0", "semver": "^7.1.2", - "ts-node": "^8.6.2" + "ts-node": "^10.9.1" }, "engines": { - "node": "16" + "node": ">=16.0" } }, "resources/build/version/node_modules/@types/node": { @@ -7199,15 +7113,6 @@ "wrap-ansi": "^6.2.0" } }, - "resources/build/version/node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, "resources/build/version/node_modules/find-up": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", @@ -7288,31 +7193,6 @@ "node": ">=8" } }, - "resources/build/version/node_modules/ts-node": { - "version": "8.10.2", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.10.2.tgz", - "integrity": "sha512-ISJJGgkIpDdBhWVu3jufsWpK3Rzo7bdiIXJjQc0ynKxVOVcg2oIrf2H2cejminGrptVc6q6/uynAHNCuWGbpVA==", - "dev": true, - "dependencies": { - "arg": "^4.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "source-map-support": "^0.5.17", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "engines": { - "node": ">=6.0.0" - }, - "peerDependencies": { - "typescript": ">=2.7" - } - }, "resources/build/version/node_modules/wrap-ansi": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", @@ -7407,8 +7287,8 @@ "karma-teamcity-reporter": "^1.1.0", "mocha": "^10.0.0", "modernizr": "^3.11.7", - "ts-node": "^9.1.1", - "typescript": "^4.5.4" + "ts-node": "^10.9.1", + "typescript": "^4.9.5" } } }, @@ -7509,8 +7389,8 @@ "@types/node": "^13.7.0", "@types/semver": "^7.1.0", "semver": "^7.1.2", - "ts-node": "^8.6.2", - "typescript": "^4.5.4", + "ts-node": "^10.9.1", + "typescript": "^4.9.5", "yargs": "^15.1.0" }, "dependencies": { @@ -7535,12 +7415,6 @@ "wrap-ansi": "^6.2.0" } }, - "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true - }, "find-up": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", @@ -7597,19 +7471,6 @@ "ansi-regex": "^5.0.1" } }, - "ts-node": { - "version": "8.10.2", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.10.2.tgz", - "integrity": "sha512-ISJJGgkIpDdBhWVu3jufsWpK3Rzo7bdiIXJjQc0ynKxVOVcg2oIrf2H2cejminGrptVc6q6/uynAHNCuWGbpVA==", - "dev": true, - "requires": { - "arg": "^4.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "source-map-support": "^0.5.17", - "yn": "3.1.1" - } - }, "wrap-ansi": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", @@ -7676,9 +7537,9 @@ "ngrok": "^4.2.2", "node-windows-trayicon": "keymanapp/node-windows-trayicon#keyman-16.0", "open": "^8.4.0", - "ts-node": "^10.4.0", + "ts-node": "^10.9.1", "tsc-watch": "^4.5.0", - "typescript": "^4.5.4", + "typescript": "^4.9.5", "ws": "^8.3.0" }, "dependencies": { @@ -7720,35 +7581,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==" - }, - "ts-node": { - "version": "10.8.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.8.1.tgz", - "integrity": "sha512-Wwsnao4DQoJsN034wePSg5nZiw4YKXf56mPIAeD6wVmiv+RytNSWqc2f3fKvcUoV+Yn2+yocD71VOfQHbmVX4g==", - "dev": true, - "requires": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "dependencies": { - "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true - } - } } } }, @@ -7767,8 +7599,8 @@ "eventemitter3": "^4.0.0", "mocha": "^10.0.0", "mocha-teamcity-reporter": "^4.0.0", - "ts-node": "^9.1.1", - "typescript": "^4.5.4" + "ts-node": "^10.9.1", + "typescript": "^4.9.5" } }, "@keymanapp/keyboard-processor": { @@ -7782,14 +7614,14 @@ "chai": "^4.3.4", "mocha": "^10.0.0", "mocha-teamcity-reporter": "^4.0.0", - "ts-node": "^9.1.1", - "typescript": "^4.5.4" + "ts-node": "^10.9.1", + "typescript": "^4.9.5" } }, "@keymanapp/keyman-version": { "version": "file:common/web/keyman-version", "requires": { - "typescript": "^4.5.4" + "typescript": "^4.9.5" } }, "@keymanapp/lexical-model-compiler": { @@ -7808,8 +7640,8 @@ "commander": "^3.0.0", "jszip": "^3.7.0", "mocha": "^10.0.0", - "ts-node": "^9.1.1", - "typescript": "^4.5.4", + "ts-node": "^10.9.1", + "typescript": "^4.9.5", "xml2js": "^0.4.19" }, "dependencies": { @@ -7907,8 +7739,8 @@ "mocha-teamcity-reporter": "^4.0.0", "sinon": "^7.1.1", "string.prototype.codepointat": "^0.2.1", - "ts-node": "^9.1.1", - "typescript": "^4.5.4" + "ts-node": "^10.9.1", + "typescript": "^4.9.5" }, "dependencies": { "@types/node": { @@ -7922,7 +7754,7 @@ "@keymanapp/lm-message-types": { "version": "file:common/web/lm-message-types", "requires": { - "typescript": "^4.5.4" + "typescript": "^4.9.5" } }, "@keymanapp/lm-worker": { @@ -7958,8 +7790,8 @@ "sinon": "^7.1.1", "string.prototype.codepointat": "^0.2.1", "string.prototype.startswith": "^0.2.0", - "ts-node": "^9.1.1", - "typescript": "^4.5.4" + "ts-node": "^10.9.1", + "typescript": "^4.9.5" }, "dependencies": { "@types/node": { @@ -7983,7 +7815,7 @@ "@types/node": "^14.0.4", "chai": "^4.3.4", "mocha": "^10.0.0", - "typescript": "^4.5.4" + "typescript": "^4.9.5" }, "dependencies": { "@types/node": { @@ -7997,7 +7829,7 @@ "@keymanapp/models-types": { "version": "file:common/models/types", "requires": { - "typescript": "^4.5.4" + "typescript": "^4.9.5" } }, "@keymanapp/models-wordbreakers": { @@ -8010,8 +7842,8 @@ "@types/node": "^14.0.3", "chai": "^4.3.4", "mocha": "^10.0.0", - "ts-node": "^9.1.1", - "typescript": "^4.5.4" + "ts-node": "^10.9.1", + "typescript": "^4.9.5" }, "dependencies": { "@types/node": { @@ -8029,7 +7861,7 @@ "@keymanapp/models-types": "*", "@keymanapp/web-utils": "*", "@types/node": "^11.9.4", - "typescript": "^4.5.4" + "typescript": "^4.9.5" } }, "@keymanapp/resources-gosh": { @@ -8045,8 +7877,8 @@ "mocha": "^10.0.0", "mocha-teamcity-reporter": "^4.0.0", "sinon": "^7.1.1", - "ts-node": "^9.1.1", - "typescript": "^4.5.4" + "ts-node": "^10.9.1", + "typescript": "^4.9.5" }, "dependencies": { "@types/node": { @@ -8062,7 +7894,7 @@ "requires": { "@keymanapp/keyman-version": "*", "@sentry/browser": "^5.27.4", - "typescript": "^4.5.4" + "typescript": "^4.9.5" } }, "@keymanapp/web-utils": { @@ -8074,7 +7906,7 @@ "chai": "^4.3.4", "mocha": "^10.0.0", "mocha-teamcity-reporter": "^4.0.0", - "typescript": "^4.5.4" + "typescript": "^4.9.5" }, "dependencies": { "@types/node": { @@ -8525,10 +8357,10 @@ "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", "dev": true }, - "@socket.io/base64-arraybuffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@socket.io/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", - "integrity": "sha512-dOlCBKnDw4iShaIsH/bxujKTM18+2TOAsYz+KSc11Am38H4q5Xw8Bbz97ZYdrVNM+um3p7w86Bvvmcn9q+5+eQ==", + "@socket.io/component-emitter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", + "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==", "dev": true }, "@szmarczak/http-timer": { @@ -8590,12 +8422,6 @@ "integrity": "sha512-/ceqdqeRraGolFTcfoXNiqjyQhZzbINDngeoAq9GoHa8PPK1yNzTaxWjA6BFWp5Ua9JpXEMSS4s5i9tS0hOJtw==", "dev": true }, - "@types/component-emitter": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.11.tgz", - "integrity": "sha512-SRXjM+tfsSlA9VuG8hGO2nft2p8zjXCK1VcC6N4NXbBbYbSia9kzCChYQajIjzIqOOOuh5Ock6MmV2oux4jDZQ==", - "dev": true - }, "@types/connect": { "version": "3.4.35", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", @@ -8612,10 +8438,13 @@ "dev": true }, "@types/cors": { - "version": "2.8.12", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz", - "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==", - "dev": true + "version": "2.8.13", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.13.tgz", + "integrity": "sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA==", + "dev": true, + "requires": { + "@types/node": "*" + } }, "@types/express": { "version": "4.17.13", @@ -8747,12 +8576,6 @@ "@types/node": "*" } }, - "@ungap/promise-all-settled": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", - "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", - "dev": true - }, "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -9304,12 +9127,6 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz", "integrity": "sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==" }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, "compress-brotli": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/compress-brotli/-/compress-brotli-1.3.6.tgz", @@ -9628,9 +9445,9 @@ } }, "engine.io": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.1.3.tgz", - "integrity": "sha512-rqs60YwkvWTLLnfazqgZqLa/aKo+9cueVfEi/dZ8PyGyaf8TLOxj++4QMIgeG3Gn0AhrWiFXvghsoY9L9h25GA==", + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.4.0.tgz", + "integrity": "sha512-OgxY1c/RuCSeO/rTr8DIFXx76IzUUft86R7/P7MMbbkuzeqJoTNw2lmeD91IyGz41QYleIIjWeMJGgug043sfQ==", "dev": true, "requires": { "@types/cookie": "^0.4.1", @@ -9642,26 +9459,14 @@ "cors": "~2.8.5", "debug": "~4.3.1", "engine.io-parser": "~5.0.3", - "ws": "~8.2.3" - }, - "dependencies": { - "ws": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", - "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", - "dev": true, - "requires": {} - } + "ws": "~8.11.0" } }, "engine.io-parser": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.3.tgz", - "integrity": "sha512-BtQxwF27XUNnSafQLvDi0dQ8s3i6VgzSoQMJacpIcGNrlUdfHSKbgm3jmjCVvQluGzqwujQMPAoMai3oYSTurg==", - "dev": true, - "requires": { - "@socket.io/base64-arraybuffer": "~1.0.2" - } + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.6.tgz", + "integrity": "sha512-tjuoZDMAdEhVnSFleYPCtdL2GXwVTGtNjoeJd9IhIG3C1xs9uwxqRNEu5WpnDZCaozwVlK/nuQhpodhXSIMaxw==", + "dev": true }, "ent": { "version": "2.2.0", @@ -10376,9 +10181,9 @@ "optional": true }, "http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==" + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" }, "http-errors": { "version": "1.8.1", @@ -10939,8 +10744,8 @@ "karma-teamcity-reporter": "^1.1.0", "mocha": "^10.0.0", "modernizr": "^3.11.7", - "ts-node": "^9.1.1", - "typescript": "^4.5.4" + "ts-node": "^10.9.1", + "typescript": "^4.9.5" } }, "keyv": { @@ -11174,12 +10979,11 @@ } }, "mocha": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.0.0.tgz", - "integrity": "sha512-0Wl+elVUD43Y0BqPZBzZt8Tnkw9CMUdNYnUsTfOM1vuhJVZL+kiesFYsqwBkEEuEixaiPe5ZQdqDgX2jddhmoA==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", + "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", "dev": true, "requires": { - "@ungap/promise-all-settled": "1.1.2", "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", "chokidar": "3.5.3", @@ -12252,17 +12056,17 @@ } }, "socket.io": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.4.1.tgz", - "integrity": "sha512-s04vrBswdQBUmuWJuuNTmXUVJhP0cVky8bBDhdkf8y0Ptsu7fKU2LuLbts9g+pdmAdyMMn8F/9Mf1/wbtUN0fg==", + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.6.0.tgz", + "integrity": "sha512-b65bp6INPk/BMMrIgVvX12x3Q+NqlGqSlTuvKQWt0BUJ3Hyy3JangBl7fEoWZTXbOKlCqNPbQ6MbWgok/km28w==", "dev": true, "requires": { "accepts": "~1.3.4", "base64id": "~2.0.0", "debug": "~4.3.2", - "engine.io": "~6.1.0", - "socket.io-adapter": "~2.3.3", - "socket.io-parser": "~4.0.4" + "engine.io": "~6.4.0", + "socket.io-adapter": "~2.5.2", + "socket.io-parser": "~4.2.1" }, "dependencies": { "debug": { @@ -12277,19 +12081,21 @@ } }, "socket.io-adapter": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.3.3.tgz", - "integrity": "sha512-Qd/iwn3VskrpNO60BeRyCyr8ZWw9CPZyitW4AQwmRZ8zCiyDiL+znRnWX6tDHXnWn1sJrM1+b6Mn6wEDJJ4aYQ==", - "dev": true - }, - "socket.io-parser": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.5.tgz", - "integrity": "sha512-sNjbT9dX63nqUFIOv95tTVm6elyIU4RvB1m8dOeZt+IgWwcWklFDOdmGcfo3zSiRsnR/3pJkjY5lfoGqEe4Eig==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz", + "integrity": "sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA==", "dev": true, "requires": { - "@types/component-emitter": "^1.2.10", - "component-emitter": "~1.3.0", + "ws": "~8.11.0" + } + }, + "socket.io-parser": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.2.tgz", + "integrity": "sha512-DJtziuKypFkMMHCm2uIshOYC7QaylbtzQwiMYDuCKy3OPkjLzu4B2vAhTlqipRHHzrI0NJeBAizTK7X+6m1jVw==", + "dev": true, + "requires": { + "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.1" } }, @@ -12299,16 +12105,6 @@ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true }, - "source-map-support": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", - "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, "split": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", @@ -12538,16 +12334,23 @@ "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" }, "ts-node": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz", - "integrity": "sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==", + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", "dev": true, "requires": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", "arg": "^4.1.0", "create-require": "^1.1.0", "diff": "^4.0.1", "make-error": "^1.1.1", - "source-map-support": "^0.5.17", + "v8-compile-cache-lib": "^3.0.1", "yn": "3.1.1" }, "dependencies": { @@ -12635,9 +12438,9 @@ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" }, "typescript": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz", - "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==" + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==" }, "ua-parser-js": { "version": "0.7.33", @@ -12829,9 +12632,9 @@ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "ws": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", - "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", "requires": {} }, "xml2js": { diff --git a/package.json b/package.json index 820d3047eb..a4be80669a 100644 --- a/package.json +++ b/package.json @@ -6,8 +6,8 @@ "esbuild": "^0.15.15", "mocha": "^10.0.0", "mocha-teamcity-reporter": "^4.0.0", - "ts-node": "^9.1.1", - "typescript": "^4.5.4" + "ts-node": "^10.9.1", + "typescript": "^4.9.5" }, "scripts": {}, "workspaces": [ diff --git a/resources/build/build-utils.md b/resources/build/build-utils.md index db797a087c..2960bce4c3 100644 --- a/resources/build/build-utils.md +++ b/resources/build/build-utils.md @@ -14,7 +14,9 @@ objectives are: 2. to be self-documenting in usage (`--help` should always tell you all you need to know) 3. for the scripts to be easily readable, coherent, and straightforward for - anyone involved in the project to maintain. + anyone involved in the project to maintain +4. for dependencies to be simple (a module dependency will always be to a whole + module, not to a specific target within that module) * [Jump to API definitions](#builder-api-functions-and-variables) @@ -124,6 +126,14 @@ another script: prefixed with a `:`, for example `:app`. If no target is defined for a script, then the default target `:project` is used. + If a folder exists with the same name as a target, then that automatically + denotes the target as a "child project". This can simplify parent-child style + scripts, using the [`builder_run_child_actions`] function. + + A child project with an alternate folder can also be specified by appending + `=path` to the target definition, for example `:app=src/app`. Where possible, + avoid differences in names of child projects and folders. + * **actions**: these are the various actions that a build script can take, such as `clean`, or `build`. If no action is passed in to on a given script invocation, then the default action is `build` (unless the script defines an @@ -214,22 +224,6 @@ The following parameters are pre-defined and should not be overridden: # Builder API functions and variables - -## `builder_check_color` function - -If you wish to provide [formatting variables] in your [`builder_describe`] call, you -will need to use `builder_check_color` first. This function takes the same -parameters as [`builder_parse`]. - -### Usage - -```bash -builder_check_color "$@" -builder_describe "sample" \ - "--ci For use with action ${BUILDER_TERM_START}test${BUILDER_TERM_END} - emits CI-friendly test reports" -``` - - ## `builder_describe` function Describes a build script, defines available parameters and their meanings. Use @@ -290,10 +284,18 @@ own in the call: * `:module`: `"this module"` * `:tools`: `"build tools for this project"` +If a folder exists with the same name as a target, then that automatically +denotes the target as a "child project". This can simplify parent-child style +scripts, using the [`builder_run_child_actions`] function. + +A child project with an alternate folder can also be specified by appending +`=path` to the target definition, for example `:app=src/app`. Where possible, +avoid differences in names of child projects and folders. + **Actions** are defined as single words, for example: ```bash -builder_describe "Sample script build "install installs app on local system" +builder_describe "Sample script" build "install installs app on local system" ``` There are several predefined actions. Again, these will not be available to @@ -338,6 +340,7 @@ this, you should use `--debug,-d` to enable the shorthand form. Note that you should not include any of the [standard builder parameters] here. +-------------------------------------------------------------------------------- ## `builder_display_usage` function @@ -351,6 +354,7 @@ builder_describe "sample" clean build test builder_display_usage ``` +-------------------------------------------------------------------------------- ## `$builder_extra_params` variable @@ -370,6 +374,7 @@ array expansion format: npm test -- "${builder_extra_params[@]}" ``` +-------------------------------------------------------------------------------- ## `builder_finish_action` function @@ -412,6 +417,7 @@ with a non-zero exit code: ## [common/web/keyman-version] action:target failed with message: yeah, something failed ``` +-------------------------------------------------------------------------------- ## `builder_has_action` function @@ -429,6 +435,7 @@ fi See [`builder_start_action`] for more details. +-------------------------------------------------------------------------------- ## `builder_has_option` function @@ -464,6 +471,7 @@ if builder_has_option --path; then fi ``` +-------------------------------------------------------------------------------- ## `builder_parse` function @@ -483,6 +491,35 @@ Generally, you will always pass `"$@"` as the parameter for this call, to pass all the command line parameters from the script invocation, with automatically correct quoting and escaping. +-------------------------------------------------------------------------------- + +## `builder_run_child_actions` function + +Executes the specified actions on or all child targets, or on the specified +targets. A child target is any target which has a sub-folder of the same name as +the target. Like [`builder_start_action`], the actions will only actually be run +if they have been specified by the user on the command-line. + +The child script will be called with the applicable action, for all targets. No +options apart from standard builder options are passed through. + +### Usage + +```bash +builder_run_child_actions action1 [...] +``` + +### Parameters + + 1...: action[:target] name of action:target to run + +### Example + +```bash +builder_run_child_actions configure build test install +``` + +-------------------------------------------------------------------------------- ## `builder_start_action` function @@ -523,6 +560,22 @@ also print a log message indicating that the action has started, for example: ## [common/web/keyman-version] build:project starting... ``` +-------------------------------------------------------------------------------- + +## `builder_term` function + +Emits the parameters passed to the function, wrapped with the helper function +`builder_term`, which wraps the passed string with `$BUILDER_TERM_START` and +`$BUILDER_TERM_END`, e.g.: `$(builder_term text)`. + +### Usage + +```bash +builder_describe "sample" \ + "--ci For use with action $(builder_term test) - emits CI-friendly test reports" +``` + +-------------------------------------------------------------------------------- ## `builder_use_color` function @@ -535,6 +588,8 @@ builder_use_color true builder_use_color false ``` +-------------------------------------------------------------------------------- + ## `$builder_verbose` variable This standard variable will be set to `"--verbose"`, if the `--verbose` or `-v` @@ -553,6 +608,8 @@ if builder_has_option --verbose; then fi ``` +-------------------------------------------------------------------------------- + ## Formatting variables These helper variables define ANSI color escapes when running in color mode, and @@ -571,9 +628,10 @@ resolve either to empty string (for `$COLOR_*`), or equivalent plain-text forms * `$HEADING_SETMARK`: Add a setmark, e.g. with VSCode +Note: it is recommended that you use `$(builder_term text)` instead of +`${BUILDER_TERM_START}text${BUILDER_TERM_END}`. [standard builder parameters]: #standard-builder-parameters -[`builder_check_color`]: #buildercheckcolor-function [`builder_describe`]: #builderdescribe-function [`builder_display_usage`]: #builderdisplayusage-function [`$builder_extra_params`]: #builderextraparams-variable @@ -585,3 +643,4 @@ resolve either to empty string (for `$COLOR_*`), or equivalent plain-text forms [`builder_use_color`]: #builderusecolor-function [`$builder_verbose`]: #builderverbose-variable [formatting variables]: #formatting-variables +[`builder_run_child_actions`]: #builderrunchildactions-function \ No newline at end of file diff --git a/resources/build/increment-version.sh b/resources/build/increment-version.sh index fd0bc7add8..4e57f04cb3 100755 --- a/resources/build/increment-version.sh +++ b/resources/build/increment-version.sh @@ -143,7 +143,7 @@ if [ "$action" == "commit" ]; then popd > /dev/null # - # Trigger builds for the previous version on TeamCity and Jenkins + # Trigger builds for the previous version on TeamCity, Jenkins and GitHub # triggerBuilds diff --git a/resources/build/run-required-test-builds.sh b/resources/build/run-required-test-builds.sh index 5213c6b5c7..400dd4f8bc 100755 --- a/resources/build/run-required-test-builds.sh +++ b/resources/build/run-required-test-builds.sh @@ -58,6 +58,10 @@ function triggerTestBuilds() { local job=${test_build%_Jenkins} echo " -- Triggering build configuration $job/$branch on Jenkins" triggerJenkinsBuild "$job" "$branch" "$force" + elif [ "${test_build:(-7)}" == "_GitHub" ]; then + local job=${test_build%_GitHub} + echo " -- Triggering GitHub action build $job/$branch" + triggerGitHubActionsBuild true "$job" "$branch" else echo " -- Triggering build configuration $test_build on teamcity" triggerTeamCityBuild true "$test_build" "$vcs_test" "$branch" @@ -172,11 +176,21 @@ while IFS= read -r line; do done <<< "$prfiles" debug_echo "Build platforms: ${build_platforms[*]}" -# -# Start the test builds -# -echo ". Start test builds" -triggerTestBuilds "`echo ${build_platforms[@]}`" "$PRNUM" +if (( ${#build_platforms[@]} > 0)); then + # + # Start the test builds + # + echo ". Start test builds" + triggerTestBuilds "`echo ${build_platforms[@]}`" "$PRNUM" +else + echo ". No builds to start" + curl --silent --write-out '\n' \ + --request POST \ + --header "Accept: application/vnd.github+json" \ + --header "Authorization: token $GITHUB_TOKEN" \ + --data '{"state":"success","description":"Skipping since no platform builds necessary","context":"Test Build (Keyman)"}' \ + "https://api.github.com/repos/keymanapp/keyman/statuses/${BUILD_VCS_NUMBER}" +fi exit 0 diff --git a/resources/build/tests/dependencies/.gitignore b/resources/build/tests/dependencies/.gitignore new file mode 100644 index 0000000000..78f329d318 --- /dev/null +++ b/resources/build/tests/dependencies/.gitignore @@ -0,0 +1 @@ +**/out.* \ No newline at end of file diff --git a/resources/build/tests/dependencies/app/build.sh b/resources/build/tests/dependencies/app/build.sh new file mode 100755 index 0000000000..83bf37f91f --- /dev/null +++ b/resources/build/tests/dependencies/app/build.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash + +set -eu + +## START STANDARD BUILD SCRIPT INCLUDE +# adjust relative paths as necessary +THIS_SCRIPT="$(greadlink -f "${BASH_SOURCE[0]}" 2>/dev/null || readlink -f "${BASH_SOURCE[0]}")" +. "$(dirname "$THIS_SCRIPT")/../../../build-utils.sh" +# END STANDARD BUILD SCRIPT INCLUDE + +cd "$THIS_SCRIPT_PATH" + +# Test builder_describe_outputs and dependencies + +builder_describe "app test module" \ + @../library \ + configure \ + build + +builder_parse "$@" + +builder_describe_outputs \ + configure:project out.configure \ + build:project out.build + +if builder_start_action clean:project; then + rm -f out.configure out.build + builder_finish_action success clean:project +fi + +if builder_start_action configure:project; then + echo " ... doing the 'configure' action for 'app'" + touch out.configure + builder_finish_action success configure:project +fi + +if builder_start_action build:project; then + echo " ... doing the 'build' action for 'app'" + touch out.build + builder_finish_action success build:project +fi diff --git a/resources/build/tests/dependencies/library/build.sh b/resources/build/tests/dependencies/library/build.sh new file mode 100755 index 0000000000..34dae97fe8 --- /dev/null +++ b/resources/build/tests/dependencies/library/build.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash + +set -eu + +## START STANDARD BUILD SCRIPT INCLUDE +# adjust relative paths as necessary +THIS_SCRIPT="$(greadlink -f "${BASH_SOURCE[0]}" 2>/dev/null || readlink -f "${BASH_SOURCE[0]}")" +. "$(dirname "$THIS_SCRIPT")/../../../build-utils.sh" +# END STANDARD BUILD SCRIPT INCLUDE + +cd "$THIS_SCRIPT_PATH" + +# Test builder_describe_outputs and dependencies + +builder_describe "library test module" \ + clean \ + configure \ + build + +builder_parse "$@" + +builder_describe_outputs \ + configure:project out.configure \ + build:project out.build + +if builder_start_action clean:project; then + rm -f out.configure out.build + builder_finish_action success clean:project +fi + +if builder_start_action configure:project; then + echo " ... doing the 'configure' action for 'library'" + touch out.configure + builder_finish_action success configure:project +fi + +if builder_start_action build:project; then + echo " ... doing the 'build' action for 'library'" + touch out.build + builder_finish_action success build:project +fi diff --git a/resources/build/tests/trees/.gitignore b/resources/build/tests/trees/.gitignore new file mode 100644 index 0000000000..4ed4ecc8ed --- /dev/null +++ b/resources/build/tests/trees/.gitignore @@ -0,0 +1 @@ +child?.* \ No newline at end of file diff --git a/resources/build/tests/trees/build.sh b/resources/build/tests/trees/build.sh new file mode 100755 index 0000000000..13d3816367 --- /dev/null +++ b/resources/build/tests/trees/build.sh @@ -0,0 +1,81 @@ +#!/usr/bin/env bash + +set -eu + +## START STANDARD BUILD SCRIPT INCLUDE +# adjust relative paths as necessary +THIS_SCRIPT="$(greadlink -f "${BASH_SOURCE[0]}" 2>/dev/null || readlink -f "${BASH_SOURCE[0]}")" +. "$(dirname "$THIS_SCRIPT")/../../build-utils.sh" +# END STANDARD BUILD SCRIPT INCLUDE + +cd "$THIS_SCRIPT_PATH" + +# Test builder_describe_outputs and dependencies + +builder_describe "parent test module" \ + :child1 \ + :child2 \ + :child3=child3_renamed/src \ + clean \ + configure \ + build \ + test \ + install \ + error + +builder_parse "$@" + +# All child actions will generate files which we need to verify for test +rm -f ./child?.* + +function test_present() { + local target=$1 + local action=$2 + + local CHECK="${COLOR_GREEN}✔${COLOR_RESET}" # ✔ + local CROSS="${COLOR_RED}❌${COLOR_RESET}" # ❌ + + if builder_has_action $action:$target; then + if [ ! -f $target.$action ]; then + builder_die "$CROSS FAIL: ./$target.$action to be present" + else + echo "$CHECK PASS: ./$target.$action found as expected" + fi + fi +} + +# We need to specify the order to run actions in the parent script +# +# This may looks as simple as: +# +# builder_run_child_actions clean configure build test install +# +builder_run_child_actions clean +test_present child1 clean +test_present child2 clean +test_present child3 clean + +builder_run_child_actions configure +test_present child1 configure +test_present child2 configure +test_present child3 configure + +# Test chaining commands in a single statement +builder_run_child_actions build test +test_present child1 build +test_present child2 build +test_present child3 build +test_present child1 test +test_present child2 test +test_present child3 test + +# We are customising the order in which child scripts are installed, so 2 goes before 1 +builder_run_child_actions install:child2 +test_present child2 install + +builder_run_child_actions install:child1 +test_present child1 install + +builder_run_child_actions error + +echo Done \ No newline at end of file diff --git a/resources/build/tests/trees/child1/build.sh b/resources/build/tests/trees/child1/build.sh new file mode 100755 index 0000000000..795e11e6d3 --- /dev/null +++ b/resources/build/tests/trees/child1/build.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash + +set -eu + +## START STANDARD BUILD SCRIPT INCLUDE +# adjust relative paths as necessary +THIS_SCRIPT="$(greadlink -f "${BASH_SOURCE[0]}" 2>/dev/null || readlink -f "${BASH_SOURCE[0]}")" +. "$(dirname "$THIS_SCRIPT")/../../../build-utils.sh" +# END STANDARD BUILD SCRIPT INCLUDE + +cd "$THIS_SCRIPT_PATH" + +# Test builder_describe_outputs and dependencies + +project=child1 + +builder_describe "$project test module" \ + clean \ + configure \ + build \ + test \ + install \ + error + +builder_parse "$@" + +function test_action() { + local action=$1 + + if builder_start_action $action; then + touch ../$project.$action + builder_finish_action success $action + fi +} + +test_action clean +test_action configure +test_action build +test_action test +test_action install + +if builder_start_action error; then + builder_die "This error action is supposed to die" +fi \ No newline at end of file diff --git a/resources/build/tests/trees/child2/build.sh b/resources/build/tests/trees/child2/build.sh new file mode 100755 index 0000000000..cbf048ea26 --- /dev/null +++ b/resources/build/tests/trees/child2/build.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash + +set -eu + +## START STANDARD BUILD SCRIPT INCLUDE +# adjust relative paths as necessary +THIS_SCRIPT="$(greadlink -f "${BASH_SOURCE[0]}" 2>/dev/null || readlink -f "${BASH_SOURCE[0]}")" +. "$(dirname "$THIS_SCRIPT")/../../../build-utils.sh" +# END STANDARD BUILD SCRIPT INCLUDE + +cd "$THIS_SCRIPT_PATH" + +# Test builder_describe_outputs and dependencies + +project=child2 + +builder_describe "$project test module" \ + clean \ + configure \ + build \ + test \ + install \ + error + +builder_parse "$@" + +function test_action() { + local action=$1 + + if builder_start_action $action; then + touch ../$project.$action + builder_finish_action success $action + fi +} + +test_action clean +test_action configure +test_action build +test_action test +test_action install + +if builder_start_action error; then + builder_die "This error action is supposed to die" +fi \ No newline at end of file diff --git a/resources/build/tests/trees/child3_renamed/src/build.sh b/resources/build/tests/trees/child3_renamed/src/build.sh new file mode 100755 index 0000000000..508cc0293f --- /dev/null +++ b/resources/build/tests/trees/child3_renamed/src/build.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash + +set -eu + +## START STANDARD BUILD SCRIPT INCLUDE +# adjust relative paths as necessary +THIS_SCRIPT="$(greadlink -f "${BASH_SOURCE[0]}" 2>/dev/null || readlink -f "${BASH_SOURCE[0]}")" +. "$(dirname "$THIS_SCRIPT")/../../../../build-utils.sh" +# END STANDARD BUILD SCRIPT INCLUDE + +cd "$THIS_SCRIPT_PATH" + +# Test builder_describe_outputs and dependencies + +project=child3 + +builder_describe "$project test module" \ + clean \ + configure \ + build \ + test \ + install \ + error + +builder_parse "$@" + +function test_action() { + local action=$1 + + if builder_start_action $action; then + touch ../../$project.$action + builder_finish_action success $action + fi +} + +test_action clean +test_action configure +test_action build +test_action test +test_action install + +if builder_start_action error; then + builder_die "This error action is supposed to die" +fi \ No newline at end of file diff --git a/resources/build/tests/trees/test.sh b/resources/build/tests/trees/test.sh new file mode 100755 index 0000000000..284e3ec8f7 --- /dev/null +++ b/resources/build/tests/trees/test.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +set -eu + +./build.sh clean configure build install test +if [ $(ls child?.* | wc -l) -ne 14 ]; then + echo unexpected output file count + exit 1 +fi + +./build.sh error && (echo should not have passed; exit 1) || (echo " ... build returned error as expected") + +./build.sh install:child1 test:child2 +if [ $(ls child?.* | wc -l) -ne 2 ]; then + echo unexpected output file count + exit 1 +fi \ No newline at end of file diff --git a/resources/build/trigger-builds.inc.sh b/resources/build/trigger-builds.inc.sh index 35234c43c0..ac8d519d4a 100644 --- a/resources/build/trigger-builds.inc.sh +++ b/resources/build/trigger-builds.inc.sh @@ -21,6 +21,10 @@ function triggerBuilds() { local job=${build%_Jenkins} echo Triggering Jenkins build "$job" "$base" "true" triggerJenkinsBuild "$job" "$base" "true" + elif [ "${build:(-7)}" == "_GitHub" ]; then + local job=${build%_GitHub} + echo Triggering GitHub action build "$job" "$base" + triggerGitHubActionsBuild false "$job" "$base" else echo Triggering TeamCity build false $build $TEAMCITY_VCS_ID $base triggerTeamCityBuild false $build $TEAMCITY_VCS_ID $base @@ -96,6 +100,7 @@ function triggerJenkinsBuild() { if echo "$OUTPUT" | grep -q "\"triggered\":true"; then echo -n " job triggered: " else + echo "##teamcity[buildProblem description='Triggering Jenkins build failed']" echo -n " triggering failed: " fi @@ -119,3 +124,47 @@ function triggerJenkinsBuild() { echo fi } + +function triggerGitHubActionsBuild() { + local IS_TEST_BUILD="$1" + local GITHUB_ACTION="$2" + local GIT_BRANCH="${3:-master}" + local GIT_REF GIT_SHA + + local GITHUB_SERVER=https://api.github.com/repos/keymanapp/keyman/dispatches + + if [ "${action:-""}" == "commit" ]; then + # This will only be true if we created and pushed a tag + GIT_REF="refs/tags/release@$VERSION_WITH_TAG" + GIT_SHA="$(git rev-parse "${GIT_REF}")" + GIT_EVENT_TYPE="${GITHUB_ACTION}: release@${VERSION_WITH_TAG}" + elif [[ $GIT_BRANCH != stable-* ]] && [[ $GIT_BRANCH =~ [0-9]+ ]]; then + GIT_REF="refs/pull/${GIT_BRANCH}/merge" + GIT_SHA="$(git rev-parse "refs/pull/${GIT_BRANCH}/head")" + GIT_EVENT_TYPE="${GITHUB_ACTION}: PR #${GIT_BRANCH}" + GIT_BRANCH="PR-${GIT_BRANCH}" + else + GIT_REF="refs/heads/${GIT_BRANCH}" + GIT_SHA="$(git rev-parse "${GIT_REF}")" + GIT_EVENT_TYPE="${GITHUB_ACTION}: ${GIT_BRANCH}" + fi + + local DATA="{\"event_type\": \"$GIT_EVENT_TYPE\", \ + \"client_payload\": { \ + \"ref\": \"$GIT_REF\", \ + \"sha\": \"$GIT_SHA\", \ + \"branch\": \"$GIT_BRANCH\", \ + \"isTestBuild\": \"$IS_TEST_BUILD\" \ + }}" + + echo "GitHub Action Data: $DATA" + + # adjust indentation for output of curl + echo -n " " + curl --silent --write-out '\n' \ + --request POST \ + --header "Accept: application/vnd.github+json" \ + --header "Authorization: token $GITHUB_TOKEN" \ + --data "$DATA" \ + $GITHUB_SERVER +} diff --git a/resources/build/trigger-definitions.inc.sh b/resources/build/trigger-definitions.inc.sh index 9224d407df..70a1b89adc 100644 --- a/resources/build/trigger-definitions.inc.sh +++ b/resources/build/trigger-definitions.inc.sh @@ -27,6 +27,7 @@ watch_developer='common|core|web' # _Jenkins should be appended to any build configuration (pipeline) name that is from Jenkins, # not TeamCity. # +# _GitHub should be appended to any build configuration name that is from GitHub, not TeamCity. # Test Build Configurations @@ -35,7 +36,7 @@ bc_test_all=() bc_test_android=(KeymanAndroid_TestPullRequests KeymanAndroid_TestSamplesAndTestProjects) bc_test_ios=(Keyman_iOS_TestPullRequests Keyman_iOS_TestSamplesAndTestProjects) -bc_test_linux=(KeymanLinux_TestPullRequests Keyman_Common_KPAPI_TestPullRequests_Linux pipeline-keyman-packaging_Jenkins) +bc_test_linux=(KeymanLinux_TestPullRequests Keyman_Common_KPAPI_TestPullRequests_Linux pipeline-keyman-packaging_Jenkins deb-pr-packaging_GitHub) bc_test_mac=(Keyman_KeymanMac_PullRequests Keyman_Common_KPAPI_TestPullRequests_macOS) bc_test_windows=(KeymanDesktop_TestPullRequests KeymanDesktop_TestPrRenderOnScreenKeyboards Keyman_Common_KPAPI_TestPullRequests_Windows) bc_test_web=(Keymanweb_TestPullRequests Keyman_Common_LMLayer_TestPullRequests Keyman_Common_KPAPI_TestPullRequests_WASM) @@ -49,7 +50,7 @@ vcs_test=HttpsGithubComKeymanappKeymanPRs bc_master_android=(KeymanAndroid_Build) bc_master_ios=(Keyman_iOS_Master) -bc_master_linux=(KeymanLinux_Master pipeline-keyman-packaging_Jenkins) +bc_master_linux=(KeymanLinux_Master pipeline-keyman-packaging_Jenkins deb-release-packaging_GitHub) bc_master_mac=(KeymanMac_Master) bc_master_windows=(Keyman_Build) bc_master_web=(Keymanweb_Build) @@ -61,7 +62,7 @@ vcs_master=HttpsGithubComKeymanappKeyman bc_beta_android=(KeymanAndroid_Build) bc_beta_ios=(Keyman_iOS_Master) -bc_beta_linux=(KeymanLinux_Master pipeline-keyman-packaging_Jenkins) +bc_beta_linux=(KeymanLinux_Master pipeline-keyman-packaging_Jenkins deb-release-packaging_GitHub) bc_beta_mac=(KeymanMac_Master) bc_beta_windows=(Keyman_Build) bc_beta_web=(Keymanweb_Build) @@ -73,7 +74,7 @@ vcs_beta=HttpsGithubComKeymanappKeyman bc_stable_14_0_android=(KeymanAndroid_Build) bc_stable_14_0_ios=(Keyman_iOS_Master) -bc_stable_14_0_linux=(KeymanLinux_Master pipeline-keyman-packaging_Jenkins) +bc_stable_14_0_linux=(KeymanLinux_Master pipeline-keyman-packaging_Jenkins deb-release-packaging_GitHub) bc_stable_14_0_mac=(KeymanMac_Master) bc_stable_14_0_windows=(Keyman_Build) bc_stable_14_0_web=(Keymanweb_Build) @@ -88,7 +89,7 @@ vcs_stable_14_0=HttpsGithubComKeymanappKeyman bc_stable_15_0_android=(KeymanAndroid_Build) bc_stable_15_0_ios=(Keyman_iOS_Master) -bc_stable_15_0_linux=(KeymanLinux_Master pipeline-keyman-packaging_Jenkins) +bc_stable_15_0_linux=(KeymanLinux_Master pipeline-keyman-packaging_Jenkins deb-release-packaging_GitHub) bc_stable_15_0_mac=(KeymanMac_Master) bc_stable_15_0_windows=(Keyman_Build) bc_stable_15_0_web=(Keymanweb_Build) diff --git a/resources/build/version/package.json b/resources/build/version/package.json index 5902dce8cc..8f639b50cc 100644 --- a/resources/build/version/package.json +++ b/resources/build/version/package.json @@ -2,7 +2,7 @@ "dependencies": { "@actions/core": "^1.9.1", "@actions/github": "^2.1.0", - "typescript": "^4.5.4", + "typescript": "^4.9.5", "yargs": "^15.1.0" }, "description": "Automatically updates HISTORY.md based on pull requests", @@ -10,10 +10,10 @@ "@types/node": "^13.7.0", "@types/semver": "^7.1.0", "semver": "^7.1.2", - "ts-node": "^8.6.2" + "ts-node": "^10.9.1" }, "engines": { - "node": "16" + "node": ">=16.0" }, "files": [ "src" diff --git a/resources/builder.inc.sh b/resources/builder.inc.sh index 4234df67d7..9c81e3b38d 100755 --- a/resources/builder.inc.sh +++ b/resources/builder.inc.sh @@ -19,7 +19,7 @@ function _builder_init() { _builder_findRepoRoot _builder_setBuildScriptIdentifiers - if [[ -n "$TERM" ]] && [[ "$TERM" != "dumb" ]] && [[ "$TERM" != "unknown" ]]; then + if [[ -n "$TERM" ]] && [[ "$TERM" != "dumb" ]] && [[ "$TERM" != "unknown" ]] && [ -t 1 ]; then builder_use_color true else builder_use_color false @@ -109,13 +109,25 @@ builder_use_color() { fi } +# +# Wraps the input string in `builder_display_usage` with $BUILDER_TERM_START and +# $BUILDER_TERM_END +# +function builder_term() { + echo "${BUILDER_TERM_START}$*${BUILDER_TERM_END}" +} + function builder_die() { echo - echo "${COLOR_RED}$*" + echo "${COLOR_RED}$*${COLOR_RESET}" echo exit 1 } +function builder_warn() { + echo "${COLOR_YELLOW}$*${COLOR_RESET}" +} + #################################################################################### # # builder_ functions for standard build script parameter and process management @@ -126,7 +138,13 @@ function builder_die() { # builder_ names are reserved. # _builder_ names are internal use and subject to change # -_builder_debug=false +if [ -z ${_builder_debug+x} ]; then + _builder_debug=false +fi + +if $_builder_debug; then + echo "[DEBUG] Command line: $0 $@" +fi # # builder_extra_params: string containing all parameters after '--' @@ -241,6 +259,90 @@ _builder_cleanup_deps() { fi } +_builder_execute_child() { + local action=$1 + local target=$2 + + local scope="[$THIS_SCRIPT_IDENTIFIER] " + local script="$THIS_SCRIPT_PATH/${_builder_target_paths[$target]}/build.sh" + + if $_builder_debug; then + echo "${COLOR_BLUE}## $scope$action$target starting...${COLOR_RESET}" + fi + + "$script" $action \ + $builder_verbose \ + $builder_debug \ + && ( + if $_builder_debug; then + echo "${COLOR_GREEN}## $scope$action$target completed successfully${COLOR_RESET}" + fi + ) || ( + result=$? + echo "${COLOR_RED}## $scope$action$target failed with exit code $result${COLOR_RESET}" + exit $result + ) +} + +_builder_run_child_action() { + local action="$1" target + + if [[ $action =~ : ]]; then + IFS=: read -r action target <<< $action + target=:$target + else + target=':*' + fi + + if builder_has_action $action$target; then + if [[ $target == ':*' ]]; then + # run all children in order specified in builder_describe + for target in "${_builder_targets[@]}"; do + # We have to re-test the action because the user may not + # have specified all targets in their invocation + if builder_has_action $action$target; then + if [ -f "$THIS_SCRIPT_PATH/${_builder_target_paths[$target]}/build.sh" ]; then + _builder_execute_child $action $target + fi + fi + done + else + # If specified explicitly, we assume existence of a child build script. + _builder_execute_child $action $target + fi + fi +} + +# +# Executes the specified actions on all child targets, or on the specified +# targets. A child target is any target which has a sub-folder of the same name +# as the target. However, the actions will only be run if they have been +# specified by the user on the command-line. +# +# ### Usage +# +# ```bash +# builder_run_child_actions action1 [...] +# ``` +# +# ### Parameters +# +# 1...: action[:target] name of action:target to run +# +# ### Example +# +# ```bash +# builder_run_child_actions configure build test install +# ``` +# +builder_run_child_actions() { + while [[ $# -gt 0 ]]; do + local action="$1" + _builder_run_child_action "$action" + shift + done +} + # # Builds the standardized `action:target` string for the specified action-target # pairing and also returns 0 if the user has asked to perform it on the command @@ -256,9 +358,11 @@ _builder_cleanup_deps() { # if build_has_action action[:target]; then ...; fi # ```` # -# Parameters: +# ### Parameters +# # 1: action[:target] name of action:target -# Example: +# +# ### Example # # ```bash # if builder_has_action build:app; then ... @@ -462,9 +566,16 @@ _builder_expand_action_targets() { # default, append a `+` to the action name, e.g. `"test+ Test the project"`. # If there is no default specified, then it will be `build`. # -# * **Target:** `":target [One line description]"` +# * **Target:** `":target[=path] [One line description]"` # -# A target always starts with colon, e.g. `:project`. +# A target always starts with colon, e.g. `:project`. If a folder exists with +# the same name as a target, then that automatically denotes the target as a +# "child project". This can simplify parent-child style scripts, using the +# [`builder_run_child_actions`] function. +# +# A child project with an alternate folder can also be specified by appending +# `=path` to the target definition, for example `:app=src/app`. Where +# possible, avoid differences in names of child projects and folders. # # * **Dependency:** "@/path/to/dependency [action][:target] ..." # @@ -482,6 +593,8 @@ _builder_expand_action_targets() { # specified, space separated. # builder_describe() { + _builder_record_function_call builder_describe + _builder_description="$1" _builder_actions=() _builder_targets=() @@ -494,6 +607,7 @@ builder_describe() { declare -A -g _builder_dep_path # array of output files for action:target pairs declare -A -g _builder_dep_related_actions # array of action:targets associated with a given dependency declare -A -g _builder_internal_dep # array of internal action:targets dependency relationships + declare -A -g _builder_target_paths # array of target child project paths shift # describe each target, action, and option possibility while [[ $# -gt 0 ]]; do @@ -506,7 +620,25 @@ builder_describe() { if [[ $value =~ ^: ]]; then # Parameter is a target + local target_path= + if [[ $value =~ = ]]; then + # The target has a custom child project path + target_path="$(echo "$value" | cut -d= -f 2 -)" + value="$(echo "$value" | cut -d= -f 1 -)" + if [[ ! -d "$THIS_SCRIPT_PATH/$target_path" ]]; then + builder_die "Target path '$target_path' for $value does not exist." + fi + else + # If the target name matches a folder name, implicitly + # make it available as a child project + if [[ -d "$THIS_SCRIPT_PATH/${value:1}" ]]; then + target_path="${value:1}" + fi + fi _builder_targets+=($value) + if [[ ! -z "$target_path" ]]; then + _builder_target_paths[$value]="$target_path" + fi elif [[ $value =~ ^@ ]]; then # Parameter is a dependency local dependency="${value:1}" @@ -599,6 +731,8 @@ builder_describe() { # ``` # function builder_describe_outputs() { + _builder_record_function_call builder_describe_outputs + while [[ $# -gt 0 ]]; do local key="$1" path="$2" action target path="`_builder_expand_relative_path "$path"`" @@ -620,6 +754,11 @@ function builder_describe_outputs() { done _builder_define_default_internal_dependencies + + # We only want to define internal dependencies after both builder_parse and builder_describe_outputs have been called + if _builder_has_function_been_called builder_parse; then + _builder_add_chosen_action_target_dependencies + fi } _builder_get_default_description() { @@ -652,16 +791,14 @@ _builder_parameter_error() { } -# Pre-initializes the color setting based on the options specified to a -# a build.sh script, parsing the command line to do so. This is only -# needed if said script wishes to use this script's defined colors while -# respecting the options provided by the script's caller. # -# Usage: -# builder_check_color "$@" +# Pre-initializes the color setting based on the options specified to a +# a build.sh script. This is called automatically during init. +# # Parameters -# 1: $@ all command-line arguments (as with builder_parse) -builder_check_color() { +# 1: "$@" all command-line arguments +# +_builder_check_color() { # Process command-line arguments while [[ $# -gt 0 ]] ; do local key="$1" @@ -690,16 +827,18 @@ _builder_add_chosen_action_target_dependencies() { while (( $i < ${#_builder_chosen_action_targets[@]} )); do action_target=${_builder_chosen_action_targets[$i]} - # If we have an internal dependency for the chosen action:target pair, add - # it to the list, but only if there is a defined output and that output is - # missing + # If we have an internal dependency for the chosen action:target pair if [[ ! -z ${_builder_internal_dep[$action_target]+x} ]]; then local dep_output=${_builder_internal_dep[$action_target]} - if [[ ! -z ${_builder_dep_path[$dep_output]+x} ]] && - [[ ! -e "$KEYMAN_ROOT/${_builder_dep_path[$dep_output]}" ]]; then - if ! _builder_item_in_array "$dep_output" "${_builder_chosen_action_targets[@]}"; then - _builder_chosen_action_targets+=($dep_output) - new_actions+=($dep_output) + # If there is a defined output for this dependency + if [[ ! -z ${_builder_dep_path[$dep_output]+x} ]]; then + # If the output for the dependency is missing, or we have --force-deps + if [[ ! -e "$KEYMAN_ROOT/${_builder_dep_path[$dep_output]}" ]] || builder_is_full_dep_build; then + # Add the dependency to the chosen action:target list + if ! _builder_item_in_array "$dep_output" "${_builder_chosen_action_targets[@]}"; then + _builder_chosen_action_targets+=($dep_output) + new_actions+=($dep_output) + fi fi fi fi @@ -707,7 +846,11 @@ _builder_add_chosen_action_target_dependencies() { done if [[ ${#new_actions[@]} -gt 0 ]]; then - echo "Automatically running following required actions with missing outputs:" + if builder_is_full_dep_build; then + echo "Automatically running all dependency actions due to --force-deps:" + else + echo "Automatically running following required actions with missing outputs:" + fi for e in "${new_actions[@]}"; do echo "* $e" done @@ -752,6 +895,9 @@ _builder_define_default_internal_dep() { # Parameters # 1: $@ command-line arguments builder_parse() { + + _builder_record_function_call builder_parse + _builder_build_deps=--deps builder_verbose= builder_debug= @@ -876,7 +1022,10 @@ builder_parse() { done fi - _builder_add_chosen_action_target_dependencies + # We only want to define internal dependencies after both builder_parse and builder_describe_outputs have been called + if _builder_has_function_been_called builder_describe_outputs; then + _builder_add_chosen_action_target_dependencies + fi if $_builder_debug; then echo "[DEBUG] Selected actions and targets:" @@ -1118,7 +1267,7 @@ builder_is_dep_build() { # `--deps` parameter (which is the default). # builder_is_quick_dep_build() { - if builder_is_dep_build && [[ $_builder_build_deps == --deps ]]; then + if [[ $_builder_build_deps == --deps ]]; then return 0 fi return 1 @@ -1129,7 +1278,7 @@ builder_is_quick_dep_build() { # corresponds to the `--force-deps`` parameter. # builder_is_full_dep_build() { - if builder_is_dep_build && [[ $_builder_build_deps == --force-deps ]]; then + if [[ $_builder_build_deps == --force-deps ]]; then return 0 fi return 1 @@ -1246,7 +1395,33 @@ _builder_report_dependencies() { exit 0 } +# +# Track whether functions have already been called; +# later we may use this to prevent multiple calls to, e.g. +# builder_describe +# + +_builder_function_calls=() + +_builder_record_function_call() { + local func=$1 + if _builder_has_function_been_called $1; then + # builder_die "ERROR: $func cannot be called more than once." + return 0 + fi + _builder_function_calls+=($1) +} + +_builder_has_function_been_called() { + local func=$1 + if _builder_item_in_array $1 "${_builder_function_calls[@]}"; then + return 0 + fi + return 1 +} + # # Initialize builder once all functions are declared # _builder_init +_builder_check_color "$@" diff --git a/web/build.sh b/web/build.sh index c67b2ae6d3..ef59d80cb9 100755 --- a/web/build.sh +++ b/web/build.sh @@ -85,13 +85,6 @@ compilecmd="$compiler" PREDICTIVE_TEXT_SOURCE="../common/predictive-text/unit_tests/in_browser/resources/models/simple-trie.js" PREDICTIVE_TEXT_OUTPUT="src/test/manual/web/prediction-ui/simple-en-trie.js" -builder_check_color "$@" - -DOC_WEB_PRODUCT="${BUILDER_TERM_START}:web${BUILDER_TERM_END} build product" -DOC_TEST_WEB="${BUILDER_TERM_START}test:web${BUILDER_TERM_END}" -DOC_BUILD_EMBED_WEB="${BUILDER_TERM_START}build:embed${BUILDER_TERM_END} and ${BUILDER_TERM_START}build:web${BUILDER_TERM_END}" -DOC_TEST_SYMBOL="actions - ${BUILDER_TERM_START}test${BUILDER_TERM_END}" - builder_describe "Builds Keyman Engine for Web (KMW)." \ "@../common/web/keyman-version build" \ "@../common/web/input-processor build" \ @@ -99,18 +92,18 @@ builder_describe "Builds Keyman Engine for Web (KMW)." \ "clean" \ "configure" \ "build" \ - "test Runs unit tests. Only ${DOC_TEST_WEB} is currently defined" \ + "test Runs unit tests. Only $(builder_term test:web) is currently defined" \ ":embed Builds the configuration of KMW used within the Keyman mobile apps" \ ":engine Builds all common code used by other targets" \ ":web Builds the website-oriented configuration of Keyman Engine for Web" \ - ":ui Builds the desktop UI modules used by the ${DOC_WEB_PRODUCT}" \ + ":ui Builds the desktop UI modules used by the $(builder_term :web) build product" \ ":samples Builds only sample & test pages found under src/samples and src/test" \ ":tools Builds related development + unit-test resources" \ - "--no-minify Skips any minification steps in the build" \ - "--all Sets action to run on KMW's submodules as well if appropriate ($DOC_TEST_SYMBOL)" + "--no-minify Skips any minification steps in the build" \ + "--all Sets action to run on KMW's submodules as well if appropriate (actions - $(builder_term test))" # Possible TODO? -# "upload-symbols Uploads build product to Sentry for error report symbolification. Only defined for $DOC_BUILD_EMBED_WEB" \ +# "upload-symbols Uploads build product to Sentry for error report symbolification. Only defined for $(builder_term build:embed) and $(builder_term build:web)" \ builder_describe_outputs \ configure ../node_modules \ diff --git a/web/package.json b/web/package.json index 08687f65d3..386f82ae2a 100644 --- a/web/package.json +++ b/web/package.json @@ -38,8 +38,8 @@ "karma-teamcity-reporter": "^1.1.0", "mocha": "^10.0.0", "modernizr": "^3.11.7", - "ts-node": "^9.1.1", - "typescript": "^4.5.4" + "ts-node": "^10.9.1", + "typescript": "^4.9.5" }, "scripts": { "tsc": "tsc", diff --git a/web/src/engine/build.sh b/web/src/engine/build.sh index 16316c8983..89fdc7d8da 100755 --- a/web/src/engine/build.sh +++ b/web/src/engine/build.sh @@ -81,8 +81,6 @@ PATH="../../../node_modules/.bin:$PATH" compiler="npm run tsc --" compilecmd="$compiler" -builder_check_color "$@" - builder_describe "Builds engine modules for Keyman Engine for Web (KMW)." \ "@../../../common/web/keyman-version build:main" \ "@../../../common/web/input-processor build:main" \ @@ -97,10 +95,10 @@ builder_describe "Builds engine modules for Keyman Engine for Web (KMW)." \ # "upload-symbols Uploads build product to Sentry for error report symbolification. Only defined for $DOC_BUILD_EMBED_WEB" \ builder_describe_outputs \ - configure ../node_modules \ - configure:device-detect ../node_modules \ - configure:element-wrappers ../node_modules \ - configure:main ../node_modules \ + configure ../../../node_modules \ + configure:device-detect ../../../node_modules \ + configure:element-wrappers ../../../node_modules \ + configure:main ../../../node_modules \ build:device-detect $(output_path $DEVICEDETECT $OUTPUT_DIR)/index.js \ build:element-wrappers $(output_path $ELEMENTWRAPPERS $OUTPUT_DIR)/index.js \ build:main $(output_path $MAIN $OUTPUT_DIR)/keymanweb.js diff --git a/web/test.sh b/web/test.sh index 6f4fad0461..bfd19cfb47 100755 --- a/web/test.sh +++ b/web/test.sh @@ -16,17 +16,15 @@ cd "$THIS_SCRIPT_PATH" ################################ Main script ################################ -builder_check_color "$@" - builder_describe "Runs the Keyman Engine for Web unit-testing suites" \ "@./src/tools/testing/recorder test:engine" \ "@./src/engine" \ "test+" \ ":engine Runs the top-level Keyman Engine for Web unit tests" \ ":libraries Runs all unit tests for KMW's submodules. Currently excludes predictive-text tests" \ - "--ci Set to utilize CI-based test configurations & reporting. May not be set with ${BUILDER_TERM_START}--debug${BUILDER_TERM_END}." \ + "--ci Set to utilize CI-based test configurations & reporting. May not be set with $(builder_term --debug)." \ "--reporters=REPORTERS Set to override the 'reporters' used by the unit testing engines" \ - "--browsers=BROWSERS Set to override automatic browser selection for ${BUILDER_TERM_START}:engine${BUILDER_TERM_END} tests" + "--browsers=BROWSERS Set to override automatic browser selection for $(builder_term :engine) tests" builder_parse "$@" diff --git a/windows/src/desktop/kmshell/locale/kan-Knda-IN/strings.xml b/windows/src/desktop/kmshell/locale/kan-Knda-IN/strings.xml deleted file mode 100644 index 855d072a74..0000000000 --- a/windows/src/desktop/kmshell/locale/kan-Knda-IN/strings.xml +++ /dev/null @@ -1,290 +0,0 @@ - - - www.ಸಿರಿಗನ್ನಡ.com (www.sirigannada.com) - Noto Sans Kannada - 10 - Keyman - ಹೌದು - ಇಲ್ಲ - &ಹೌದು - &ಇಲ್ಲ - ಸರಿ - ರದ್ದುಮಾಡು - ಮುಚ್ಚು - ಅನ್ವಯಿಸು - ನಂತರ ನನಗೆ ನೆನಪಿಸು - ಸರಿ - ರದ್ದುಮಾಡಿ - ಕೀಲಿಮಣೆಯನ್ನು ಆಯ್ಕೆ ಮಾಡಲು ಈ ಚಿತ್ರ(ಐಕಾನ್) ಅನ್ನು ಕ್ಲಿಕ್ ಮಾಡಿ - Keyman ಇನ್ನೂ ಚಾಲನೆಯಲ್ಲಿದೆ. ನಿಮ್ಮ ಭಾಷೆ ಕೀಲಿಮಣೆಯನ್ನು ಯಾವುದೇ ಸಮಯದಲ್ಲಿ ಬಳಸಲು ಈ ಚಿತ್ರ(ಐಕಾನ್) ಅನ್ನು ಕ್ಲಿಕ್ ಮಾಡಿ - Keyman ಸಂರಚನೆ (ಕಾನ್ಫಿಗರೇಷನ್) - ಶುರುವಾಗುತ್ತಿದೆ - ಸಹಾಯ - ಕೀಲಿಮಣೆ ವಿನ್ಯಾಸಗಳು - - ಆಯ್ಕೆಗಳು - - ನೇರ ಕೀಲಿಗಳು (ಹಾಟ್‌ಕೀ/ಶಾರ್ಟ್‌ಕಟ್‌ಕೀ) - - ಸಹಾಯ - - ನಮ್ಮ ಸಂಪರ್ಕ - - ಕಡತದ ಹೆಸರು: - ಪ್ಯಾಕೇಜ್ ಆವೃತ್ತಿ: - ಕೀಲಿಮಣೆ ಆವೃತ್ತಿ: - ಲೇಖಕ: - ವೆಬ್‌ಸೈಟ್: - ಪ್ಯಾಕೇಜ್: - ಅಕ್ಷರ ಶೈಲಿಗಳು(ಫಾಂಟ್): - ಕೀಲಿಮಣೆ ವಿನ್ಯಾಸಗಳು: - ಎನ್ಕೋಡಿಂಗ್: - ವಿನ್ಯಾಸ ಪ್ರಕಾರ: - ಸ್ಥಿರ (ಸ್ಥಾನಿಕ) - ವಿಂಡೋಸ್ ಆವೃತ್ತಿಗೆ ಮ್ಯಾಪ್ ಮಾಡಲಾಗಿದೆ - ವಿವರಣೆ: - ಇದಕ್ಕಾಗಿ ಸ್ಥಾಪಿಸಲಾಗಿದೆ: - ಎಲ್ಲಾ ಬಳಕೆದಾರರು - ಪ್ರಸ್ತುತ ಬಳಕೆದಾರ - ಈ ಕೀಲಿಮಣೆ ಬಳಕೆಯ ಭಾಷೆಗಳು: - X - ಬೇರೆ ಭಾಷೆಯನ್ನು ಈ ಕೀಲಿಮಣೆಗೆ ಸೇರಿಸು - ತೆರೆಯ ಮೇಲಿನ ಕೀಲಿಮಣೆ: - ಕಸ್ಟಮ್ - ಸ್ಥಾಪಿಸಲಾಗಿದೆ - ಸ್ಥಾಪಿಸಲಾಗಿಲ್ಲ - ದಾಖಲೆ: - ಸ್ಥಾಪಿಸಲಾಗಿದೆ - ಸ್ಥಾಪಿಸಲಾಗಿಲ್ಲ - ಸಂದೇಶ: - ಕೃತಿಸ್ವಾಮ್ಯ: - ಪ್ಯಾಕೇಜ್ ಆಯ್ಕೆಗಳು - ಆಯ್ಕೆಗಳು - ಕೀಲಿಮಣೆಯನ್ನು ಅನುಸ್ಥಾಪಿಸು - ಕೀಲಿಮಣೆ ಡೌನ್ಲೋಡ್ ಮಾಡಿ - ಕೀಲಿಯನ್ನು ಆಯ್ಕೆಗಳು - ಅಸ್ಥಾಪಿಸು - ಪ್ಯಾಕೇಜ್‌ಅನ್ನು ಅಸ್ಥಾಪಿಸು - ಪರಿಚಯಾತ್ಮಕ ಸಹಾಯವನ್ನು ತೋರಿಸು - ನೇರ ಕೀಲಿಯನ್ನು ಬದಲಾಯಿಸು - ನೇರ ಕೀಲಿಗಳು ಹೊಂದಿಸು - ತೆರೆಯ ಮೇಲಿನ ಕೀಲಿಮಣೆಯನ್ನು ಅಸ್ಥಾಪಿಸು - ತೆರೆಯ ಮೇಲಿನ ಕೀಲಿಮಣೆ ಅನುಸ್ಥಾಪಿಸು - ನೀವು ಯಾವುದೇ ಕೀಲಿಮಣೆಯನ್ನು ಸ್ಥಾಪಿಸಿಲ್ಲ. ಕೀಮ್ಯಾನ್ ವೆಬ್‌ಸೈಟ್‌ನಿಂದ ಕೀಲಿಮಣೆ ವಿನ್ಯಾಸವನ್ನು ಸ್ಥಾಪಿಸಲು ಡೌನ್ಲೋಡ್ ಕೀಲಿಮಣೆ ಗುಂಡಿಯನ್ನು ಕ್ಲಿಕ್ ಮಾಡಿ. - ನಿರ್ವಾಹಕರಾಗಿದ್ದರೆ(ಅಡ್ಮಿನಿಸ್ಟ್ರೇಟರ್) ಮಾತ್ರ ಕೀಲಿಮಣೆ '%0:s' ಅನ್ನು ಅಸ್ಥಾಪಿಸಬಹುದು - ಸಾಮಾನ್ಯ - ಆರಂಭಿಕ - ತೆರೆಯ ಮೇಲಿನ ಕೀಲಿಮಣೆ - ಸುಧಾರಿತ(ಅಡ್ವಾನ್ಸ್ಡ್) - ನೇರಕೀಲಿಗಳು (ಹಾಟ್‌ಕೀ/ಶಾರ್ಟ್‌ಕಟ್‌ಕೀ), ಕೀಲಿಮಣೆ ಕ್ರಿಯಾತ್ಮಕತೆಯನ್ನು ಟಾಗಲ್ ಮಾಡಲಿ - AltGr ಅನ್ನು Ctrl+Alt ಆಗಿ ಅನುಕರಿಸು - ಹಾರ್ಡ್‌ವೇರ್ ಕೀಲಿಗಳನ್ನು ಸರಳ ಕೀಲಿಗಳಾಗಿ ಪರಿಗಣಿಸು - ಸುಳಿವುಗಳನ್ನು ತೋರಿಸು - ಕೀಮ್ಯಾನ್ ಚಲನೆಯನ್ನು ವಿಂಡೋಸ್ ಪ್ರಾರಂಭವಾದಾಗ ಪ್ರಾರಂಭಿಸು - ಸ್ಪ್ಲಾಶ್ ಪರದೆಯನ್ನು ತೋರಿಸು - ಸ್ವಾಗತ ಪರದೆಯನ್ನು ತೋರಿಸು - ನವೀಕರಣಗಳನ್ನು ಸ್ವಯಂಚಾಲಿತವಾಗಿ www.keyman.com ನಲ್ಲಿ ಸಾಪ್ತಾಹಿಕವಾಗಿ ಪರಿಶೀಲಿಸು - Keyman ಪ್ರಾರಂಭವಾದಾಗ ವೈಫಲ್ಯದ ಅನ್ವಯಗಳನ್ನು ಪರೀಕ್ಷಿಸು - "ತೆರೆಯ ಮೇಲಿನ ಕೀಲಿಮಣೆ"ಯಲ್ಲಿ ಯಾವುದೆ ಕೀಲಿಯನ್ನು ಕ್ಲಿಕ್ ಮಾಡಿದ ನಂತರ Shift/Ctrl/Alt ಅನ್ನು ಬಿಡುಗಡೆ ಮಾಡು - ಹೊಸ ಕೀಮ್ಯಾನ್ ಕೀಲಿಮಣೆಯನ್ನು ಆಯ್ಕೆ ಮಾಡಿದಾಗ ತೆರೆಯ ಮೇಲಿನ ಕೀಲಿಮಣೆಯನ್ನು ತೋರಿಸು - ಬೇರೆ ಕೀಲಿಮಣೆಯನ್ನು ಆಯ್ಕೆ ಮಾಡಿದಾಗ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಸಹಾಯ ಅಥವಾ ತೆರೆಯ ಮೇಲಿನ ಕೀಲಿಮಣೆಯನ್ನು ಬದಲಿಸು - ಡೀಬಗ್ ಮಾಡುವುದು - ಬಳಕೆದಾರ ಇಂಟರ್ಫೇಸ್ ಭಾಷೆ... - ಮೂಲ(ಬೇಸ್) ಕೀಲಿಮಣೆ... - (ಯಾವುದೂ ಇಲ್ಲ) - Keyman ಸ್ಥಗಿತಗೊಳಿಸಲು - ಕೀಲಿಮಣೆ ಆಯ್ಕೆ ಪಟ್ಟಿಯನ್ನು ತೆರೆಯಲು - ತೆರೆಯ ಮೇಲಿನ ಕೀಲಿಮಣೆ ಫಲಕ ತೋರಿಸಲು - ಸಂರಚನೆ(ಕಾನ್ಫಿಗರೇಷನ್) ತೆರೆಯಲು - ಅಕ್ಷರ ಶೈಲಿ(ಫಾಂಟ್) ಸಹಾಯಕ ಫಲಕವನ್ನು ತೋರಿಸಲು - ಅಕ್ಷರ ನಕ್ಷೆ ಫಲಕವನ್ನು ತೋರಿಸಲು - ಪಠ್ಯ ಸಂಪಾದಕವನ್ನು ತೆರೆಯಲು - ಭಾಷಾ ಬದಲಾವಣೆ ಫಲಕವನ್ನು ತೋರಿಸಲು - ಸಾಮಾನ್ಯ ನೇರ ಕೀಲಿಗಳು (ಹಾಟ್‌ಕೀ/ಶಾರ್ಟ್‌ಕಟ್‌ಕೀ) - ಕೀಲಿಮಣೆಗಳು - ಸ್ಥಾಪಿಸಲಾಗಿರುವ ಭಾಷೆಗಳು - ವಿಂಡೋಸ್ ಲೇಔಟ್ - ಕೀಮ್ಯಾನ್ ಕೀಲಿಮಣೆ - (ವಿಂಡೋಸ್ ಲೇಔಟ್ ಬಳಸಿ) - ಈಗ ಹೊಸ ಆವೃತ್ತಿಯನ್ನು(ಅಪ್‌ಗ್ರೇಡ್) ಅನುಸ್ಥಾಪಿಸು! - ಸಹಾಯ ವಿನಂತಿ ಕಳುಹಿಸು - ಕೀಮ್ಯಾನ್ ಬೆಂಬಲವನ್ನು ಸಂಪರ್ಕಿಸು - ಕೀಮ್ಯಾನ್‌ ಅನ್ನು ಬಳಸುವಾಗ ನಿಮಗೆ ಯಾವುದೇ ಸಮಸ್ಯೆಗಳು ಕಂಡು ಬಂದರೆ, ಕೀಮ್ಯಾನ್ ಸಮುದಾಯ ವೇದಿಕೆಯಲ್ಲಿ (Keyman Community Forum) ಪ್ರಶ್ನೆಯನ್ನು ಕೇಳಿ. - ಕೀಮ್ಯಾನ್ ಸಮುದಾಯ ವೇದಿಕೆ ತೆರೆಯಿರಿ - ಕೃತಿಸ್ವಾಮ್ಯ © ಎಸ್‌ಐಎಲ್‌ ಇಂಟರ್‌ನ್ಯಾಷನಲ್. ಎಲ್ಲ ಹಕ್ಕುಗಳನ್ನು ಕಾಯ್ದಿರಿಸಲಾಗಿದೆ. - ಆವೃತ್ತಿ - ಇಂಗ್ಲೀಷ್ ಆವೃತ್ತಿ - ಉಪಯುಕ್ತ ಕೊಂಡಿಗಳು - ಆನ್‌ಲೈನ್ ಸಹಾಯ - ಡಯಗ್ನೊಸ್ಟಿಕ್ - ನವೀಕರಣಗಳಿಗಾಗಿ ಪರಿಶೀಲಿಸಿ - ಪ್ರಾಕ್ಸಿ ಸೆಟ್ಟಿಂಗ್ಗಳು... - ಡಯಗ್ನೊಸ್ಟಿಕ್ - ಭಾಷಾ ಸಂಯೋಜನೆಗಳನ್ನು (ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು) ಪರಿಶೀಲಿಸು - ಮೈಕ್ರೋಸಾಫ್ಟ್ ವಿಂಡೋಸ್ ನಿಮ್ಮ ಭಾಷೆ(ಗಳು) ಗಾಗಿ ಸರಿಯಾಗಿ ಸಂಯೋಜನೆ ಮಾಡಲ್ಪಟ್ಟಿದೆ. - keyman.com ಯಿಂದ ಕೀಲಿಮಣೆ ಡೌನ್ಲೋಡ್ ಮಾಡಿ - ಸ್ಥಾಪಿಸಬೇಡಿ, ಡೌನ್ಲೋಡ್ ಮಾಡಿ - ಕೀಲಿಮಣೆ/ಪ್ಯಾಕೇಜ್ ಅನುಸ್ಥಾಪಿಸು - ವಿವರಗಳು - ಸಂದೇಶವನ್ನು ಓದಿ - ಅನುಸ್ಥಾಪಿಸು - ಎಲ್ಲಾ ಬಳಕೆದಾರರಿಗೆ ಅನುಸ್ಥಾಪಿಸು - ಪ್ರಾಕ್ಸಿ ಸರ್ವರ್ ಸಂರಚನೆ(ಕಾನ್ಫಿಗರೇಷನ್) - ಸರ್ವರ್(server): - ಪೊರ್ಟ್(port): - ಬಳಕೆದಾರರ ಹೆಸರು(username): - ಪ್ರವೇಶಪದ(password): - ಮೂಲ(ಬೇಸ್) ಕೀಲಿಮಣೆ ಹೊಂದಿಸಿ - ನೀವು ವಿಂಡೋಸ್‌ನಲ್ಲಿ ಬಳಸುವ ಮೂಲ(ಬೇಸ್) ಲ್ಯಾಟಿನ್(ಇಂಗೀಷ್) ಸ್ಕ್ರಿಪ್ಟ್ ಕೀಲಿಮಣೆ ಆಯ್ಕೆಮಾಡಿ. ಕೀಮ್ಯಾನ್ ಕೀಲಿಮಣೆಯು ನಿಮ್ಮ ಆದ್ಯತೆಯ ವಿನ್ಯಾಸಕ್ಕೆ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಹೊಂದಿಕೊಳ್ಳುತ್ತದೆ. - ನೇರ ಕೀಲಿ ಬದಲಾಯಿಸು - &ನೇರ ಕೀಲಿ ತೆರವುಗೊಳಿಸು - ಭಾಷೆ %0:s ಗಾಗಿ ಪ್ರಮಾಣಿತ ನೇರ ಕೀಲಿಯನ್ನು ಆಯ್ಕೆಮಾಡಿ ಅಥವಾ 'ಕಸ್ಟಮ್' ಆಯ್ಕೆಮಾಡಿ ಮತ್ತು Ctrl, Shift ಮತ್ತು/ಅಥವಾ Alt ಅನ್ನು ಒತ್ತಿ ಮತ್ತು ನೀವು ಬಯಸಿದ ನೇರ ಕೀಲಿಯನ್ನು ಟೈಪ್ ಮಾಡಿ: - ಭಾಷೆ %0:s ಗಾಗಿ ಪ್ರಮಾಣಿತ ಹಾಟ್ಕೀ ಅನ್ನು ಆಯ್ಕೆಮಾಡಿ ಅಥವಾ 'ಕಸ್ಟಮ್' ಆಯ್ಕೆಮಾಡಿ ಮತ್ತು Ctrl, Shift ಮತ್ತು/ಅಥವಾ Alt ಅನ್ನು ಒತ್ತಿ ಮತ್ತು ನಿಮ್ಮ ಬಯಸಿದ ಹಾಟ್ ಕೀಲಿಯನ್ನು ಟೈಪ್ ಮಾಡಿ: - ಪ್ರಮಾಣಿತ ನೇರ ಕೀಲಿಯನ್ನು ಆಯ್ಕೆಮಾಡಿ ಅಥವಾ 'ಕಸ್ಟಮ್' ಆಯ್ಕೆಮಾಡಿ ಮತ್ತು Ctrl, Shift ಮತ್ತು/ಅಥವಾ Alt ಅನ್ನು ಒತ್ತಿ ಮತ್ತು ನೀವು ಬಯಸಿದ ನೇರ ಕೀಲಿಯನ್ನು ಟೈಪ್ ಮಾಡಿ: - ನೇರ ಕೀಲಿ %0:s ಸಾಮಾನ್ಯ ಕೀಲಿಮಣೆ ಬಳಕೆಗೆ ತೊಂದರೆ ಮಾಡುತ್ತದೆ. ನೀವು ಕನಿಷ್ಠ Ctrl ಅಥವಾ Alt ಅನ್ನು ಬಳಸಬೇಕು. ಈಗ ನೀವು ಇದನ್ನು ಬದಲಾಯಿಸಲು ಬಯಸುವಿರಾ? - ನೇರ ಕೀಲಿ %0:s ಕೀಲಿಮಣೆ %1:s ಗಾಗಿ ಆಯ್ಕೆ ಮಾಡಲಾಗಿದೆ. ನೀವು ಮುಂದುವರಿಸಿದರೆ, ಕೀಲಿಮಣೆ %1:s ಗಾಗಿ ನೇರ ಕೀಲಿಯನ್ನು ತೆರವುಗೊಳಿಸಲಾಗುತ್ತದೆ. ಮುಂದುವರಿಸಬೇಕೆ? - ಅನುಸ್ಥಾಪಿಸಲು ಕೀಲಿಮಣೆಯನ್ನು ಆಯ್ಕೆಮಾಡಿ - ಈ ಪ್ಯಾಕೇಜ್‌ನಲ್ಲಿ ಎಲ್ಲಾ ಕೀಲಿಮಣೆಗಳನ್ನು ಸ್ಥಾಪಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ಗರಿಷ್ಟ %0:d ಹೆಚ್ಚುವರಿ ಕೀಲಿಮಣೆಗಳನ್ನು ಸ್ಥಾಪಿಸಬಹುದು. ದಯವಿಟ್ಟು ನೀವು ಈ ಪ್ಯಾಕೇಜ್‌ನಿಂದ ಸ್ಥಾಪಿಸಲು ಬಯಸುವ ಕೀಲಿಮಣೆಯನ್ನು ಮಾತ್ರ ಆಯ್ಕೆ ಮಾಡಿ. - ನವೀಕರಿಸಲಾದ Keyman ಘಟಕಗಳು ಲಭ್ಯವಿದೆ - Keyman ಇದಕ್ಕಾಗಿ ಅಪ್‌ಡೇಟ್‌ಗಳು ಲಭ್ಯವಿದೆ - ದಯವಿಟ್ಟು ನೀವು ಸ್ಥಾಪಿಸಲು ಬಯಸುವ ನವೀಕರಣಗಳನ್ನು ಆಯ್ಕೆ ಮಾಡಿ: - ಈ ಪ್ಯಾಚ್ ಅನ್ನು ಇದೀಗ ನೀವು ಡೌನ್ಲೋಡ್ ಮಾಡಲು ಮತ್ತು ಸ್ಥಾಪಿಸಲು ಬಯಸುವಿರಾ? - ನೀವು ಈ ಹೊಸ ಆವೃತ್ತಿಯನ್ನು ಡೌನ್ಲೋಡ್ ಮಾಡಬಹುದು: - ನೀವು ಈಗ ವೆಬ್‌ಸೈಟ್‌ಗೆ ಭೇಟಿ ನೀಡಲು ಬಯಸುವಿರಾ? - ಈಗ ಅನುಸ್ಥಾಪಿಸಿ - ರದ್ದುಮಾಡಿ - ಹಳೆಯ ಆವೃತ್ತಿ - ಅಪ್‌ಡೇಟ್‌ ಮಾಡಲಾದ ಘಟಕಗಳು - ಗಾತ್ರ - Keyman %0:s - ಕೀಲಿಮಣೆ %0:s %1:s - keyman.com ವೆಬ್‌ಸೈಟ್‌ ಅನ್ನು ಸಂಪರ್ಕಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ - ದಯವಿಟ್ಟು ನೀವು ಸಕ್ರಿಯ ಇಂಟರ್ನೆಟ್ ಸಂಪರ್ಕವನ್ನು ಹೊಂದಿದ್ದೀರ ಎಂದು ಖಚಿತಪಡಿಸಿಕೊಂಡು ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ. - keyman.com ವೆಬ್‌ಸೈಟ್‌ ಅನ್ನು ಸಂಪರ್ಕಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ - ದಯವಿಟ್ಟು ನೀವು ಸಕ್ರಿಯ ಇಂಟರ್ನೆಟ್ ಸಂಪರ್ಕವನ್ನು ಹೊಂದಿರುವಿರಿ ಎಂದು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಿ ಮತ್ತು ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ. ದೋಷ ಸ್ವೀಕರಿಸಲಾಗಿದೆ: %0:s - Keyman ನವೀಕರಣಗಳು ಲಭ್ಯವಿದೆ - ನವೀಕರಣಗಳನ್ನು ಡೌನ್ಲೋಡ್ ಮಾಡಲು ಮತ್ತು ಅನುಸ್ಥಾಪಿಸಲು ಈ ಐಕಾನ್ ಕ್ಲಿಕ್ ಮಾಡಿ - ವೀಕ್ಷಿಸಿ ಮತ್ತು ಅನುಸ್ಥಾಪನೆ Keyman ನವೀಕರಣಗಳು - ಆನ್‌ಲೈನ್ ಅಪ್‌ಡೇಟ್ ಪರಿಶೀಲನೆಗೆ ನಿರ್ಗಮನ - Keyman - Keyman - ಪ್ರಾರಂಭಿಸು - ನಿರ್ಗಮಿಸು - ಇತರೆ ಕಾರ್ಯಗಳು - ಸಂರಚನೆ - ಆರಂಭದಲ್ಲಿ ಈ ಪರದೆಯನ್ನು ತೋರಿಸು - ಆರಂಭದಲ್ಲಿ ಈ ಪರದೆಯನ್ನು ತೋರಿಸಬೇಡ - ಪ್ರದರ್ಶನ ಭಾಷೆ - ಇತರ ಪ್ರದರ್ಶನ ಭಾಷೆಗಳನ್ನು ಆನ್‌ಲೈನ್‌ನಲ್ಲಿ ಹುಡುಕಿ... - ಪ್ರದರ್ಶನ ಭಾಷೆ ಭಾಷಾಂತರಿಸಲು ಸಹಾಯ ಮಾಡಿ - ಕನ್ನಡ - ಕನ್ನಡ (Kannada) - kan - en - Keyman - ಪ್ರದರ್ಶನ ಭಾಷೆಯನ್ನು ಆಯ್ಕೆಮಾಡಿ - ನೀವು ಬಯಸುವ ಪ್ರದರ್ಶನ ಭಾಷೆಯನ್ನು Keyman ಫಲಕದಲ್ಲಿ ಆಯ್ಕೆಮಾಡಿ. - &ಆನ್‌ಲೈನ್‌ನಲ್ಲಿ ಇನ್ನಷ್ಟು ಭಾಷೆಗಳು... - ಹೊಸ ಪ್ರದರ್ಶನ ಭಾಷೆಯನ್ನು ಆನ್‌ಲೈನ್‌ನಲ್ಲಿ ಭಾಷಾಂತರ ಮಾಡಿ - ಭಾಷಾ ಸಂರಚನೆ(ಕಾನ್ಫಿಗರೇಷನ್) ಕಾರ್ಯಗಳು - ಕೊನೆಯಲ್ಲಿ ಸೂಚಿಸಲಾದ ಭಾಷೆಯ ಜೊತೆಯಲ್ಲಿ ಕೆಲಸ ಮಾಡಲು, ನಿಮ್ಮ ಕಂಪ್ಯೂಟರ್ ಅನ್ನು ಸಂರಚನೆ(ಕಾನ್ಫಿಗರ್) ಮಾಡಿ: - ಕೆಳಗಿನ ಸಂರಚನಾ ಕಾರ್ಯಗಳ ಸಲುವಾಗಿ ಪೂರ್ಣಗೊಳಿಸಬೇಕು Keyman ಎಂದು ಪತ್ತೆಹಚ್ಚಿದೆ - ಲಿಪಿ(ಗಳು), ನಿಮ್ಮ ಕಂಪ್ಯೂಟರ್‌ನಲ್ಲಿ ಸರಿಯಾಗಿ ಕೆಲಸ ಮಾಡಲು: - ಮೈಕ್ರೋಸಾಫ್ಟ್ ಆಫೀಸ್ ಭಾಷಾ ಬೆಂಬಲ - ಹೆಚ್ಚಿನ ಮಾಹಿತಿ... - ಈ ಕಾರ್ಯಗಳನ್ನು Keyman ಈಗ ಪೂರ್ಣಗೊಳಿಸಲು ಬಯಸುತ್ತೀರಾ? - ಇದನ್ನು ಮತ್ತೊಮ್ಮೆ ಕೇಳಬೇಡ - ಸುಳಿವುಗಳನ್ನು ಮರುಹೊಂದಿಸು - ಎಲ್ಲಾ ಸುಳಿವು ಸಂದೇಶಗಳನ್ನು ಮರುಹೊಂದಿಸಲಾಗಿದೆ ಮತ್ತು ಮತ್ತೆ ಪ್ರದರ್ಶಿಸಲಾಗುತ್ತದೆ. - ನಿರ್ಗಮನ Keyman? - ನೀವು Keyman ನಿರ್ಗಮಸಲು ಬಯಸುತ್ತೀರಾ? -ವಿಂಡೋಸ್ ಕೀಲಿಮಣೆಗಳ ಪಟ್ಟಿಯಲ್ಲಿ ಕೀಮ್ಯಾನ್ ಕೀಲಿಮಣೆಗಳನ್ನು ಸೇರಿಸಲಾಗಿದೆ. -ಆದರೆ ನೀವು Keyman ಅನ್ನು ಮರುಪ್ರಾರಂಭಿಸುವವರೆಗೆ ಕೀಮ್ಯಾನ್ ಕೀಲಿಮಣೆಗಳು ಕ್ರಿಯಾತ್ಮಕವಾಗಿರುವುದಿಲ್ಲ. - ತೆರೆಯ ಮೇಲಿನ ಕೀಲಿಮಣೆ ಮುಚ್ಚಲಾಗಿದೆ - ನೀವು "ತೆರೆಯ ಮೇಲಿನ ಕೀಲಿಮಣೆ"ಅನ್ನು ಮುಚ್ಚಿದ್ದೀರಿ. Keyman ಇನ್ನೂ ಚಾಲನೆಯಲ್ಲಿದೆ. Keyman ಚಿತ್ರ(ಐಕಾನ್) ಮೇಲೆ ನೀವು ಯಾವುದೇ ಸಮಯದಲ್ಲಿ ಕ್ಲಿಕ್ ಮಾಡಿ ಮತ್ತು "ತೆರೆಯ ಮೇಲಿನ ಕೀಲಿಮಣೆ" ಆಯ್ಕೆಮಾಡುವ ಮೂಲಕ; "ತೆರೆಯ ಮೇಲಿನ ಕೀಲಿಮಣೆ"ಅನ್ನು ತೆರೆಯಬಹುದು. - ಈ ಸುಳಿವನ್ನು ಮತ್ತೆ ತೋರಿಸಬೇಡ - Keyman ಸಹಾಯ - ಪ್ರಾರಂಭಿಸಿ - ಸಹಾಯ ಪರಿವಿಡಿ - " - " ಕೀಲಿಮಣೆಗೆ ಸಹಾಯ - "ತೆರೆಯ ಮೇಲಿನ ಕೀಲಿಮಣೆ" ತೆರೆ - ಅಕ್ಷರ ಶೈಲಿ(ಫಾಂಟ್) ಸಹಾಯಕ ಫಲಕವನ್ನು ತೆರೆ - ಅಕ್ಷರ ನಕ್ಷೆ ಫಲಕವನ್ನು ತೆರೆ - Keyman ಬೆಳಕನ್ನು ಮುಚ್ಚಿ - Keyman ಸಂರಚನೆ(ಕಾನ್ಫಿಗರೇಷನ್) ತೆರೆ - ಸಹಾಯ ತೆರೆ - "ತೆರೆಯ ಮೇಲಿನ ಕೀಲಿಮಣೆ" ಮುಚ್ಷು - &ತೆರೆಯ ಮೇಲಿನ ಕೀಲಿಮಣೆ - &ಸಹಾಯ... - &ನಿರ್ಗಮನ - ನೀವು ಯಾವುದೇ ಕೀಲಿಮಣೆಯನ್ನು ಅನುಸ್ಥಾಪಿಸಿಲ್ಲ. ಕೀಲಿಮಣೆ ವಿನ್ಯಾಸವನ್ನು ಸ್ಥಾಪಿಸಲು "ಸಂರಚನೆ"(ಕಾನ್ಫಿಗರೇಷನ್)ನಲ್ಲಿ "ಡೌನ್ಲೋಡ್ ಕೀಲಿಮಣೆ" ಗುಂಡಿಯನ್ನು ಕ್ಲಿಕ್ ಮಾಡಿ. - ನಿಷ್ಕ್ರಿಯವಾಗಿದ್ದಾಗ ಫೇಡ್ ಮಾಡಿ - ಉಪಕರಣ ಪಟ್ಟಿ(ಟೂಲ್‌ಬಾರ್) ತೋರಿಸು - ವೆಬ್ ಪುಟದಂತೆ ಉಳಿಸು... - ಪ್ರಿಂಟ್... - Keyman - ಆವೃತ್ತಿ %0:s - ಸಹಾಯ - &ಮುದ್ರಿಸು.... - &ಡೌನ್ಲೋಡ್... - %0:s ಹೆಸರಿನ ಪ್ಯಾಕೇಜ್‌ಅನ್ನು ಈಗಾಗಲೇ ಸ್ಥಾಪಿಸಲಾಗಿದೆ. ನೀವು ಅದನ್ನು ಅಸ್ಥಾಪಿಸಲು ಹಾಗು ಹೊಸದನ್ನು ಅನುಸ್ಥಾಪಿಸಲು ಬಯಸುವಿರಾ? - %0:s ಹೆಸರಿನ ಕೀಲಿಮಣೆ ಈಗಾಗಲೇ ಅನುಸ್ಥಾಪಿಸಲಾಗಿದೆ. ನೀವು ಅದನ್ನು ಅಸ್ಥಾಪಿಸಬೇಕಾಗುತ್ತದೆ ಹಾಗು ಹೊಸ ಕೀಲಿಮಣೆಯನ್ನು ಸ್ಥಾಪಿಸಲಾಗುವುದು. ಮುಂದುವರಿಸಬೇಕೆ? - '%0:s' ಕೀಲಿಮಣೆ '%1:s' ಪ್ಯಾಕೇಜಿನ ಭಾಗವಾಗಿದೆ. ನೀವು ಸಂಪೂರ್ಣ ಪ್ಯಾಕೇಜ್ ಅನ್ನು ಅಸ್ಥಾಪಿಸಬೇಕಾಗುತ್ತದೆ. ಮುಂದುವರಿಸಬೇಕೇ? - ನಿರ್ವಾಹಕರಾಗಿದ್ದರೆ(ಅಡ್ಮಿನಿಸ್ಟ್ರೇಟರ್) ಮಾತ್ರ ಕೀಲಿಮಣೆಗಳನ್ನು ಅನುಸ್ಥಾಪಿಸಿ ಅಥವಾ ಅಸ್ಥಾಪಿಸಬಹುದು. ಸಾಮಾನ್ಯ ಬಳಕೆದಾರನಾಗಿ ಬಳಸಲು ಭಾಷೆಯನ್ನು ಆಯ್ಕೆ ಮಾಡಲು ನಿಯಂತ್ರಣ ಫಲಕವನ್ನು (control panel) ಬಳಸಿ. - ಪರ್ಯಾಯ ಸಂಯೋಜನೆಗಳನ್ನು (ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು) ಬದಲಾಯಿಸಲು ವಿಂಡೋಸ್ ಅನ್ನು ಪುನರಾರಂಭಿಸಬೇಕಾಗಿದೆ. ನೀವು ಈಗ ವಿಂಡೋಸ್ ಅನ್ನು ಮರುಪ್ರಾರಂಭಿಸಲು ಬಯಸುವಿರಾ? - ಈ '%0:s' ಪ್ಯಾಕೇಜ್ ಅಥವಾ ಕೀಲಿಮಣೆ ಯಾವುದೇ ಪರಿಚಯಾತ್ಮಕ ಸಹಾಯವನ್ನು ಒಳಗೊಂಡಿಲ್ಲ. - ಈ ಆಪರೇಟಿಂಗ್ ಸಿಸ್ಟಮ್‌ನಲ್ಲಿ ನಮ್ಮ ತಂತ್ರಾಂಶ ಕೆಲಸ ಮಾಡುವುದಿಲ್ಲ. - ನಿಮ್ಮ ಪರವಾನಗಿ ಯಶಸ್ವಿಯಾಗಿ ಸಕ್ರಿಯಗೊಂಡಿದೆ. - KeymanDesktop.chm - ಸಹಾಯ ಕಡತ $(SKOnlineHelpFile) ಕಂಡುಬಂದಿಲ್ಲ. - <ಹಾನಿಗೊಳಗಾದ ಕೀಲಿಮಣೆ> - ಕೋಡ್‌ಪುಟ - ಯೂನಿಕೋಡ್ - ಡೌನ್ಲೋಡ್ ಮಾಡಲಾಗುತ್ತಿದೆ - %0:s ಕೀಲಿಮಣೆಯ "ತೆರೆಯ ಮೇಲಿನ ಕೀಲಿಮಣೆ ಫಲಕ" ಅಸ್ಥಾಪಿಸಲು ನೀವು ಖಚಿತವಾಗಿ ಬಯಸುವಿರಾ? - %0:s ಕೀಲಿಮಣೆಯನ್ನು ಅಸ್ಥಾಪಿಸಲು ನೀವು ಖಚಿತವಾಗಿ ಬಯಸುವಿರಾ? - %0:s ಪ್ಯಾಕೇಜ್‌ಅನ್ನು ಹಾಗು %1:s ಅಕ್ಷರ ಶೈಲಿ(ಫಾಂಟ್)/ಗಳನ್ನು ಅಸ್ಥಾಪಿಸಲು ನೀವು ಖಚಿತವಾಗಿ ಬಯಸುವಿರಾ? - ಕೆಳಗಿನ ಅಕ್ಷರ ಶೈಲಿ(ಫಾಂಟ್)/ಗಳನ್ನು ಸಹ ಅಸ್ಥಾಪಿಸಲ್ಪಡುತ್ತವೆ: %0:s. - ಪರವಾನಗಿ ಸಂಖ್ಯೆ %0:s ಯೊಂದಿಗೆ ಈಗ ನೀವು ಆನ್‌ಲೈನ್‌ನಲ್ಲಿ ಸಕ್ರಿಯಗೊಳಿಸಲು $(SKShortApplicationTitle) ಬಯಸುತ್ತೀರಾ? ನೀವು "ಇಲ್ಲ" ಅಥವಾ "ರದ್ದುಮಾಡಿ" ಗುಂಡಿಯನ್ನು ಕ್ಲಿಕ್ ಮಾಡದಿದ್ದರೆ, ಪರ್ಯಾಯ ಸಕ್ರಿಯಗೊಳಿಸುವ ವಿಧಾನಗಳಿಂದ ನೀವು ಆಯ್ಕೆ ಮಾಡಬಹುದು. - ಕ್ಯಾರೆಕ್ಟರ್ ಮ್ಯಾಪ್ ಅನ್ನು ಬಳಸಬಹುದಾದ ಮೊದಲು ನಿರ್ಮಿಸಬೇಕಾದ ಪಾತ್ರಗಳ ದತ್ತಾಂಶ ಹೊಂದಿದೆ. ಈಗ ನಿರ್ಮಿಸಲು ಬಯಸುವಿರಾ? - ಪುನರ್ನಿರ್ಮಾಣಕ್ಕಾಗಿ ಯೂನಿಕೋಡ್ ಕ್ಯಾರೆಕ್ಟರ್ ಡೇಟಾಬೇಸ್ ಅನ್ನು ಅಳಿಸಲಾಗಲಿಲ್ಲ. ದೋಷ ವಿವರಗಳು: %0:s - ಯುನಿಕೋಡ್ ಕ್ಯಾರೆಕ್ಟರ್ ಡೇಟಾಬೇಸ್ ಅನ್ನು ರಚಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ ಮತ್ತು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ. ದೋಷ ವಿವರಗಳು: %0:s - ಯುನಿಕೋಡ್ ಪಾತ್ರ ಡೇಟಾಬೇಸ್ ಯಶಸ್ವಿಯಾಗಿ ಲೋಡ್ ಮಾಡಲಿಲ್ಲ (%0:s). ಇದೀಗ ಅದನ್ನು ಮರುನಿರ್ಮಾಣ ಮಾಡುವುದೇ? - ಬ್ರೌಸರ್ ಅನ್ನು ಅಥವಾ ಈ URL ಗಾಗಿ ಇಮೇಲ್ ಪ್ರೋಗ್ರಾಂ ಸಕ್ರಿಯಗೊಳಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ. - ಕೀಲಿಮಣೆ ಯಶಸ್ವಿಯಾಗಿ ಮುದ್ರಿಸಲಾಗಲಿಲ್ಲ. ವೆಬ್ ಪುಟಕ್ಕೆ ಉಳಿಸಲು ಮತ್ತು ಮುದ್ರಿಸಲು ದಯವಿಟ್ಟು ಬೇರೆ ಪ್ರಯತ್ನಿಸಿ. - Keyman ಪ್ರಾರಂಭಿಸಲು ವಿಫಲವಾಗಿದೆ. ಮುಂದುವರೆಯುವ ಮೊದಲು keyman.exe ಅನ್ನು ಆರಂಭಿಸಲು ಅನುಮತಿಸಲಾಗಿದೆಯೇ ಎಂದು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಲು ದಯವಿಟ್ಟು ನಿಮ್ಮ ಭದ್ರತೆ ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು(security settings) ಪರಿಶೀಲಿಸಿ. ಹಿಂದಿರುಗಿದ ದೋಷವೆಂದರೆ: "%0:s". ಈಗ ನೀವು ಪ್ರಯತ್ನಿಸಿ ಹಾಗೂ ಮತ್ತೆ Keyman ಪ್ರಾರಂಭಿಸಲು ಬಯಸುವಿರಾ? - Keyman ಡೀಬಗ್ ಮಾಹಿತಿಯನ್ನು ನಿಮ್ಮ ಡೆಸ್ಕ್‌ಟಾಪ್‌ನಲ್ಲಿ keymanlog\system.log ಕರೆಯಲಾಗುವ ಪಠ್ಯ ಫೈಲ್‌ನಲ್ಲಿ ಸಂಗ್ರಹಿಸಲಾಗುತ್ತದೆ. ಈ ಫೈಲ್ ಅನ್ನು ಓದುವ ಅಥವಾ ಅಳಿಸುವ ಮೊದಲು ನೀವು Keyman ನಿರ್ಗಮಿಸಬೇಕು. ಎಚ್ಚರಿಕೆ: ಈ ಫೈಲ್ ಬಹಳ ವೇಗವಾಗಿ ಬೆಳೆಯುತ್ತದೆ. ಡೀಬಗ್ ಮಾಡುವುದನ್ನು ಸಕ್ರಿಯಗೊಳಿಸುವುದರಿಂದ ನಿಮ್ಮ ಸಿಸ್ಟಮ್ ಅನ್ನು ನಿಧಾನಗೊಳಿಸುತ್ತದೆ ಮತ್ತು ತಾಂತ್ರಿಕ ಬೆಂಬಲದಿಂದ ಸಲಹೆ ನೀಡಿದರೆ ಮಾತ್ರ ಮಾಡಬೇಕು. ಖಾಸಗಿ ಎಚ್ಚರಿಕೆ: ನೀವು ಟೈಪ್ ಮಾಡುವ ಎಲ್ಲಾ ಕೀಸ್ಟ್ರೋಕ್‌ಗಳನ್ನು ಡೀಬಗ್ ಲಾಗ್‌ಫೈಲ್ ದಾಖಲಿಸುತ್ತದೆ ಎಂಬುದನ್ನು ದಯವಿಟ್ಟು ಗಮನಿಸಿ. ಡೀಬಗ್ ಮಾಡುವಿಕೆ ಅಥವಾ ಡಯಗ್ನೊಸ್ಟಿಕ್ ಆಗುವ ಅವಧಿಯನ್ನು ನೀವು ಮಾತ್ರ ಡೀಬಗ್ ಲಾಗ್ಆನ್ ಮಾಡಬೇಕು, ಮತ್ತು ಸಾಧ್ಯವಾದಷ್ಟು ಬೇಗ [desktop]\keymanlog\system.log ಫೈಲ್ ಅಳಿಸಿ. - %1:s ಗೆ %0:s ಸಂಪಾದನೆ ಬೆಂಬಲವನ್ನು ಸೇರಿಸಿ - ಮೈಕ್ರೋಸಾಫ್ಟ್ ಆಫೀಸ್ ೨೦೦೦ - ಮೈಕ್ರೋಸಾಫ್ಟ್ ಆಫೀಸ್ ಎಕ್ಸ್ ಪಿ - ಮೈಕ್ರೋಸಾಫ್ಟ್ ಆಫೀಸ್ ೨೦೦೩ - ಮೈಕ್ರೋಸಾಫ್ಟ್ ಆಫೀಸ್ ೨೦೦೭ - ಮೈಕ್ರೋಸಾಫ್ಟ್ ಆಫೀಸ್ ೨೦೧೦ - ಭಾಷೆ %0:s ಅನ್ನು ಕೀಮನ್ ಕೀಲಿಮಣೆ %1:s ಗೆ ಸೇರಿಸು - ಭಾಷೆ %0:s ಅನ್ನು ಸ್ಥಾಪಿಸಿ ಮತ್ತು ಕೀಮನ್ ಕೀಲಿಮಣೆ %1:s ಗೆ ಸೇರಿಸು - ದಯವಿಟ್ಟು ನಿರೀಕ್ಷಿಸಿ, ನಿಮ್ಮ - ಕೀಲಿಮಣೆ ಜೊತೆ ಕೆಲಸ ಕಾರ್ಯನಿರ್ವಹಿಸುವ ಅಕ್ಷರ ಶೈಲಿ(ಫಾಂಟ್)/ಗಳುನ್ನು Keyman ಹುಡುಕುತ್ತಿದೆ. - ಯುನಿಕೋಡ್ ಕೀಲಿಮಣೆ ಅಲ್ಲ. ಅಕ್ಷರ ಶೈಲಿ(ಫಾಂಟ್)/ಗಳನ್ನು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಸ್ಥಾಪಿಸಲಾಗುವುದಿಲ್ಲ. ಅಕ್ಷರ ಶೈಲಿ(ಫಾಂಟ್)/ಗಳ ಮಾಹಿತಿಗಾಗಿ ದಯವಿಟ್ಟು ಕೀಲಿಮಣೆ ದಸ್ತಾವೇಜನ್ನು(documentation) ಪರಿಶೀಲಿಸಿ. - ಕೆಳಗಿನ ಅಕ್ಷರ ಶೈಲಿ(ಫಾಂಟ್)/ಗಳು ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತವೆ - ಕೀಲಿಮಣೆ: - ಕೆಳಗಿನ ಅಕ್ಷರ ಶೈಲಿ(ಫಾಂಟ್)/ಗಳು ಸಹ ಕೆಲಸ ಮಾಡಬಹುದು: - ಕೆಳಗಿನ ಅಕ್ಷರ ಶೈಲಿ(ಫಾಂಟ್)/ಗಳು - ಕೀಲಿಮಣೆಯ ಜೊತೆ ಮಾಡಬಹುದು - ನಿಮ್ಮ ಸಿಸ್ಟಂನಲ್ಲಿ ಯಾವುದೇ ಅಕ್ಷರ ಶೈಲಿ(ಫಾಂಟ್)/ಗಳು - ಕೀಲಿಮಣೆಯ ಜೊತೆ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆಯೆಂದು ಕಂಡುಬಂದಿಲ್ಲ. ಈ ಕೀಲಿಮಣೆಗಾಗಿ ಅಕ್ಷರ ಶೈಲಿ(ಫಾಂಟ್)/ಗಳುನ್ನು ಹುಡುಕಲು, ದಯವಿಟ್ಟು ದಾಖಲೆಯನ್ನು ಪರಿಶೀಲಿಸಿ. - ನೀವು ಯಾವುದೇ ಕೀಲಿಮಣೆಯನ್ನು ಅನುಸ್ಥಾಪಿಸಿಲ್ಲ ಅಥವಾ ಲೋಡ್ ಮಾಡಲಾಗಿಲ್ಲ. ಕೀಲಿಮಣೆ ವಿನ್ಯಾಸವನ್ನು ಅನುಸ್ಥಾಪಿಸಲು Keyman "ಸಂರಚನೆ"(ಕಾನ್ಫಿಗರೇಷನ್)ನಲ್ಲಿ "ಡೌನ್ಲೋಡ್ ಕೀಲಿಮಣೆ" ಗುಂಡಿಯನ್ನು ಕ್ಲಿಕ್ ಮಾಡಿ. - ಅಕ್ಷರ ಶೈಲಿ(ಫಾಂಟ್)/ಗಳನ್ನು ಹುಡುಕಲು, ದಯವಿಟ್ಟು ಒಂದು Keyman ಕೀಲಿಮಣೆ ಆಯ್ಕೆಮಾಡಿ ಆಯ್ಕೆಮಾಡಿ. - ಸುಳಿವು: - ವಿಂಡೋ ಅಂಚಿನಲ್ಲಿ ಕ್ಲಿಕ್ ಮಾಡಿ ಮತ್ತು ಎಳೆಯುವುದರ ಮೂಲಕ "ತೆರೆಯ ಮೇಲಿನ ಕೀಲಿಮಣೆ" ಗಾತ್ರ ಬದಲಾಯಿಸಿ - "Keyman" ಶೀರ್ಷಿಕೆ ಮೇಲೆ ಕ್ಲಿಕ್ ಮಾಡಿ ಮತ್ತು ಎಳೆಯುವ ಮೂಲಕ "ತೆರೆಯ ಮೇಲಿನ ಕೀಲಿಮಣೆ" ಅನ್ನು ಸರಿಸಿ. - ನಿಮ್ಮ ದಾಖಲೆಯಲ್ಲಿ ಯಾವುದೇ ಯೂನಿಕೋಡ್ ಅಕ್ಷರವನ್ನು ಸೇರಿಸಿ - ಅಕ್ಷರ ನಕ್ಷೆ ಉಪಕರಣ - ನಿಮ್ಮ ಭಾಷೆಗೆ ಯಾವ ಅಕ್ಷರ ಶೈಲಿ(ಫಾಂಟ್)/ಗಳು ಕಾರ್ಯ ನಿರ್ವಹಿಸುವೆಂಬುದನ್ನು ಕಂಡುಹಿಡಿಯಲು - ಅಕ್ಷರ ಶೈಲಿ(ಫಾಂಟ್) ಸಹಾಯಕ ಉಪಕರಣ - ಕೀಲಿಮಣೆಯ ಇನ್ನಷ್ಟು ಸಹಾಯ ಪಡೆಯಲು, ಇಲ್ಲಿ ಕ್ಲಿಕ್ ಮಾಡಿ - ಕೀಲಿಮಣೆ ಬಳಕೆ ಗುಂಡಿ - ಅಕ್ಷ&ರ ಶೈಲಿ (ಫಾಂಟ್) ಸಹಾಯಕ - &ಅಕ್ಷರ ನಕ್ಷೆ - &ಪಠ್ಯ ಸಂಪಾದಕ - ಸಂರಚನೆ (&ಕಾನ್ಫಿಗರೇಷನ್) - ಪಠ್ಯ ಸಂಪಾದಕ - Keyman - diff --git a/windows/src/desktop/kmshell/locale/kn-IN/strings.xml b/windows/src/desktop/kmshell/locale/kn/strings.xml similarity index 100% rename from windows/src/desktop/kmshell/locale/kn-IN/strings.xml rename to windows/src/desktop/kmshell/locale/kn/strings.xml diff --git a/windows/src/desktop/kmshell/locale/pt-BR/strings.xml b/windows/src/desktop/kmshell/locale/pt-BR/strings.xml index 6d0794ab39..7c7b31dd4a 100644 --- a/windows/src/desktop/kmshell/locale/pt-BR/strings.xml +++ b/windows/src/desktop/kmshell/locale/pt-BR/strings.xml @@ -46,6 +46,10 @@ Cancel + + Add/remove language... + + Click this icon to select a keyboard @@ -64,6 +68,18 @@ Help + + + + Uninstall + + + + Enable + + + + Disable @@ -174,6 +190,10 @@ Add language + + Add/remove language + + On Screen Keyboard: @@ -223,7 +243,7 @@ - Keyboard options + Keyboard options... @@ -341,7 +361,7 @@ - (none) + (no hotkey) @@ -622,11 +642,11 @@ keyboard that you use in Windows. Keyman keyboards will adapt automatically to - English + Português do Brasil - English + Português do Brasil (Brazilian Portuguese) diff --git a/windows/src/desktop/kmshell/xml/keyman_keyboardlist.xsl b/windows/src/desktop/kmshell/xml/keyman_keyboardlist.xsl index d8e90fbef5..79debebe39 100644 --- a/windows/src/desktop/kmshell/xml/keyman_keyboardlist.xsl +++ b/windows/src/desktop/kmshell/xml/keyman_keyboardlist.xsl @@ -150,7 +150,7 @@ add_remove_ kbd_button - javascript:showModifyLink('') + javascript:showModifyLink('') 0 @@ -382,10 +382,10 @@
- modify- + modify-
- return hideModifyLink('') + return hideModifyLink('')
@@ -405,7 +405,7 @@ kbd_button - return hideModifyLink('') + return hideModifyLink('')
diff --git a/windows/src/desktop/setup/locale/kn/strings.xml b/windows/src/desktop/setup/locale/kn/strings.xml new file mode 100644 index 0000000000..c6b39409a2 --- /dev/null +++ b/windows/src/desktop/setup/locale/kn/strings.xml @@ -0,0 +1,78 @@ + + + ಕನ್ನಡ + $APPNAME $VERSION ಸೆಟ್ಅಪ್ + $APPNAME $VERSION ಸ್ಥಾಪಿಸಿ + $APPNAME $VERSION ಯಶಸ್ವಿಯಾಗಿ ಸ್ಥಾಪಿಸಲಾಗಿದೆ. + $APPNAME ಸ್ಥಾಪನೆಯನ್ನು ರದ್ದುಗೊಳಿಸಲು ನೀವು ಖಚಿತವಾಗಿ ಬಯಸುವಿರಾ? + ಕಡತಗಳನ್ನು ಹೊರತೆಗೆಯಲಾಗುತ್ತಿದೆ... + ಪ್ಯಾಕೇಜ್‌ಗಳನ್ನು ಪರಿಶೀಲಿಸಲಾಗುತ್ತಿದೆ... + ನವೀಕರಣಗಳಿಗಾಗಿ ಆನ್‌ಲೈನ್‌ನಲ್ಲಿ ಪರಿಶೀಲಿಸಲಾಗುತ್ತಿದೆ... + ಸ್ಥಾಪಿಸಲಾದ ಆವೃತ್ತಿಗಳನ್ನು ಪರಿಶೀಲಿಸಲಾಗುತ್ತಿದೆ... + ಪೂರ್ಣಗೊಳಿಸುತ್ತಿದೆ... + + $APPNAME %0:s %1:s + + • %0:s %1:s %2:s + + • %2:s ಗೆ %0:s %1:s %3:s + ಸ್ಥಾಪಿಸಲು ಏನೂ ಇಲ್ಲ. + + (ಡೌನ್ಲೋಡ್ %0:s) + ಸೆಟ್ಅಪ್ ಸ್ಥಾಪಿಸುತ್ತದೆ: + $APPNAME $VERSION ಉಚಿತ ಮತ್ತು ಮುಕ್ತ ಸಂಪನ್ಮೂಲವಾಗಿದೆ + &ಪರವಾನಗಿಯನ್ನು ಓದಿ + ಅನುಸ್ಥಾಪಿಸುವ & ಆಯ್ಕೆಗಳು + $APPNAME ಅನುಸ್ಥಾಪಿಸು + ಸರಿ + &ಅನುಸ್ಥಾಪಿಸು + ರದ್ದುಮಾಡು + ನಿರ್ಗಮನ& + $APPNAME ಸ್ಥಾಪಿಸಲಾಗುತ್ತಿದೆ + ಹಳೆಯ ಆವೃತ್ತಿಗಳನ್ನು ತೆಗೆದುಹಾಕಲಾಗುತ್ತಿದೆ + ಅನುಸ್ಥಾಪನೆಯು ಪೂರ್ಣಗೊಂಡಿದೆ + ಸೆಟ್‌ಅಪ್ ಅನ್ನು ಪೂರ್ಣಗೊಳಿಸಲು ನೀವು ವಿಂಡೋಸ್ ಅನ್ನು ಮರುಪ್ರಾರಂಭಿಸಬೇಕು. ನೀವು ವಿಂಡೋಸ್ ಅನ್ನು ಮರುಪ್ರಾರಂಭಿಸಿದಾಗ, ಸೆಟ್‌ಅಪ್ ಮುಂದುವರಿಯುತ್ತದೆ. + +ಈಗ ವಿಂಡೋಸ್ ಅನ್ನು ಮರುಪ್ರಾರಂಭಿಸಬಹುದೇ? + ವಿಂಡೋಸ್ ಅನ್ನು ಮರುಪ್ರಾರಂಭಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ. ನೀವು $APPNAME ಅನ್ನು ಪ್ರಾರಂಭಿಸುವ ಮೊದಲು, ವಿಂಡೋಸ್ ಅನ್ನು ಮರುಪ್ರಾರಂಭಿಸಬೇಕು. + ಸೆಟ್‌ಅಪ್ ಅನ್ನು ಪೂರ್ಣಗೊಳಿಸಲು ನೀವು ವಿಂಡೋಸ್ ಅನ್ನು ಮರುಪ್ರಾರಂಭಿಸಬೇಕು. ನೀವು ವಿಂಡೋಸ್ ಅನ್ನು ಮರುಪ್ರಾರಂಭಿಸಿದಾಗ, ಸೆಟ್‌ಅಪ್ ಮುಕ್ತಾಯಗೊಳ್ಳುತ್ತದೆ. + $APPNAME $VERSION ಸ್ಥಾಪಿಸಲು (Windows 7) ವಿಂಡೋಸ್ ೭ ಅಥವಾ ನಂತರದ ಅಗತ್ಯವಿದೆ. ಆದಾಗ್ಯೂ, ಕೀಮನ್ ಡೆಸ್ಕ್‌ಟಾಪ್ 7, 8 ಅಥವಾ 9 ಅನ್ನು ಪತ್ತೆಹಚ್ಚಲಾಗಿದೆ. ಈ ಸ್ಥಾಪಕದಲ್ಲಿ ಸೇರಿಸಲಾದ ಕೀಲಿಮಣೆಗಳನ್ನು ಸ್ಥಾಪಿಸಲಾದ ಕೀಮ್ಯಾನ್ ಡೆಸ್ಕ್‌ಟಾಪ್ ಆವೃತ್ತಿಗೆ ಸ್ಥಾಪಿಸಲು ನೀವು ಬಯಸುವಿರಾ? + $APPNAME ನ ಈ ಆವೃತ್ತಿಯನ್ನು ಸ್ಥಾಪಿಸಲು (Windows 7) ವಿಂಡೋಸ್ ೭ ಅಥವಾ ನಂತರದ ಅಗತ್ಯವಿದೆ. ನೀವು ಕೀಮ್ಯಾನ್ ಡೆಸ್ಕ್‌ಟಾಪ್ ೮ ಅನ್ನು ಡೌನ್‌ಲೋಡ್ ಮಾಡಲು ಬಯಸುವಿರಾ? + ಸ್ಥಾಪಿಸುವ ಆಯ್ಕೆಗಳು + ಅನುಸ್ಥಾಪನೆಯ ಆಯ್ಕೆಗಳು + ಪೂರ್ವನಿರ್ಧರಿತ $APPNAME ಸೆಟ್ಟಿಂಗ್‌ಗಳು + ಸ್ಥಾಪಿಸಲು ಅಥವ ನವೀಕರಿಸಲು ಇರುವ ಮಾಡ್ಯೂಲ್‌ಗಳು + ಕೀಲಿಮಣೆ ಸಂಬಂಧಿತ ಭಾಷೆಗಳು + ಸ್ಥಾಪಿಸಲು ಆವೃತ್ತಿ + $APPNAME ಚಲನೆಯನ್ನು ವಿಂಡೋಸ್ ಪ್ರಾರಂಭವಾದಾಗ ಪ್ರಾರಂಭಿಸು + ಸ್ಥಾಪನೆ ಪೂರ್ಣಗೊಂಡಾಗ $APPNAME ಅನ್ನು ಪ್ರಾರಂಭಿಸಿ + ನವೀಕರಣಗಳಿಗೆ ನಿಯತಕಾಲಿಕವಾಗಿ ಆನ್‌ಲೈನ್‌ನಲ್ಲಿ ಪರಿಶೀಲಿಸಿ + ಹಳೆಯ ಆವೃತ್ತಿಗಳೊಂದಿಗೆ ಸ್ಥಾಪಿಸಲಾದ ಕೀಲಿಮಣೆ‌ಗಳನ್ನು $VERSION ಆವೃತ್ತಿಗೆ ನವೀಕರಿಸು + keyman.com ಜೊತೆಗೆ ಅನಾಮಧೇಯ ಬಳಕೆಯ ಅಂಕಿಅಂಶಗಳನ್ನು ಹಂಚಿಕೊಳ್ಳಿ + + ಸೆಟ್ಅಪ್ ಆವೃತ್ತಿ: %0:s + $APPNAME ಸ್ಥಾಪಿಸು + $APPNAME ನವೀಕರಿಸು + + $APPNAME %0:s ಈಗಾಗಲೇ ಸ್ಥಾಪಿಸಲಾಗಿದೆ. + + ಡೌನ್ಲೋಡ್ ಆವೃತ್ತಿ %0:s (%1:s) + + ಆವೃತ್ತಿ %0:s + + %0:s ಸ್ಥಾಪಿಸು + + ಡೌನ್ಲೋಡ್ ಆವೃತ್ತಿ %0:s (%1:s) + + ಆವೃತ್ತಿ %0:s + + %0:s ಕೀಲಿಮಣೆಗೆ ಸಂಬಂಧಿತ ಭಾಷೆಯನ್ನು ಆಯ್ಕೆಮಾಡಿ + ಪೂರ್ವನಿರ್ಧರಿತ ಭಾಷೆ + + %0:s ಡೌನ್ಲೋಡ್ ಮಾಡಲಾಗುತ್ತಿದೆ + + %0:s ಡೌನ್ಲೋಡ್ ಮಾಡಲಾಗುತ್ತಿದೆ + $APPNAME Setup could not connect to keyman.com to download additional resources. + Please check that you are online, and give $APPNAME Setup permission to access the Internet in your firewall settings. + Click Abort to exit Setup, Retry to try and download resources again, or Ignore to continue offline. +