1
0
mirror of https://github.com/bitwarden/mobile synced 2025-12-10 13:23:39 +00:00

Compare commits

..

79 Commits

Author SHA1 Message Date
Álison Fernandes
a798ae0761 [PM-7014] Track MessagePack fork and turn off CI / recurring workflows (#3456)
* Remove messagepack submodule

* Migrate MessagePack fork to this repo

* Disable build CI

* Disable Renovate

* Disable Crowdin recurring job

* Address workflow linter errors
2025-01-06 18:59:54 -03:00
Vince Grassia
7f8b19a0a7 BRE-540 - Update Crowdin Sync workflow to use GitHub App (#3454) 2025-01-06 16:55:08 -05:00
github-actions[bot]
e50175abe1 Autosync the updated translations (#3446)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2024-12-13 14:30:02 +00:00
github-actions[bot]
8f435b2f26 Autosync the updated translations (#3445)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2024-12-06 11:02:38 +00:00
github-actions[bot]
cdbdec8943 Autosync the updated translations (#3443)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2024-11-29 13:00:47 +00:00
github-actions[bot]
3d42da2a29 Autosync the updated translations (#3442)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2024-11-22 11:15:15 +00:00
github-actions[bot]
16303e581b Autosync the updated translations (#3439)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2024-11-15 12:37:46 +00:00
github-actions[bot]
bc4b03b994 Autosync the updated translations (#3438)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2024-11-08 00:45:53 +00:00
github-actions[bot]
484eb03eca Autosync the updated translations (#3435)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2024-11-01 09:55:55 +01:00
github-actions[bot]
d59f80776c Autosync the updated translations (#3431)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2024-10-25 11:40:08 +02:00
Opeyemi
44849cb0a2 [BRE-365] - Enable Android and F-droid build (#3430) 2024-10-22 11:42:16 -04:00
Opeyemi
65794c02b1 [BRE-372] - Clean up document start (#3427) 2024-10-21 15:22:35 -03:00
Álison Fernandes
8bc90b9649 [PM-13677] Disable WatchOS (#3426)
* Disable watchos

* enable testflight validation

* Revert "enable testflight validation"

This reverts commit 75012f0854.
2024-10-18 10:29:03 -03:00
github-actions[bot]
466bb81cb7 Autosync the updated translations (#3423)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2024-10-18 09:22:56 +02:00
Michał Chęciński
c957e46ff8 [BRE-101] Remove dept-devops from CODEOWNERS (#3289)
* BRE-101: Remove dept-devops from CODEOWNERS

* Fix

* Update CODEOWNERS for CI/CD Partnership Phase 2

* Update .github/CODEOWNERS

Co-authored-by: Vince Grassia <593223+vgrassia@users.noreply.github.com>

* Fix

---------

Co-authored-by: Vince Grassia <593223+vgrassia@users.noreply.github.com>
2024-10-17 13:01:25 -03:00
Opeyemi
d2d442253b [BRE-365] - Update Apple Store Creds to Team Issuer Credential (#3421)
* update Apple store creds to team issuer credential

* update

* Update key id for altool

---------

Co-authored-by: Vince Grassia <593223+vgrassia@users.noreply.github.com>
2024-10-14 16:20:23 +01:00
Bitwarden DevOps
f1a2714e8a Bumped version to 2024.10.111 (#3417) 2024-10-11 16:13:06 +00:00
Opeyemi
9083bb1ab8 disable android build (#3416) 2024-10-11 10:02:56 -06:00
Bitwarden DevOps
a69420257d Bumped version to 2024.10.0 (#3415) 2024-10-11 14:24:32 +00:00
Opeyemi
ef81365ae0 [BRE-365] - Disable OS build (#3414)
* disable ios build
2024-10-11 16:12:29 +02:00
github-actions[bot]
81ad6b3cc4 Autosync the updated translations (#3413)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2024-10-11 07:53:38 +00:00
Álison Fernandes
5ca0167dbb [PM-13357] Disable Cipher Key Encryption (#3408)
* Enables the cipher key encryption flag

* Revert "Enables the cipher key encryption flag"

This reverts commit f933c7d69f.
2024-10-10 12:38:19 +02:00
Álison Fernandes
e1f3f3dfd9 [PM-13356] Fix iOS build by pinning dotnet and MAUI version (#3410)
* Pinning MauiVersion hardcoded to 8.0.7 to avoid using the MauiVersion variable. Also pinning .NET version to use to 8.0.7 so it's the same one as the latest public release.

* Pinned dotnet version to 8.0.303 which was the latest one of the latest public release

* Added global json to pin .NET version to use and added diagnostic logs on dotnet publish, also commented other workflows.

* Set TargetPlatformVersion in Directory Build props

* test moving global.json

* Check out the repo first so global.json is available

* Remove workloadVersion from global.json

* pin maui install version

* Try workload restore

* Adding workload restore

* Use ios workload instead

* Set specific MAUI workload to install to 8.0.402

* Fix MAUI workload install to 8.0.300

* Add step to remove dotnet

* Update sdk / maui to 8.0.402

* Bumped xcode to 15.4

* Revert build.yml comments

* Revert csproj and build.props

* Remove diag flag

* Android / F-droid: Install pinned version of maui workload instead of latest

* Android / F-Droid: checkout repo earlier in the build process so global.json is used

---------

Co-authored-by: Federico Maccaroni <fedemkr@gmail.com>
2024-10-10 11:51:28 +02:00
github-actions[bot]
53a5a9caaa Autosync the updated translations (#3403)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2024-10-04 10:32:25 +02:00
github-actions[bot]
94381eebf0 Autosync the updated translations (#3395)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2024-09-27 08:47:17 +00:00
github-actions[bot]
b43eaf4a0a Autosync the updated translations (#3390)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2024-09-20 11:17:59 +00:00
github-actions[bot]
b89d8214d2 Autosync the updated translations (#3385)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2024-09-13 09:50:40 +00:00
github-actions[bot]
902ce67867 Autosync the updated translations (#3384)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2024-08-30 10:22:37 +00:00
github-actions[bot]
062b15aae9 Autosync the updated translations (#3382)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2024-08-23 10:45:37 +02:00
github-actions[bot]
dcf441afd7 Autosync the updated translations (#3379)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2024-08-16 11:59:32 +02:00
github-actions[bot]
c987840936 Autosync the updated translations (#3370)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2024-08-09 10:02:10 +00:00
Vince Grassia
6e93983711 Fix F-Droid build and release process (#3374) 2024-08-05 16:07:43 -03:00
Bitwarden DevOps
70de8245fe Bumped version to 2024.7.2 (#3364) 2024-07-26 14:52:38 +00:00
github-actions[bot]
77d9920aab Autosync the updated translations (#3362)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2024-07-26 10:37:21 +00:00
github-actions[bot]
b908f1c721 Autosync the updated translations (#3359)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2024-07-19 19:21:08 +00:00
GitHubArchive
46a249de46 [deps]: Update gh minor (#3298)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-16 15:06:47 -04:00
Bitwarden DevOps
837628e9bc Bumped version to 2024.7.1 (#3355) 2024-07-16 14:31:41 +00:00
Vince Grassia
3262fdc9ec Fix build pipeline MAUI version (#3354) 2024-07-16 14:51:29 +02:00
github-actions[bot]
c763b0072b Autosync the updated translations (#3343)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2024-07-12 11:27:59 +02:00
Carlos Gonçalves
b81ce44cc7 pm-9483 Update model attachments (#3344) 2024-07-08 15:27:11 +01:00
Álison Fernandes
8a43bb4655 [PM-9340] Updates the Bugs template to reference the new native apps (#3336)
* Update bug.yml to reference the new native apps

* Replacing table with a GitHub Alert.

https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#alerts

* Added Alert to README

* Fix template syntax error

* Improved bug templated and added config links

* Update .github/ISSUE_TEMPLATE/config.yml

Co-authored-by: Matt Bishop <mbishop@bitwarden.com>

---------

Co-authored-by: Matt Bishop <mbishop@bitwarden.com>
2024-07-03 09:26:39 -03:00
Vince Grassia
44f8901519 Fix increment version steps (#3342) 2024-07-02 19:02:31 -07:00
Bitwarden DevOps
463d837fa8 Bumped version to 2024.7.0 (#3341) 2024-07-01 17:15:59 +00:00
Matt Czech
ad6ffad5d1 [PM-9043] BIT-2356: Update casing of Bitwarden Help Center string (#3305) 2024-06-19 21:00:59 +00:00
Federico Maccaroni
9edcc8b4f7 [AC-2788] Remove unassigned items feature flag and logic (#3300) 2024-06-19 08:57:04 -03:00
Álison Fernandes
cf5c5aa114 [PM-8392] Enables the Cipher Key Encryption preprocessor define (#3266) 2024-06-18 13:41:49 +01:00
github-actions[bot]
36c7beb1e6 Autosync Crowdin Translations (#3297)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2024-06-14 08:23:03 +00:00
Bitwarden DevOps
f6d798af94 Bump version to 2024.6.1 (#3296) 2024-06-13 15:50:57 +00:00
Michał Chęciński
08ed70d5b1 Fix release (#3294) 2024-06-13 08:40:18 -07:00
André Bispo
33e0187460 [PM-8814] Remove EU feature flag (#3291) 2024-06-12 14:32:04 +01:00
github-actions[bot]
2b78859d06 Autosync Crowdin Translations (#3283)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2024-06-07 06:12:26 +00:00
Federico Maccaroni
81205154c4 [PM-8666] Fix Password Autofill from Quick Type on iOS < 17 (#3282) 2024-06-06 16:30:51 -03:00
Michał Chęciński
14d2660b61 [BRE-94] Replace dawidd6/action-download-artifact with bitwarden/gh-actions/download-artifacts (#3278) 2024-06-04 16:25:56 +02:00
renovate[bot]
bad5673724 [deps]: Update crowdin/github-action action to v2 (#3271)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-03 16:51:08 -04:00
Bitwarden DevOps
67b76a777e Bump version to 2024.6.0 (#3274) 2024-06-03 18:33:00 +00:00
github-actions[bot]
02f5936fce Autosync Crowdin Translations (#3269)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2024-05-31 06:15:27 +00:00
github-actions[bot]
fc208b08d7 Autosync the updated translations (#3267)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2024-05-29 20:07:32 +00:00
Alex Urbina
f165135147 BRE-87 ADD: Slack notification enable feature and check in version-bump workflow (#3264) 2024-05-27 15:33:11 -06:00
github-actions[bot]
d458f17ad6 Autosync the updated translations (#3257)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2024-05-24 12:09:19 +00:00
Alex Urbina
c3bd4b84b1 BRE-40 ADD: step to report upcoming release version to Slack (#3247) 2024-05-21 11:15:00 -06:00
renovate[bot]
0af78d0e03 [deps]: Update gh minor (#3252)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-21 11:06:29 -04:00
github-actions[bot]
e86a01a7db Autosync the updated translations (#3255)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2024-05-20 08:33:29 +00:00
github-actions[bot]
e16074a73e Autosync the updated translations (#3250)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2024-05-17 10:36:01 +00:00
Vince Grassia
a333e72448 Update F-Droid release process (#3249) 2024-05-17 00:15:17 -03:00
Bitwarden DevOps
ffb7b3b8ac Bumped version to 2024.5.2 (#3248) 2024-05-16 22:33:03 +00:00
Federico Maccaroni
c8d0db9f31 PM-8051 Fix 2FA launch from iOS autofill, was missing passing appOptions to the App (#3244) 2024-05-15 13:25:27 -03:00
Federico Maccaroni
8566f5c00a PM-8051 Fix WebAuthenticator getting the Window properly on iOS with the workaround to use Share app window when coming from iOS extension (#3239) 2024-05-13 14:26:37 -03:00
renovate[bot]
b65f18d8e2 [deps]: Update gh minor (#3235)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-13 09:23:54 -04:00
github-actions[bot]
7a3816007b Autosync the updated translations (#3233)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2024-05-13 12:34:45 +00:00
Federico Maccaroni
477b1cca44 [PM-7255] Fix autofill cancelling the request producing inconsistent behavior (#3230)
* PM-7255 Fix autofill cancelling the request on password autofill because of wrong safeguard

* PM-7255 Clear code no longer used
2024-05-08 16:54:00 -03:00
Bitwarden DevOps
dee9524b2c Bumped version to 2024.5.1 (#3227) 2024-05-06 22:37:03 +00:00
renovate[bot]
f5572511c6 [deps]: Update nuget/setup-nuget action to v2 (#3222)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-06 10:18:57 -04:00
renovate[bot]
9a17da009c [deps]: Update ubuntu to v22 (#3224)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-06 10:18:38 -04:00
Álison Fernandes
b5443c79d2 [PM-7922] Updating labeler.yml to the new format required by V5 (#3219) 2024-05-04 15:51:16 +01:00
Joseph Flinn
9dc620b492 Revert "Bumped version to 2024.5.1 (#3217)" (#3218)
This reverts commit 1f966e6cbe.
2024-05-03 13:02:44 -07:00
Bitwarden DevOps
1f966e6cbe Bumped version to 2024.5.1 (#3217) 2024-05-03 19:37:30 +00:00
Bitwarden DevOps
a4fa03656e Bumped version to 2024.5.0 (#3216) 2024-05-03 19:35:24 +00:00
Federico Maccaroni
12385d9add [PM-7877] Added loading dialog when unlocking with PIN (#3215)
* PM-7877 Added loading dialog when unlocking with PIN

* PM-7877 Added exception logging on unlock with PIN
2024-05-03 14:22:46 -03:00
github-actions[bot]
13ca0fd4cb Autosync the updated translations (#3213)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2024-05-03 14:06:00 +00:00
192 changed files with 6353 additions and 3176 deletions

24
.github/CODEOWNERS vendored
View File

@@ -7,15 +7,6 @@
# Default file owners # Default file owners
* @bitwarden/dept-development-mobile * @bitwarden/dept-development-mobile
# DevOps for Actions and other workflow changes
.github/workflows @bitwarden/dept-devops
# DevOps for Version Bumping
src/App/Platforms/Android/AndroidManifest.xml
src/iOS.Autofill/Info.plist
src/iOS.Extension/Info.plist
src/iOS.ShareExtension/Info.plist
src/App/Platforms/iOS/Info.plist
## Auth team files ## ## Auth team files ##
@@ -43,3 +34,18 @@ store/google/en
## Utils ## ## Utils ##
store/google/Publisher store/google/Publisher
## These workflows have joint ownership ##
.github/workflows/build.yml @bitwarden/dept-bre @bitwarden/dept-development-mobile
.github/workflows/build-beta.yml @bitwarden/dept-bre @bitwarden/dept-development-mobile
.github/workflows/cleanup-rc-branch.yml @bitwarden/dept-bre @bitwarden/dept-development-mobile
.github/workflows/release.yml @bitwarden/dept-bre @bitwarden/dept-development-mobile
.github/workflows/version-auto-bump.yml @bitwarden/dept-bre @bitwarden/dept-development-mobile
.github/workflows/version-bump.yml @bitwarden/dept-bre @bitwarden/dept-development-mobile
# Shared ownership for version bump automation
src/App/Platforms/Android/AndroidManifest.xml
src/iOS.Autofill/Info.plist
src/iOS.Extension/Info.plist
src/iOS.ShareExtension/Info.plist
src/App/Platforms/iOS/Info.plist

View File

@@ -7,7 +7,19 @@ body:
value: | value: |
Thanks for taking the time to fill out this bug report! Thanks for taking the time to fill out this bug report!
> [!WARNING]
> Testing the new Bitwarden Beta apps? Submit your report in [bitwarden/android](https://github.com/bitwarden/android) or [bitwarden/ios](https://github.com/bitwarden/ios)
Please do not submit feature requests. The [Community Forums](https://community.bitwarden.com) has a section for submitting, voting for, and discussing product feature requests. Please do not submit feature requests. The [Community Forums](https://community.bitwarden.com) has a section for submitting, voting for, and discussing product feature requests.
- type: checkboxes
id: production
attributes:
label: Production Build
options:
- label: I'm using the legacy Bitwarden app pubicly available in App Store / Play Store and I'm aware that Bitwarden Beta bugs should be reported in [bitwarden/android](https://github.com/bitwarden/android) or [bitwarden/ios](https://github.com/bitwarden/ios)
validations:
required: true
- type: textarea - type: textarea
id: reproduce id: reproduce
attributes: attributes:
@@ -73,9 +85,3 @@ body:
description: What version of our software are you running? (go to "Settings" → "About" in the app) description: What version of our software are you running? (go to "Settings" → "About" in the app)
validations: validations:
required: true required: true
- type: checkboxes
id: beta
attributes:
label: Beta
options:
- label: Using a pre-release version of the application.

View File

@@ -1,5 +1,11 @@
blank_issues_enabled: false blank_issues_enabled: false
contact_links: contact_links:
- name: Native Android Beta Bug Reports
url: https://github.com/bitwarden/android/issues
about: Bugs found in the new native Android Beta app should be reported in [bitwarden/android](https://github.com/bitwarden/android)
- name: Native iOS BETA Bug Reports
url: https://github.com/bitwarden/ios/issues
about: Bugs found in the new native iOS Beta app should be reported in [bitwarden/ios](https://github.com/bitwarden/ios)
- name: Customer Support - name: Customer Support
url: https://bitwarden.com/contact/ url: https://bitwarden.com/contact/
about: Please contact our customer support for account issues and general customer support. about: Please contact our customer support for account issues and general customer support.

35
.github/labeler.yml vendored
View File

@@ -1,19 +1,26 @@
android: android:
- src/App/* - changed-files:
- src/Core/* - any-glob-to-any-file:
- src/Android/* - src/App/*
- src/Core/*
- src/Android/*
- 'src/Xamarin.AndroidX.Credentials/*'
iOS: iOS:
- src/App/* - changed-files:
- src/Core/* - any-glob-to-any-file:
- lib/ios/* - src/App/*
- src/iOS/* - src/Core/*
- 'src/iOS.Autofill/*' - lib/ios/*
- 'src/iOS.Core/*' - src/iOS/*
- 'src/iOS.Extension/*' - 'src/iOS.Autofill/*'
- 'src/iOS.ShareExtension/*' - 'src/iOS.Core/*'
- 'src/iOS.Widget/*' - 'src/iOS.Extension/*'
- src/watchOS/* - 'src/iOS.ShareExtension/*'
- 'src/iOS.Widget/*'
- src/watchOS/*
watchOS: watchOS:
- src/watchOS/* - changed-files:
- any-glob-to-any-file:
- src/watchOS/*

View File

@@ -1,4 +1,5 @@
{ {
"enabled": false,
"$schema": "https://docs.renovatebot.com/renovate-schema.json", "$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [ "extends": [
"config:base", "config:base",

View File

@@ -1,4 +1,3 @@
---
name: Automatic responses name: Automatic responses
on: on:
issues: issues:
@@ -7,7 +6,7 @@ on:
jobs: jobs:
close-issue: close-issue:
name: 'Close issue with automatic response' name: 'Close issue with automatic response'
runs-on: ubuntu-20.04 runs-on: ubuntu-22.04
permissions: permissions:
issues: write issues: write
steps: steps:

View File

@@ -1,4 +1,3 @@
---
name: Build Beta name: Build Beta
on: on:
@@ -24,7 +23,7 @@ jobs:
hotfix_branch_exists: ${{ steps.branch-check.outputs.hotfix_branch_exists }} hotfix_branch_exists: ${{ steps.branch-check.outputs.hotfix_branch_exists }}
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with: with:
submodules: 'true' submodules: 'true'
@@ -48,9 +47,9 @@ jobs:
runs-on: macos-14 runs-on: macos-14
needs: setup needs: setup
env: env:
ios_folder_path: src/App/Platforms/iOS _IOS_FOLDER_PATH: src/App/Platforms/iOS
app_output_name: App _APP_OUTPUT_NAME: App
app_ci_output_filename: App_x64_Debug _APP_CI_OUTPUT_FILENAME: App_x64_Debug
steps: steps:
- name: Set XCode version - name: Set XCode version
uses: maxim-lobanov/setup-xcode@60606e260d2fc5762a71e64e74b2174e8ea3c8bd # v1.6.0 uses: maxim-lobanov/setup-xcode@60606e260d2fc5762a71e64e74b2174e8ea3c8bd # v1.6.0
@@ -58,12 +57,12 @@ jobs:
xcode-version: 15.1 xcode-version: 15.1
- name: Setup NuGet - name: Setup NuGet
uses: nuget/setup-nuget@296fd3ccf8528660c91106efefe2364482f86d6f # v1.2.0 uses: nuget/setup-nuget@a21f25cd3998bf370fde17e3f1b4c12c175172f9 # v2.0.0
with: with:
nuget-version: 6.4.0 nuget-version: 6.4.0
- name: Set up .NET - name: Set up .NET
uses: actions/setup-dotnet@4d6c8fcf3c8f7a60068d26b594648e99df24cee3 # v4.0.0 uses: actions/setup-dotnet@6bd8b7f7774af54e05809fcc5431931b3eb1ddee # v4.0.1
with: with:
dotnet-version: '8.0.x' dotnet-version: '8.0.x'
@@ -80,7 +79,7 @@ jobs:
echo "GitHub event: $GITHUB_EVENT" echo "GitHub event: $GITHUB_EVENT"
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with: with:
fetch-depth: 0 fetch-depth: 0
ref: ${{ inputs.ref }} ref: ${{ inputs.ref }}
@@ -136,7 +135,7 @@ jobs:
echo "### CFBundleVersion $BUILD_NUMBER" >> $GITHUB_STEP_SUMMARY echo "### CFBundleVersion $BUILD_NUMBER" >> $GITHUB_STEP_SUMMARY
perl -0777 -pi.bak -e 's/<key>CFBundleVersion<\/key>\s*<string>1<\/string>/<key>CFBundleVersion<\/key>\n\t<string>'"$BUILD_NUMBER"'<\/string>/' ./${{ env.ios_folder_path }}/Info.plist perl -0777 -pi.bak -e 's/<key>CFBundleVersion<\/key>\s*<string>1<\/string>/<key>CFBundleVersion<\/key>\n\t<string>'"$BUILD_NUMBER"'<\/string>/' ./${{ env._IOS_FOLDER_PATH }}/Info.plist
perl -0777 -pi.bak -e 's/<key>CFBundleVersion<\/key>\s*<string>1<\/string>/<key>CFBundleVersion<\/key>\n\t<string>'"$BUILD_NUMBER"'<\/string>/' ./src/iOS.Extension/Info.plist perl -0777 -pi.bak -e 's/<key>CFBundleVersion<\/key>\s*<string>1<\/string>/<key>CFBundleVersion<\/key>\n\t<string>'"$BUILD_NUMBER"'<\/string>/' ./src/iOS.Extension/Info.plist
perl -0777 -pi.bak -e 's/<key>CFBundleVersion<\/key>\s*<string>1<\/string>/<key>CFBundleVersion<\/key>\n\t<string>'"$BUILD_NUMBER"'<\/string>/' ./src/iOS.Autofill/Info.plist perl -0777 -pi.bak -e 's/<key>CFBundleVersion<\/key>\s*<string>1<\/string>/<key>CFBundleVersion<\/key>\n\t<string>'"$BUILD_NUMBER"'<\/string>/' ./src/iOS.Autofill/Info.plist
perl -0777 -pi.bak -e 's/<key>CFBundleVersion<\/key>\s*<string>1<\/string>/<key>CFBundleVersion<\/key>\n\t<string>'"$BUILD_NUMBER"'<\/string>/' ./src/iOS.ShareExtension/Info.plist perl -0777 -pi.bak -e 's/<key>CFBundleVersion<\/key>\s*<string>1<\/string>/<key>CFBundleVersion<\/key>\n\t<string>'"$BUILD_NUMBER"'<\/string>/' ./src/iOS.ShareExtension/Info.plist
@@ -146,7 +145,7 @@ jobs:
- name: Update Entitlements - name: Update Entitlements
run: | run: |
echo "##### Updating Entitlements" echo "##### Updating Entitlements"
perl -0777 -pi.bak -e 's/<key>aps-environment<\/key>\s*<string>development<\/string>/<key>aps-environment<\/key>\n\t<string>beta<\/string>/' ./${{ env.ios_folder_path }}/Entitlements.plist perl -0777 -pi.bak -e 's/<key>aps-environment<\/key>\s*<string>development<\/string>/<key>aps-environment<\/key>\n\t<string>beta<\/string>/' ./${{ env._IOS_FOLDER_PATH }}/Entitlements.plist
- name: Get certificates - name: Get certificates
run: | run: |
@@ -246,8 +245,8 @@ jobs:
ARCHIVE_PATH: ./${{ env.main_app_folder_path }}/bin/Debug/${{ env.target-net-version }}-ios/iossimulator-x64 ARCHIVE_PATH: ./${{ env.main_app_folder_path }}/bin/Debug/${{ env.target-net-version }}-ios/iossimulator-x64
EXPORT_PATH: ./bitwarden-export EXPORT_PATH: ./bitwarden-export
run: | run: |
zip -r -q ${{ env.app_ci_output_filename }}.app.zip $ARCHIVE_PATH zip -r -q ${{ env._APP_CI_OUTPUT_FILENAME }}.app.zip $ARCHIVE_PATH
mv ${{ env.app_ci_output_filename }}.app.zip $EXPORT_PATH mv ${{ env._APP_CI_OUTPUT_FILENAME }}.app.zip $EXPORT_PATH
- name: Show Bitwarden Export - name: Show Bitwarden Export
shell: bash shell: bash
@@ -266,7 +265,7 @@ jobs:
cp -r -v $WATCH_ARCHIVE_DSYMS_PATH $WATCH_DSYMS_EXPORT_PATH cp -r -v $WATCH_ARCHIVE_DSYMS_PATH $WATCH_DSYMS_EXPORT_PATH
- name: Upload App Store .ipa & dSYMs artifacts - name: Upload App Store .ipa & dSYMs artifacts
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4
with: with:
name: Bitwarden iOS name: Bitwarden iOS
path: | path: |
@@ -275,10 +274,10 @@ jobs:
if-no-files-found: error if-no-files-found: error
- name: Upload .app file for Automation CI - name: Upload .app file for Automation CI
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4
with: with:
name: ${{ env.app_ci_output_filename }}.app.zip name: ${{ env._APP_CI_OUTPUT_FILENAME }}.app.zip
path: ./bitwarden-export/${{ env.app_ci_output_filename }}.app.zip path: ./bitwarden-export/${{ env._APP_CI_OUTPUT_FILENAME }}.app.zip
if-no-files-found: error if-no-files-found: error
- name: Install AppCenter CLI - name: Install AppCenter CLI

View File

@@ -1,19 +1,14 @@
---
name: Build name: Build
on: on:
push:
branches-ignore:
- "l10n_master"
- "gh-pages"
paths-ignore:
- ".github/workflows/**"
workflow_dispatch: workflow_dispatch:
env: env:
main_app_folder_path: src/App main_app_folder_path: src/App
main_app_project_path: src/App/App.csproj main_app_project_path: src/App/App.csproj
target-net-version: net8.0 target-net-version: net8.0
dotnet-version: '8.0.402'
maui-workload-version: '8.0.402'
jobs: jobs:
cloc: cloc:
@@ -21,7 +16,7 @@ jobs:
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Set up CLOC - name: Set up CLOC
run: | run: |
@@ -40,7 +35,7 @@ jobs:
hotfix_branch_exists: ${{ steps.branch-check.outputs.hotfix_branch_exists }} hotfix_branch_exists: ${{ steps.branch-check.outputs.hotfix_branch_exists }}
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with: with:
submodules: 'true' submodules: 'true'
@@ -69,27 +64,31 @@ jobs:
matrix: matrix:
variant: ["prod", "qa"] variant: ["prod", "qa"]
env: env:
android_folder_path: src\App\Platforms\Android _ANDROID_FOLDER_PATH: src\App\Platforms\Android
android_folder_path_bash: src/App/Platforms/Android _ANDROID_FOLDER_PATH_BASH: src/App/Platforms/Android
steps: steps:
- name: Checkout repo
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
fetch-depth: 0
- name: Setup NuGet - name: Setup NuGet
uses: nuget/setup-nuget@296fd3ccf8528660c91106efefe2364482f86d6f # v1.2.0 uses: nuget/setup-nuget@a21f25cd3998bf370fde17e3f1b4c12c175172f9 # v2.0.0
with: with:
nuget-version: 6.4.0 nuget-version: 6.4.0
- name: Set up .NET - name: Set up .NET
uses: actions/setup-dotnet@4d6c8fcf3c8f7a60068d26b594648e99df24cee3 # v4.0.0 uses: actions/setup-dotnet@6bd8b7f7774af54e05809fcc5431931b3eb1ddee # v4.0.1
with: with:
dotnet-version: '8.0.x' dotnet-version: ${{ env.dotnet-version }}
- name: Install MAUI Workload
run: |
dotnet workload install maui --version ${{ env.maui-workload-version }}
- name: Set up MSBuild - name: Set up MSBuild
uses: microsoft/setup-msbuild@6fb02220983dee41ce7ae257b6f4d8f9bf5ed4ce # v2.0.0 uses: microsoft/setup-msbuild@6fb02220983dee41ce7ae257b6f4d8f9bf5ed4ce # v2.0.0
# This step might be obsolete at some point as .NET MAUI workloads
# are starting to come pre-installed on the GH Actions build agents.
- name: Install MAUI Workload
run: dotnet workload install maui --ignore-failed-sources
- name: Setup Windows builder - name: Setup Windows builder
run: choco install checksum --no-progress run: choco install checksum --no-progress
@@ -108,11 +107,6 @@ jobs:
echo "GitHub ref: $GITHUB_REF" echo "GitHub ref: $GITHUB_REF"
echo "GitHub event: $GITHUB_EVENT" echo "GitHub event: $GITHUB_EVENT"
- name: Checkout repo
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
with:
fetch-depth: 0
- name: Login to Azure - CI Subscription - name: Login to Azure - CI Subscription
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0 uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
with: with:
@@ -126,9 +120,9 @@ jobs:
mkdir -p $HOME/secrets mkdir -p $HOME/secrets
az storage blob download --account-name $ACCOUNT_NAME --container-name $CONTAINER_NAME \ az storage blob download --account-name $ACCOUNT_NAME --container-name $CONTAINER_NAME \
--name app_play-keystore.jks --file ./${{ env.android_folder_path_bash }}/app_play-keystore.jks --output none --name app_play-keystore.jks --file ./${{ env._ANDROID_FOLDER_PATH_BASH }}/app_play-keystore.jks --output none
az storage blob download --account-name $ACCOUNT_NAME --container-name $CONTAINER_NAME \ az storage blob download --account-name $ACCOUNT_NAME --container-name $CONTAINER_NAME \
--name app_upload-keystore.jks --file ./${{ env.android_folder_path_bash }}/app_upload-keystore.jks --output none --name app_upload-keystore.jks --file ./${{ env._ANDROID_FOLDER_PATH_BASH }}/app_upload-keystore.jks --output none
az storage blob download --account-name $ACCOUNT_NAME --container-name $CONTAINER_NAME \ az storage blob download --account-name $ACCOUNT_NAME --container-name $CONTAINER_NAME \
--name play_creds.json --file $HOME/secrets/play_creds.json --output none --name play_creds.json --file $HOME/secrets/play_creds.json --output none
shell: bash shell: bash
@@ -140,16 +134,16 @@ jobs:
CONTAINER_NAME: mobile CONTAINER_NAME: mobile
run: | run: |
az storage blob download --account-name $ACCOUNT_NAME --container-name $CONTAINER_NAME \ az storage blob download --account-name $ACCOUNT_NAME --container-name $CONTAINER_NAME \
--name google-services.json --file ./${{ env.android_folder_path_bash }}/google-services.json --output none --name google-services.json --file ./${{ env._ANDROID_FOLDER_PATH_BASH }}/google-services.json --output none
shell: bash shell: bash
- name: Increment version - name: Increment version
run: | run: |
BUILD_NUMBER=$((3000 + $GITHUB_RUN_NUMBER)) BUILD_NUMBER=$((11000 + $GITHUB_RUN_NUMBER))
echo "##### Setting Android Version Code to $BUILD_NUMBER" | tee -a $GITHUB_STEP_SUMMARY echo "##### Setting Android Version Code to $BUILD_NUMBER" | tee -a $GITHUB_STEP_SUMMARY
sed -i "s/android:versionCode=\"1\"/android:versionCode=\"$BUILD_NUMBER\"/" \ sed -i "s/android:versionCode=\"1\"/android:versionCode=\"$BUILD_NUMBER\"/" \
./${{ env.android_folder_path_bash }}/AndroidManifest.xml ./${{ env._ANDROID_FOLDER_PATH_BASH }}/AndroidManifest.xml
shell: bash shell: bash
- name: Restore packages - name: Restore packages
@@ -193,7 +187,7 @@ jobs:
} }
Write-Output "##### Sign Google Play Bundle Release Configuration" Write-Output "##### Sign Google Play Bundle Release Configuration"
$signingUploadKeyStore = "$($env:GITHUB_WORKSPACE)\${{ env.android_folder_path }}\app_upload-keystore.jks" $signingUploadKeyStore = "$($env:GITHUB_WORKSPACE)\${{ env._ANDROID_FOLDER_PATH }}\app_upload-keystore.jks"
dotnet publish $projToBuild -c Release -f ${{ env.target-net-version }}-android ` dotnet publish $projToBuild -c Release -f ${{ env.target-net-version }}-android `
/p:AndroidPackageFormats=aab ` /p:AndroidPackageFormats=aab `
/p:AndroidKeyStore=true ` /p:AndroidKeyStore=true `
@@ -210,7 +204,7 @@ jobs:
Write-Output "##### Sign APK Release Configuration" Write-Output "##### Sign APK Release Configuration"
$signingPlayKeyStore = "$($env:GITHUB_WORKSPACE)\${{ env.android_folder_path }}\app_play-keystore.jks" $signingPlayKeyStore = "$($env:GITHUB_WORKSPACE)\${{ env._ANDROID_FOLDER_PATH }}\app_play-keystore.jks"
dotnet publish $projToBuild -c Release -f ${{ env.target-net-version }}-android ` dotnet publish $projToBuild -c Release -f ${{ env.target-net-version }}-android `
/p:AndroidKeyStore=true ` /p:AndroidKeyStore=true `
/p:AndroidSigningKeyStore=$signingPlayKeyStore ` /p:AndroidSigningKeyStore=$signingPlayKeyStore `
@@ -226,7 +220,7 @@ jobs:
- name: Upload Prod .aab artifact - name: Upload Prod .aab artifact
if: ${{ matrix.variant == 'prod' }} if: ${{ matrix.variant == 'prod' }}
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4
with: with:
name: com.x8bit.bitwarden.aab name: com.x8bit.bitwarden.aab
path: ./com.x8bit.bitwarden.aab path: ./com.x8bit.bitwarden.aab
@@ -234,7 +228,7 @@ jobs:
- name: Upload Prod .apk artifact - name: Upload Prod .apk artifact
if: ${{ matrix.variant == 'prod' }} if: ${{ matrix.variant == 'prod' }}
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4
with: with:
name: com.x8bit.bitwarden.apk name: com.x8bit.bitwarden.apk
path: ./com.x8bit.bitwarden.apk path: ./com.x8bit.bitwarden.apk
@@ -242,7 +236,7 @@ jobs:
- name: Upload Other .apk artifact - name: Upload Other .apk artifact
if: ${{ matrix.variant != 'prod' }} if: ${{ matrix.variant != 'prod' }}
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4
with: with:
name: com.x8bit.bitwarden.${{ matrix.variant }}.apk name: com.x8bit.bitwarden.${{ matrix.variant }}.apk
path: ./com.x8bit.bitwarden.${{ matrix.variant }}.apk path: ./com.x8bit.bitwarden.${{ matrix.variant }}.apk
@@ -262,7 +256,7 @@ jobs:
- name: Upload .apk sha file for prod - name: Upload .apk sha file for prod
if: ${{ matrix.variant == 'prod' }} if: ${{ matrix.variant == 'prod' }}
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4
with: with:
name: bw-android-apk-sha256.txt name: bw-android-apk-sha256.txt
path: ./bw-android-apk-sha256.txt path: ./bw-android-apk-sha256.txt
@@ -270,7 +264,7 @@ jobs:
- name: Upload .apk sha file for other - name: Upload .apk sha file for other
if: ${{ matrix.variant != 'prod' }} if: ${{ matrix.variant != 'prod' }}
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4
with: with:
name: bw-android-${{ matrix.variant }}-apk-sha256.txt name: bw-android-${{ matrix.variant }}-apk-sha256.txt
path: ./bw-android-${{ matrix.variant }}-apk-sha256.txt path: ./bw-android-${{ matrix.variant }}-apk-sha256.txt
@@ -295,28 +289,32 @@ jobs:
name: F-Droid Build name: F-Droid Build
runs-on: windows-2022 runs-on: windows-2022
env: env:
android_folder_path: src\App\Platforms\Android _ANDROID_FOLDER_PATH: src\App\Platforms\Android
android_folder_path_bash: src/App/Platforms/Android _ANDROID_FOLDER_PATH_BASH: src/App/Platforms/Android
android_manifest_path: src/App/Platforms/Android/AndroidManifest.xml _ANDROID_MANIFEST_PATH: src/App/Platforms/Android/AndroidManifest.xml
steps: steps:
- name: Checkout repo
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
fetch-depth: 0
- name: Setup NuGet - name: Setup NuGet
uses: nuget/setup-nuget@296fd3ccf8528660c91106efefe2364482f86d6f # v1.2.0 uses: nuget/setup-nuget@a21f25cd3998bf370fde17e3f1b4c12c175172f9 # v2.0.0
with: with:
nuget-version: 6.4.0 nuget-version: 6.4.0
- name: Set up .NET - name: Set up .NET
uses: actions/setup-dotnet@4d6c8fcf3c8f7a60068d26b594648e99df24cee3 # v4.0.0 uses: actions/setup-dotnet@6bd8b7f7774af54e05809fcc5431931b3eb1ddee # v4.0.1
with: with:
dotnet-version: '8.0.x' dotnet-version: ${{ env.dotnet-version }}
- name: Install MAUI Workload
run: |
dotnet workload install maui --version ${{ env.maui-workload-version }}
- name: Set up MSBuild - name: Set up MSBuild
uses: microsoft/setup-msbuild@6fb02220983dee41ce7ae257b6f4d8f9bf5ed4ce # v2.0.0 uses: microsoft/setup-msbuild@6fb02220983dee41ce7ae257b6f4d8f9bf5ed4ce # v2.0.0
# This step might be obsolete at some point as .NET MAUI workloads
# are starting to come pre-installed on the GH Actions build agents.
- name: Install MAUI Workload
run: dotnet workload install maui --ignore-failed-sources
- name: Setup Windows builder - name: Setup Windows builder
run: choco install checksum --no-progress run: choco install checksum --no-progress
@@ -334,9 +332,6 @@ jobs:
echo "GitHub ref: $GITHUB_REF" echo "GitHub ref: $GITHUB_REF"
echo "GitHub event: $GITHUB_EVENT" echo "GitHub event: $GITHUB_EVENT"
- name: Checkout repo
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
- name: Login to Azure - CI Subscription - name: Login to Azure - CI Subscription
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0 uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
with: with:
@@ -349,23 +344,23 @@ jobs:
FILE: app_fdroid-keystore.jks FILE: app_fdroid-keystore.jks
run: | run: |
az storage blob download --account-name $ACCOUNT_NAME --container-name $CONTAINER_NAME --name $FILE \ az storage blob download --account-name $ACCOUNT_NAME --container-name $CONTAINER_NAME --name $FILE \
--file ${{ env.android_folder_path_bash }}/$FILE --output none --file ${{ env._ANDROID_FOLDER_PATH_BASH }}/$FILE --output none
shell: bash shell: bash
- name: Increment version - name: Increment version
run: | run: |
BUILD_NUMBER=$((3000 + $GITHUB_RUN_NUMBER)) BUILD_NUMBER=$((11000 + $GITHUB_RUN_NUMBER))
echo "##### Setting F-Droid Version Code to $BUILD_NUMBER" | tee -a $GITHUB_STEP_SUMMARY echo "##### Setting F-Droid Version Code to $BUILD_NUMBER" | tee -a $GITHUB_STEP_SUMMARY
sed -i "s/android:versionCode=\"1\"/android:versionCode=\"$BUILD_NUMBER\"/" \ sed -i "s/android:versionCode=\"1\"/android:versionCode=\"$BUILD_NUMBER\"/" \
./${{ env.android_manifest_path }} ./${{ env._ANDROID_MANIFEST_PATH }}
shell: bash shell: bash
- name: Clean for F-Droid - name: Clean for F-Droid
run: | run: |
$directoryBuildProps = $($env:GITHUB_WORKSPACE + "/Directory.Build.props"); $directoryBuildProps = $($env:GITHUB_WORKSPACE + "/Directory.Build.props");
$androidManifest = $($env:GITHUB_WORKSPACE + "/${{ env.android_manifest_path }}"); $androidManifest = $($env:GITHUB_WORKSPACE + "/${{ env._ANDROID_MANIFEST_PATH }}");
Write-Output "##### Back up project files" Write-Output "##### Back up project files"
@@ -398,7 +393,7 @@ jobs:
Write-Output "##### Sign FDroid" Write-Output "##### Sign FDroid"
$signingFdroidKeyStore = "$($env:GITHUB_WORKSPACE)\${{ env.android_folder_path }}\app_fdroid-keystore.jks" $signingFdroidKeyStore = "$($env:GITHUB_WORKSPACE)\${{ env._ANDROID_FOLDER_PATH }}\app_fdroid-keystore.jks"
dotnet build $projToBuild -c Release -f ${{ env.target-net-version }}-android ` dotnet build $projToBuild -c Release -f ${{ env.target-net-version }}-android `
/p:AndroidKeyStore=true ` /p:AndroidKeyStore=true `
/p:AndroidSigningKeyStore=$signingFdroidKeyStore ` /p:AndroidSigningKeyStore=$signingFdroidKeyStore `
@@ -414,7 +409,7 @@ jobs:
Copy-Item $signedApkPath $signedApkDestPath Copy-Item $signedApkPath $signedApkDestPath
- name: Upload F-Droid .apk artifact - name: Upload F-Droid .apk artifact
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4
with: with:
name: com.x8bit.bitwarden-fdroid.apk name: com.x8bit.bitwarden-fdroid.apk
path: ./com.x8bit.bitwarden-fdroid.apk path: ./com.x8bit.bitwarden-fdroid.apk
@@ -426,7 +421,7 @@ jobs:
-t sha256 | Out-File -Encoding ASCII ./bw-fdroid-apk-sha256.txt -t sha256 | Out-File -Encoding ASCII ./bw-fdroid-apk-sha256.txt
- name: Upload F-Droid sha file - name: Upload F-Droid sha file
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4
with: with:
name: bw-fdroid-apk-sha256.txt name: bw-fdroid-apk-sha256.txt
path: ./bw-fdroid-apk-sha256.txt path: ./bw-fdroid-apk-sha256.txt
@@ -438,29 +433,32 @@ jobs:
runs-on: macos-14 runs-on: macos-14
needs: setup needs: setup
env: env:
ios_folder_path: src/App/Platforms/iOS _IOS_FOLDER_PATH: src/App/Platforms/iOS
app_output_name: App _APP_OUTPUT_NAME: App
app_ci_output_filename: App_x64_Debug _APP_CI_OUTPUT_FILENAME: App_x64_Debug
steps: steps:
- name: Checkout repo
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
submodules: 'true'
- name: Set XCode version - name: Set XCode version
uses: maxim-lobanov/setup-xcode@60606e260d2fc5762a71e64e74b2174e8ea3c8bd # v1.6.0 uses: maxim-lobanov/setup-xcode@60606e260d2fc5762a71e64e74b2174e8ea3c8bd # v1.6.0
with: with:
xcode-version: 15.1 xcode-version: 15.4
- name: Setup NuGet - name: Setup NuGet
uses: nuget/setup-nuget@296fd3ccf8528660c91106efefe2364482f86d6f # v1.2.0 uses: nuget/setup-nuget@a21f25cd3998bf370fde17e3f1b4c12c175172f9 # v2.0.0
with: with:
nuget-version: 6.4.0 nuget-version: 6.4.0
- name: Set up .NET - name: Set up .NET
uses: actions/setup-dotnet@4d6c8fcf3c8f7a60068d26b594648e99df24cee3 # v4.0.0 uses: actions/setup-dotnet@6bd8b7f7774af54e05809fcc5431931b3eb1ddee # v4.0.1
with: with:
dotnet-version: '8.0.x' dotnet-version: ${{ env.dotnet-version }}
# This step might be obsolete at some point as .NET MAUI workloads
# are starting to come pre-installed on the GH Actions build agents.
- name: Install MAUI Workload - name: Install MAUI Workload
run: dotnet workload install maui --ignore-failed-sources run: dotnet workload install maui --version ${{ env.maui-workload-version }}
- name: Print environment - name: Print environment
run: | run: |
@@ -469,11 +467,6 @@ jobs:
echo "GitHub ref: $GITHUB_REF" echo "GitHub ref: $GITHUB_REF"
echo "GitHub event: $GITHUB_EVENT" echo "GitHub event: $GITHUB_EVENT"
- name: Checkout repo
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
with:
submodules: 'true'
- name: Login to Azure - CI Subscription - name: Login to Azure - CI Subscription
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0 uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
with: with:
@@ -519,10 +512,10 @@ jobs:
- name: Increment version - name: Increment version
run: | run: |
BUILD_NUMBER=$((100 + $GITHUB_RUN_NUMBER)) BUILD_NUMBER=$((8000 + $GITHUB_RUN_NUMBER))
echo "##### Setting iOS CFBundleVersion to $BUILD_NUMBER" | tee -a $GITHUB_STEP_SUMMARY echo "##### Setting iOS CFBundleVersion to $BUILD_NUMBER" | tee -a $GITHUB_STEP_SUMMARY
perl -0777 -pi.bak -e 's/<key>CFBundleVersion<\/key>\s*<string>1<\/string>/<key>CFBundleVersion<\/key>\n\t<string>'"$BUILD_NUMBER"'<\/string>/' ./${{ env.ios_folder_path }}/Info.plist perl -0777 -pi.bak -e 's/<key>CFBundleVersion<\/key>\s*<string>1<\/string>/<key>CFBundleVersion<\/key>\n\t<string>'"$BUILD_NUMBER"'<\/string>/' ./${{ env._IOS_FOLDER_PATH }}/Info.plist
perl -0777 -pi.bak -e 's/<key>CFBundleVersion<\/key>\s*<string>1<\/string>/<key>CFBundleVersion<\/key>\n\t<string>'"$BUILD_NUMBER"'<\/string>/' ./src/iOS.Extension/Info.plist perl -0777 -pi.bak -e 's/<key>CFBundleVersion<\/key>\s*<string>1<\/string>/<key>CFBundleVersion<\/key>\n\t<string>'"$BUILD_NUMBER"'<\/string>/' ./src/iOS.Extension/Info.plist
perl -0777 -pi.bak -e 's/<key>CFBundleVersion<\/key>\s*<string>1<\/string>/<key>CFBundleVersion<\/key>\n\t<string>'"$BUILD_NUMBER"'<\/string>/' ./src/iOS.Autofill/Info.plist perl -0777 -pi.bak -e 's/<key>CFBundleVersion<\/key>\s*<string>1<\/string>/<key>CFBundleVersion<\/key>\n\t<string>'"$BUILD_NUMBER"'<\/string>/' ./src/iOS.Autofill/Info.plist
perl -0777 -pi.bak -e 's/<key>CFBundleVersion<\/key>\s*<string>1<\/string>/<key>CFBundleVersion<\/key>\n\t<string>'"$BUILD_NUMBER"'<\/string>/' ./src/iOS.ShareExtension/Info.plist perl -0777 -pi.bak -e 's/<key>CFBundleVersion<\/key>\s*<string>1<\/string>/<key>CFBundleVersion<\/key>\n\t<string>'"$BUILD_NUMBER"'<\/string>/' ./src/iOS.ShareExtension/Info.plist
@@ -532,7 +525,7 @@ jobs:
- name: Update Entitlements - name: Update Entitlements
run: | run: |
echo "##### Updating Entitlements" echo "##### Updating Entitlements"
perl -0777 -pi.bak -e 's/<key>aps-environment<\/key>\s*<string>development<\/string>/<key>aps-environment<\/key>\n\t<string>production<\/string>/' ./${{ env.ios_folder_path }}/Entitlements.plist perl -0777 -pi.bak -e 's/<key>aps-environment<\/key>\s*<string>development<\/string>/<key>aps-environment<\/key>\n\t<string>production<\/string>/' ./${{ env._IOS_FOLDER_PATH }}/Entitlements.plist
- name: Get certificates - name: Get certificates
run: | run: |
@@ -616,8 +609,8 @@ jobs:
ARCHIVE_PATH: ./${{ env.main_app_folder_path }}/bin/Debug/${{ env.target-net-version }}-ios/iossimulator-x64 ARCHIVE_PATH: ./${{ env.main_app_folder_path }}/bin/Debug/${{ env.target-net-version }}-ios/iossimulator-x64
EXPORT_PATH: ./bitwarden-export EXPORT_PATH: ./bitwarden-export
run: | run: |
zip -r -q ${{ env.app_ci_output_filename }}.app.zip $ARCHIVE_PATH zip -r -q ${{ env._APP_CI_OUTPUT_FILENAME }}.app.zip $ARCHIVE_PATH
mv ${{ env.app_ci_output_filename }}.app.zip $EXPORT_PATH mv ${{ env._APP_CI_OUTPUT_FILENAME }}.app.zip $EXPORT_PATH
- name: Copy all dSYMs files to upload - name: Copy all dSYMs files to upload
env: env:
@@ -631,7 +624,7 @@ jobs:
cp -r -v $WATCH_ARCHIVE_DSYMS_PATH $WATCH_DSYMS_EXPORT_PATH cp -r -v $WATCH_ARCHIVE_DSYMS_PATH $WATCH_DSYMS_EXPORT_PATH
- name: Upload App Store .ipa & dSYMs artifacts - name: Upload App Store .ipa & dSYMs artifacts
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4
with: with:
name: Bitwarden iOS name: Bitwarden iOS
path: | path: |
@@ -640,10 +633,10 @@ jobs:
if-no-files-found: error if-no-files-found: error
- name: Upload .app file for Automation CI - name: Upload .app file for Automation CI
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4
with: with:
name: ${{ env.app_ci_output_filename }}.app.zip name: ${{ env._APP_CI_OUTPUT_FILENAME }}.app.zip
path: ./bitwarden-export/${{ env.app_ci_output_filename }}.app.zip path: ./bitwarden-export/${{ env._APP_CI_OUTPUT_FILENAME }}.app.zip
if-no-files-found: error if-no-files-found: error
- name: Install AppCenter CLI - name: Install AppCenter CLI
@@ -677,19 +670,27 @@ jobs:
echo "##### Uploading Watch dSYMs to Firebase" echo "##### Uploading Watch dSYMs to Firebase"
find "$HOME/Library/Developer/XCode/DerivedData" -name "upload-symbols" -exec chmod +x {} \; -exec {} -gsp "./src/watchOS/bitwarden/GoogleService-Info.plist" -p ios "./bitwarden-export/Watch_dSYMs" \; find "$HOME/Library/Developer/XCode/DerivedData" -name "upload-symbols" -exec chmod +x {} \; -exec {} -gsp "./src/watchOS/bitwarden/GoogleService-Info.plist" -p ios "./bitwarden-export/Watch_dSYMs" \;
- name: Set up private auth key
run: |
mkdir ~/private_keys
cat << EOF > ~/private_keys/AuthKey_U362LJ87AA.p8
${{ secrets.APP_STORE_CONNECT_AUTH_KEY }}
EOF
- name: Validate app in App Store - name: Validate app in App Store
if: | if: |
(github.ref == 'refs/heads/master' (github.ref == 'refs/heads/main'
&& needs.setup.outputs.rc_branch_exists == 0 && needs.setup.outputs.rc_branch_exists == 0
&& needs.setup.outputs.hotfix_branch_exists == 0) && needs.setup.outputs.hotfix_branch_exists == 0)
|| (github.ref == 'refs/heads/rc' && needs.setup.outputs.hotfix_branch_exists == 0) || (github.ref == 'refs/heads/rc' && needs.setup.outputs.hotfix_branch_exists == 0)
|| github.ref == 'refs/heads/hotfix-rc' || github.ref == 'refs/heads/hotfix-rc'
env:
APPLE_ID_USERNAME: ${{ secrets.APPLE_ID_USERNAME }}
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
run: | run: |
xcrun altool --validate-app --type ios --file "./bitwarden-export/Bitwarden.ipa" \ xcrun altool \
--username "$APPLE_ID_USERNAME" --password "$APPLE_ID_PASSWORD" --validate-app \
--type ios \
--file "./bitwarden-export/Bitwarden.ipa" \
--apiKey "U362LJ87AA" \
--apiIssuer ${{ secrets.APP_STORE_CONNECT_TEAM_ISSUER }}
- name: Deploy to App Store - name: Deploy to App Store
if: | if: |
@@ -698,13 +699,13 @@ jobs:
&& needs.setup.outputs.hotfix_branch_exists == 0) && needs.setup.outputs.hotfix_branch_exists == 0)
|| (github.ref == 'refs/heads/rc' && needs.setup.outputs.hotfix_branch_exists == 0) || (github.ref == 'refs/heads/rc' && needs.setup.outputs.hotfix_branch_exists == 0)
|| github.ref == 'refs/heads/hotfix-rc' || github.ref == 'refs/heads/hotfix-rc'
env:
APPLE_ID_USERNAME: ${{ secrets.APPLE_ID_USERNAME }}
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
run: | run: |
xcrun altool --upload-app --type ios --file "./bitwarden-export/Bitwarden.ipa" \ xcrun altool \
--username "$APPLE_ID_USERNAME" --password "$APPLE_ID_PASSWORD" --upload-app \
--type ios \
--file "./bitwarden-export/Bitwarden.ipa" \
--apiKey "U362LJ87AA" \
--apiIssuer ${{ secrets.APP_STORE_CONNECT_TEAM_ISSUER }}
crowdin-push: crowdin-push:
name: Crowdin Push name: Crowdin Push
@@ -718,7 +719,7 @@ jobs:
_CROWDIN_PROJECT_ID: "269690" _CROWDIN_PROJECT_ID: "269690"
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Login to Azure - CI Subscription - name: Login to Azure - CI Subscription
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0 uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
@@ -733,7 +734,7 @@ jobs:
secrets: "crowdin-api-token" secrets: "crowdin-api-token"
- name: Upload Sources - name: Upload Sources
uses: crowdin/github-action@67705afb6985401459cd143d5f5f00c9dc212f23 # v1.20.2 uses: crowdin/github-action@61ac8b980551f674046220c3e104bddae2916ac5 # v2.0.0
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }} CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }}

View File

@@ -1,4 +1,3 @@
---
name: Cleanup RC Branch name: Cleanup RC Branch
on: on:
@@ -24,7 +23,7 @@ jobs:
secrets: "github-pat-bitwarden-devops-bot-repo-scope" secrets: "github-pat-bitwarden-devops-bot-repo-scope"
- name: Checkout main - name: Checkout main
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with: with:
ref: main ref: main
token: ${{ steps.retrieve-bot-secrets.outputs.github-pat-bitwarden-devops-bot-repo-scope }} token: ${{ steps.retrieve-bot-secrets.outputs.github-pat-bitwarden-devops-bot-repo-scope }}

View File

@@ -1,21 +1,27 @@
---
name: Crowdin Sync name: Crowdin Sync
on: on:
workflow_dispatch: workflow_dispatch:
inputs: {} inputs: {}
schedule:
- cron: '0 0 * * 5'
jobs: jobs:
crowdin-sync: crowdin-sync:
name: Autosync name: Autosync
runs-on: ubuntu-20.04 runs-on: ubuntu-24.04
env: env:
_CROWDIN_PROJECT_ID: "269690" _CROWDIN_PROJECT_ID: "269690"
steps: steps:
- name: Generate GH App token
uses: actions/create-github-app-token@c1a285145b9d317df6ced56c09f525b5c2b6f755 # v1.11.1
id: app-token
with:
app-id: ${{ secrets.BW_GHAPP_ID }}
private-key: ${{ secrets.BW_GHAPP_KEY }}
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
token: ${{ steps.app-token.outputs.token }}
- name: Login to Azure - CI Subscription - name: Login to Azure - CI Subscription
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0 uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
@@ -30,9 +36,9 @@ jobs:
secrets: "crowdin-api-token, github-gpg-private-key, github-gpg-private-key-passphrase" secrets: "crowdin-api-token, github-gpg-private-key, github-gpg-private-key-passphrase"
- name: Download translations - name: Download translations
uses: crowdin/github-action@67705afb6985401459cd143d5f5f00c9dc212f23 # v1.20.2 uses: crowdin/github-action@61ac8b980551f674046220c3e104bddae2916ac5 # v2.0.0
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ steps.app-token.outputs.token }}
CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }} CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }}
with: with:
config: crowdin.yml config: crowdin.yml

View File

@@ -1,4 +1,3 @@
---
name: Enforce PR labels name: Enforce PR labels
on: on:
@@ -7,7 +6,7 @@ on:
jobs: jobs:
enforce-label: enforce-label:
name: EnforceLabel name: EnforceLabel
runs-on: ubuntu-20.04 runs-on: ubuntu-22.04
steps: steps:
- name: Enforce Label - name: Enforce Label
uses: yogevbd/enforce-label-action@a3c219da6b8fa73f6ba62b68ff09c469b3a1c024 # 2.2.2 uses: yogevbd/enforce-label-action@a3c219da6b8fa73f6ba62b68ff09c469b3a1c024 # 2.2.2

View File

@@ -1,4 +1,3 @@
---
name: "Pull Request Labeler" name: "Pull Request Labeler"
on: on:
@@ -10,8 +9,9 @@ jobs:
permissions: permissions:
contents: read contents: read
pull-requests: write pull-requests: write
runs-on: ubuntu-20.04 runs-on: ubuntu-22.04
steps: steps:
- uses: actions/labeler@8558fd74291d67161a8a78ce36a881fa63b766a9 # v5.0.0 - name: Label PR
uses: actions/labeler@8558fd74291d67161a8a78ce36a881fa63b766a9 # v5.0.0
with: with:
sync-labels: true sync-labels: true

View File

@@ -1,4 +1,3 @@
---
name: Release name: Release
run-name: Release ${{ inputs.release_type }} run-name: Release ${{ inputs.release_type }}
@@ -23,7 +22,7 @@ on:
jobs: jobs:
release: release:
name: Create Release name: Create Release
runs-on: ubuntu-20.04 runs-on: ubuntu-22.04
outputs: outputs:
branch-name: ${{ steps.branch.outputs.branch-name }} branch-name: ${{ steps.branch.outputs.branch-name }}
steps: steps:
@@ -38,7 +37,7 @@ jobs:
fi fi
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Check Release Version - name: Check Release Version
id: version id: version
@@ -65,25 +64,31 @@ jobs:
description: 'Deployment ${{ steps.version.outputs.version }} from branch ${{ steps.branch.outputs.branch-name }}' description: 'Deployment ${{ steps.version.outputs.version }} from branch ${{ steps.branch.outputs.branch-name }}'
task: release task: release
- name: Download all artifacts - name: Download all artifacts
if: ${{ inputs.release_type != 'Dry Run' }} if: ${{ inputs.release_type != 'Dry Run' }}
uses: dawidd6/action-download-artifact@09f2f74827fd3a8607589e5ad7f9398816f540fe # v3.1.4 uses: bitwarden/gh-actions/download-artifacts@main
with: with:
workflow: build.yml workflow: build.yml
workflow_conclusion: success workflow_conclusion: success
branch: ${{ steps.branch.outputs.branch-name }} branch: ${{ steps.branch.outputs.branch-name }}
skip_unpack: true
- name: Dry Run - Download all artifacts - name: Dry Run - Download all artifacts
if: ${{ inputs.release_type == 'Dry Run' }} if: ${{ inputs.release_type == 'Dry Run' }}
uses: dawidd6/action-download-artifact@09f2f74827fd3a8607589e5ad7f9398816f540fe # v3.1.4 uses: bitwarden/gh-actions/download-artifacts@main
with: with:
workflow: build.yml workflow: build.yml
workflow_conclusion: success workflow_conclusion: success
branch: main branch: main
skip_unpack: true
- name: Prep Bitwarden iOS release asset - name: Unzip release assets
run: zip -r Bitwarden\ iOS.zip Bitwarden\ iOS run: |
unzip bw-android-apk-sha256.txt.zip -d bw-android-apk-sha256.txt
unzip bw-fdroid-apk-sha256.txt.zip -d bw-fdroid-apk-sha256.txt
unzip com.x8bit.bitwarden-fdroid.apk.zip -d com.x8bit.bitwarden-fdroid.apk
unzip com.x8bit.bitwarden.aab.zip -d com.x8bit.bitwarden.aab
unzip com.x8bit.bitwarden.apk.zip -d com.x8bit.bitwarden.apk
- name: Create release - name: Create release
if: ${{ inputs.release_type != 'Dry Run' }} if: ${{ inputs.release_type != 'Dry Run' }}
@@ -121,40 +126,36 @@ jobs:
f-droid: f-droid:
name: F-Droid Release name: F-Droid Release
runs-on: ubuntu-20.04 runs-on: ubuntu-22.04
needs: release needs: release
if: inputs.fdroid_publish if: inputs.fdroid_publish
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Download F-Droid .apk artifact - name: Download F-Droid .apk artifact
if: ${{ inputs.release_type != 'Dry Run' }} if: ${{ inputs.release_type != 'Dry Run' }}
uses: dawidd6/action-download-artifact@09f2f74827fd3a8607589e5ad7f9398816f540fe # v3.1.4 uses: bitwarden/gh-actions/download-artifacts@main
with: with:
workflow: build.yml workflow: build.yml
workflow_conclusion: success workflow_conclusion: success
branch: ${{ needs.release.outputs.branch-name }} branch: ${{ needs.release.outputs.branch-name }}
name: com.x8bit.bitwarden-fdroid.apk
- name: Dry Run - Download F-Droid .apk artifact - name: Dry Run - Download F-Droid .apk artifact
if: ${{ inputs.release_type == 'Dry Run' }} if: ${{ inputs.release_type == 'Dry Run' }}
uses: dawidd6/action-download-artifact@09f2f74827fd3a8607589e5ad7f9398816f540fe # v3.1.4 uses: bitwarden/gh-actions/download-artifacts@main
with: with:
workflow: build.yml workflow: build.yml
workflow_conclusion: success workflow_conclusion: success
branch: main branch: main
name: com.x8bit.bitwarden-fdroid.apk
- name: Set up Node - name: Set up Node
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
with: with:
node-version: '16.x' node-version: '16.x'
- name: Set up F-Droid server - name: Set up F-Droid server
run: | run: pip install git+https://gitlab.com/fdroid/fdroidserver.git
sudo apt-get -qq update
sudo apt-get -qqy install --no-install-recommends fdroidserver wget
- name: Set up Git credentials - name: Set up Git credentials
env: env:
@@ -167,9 +168,10 @@ jobs:
- name: Print environment - name: Print environment
run: | run: |
node --version echo "Node Version: $(node --version)"
npm --version echo "NPM Version: $(npm --version)"
git --version echo "Git Version: $(git --version)"
echo "F-Droid Server Version: $(fdroid --version)"
echo "GitHub ref: $GITHUB_REF" echo "GitHub ref: $GITHUB_REF"
echo "GitHub event: $GITHUB_EVENT" echo "GitHub event: $GITHUB_EVENT"
@@ -181,6 +183,28 @@ jobs:
with: with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
- name: Retrieve secrets
id: retrieve-secrets
uses: bitwarden/gh-actions/get-keyvault-secrets@main
with:
keyvault: "bitwarden-ci"
secrets: "github-gpg-private-key,
github-gpg-private-key-passphrase,
github-pat-bitwarden-devops-bot-mobile-fdroid"
- name: Import GPG key
uses: crazy-max/ghaction-import-gpg@01dd5d3ca463c7f10f7f4f7b4f177225ac661ee4 # v6.1.0
with:
gpg_private_key: ${{ steps.retrieve-secrets.outputs.github-gpg-private-key }}
passphrase: ${{ steps.retrieve-secrets.outputs.github-gpg-private-key-passphrase }}
git_user_signingkey: true
git_commit_gpgsign: true
- name: Setup git
run: |
git config --local user.email "106330231+bitwarden-devops-bot@users.noreply.github.com"
git config --local user.name "bitwarden-devops-bot"
- name: Download secrets - name: Download secrets
env: env:
ACCOUNT_NAME: bitwardenci ACCOUNT_NAME: bitwardenci
@@ -194,28 +218,35 @@ jobs:
env: env:
FDROID_STORE_KEYSTORE_PASSWORD: ${{ secrets.FDROID_STORE_KEYSTORE_PASSWORD }} FDROID_STORE_KEYSTORE_PASSWORD: ${{ secrets.FDROID_STORE_KEYSTORE_PASSWORD }}
run: | run: |
cd $GITHUB_WORKSPACE # Create required directories.
mkdir dist mkdir dist
cp CNAME ./dist mkdir -p store/temp/fdroid
cd store mkdir -p store/fdroid/repo
chmod 600 fdroid/config.py fdroid/keystore.jks
mkdir -p temp/fdroid # Configure F-Droid server.
cp CNAME dist/
chmod 600 store/fdroid/config.yml store/fdroid/keystore.jks
TEMP_DIR="$GITHUB_WORKSPACE/store/temp/fdroid" TEMP_DIR="$GITHUB_WORKSPACE/store/temp/fdroid"
cd fdroid echo "keypass: $FDROID_STORE_KEYSTORE_PASSWORD" >> store/fdroid/config.yml
echo "keypass=\"$FDROID_STORE_KEYSTORE_PASSWORD\"" >>config.py echo "keystorepass: $FDROID_STORE_KEYSTORE_PASSWORD" >> store/fdroid/config.yml
echo "keystorepass=\"$FDROID_STORE_KEYSTORE_PASSWORD\"" >>config.py echo "local_copy_dir: $TEMP_DIR" >> store/fdroid/config.yml
echo "local_copy_dir=\"$TEMP_DIR\"" >>config.py mv $GITHUB_WORKSPACE/com.x8bit.bitwarden-fdroid.apk store/fdroid/repo/
mkdir -p repo
mv $GITHUB_WORKSPACE/com.x8bit.bitwarden-fdroid.apk ./repo/ # Run update and deploy.
cd store/fdroid
fdroid update fdroid update
fdroid server update fdroid deploy
cd .. cd ../..
rm -rf temp/fdroid/archive
mv -v temp/fdroid ../dist # Move files for distribution.
cd fdroid rm -rf store/temp/fdroid/archive
cp index.html btn.png qr.png ../../dist/fdroid mv -v store/temp/fdroid dist
cd $GITHUB_WORKSPACE cp store/fdroid/index.html store/fdroid/btn.png store/fdroid/qr.png dist/fdroid
- name: Deploy to gh-pages - name: Deploy to gh-pages
if: ${{ inputs.release_type != 'Dry Run' }} if: ${{ inputs.release_type != 'Dry Run' }}
run: npm run deploy env:
TOKEN: ${{ steps.retrieve-secrets.outputs.github-pat-bitwarden-devops-bot-mobile-fdroid }}
run: |
git remote set-url origin https://git:${TOKEN}@github.com/${GITHUB_REPOSITORY}.git
npm run deploy -- -u "bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>"

View File

@@ -1,4 +1,3 @@
---
name: 'Close stale issues and PRs' name: 'Close stale issues and PRs'
on: on:
workflow_dispatch: workflow_dispatch:
@@ -8,7 +7,7 @@ on:
jobs: jobs:
stale: stale:
name: 'Check for stale issues and PRs' name: 'Check for stale issues and PRs'
runs-on: ubuntu-20.04 runs-on: ubuntu-22.04
steps: steps:
- name: 'Run stale action' - name: 'Run stale action'
uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e # v9.0.0 uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e # v9.0.0

View File

@@ -1,4 +1,3 @@
---
name: Auto Bump Mobile Version name: Auto Bump Mobile Version
on: on:

View File

@@ -1,4 +1,3 @@
---
name: Version Bump name: Version Bump
on: on:
@@ -12,6 +11,10 @@ on:
description: "Cut RC branch?" description: "Cut RC branch?"
default: true default: true
type: boolean type: boolean
enable_slack_notification:
description: "Enable Slack notifications for upcoming release?"
default: false
type: boolean
jobs: jobs:
bump_version: bump_version:
@@ -26,8 +29,16 @@ jobs:
with: with:
version: ${{ inputs.version_number_override }} version: ${{ inputs.version_number_override }}
- name: Slack Notification Check
run: |
if [[ "${{ inputs.enable_slack_notification }}" == true ]]; then
echo "Slack notifications enabled."
else
echo "Slack notifications disabled."
fi
- name: Checkout Branch - name: Checkout Branch
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with: with:
ref: main ref: main
@@ -257,6 +268,14 @@ jobs:
PR_NUMBER: ${{ steps.create-pr.outputs.pr_number }} PR_NUMBER: ${{ steps.create-pr.outputs.pr_number }}
run: gh pr merge $PR_NUMBER --squash --auto --delete-branch run: gh pr merge $PR_NUMBER --squash --auto --delete-branch
- name: Report upcoming release version to Slack
if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' && inputs.enable_slack_notification == true }}
uses: bitwarden/gh-actions/report-upcoming-release-version@main
with:
version: ${{ steps.set-final-version-output.outputs.version }}
project: ${{ github.repository }}
AZURE_KV_CI_SERVICE_PRINCIPAL: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
cut_rc: cut_rc:
name: Cut RC branch name: Cut RC branch
if: ${{ inputs.cut_rc_branch == true }} if: ${{ inputs.cut_rc_branch == true }}
@@ -264,7 +283,7 @@ jobs:
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
steps: steps:
- name: Checkout Branch - name: Checkout Branch
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with: with:
ref: main ref: main

16
.gitignore vendored
View File

@@ -296,17 +296,11 @@ iOSInjectionProject/
timeline.xctimeline timeline.xctimeline
playground.xcworkspace playground.xcworkspace
# Swift Package Manager # xcode / swift package manager - used by the MessagePack lib
# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. /.build
# Packages/ /Packages
# Package.pins /*.xcodeproj
# Package.resolved .swiftpm
# *.xcodeproj
# Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata
# hence it is not needed unless you have added a package configuration file to your project
# .swiftpm
.build/
# CocoaPods # CocoaPods
# We recommend against adding the Pods directory to your .gitignore. However # We recommend against adding the Pods directory to your .gitignore. However

3
.gitmodules vendored
View File

@@ -1,3 +0,0 @@
[submodule "lib/MessagePack"]
path = lib/MessagePack
url = https://github.com/bitwarden/MessagePack.git

View File

@@ -4,9 +4,8 @@
<ReleaseCodesignProvision>Automatic:AppStore</ReleaseCodesignProvision> <ReleaseCodesignProvision>Automatic:AppStore</ReleaseCodesignProvision>
<ReleaseCodesignKey>iPhone Distribution</ReleaseCodesignKey> <ReleaseCodesignKey>iPhone Distribution</ReleaseCodesignKey>
<IncludeBitwardeniOSExtensions>True</IncludeBitwardeniOSExtensions> <IncludeBitwardeniOSExtensions>True</IncludeBitwardeniOSExtensions>
<IncludeBitwardenWatchOSApp>True</IncludeBitwardenWatchOSApp> <IncludeBitwardenWatchOSApp>False</IncludeBitwardenWatchOSApp>
<Argon2IdLoadMtouchExtraArgs>-gcc_flags "-L$(ProjectDir)../../lib/ios -largon2 -force_load $(ProjectDir)../../lib/ios/libargon2.a"</Argon2IdLoadMtouchExtraArgs> <Argon2IdLoadMtouchExtraArgs>-gcc_flags "-L$(ProjectDir)../../lib/ios -largon2 -force_load $(ProjectDir)../../lib/ios/libargon2.a"</Argon2IdLoadMtouchExtraArgs>
<!-- Uncomment this when Unit Testing--> <!-- Uncomment this when Unit Testing-->
<!-- <CustomConstants>UT</CustomConstants> --> <!-- <CustomConstants>UT</CustomConstants> -->

View File

@@ -4,6 +4,10 @@
# Bitwarden Mobile Application # Bitwarden Mobile Application
> [!TIP]
> Looking for the new native apps? Head on over to [bitwarden/android](https://github.com/bitwarden/android) and [bitwarden/ios](https://github.com/bitwarden/ios)
<a href="https://play.google.com/store/apps/details?id=com.x8bit.bitwarden" target="_blank"><img alt="Get it on Google Play" src="https://imgur.com/YQzmZi9.png" width="153" height="46"></a> <a href="https://mobileapp.bitwarden.com/fdroid/" target="_blank"><img alt="Get it on F-Droid" src="https://i.imgur.com/HDicnzz.png" width="154" height="46"></a> <a href="https://itunes.apple.com/us/app/bitwarden-free-password-manager/id1137397744?mt=8" target="_blank"><img src="https://imgur.com/GdGqPMY.png" width="135" height="40"></a> <a href="https://play.google.com/store/apps/details?id=com.x8bit.bitwarden" target="_blank"><img alt="Get it on Google Play" src="https://imgur.com/YQzmZi9.png" width="153" height="46"></a> <a href="https://mobileapp.bitwarden.com/fdroid/" target="_blank"><img alt="Get it on F-Droid" src="https://i.imgur.com/HDicnzz.png" width="154" height="46"></a> <a href="https://itunes.apple.com/us/app/bitwarden-free-password-manager/id1137397744?mt=8" target="_blank"><img src="https://imgur.com/GdGqPMY.png" width="135" height="40"></a>
The Bitwarden mobile application is written in C# using .NET MAUI. The Bitwarden mobile application is written in C# using .NET MAUI.

6
global.json Normal file
View File

@@ -0,0 +1,6 @@
{
"sdk": {
"version": "8.0.402",
"rollForward": "disable"
}
}

Submodule lib/MessagePack deleted from 1ecb15e311

View File

@@ -0,0 +1,19 @@
Copyright 2018 Read Evaluate Press, LLC
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,32 @@
Pod::Spec.new do |s|
s.name = 'MessagePack-FlightSchool'
s.module_name = 'MessagePack'
s.version = '1.2.4'
s.summary = 'A MessagePack encoder and decoder for Codable types.'
s.description = <<-DESC
This functionality is discussed in Chapter 7 of
Flight School Guide to Swift Codable.
DESC
s.homepage = 'https://flight.school/books/codable/'
s.license = { type: 'MIT', file: 'LICENSE.md' }
s.author = { 'Mattt' => 'mattt@flight.school' }
s.social_media_url = 'https://twitter.com/mattt'
s.ios.deployment_target = '8.0'
s.osx.deployment_target = '10.10'
s.watchos.deployment_target = '2.0'
s.tvos.deployment_target = '9.0'
s.source = { git: 'https://github.com/Flight-School/MessagePack.git',
tag: s.version.to_s }
s.source_files = 'Sources/**/*.swift'
s.swift_version = '4.2'
s.static_framework = true
end

View File

@@ -0,0 +1,13 @@
import MessagePack
let encoder = MessagePackEncoder()
let value: String = "hello"
let encodedData = try encoder.encode(value)
print("Bytes: ", encodedData.map{ String($0, radix: 16, uppercase: true) })
let decoder = MessagePackDecoder()
let decodedValue = try decoder.decode(String.self, from: encodedData)
decodedValue == value

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<playground version='5.0' target-platform='macos' executeOnSourceChanges='false'>
<timeline fileName='timeline.xctimeline'/>
</playground>

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>

View File

@@ -0,0 +1,543 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXAggregateTarget section */
"MessagePack::MessagePackPackageTests::ProductTarget" /* MessagePackPackageTests */ = {
isa = PBXAggregateTarget;
buildConfigurationList = OBJ_57 /* Build configuration list for PBXAggregateTarget "MessagePackPackageTests" */;
buildPhases = (
);
dependencies = (
OBJ_60 /* PBXTargetDependency */,
);
name = MessagePackPackageTests;
productName = MessagePackPackageTests;
};
/* End PBXAggregateTarget section */
/* Begin PBXBuildFile section */
1BC312FF2992DE9C00177F2A /* DataSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1BC312FE2992DE9C00177F2A /* DataSpec.swift */; };
OBJ_38 /* AnyCodingKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_9 /* AnyCodingKey.swift */; };
OBJ_39 /* Box.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_10 /* Box.swift */; };
OBJ_40 /* KeyedDecodingContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_12 /* KeyedDecodingContainer.swift */; };
OBJ_41 /* MessagePackDecoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_13 /* MessagePackDecoder.swift */; };
OBJ_42 /* SingleValueDecodingContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_14 /* SingleValueDecodingContainer.swift */; };
OBJ_43 /* UnkeyedDecodingContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_15 /* UnkeyedDecodingContainer.swift */; };
OBJ_44 /* KeyedEncodingContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_17 /* KeyedEncodingContainer.swift */; };
OBJ_45 /* MessagePackEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_18 /* MessagePackEncoder.swift */; };
OBJ_46 /* SingleValueEncodingContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_19 /* SingleValueEncodingContainer.swift */; };
OBJ_47 /* UnkeyedEncodingContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_20 /* UnkeyedEncodingContainer.swift */; };
OBJ_48 /* FixedWidthInteger+Bytes.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_21 /* FixedWidthInteger+Bytes.swift */; };
OBJ_55 /* Package.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_6 /* Package.swift */; };
OBJ_66 /* Airport.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_24 /* Airport.swift */; };
OBJ_67 /* MessagePackDecodingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_25 /* MessagePackDecodingTests.swift */; };
OBJ_68 /* MessagePackEncodingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_26 /* MessagePackEncodingTests.swift */; };
OBJ_69 /* MessagePackPerformanceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_27 /* MessagePackPerformanceTests.swift */; };
OBJ_70 /* MessagePackRoundTripTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_28 /* MessagePackRoundTripTests.swift */; };
OBJ_72 /* MessagePack.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = "MessagePack::MessagePack::Product" /* MessagePack.framework */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
1BC312FC2989A1AD00177F2A /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = OBJ_1 /* Project object */;
proxyType = 1;
remoteGlobalIDString = "MessagePack::MessagePack";
remoteInfo = MessagePack;
};
1BC312FD2989A1B200177F2A /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = OBJ_1 /* Project object */;
proxyType = 1;
remoteGlobalIDString = "MessagePack::MessagePackTests";
remoteInfo = MessagePackTests;
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
1BC312FE2992DE9C00177F2A /* DataSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataSpec.swift; sourceTree = "<group>"; };
"MessagePack::MessagePack::Product" /* MessagePack.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = MessagePack.framework; sourceTree = BUILT_PRODUCTS_DIR; };
"MessagePack::MessagePackTests::Product" /* MessagePackTests.xctest */ = {isa = PBXFileReference; lastKnownFileType = file; path = MessagePackTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
OBJ_10 /* Box.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Box.swift; sourceTree = "<group>"; };
OBJ_12 /* KeyedDecodingContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyedDecodingContainer.swift; sourceTree = "<group>"; };
OBJ_13 /* MessagePackDecoder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessagePackDecoder.swift; sourceTree = "<group>"; };
OBJ_14 /* SingleValueDecodingContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SingleValueDecodingContainer.swift; sourceTree = "<group>"; };
OBJ_15 /* UnkeyedDecodingContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnkeyedDecodingContainer.swift; sourceTree = "<group>"; };
OBJ_17 /* KeyedEncodingContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyedEncodingContainer.swift; sourceTree = "<group>"; };
OBJ_18 /* MessagePackEncoder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessagePackEncoder.swift; sourceTree = "<group>"; };
OBJ_19 /* SingleValueEncodingContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SingleValueEncodingContainer.swift; sourceTree = "<group>"; };
OBJ_20 /* UnkeyedEncodingContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnkeyedEncodingContainer.swift; sourceTree = "<group>"; };
OBJ_21 /* FixedWidthInteger+Bytes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FixedWidthInteger+Bytes.swift"; sourceTree = "<group>"; };
OBJ_24 /* Airport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Airport.swift; sourceTree = "<group>"; };
OBJ_25 /* MessagePackDecodingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessagePackDecodingTests.swift; sourceTree = "<group>"; };
OBJ_26 /* MessagePackEncodingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessagePackEncodingTests.swift; sourceTree = "<group>"; };
OBJ_27 /* MessagePackPerformanceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessagePackPerformanceTests.swift; sourceTree = "<group>"; };
OBJ_28 /* MessagePackRoundTripTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessagePackRoundTripTests.swift; sourceTree = "<group>"; };
OBJ_29 /* MessagePack.xcworkspace */ = {isa = PBXFileReference; lastKnownFileType = wrapper.workspace; path = MessagePack.xcworkspace; sourceTree = SOURCE_ROOT; };
OBJ_6 /* Package.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; path = Package.swift; sourceTree = "<group>"; };
OBJ_9 /* AnyCodingKey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnyCodingKey.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
OBJ_49 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 0;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
OBJ_71 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 0;
files = (
OBJ_72 /* MessagePack.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
OBJ_11 /* Decoder */ = {
isa = PBXGroup;
children = (
OBJ_12 /* KeyedDecodingContainer.swift */,
OBJ_13 /* MessagePackDecoder.swift */,
OBJ_14 /* SingleValueDecodingContainer.swift */,
OBJ_15 /* UnkeyedDecodingContainer.swift */,
);
path = Decoder;
sourceTree = "<group>";
};
OBJ_16 /* Encoder */ = {
isa = PBXGroup;
children = (
OBJ_17 /* KeyedEncodingContainer.swift */,
OBJ_18 /* MessagePackEncoder.swift */,
OBJ_19 /* SingleValueEncodingContainer.swift */,
OBJ_20 /* UnkeyedEncodingContainer.swift */,
);
path = Encoder;
sourceTree = "<group>";
};
OBJ_22 /* Tests */ = {
isa = PBXGroup;
children = (
OBJ_23 /* MessagePackTests */,
);
name = Tests;
sourceTree = SOURCE_ROOT;
};
OBJ_23 /* MessagePackTests */ = {
isa = PBXGroup;
children = (
OBJ_24 /* Airport.swift */,
OBJ_25 /* MessagePackDecodingTests.swift */,
OBJ_26 /* MessagePackEncodingTests.swift */,
OBJ_27 /* MessagePackPerformanceTests.swift */,
OBJ_28 /* MessagePackRoundTripTests.swift */,
);
name = MessagePackTests;
path = Tests/MessagePackTests;
sourceTree = SOURCE_ROOT;
};
OBJ_30 /* Products */ = {
isa = PBXGroup;
children = (
"MessagePack::MessagePackTests::Product" /* MessagePackTests.xctest */,
"MessagePack::MessagePack::Product" /* MessagePack.framework */,
);
name = Products;
sourceTree = BUILT_PRODUCTS_DIR;
};
OBJ_5 /* */ = {
isa = PBXGroup;
children = (
OBJ_6 /* Package.swift */,
OBJ_7 /* Sources */,
OBJ_22 /* Tests */,
OBJ_29 /* MessagePack.xcworkspace */,
OBJ_30 /* Products */,
);
name = "";
sourceTree = "<group>";
};
OBJ_7 /* Sources */ = {
isa = PBXGroup;
children = (
OBJ_8 /* MessagePack */,
);
name = Sources;
sourceTree = SOURCE_ROOT;
};
OBJ_8 /* MessagePack */ = {
isa = PBXGroup;
children = (
OBJ_9 /* AnyCodingKey.swift */,
OBJ_10 /* Box.swift */,
OBJ_11 /* Decoder */,
OBJ_16 /* Encoder */,
OBJ_21 /* FixedWidthInteger+Bytes.swift */,
1BC312FE2992DE9C00177F2A /* DataSpec.swift */,
);
name = MessagePack;
path = Sources/MessagePack;
sourceTree = SOURCE_ROOT;
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
"MessagePack::MessagePack" /* MessagePack */ = {
isa = PBXNativeTarget;
buildConfigurationList = OBJ_34 /* Build configuration list for PBXNativeTarget "MessagePack" */;
buildPhases = (
OBJ_37 /* Sources */,
OBJ_49 /* Frameworks */,
);
buildRules = (
);
dependencies = (
);
name = MessagePack;
productName = MessagePack;
productReference = "MessagePack::MessagePack::Product" /* MessagePack.framework */;
productType = "com.apple.product-type.framework";
};
"MessagePack::MessagePackTests" /* MessagePackTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = OBJ_62 /* Build configuration list for PBXNativeTarget "MessagePackTests" */;
buildPhases = (
OBJ_65 /* Sources */,
OBJ_71 /* Frameworks */,
);
buildRules = (
);
dependencies = (
OBJ_73 /* PBXTargetDependency */,
);
name = MessagePackTests;
productName = MessagePackTests;
productReference = "MessagePack::MessagePackTests::Product" /* MessagePackTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
"MessagePack::SwiftPMPackageDescription" /* MessagePackPackageDescription */ = {
isa = PBXNativeTarget;
buildConfigurationList = OBJ_51 /* Build configuration list for PBXNativeTarget "MessagePackPackageDescription" */;
buildPhases = (
OBJ_54 /* Sources */,
);
buildRules = (
);
dependencies = (
);
name = MessagePackPackageDescription;
productName = MessagePackPackageDescription;
productType = "com.apple.product-type.framework";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
OBJ_1 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 9999;
};
buildConfigurationList = OBJ_2 /* Build configuration list for PBXProject "MessagePack" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
English,
en,
);
mainGroup = OBJ_5 /* */;
productRefGroup = OBJ_30 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
"MessagePack::MessagePack" /* MessagePack */,
"MessagePack::SwiftPMPackageDescription" /* MessagePackPackageDescription */,
"MessagePack::MessagePackPackageTests::ProductTarget" /* MessagePackPackageTests */,
"MessagePack::MessagePackTests" /* MessagePackTests */,
);
};
/* End PBXProject section */
/* Begin PBXSourcesBuildPhase section */
OBJ_37 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 0;
files = (
OBJ_38 /* AnyCodingKey.swift in Sources */,
OBJ_39 /* Box.swift in Sources */,
OBJ_40 /* KeyedDecodingContainer.swift in Sources */,
OBJ_41 /* MessagePackDecoder.swift in Sources */,
OBJ_42 /* SingleValueDecodingContainer.swift in Sources */,
OBJ_43 /* UnkeyedDecodingContainer.swift in Sources */,
OBJ_44 /* KeyedEncodingContainer.swift in Sources */,
OBJ_45 /* MessagePackEncoder.swift in Sources */,
OBJ_46 /* SingleValueEncodingContainer.swift in Sources */,
OBJ_47 /* UnkeyedEncodingContainer.swift in Sources */,
1BC312FF2992DE9C00177F2A /* DataSpec.swift in Sources */,
OBJ_48 /* FixedWidthInteger+Bytes.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
OBJ_54 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 0;
files = (
OBJ_55 /* Package.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
OBJ_65 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 0;
files = (
OBJ_66 /* Airport.swift in Sources */,
OBJ_67 /* MessagePackDecodingTests.swift in Sources */,
OBJ_68 /* MessagePackEncodingTests.swift in Sources */,
OBJ_69 /* MessagePackPerformanceTests.swift in Sources */,
OBJ_70 /* MessagePackRoundTripTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
OBJ_60 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = "MessagePack::MessagePackTests" /* MessagePackTests */;
targetProxy = 1BC312FD2989A1B200177F2A /* PBXContainerItemProxy */;
};
OBJ_73 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = "MessagePack::MessagePack" /* MessagePack */;
targetProxy = 1BC312FC2989A1AD00177F2A /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
OBJ_3 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_OBJC_ARC = YES;
COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_NS_ASSERTIONS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
MACOSX_DEPLOYMENT_TARGET = 10.10;
ONLY_ACTIVE_ARCH = YES;
OTHER_SWIFT_FLAGS = "-DXcode";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = macosx;
SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator appletvos appletvsimulator watchos watchsimulator";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "SWIFT_PACKAGE DEBUG";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
USE_HEADERMAP = NO;
};
name = Debug;
};
OBJ_35 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ENABLE_TESTABILITY = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PLATFORM_DIR)/Developer/Library/Frameworks",
);
HEADER_SEARCH_PATHS = "$(inherited)";
INFOPLIST_FILE = MessagePack.xcodeproj/MessagePack_Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) $(TOOLCHAIN_DIR)/usr/lib/swift/macosx";
OTHER_CFLAGS = "$(inherited)";
OTHER_LDFLAGS = "$(inherited)";
OTHER_SWIFT_FLAGS = "$(inherited)";
PRODUCT_BUNDLE_IDENTIFIER = MessagePack;
PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)";
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SKIP_INSTALL = YES;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)";
SWIFT_VERSION = 4.0;
TARGET_NAME = MessagePack;
};
name = Debug;
};
OBJ_36 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ENABLE_TESTABILITY = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PLATFORM_DIR)/Developer/Library/Frameworks",
);
HEADER_SEARCH_PATHS = "$(inherited)";
INFOPLIST_FILE = MessagePack.xcodeproj/MessagePack_Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) $(TOOLCHAIN_DIR)/usr/lib/swift/macosx";
OTHER_CFLAGS = "$(inherited)";
OTHER_LDFLAGS = "$(inherited)";
OTHER_SWIFT_FLAGS = "$(inherited)";
PRODUCT_BUNDLE_IDENTIFIER = MessagePack;
PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)";
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SKIP_INSTALL = YES;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)";
SWIFT_VERSION = 4.0;
TARGET_NAME = MessagePack;
};
name = Release;
};
OBJ_4 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_OBJC_ARC = YES;
COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DYLIB_INSTALL_NAME_BASE = "@rpath";
GCC_OPTIMIZATION_LEVEL = s;
MACOSX_DEPLOYMENT_TARGET = 10.10;
OTHER_SWIFT_FLAGS = "-DXcode";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = macosx;
SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator appletvos appletvsimulator watchos watchsimulator";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = SWIFT_PACKAGE;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
USE_HEADERMAP = NO;
};
name = Release;
};
OBJ_52 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
LD = /usr/bin/true;
OTHER_SWIFT_FLAGS = "-swift-version 4 -I $(TOOLCHAIN_DIR)/usr/lib/swift/pm/4 -target x86_64-apple-macosx10.10 -sdk /Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk";
SWIFT_VERSION = 4.0;
};
name = Debug;
};
OBJ_53 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
LD = /usr/bin/true;
OTHER_SWIFT_FLAGS = "-swift-version 4 -I $(TOOLCHAIN_DIR)/usr/lib/swift/pm/4 -target x86_64-apple-macosx10.10 -sdk /Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk";
SWIFT_VERSION = 4.0;
};
name = Release;
};
OBJ_58 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
};
name = Debug;
};
OBJ_59 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
};
name = Release;
};
OBJ_63 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
EMBEDDED_CONTENT_CONTAINS_SWIFT = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PLATFORM_DIR)/Developer/Library/Frameworks",
);
HEADER_SEARCH_PATHS = "$(inherited)";
INFOPLIST_FILE = MessagePack.xcodeproj/MessagePackTests_Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @loader_path/../Frameworks @loader_path/Frameworks";
OTHER_CFLAGS = "$(inherited)";
OTHER_LDFLAGS = "$(inherited)";
OTHER_SWIFT_FLAGS = "$(inherited)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)";
SWIFT_VERSION = 4.0;
TARGET_NAME = MessagePackTests;
};
name = Debug;
};
OBJ_64 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
EMBEDDED_CONTENT_CONTAINS_SWIFT = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PLATFORM_DIR)/Developer/Library/Frameworks",
);
HEADER_SEARCH_PATHS = "$(inherited)";
INFOPLIST_FILE = MessagePack.xcodeproj/MessagePackTests_Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @loader_path/../Frameworks @loader_path/Frameworks";
OTHER_CFLAGS = "$(inherited)";
OTHER_LDFLAGS = "$(inherited)";
OTHER_SWIFT_FLAGS = "$(inherited)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)";
SWIFT_VERSION = 4.0;
TARGET_NAME = MessagePackTests;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
OBJ_2 /* Build configuration list for PBXProject "MessagePack" */ = {
isa = XCConfigurationList;
buildConfigurations = (
OBJ_3 /* Debug */,
OBJ_4 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
OBJ_34 /* Build configuration list for PBXNativeTarget "MessagePack" */ = {
isa = XCConfigurationList;
buildConfigurations = (
OBJ_35 /* Debug */,
OBJ_36 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
OBJ_51 /* Build configuration list for PBXNativeTarget "MessagePackPackageDescription" */ = {
isa = XCConfigurationList;
buildConfigurations = (
OBJ_52 /* Debug */,
OBJ_53 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
OBJ_57 /* Build configuration list for PBXAggregateTarget "MessagePackPackageTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
OBJ_58 /* Debug */,
OBJ_59 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
OBJ_62 /* Build configuration list for PBXNativeTarget "MessagePackTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
OBJ_63 /* Debug */,
OBJ_64 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = OBJ_1 /* Project object */;
}

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded</key>
<false/>
</dict>
</plist>

View File

@@ -0,0 +1,99 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1010"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "MessagePack::MessagePack"
BuildableName = "MessagePack.framework"
BlueprintName = "MessagePack"
ReferencedContainer = "container:MessagePack.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "MessagePack::MessagePackTests"
BuildableName = "MessagePackTests.xctest"
BlueprintName = "MessagePackTests"
ReferencedContainer = "container:MessagePack.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "MessagePack::MessagePack"
BuildableName = "MessagePack.framework"
BlueprintName = "MessagePack"
ReferencedContainer = "container:MessagePack.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "MessagePack::MessagePack"
BuildableName = "MessagePack.framework"
BlueprintName = "MessagePack"
ReferencedContainer = "container:MessagePack.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "MessagePack::MessagePack"
BuildableName = "MessagePack.framework"
BlueprintName = "MessagePack"
ReferencedContainer = "container:MessagePack.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:MessagePack.playground">
</FileRef>
<FileRef
location = "group:MessagePack.xcodeproj">
</FileRef>
</Workspace>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded</key>
<false/>
</dict>
</plist>

View File

@@ -0,0 +1,28 @@
// swift-tools-version:4.0
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "MessagePack",
products: [
// Products define the executables and libraries produced by a package, and make them visible to other packages.
.library(
name: "MessagePack",
targets: ["MessagePack"]),
],
dependencies: [
// Dependencies declare other packages that this package depends on.
// .package(url: /* package url */, from: "1.0.0"),
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
// Targets can depend on other targets in this package, and on products in packages which this package depends on.
.target(
name: "MessagePack",
dependencies: []),
.testTarget(
name: "MessagePackTests",
dependencies: ["MessagePack"]),
]
)

87
lib/MessagePack/README.md Normal file
View File

@@ -0,0 +1,87 @@
# MessagePack
[![Build Status][build status badge]][build status]
A [MessagePack](https://msgpack.org/) encoder and decoder for `Codable` types.
This functionality is discussed in Chapter 7 of
[Flight School Guide to Swift Codable](https://flight.school/books/codable).
## Requirements
- Swift 4.2+
## Usage
### Encoding Messages
```swift
import MessagePack
let encoder = MessagePackEncoder()
let value = try! encoder.encode(["a": 1, "b": 2, "c": 3])
// [0x83, 0xA1, 0x62, 0x02, 0xA1, 0x61, 0x01, 0xA1, 0x63, 0x03]
```
### Decoding Messages
```swift
import MessagePack
let decoder = MessagePackDecoder()
let data = Data(bytes: [0xCB, 0x40, 0x09, 0x21, 0xF9, 0xF0, 0x1B, 0x86, 0x6E])
let value = try! decoder.decode(Double.self, from: data)
// 3.14159
```
## Installation
### Swift Package Manager
Add the MessagePack package to your target dependencies in `Package.swift`:
```swift
import PackageDescription
let package = Package(
name: "YourProject",
dependencies: [
.package(
url: "https://github.com/Flight-School/MessagePack",
from: "1.2.3"
),
]
)
```
Then run the `swift build` command to build your project.
### CocoaPods
You can install `MessagePack` via CocoaPods,
by adding the following line to your `Podfile`:
```ruby
pod 'MessagePack-FlightSchool', '~> 1.2.4'
```
Run the `pod install` command to download the library
and integrate it into your Xcode project.
> **Note**
> The module name for this library is "MessagePack" ---
> that is, to use it, you add `import MessagePack` to the top of your Swift code
> just as you would by any other installation method.
> The pod is called "MessagePack-FlightSchool"
> because there's an existing pod with the name "MessagePack".
## License
MIT
## Contact
Mattt ([@mattt](https://twitter.com/mattt))
[build status]: https://github.com/Flight-School/MessagePack/actions?query=workflow%3ACI
[build status badge]: https://github.com/Flight-School/MessagePack/workflows/CI/badge.svg

View File

@@ -0,0 +1,28 @@
struct AnyCodingKey: CodingKey, Equatable {
var stringValue: String
var intValue: Int?
init?(stringValue: String) {
self.stringValue = stringValue
self.intValue = nil
}
init?(intValue: Int) {
self.stringValue = "\(intValue)"
self.intValue = intValue
}
init<Key>(_ base: Key) where Key : CodingKey {
if let intValue = base.intValue {
self.init(intValue: intValue)!
} else {
self.init(stringValue: base.stringValue)!
}
}
}
extension AnyCodingKey: Hashable {
var hashValue: Int {
return self.intValue?.hashValue ?? self.stringValue.hashValue
}
}

View File

@@ -0,0 +1,44 @@
import Foundation
struct Box<Value> {
let value: Value
init(_ value: Value) {
self.value = value
}
}
extension Box: Encodable where Value: Encodable {
func encode(to encoder: Encoder) throws {
try self.value.encode(to: encoder)
}
}
extension Box: Decodable where Value: Decodable {
init(from decoder: Decoder) throws {
self.init(try Value(from: decoder))
}
}
extension Box where Value == Data {
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
self.init(try container.decode(Value.self))
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try container.encode(self.value)
}
}
extension Box where Value == Date {
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
self.init(try container.decode(Value.self))
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try container.encode(self.value)
}
}

View File

@@ -0,0 +1,60 @@
import Foundation
public struct DataSpec {
let name: String
let isObj: Bool
let isArray: Bool
let dataSpecBuilder: DataSpecBuilder?
init(_ name: String, _ isObj: Bool, _ isArray: Bool, _ dataSpecBuilder: DataSpecBuilder?) {
self.name = name
self.isObj = isObj
self.isArray = isArray
self.dataSpecBuilder = dataSpecBuilder
}
}
public class DataSpecBuilder : NSCopying {
var specs: [DataSpec] = []
var specsIterator: IndexingIterator<[DataSpec]>
init() {
specsIterator = IndexingIterator(_elements: [])
}
func append(_ name: String) -> DataSpecBuilder {
return append(DataSpec(name, false, false, nil))
}
func appendObj(_ name: String, _ dataSpecBuilder: DataSpecBuilder) -> DataSpecBuilder {
return append(DataSpec(name, true, false, dataSpecBuilder))
}
func appendArray(_ name: String) -> DataSpecBuilder {
return append(DataSpec(name, false, true, nil))
}
func appendArray(_ name: String, _ dataSpecBuilder: DataSpecBuilder) -> DataSpecBuilder {
return append(DataSpec(name, false, true, dataSpecBuilder))
}
func append(_ spec: DataSpec) -> DataSpecBuilder {
specs.append(spec)
return self
}
func build() -> DataSpecBuilder {
specsIterator = specs.makeIterator()
return self
}
func next() -> DataSpec {
return specsIterator.next()!
}
public func copy(with zone: NSZone? = nil) -> Any {
let b = DataSpecBuilder()
b.specs = specs
return b.build()
}
}

View File

@@ -0,0 +1,178 @@
import Foundation
extension _MessagePackDecoder {
final class KeyedContainer<Key> where Key: CodingKey {
lazy var nestedContainers: [String: MessagePackDecodingContainer] = {
guard let count = self.count else {
return [:]
}
var nestedContainers: [String: MessagePackDecodingContainer] = [:]
let unkeyedContainer = UnkeyedContainer(data: self.data.suffix(from: self.index), codingPath: self.codingPath, userInfo: self.userInfo)
if currentSpec != nil && currentSpec!.isObj {
unkeyedContainer.count = count
} else {
unkeyedContainer.count = count * 2
}
do {
var iterator = unkeyedContainer.nestedContainers.makeIterator()
for _ in 0..<count {
var key: String = ""
if currentSpec == nil || !currentSpec!.isObj {
guard let keyContainer = iterator.next() as? _MessagePackDecoder.SingleValueContainer else {
fatalError() // FIXME
}
key = try keyContainer.decode(String.self)
}
guard let container = iterator.next() else {
fatalError() // FIXME
}
if currentSpec != nil && currentSpec!.isObj {
key = container.currentSpec!.name
}
container.codingPath += [AnyCodingKey(stringValue: key)!]
nestedContainers[key] = container
}
} catch {
fatalError("\(error)") // FIXME
}
self.index = unkeyedContainer.index
return nestedContainers
}()
lazy var count: Int? = {
do {
let format = try self.readByte()
if currentSpec != nil && currentSpec!.isObj && 0x90...0x9f ~= format {
return Int(format & 0x0F)
}
switch format {
case 0x80...0x8f:
return Int(format & 0x0F)
case 0xde:
return Int(try read(UInt16.self))
case 0xdf:
return Int(try read(UInt32.self))
default:
return nil
}
} catch {
return nil
}
}()
var data: Data
var index: Data.Index
var codingPath: [CodingKey]
var userInfo: [CodingUserInfoKey: Any]
var currentSpec: DataSpec?
func nestedCodingPath(forKey key: CodingKey) -> [CodingKey] {
return self.codingPath + [key]
}
init(data: Data, codingPath: [CodingKey], userInfo: [CodingUserInfoKey : Any]) {
self.codingPath = codingPath
self.userInfo = userInfo
self.data = data
self.index = self.data.startIndex
}
func checkCanDecodeValue(forKey key: Key) throws {
guard self.contains(key) else {
let context = DecodingError.Context(codingPath: self.codingPath, debugDescription: "key not found: \(key)")
throw DecodingError.keyNotFound(key, context)
}
}
}
}
extension _MessagePackDecoder.KeyedContainer: KeyedDecodingContainerProtocol {
var allKeys: [Key] {
return self.nestedContainers.keys.map{ Key(stringValue: $0)! }
}
func contains(_ key: Key) -> Bool {
return self.nestedContainers.keys.contains(key.stringValue)
}
func decodeNil(forKey key: Key) throws -> Bool {
try checkCanDecodeValue(forKey: key)
let nestedContainer = self.nestedContainers[key.stringValue]
switch nestedContainer {
case let singleValueContainer as _MessagePackDecoder.SingleValueContainer:
return singleValueContainer.decodeNil()
case is _MessagePackDecoder.UnkeyedContainer,
is _MessagePackDecoder.KeyedContainer<AnyCodingKey>:
return false
default:
let context = DecodingError.Context(codingPath: self.codingPath, debugDescription: "cannot decode nil for key: \(key)")
throw DecodingError.typeMismatch(Any?.self, context)
}
}
func decode<T>(_ type: T.Type, forKey key: Key) throws -> T where T : Decodable {
try checkCanDecodeValue(forKey: key)
let container = self.nestedContainers[key.stringValue]!
let decoder = MessagePackDecoder()
if userInfo.keys.contains(MessagePackDecoder.dataSpecKey) {
decoder.userInfo[MessagePackDecoder.dataSpecKey] = container.currentSpec!.dataSpecBuilder?.copy() as? DataSpecBuilder
if container.currentSpec!.isArray {
decoder.userInfo[MessagePackDecoder.isArrayDataSpecKey] = true
}
}
let value = try decoder.decode(T.self, from: container.data)
return value
}
func nestedUnkeyedContainer(forKey key: Key) throws -> UnkeyedDecodingContainer {
try checkCanDecodeValue(forKey: key)
guard let unkeyedContainer = self.nestedContainers[key.stringValue] as? _MessagePackDecoder.UnkeyedContainer else {
throw DecodingError.dataCorruptedError(forKey: key, in: self, debugDescription: "cannot decode nested container for key: \(key)")
}
return unkeyedContainer
}
func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type, forKey key: Key) throws -> KeyedDecodingContainer<NestedKey> where NestedKey : CodingKey {
try checkCanDecodeValue(forKey: key)
guard let keyedContainer = self.nestedContainers[key.stringValue] as? _MessagePackDecoder.KeyedContainer<NestedKey> else {
throw DecodingError.dataCorruptedError(forKey: key, in: self, debugDescription: "cannot decode nested container for key: \(key)")
}
return KeyedDecodingContainer(keyedContainer)
}
func superDecoder() throws -> Decoder {
return _MessagePackDecoder(data: self.data)
}
func superDecoder(forKey key: Key) throws -> Decoder {
let decoder = _MessagePackDecoder(data: self.data)
decoder.codingPath = [key]
return decoder
}
}
extension _MessagePackDecoder.KeyedContainer: MessagePackDecodingContainer {}

View File

@@ -0,0 +1,168 @@
import Foundation
/**
An object that decodes instances of a data type from MessagePack objects.
*/
final public class MessagePackDecoder {
public init() {}
/**
A dictionary you use to customize the decoding process
by providing contextual information.
*/
public var userInfo: [CodingUserInfoKey : Any] = [:]
/**
Returns a value of the type you specify,
decoded from a MessagePack object.
- Parameters:
- type: The type of the value to decode
from the supplied MessagePack object.
- data: The MessagePack object to decode.
- Throws: `DecodingError.dataCorrupted(_:)`
if the data is not valid MessagePack.
*/
public func decode<T>(_ type: T.Type, from data: Data) throws -> T where T : Decodable {
let decoder = _MessagePackDecoder(data: data)
decoder.userInfo = self.userInfo
decoder.userInfo[MessagePackDecoder.nonMatchingFloatDecodingStrategyKey] = nonMatchingFloatDecodingStrategy
switch type {
case is Data.Type:
let box = try Box<Data>(from: decoder)
return box.value as! T
case is Date.Type:
let box = try Box<Date>(from: decoder)
return box.value as! T
default:
return try T(from: decoder)
}
}
/**
The strategy used by a decoder when it encounters format mismatches for floating point values.
*/
public var nonMatchingFloatDecodingStrategy: NonMatchingFloatDecodingStrategy = .strict
/**
The strategies for decoding floating point values when their format doesn't match.
*/
public enum NonMatchingFloatDecodingStrategy {
/// Throws a DecodingError.typeMismatch
case strict
/// Performs a cast
case cast
}
internal static var nonMatchingFloatDecodingStrategyKey: CodingUserInfoKey {
return CodingUserInfoKey(rawValue: "nonMatchingFloatDecodingStrategyKey")!
}
static var dataSpecKey : CodingUserInfoKey {
return CodingUserInfoKey(rawValue: "dataSpecKey")!
}
static var isArrayDataSpecKey : CodingUserInfoKey {
return CodingUserInfoKey(rawValue: "isArrayDataSpecKey")!
}
}
// MARK: - TopLevelDecoder
#if canImport(Combine)
import Combine
extension MessagePackDecoder: TopLevelDecoder {
public typealias Input = Data
}
#endif
// MARK: -
final class _MessagePackDecoder {
var codingPath: [CodingKey] = []
var userInfo: [CodingUserInfoKey : Any] = [:]
var container: MessagePackDecodingContainer?
fileprivate var data: Data
init(data: Data) {
self.data = data
}
}
extension _MessagePackDecoder: Decoder {
fileprivate func assertCanCreateContainer() {
precondition(self.container == nil)
}
func container<Key>(keyedBy type: Key.Type) -> KeyedDecodingContainer<Key> where Key : CodingKey {
assertCanCreateContainer()
let container = KeyedContainer<Key>(data: self.data, codingPath: self.codingPath, userInfo: self.userInfo)
if userInfo.keys.contains(MessagePackDecoder.dataSpecKey) {
container.currentSpec = DataSpec("", true, false, nil)
}
self.container = container
return KeyedDecodingContainer(container)
}
func unkeyedContainer() -> UnkeyedDecodingContainer {
assertCanCreateContainer()
let container = UnkeyedContainer(data: self.data, codingPath: self.codingPath, userInfo: self.userInfo)
self.container = container
return container
}
func singleValueContainer() -> SingleValueDecodingContainer {
assertCanCreateContainer()
let container = SingleValueContainer(data: self.data, codingPath: self.codingPath, userInfo: self.userInfo)
self.container = container
return container
}
}
protocol MessagePackDecodingContainer: class {
var codingPath: [CodingKey] { get set }
var userInfo: [CodingUserInfoKey : Any] { get }
var data: Data { get set }
var index: Data.Index { get set }
var currentSpec: DataSpec? { get set }
}
extension MessagePackDecodingContainer {
func readByte() throws -> UInt8 {
return try read(1).first!
}
func read(_ length: Int) throws -> Data {
let nextIndex = self.index.advanced(by: length)
guard nextIndex <= self.data.endIndex else {
let context = DecodingError.Context(codingPath: self.codingPath, debugDescription: "Unexpected end of data")
throw DecodingError.dataCorrupted(context)
}
defer { self.index = nextIndex }
return self.data.subdata(in: self.index..<nextIndex)
}
func read<T>(_ type: T.Type) throws -> T where T : FixedWidthInteger {
let stride = MemoryLayout<T>.stride
let bytes = [UInt8](try read(stride))
return T(bytes: bytes)
}
}

View File

@@ -0,0 +1,226 @@
import Foundation
#if os(Linux)
let NSEC_PER_SEC: UInt64 = 1000000000
#endif
extension _MessagePackDecoder {
final class SingleValueContainer {
var codingPath: [CodingKey]
var userInfo: [CodingUserInfoKey: Any]
var data: Data
var index: Data.Index
var currentSpec: DataSpec?
init(data: Data, codingPath: [CodingKey], userInfo: [CodingUserInfoKey : Any]) {
self.codingPath = codingPath
self.userInfo = userInfo
self.data = data
self.index = self.data.startIndex
}
func checkCanDecode<T>(_ type: T.Type, format: UInt8) throws {
guard self.index <= self.data.endIndex else {
throw DecodingError.dataCorruptedError(in: self, debugDescription: "Unexpected end of data")
}
guard self.data[self.index] == format else {
let context = DecodingError.Context(codingPath: self.codingPath, debugDescription: "Invalid format: \(format)")
throw DecodingError.typeMismatch(type, context)
}
}
var nonMatchingFloatDecodingStrategy: MessagePackDecoder.NonMatchingFloatDecodingStrategy {
return userInfo[MessagePackDecoder.nonMatchingFloatDecodingStrategyKey] as? MessagePackDecoder.NonMatchingFloatDecodingStrategy ?? .strict
}
}
}
extension _MessagePackDecoder.SingleValueContainer: SingleValueDecodingContainer {
func decodeNil() -> Bool {
let format = try? readByte()
return format == 0xc0
}
func decode(_ type: Bool.Type) throws -> Bool {
let format = try readByte()
switch format {
case 0xc2: return false
case 0xc3: return true
default:
let context = DecodingError.Context(codingPath: self.codingPath, debugDescription: "Invalid format: \(format)")
throw DecodingError.typeMismatch(Bool.self, context)
}
}
func decode(_ type: String.Type) throws -> String {
let length: Int
let format = try readByte()
switch format {
case 0xa0...0xbf:
length = Int(format - 0xa0)
case 0xd9:
length = Int(try read(UInt8.self))
case 0xda:
length = Int(try read(UInt16.self))
case 0xdb:
length = Int(try read(UInt32.self))
default:
throw DecodingError.dataCorruptedError(in: self, debugDescription: "Invalid format for String length: \(format)")
}
let data = try read(length)
guard let string = String(data: data, encoding: .utf8) else {
let context = DecodingError.Context(codingPath: self.codingPath, debugDescription: "Couldn't decode string with UTF-8 encoding")
throw DecodingError.dataCorrupted(context)
}
return string
}
func decode(_ type: Double.Type) throws -> Double {
let format = try readByte()
switch format {
case 0xca:
switch nonMatchingFloatDecodingStrategy {
case .strict:
break
case .cast:
let bitPattern = try read(UInt32.self)
return Double(Float(bitPattern: bitPattern))
}
case 0xcb:
let bitPattern = try read(UInt64.self)
return Double(bitPattern: bitPattern)
default:
break
}
let context = DecodingError.Context(codingPath: self.codingPath, debugDescription: "Invalid format: \(format)")
throw DecodingError.typeMismatch(Double.self, context)
}
func decode(_ type: Float.Type) throws -> Float {
let format = try readByte()
switch format {
case 0xca:
let bitPattern = try read(UInt32.self)
return Float(bitPattern: bitPattern)
case 0xcb:
switch nonMatchingFloatDecodingStrategy {
case .strict:
break
case .cast:
let bitPattern = try read(UInt64.self)
return Float(Double(bitPattern: bitPattern))
}
default:
break
}
let context = DecodingError.Context(codingPath: self.codingPath, debugDescription: "Invalid format: \(format)")
throw DecodingError.typeMismatch(Float.self, context)
}
func decode<T>(_ type: T.Type) throws -> T where T : BinaryInteger & Decodable {
let format = try readByte()
var t: T?
switch format {
case 0x00...0x7f:
t = T(format)
case 0xcc:
t = T(exactly: try read(UInt8.self))
case 0xcd:
t = T(exactly: try read(UInt16.self))
case 0xce:
t = T(exactly: try read(UInt32.self))
case 0xcf:
t = T(exactly: try read(UInt64.self))
case 0xd0:
t = T(exactly: try read(Int8.self))
case 0xd1:
t = T(exactly: try read(Int16.self))
case 0xd2:
t = T(exactly: try read(Int32.self))
case 0xd3:
t = T(exactly: try read(Int64.self))
case 0xe0...0xff:
t = T(exactly: Int8(bitPattern: format))
default:
t = nil
}
guard let value = t else {
let context = DecodingError.Context(codingPath: self.codingPath, debugDescription: "Invalid format: \(format)")
throw DecodingError.typeMismatch(T.self, context)
}
return value
}
func decode(_ type: Date.Type) throws -> Date {
let format = try readByte()
var seconds: TimeInterval
var nanoseconds: TimeInterval
switch format {
case 0xd6:
_ = try read(Int8.self) // -1
nanoseconds = 0
seconds = TimeInterval(try read(UInt32.self))
case 0xd7:
_ = try read(Int8.self) // -1
let bitPattern = try read(UInt64.self)
nanoseconds = TimeInterval(UInt32(bitPattern >> 34))
seconds = TimeInterval(UInt32(bitPattern & 0x03_FF_FF_FF_FF))
case 0xc7:
_ = try read(Int8.self) // 12
_ = try read(Int8.self) // -1
nanoseconds = TimeInterval(try read(UInt32.self))
seconds = TimeInterval(try read(Int64.self))
default:
let context = DecodingError.Context(codingPath: self.codingPath, debugDescription: "Invalid format: \(format)")
throw DecodingError.typeMismatch(Date.self, context)
}
let timeInterval = TimeInterval(seconds) + nanoseconds / Double(NSEC_PER_SEC)
return Date(timeIntervalSince1970: timeInterval)
}
func decode(_ type: Data.Type) throws -> Data {
let length: Int
let format = try readByte()
switch format {
case 0xc4:
length = Int(try read(UInt8.self))
case 0xc5:
length = Int(try read(UInt16.self))
case 0xc6:
length = Int(try read(UInt32.self))
default:
throw DecodingError.dataCorruptedError(in: self, debugDescription: "Invalid format for Data length: \(format)")
}
return self.data.subdata(in: self.index..<self.index.advanced(by: length))
}
func decode<T>(_ type: T.Type) throws -> T where T : Decodable {
switch type {
case is Data.Type:
return try decode(Data.self) as! T
case is Date.Type:
return try decode(Date.self) as! T
default:
let decoder = _MessagePackDecoder(data: self.data)
let value = try T(from: decoder)
if let nextIndex = decoder.container?.index {
self.index = nextIndex
}
return value
}
}
}
extension _MessagePackDecoder.SingleValueContainer: MessagePackDecodingContainer {}

View File

@@ -0,0 +1,235 @@
import Foundation
extension _MessagePackDecoder {
final class UnkeyedContainer {
var codingPath: [CodingKey]
var nestedCodingPath: [CodingKey] {
return self.codingPath + [AnyCodingKey(intValue: self.count ?? 0)!]
}
var userInfo: [CodingUserInfoKey: Any]
var data: Data
var index: Data.Index
var currentSpec: DataSpec?
lazy var count: Int? = {
do {
let format = try self.readByte()
switch format {
case 0x90...0x9f:
return Int(format & 0x0F)
case 0xdc:
return Int(try read(UInt16.self))
case 0xdd:
return Int(try read(UInt32.self))
default:
return nil
}
} catch {
return nil
}
}()
var currentIndex: Int = 0
lazy var nestedContainers: [MessagePackDecodingContainer] = {
guard let count = self.count else {
return []
}
var nestedContainers: [MessagePackDecodingContainer] = []
do {
for _ in 0..<count {
let container = try self.decodeContainer()
nestedContainers.append(container)
}
} catch {
fatalError("\(error)") // FIXME
}
self.currentIndex = 0
return nestedContainers
}()
init(data: Data, codingPath: [CodingKey], userInfo: [CodingUserInfoKey : Any]) {
self.codingPath = codingPath
self.userInfo = userInfo
self.data = data
self.index = self.data.startIndex
}
var isAtEnd: Bool {
guard let count = self.count else {
return true
}
return currentIndex >= count
}
func checkCanDecodeValue() throws {
guard !self.isAtEnd else {
throw DecodingError.dataCorruptedError(in: self, debugDescription: "Unexpected end of data")
}
}
}
}
extension _MessagePackDecoder.UnkeyedContainer: UnkeyedDecodingContainer {
func decodeNil() throws -> Bool {
try checkCanDecodeValue()
defer { self.currentIndex += 1 }
let nestedContainer = self.nestedContainers[self.currentIndex]
switch nestedContainer {
case let singleValueContainer as _MessagePackDecoder.SingleValueContainer:
return singleValueContainer.decodeNil()
case is _MessagePackDecoder.UnkeyedContainer,
is _MessagePackDecoder.KeyedContainer<AnyCodingKey>:
return false
default:
let context = DecodingError.Context(codingPath: self.codingPath, debugDescription: "cannot decode nil for index: \(self.currentIndex)")
throw DecodingError.typeMismatch(Any?.self, context)
}
}
func decode<T>(_ type: T.Type) throws -> T where T : Decodable {
try checkCanDecodeValue()
defer { self.currentIndex += 1 }
if userInfo.keys.contains(MessagePackDecoder.isArrayDataSpecKey) {
currentSpec = DataSpec("", false, true, (userInfo[MessagePackDecoder.dataSpecKey] as? DataSpecBuilder)?.copy() as? DataSpecBuilder)
}
let container = self.nestedContainers[self.currentIndex]
let decoder = MessagePackDecoder()
if userInfo.keys.contains(MessagePackDecoder.dataSpecKey) {
decoder.userInfo[MessagePackDecoder.dataSpecKey] = (userInfo[MessagePackDecoder.dataSpecKey] as? DataSpecBuilder)?.copy() as? DataSpecBuilder
}
let value = try decoder.decode(T.self, from: container.data)
return value
}
func nestedUnkeyedContainer() throws -> UnkeyedDecodingContainer {
try checkCanDecodeValue()
defer { self.currentIndex += 1 }
let container = self.nestedContainers[self.currentIndex] as! _MessagePackDecoder.UnkeyedContainer
return container
}
func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type) throws -> KeyedDecodingContainer<NestedKey> where NestedKey : CodingKey {
try checkCanDecodeValue()
defer { self.currentIndex += 1 }
let container = self.nestedContainers[self.currentIndex] as! _MessagePackDecoder.KeyedContainer<NestedKey>
return KeyedDecodingContainer(container)
}
func superDecoder() throws -> Decoder {
return _MessagePackDecoder(data: self.data)
}
}
extension _MessagePackDecoder.UnkeyedContainer {
func decodeContainer() throws -> MessagePackDecodingContainer {
try checkCanDecodeValue()
defer { self.currentIndex += 1 }
let startIndex = self.index
var currDataSpec: DataSpec? = nil
if currentSpec != nil && currentSpec!.isArray && currentSpec!.dataSpecBuilder != nil {
currDataSpec = DataSpec("", true, false, currentSpec!.dataSpecBuilder!.copy() as? DataSpecBuilder)
} else {
let dataSpec = self.userInfo[MessagePackDecoder.dataSpecKey] as? DataSpecBuilder
if let currDS = dataSpec?.next() {
currDataSpec = DataSpec(currDS.name, currDS.isObj, currDS.isArray, currDS.dataSpecBuilder?.copy() as? DataSpecBuilder)
}
}
let length: Int
let format = try self.readByte()
switch format {
case 0x00...0x7f,
0xc0, 0xc2, 0xc3,
0xe0...0xff:
length = 0
case 0xcc, 0xd0, 0xd4:
length = 1
case 0xcd, 0xd1, 0xd5:
length = 2
case 0xca, 0xce, 0xd2:
length = 4
case 0xcb, 0xcf, 0xd3:
length = 8
case 0xd6:
length = 5
case 0xd7:
length = 9
case 0xd8:
length = 16
case 0xa0...0xbf:
length = Int(format - 0xa0)
case 0xc4, 0xc7, 0xd9:
length = Int(try read(UInt8.self))
case 0xc5, 0xc8, 0xda:
length = Int(try read(UInt16.self))
case 0xc6, 0xc9, 0xdb:
length = Int(try read(UInt32.self))
case 0x80...0x8f, 0xde, 0xdf:
let container = _MessagePackDecoder.KeyedContainer<AnyCodingKey>(data: self.data.suffix(from: startIndex), codingPath: self.nestedCodingPath, userInfo: self.userInfo)
container.currentSpec = currDataSpec
_ = container.nestedContainers // FIXME
self.index = container.index
return container
case 0x90...0x9f, 0xdc, 0xdd:
if currDataSpec != nil && currDataSpec!.isObj {
var objUserInfo = self.userInfo
objUserInfo[MessagePackDecoder.dataSpecKey] = currDataSpec!.dataSpecBuilder!
let container = _MessagePackDecoder.KeyedContainer<AnyCodingKey>(data: self.data.suffix(from: startIndex), codingPath: self.nestedCodingPath, userInfo: objUserInfo)
container.currentSpec = currDataSpec
_ = container.nestedContainers // FIXME
self.index = container.index
return container
}
var arrUserInfo = self.userInfo
if currDataSpec != nil && currDataSpec!.isArray {
arrUserInfo[MessagePackDecoder.dataSpecKey] = currDataSpec!.dataSpecBuilder!
}
let container = _MessagePackDecoder.UnkeyedContainer(data: self.data.suffix(from: startIndex), codingPath: self.nestedCodingPath, userInfo: arrUserInfo)
container.currentSpec = currDataSpec
_ = container.nestedContainers // FIXME
self.index = container.index
return container
default:
throw DecodingError.dataCorruptedError(in: self, debugDescription: "Invalid format: \(format)")
}
let range: Range<Data.Index> = startIndex..<self.index.advanced(by: length)
self.index = range.upperBound
let container = _MessagePackDecoder.SingleValueContainer(data: self.data.subdata(in: range), codingPath: self.codingPath, userInfo: self.userInfo)
container.currentSpec = currDataSpec
return container
}
}
extension _MessagePackDecoder.UnkeyedContainer: MessagePackDecodingContainer {}

View File

@@ -0,0 +1,90 @@
import Foundation
extension _MessagePackEncoder {
final class KeyedContainer<Key> where Key: CodingKey {
private var storage: [AnyCodingKey: _MessagePackEncodingContainer] = [:]
var codingPath: [CodingKey]
var userInfo: [CodingUserInfoKey: Any]
func nestedCodingPath(forKey key: CodingKey) -> [CodingKey] {
return self.codingPath + [key]
}
init(codingPath: [CodingKey], userInfo: [CodingUserInfoKey : Any]) {
self.codingPath = codingPath
self.userInfo = userInfo
}
}
}
extension _MessagePackEncoder.KeyedContainer: KeyedEncodingContainerProtocol {
func encodeNil(forKey key: Key) throws {
var container = self.nestedSingleValueContainer(forKey: key)
try container.encodeNil()
}
func encode<T>(_ value: T, forKey key: Key) throws where T : Encodable {
var container = self.nestedSingleValueContainer(forKey: key)
try container.encode(value)
}
private func nestedSingleValueContainer(forKey key: Key) -> SingleValueEncodingContainer {
let container = _MessagePackEncoder.SingleValueContainer(codingPath: self.nestedCodingPath(forKey: key), userInfo: self.userInfo)
self.storage[AnyCodingKey(key)] = container
return container
}
func nestedUnkeyedContainer(forKey key: Key) -> UnkeyedEncodingContainer {
let container = _MessagePackEncoder.UnkeyedContainer(codingPath: self.nestedCodingPath(forKey: key), userInfo: self.userInfo)
self.storage[AnyCodingKey(key)] = container
return container
}
func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type, forKey key: Key) -> KeyedEncodingContainer<NestedKey> where NestedKey : CodingKey {
let container = _MessagePackEncoder.KeyedContainer<NestedKey>(codingPath: self.nestedCodingPath(forKey: key), userInfo: self.userInfo)
self.storage[AnyCodingKey(key)] = container
return KeyedEncodingContainer(container)
}
func superEncoder() -> Encoder {
fatalError("Unimplemented") // FIXME
}
func superEncoder(forKey key: Key) -> Encoder {
fatalError("Unimplemented") // FIXME
}
}
extension _MessagePackEncoder.KeyedContainer: _MessagePackEncodingContainer {
var data: Data {
var data = Data()
let length = storage.count
if let uint16 = UInt16(exactly: length) {
if length <= 15 {
data.append(0x80 + UInt8(length))
} else {
data.append(0xde)
data.append(contentsOf: uint16.bytes)
}
} else if let uint32 = UInt32(exactly: length) {
data.append(0xdf)
data.append(contentsOf: uint32.bytes)
} else {
fatalError()
}
for (key, container) in self.storage {
let keyContainer = _MessagePackEncoder.SingleValueContainer(codingPath: self.codingPath, userInfo: self.userInfo)
try! keyContainer.encode(key.stringValue)
data.append(keyContainer.data)
data.append(container.data)
}
return data
}
}

View File

@@ -0,0 +1,99 @@
import Foundation
/**
An object that encodes instances of a data type as MessagePack objects.
*/
final public class MessagePackEncoder {
public init() {}
/**
A dictionary you use to customize the encoding process
by providing contextual information.
*/
public var userInfo: [CodingUserInfoKey : Any] = [:]
/**
Returns a MessagePack-encoded representation of the value you supply.
- Parameters:
- value: The value to encode as MessagePack.
- Throws: `EncodingError.invalidValue(_:_:)`
if the value can't be encoded as a MessagePack object.
*/
public func encode<T>(_ value: T) throws -> Data where T : Encodable {
let encoder = _MessagePackEncoder()
encoder.userInfo = self.userInfo
switch value {
case let data as Data:
try Box<Data>(data).encode(to: encoder)
case let date as Date:
try Box<Date>(date).encode(to: encoder)
default:
try value.encode(to: encoder)
}
return encoder.data
}
}
// MARK: - TopLevelEncoder
#if canImport(Combine)
import Combine
extension MessagePackEncoder: TopLevelEncoder {
public typealias Input = Data
}
#endif
// MARK: -
protocol _MessagePackEncodingContainer {
var data: Data { get }
}
class _MessagePackEncoder {
var codingPath: [CodingKey] = []
var userInfo: [CodingUserInfoKey : Any] = [:]
fileprivate var container: _MessagePackEncodingContainer?
var data: Data {
return container?.data ?? Data()
}
}
extension _MessagePackEncoder: Encoder {
fileprivate func assertCanCreateContainer() {
precondition(self.container == nil)
}
func container<Key>(keyedBy type: Key.Type) -> KeyedEncodingContainer<Key> where Key : CodingKey {
assertCanCreateContainer()
let container = KeyedContainer<Key>(codingPath: self.codingPath, userInfo: self.userInfo)
self.container = container
return KeyedEncodingContainer(container)
}
func unkeyedContainer() -> UnkeyedEncodingContainer {
assertCanCreateContainer()
let container = UnkeyedContainer(codingPath: self.codingPath, userInfo: self.userInfo)
self.container = container
return container
}
func singleValueContainer() -> SingleValueEncodingContainer {
assertCanCreateContainer()
let container = SingleValueContainer(codingPath: self.codingPath, userInfo: self.userInfo)
self.container = container
return container
}
}

View File

@@ -0,0 +1,264 @@
import Foundation
extension _MessagePackEncoder {
final class SingleValueContainer {
private var storage: Data = Data()
fileprivate var canEncodeNewValue = true
fileprivate func checkCanEncode(value: Any?) throws {
guard self.canEncodeNewValue else {
let context = EncodingError.Context(codingPath: self.codingPath, debugDescription: "Attempt to encode value through single value container when previously value already encoded.")
throw EncodingError.invalidValue(value as Any, context)
}
}
var codingPath: [CodingKey]
var userInfo: [CodingUserInfoKey: Any]
init(codingPath: [CodingKey], userInfo: [CodingUserInfoKey : Any]) {
self.codingPath = codingPath
self.userInfo = userInfo
}
}
}
extension _MessagePackEncoder.SingleValueContainer: SingleValueEncodingContainer {
func encodeNil() throws {
try checkCanEncode(value: nil)
defer { self.canEncodeNewValue = false }
self.storage.append(0xc0)
}
func encode(_ value: Bool) throws {
try checkCanEncode(value: nil)
defer { self.canEncodeNewValue = false }
switch value {
case false:
self.storage.append(0xc2)
case true:
self.storage.append(0xc3)
}
}
func encode(_ value: String) throws {
try checkCanEncode(value: value)
defer { self.canEncodeNewValue = false }
guard let data = value.data(using: .utf8) else {
let context = EncodingError.Context(codingPath: self.codingPath, debugDescription: "Cannot encode string using UTF-8 encoding.")
throw EncodingError.invalidValue(value, context)
}
let length = data.count
if let uint8 = UInt8(exactly: length) {
if (uint8 <= 31) {
self.storage.append(0xa0 + uint8)
} else {
self.storage.append(0xd9)
self.storage.append(contentsOf: uint8.bytes)
}
} else if let uint16 = UInt16(exactly: length) {
self.storage.append(0xda)
self.storage.append(contentsOf: uint16.bytes)
} else if let uint32 = UInt32(exactly: length) {
self.storage.append(0xdb)
self.storage.append(contentsOf: uint32.bytes)
} else {
let context = EncodingError.Context(codingPath: self.codingPath, debugDescription: "Cannot encode string with length \(length).")
throw EncodingError.invalidValue(value, context)
}
self.storage.append(data)
}
func encode(_ value: Double) throws {
try checkCanEncode(value: value)
defer { self.canEncodeNewValue = false }
self.storage.append(0xcb)
self.storage.append(contentsOf: value.bitPattern.bytes)
}
func encode(_ value: Float) throws {
try checkCanEncode(value: value)
defer { self.canEncodeNewValue = false }
self.storage.append(0xca)
self.storage.append(contentsOf: value.bitPattern.bytes)
}
func encode<T>(_ value: T) throws where T : BinaryInteger & Encodable {
try checkCanEncode(value: value)
defer { self.canEncodeNewValue = false }
if value < 0 {
if let int8 = Int8(exactly: value) {
return try encode(int8)
} else if let int16 = Int16(exactly: value) {
return try encode(int16)
} else if let int32 = Int32(exactly: value) {
return try encode(int32)
} else if let int64 = Int64(exactly: value) {
return try encode(int64)
}
} else {
if let uint8 = UInt8(exactly: value) {
return try encode(uint8)
} else if let uint16 = UInt16(exactly: value) {
return try encode(uint16)
} else if let uint32 = UInt32(exactly: value) {
return try encode(uint32)
} else if let uint64 = UInt64(exactly: value) {
return try encode(uint64)
}
}
let context = EncodingError.Context(codingPath: self.codingPath, debugDescription: "Cannot encode integer \(value).")
throw EncodingError.invalidValue(value, context)
}
func encode(_ value: Int8) throws {
try checkCanEncode(value: value)
defer { self.canEncodeNewValue = false }
if (value >= 0 && value <= 127) {
self.storage.append(UInt8(value))
} else if (value < 0 && value >= -31) {
self.storage.append(0xe0 + (0x1f & UInt8(truncatingIfNeeded: value)))
} else {
self.storage.append(0xd0)
self.storage.append(contentsOf: value.bytes)
}
}
func encode(_ value: Int16) throws {
try checkCanEncode(value: value)
defer { self.canEncodeNewValue = false }
self.storage.append(0xd1)
self.storage.append(contentsOf: value.bytes)
}
func encode(_ value: Int32) throws {
try checkCanEncode(value: value)
defer { self.canEncodeNewValue = false }
self.storage.append(0xd2)
self.storage.append(contentsOf: value.bytes)
}
func encode(_ value: Int64) throws {
try checkCanEncode(value: value)
defer { self.canEncodeNewValue = false }
self.storage.append(0xd3)
self.storage.append(contentsOf: value.bytes)
}
func encode(_ value: UInt8) throws {
try checkCanEncode(value: value)
defer { self.canEncodeNewValue = false }
if (value <= 127) {
self.storage.append(value)
} else {
self.storage.append(0xcc)
self.storage.append(contentsOf: value.bytes)
}
}
func encode(_ value: UInt16) throws {
try checkCanEncode(value: value)
defer { self.canEncodeNewValue = false }
self.storage.append(0xcd)
self.storage.append(contentsOf: value.bytes)
}
func encode(_ value: UInt32) throws {
try checkCanEncode(value: value)
defer { self.canEncodeNewValue = false }
self.storage.append(0xce)
self.storage.append(contentsOf: value.bytes)
}
func encode(_ value: UInt64) throws {
try checkCanEncode(value: value)
defer { self.canEncodeNewValue = false }
self.storage.append(0xcf)
self.storage.append(contentsOf: value.bytes)
}
func encode(_ value: Date) throws {
try checkCanEncode(value: value)
defer { self.canEncodeNewValue = false }
let timeInterval = value.timeIntervalSince1970
let (integral, fractional) = modf(timeInterval)
let seconds = Int64(integral)
let nanoseconds = UInt32(fractional * Double(NSEC_PER_SEC))
if seconds < 0 || seconds > UInt32.max {
self.storage.append(0xc7)
self.storage.append(0x0C)
self.storage.append(0xFF)
self.storage.append(contentsOf: nanoseconds.bytes)
self.storage.append(contentsOf: seconds.bytes)
} else if nanoseconds > 0 {
self.storage.append(0xd7)
self.storage.append(0xFF)
self.storage.append(contentsOf: ((UInt64(nanoseconds) << 34) + UInt64(seconds)).bytes)
} else {
self.storage.append(0xd6)
self.storage.append(0xFF)
self.storage.append(contentsOf: UInt32(seconds).bytes)
}
}
func encode(_ value: Data) throws {
let length = value.count
if let uint8 = UInt8(exactly: length) {
self.storage.append(0xc4)
self.storage.append(uint8)
self.storage.append(value)
} else if let uint16 = UInt16(exactly: length) {
self.storage.append(0xc5)
self.storage.append(contentsOf: uint16.bytes)
self.storage.append(value)
} else if let uint32 = UInt32(exactly: length) {
self.storage.append(0xc6)
self.storage.append(contentsOf: uint32.bytes)
self.storage.append(value)
} else {
let context = EncodingError.Context(codingPath: self.codingPath, debugDescription: "Cannot encode data of length \(value.count).")
throw EncodingError.invalidValue(value, context)
}
}
func encode<T>(_ value: T) throws where T : Encodable {
try checkCanEncode(value: value)
defer { self.canEncodeNewValue = false }
switch value {
case let data as Data:
try self.encode(data)
case let date as Date:
try self.encode(date)
default:
let encoder = _MessagePackEncoder()
try value.encode(to: encoder)
self.storage.append(encoder.data)
}
}
}
extension _MessagePackEncoder.SingleValueContainer: _MessagePackEncodingContainer {
var data: Data {
return storage
}
}

View File

@@ -0,0 +1,88 @@
import Foundation
extension _MessagePackEncoder {
final class UnkeyedContainer {
private var storage: [_MessagePackEncodingContainer] = []
var count: Int {
return storage.count
}
var codingPath: [CodingKey]
var nestedCodingPath: [CodingKey] {
return self.codingPath + [AnyCodingKey(intValue: self.count)!]
}
var userInfo: [CodingUserInfoKey: Any]
init(codingPath: [CodingKey], userInfo: [CodingUserInfoKey : Any]) {
self.codingPath = codingPath
self.userInfo = userInfo
}
}
}
extension _MessagePackEncoder.UnkeyedContainer: UnkeyedEncodingContainer {
func encodeNil() throws {
var container = self.nestedSingleValueContainer()
try container.encodeNil()
}
func encode<T>(_ value: T) throws where T : Encodable {
var container = self.nestedSingleValueContainer()
try container.encode(value)
}
private func nestedSingleValueContainer() -> SingleValueEncodingContainer {
let container = _MessagePackEncoder.SingleValueContainer(codingPath: self.nestedCodingPath, userInfo: self.userInfo)
self.storage.append(container)
return container
}
func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type) -> KeyedEncodingContainer<NestedKey> where NestedKey : CodingKey {
let container = _MessagePackEncoder.KeyedContainer<NestedKey>(codingPath: self.nestedCodingPath, userInfo: self.userInfo)
self.storage.append(container)
return KeyedEncodingContainer(container)
}
func nestedUnkeyedContainer() -> UnkeyedEncodingContainer {
let container = _MessagePackEncoder.UnkeyedContainer(codingPath: self.nestedCodingPath, userInfo: self.userInfo)
self.storage.append(container)
return container
}
func superEncoder() -> Encoder {
fatalError("Unimplemented") // FIXME
}
}
extension _MessagePackEncoder.UnkeyedContainer: _MessagePackEncodingContainer {
var data: Data {
var data = Data()
let length = storage.count
if let uint16 = UInt16(exactly: length) {
if uint16 <= 15 {
data.append(UInt8(0x90 + uint16))
} else {
data.append(0xdc)
data.append(contentsOf: uint16.bytes)
}
} else if let uint32 = UInt32(exactly: length) {
data.append(0xdd)
data.append(contentsOf: uint32.bytes)
} else {
fatalError()
}
for container in storage {
data.append(container.data)
}
return data
}
}

View File

@@ -0,0 +1,20 @@
extension FixedWidthInteger {
init(bytes: [UInt8]) {
self = bytes.withUnsafeBufferPointer {
$0.baseAddress!.withMemoryRebound(to: Self.self, capacity: 1) {
$0.pointee
}
}.bigEndian
}
var bytes: [UInt8] {
let capacity = MemoryLayout<Self>.size
var mutableValue = self.bigEndian
return withUnsafePointer(to: &mutableValue) {
return $0.withMemoryRebound(to: UInt8.self, capacity: capacity) {
return Array(UnsafeBufferPointer(start: $0, count: capacity))
}
}
}
}

View File

@@ -0,0 +1,8 @@
import XCTest
@testable import MessagePackTests
XCTMain([
testCase(MessagePackDecodingTests.allTests),
testCase(MessagePackEncodingTests.allTests),
testCase(MessagePackRoundTripTests.allTests),
])

View File

@@ -0,0 +1,63 @@
struct Airport: Codable, Equatable {
let name: String
let iata: String
let icao: String
let coordinates: [Double]
struct Runway: Codable, Equatable {
enum Surface: String, Codable, Equatable {
case rigid, flexible, gravel, sealed, unpaved, other
}
let direction: String
let distance: Int
let surface: Surface
}
let runways: [Runway]
let instrumentApproachProcedures: [String]
static var example: Airport {
return Airport(
name: "Portland International Airport",
iata: "PDX",
icao: "KPDX",
coordinates: [-122.5975,
45.5886111111111],
runways: [
Airport.Runway(
direction: "3/21",
distance: 1829,
surface: .flexible
)
],
instrumentApproachProcedures: [
"HI-ILS OR LOC RWY 28",
"HI-ILS OR LOC/DME RWY 10",
"ILS OR LOC RWY 10L",
"ILS OR LOC RWY 10R",
"ILS OR LOC RWY 28L",
"ILS OR LOC RWY 28R",
"ILS RWY 10R (SA CAT I)",
"ILS RWY 10R (CAT II - III)",
"RNAV (RNP) Y RWY 28L",
"RNAV (RNP) Y RWY 28R",
"RNAV (RNP) Z RWY 10L",
"RNAV (RNP) Z RWY 10R",
"RNAV (RNP) Z RWY 28L",
"RNAV (RNP) Z RWY 28R",
"RNAV (GPS) X RWY 28L",
"RNAV (GPS) X RWY 28R",
"RNAV (GPS) Y RWY 10L",
"RNAV (GPS) Y RWY 10R",
"LOC/DME RWY 21",
"VOR-A",
"HI-TACAN RWY 10",
"TACAN RWY 28",
"COLUMBIA VISUAL RWY 10L/",
"MILL VISUAL RWY 28L/R"
]
)
}
}

View File

@@ -0,0 +1,301 @@
import XCTest
@testable import MessagePack
class MessagePackDecodingTests: XCTestCase {
var decoder: MessagePackDecoder!
override func setUp() {
self.decoder = MessagePackDecoder()
}
func assertTypeMismatch<T>(_ expression: @autoclosure () throws -> T,
_ message: @autoclosure () -> String = "",
file: StaticString = #file,
line: UInt = #line) -> Any.Type? {
var error: Error?
XCTAssertThrowsError(expression, message,
file: file, line: line) {
error = $0
}
guard case .typeMismatch(let type, _) = error as? DecodingError else {
XCTFail(file: file, line: line)
return nil
}
return type
}
func testDecodeNil() {
let data = Data(bytes: [0xC0])
let value = try! decoder.decode(Int?.self, from: data)
XCTAssertNil(value)
}
func testDecodeFalse() {
let data = Data(bytes: [0xc2])
let value = try! decoder.decode(Bool.self, from: data)
XCTAssertEqual(value, false)
}
func testDecodeTrue() {
let data = Data(bytes: [0xc3])
let value = try! decoder.decode(Bool.self, from: data)
XCTAssertEqual(value, true)
}
func testDecodeInt() {
let data = Data(bytes: [0x2A])
let value = try! decoder.decode(Int.self, from: data)
XCTAssertEqual(value, 42)
}
func testDecodeNegativeInt() {
let data = Data(bytes: [0xFF])
let value = try! decoder.decode(Int.self, from: data)
XCTAssertEqual(value, -1)
}
func testDecodeUInt() {
let data = Data(bytes: [0xCC, 0x80])
let value = try! decoder.decode(Int.self, from: data)
XCTAssertEqual(value, 128)
}
func testDecodeFloat() {
let data = Data(bytes: [0xCA, 0x40, 0x48, 0xF5, 0xC3])
let value = try! decoder.decode(Float.self, from: data)
XCTAssertEqual(value, 3.14)
}
func testDecodeFloatToDouble() {
let data = Data(bytes: [0xCA, 0x40, 0x48, 0xF5, 0xC3])
let type = assertTypeMismatch(try decoder.decode(Double.self, from: data))
XCTAssertTrue(type is Double.Type)
decoder.nonMatchingFloatDecodingStrategy = .cast
let value = try! decoder.decode(Double.self, from: data)
XCTAssertEqual(value, 3.14, accuracy: 1e-6)
}
func testDecodeDouble() {
let data = Data(bytes: [0xCB, 0x40, 0x09, 0x21, 0xF9, 0xF0, 0x1B, 0x86, 0x6E])
let value = try! decoder.decode(Double.self, from: data)
XCTAssertEqual(value, 3.14159)
}
func testDecodeDoubleToFloat() {
let data = Data(bytes: [0xCB, 0x40, 0x09, 0x21, 0xF9, 0xF0, 0x1B, 0x86, 0x6E])
let type = assertTypeMismatch(try decoder.decode(Float.self, from: data))
XCTAssertTrue(type is Float.Type)
decoder.nonMatchingFloatDecodingStrategy = .cast
let value = try! decoder.decode(Float.self, from: data)
XCTAssertEqual(value, 3.14159)
}
func testDecodeFixedArray() {
let data = Data(bytes: [0x93, 0x01, 0x02, 0x03])
let value = try! decoder.decode([Int].self, from: data)
XCTAssertEqual(value, [1, 2, 3])
}
func testDecodeVariableArray() {
let data = Data(bytes: [0xdc] + [0x00, 0x10] + Array(0x01...0x10))
let value = try! decoder.decode([Int].self, from: data)
XCTAssertEqual(value, Array(1...16))
}
func testDecodeFixedDictionary() {
let data = Data(bytes: [0x83, 0xA1, 0x62, 0x02, 0xA1, 0x61, 0x01, 0xA1, 0x63, 0x03])
let value = try! decoder.decode([String: Int].self, from: data)
XCTAssertEqual(value, ["a": 1, "b": 2, "c": 3])
}
func testDecodeData() {
let data = Data(bytes: [0xC4, 0x05, 0x68, 0x65, 0x6C, 0x6C, 0x6F])
let value = try! decoder.decode(Data.self, from: data)
XCTAssertEqual(value, "hello".data(using: .utf8))
}
func testDecodeDate() {
let data = Data(bytes: [0xD6, 0xFF, 0x00, 0x00, 0x00, 0x01])
let date = Date(timeIntervalSince1970: 1)
let value = try! decoder.decode(Date.self, from: data)
XCTAssertEqual(value, date)
}
func testDecodeDistantPast() {
let data = Data(bytes: [0xC7, 0x0C, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xF1, 0x88, 0x6B, 0x66, 0x00])
let date = Date.distantPast
let value = try! decoder.decode(Date.self, from: data)
XCTAssertEqual(value, date)
}
func testDecodeDistantFuture() {
let data = Data(bytes: [0xC7, 0x0C, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0xEC, 0x31, 0x88, 0x00])
let date = Date.distantFuture
let value = try! decoder.decode(Date.self, from: data)
XCTAssertEqual(value, date)
}
func testDecodeArrayWithDate() {
let data = Data(bytes: [0x91, 0xD6, 0xFF, 0x00, 0x00, 0x00, 0x01])
let date = Date(timeIntervalSince1970: 1)
let value = try! decoder.decode([Date].self, from: data)
XCTAssertEqual(value, [date])
}
func testDecodeDictionaryWithDate() {
let data = Data(bytes: [0x81, 0xA1, 0x31, 0xD6, 0xFF, 0x00, 0x00, 0x00, 0x01])
let date = Date(timeIntervalSince1970: 1)
let value = try! decoder.decode([String: Date].self, from: data)
XCTAssertEqual(value, ["1": date])
}
func testDecodeBv() {
let b64 = "lK50ZXN0aW5nIHN0cmluZyeSpnF3ZXF3ZagxMjNpY29uc5OU2SRlMTZkYTYwMi0zMjE1LTRiZDYtYjY5MC00Y2Q4NmEwZmU3NjSoQ2lwaGVyIDEBk61jaXBodXNlcm5hbWUxrWFkZmFmZHcyMzQxMzGSkblodHRwczovL3d3dy5nb29nbGUuY29tLmFykbVodHRwczovL3d3dy5hcHBsZS5jb22U2SRhNjExMWU2Ny1hMTMwLTRiM2ItODM5NS0xZjIzMDFjNjk3ZjeoQ2lwaGVyIDIBk6g0MzEzMjEzMatqbGpsbHl1bHVpecCU2SRiOGIwODM3MC0xNGU0LTQzZmUtYjBkOS04ZjJlMDlmODJkYzWoQ2lwaGVyIDMBk6twaW9waW9waXBpb6x6eGN6eHZ6eHZ4enaSkbdodHRwczovL3d3dy52aXNhLmNvbS5hcpG1aHR0cHM6Ly93d3cuZG9ja3MuY29t" // array mode with envData and ciphers
// let b64 = "hKFirnRlc3Rpbmcgc3RyaW5noWMnp2VudkRhdGGCpGJhc2WmcXdlcXdlpWljb25zqDEyM2ljb25zp2NpcGhlcnOThKJpZNkkMDA4YmE0NDctZjU0Mi00OWVjLWJjYTktMDMzZTQ2OTU0YTBipG5hbWWoQ2lwaGVyIDGkdHlwZQGlbG9naW6DqHVzZXJuYW1lrWNpcGh1c2VybmFtZTGkdG90cK1hZGZhZmR3MjM0MTMxpHVyaXOSgaN1cmm5aHR0cHM6Ly93d3cuZ29vZ2xlLmNvbS5hcoGjdXJptWh0dHBzOi8vd3d3LmFwcGxlLmNvbYSiaWTZJDQ1ZTBhODJiLTgyZGQtNDJiZi05ODhhLTAyYTkyNGM4Yzg5M6RuYW1lqENpcGhlciAypHR5cGUBpWxvZ2lug6h1c2VybmFtZag0MzEzMjEzMaR0b3Rwq2psamxseXVsdWl5pHVyaXPAhKJpZNkkZTBjZWU5NDEtZDI1Ni00MjdiLWJkNWUtNDMxMmMwN2U1NDI5pG5hbWWoQ2lwaGVyIDOkdHlwZQGlbG9naW6DqHVzZXJuYW1lq3Bpb3Bpb3BpcGlvpHRvdHCsenhjenh2enh2eHp2pHVyaXOSgaN1cmm3aHR0cHM6Ly93d3cudmlzYS5jb20uYXKBo3VyabVodHRwczovL3d3dy5kb2Nrcy5jb20=" // dict mode with envData and ciphers
do {
if let d = Data(base64Encoded: b64) {
let decoder = MessagePackDecoder()
decoder.userInfo[MessagePackDecoder.dataSpecKey] = DataSpecBuilder()
.append("b")
.append("c")
.appendObj("envData", DataSpecBuilder()
.append("base")
.append("icons")
.build())
.appendArray("ciphers", DataSpecBuilder()
.append("id")
.append("name")
.append("type")
.appendObj("login", DataSpecBuilder()
.append("username")
.append("totp")
.appendArray("uris", DataSpecBuilder()
.append("uri")
.build())
.build())
.build())
.build()
let codTest = try decoder.decode(CodableTest.self, from: d)
XCTAssertEqual(codTest.b, "testing string")
XCTAssertEqual(codTest.envData.base, "qweqwe")
XCTAssertEqual(codTest.envData.icons, "123icons")
XCTAssertTrue(codTest.ciphers!.count > 1)
} else {
XCTAssertEqual(1, 0)
}
} catch let error {
XCTFail("E: \(error)")
}
}
static var allTests = [
("testDecodeNil", testDecodeNil),
("testDecodeFalse", testDecodeFalse),
("testDecodeTrue", testDecodeTrue),
("testDecodeInt", testDecodeInt),
("testDecodeUInt", testDecodeUInt),
("testDecodeFloat", testDecodeFloat),
("testDecodeFloatToDouble", testDecodeFloatToDouble),
("testDecodeDouble", testDecodeDouble),
("testDecodeDoubleToFloat", testDecodeDoubleToFloat),
("testDecodeFixedArray", testDecodeFixedArray),
("testDecodeFixedDictionary", testDecodeFixedDictionary),
("testDecodeData", testDecodeData),
("testDecodeDistantPast", testDecodeDistantPast),
("testDecodeDistantFuture", testDecodeDistantFuture),
("testDecodeArrayWithDate", testDecodeArrayWithDate),
("testDecodeDictionaryWithDate", testDecodeDictionaryWithDate),
("testDecodeBv", testDecodeBv)
]
}
struct CodableTest : Codable {
enum CodingKeys: Int, CodingKey {
case b
case c
case envData
case ciphers
}
var b: String
var c: Int
var envData: EnvironmentUrlDataDto
var ciphers: [Cipher]?
func printt() {
print("B: \(b)")
print("C: \(c)")
print("ENVDATA")
envData.printt()
if let cs = ciphers {
print("CIPHERS")
for c in cs {
c.printt()
print("----------------------------")
}
}
print("###########################")
}
}
struct EnvironmentUrlDataDto : Codable {
var base: String?
var icons: String?
func printt() {
print("Base: \(base ?? "")")
print("Icons: \(icons ?? "")")
}
}
struct Cipher:Identifiable,Codable{
enum CodingKeys: Int, CodingKey {
case id
case name
case login
}
var id:String
var name:String?
var userId:String?
var login:Login
func printt() {
print("id: \(id)")
print("name: \(name ?? "")")
print("LOGIN")
login.printt()
}
}
struct Login:Codable{
var username:String?
var totp:String?
var uris:[LoginUri]?
func printt() {
print("username: \(username ?? "")")
print("totp: \(totp ?? "")")
print("URIS")
if let us = uris {
for u in us {
u.printt()
print("----------------------------")
}
}
}
}
struct LoginUri:Codable{
var uri:String?
func printt() {
print("Uri: \(uri ?? "")")
}
}

View File

@@ -0,0 +1,127 @@
import XCTest
@testable import MessagePack
class MessagePackEncodingTests: XCTestCase {
var encoder: MessagePackEncoder!
override func setUp() {
self.encoder = MessagePackEncoder()
}
func testEncodeNil() {
let value = try! encoder.encode(nil as Int?)
XCTAssertEqual(value, Data(bytes: [0xc0]))
}
func testEncodeFalse() {
let value = try! encoder.encode(false)
XCTAssertEqual(value, Data(bytes: [0xc2]))
}
func testEncodeTrue() {
let value = try! encoder.encode(true)
XCTAssertEqual(value, Data(bytes: [0xc3]))
}
func testEncodeInt() {
let value = try! encoder.encode(42 as Int)
XCTAssertEqual(value, Data(bytes: [0x2A]))
}
func testEncodeUInt() {
let value = try! encoder.encode(128 as UInt)
XCTAssertEqual(value, Data(bytes: [0xCC, 0x80]))
}
func testEncodeFloat() {
let value = try! encoder.encode(3.14 as Float)
XCTAssertEqual(value, Data(bytes: [0xCA, 0x40, 0x48, 0xF5, 0xC3]))
}
func testEncodeDouble() {
let value = try! encoder.encode(3.14159 as Double)
XCTAssertEqual(value, Data(bytes: [0xCB, 0x40, 0x09, 0x21, 0xF9, 0xF0, 0x1B, 0x86, 0x6E]))
}
func testEncodeString() {
let value = try! encoder.encode("hello")
XCTAssertEqual(value, Data(bytes: [0xA5, 0x68, 0x65, 0x6C, 0x6C, 0x6F]))
}
func testEncodeFixedArray() {
let value = try! encoder.encode([1, 2, 3])
XCTAssertEqual(value, Data(bytes: [0x93, 0x01, 0x02, 0x03]))
}
func testEncodeVariableArray() {
let value = try! encoder.encode(Array(1...16))
XCTAssertEqual(value, Data(bytes: [0xdc] + [0x00, 0x10] + Array(0x01...0x10)))
}
func testEncodeFixedDictionary() {
let value = try! encoder.encode(["a": 1])
XCTAssertEqual(value, Data(bytes: [0x81, 0xA1, 0x61, 0x01]))
}
func testEncodeVariableDictionary() {
let letters = "abcdefghijklmnopqrstuvwxyz".unicodeScalars
let dictionary = Dictionary(uniqueKeysWithValues: zip(letters.map { String($0) }, 1...26))
let value = try! encoder.encode(dictionary)
XCTAssertEqual(value.count, 81)
XCTAssert(value.starts(with: [0xde] + [0x00, 0x1A]))
}
func testEncodeData() {
let data = "hello".data(using: .utf8)
let value = try! encoder.encode(data)
XCTAssertEqual(value, Data(bytes: [0xC4, 0x05, 0x68, 0x65, 0x6C, 0x6C, 0x6F]))
}
func testEncodeDate() {
let date = Date(timeIntervalSince1970: 1)
let value = try! encoder.encode(date)
XCTAssertEqual(value, Data(bytes: [0xD6, 0xFF, 0x00, 0x00, 0x00, 0x01]))
}
func testEncodeDistantPast() {
let date = Date.distantPast
let value = try! encoder.encode(date)
XCTAssertEqual(value, Data(bytes: [0xC7, 0x0C, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xF1, 0x88, 0x6B, 0x66, 0x00]))
}
func testEncodeDistantFuture() {
let date = Date.distantFuture
let value = try! encoder.encode(date)
XCTAssertEqual(value, Data(bytes: [0xC7, 0x0C, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0xEC, 0x31, 0x88, 0x00]))
}
func testEncodeArrayWithDate() {
let date = Date(timeIntervalSince1970: 1)
let value = try! encoder.encode([date])
XCTAssertEqual(value, Data(bytes: [0x91, 0xD6, 0xFF, 0x00, 0x00, 0x00, 0x01]))
}
func testEncodeDictionaryWithDate() {
let date = Date(timeIntervalSince1970: 1)
let value = try! encoder.encode(["1": date])
XCTAssertEqual(value, Data(bytes: [0x81, 0xA1, 0x31, 0xD6, 0xFF, 0x00, 0x00, 0x00, 0x01]))
}
static var allTests = [
("testEncodeFalse", testEncodeFalse),
("testEncodeTrue", testEncodeTrue),
("testEncodeInt", testEncodeInt),
("testEncodeUInt", testEncodeUInt),
("testEncodeFloat", testEncodeFloat),
("testEncodeDouble", testEncodeDouble),
("testEncodeFixedArray", testEncodeFixedArray),
("testEncodeVariableArray", testEncodeVariableArray),
("testEncodeFixedDictionary", testEncodeFixedDictionary),
("testEncodeVariableDictionary", testEncodeVariableDictionary),
("testEncodeDate", testEncodeDate),
("testEncodeDistantPast", testEncodeDistantPast),
("testEncodeDistantFuture", testEncodeDistantFuture),
("testEncodeArrayWithDate", testEncodeArrayWithDate),
("testEncodeDictionaryWithDate", testEncodeDictionaryWithDate)
]
}

View File

@@ -0,0 +1,23 @@
import XCTest
@testable import MessagePack
class MessagePackPerformanceTests: XCTestCase {
var encoder: MessagePackEncoder!
var decoder: MessagePackDecoder!
override func setUp() {
self.encoder = MessagePackEncoder()
self.decoder = MessagePackDecoder()
}
func testPerformance() {
let count = 100
let values = [Airport](repeating: .example, count: count)
self.measure {
let encoded = try! encoder.encode(values)
let decoded = try! decoder.decode([Airport].self, from: encoded)
XCTAssertEqual(decoded.count, count)
}
}
}

View File

@@ -0,0 +1,106 @@
import XCTest
@testable import MessagePack
class MessagePackRoundTripTests: XCTestCase {
var encoder: MessagePackEncoder!
var decoder: MessagePackDecoder!
override func setUp() {
self.encoder = MessagePackEncoder()
self.decoder = MessagePackDecoder()
}
func testRoundTripAirport() {
let value = Airport.example
let encoded = try! encoder.encode(value)
let decoded = try! decoder.decode(Airport.self, from: encoded)
XCTAssertEqual(value.name, decoded.name)
XCTAssertEqual(value.iata, decoded.iata)
XCTAssertEqual(value.icao, decoded.icao)
XCTAssertEqual(value.coordinates[0], decoded.coordinates[0], accuracy: 0.01)
XCTAssertEqual(value.coordinates[1], decoded.coordinates[1], accuracy: 0.01)
XCTAssertEqual(value.runways[0].direction, decoded.runways[0].direction)
XCTAssertEqual(value.runways[0].distance, decoded.runways[0].distance)
XCTAssertEqual(value.runways[0].surface, decoded.runways[0].surface)
}
func testRoundTripParachutePack() {
struct Parachute: Codable, Equatable {
enum Canopy: String, Codable, Equatable {
case round, cruciform, rogalloWing, annular, ramAir
}
let canpoy: Canopy
let surfaceArea: Double
}
struct ParachutePack: Codable, Equatable {
let main: Parachute?
let reserve: Parachute?
}
let value = ParachutePack(main: Parachute(canpoy: .ramAir, surfaceArea: 200), reserve: nil)
let encoded = try! encoder.encode(value)
let decoded = try! decoder.decode(ParachutePack.self, from: encoded)
XCTAssertEqual(value, decoded)
}
func testRoundTripArray() {
let count: UInt8 = 100
var bytes: [UInt8] = [0xdc, 0x00, count]
var encoded: [Int] = []
for n in 1...count {
bytes.append(n)
encoded.append(Int(n))
}
let data = Data(bytes: bytes)
let decoded = try! decoder.decode([Int].self, from: data)
XCTAssertEqual(encoded, decoded)
}
func testRoundTripDictionary() {
let (a, z): (UInt8, UInt8) = (0x61, 0x7a)
var bytes: [UInt8] = [0xde, 0x00, 0x1A]
var encoded: [String: Int] = [:]
for n in a...z {
bytes.append(contentsOf: [0xA1, n, n])
encoded[String(Unicode.Scalar(n))] = Int(n)
}
let data = Data(bytes: bytes)
let decoded = try! decoder.decode([String: Int].self, from: data)
XCTAssertEqual(encoded, decoded)
}
func testRoundTripDate() {
var bytes: [UInt8] = [0xD6, 0xFF]
let dateComponents = DateComponents(year: 2018, month: 4, day: 20)
let encoded = Calendar.current.date(from: dateComponents)!
let secondsSince1970 = UInt32(encoded.timeIntervalSince1970)
bytes.append(contentsOf: secondsSince1970.bytes)
let data = Data(bytes: bytes)
let decoded = try! decoder.decode(Date.self, from: data)
XCTAssertEqual(encoded, decoded)
}
func testRoundTripDateWithNanoseconds() {
let encoded = Date()
let data = try! self.encoder.encode(encoded)
let decoded = try! self.decoder.decode(Date.self, from: data)
XCTAssertEqual(encoded.timeIntervalSinceReferenceDate, decoded.timeIntervalSinceReferenceDate, accuracy: 0.0001)
}
static var allTests = [
("testRoundTripAirport", testRoundTripAirport),
("testRoundTripArray", testRoundTripArray),
("testRoundTripDictionary", testRoundTripDictionary),
("testRoundTripDate", testRoundTripDate),
("testRoundTripDateWithNanoseconds", testRoundTripDateWithNanoseconds)
]
}

169
package-lock.json generated
View File

@@ -8,7 +8,7 @@
"name": "bitwarden-mobile", "name": "bitwarden-mobile",
"version": "0.0.0", "version": "0.0.0",
"devDependencies": { "devDependencies": {
"gh-pages": "3.2.3" "gh-pages": "^6.1.1"
} }
}, },
"node_modules/array-union": { "node_modules/array-union": {
@@ -33,13 +33,11 @@
} }
}, },
"node_modules/async": { "node_modules/async": {
"version": "2.6.3", "version": "3.2.5",
"resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz",
"integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==",
"dev": true, "dev": true,
"dependencies": { "license": "MIT"
"lodash": "^4.17.14"
}
}, },
"node_modules/balanced-match": { "node_modules/balanced-match": {
"version": "1.0.2", "version": "1.0.2",
@@ -58,10 +56,14 @@
} }
}, },
"node_modules/commander": { "node_modules/commander": {
"version": "2.20.3", "version": "11.1.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==",
"dev": true "dev": true,
"license": "MIT",
"engines": {
"node": ">=16"
}
}, },
"node_modules/commondir": { "node_modules/commondir": {
"version": "1.0.1", "version": "1.0.1",
@@ -76,10 +78,11 @@
"dev": true "dev": true
}, },
"node_modules/email-addresses": { "node_modules/email-addresses": {
"version": "3.1.0", "version": "5.0.0",
"resolved": "https://registry.npmjs.org/email-addresses/-/email-addresses-3.1.0.tgz", "resolved": "https://registry.npmjs.org/email-addresses/-/email-addresses-5.0.0.tgz",
"integrity": "sha512-k0/r7GrWVL32kZlGwfPNgB2Y/mMXVTq/decgLczm/j34whdaspNrZO8CnXPf1laaHxI6ptUlsnAxN+UAPw+fzg==", "integrity": "sha512-4OIPYlA6JXqtVn8zpHpGiI7vE6EQOAg16aGnDMIAlZVinnoZ8208tW1hAbjWydgN/4PLTT9q+O1K6AH/vALJGw==",
"dev": true "dev": true,
"license": "MIT"
}, },
"node_modules/escape-string-regexp": { "node_modules/escape-string-regexp": {
"version": "1.0.5", "version": "1.0.5",
@@ -147,17 +150,18 @@
} }
}, },
"node_modules/fs-extra": { "node_modules/fs-extra": {
"version": "8.1.0", "version": "11.2.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz",
"integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"graceful-fs": "^4.2.0", "graceful-fs": "^4.2.0",
"jsonfile": "^4.0.0", "jsonfile": "^6.0.1",
"universalify": "^0.1.0" "universalify": "^2.0.0"
}, },
"engines": { "engines": {
"node": ">=6 <7 || >=8" "node": ">=14.14"
} }
}, },
"node_modules/fs.realpath": { "node_modules/fs.realpath": {
@@ -167,17 +171,18 @@
"dev": true "dev": true
}, },
"node_modules/gh-pages": { "node_modules/gh-pages": {
"version": "3.2.3", "version": "6.1.1",
"resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-3.2.3.tgz", "resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-6.1.1.tgz",
"integrity": "sha512-jA1PbapQ1jqzacECfjUaO9gV8uBgU6XNMV0oXLtfCX3haGLe5Atq8BxlrADhbD6/UdG9j6tZLWAkAybndOXTJg==", "integrity": "sha512-upnohfjBwN5hBP9w2dPE7HO5JJTHzSGMV1JrLrHvNuqmjoYHg6TBrCcnEoorjG/e0ejbuvnwyKMdTyM40PEByw==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"async": "^2.6.1", "async": "^3.2.4",
"commander": "^2.18.0", "commander": "^11.0.0",
"email-addresses": "^3.0.1", "email-addresses": "^5.0.0",
"filenamify": "^4.3.0", "filenamify": "^4.3.0",
"find-cache-dir": "^3.3.1", "find-cache-dir": "^3.3.1",
"fs-extra": "^8.1.0", "fs-extra": "^11.1.1",
"globby": "^6.1.0" "globby": "^6.1.0"
}, },
"bin": { "bin": {
@@ -225,10 +230,11 @@
} }
}, },
"node_modules/graceful-fs": { "node_modules/graceful-fs": {
"version": "4.2.8", "version": "4.2.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
"integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
"dev": true "dev": true,
"license": "ISC"
}, },
"node_modules/inflight": { "node_modules/inflight": {
"version": "1.0.6", "version": "1.0.6",
@@ -247,10 +253,14 @@
"dev": true "dev": true
}, },
"node_modules/jsonfile": { "node_modules/jsonfile": {
"version": "4.0.0", "version": "6.1.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
"integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": {
"universalify": "^2.0.0"
},
"optionalDependencies": { "optionalDependencies": {
"graceful-fs": "^4.1.6" "graceful-fs": "^4.1.6"
} }
@@ -267,12 +277,6 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"dev": true
},
"node_modules/make-dir": { "node_modules/make-dir": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
@@ -448,12 +452,13 @@
} }
}, },
"node_modules/universalify": { "node_modules/universalify": {
"version": "0.1.2", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
"integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
"dev": true, "dev": true,
"license": "MIT",
"engines": { "engines": {
"node": ">= 4.0.0" "node": ">= 10.0.0"
} }
}, },
"node_modules/wrappy": { "node_modules/wrappy": {
@@ -480,13 +485,10 @@
"dev": true "dev": true
}, },
"async": { "async": {
"version": "2.6.3", "version": "3.2.5",
"resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz",
"integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==",
"dev": true, "dev": true
"requires": {
"lodash": "^4.17.14"
}
}, },
"balanced-match": { "balanced-match": {
"version": "1.0.2", "version": "1.0.2",
@@ -505,9 +507,9 @@
} }
}, },
"commander": { "commander": {
"version": "2.20.3", "version": "11.1.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==",
"dev": true "dev": true
}, },
"commondir": { "commondir": {
@@ -523,9 +525,9 @@
"dev": true "dev": true
}, },
"email-addresses": { "email-addresses": {
"version": "3.1.0", "version": "5.0.0",
"resolved": "https://registry.npmjs.org/email-addresses/-/email-addresses-3.1.0.tgz", "resolved": "https://registry.npmjs.org/email-addresses/-/email-addresses-5.0.0.tgz",
"integrity": "sha512-k0/r7GrWVL32kZlGwfPNgB2Y/mMXVTq/decgLczm/j34whdaspNrZO8CnXPf1laaHxI6ptUlsnAxN+UAPw+fzg==", "integrity": "sha512-4OIPYlA6JXqtVn8zpHpGiI7vE6EQOAg16aGnDMIAlZVinnoZ8208tW1hAbjWydgN/4PLTT9q+O1K6AH/vALJGw==",
"dev": true "dev": true
}, },
"escape-string-regexp": { "escape-string-regexp": {
@@ -573,14 +575,14 @@
} }
}, },
"fs-extra": { "fs-extra": {
"version": "8.1.0", "version": "11.2.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz",
"integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==",
"dev": true, "dev": true,
"requires": { "requires": {
"graceful-fs": "^4.2.0", "graceful-fs": "^4.2.0",
"jsonfile": "^4.0.0", "jsonfile": "^6.0.1",
"universalify": "^0.1.0" "universalify": "^2.0.0"
} }
}, },
"fs.realpath": { "fs.realpath": {
@@ -590,17 +592,17 @@
"dev": true "dev": true
}, },
"gh-pages": { "gh-pages": {
"version": "3.2.3", "version": "6.1.1",
"resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-3.2.3.tgz", "resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-6.1.1.tgz",
"integrity": "sha512-jA1PbapQ1jqzacECfjUaO9gV8uBgU6XNMV0oXLtfCX3haGLe5Atq8BxlrADhbD6/UdG9j6tZLWAkAybndOXTJg==", "integrity": "sha512-upnohfjBwN5hBP9w2dPE7HO5JJTHzSGMV1JrLrHvNuqmjoYHg6TBrCcnEoorjG/e0ejbuvnwyKMdTyM40PEByw==",
"dev": true, "dev": true,
"requires": { "requires": {
"async": "^2.6.1", "async": "^3.2.4",
"commander": "^2.18.0", "commander": "^11.0.0",
"email-addresses": "^3.0.1", "email-addresses": "^5.0.0",
"filenamify": "^4.3.0", "filenamify": "^4.3.0",
"find-cache-dir": "^3.3.1", "find-cache-dir": "^3.3.1",
"fs-extra": "^8.1.0", "fs-extra": "^11.1.1",
"globby": "^6.1.0" "globby": "^6.1.0"
} }
}, },
@@ -632,9 +634,9 @@
} }
}, },
"graceful-fs": { "graceful-fs": {
"version": "4.2.8", "version": "4.2.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
"integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
"dev": true "dev": true
}, },
"inflight": { "inflight": {
@@ -654,12 +656,13 @@
"dev": true "dev": true
}, },
"jsonfile": { "jsonfile": {
"version": "4.0.0", "version": "6.1.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
"integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"graceful-fs": "^4.1.6" "graceful-fs": "^4.1.6",
"universalify": "^2.0.0"
} }
}, },
"locate-path": { "locate-path": {
@@ -671,12 +674,6 @@
"p-locate": "^4.1.0" "p-locate": "^4.1.0"
} }
}, },
"lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"dev": true
},
"make-dir": { "make-dir": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
@@ -801,9 +798,9 @@
} }
}, },
"universalify": { "universalify": {
"version": "0.1.2", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
"integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
"dev": true "dev": true
}, },
"wrappy": { "wrappy": {

View File

@@ -6,6 +6,6 @@
"clean:l10n": "git push origin --delete l10n_master" "clean:l10n": "git push origin --delete l10n_master"
}, },
"devDependencies": { "devDependencies": {
"gh-pages": "3.2.3" "gh-pages": "^6.1.1"
} }
} }

View File

@@ -44,7 +44,7 @@
<AndroidEnableMultiDex>True</AndroidEnableMultiDex> <AndroidEnableMultiDex>True</AndroidEnableMultiDex>
<UseInterpreter>False</UseInterpreter> <UseInterpreter>False</UseInterpreter>
<DebugSymbols>False</DebugSymbols> <DebugSymbols>False</DebugSymbols>
<RunAOTCompilation>False</RunAOTCompilation> <RunAOTCompilation>True</RunAOTCompilation>
<AndroidSupportedAbis>armeabi-v7a;x86;x86_64;arm64-v8a</AndroidSupportedAbis> <AndroidSupportedAbis>armeabi-v7a;x86;x86_64;arm64-v8a</AndroidSupportedAbis>
<JavaMaximumHeapSize>1G</JavaMaximumHeapSize> <JavaMaximumHeapSize>1G</JavaMaximumHeapSize>
<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk> <EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>
@@ -99,6 +99,7 @@
<PackageReference Include="Plugin.Fingerprint" Version="3.0.0-beta.1" /> <PackageReference Include="Plugin.Fingerprint" Version="3.0.0-beta.1" />
<PackageReference Include="SkiaSharp.Views.Maui.Controls" Version="2.88.4-preview.84" /> <PackageReference Include="SkiaSharp.Views.Maui.Controls" Version="2.88.4-preview.84" />
<PackageReference Include="SkiaSharp.Views.Maui.Controls.Compatibility" Version="2.88.4-preview.84" /> <PackageReference Include="SkiaSharp.Views.Maui.Controls.Compatibility" Version="2.88.4-preview.84" />
<PackageReference Include="FFImageLoadingCompat.Maui" Version="0.1.1" />
<PackageReference Include="AsyncAwaitBestPractices.MVVM" Version="6.0.6" /> <PackageReference Include="AsyncAwaitBestPractices.MVVM" Version="6.0.6" />
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.1" /> <PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.1" />
<PackageReference Include="PCLCrypto" Version="2.1.40-alpha" /> <PackageReference Include="PCLCrypto" Version="2.1.40-alpha" />

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:versionCode="1" android:versionName="2024.4.2" android:installLocation="internalOnly" package="com.x8bit.bitwarden"> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:versionCode="1" android:versionName="2024.10.111" android:installLocation="internalOnly" package="com.x8bit.bitwarden">
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="34" /> <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="34" />
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.NFC" /> <uses-permission android:name="android.permission.NFC" />

View File

@@ -11,7 +11,7 @@
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
<string>com.8bit.bitwarden</string> <string>com.8bit.bitwarden</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>2024.4.2</string> <string>2024.10.111</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>1</string> <string>1</string>
<key>CFBundleIconName</key> <key>CFBundleIconName</key>

View File

@@ -41,7 +41,6 @@ namespace Bit.Core.Abstractions
Task<CipherResponse> PutShareCipherAsync(string id, CipherShareRequest request); Task<CipherResponse> PutShareCipherAsync(string id, CipherShareRequest request);
Task PutDeleteCipherAsync(string id); Task PutDeleteCipherAsync(string id);
Task<CipherResponse> PutRestoreCipherAsync(string id); Task<CipherResponse> PutRestoreCipherAsync(string id);
Task<bool> HasUnassignedCiphersAsync();
Task RefreshIdentityTokenAsync(); Task RefreshIdentityTokenAsync();
Task<SsoPrevalidateResponse> PreValidateSsoAsync(string identifier); Task<SsoPrevalidateResponse> PreValidateSsoAsync(string identifier);
Task<TResponse> SendAsync<TRequest, TResponse>(HttpMethod method, string path, Task<TResponse> SendAsync<TRequest, TResponse>(HttpMethod method, string path,

View File

@@ -36,6 +36,5 @@ namespace Bit.Core.Abstractions
Task RestoreWithServerAsync(string id); Task RestoreWithServerAsync(string id);
Task<string> CreateNewLoginForPasskeyAsync(Fido2ConfirmNewCredentialParams newPasskeyParams); Task<string> CreateNewLoginForPasskeyAsync(Fido2ConfirmNewCredentialParams newPasskeyParams);
Task CopyTotpCodeIfNeededAsync(CipherView cipher); Task CopyTotpCodeIfNeededAsync(CipherView cipher);
Task<bool> VerifyOrganizationHasUnassignedItemsAsync();
} }
} }

View File

@@ -187,8 +187,6 @@ namespace Bit.Core.Abstractions
Task<BwRegion?> GetPreAuthRegionAsync(); Task<BwRegion?> GetPreAuthRegionAsync();
Task SetPreAuthRegionAsync(BwRegion value); Task SetPreAuthRegionAsync(BwRegion value);
Task ReloadStateAsync(); Task ReloadStateAsync();
Task<bool> GetShouldCheckOrganizationUnassignedItemsAsync(string userId = null);
Task SetShouldCheckOrganizationUnassignedItemsAsync(bool shouldCheck, string userId = null);
[Obsolete("Use GetPinKeyEncryptedUserKeyAsync instead, left for migration purposes")] [Obsolete("Use GetPinKeyEncryptedUserKeyAsync instead, left for migration purposes")]
Task<string> GetPinProtectedAsync(string userId = null); Task<string> GetPinProtectedAsync(string userId = null);
[Obsolete("Use SetPinKeyEncryptedUserKeyAsync instead, left for migration purposes")] [Obsolete("Use SetPinKeyEncryptedUserKeyAsync instead, left for migration purposes")]

View File

@@ -45,8 +45,6 @@ namespace Bit.Core
public const string PasswordlessLoginRequestKey = "passwordlessLoginRequest"; public const string PasswordlessLoginRequestKey = "passwordlessLoginRequest";
public const string PreLoginEmailKey = "preLoginEmailKey"; public const string PreLoginEmailKey = "preLoginEmailKey";
public const string ConfigsKey = "configsKey"; public const string ConfigsKey = "configsKey";
public const string DisplayEuEnvironmentFlag = "display-eu-environment";
public const string UnassignedItemsBannerFlag = "unassigned-items-banner";
public const string RegionEnvironment = "regionEnvironment"; public const string RegionEnvironment = "regionEnvironment";
public const string DuoCallback = "bitwarden://duo-callback"; public const string DuoCallback = "bitwarden://duo-callback";
public const string NavigateToMessageCommand = "navigateTo"; public const string NavigateToMessageCommand = "navigateTo";
@@ -139,7 +137,6 @@ namespace Bit.Core
public static string ShouldConnectToWatchKey(string userId) => $"shouldConnectToWatch_{userId}"; public static string ShouldConnectToWatchKey(string userId) => $"shouldConnectToWatch_{userId}";
public static string ScreenCaptureAllowedKey(string userId) => $"screenCaptureAllowed_{userId}"; public static string ScreenCaptureAllowedKey(string userId) => $"screenCaptureAllowed_{userId}";
public static string PendingAdminAuthRequest(string userId) => $"pendingAdminAuthRequest_{userId}"; public static string PendingAdminAuthRequest(string userId) => $"pendingAdminAuthRequest_{userId}";
public static string ShouldCheckOrganizationUnassignedItemsKey(string userId) => $"shouldCheckOrganizationUnassignedItems_{userId}";
[Obsolete] [Obsolete]
public static string KeyKey(string userId) => $"key_{userId}"; public static string KeyKey(string userId) => $"key_{userId}";
[Obsolete] [Obsolete]

View File

@@ -18,16 +18,17 @@
<u:InverseBoolConverter x:Key="inverseBool" /> <u:InverseBoolConverter x:Key="inverseBool" />
</controls:BaseCipherViewCell.Resources> </controls:BaseCipherViewCell.Resources>
<Image <controls:CachedImage
x:Name="_iconImage" x:Name="_iconImage"
Grid.Column="0" Grid.Column="0"
Grid.RowSpan="2" Grid.RowSpan="2"
IsOpaque="True" BitmapOptimizations="True"
HorizontalOptions="Center" HorizontalOptions="Center"
VerticalOptions="Center" VerticalOptions="Center"
WidthRequest="22" WidthRequest="22"
HeightRequest="22" HeightRequest="22"
Loaded="Image_OnLoaded" Success="Icon_Success"
Error="Icon_Error"
AutomationProperties.IsInAccessibleTree="False" /> AutomationProperties.IsInAccessibleTree="False" />
<controls:IconLabel <controls:IconLabel

View File

@@ -1,6 +1,4 @@
using Bit.Core.Services; namespace Bit.App.Controls
namespace Bit.App.Controls
{ {
public partial class AuthenticatorViewCell : BaseCipherViewCell public partial class AuthenticatorViewCell : BaseCipherViewCell
{ {
@@ -9,36 +7,8 @@ namespace Bit.App.Controls
InitializeComponent(); InitializeComponent();
} }
protected override Image Icon => _iconImage; protected override CachedImage Icon => _iconImage;
protected override IconLabel IconPlaceholder => _iconPlaceholderImage; protected override IconLabel IconPlaceholder => _iconPlaceholderImage;
private async void Image_OnLoaded(object sender, EventArgs e)
{
if (Handler?.MauiContext == null) { return; }
if (_iconImage?.Source == null) { return; }
try
{
var result = await _iconImage.Source.GetPlatformImageAsync(Handler.MauiContext);
if (result == null)
{
Icon_Error(sender, e);
}
else
{
Icon_Success(sender, e);
}
}
catch (InvalidOperationException) //Can occur with incorrect/malformed uris
{
Icon_Error(sender, e);
}
catch (Exception ex)
{
LoggerHelper.LogEvenIfCantBeResolved(ex);
Icon_Error(sender, e);
}
}
} }
} }

View File

@@ -0,0 +1,42 @@
namespace Bit.App.Controls
{
#if !UT
public class CachedImage : FFImageLoading.Maui.CachedImage
{
}
#else
/// <summary>
/// Given that FFImageLoading package doesn't support net8.0 then for Unit tests projects to build and run correctly
/// we need to not include the reference to FFImageLoading and therefore wrap this class
/// to provide a stub one that does nothing so this project doesn't break and we can run the tests.
/// </summary>
public class CachedImage : View
{
public static readonly BindableProperty SourceProperty = BindableProperty.Create(
nameof(Source), typeof(ImageSource), typeof(CachedImage));
public static readonly BindableProperty AspectProperty = BindableProperty.Create(
nameof(Aspect), typeof(Aspect), typeof(CachedImage));
public bool BitmapOptimizations { get; set; }
public string ErrorPlaceholder { get; set; }
public string LoadingPlaceholder { get; set; }
public ImageSource Source
{
get { return (ImageSource)GetValue(SourceProperty); }
set { SetValue(SourceProperty, value); }
}
public Aspect Aspect
{
get { return (Aspect)GetValue(AspectProperty); }
set { SetValue(AspectProperty, value); }
}
public bool IsLoading { get; set; }
public event EventHandler Success;
public event EventHandler Error;
}
#endif
}

View File

@@ -4,7 +4,7 @@ namespace Bit.App.Controls
{ {
public abstract class BaseCipherViewCell : ExtendedGrid public abstract class BaseCipherViewCell : ExtendedGrid
{ {
protected virtual Image Icon { get; } protected virtual CachedImage Icon { get; }
protected virtual IconLabel IconPlaceholder { get; } protected virtual IconLabel IconPlaceholder { get; }
@@ -15,7 +15,7 @@ namespace Bit.App.Controls
// the app would crash because there can't be any lock files by the app when it gets suspended. // the app would crash because there can't be any lock files by the app when it gets suspended.
// So, the approach has changed to reuse the IconLabel default icon to use it for these placeholders // So, the approach has changed to reuse the IconLabel default icon to use it for these placeholders
// as well. In order to do that both icon controls change their visibility dynamically here reacting to // as well. In order to do that both icon controls change their visibility dynamically here reacting to
// Image OnLoaded event and binding context changes. // CachedImage events and binding context changes.
protected override void OnBindingContextChanged() protected override void OnBindingContextChanged()
{ {
@@ -47,7 +47,8 @@ namespace Bit.App.Controls
}); });
} }
public void Icon_Success(object sender, EventArgs e) #if !UT
public void Icon_Success(object sender, FFImageLoading.Maui.CachedImageEvents.SuccessEventArgs e)
{ {
if (BindingContext is CipherItemViewModel cipherItemVM) if (BindingContext is CipherItemViewModel cipherItemVM)
{ {
@@ -61,7 +62,7 @@ namespace Bit.App.Controls
} }
} }
public void Icon_Error(object sender, EventArgs e) public void Icon_Error(object sender, FFImageLoading.Maui.CachedImageEvents.ErrorEventArgs e)
{ {
if (BindingContext is CipherItemViewModel cipherItemVM) if (BindingContext is CipherItemViewModel cipherItemVM)
{ {
@@ -73,5 +74,38 @@ namespace Bit.App.Controls
IconPlaceholder.IsVisible = true; IconPlaceholder.IsVisible = true;
}); });
} }
#else
private void Icon_Success(object sender, EventArgs e) {}
private void Icon_Error(object sender, EventArgs e) {}
#endif
}
public class StubBaseCipherViewCellSoLinkerDoesntRemoveMethods : BaseCipherViewCell
{
protected override CachedImage Icon => new CachedImage();
protected override IconLabel IconPlaceholder => new IconLabel();
public static void CallThisSoLinkerDoesntRemoveMethods()
{
#if !UT
var stub = new StubBaseCipherViewCellSoLinkerDoesntRemoveMethods();
try
{
stub.Icon_Success(stub, new FFImageLoading.Maui.CachedImageEvents.SuccessEventArgs(new FFImageLoading.Work.ImageInformation(), FFImageLoading.Work.LoadingResult.Disk));
}
catch (Exception)
{
}
try
{
stub.Icon_Error(stub, new FFImageLoading.Maui.CachedImageEvents.ErrorEventArgs(new InvalidOperationException("stub")));
}
catch (Exception)
{
}
#endif
}
} }
} }

View File

@@ -29,17 +29,18 @@
<ColumnDefinition Width="60" /> <ColumnDefinition Width="60" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<Image <controls:CachedImage
x:Name="_iconImage" x:Name="_iconImage"
Grid.Column="0" Grid.Column="0"
IsOpaque="True" BitmapOptimizations="True"
HorizontalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand"
VerticalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand"
Margin="9" Margin="9"
WidthRequest="22" WidthRequest="22"
HeightRequest="22" HeightRequest="22"
Aspect="AspectFit" Aspect="AspectFit"
Loaded="Image_OnLoaded" Success="Icon_Success"
Error="Icon_Error"
AutomationProperties.IsInAccessibleTree="False" AutomationProperties.IsInAccessibleTree="False"
AutomationId="CipherWebsiteIcon" /> AutomationId="CipherWebsiteIcon" />

View File

@@ -1,7 +1,6 @@
using System.Windows.Input; using System.Windows.Input;
using Bit.App.Abstractions; using Bit.App.Abstractions;
using Bit.App.Pages; using Bit.App.Pages;
using Bit.Core.Services;
using Bit.Core.Utilities; using Bit.Core.Utilities;
namespace Bit.App.Controls namespace Bit.App.Controls
@@ -24,7 +23,7 @@ namespace Bit.App.Controls
_iconImage.HeightRequest = ICON_IMAGE_DEFAULT_WIDTH * fontScale; _iconImage.HeightRequest = ICON_IMAGE_DEFAULT_WIDTH * fontScale;
} }
protected override Image Icon => _iconImage; protected override CachedImage Icon => _iconImage;
protected override IconLabel IconPlaceholder => _iconPlaceholderImage; protected override IconLabel IconPlaceholder => _iconPlaceholderImage;
@@ -41,33 +40,5 @@ namespace Bit.App.Controls
ButtonCommand?.Execute(cipherItem.Cipher); ButtonCommand?.Execute(cipherItem.Cipher);
} }
} }
private async void Image_OnLoaded(object sender, EventArgs e)
{
if (Handler?.MauiContext == null) { return; }
if (_iconImage?.Source == null) { return; }
try
{
var result = await _iconImage.Source.GetPlatformImageAsync(Handler.MauiContext);
if (result == null)
{
Icon_Error(sender, e);
}
else
{
Icon_Success(sender, e);
}
}
catch (InvalidOperationException) //Can occur with incorrect/malformed uris
{
Icon_Error(sender, e);
}
catch (Exception ex)
{
LoggerHelper.LogEvenIfCantBeResolved(ex);
Icon_Error(sender, e);
}
}
} }
} }

View File

@@ -48,6 +48,7 @@
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.1" /> <PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.1" />
<PackageReference Include="Portable.BouncyCastle" Version="1.9.0" /> <PackageReference Include="Portable.BouncyCastle" Version="1.9.0" />
<!-- HACK: When running Unit Tests we cannot load FFImageLoading because it doesn't support "raw" net8.0 --> <!-- HACK: When running Unit Tests we cannot load FFImageLoading because it doesn't support "raw" net8.0 -->
<PackageReference Condition="!$(CustomConstants.Contains(UT))" Include="FFImageLoadingCompat.Maui" Version="0.1.1" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'"> <ItemGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">
<PackageReference Include="Xamarin.AndroidX.AutoFill" Version="1.1.0.18" /> <PackageReference Include="Xamarin.AndroidX.AutoFill" Version="1.1.0.18" />

View File

@@ -1,8 +1,12 @@
 using Bit.App.Controls;
using Camera.MAUI; using Camera.MAUI;
using CommunityToolkit.Maui; using CommunityToolkit.Maui;
#if !UT
using FFImageLoading.Maui;
#endif
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Maui.Controls.Compatibility.Hosting; using Microsoft.Maui.Controls.Compatibility.Hosting;
using Microsoft.Maui.Handlers;
using SkiaSharp.Views.Maui.Controls.Hosting; using SkiaSharp.Views.Maui.Controls.Hosting;
using AppEffects = Bit.App.Effects; using AppEffects = Bit.App.Effects;
@@ -22,6 +26,9 @@ public static class MauiProgram
.UseMauiCompatibility() .UseMauiCompatibility()
.UseMauiCameraView() .UseMauiCameraView()
.UseSkiaSharp() .UseSkiaSharp()
#if !UT
.UseFFImageLoading()
#endif
.ConfigureEffects(effects => .ConfigureEffects(effects =>
{ {
#if ANDROID #if ANDROID
@@ -56,6 +63,13 @@ public static class MauiProgram
builder.Logging.AddDebug(); builder.Logging.AddDebug();
#endif #endif
ExplicitlyPreventThingsGetRemovedBecauseOfLinker();
return builder; return builder;
} }
private static void ExplicitlyPreventThingsGetRemovedBecauseOfLinker()
{
StubBaseCipherViewCellSoLinkerDoesntRemoveMethods.CallThisSoLinkerDoesntRemoveMethods();
}
} }

View File

@@ -27,7 +27,6 @@ namespace Bit.App.Models
public bool HideAccountSwitcher { get; set; } public bool HideAccountSwitcher { get; set; }
public OtpData? OtpData { get; set; } public OtpData? OtpData { get; set; }
public bool HasUnlockedInThisTransaction { get; set; } public bool HasUnlockedInThisTransaction { get; set; }
public bool HasJustLoggedInOrUnlocked { get; set; }
public void SetAllFrom(AppOptions o) public void SetAllFrom(AppOptions o)
{ {

View File

@@ -25,7 +25,6 @@ namespace Bit.App.Pages
private bool _rememberEmail; private bool _rememberEmail;
private string _email; private string _email;
private string _selectedEnvironmentName; private string _selectedEnvironmentName;
private bool _displayEuEnvironment;
public HomeViewModel() public HomeViewModel()
{ {
@@ -116,7 +115,6 @@ namespace Bit.App.Pages
{ {
Email = await _stateService.GetRememberedEmailAsync(); Email = await _stateService.GetRememberedEmailAsync();
RememberEmail = !string.IsNullOrEmpty(Email); RememberEmail = !string.IsNullOrEmpty(Email);
_displayEuEnvironment = await _configService.GetFeatureFlagBoolAsync(Constants.DisplayEuEnvironmentFlag, forceRefresh: true);
} }
public async Task ContinueToLoginStepAsync() public async Task ContinueToLoginStepAsync()
@@ -158,11 +156,7 @@ namespace Bit.App.Pages
public async Task ShowEnvironmentPickerAsync() public async Task ShowEnvironmentPickerAsync()
{ {
_displayEuEnvironment = await _configService.GetFeatureFlagBoolAsync(Constants.DisplayEuEnvironmentFlag); var options = new string[] { BwRegion.US.Domain(), BwRegion.EU.Domain(), AppResources.SelfHosted };
var options = _displayEuEnvironment
? new string[] { BwRegion.US.Domain(), BwRegion.EU.Domain(), AppResources.SelfHosted }
: new string[] { BwRegion.US.Domain(), AppResources.SelfHosted };
await MainThread.InvokeOnMainThreadAsync(async () => await MainThread.InvokeOnMainThreadAsync(async () =>
{ {
var result = await _deviceActionService.Value.DisplayActionSheetAsync(AppResources.LoggingInOn, AppResources.Cancel, null, options); var result = await _deviceActionService.Value.DisplayActionSheetAsync(AppResources.LoggingInOn, AppResources.Cancel, null, options);

View File

@@ -232,11 +232,6 @@ namespace Bit.App.Pages
return; return;
} }
var previousPage = await AppHelpers.ClearPreviousPage(); var previousPage = await AppHelpers.ClearPreviousPage();
if (_appOptions != null)
{
_appOptions.HasJustLoggedInOrUnlocked = true;
}
App.MainPage = new TabsPage(_appOptions, previousPage); App.MainPage = new TabsPage(_appOptions, previousPage);
} }
} }

View File

@@ -285,6 +285,8 @@ namespace Bit.App.Pages
var failed = true; var failed = true;
try try
{ {
await MainThread.InvokeOnMainThreadAsync(() => _deviceActionService.ShowLoadingAsync(AppResources.Loading));
EncString userKeyPin; EncString userKeyPin;
EncString oldPinProtected; EncString oldPinProtected;
switch (_pinStatus) switch (_pinStatus)
@@ -333,21 +335,26 @@ namespace Bit.App.Pages
{ {
Pin = string.Empty; Pin = string.Empty;
await AppHelpers.ResetInvalidUnlockAttemptsAsync(); await AppHelpers.ResetInvalidUnlockAttemptsAsync();
await SetUserKeyAndContinueAsync(userKey); await SetUserKeyAndContinueAsync(userKey, shouldHandleHideLoading: true);
await Task.Delay(150); //Workaround Delay to avoid "duplicate" execution of SubmitAsync on Android when invoked from the ReturnCommand await Task.Delay(150); //Workaround Delay to avoid "duplicate" execution of SubmitAsync on Android when invoked from the ReturnCommand
} }
} }
catch (LegacyUserException) catch (LegacyUserException)
{ {
await MainThread.InvokeOnMainThreadAsync(_deviceActionService.HideLoadingAsync);
throw; throw;
} }
catch catch (Exception ex)
{ {
_logger.Exception(ex);
failed = true; failed = true;
} }
if (failed) if (failed)
{ {
var invalidUnlockAttempts = await AppHelpers.IncrementInvalidUnlockAttemptsAsync(); var invalidUnlockAttempts = await AppHelpers.IncrementInvalidUnlockAttemptsAsync();
await MainThread.InvokeOnMainThreadAsync(_deviceActionService.HideLoadingAsync);
if (invalidUnlockAttempts >= 5) if (invalidUnlockAttempts >= 5)
{ {
_messagingService.Send("logout"); _messagingService.Send("logout");
@@ -536,7 +543,7 @@ namespace Bit.App.Pages
} }
} }
private async Task SetUserKeyAndContinueAsync(UserKey key) private async Task SetUserKeyAndContinueAsync(UserKey key, bool shouldHandleHideLoading = false)
{ {
var hasKey = await _cryptoService.HasUserKeyAsync(); var hasKey = await _cryptoService.HasUserKeyAsync();
if (!hasKey) if (!hasKey)
@@ -544,14 +551,18 @@ namespace Bit.App.Pages
await _cryptoService.SetUserKeyAsync(key); await _cryptoService.SetUserKeyAsync(key);
} }
await _deviceTrustCryptoService.TrustDeviceIfNeededAsync(); await _deviceTrustCryptoService.TrustDeviceIfNeededAsync();
await DoContinueAsync(); await DoContinueAsync(shouldHandleHideLoading);
} }
private async Task DoContinueAsync() private async Task DoContinueAsync(bool shouldHandleHideLoading = false)
{ {
_syncService.FullSyncAsync(false).FireAndForget(); _syncService.FullSyncAsync(false).FireAndForget();
await _stateService.SetBiometricLockedAsync(false); await _stateService.SetBiometricLockedAsync(false);
_watchDeviceService.SyncDataToWatchAsync().FireAndForget(); _watchDeviceService.SyncDataToWatchAsync().FireAndForget();
if (shouldHandleHideLoading)
{
await MainThread.InvokeOnMainThreadAsync(_deviceActionService.HideLoadingAsync);
}
_messagingService.Send("unlocked"); _messagingService.Send("unlocked");
UnlockedAction?.Invoke(); UnlockedAction?.Invoke();
} }

View File

@@ -35,11 +35,6 @@ namespace Bit.App.Pages
{ {
return; return;
} }
if (_appOptions != null)
{
_appOptions.HasJustLoggedInOrUnlocked = true;
}
var previousPage = await AppHelpers.ClearPreviousPage(); var previousPage = await AppHelpers.ClearPreviousPage();
App.MainPage = new TabsPage(_appOptions, previousPage); App.MainPage = new TabsPage(_appOptions, previousPage);
} }

View File

@@ -25,6 +25,7 @@ namespace Bit.App.Pages
_broadcasterService = ServiceContainer.Resolve<IBroadcasterService>(); _broadcasterService = ServiceContainer.Resolve<IBroadcasterService>();
_vm = BindingContext as LoginPageViewModel; _vm = BindingContext as LoginPageViewModel;
_vm.Page = this; _vm.Page = this;
_vm.FromIosExtension = _appOptions?.IosExtension ?? false;
_vm.StartTwoFactorAction = () => MainThread.BeginInvokeOnMainThread(async () => await StartTwoFactorAsync()); _vm.StartTwoFactorAction = () => MainThread.BeginInvokeOnMainThread(async () => await StartTwoFactorAsync());
_vm.LogInSuccessAction = () => MainThread.BeginInvokeOnMainThread(async () => await LogInSuccessAsync()); _vm.LogInSuccessAction = () => MainThread.BeginInvokeOnMainThread(async () => await LogInSuccessAsync());
_vm.LogInWithDeviceAction = () => StartLoginWithDeviceAsync().FireAndForget(); _vm.LogInWithDeviceAction = () => StartLoginWithDeviceAsync().FireAndForget();
@@ -195,11 +196,6 @@ namespace Bit.App.Pages
{ {
return; return;
} }
if (_appOptions != null)
{
_appOptions.HasJustLoggedInOrUnlocked = true;
}
var previousPage = await AppHelpers.ClearPreviousPage(); var previousPage = await AppHelpers.ClearPreviousPage();
App.MainPage = new TabsPage(_appOptions, previousPage); App.MainPage = new TabsPage(_appOptions, previousPage);
} }

View File

@@ -19,6 +19,7 @@ namespace Bit.App.Pages
_vm.Email = email; _vm.Email = email;
_vm.AuthRequestType = authRequestType; _vm.AuthRequestType = authRequestType;
_vm.AuthingWithSso = authingWithSso; _vm.AuthingWithSso = authingWithSso;
_vm.FromIosExtension = _appOptions?.IosExtension ?? false;
_vm.StartTwoFactorAction = () => MainThread.BeginInvokeOnMainThread(async () => await StartTwoFactorAsync()); _vm.StartTwoFactorAction = () => MainThread.BeginInvokeOnMainThread(async () => await StartTwoFactorAsync());
_vm.LogInSuccessAction = () => MainThread.BeginInvokeOnMainThread(async () => await LogInSuccessAsync()); _vm.LogInSuccessAction = () => MainThread.BeginInvokeOnMainThread(async () => await LogInSuccessAsync());
_vm.UpdateTempPasswordAction = () => MainThread.BeginInvokeOnMainThread(async () => await UpdateTempPasswordAsync()); _vm.UpdateTempPasswordAction = () => MainThread.BeginInvokeOnMainThread(async () => await UpdateTempPasswordAsync());
@@ -55,11 +56,6 @@ namespace Bit.App.Pages
{ {
return; return;
} }
if (_appOptions != null)
{
_appOptions.HasJustLoggedInOrUnlocked = true;
}
var previousPage = await AppHelpers.ClearPreviousPage(); var previousPage = await AppHelpers.ClearPreviousPage();
App.MainPage = new TabsPage(_appOptions, previousPage); App.MainPage = new TabsPage(_appOptions, previousPage);
} }

View File

@@ -1,4 +1,6 @@
namespace Bit.App.Pages using Bit.App.Models;
namespace Bit.App.Pages
{ {
public partial class RegisterPage : BaseContentPage public partial class RegisterPage : BaseContentPage
{ {
@@ -6,11 +8,12 @@
private bool _inputFocused; private bool _inputFocused;
public RegisterPage(HomePage homePage) public RegisterPage(HomePage homePage, AppOptions appOptions = null)
{ {
InitializeComponent(); InitializeComponent();
_vm = BindingContext as RegisterPageViewModel; _vm = BindingContext as RegisterPageViewModel;
_vm.Page = this; _vm.Page = this;
_vm.FromIosExtension = appOptions?.IosExtension ?? false;
_vm.RegistrationSuccess = () => MainThread.BeginInvokeOnMainThread(async () => await RegistrationSuccessAsync(homePage)); _vm.RegistrationSuccess = () => MainThread.BeginInvokeOnMainThread(async () => await RegistrationSuccessAsync(homePage));
_vm.CloseAction = async () => _vm.CloseAction = async () =>
{ {

View File

@@ -71,11 +71,6 @@ namespace Bit.App.Pages
{ {
return; return;
} }
if (_appOptions != null)
{
_appOptions.HasJustLoggedInOrUnlocked = true;
}
var previousPage = await AppHelpers.ClearPreviousPage(); var previousPage = await AppHelpers.ClearPreviousPage();
App.MainPage = new TabsPage(_appOptions, previousPage); App.MainPage = new TabsPage(_appOptions, previousPage);
} }

View File

@@ -28,6 +28,7 @@ namespace Bit.App.Pages
_vm = BindingContext as TwoFactorPageViewModel; _vm = BindingContext as TwoFactorPageViewModel;
_vm.Page = this; _vm.Page = this;
_vm.AuthingWithSso = authingWithSso ?? false; _vm.AuthingWithSso = authingWithSso ?? false;
_vm.FromIosExtension = _appOptions?.IosExtension ?? false;
_vm.StartSetPasswordAction = () => _vm.StartSetPasswordAction = () =>
MainThread.BeginInvokeOnMainThread(async () => await StartSetPasswordAsync()); MainThread.BeginInvokeOnMainThread(async () => await StartSetPasswordAsync());
_vm.TwoFactorAuthSuccessAction = () => _vm.TwoFactorAuthSuccessAction = () =>
@@ -206,11 +207,6 @@ namespace Bit.App.Pages
{ {
return; return;
} }
if (_appOptions != null)
{
_appOptions.HasJustLoggedInOrUnlocked = true;
}
var previousPage = await AppHelpers.ClearPreviousPage(); var previousPage = await AppHelpers.ClearPreviousPage();
App.MainPage = new TabsPage(_appOptions, previousPage); App.MainPage = new TabsPage(_appOptions, previousPage);
} }

View File

@@ -11,6 +11,13 @@ using Bit.Core.Models.Request;
using Bit.Core.Resources.Localization; using Bit.Core.Resources.Localization;
using Bit.Core.Utilities; using Bit.Core.Utilities;
using Newtonsoft.Json; using Newtonsoft.Json;
using Bit.Core.Services;
#if IOS
using WebAuthenticator = Bit.Core.Utilities.MAUI.WebAuthenticator;
using WebAuthenticatorResult = Bit.Core.Utilities.MAUI.WebAuthenticatorResult;
using WebAuthenticatorOptions = Bit.Core.Utilities.MAUI.WebAuthenticatorOptions;
#endif
namespace Bit.App.Pages namespace Bit.App.Pages
{ {
@@ -136,6 +143,7 @@ namespace Bit.App.Pages
nameof(ShowTryAgain), nameof(ShowTryAgain),
}); });
} }
public ICommand SubmitCommand { get; } public ICommand SubmitCommand { get; }
public ICommand MoreCommand { get; } public ICommand MoreCommand { get; }
public ICommand AuthenticateWithDuoFramelessCommand { get; } public ICommand AuthenticateWithDuoFramelessCommand { get; }
@@ -261,7 +269,11 @@ namespace Bit.App.Pages
authResult = await WebAuthenticator.AuthenticateAsync(new WebAuthenticatorOptions authResult = await WebAuthenticator.AuthenticateAsync(new WebAuthenticatorOptions
{ {
Url = new Uri(url), Url = new Uri(url),
CallbackUrl = new Uri(Constants.DuoCallback) CallbackUrl = new Uri(Constants.DuoCallback),
#if IOS
ShouldUseSharedApplicationKeyWindow = FromIosExtension
#endif
}); });
} }
catch (TaskCanceledException) catch (TaskCanceledException)
@@ -348,6 +360,9 @@ namespace Bit.App.Pages
Url = new Uri(url), Url = new Uri(url),
CallbackUrl = new Uri(callbackUri), CallbackUrl = new Uri(callbackUri),
PrefersEphemeralWebBrowserSession = true, PrefersEphemeralWebBrowserSession = true,
#if IOS
ShouldUseSharedApplicationKeyWindow = FromIosExtension
#endif
}; };
authResult = await WebAuthenticator.AuthenticateAsync(options); authResult = await WebAuthenticator.AuthenticateAsync(options);
} }

View File

@@ -6,6 +6,12 @@ using Bit.App.Utilities;
using Bit.Core.Abstractions; using Bit.Core.Abstractions;
using Microsoft.Maui.Authentication; using Microsoft.Maui.Authentication;
#if IOS
using WebAuthenticator = Bit.Core.Utilities.MAUI.WebAuthenticator;
using WebAuthenticatorResult = Bit.Core.Utilities.MAUI.WebAuthenticatorResult;
using WebAuthenticatorOptions = Bit.Core.Utilities.MAUI.WebAuthenticatorOptions;
#endif
namespace Bit.App.Pages namespace Bit.App.Pages
{ {
public abstract class CaptchaProtectedViewModel : BaseViewModel public abstract class CaptchaProtectedViewModel : BaseViewModel
@@ -16,6 +22,8 @@ namespace Bit.App.Pages
protected abstract IPlatformUtilsService platformUtilsService { get; } protected abstract IPlatformUtilsService platformUtilsService { get; }
protected string _captchaToken = null; protected string _captchaToken = null;
public bool FromIosExtension { get; set; }
protected async Task<bool> HandleCaptchaAsync(string captchaSiteKey, bool needsCaptcha, Func<Task> onSuccess) protected async Task<bool> HandleCaptchaAsync(string captchaSiteKey, bool needsCaptcha, Func<Task> onSuccess)
{ {
if (!needsCaptcha) if (!needsCaptcha)
@@ -61,6 +69,9 @@ namespace Bit.App.Pages
Url = new Uri(url), Url = new Uri(url),
CallbackUrl = new Uri(callbackUri), CallbackUrl = new Uri(callbackUri),
PrefersEphemeralWebBrowserSession = false, PrefersEphemeralWebBrowserSession = false,
#if IOS
ShouldUseSharedApplicationKeyWindow = FromIosExtension
#endif
}; };
authResult = await WebAuthenticator.AuthenticateAsync(options); authResult = await WebAuthenticator.AuthenticateAsync(options);
} }

View File

@@ -33,7 +33,7 @@ namespace Bit.App.Pages
_keyConnectorService = ServiceContainer.Resolve<IKeyConnectorService>("keyConnectorService"); _keyConnectorService = ServiceContainer.Resolve<IKeyConnectorService>("keyConnectorService");
_stateService = ServiceContainer.Resolve<IStateService>(); _stateService = ServiceContainer.Resolve<IStateService>();
_groupingsPage = new NavigationPage(new GroupingsPage(true, previousPage: previousPage, appOptions: appOptions)) _groupingsPage = new NavigationPage(new GroupingsPage(true, previousPage: previousPage))
{ {
Title = AppResources.MyVault, Title = AppResources.MyVault,
IconImageSource = "lock.png" IconImageSource = "lock.png"

View File

@@ -7,7 +7,7 @@ namespace Bit.App.Pages
public class CipherItemViewModel : ExtendedViewModel, IGroupingsPageListItem public class CipherItemViewModel : ExtendedViewModel, IGroupingsPageListItem
{ {
private readonly bool _websiteIconsEnabled; private readonly bool _websiteIconsEnabled;
private UriImageSource _iconImageSource = null; private string _iconImageSource = string.Empty;
public CipherItemViewModel(CipherView cipherView, bool websiteIconsEnabled, bool fuzzyAutofill = false) public CipherItemViewModel(CipherView cipherView, bool websiteIconsEnabled, bool fuzzyAutofill = false)
{ {
@@ -27,23 +27,14 @@ namespace Bit.App.Pages
&& IconImageSource != null; && IconImageSource != null;
} }
public UriImageSource IconImageSource public string IconImageSource
{ {
get get
{ {
if (_iconImageSource == null) // default value since icon source can return null if (_iconImageSource == string.Empty) // default value since icon source can return null
{ {
var iconImageStr = IconImageHelper.GetIconImage(Cipher); _iconImageSource = IconImageHelper.GetIconImage(Cipher);
if (string.IsNullOrWhiteSpace(iconImageStr)) { return null; }
_iconImageSource = new UriImageSource
{
Uri = new Uri(iconImageStr),
CacheValidity = TimeSpan.FromDays(90),
CachingEnabled = true
};
} }
return _iconImageSource; return _iconImageSource;
} }
} }

View File

@@ -28,7 +28,7 @@ namespace Bit.App.Pages
public GroupingsPage(bool mainPage, CipherType? type = null, string folderId = null, public GroupingsPage(bool mainPage, CipherType? type = null, string folderId = null,
string collectionId = null, string pageTitle = null, string vaultFilterSelection = null, string collectionId = null, string pageTitle = null, string vaultFilterSelection = null,
PreviousPageInfo previousPage = null, bool deleted = false, bool showTotp = false, AppOptions appOptions = null) PreviousPageInfo previousPage = null, bool deleted = false, bool showTotp = false)
{ {
_pageName = string.Concat(nameof(GroupingsPage), "_", DateTime.UtcNow.Ticks); _pageName = string.Concat(nameof(GroupingsPage), "_", DateTime.UtcNow.Ticks);
InitializeComponent(); InitializeComponent();
@@ -51,7 +51,6 @@ namespace Bit.App.Pages
_vm.CollectionId = collectionId; _vm.CollectionId = collectionId;
_vm.Deleted = deleted; _vm.Deleted = deleted;
_vm.ShowTotp = showTotp; _vm.ShowTotp = showTotp;
_vm.AppOptions = appOptions;
_previousPage = previousPage; _previousPage = previousPage;
if (pageTitle != null) if (pageTitle != null)
{ {
@@ -162,8 +161,6 @@ namespace Bit.App.Pages
return; return;
} }
await _vm.CheckOrganizationUnassignedItemsAsync();
// Push registration // Push registration
var lastPushRegistration = await _stateService.GetPushLastRegistrationDateAsync(); var lastPushRegistration = await _stateService.GetPushLastRegistrationDateAsync();
lastPushRegistration = lastPushRegistration.GetValueOrDefault(DateTime.MinValue); lastPushRegistration = lastPushRegistration.GetValueOrDefault(DateTime.MinValue);

View File

@@ -46,8 +46,6 @@ namespace Bit.App.Pages
private readonly IPasswordRepromptService _passwordRepromptService; private readonly IPasswordRepromptService _passwordRepromptService;
private readonly IOrganizationService _organizationService; private readonly IOrganizationService _organizationService;
private readonly IPolicyService _policyService; private readonly IPolicyService _policyService;
private readonly IConfigService _configService;
private readonly IEnvironmentService _environmentService;
private readonly ILogger _logger; private readonly ILogger _logger;
public GroupingsPageViewModel() public GroupingsPageViewModel()
@@ -64,8 +62,6 @@ namespace Bit.App.Pages
_passwordRepromptService = ServiceContainer.Resolve<IPasswordRepromptService>("passwordRepromptService"); _passwordRepromptService = ServiceContainer.Resolve<IPasswordRepromptService>("passwordRepromptService");
_organizationService = ServiceContainer.Resolve<IOrganizationService>("organizationService"); _organizationService = ServiceContainer.Resolve<IOrganizationService>("organizationService");
_policyService = ServiceContainer.Resolve<IPolicyService>("policyService"); _policyService = ServiceContainer.Resolve<IPolicyService>("policyService");
_configService = ServiceContainer.Resolve<IConfigService>();
_environmentService = ServiceContainer.Resolve<IEnvironmentService>();
_logger = ServiceContainer.Resolve<ILogger>("logger"); _logger = ServiceContainer.Resolve<ILogger>("logger");
Loading = true; Loading = true;
@@ -109,7 +105,6 @@ namespace Bit.App.Pages
public List<Core.Models.View.CollectionView> Collections { get; set; } public List<Core.Models.View.CollectionView> Collections { get; set; }
public List<TreeNode<Core.Models.View.CollectionView>> NestedCollections { get; set; } public List<TreeNode<Core.Models.View.CollectionView>> NestedCollections { get; set; }
public AppOptions AppOptions { get; internal set; }
protected override ICipherService cipherService => _cipherService; protected override ICipherService cipherService => _cipherService;
protected override IPolicyService policyService => _policyService; protected override IPolicyService policyService => _policyService;
protected override IOrganizationService organizationService => _organizationService; protected override IOrganizationService organizationService => _organizationService;
@@ -705,59 +700,5 @@ namespace Bit.App.Pages
var folders = decFolders.Where(f => _allCiphers.Any(c => c.FolderId == f.Id)).ToList(); var folders = decFolders.Where(f => _allCiphers.Any(c => c.FolderId == f.Id)).ToList();
return folders.Any() ? folders : null; return folders.Any() ? folders : null;
} }
internal async Task CheckOrganizationUnassignedItemsAsync()
{
try
{
if (AppOptions?.HasJustLoggedInOrUnlocked != true)
{
return;
}
AppOptions.HasJustLoggedInOrUnlocked = false;
if (!await _configService.GetFeatureFlagBoolAsync(Core.Constants.UnassignedItemsBannerFlag)
||
!await _stateService.GetShouldCheckOrganizationUnassignedItemsAsync())
{
return;
}
var waitSyncTask = Task.Run(async () =>
{
while (_syncService.SyncInProgress)
{
await Task.Delay(100);
}
});
await waitSyncTask.WaitAsync(TimeSpan.FromMinutes(5));
if (!await _cipherService.VerifyOrganizationHasUnassignedItemsAsync())
{
return;
}
var message = _environmentService.SelectedRegion == Core.Enums.Region.SelfHosted
? AppResources.OrganizationUnassignedItemsMessageSelfHost041624DescriptionLong
: AppResources.OrganizationUnassignedItemsMessageUSEUDescriptionLong;
var response = await _deviceActionService.DisplayAlertAsync(AppResources.Notice,
message,
null,
AppResources.RemindMeLater,
AppResources.Ok);
if (response == AppResources.Ok)
{
await _stateService.SetShouldCheckOrganizationUnassignedItemsAsync(false);
}
}
catch (TimeoutException) { }
catch (Exception ex)
{
_logger.Exception(ex);
}
}
} }
} }

View File

@@ -1328,7 +1328,7 @@ namespace Bit.Core.Resources.Localization {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Bitwarden Help Center. /// Looks up a localized string similar to Bitwarden help center.
/// </summary> /// </summary>
public static string BitwardenHelpCenter { public static string BitwardenHelpCenter {
get { get {
@@ -4929,15 +4929,6 @@ namespace Bit.Core.Resources.Localization {
} }
} }
/// <summary>
/// Looks up a localized string similar to Notice.
/// </summary>
public static string Notice {
get {
return ResourceManager.GetString("Notice", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to This account has two-step login set up, however, none of the configured two-step providers are supported on this device. Please use a supported device and/or add additional providers that are better supported across devices (such as an authenticator app).. /// Looks up a localized string similar to This account has two-step login set up, however, none of the configured two-step providers are supported on this device. Please use a supported device and/or add additional providers that are better supported across devices (such as an authenticator app)..
/// </summary> /// </summary>
@@ -5173,24 +5164,6 @@ namespace Bit.Core.Resources.Localization {
} }
} }
/// <summary>
/// Looks up a localized string similar to On May 16, 2024, unassigned organization items will no longer be visible in the All Vaults view and only accessible via the Admin Console. Assign these items to a collection from the Admin Console to make them visible..
/// </summary>
public static string OrganizationUnassignedItemsMessageSelfHost041624DescriptionLong {
get {
return ResourceManager.GetString("OrganizationUnassignedItemsMessageSelfHost041624DescriptionLong", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Unassigned organization items are no longer visible in the All Vaults view and only accessible via the Admin Console. Assign these items to a collection from the Admin Console to make them visible..
/// </summary>
public static string OrganizationUnassignedItemsMessageUSEUDescriptionLong {
get {
return ResourceManager.GetString("OrganizationUnassignedItemsMessageUSEUDescriptionLong", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Organization identifier. /// Looks up a localized string similar to Organization identifier.
/// </summary> /// </summary>
@@ -5876,15 +5849,6 @@ namespace Bit.Core.Resources.Localization {
} }
} }
/// <summary>
/// Looks up a localized string similar to Remind me later.
/// </summary>
public static string RemindMeLater {
get {
return ResourceManager.GetString("RemindMeLater", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Remove. /// Looks up a localized string similar to Remove.
/// </summary> /// </summary>

View File

@@ -2753,7 +2753,7 @@ Wil u na die rekening omskakel?</value>
<value>Log in with device must be set up in the settings of the Bitwarden app. Need another option?</value> <value>Log in with device must be set up in the settings of the Bitwarden app. Need another option?</value>
</data> </data>
<data name="LogInWithDevice" xml:space="preserve"> <data name="LogInWithDevice" xml:space="preserve">
<value>Log in with device</value> <value>Teken Aan met 'n ander toestel</value>
</data> </data>
<data name="LoggingInOn" xml:space="preserve"> <data name="LoggingInOn" xml:space="preserve">
<value>Logging in on</value> <value>Logging in on</value>
@@ -2768,7 +2768,7 @@ Wil u na die rekening omskakel?</value>
<value>Account security</value> <value>Account security</value>
</data> </data>
<data name="BitwardenHelpCenter" xml:space="preserve"> <data name="BitwardenHelpCenter" xml:space="preserve">
<value>Bitwarden Help Center</value> <value>Bitwarden help center</value>
</data> </data>
<data name="ContactBitwardenSupport" xml:space="preserve"> <data name="ContactBitwardenSupport" xml:space="preserve">
<value>Contact Bitwarden support</value> <value>Contact Bitwarden support</value>
@@ -2974,19 +2974,22 @@ Wil u na die rekening omskakel?</value>
<data name="YourPasskeyWillBeSavedToYourBitwardenVaultForX" xml:space="preserve"> <data name="YourPasskeyWillBeSavedToYourBitwardenVaultForX" xml:space="preserve">
<value>Your passkey will be saved to your Bitwarden vault for {0}</value> <value>Your passkey will be saved to your Bitwarden vault for {0}</value>
</data> </data>
<data name="OrganizationUnassignedItemsMessageUSEUDescriptionLong" xml:space="preserve">
<value>Unassigned organization items are no longer visible in the All Vaults view and only accessible via the Admin Console. Assign these items to a collection from the Admin Console to make them visible.</value>
</data>
<data name="OrganizationUnassignedItemsMessageSelfHost041624DescriptionLong" xml:space="preserve">
<value>On May 16, 2024, unassigned organization items will no longer be visible in the All Vaults view and only accessible via the Admin Console. Assign these items to a collection from the Admin Console to make them visible.</value>
</data>
<data name="RemindMeLater" xml:space="preserve">
<value>Remind me later</value>
</data>
<data name="Notice" xml:space="preserve">
<value>Notice</value>
</data>
<data name="PasskeysNotSupportedForThisApp" xml:space="preserve"> <data name="PasskeysNotSupportedForThisApp" xml:space="preserve">
<value>Passkeys not supported for this app</value> <value>Passkeys not supported for this app</value>
</data> </data>
<data name="PasskeyOperationFailedBecauseBrowserIsNotPrivileged" xml:space="preserve">
<value>Passkey operation failed because browser is not privileged</value>
</data>
<data name="PasskeyOperationFailedBecauseBrowserSignatureDoesNotMatch" xml:space="preserve">
<value>Passkey operation failed because browser signature does not match</value>
</data>
<data name="PasskeyOperationFailedBecauseOfMissingAssetLinks" xml:space="preserve">
<value>Passkey operation failed because of missing asset links</value>
</data>
<data name="PasskeyOperationFailedBecauseAppNotFoundInAssetLinks" xml:space="preserve">
<value>Passkey operation failed because app not found in asset links</value>
</data>
<data name="PasskeyOperationFailedBecauseAppCouldNotBeVerified" xml:space="preserve">
<value>Passkey operation failed because app could not be verified</value>
</data>
</root> </root>

View File

@@ -422,7 +422,7 @@
<value>خدمة التعبئة التلقائية</value> <value>خدمة التعبئة التلقائية</value>
</data> </data>
<data name="SetBitwardenAsPasskeyManagerDescription" xml:space="preserve"> <data name="SetBitwardenAsPasskeyManagerDescription" xml:space="preserve">
<value>Set Bitwarden as your passkey provider in device settings.</value> <value>تعيين Bitwarden كموفر مفتاح المرور الخاص بك في إعدادات الجهاز.</value>
</data> </data>
<data name="AvoidAmbiguousCharacters" xml:space="preserve"> <data name="AvoidAmbiguousCharacters" xml:space="preserve">
<value>تجنب الأحرف الغامضة</value> <value>تجنب الأحرف الغامضة</value>
@@ -446,7 +446,7 @@
<value>تغيير البريد الإلكتروني</value> <value>تغيير البريد الإلكتروني</value>
</data> </data>
<data name="ChangeEmailConfirmation" xml:space="preserve"> <data name="ChangeEmailConfirmation" xml:space="preserve">
<value>يمكنك تغيير عنوان بريدك الإلكتروني من خزنة الويب على bitwarden.com. هل تريد زيارة الموقع الآن؟</value> <value>يمكنك تغيير عنوان بريدك الإلكتروني من خزانة الويب على bitwarden.com. هل تريد زيارة الموقع الآن؟</value>
</data> </data>
<data name="ChangeMasterPassword" xml:space="preserve"> <data name="ChangeMasterPassword" xml:space="preserve">
<value>تغيير كلمة المرور الرئيسية</value> <value>تغيير كلمة المرور الرئيسية</value>
@@ -550,20 +550,20 @@
<value>فورًا</value> <value>فورًا</value>
</data> </data>
<data name="VaultTimeout" xml:space="preserve"> <data name="VaultTimeout" xml:space="preserve">
<value>مهلة الخزنة</value> <value>مهلة الخزانة</value>
</data> </data>
<data name="VaultTimeoutAction" xml:space="preserve"> <data name="VaultTimeoutAction" xml:space="preserve">
<value>إجراء مهلة الخزنة</value> <value>إجراء مهلة الخزانة</value>
</data> </data>
<data name="VaultTimeoutLogOutConfirmation" xml:space="preserve"> <data name="VaultTimeoutLogOutConfirmation" xml:space="preserve">
<value>سيؤدي تسجيل الخروج إلى إزالة جميع الوصول إلى الخزنة الخاصة بك ويتطلب المصادقة عبر الإنترنت بعد انتهاء المهلة. هل أنت متأكد من أنك تريد استخدام هذا الإعداد؟</value> <value>سيؤدي تسجيل الخروج إلى إزالة جميع الوصول إلى الخزانة الخاصة بك ويتطلب المصادقة عبر الإنترنت بعد انتهاء المهلة. هل أنت متأكد من أنك تريد استخدام هذا الإعداد؟</value>
</data> </data>
<data name="LoggingIn" xml:space="preserve"> <data name="LoggingIn" xml:space="preserve">
<value>جارِ تسجيل الدخول...</value> <value>جارِ تسجيل الدخول...</value>
<comment>Message shown when interacting with the server</comment> <comment>Message shown when interacting with the server</comment>
</data> </data>
<data name="LoginOrCreateNewAccount" xml:space="preserve"> <data name="LoginOrCreateNewAccount" xml:space="preserve">
<value>قم بتسجيل الدخول أو إنشاء حساب جديد للوصول إلى خزنتك الآمنة.</value> <value>قم بتسجيل الدخول أو إنشاء حساب جديد للوصول إلى خزانتك الآمنة.</value>
</data> </data>
<data name="Manage" xml:space="preserve"> <data name="Manage" xml:space="preserve">
<value>إدارة</value> <value>إدارة</value>
@@ -572,7 +572,7 @@
<value>تأكيد كلمة المرور غير صحيح.</value> <value>تأكيد كلمة المرور غير صحيح.</value>
</data> </data>
<data name="MasterPasswordDescription" xml:space="preserve"> <data name="MasterPasswordDescription" xml:space="preserve">
<value>كلمة المرور الرئيسية هي كلمة المرور المستخدمة للوصول إلى الخزنة الخاصة بك. من المهم جدا ً ألا تنسى ذلك. لا توجد طريقة للعثور عليها إذا نسيت.</value> <value>كلمة المرور الرئيسية هي كلمة المرور المستخدمة للوصول إلى الخزانة الخاصة بك. من المهم جدا ً ألا تنسى ذلك. لا توجد طريقة للعثور عليها إذا نسيت.</value>
</data> </data>
<data name="MasterPasswordHint" xml:space="preserve"> <data name="MasterPasswordHint" xml:space="preserve">
<value>فهرس كلمة المرور الرئيسية (اختياري)</value> <value>فهرس كلمة المرور الرئيسية (اختياري)</value>
@@ -604,13 +604,13 @@
<value>تم إنشاء عنصر جديد.</value> <value>تم إنشاء عنصر جديد.</value>
</data> </data>
<data name="NoFavorites" xml:space="preserve"> <data name="NoFavorites" xml:space="preserve">
<value>لا توجد عناصر مفضلة في خزنتك.</value> <value>لا توجد عناصر مفضلة في خزانتك.</value>
</data> </data>
<data name="NoItems" xml:space="preserve"> <data name="NoItems" xml:space="preserve">
<value>لا توجد عناصر في خزنتك.</value> <value>لا توجد عناصر في خزانتك.</value>
</data> </data>
<data name="NoItemsTap" xml:space="preserve"> <data name="NoItemsTap" xml:space="preserve">
<value>لا توجد في خزنتك عناصر لهذا الموقع/التطبيق. انقر لإضافة واحد.</value> <value>لا توجد في خزانتك عناصر لهذا الموقع/التطبيق. انقر لإضافة واحد.</value>
</data> </data>
<data name="NoUsernamePasswordConfigured" xml:space="preserve"> <data name="NoUsernamePasswordConfigured" xml:space="preserve">
<value>لا يحتوي هذا المعرّف على اسم مستخدم أو كلمة مرور تم تكوينها.</value> <value>لا يحتوي هذا المعرّف على اسم مستخدم أو كلمة مرور تم تكوينها.</value>
@@ -644,7 +644,7 @@
<value>هل أنت متأكد من أنك تريد سحق كلمة المرور الموجودة؟</value> <value>هل أنت متأكد من أنك تريد سحق كلمة المرور الموجودة؟</value>
</data> </data>
<data name="PushNotificationAlert" xml:space="preserve"> <data name="PushNotificationAlert" xml:space="preserve">
<value>bitwarden تلقائيا يحافظ على خزنتك في المزامنة باستخدام دفع الإخطارات. للحصول على أفضل تجربة ممكنة، يرجى اختيار "موافق" على مربع الحوار التالي (تفعيل دفع الإخطارات ).</value> <value>Bitwarden يحافظ تلقائيا على خزانتك في المزامنة باستخدام دفع الإخطارات. للحصول على أفضل تجربة ممكنة، يرجى اختيار "سماح" على مربع الحوار التالي عند طلب السماح بدفع الإشعارات.</value>
<comment>Push notifications for apple products</comment> <comment>Push notifications for apple products</comment>
</data> </data>
<data name="RateTheApp" xml:space="preserve"> <data name="RateTheApp" xml:space="preserve">
@@ -660,7 +660,7 @@
<value>إعادة إدخال كلمة المرور الرئيسية</value> <value>إعادة إدخال كلمة المرور الرئيسية</value>
</data> </data>
<data name="SearchVault" xml:space="preserve"> <data name="SearchVault" xml:space="preserve">
<value>البحث في الخزنة</value> <value>البحث في الخزانة</value>
</data> </data>
<data name="Security" xml:space="preserve"> <data name="Security" xml:space="preserve">
<value>الأمان</value> <value>الأمان</value>
@@ -695,7 +695,7 @@
<value>فشل المزامنة.</value> <value>فشل المزامنة.</value>
</data> </data>
<data name="SyncVaultNow" xml:space="preserve"> <data name="SyncVaultNow" xml:space="preserve">
<value>مزامنة الخزنة الآن</value> <value>مزامنة الخزانة الآن</value>
</data> </data>
<data name="TouchID" xml:space="preserve"> <data name="TouchID" xml:space="preserve">
<value>Touch ID معرف اتصال البصمة</value> <value>Touch ID معرف اتصال البصمة</value>
@@ -721,7 +721,7 @@
<value>عرض العنصر</value> <value>عرض العنصر</value>
</data> </data>
<data name="WebVault" xml:space="preserve"> <data name="WebVault" xml:space="preserve">
<value>خزنة الويب Bitwarden</value> <value>خزانة الويب Bitwarden</value>
</data> </data>
<data name="Lost2FAApp" xml:space="preserve"> <data name="Lost2FAApp" xml:space="preserve">
<value>هل تم فقدان تطبيق المصادقة؟</value> <value>هل تم فقدان تطبيق المصادقة؟</value>
@@ -744,14 +744,14 @@
<comment>This is used for the autofill service. ex. "Logins for twitter.com"</comment> <comment>This is used for the autofill service. ex. "Logins for twitter.com"</comment>
</data> </data>
<data name="NoItemsForUri" xml:space="preserve"> <data name="NoItemsForUri" xml:space="preserve">
<value>لا توجد عناصر في خزنتك لـ {0}.</value> <value>لا توجد عناصر في خزانتك لـ {0}.</value>
<comment>This is used for the autofill service. ex. "There are no items in your vault for twitter.com".</comment> <comment>This is used for the autofill service. ex. "There are no items in your vault for twitter.com".</comment>
</data> </data>
<data name="BitwardenAutofillServiceOverlay" xml:space="preserve"> <data name="BitwardenAutofillServiceOverlay" xml:space="preserve">
<value>عند تحديد حقل الإدخال ومشاهدة تراكب الملء التلقائي لـ Bitwarden ، يمكنك النقر عليه لتشغيل خدمة الملء التلقائي.</value> <value>عند تحديد حقل الإدخال ومشاهدة تراكب الملء التلقائي لـ Bitwarden ، يمكنك النقر عليه لتشغيل خدمة الملء التلقائي.</value>
</data> </data>
<data name="BitwardenAutofillServiceNotificationContent" xml:space="preserve"> <data name="BitwardenAutofillServiceNotificationContent" xml:space="preserve">
<value>اضغط على هذا الإشعار لملء معلومات تسجيل الدخول تلقائيًا من خزنتك.</value> <value>اضغط على هذا الإشعار لملء معلومات تسجيل الدخول تلقائيًا من خزانتك.</value>
</data> </data>
<data name="BitwardenAutofillServiceOpenAccessibilitySettings" xml:space="preserve"> <data name="BitwardenAutofillServiceOpenAccessibilitySettings" xml:space="preserve">
<value>فتح إعدادات إمكانية الوصول</value> <value>فتح إعدادات إمكانية الوصول</value>
@@ -778,7 +778,7 @@
<value>الحالة</value> <value>الحالة</value>
</data> </data>
<data name="BitwardenAutofillServiceAlert2" xml:space="preserve"> <data name="BitwardenAutofillServiceAlert2" xml:space="preserve">
<value>أسهل طريقة لإضافة تسجيلات دخول جديدة إلى خزنتك هي من خدمة التعبئة التلقائية Bitwarden تعرف على المزيد حول استخدام خدمة الملء التلقائي لـ Bitwarden عن طريق الانتقال إلى شاشة "إعدادات".</value> <value>أسهل طريقة لإضافة تسجيلات دخول جديدة إلى خزانتك هي من خدمة التعبئة التلقائية Bitwarden تعرف على المزيد حول استخدام خدمة الملء التلقائي لـ Bitwarden عن طريق الانتقال إلى شاشة "إعدادات".</value>
</data> </data>
<data name="Autofill" xml:space="preserve"> <data name="Autofill" xml:space="preserve">
<value>التعبئة التلقائية</value> <value>التعبئة التلقائية</value>
@@ -949,7 +949,7 @@
<value>لا يمكنك استخدام هذه الميزة حتى تقوم بتحديث مفتاح التشفير الخاص بك.</value> <value>لا يمكنك استخدام هذه الميزة حتى تقوم بتحديث مفتاح التشفير الخاص بك.</value>
</data> </data>
<data name="EncryptionKeyMigrationRequiredDescriptionLong" xml:space="preserve"> <data name="EncryptionKeyMigrationRequiredDescriptionLong" xml:space="preserve">
<value>مطلوب ترحيل مفتاح التشفير. الرجاء تسجيل الدخول بواسطة مخزن الويب لتحديث مفتاح التشفير الخاص بك.</value> <value>مطلوب ترحيل مفتاح التشفير. الرجاء تسجيل الدخول بواسطة خزانة الويب لتحديث مفتاح التشفير الخاص بك.</value>
</data> </data>
<data name="LearnMore" xml:space="preserve"> <data name="LearnMore" xml:space="preserve">
<value>اعرف المزيد</value> <value>اعرف المزيد</value>
@@ -984,10 +984,10 @@
<value>رابط الخادم</value> <value>رابط الخادم</value>
</data> </data>
<data name="WebVaultUrl" xml:space="preserve"> <data name="WebVaultUrl" xml:space="preserve">
<value>رابط خادم مخزن الويب</value> <value>رابط خادم خزانة الويب</value>
</data> </data>
<data name="BitwardenAutofillServiceNotificationContentOld" xml:space="preserve"> <data name="BitwardenAutofillServiceNotificationContentOld" xml:space="preserve">
<value>اضغط على هذا الإشعار لعرض العناصر من الخزنة الخاصة بك.</value> <value>اضغط على هذا الإشعار لعرض العناصر من الخزانة الخاصة بك.</value>
</data> </data>
<data name="CustomFields" xml:space="preserve"> <data name="CustomFields" xml:space="preserve">
<value>حقول مخصصة</value> <value>حقول مخصصة</value>
@@ -1149,10 +1149,10 @@
<value>ملء تلقائي باستخدام Bitwarden</value> <value>ملء تلقائي باستخدام Bitwarden</value>
</data> </data>
<data name="VaultIsLocked" xml:space="preserve"> <data name="VaultIsLocked" xml:space="preserve">
<value>الخزنة مقفلة</value> <value>الخزانة مقفلة</value>
</data> </data>
<data name="GoToMyVault" xml:space="preserve"> <data name="GoToMyVault" xml:space="preserve">
<value>اذهب لخزنتي</value> <value>اذهب لخزانتي</value>
</data> </data>
<data name="Collections" xml:space="preserve"> <data name="Collections" xml:space="preserve">
<value>المختارات</value> <value>المختارات</value>
@@ -1195,7 +1195,7 @@
<value>ويندوز هيلو</value> <value>ويندوز هيلو</value>
</data> </data>
<data name="BitwardenCredentialProviderGoToSettings" xml:space="preserve"> <data name="BitwardenCredentialProviderGoToSettings" xml:space="preserve">
<value>We were unable to automatically open the Android credential provider settings menu for you. You can navigate to the credential provider settings menu manually from Android Settings &gt; System &gt; Passwords &amp; accounts &gt; Passwords, passkeys and data services.</value> <value>لم نتمكن من فتح قائمة إعدادات موفر بيانات اعتماد أندرويد تلقائياً لك. يمكنك الانتقال إلى قائمة إعدادات موفر بيانات الاعتماد يدويًا من إعدادات الأندرويد &gt; النظام &gt; كلمات المرور والحسابات &gt; كلمات المرور. مفاتيح المرور وخدمات البيانات.</value>
</data> </data>
<data name="BitwardenAutofillGoToSettings" xml:space="preserve"> <data name="BitwardenAutofillGoToSettings" xml:space="preserve">
<value>لم نتمكن من فتح قائمة إعدادات الملء التلقائي لنظام Android نيابةً عنك. يمكنك الانتقال إلى قائمة إعدادات الملء التلقائي يدويًا من إعدادات Android &amp; GT ؛ نظام &amp; GT. اللغات والمدخلات &amp; GT. متقدم &amp; GT. خدمة الملء التلقائي.</value> <value>لم نتمكن من فتح قائمة إعدادات الملء التلقائي لنظام Android نيابةً عنك. يمكنك الانتقال إلى قائمة إعدادات الملء التلقائي يدويًا من إعدادات Android &amp; GT ؛ نظام &amp; GT. اللغات والمدخلات &amp; GT. متقدم &amp; GT. خدمة الملء التلقائي.</value>
@@ -1301,7 +1301,7 @@
<value>نوصي بتعطيل أي تطبيقات أخرى من تطبيقات التعبئة التلقائية تحت الإعدادات إذا كنت لا تخطط لاستخدامها.</value> <value>نوصي بتعطيل أي تطبيقات أخرى من تطبيقات التعبئة التلقائية تحت الإعدادات إذا كنت لا تخطط لاستخدامها.</value>
</data> </data>
<data name="BitwardenAutofillDescription" xml:space="preserve"> <data name="BitwardenAutofillDescription" xml:space="preserve">
<value>الوصول إلى الخزن, الخاص, بك مباشرة من لوحة المفاتيح الخاصة بك لملء كلمات المرور تلقائياً بسرعة.</value> <value>الوصول إلى الخزانة الخاصة بك مباشرة من لوحة المفاتيح الخاصة بك لملء كلمات المرور تلقائياً بسرعة.</value>
</data> </data>
<data name="AutofillTurnOn" xml:space="preserve"> <data name="AutofillTurnOn" xml:space="preserve">
<value>لتمكين التعبئة التلقائية لكلمة المرور على جهازك، اتبع هذه التعليمات:</value> <value>لتمكين التعبئة التلقائية لكلمة المرور على جهازك، اتبع هذه التعليمات:</value>
@@ -1325,7 +1325,7 @@
<value>تعبئة تلقائية لكلمة المرور</value> <value>تعبئة تلقائية لكلمة المرور</value>
</data> </data>
<data name="BitwardenAutofillAlert2" xml:space="preserve"> <data name="BitwardenAutofillAlert2" xml:space="preserve">
<value>أسهل طريقة لإضافة تسجيلات دخول جديدة إلى خزنتك هي من خدمة التعبئة التلقائية Bitwarden. تعرف على المزيد حول استخدام خدمة الملء التلقائي لـ Bitwarden عن طريق الانتقال إلى شاشة "إعدادات".</value> <value>أسهل طريقة لإضافة تسجيلات دخول جديدة إلى خزانتك هي من خدمة التعبئة التلقائية Bitwarden. تعرف على المزيد حول استخدام خدمة الملء التلقائي لـ Bitwarden عن طريق الانتقال إلى شاشة "إعدادات".</value>
</data> </data>
<data name="InvalidEmail" xml:space="preserve"> <data name="InvalidEmail" xml:space="preserve">
<value>عنوان البريد الإلكتروني غير صالح.</value> <value>عنوان البريد الإلكتروني غير صالح.</value>
@@ -1468,10 +1468,10 @@
<comment>A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing.</comment> <comment>A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing.</comment>
</data> </data>
<data name="LearnOrgConfirmation" xml:space="preserve"> <data name="LearnOrgConfirmation" xml:space="preserve">
<value>يسمح لك Bitwarden بمشاركة عناصر خزنتك مع الآخرين باستخدام حساب المؤسسة. هل ترغب في زيارة موقع bitwarden.com لمعرفة المزيد؟</value> <value>يسمح لك Bitwarden بمشاركة عناصر خزانتك مع الآخرين باستخدام حساب المؤسسة. هل ترغب في زيارة موقع bitwarden.com لمعرفة المزيد؟</value>
</data> </data>
<data name="ExportVault" xml:space="preserve"> <data name="ExportVault" xml:space="preserve">
<value>تصدير الخزنة</value> <value>تصدير الخزانة</value>
</data> </data>
<data name="LockNow" xml:space="preserve"> <data name="LockNow" xml:space="preserve">
<value>إقفل الآن</value> <value>إقفل الآن</value>
@@ -1496,13 +1496,13 @@
<comment>ex: Logged in as user@example.com on bitwarden.com.</comment> <comment>ex: Logged in as user@example.com on bitwarden.com.</comment>
</data> </data>
<data name="VaultLockedMasterPassword" xml:space="preserve"> <data name="VaultLockedMasterPassword" xml:space="preserve">
<value>خزنتك مقفلة. تحقق من كلمة المرور الرئيسية للمتابعة.</value> <value>خزانتك مقفلة. تحقق من كلمة المرور الرئيسية للمتابعة.</value>
</data> </data>
<data name="VaultLockedPIN" xml:space="preserve"> <data name="VaultLockedPIN" xml:space="preserve">
<value>خزنتك مقفلة. تحقق من رمز PIN الخاص بك للمتابعة.</value> <value>خزانتك مقفلة. تحقق من رمز PIN الخاص بك للمتابعة.</value>
</data> </data>
<data name="VaultLockedIdentity" xml:space="preserve"> <data name="VaultLockedIdentity" xml:space="preserve">
<value>خزنتك مقفلة. تحقق من هويتك للمتابعة.</value> <value>خزانتك مقفلة. تحقق من هويتك للمتابعة.</value>
</data> </data>
<data name="Dark" xml:space="preserve"> <data name="Dark" xml:space="preserve">
<value>داكن</value> <value>داكن</value>
@@ -1586,13 +1586,13 @@
<value>اطلب إضافة تسجيل الدخول</value> <value>اطلب إضافة تسجيل الدخول</value>
</data> </data>
<data name="AskToAddLoginDescription" xml:space="preserve"> <data name="AskToAddLoginDescription" xml:space="preserve">
<value>اطلب إضافة عنصر إذا لم يتم العثور عليه في خزنتك.</value> <value>اطلب إضافة عنصر إذا لم يتم العثور عليه في خزانتك.</value>
</data> </data>
<data name="OnRestart" xml:space="preserve"> <data name="OnRestart" xml:space="preserve">
<value>عند إعادة تشغيل التطبيق</value> <value>عند إعادة تشغيل التطبيق</value>
</data> </data>
<data name="AutofillServiceNotEnabled" xml:space="preserve"> <data name="AutofillServiceNotEnabled" xml:space="preserve">
<value>التعبئة التلقائية تجعل من السهل الوصول بشكل آمن إلى خزنة Bitwarden الخاصة بك من مواقع الويب والتطبيقات الأخرى. يبدو أنك لم تقم بتمكين خدمة التعبئة التلقائية لـ Bitwarden. تمكين التعبئة التلقائية لـ Bitwarden من شاشة "الإعدادات".</value> <value>التعبئة التلقائية تجعل من السهل الوصول بشكل آمن إلى خزانة Bitwarden الخاصة بك من مواقع الويب والتطبيقات الأخرى. يبدو أنك لم تقم بتمكين خدمة التعبئة التلقائية لـ Bitwarden. تمكين التعبئة التلقائية لـ Bitwarden من شاشة "الإعدادات".</value>
</data> </data>
<data name="ThemeAppliedOnRestart" xml:space="preserve"> <data name="ThemeAppliedOnRestart" xml:space="preserve">
<value>سيتم تطبيق تغييرات السمة الخاصة بك عند إعادة تشغيل التطبيق.</value> <value>سيتم تطبيق تغييرات السمة الخاصة بك عند إعادة تشغيل التطبيق.</value>
@@ -1650,7 +1650,7 @@
<value>صيغة الملف</value> <value>صيغة الملف</value>
</data> </data>
<data name="ExportVaultMasterPasswordDescription" xml:space="preserve"> <data name="ExportVaultMasterPasswordDescription" xml:space="preserve">
<value>أدخل كلمة المرور الرئيسية لتصدير بيانات خزنتك.</value> <value>أدخل كلمة المرور الرئيسية لتصدير بيانات خزانتك.</value>
</data> </data>
<data name="SendVerificationCodeToEmail" xml:space="preserve"> <data name="SendVerificationCodeToEmail" xml:space="preserve">
<value>إرسال رمز التحقق إلى بريدك الإلكتروني</value> <value>إرسال رمز التحقق إلى بريدك الإلكتروني</value>
@@ -1662,7 +1662,7 @@
<value>قم بتأكيد هويتك للمتابعة.</value> <value>قم بتأكيد هويتك للمتابعة.</value>
</data> </data>
<data name="ExportVaultWarning" xml:space="preserve"> <data name="ExportVaultWarning" xml:space="preserve">
<value>يحتوي هذا التصدير على بيانات خزنتك بتنسيق غير مشفر. لا يجب عليك تخزين أو إرسال الملف الذي تم تصديره عبر قنوات غير آمنة (مثل البريد الإلكتروني). احذفه مباشرة بعد انتهائك من استخدامه.</value> <value>يحتوي هذا التصدير على بيانات خزانتك بتنسيق غير مشفر. لا يجب عليك تخزين أو إرسال الملف الذي تم تصديره عبر قنوات غير آمنة (مثل البريد الإلكتروني). احذفه مباشرة بعد انتهائك من استخدامه.</value>
</data> </data>
<data name="EncExportKeyWarning" xml:space="preserve"> <data name="EncExportKeyWarning" xml:space="preserve">
<value>يقوم هذا التصدير بتشفير بياناتك باستخدام مفتاح تشفير حسابك. إذا قمت بتدوير مفتاح تشفير حسابك يجب عليك التصدير مرة أخرى لأنك لن تتمكن من فك تشفير ملف التصدير هذا.</value> <value>يقوم هذا التصدير بتشفير بياناتك باستخدام مفتاح تشفير حسابك. إذا قمت بتدوير مفتاح تشفير حسابك يجب عليك التصدير مرة أخرى لأنك لن تتمكن من فك تشفير ملف التصدير هذا.</value>
@@ -1671,17 +1671,17 @@
<value>مفاتيح تشفير الحساب فريدة من نوعها لكل حساب مستخدم Bitwarden، لذلك لا يمكنك استيراد تصدير مشفر إلى حساب آخر.</value> <value>مفاتيح تشفير الحساب فريدة من نوعها لكل حساب مستخدم Bitwarden، لذلك لا يمكنك استيراد تصدير مشفر إلى حساب آخر.</value>
</data> </data>
<data name="ExportVaultConfirmationTitle" xml:space="preserve"> <data name="ExportVaultConfirmationTitle" xml:space="preserve">
<value>تأكيد تصدير الخزنة</value> <value>تأكيد تصدير الخزانة</value>
<comment>Title for the alert to confirm vault exports.</comment> <comment>Title for the alert to confirm vault exports.</comment>
</data> </data>
<data name="Warning" xml:space="preserve"> <data name="Warning" xml:space="preserve">
<value>تحذير</value> <value>تحذير</value>
</data> </data>
<data name="ExportVaultFailure" xml:space="preserve"> <data name="ExportVaultFailure" xml:space="preserve">
<value>كانت هناك مشكلة في تصدير خزنتك. إذا استمرت المشكلة، ستحتاج إلى التصدير من خزانة الويب.</value> <value>كانت هناك مشكلة في تصدير خزانتك. إذا استمرت المشكلة، ستحتاج إلى التصدير من خزانة الويب.</value>
</data> </data>
<data name="ExportVaultSuccess" xml:space="preserve"> <data name="ExportVaultSuccess" xml:space="preserve">
<value>تم تصدير الخزنة بنجاح</value> <value>تم تصدير الخزانة بنجاح</value>
</data> </data>
<data name="Clone" xml:space="preserve"> <data name="Clone" xml:space="preserve">
<value>استنساخ</value> <value>استنساخ</value>
@@ -1695,7 +1695,7 @@
<comment>Button text for an open operation (verb).</comment> <comment>Button text for an open operation (verb).</comment>
</data> </data>
<data name="UnableToSaveAttachment" xml:space="preserve"> <data name="UnableToSaveAttachment" xml:space="preserve">
<value>كانت هناك مشكلة في حفظ هذا المرفق. إذا استمرت المشكلة ، يمكنك حفظها من خزنة الويب.</value> <value>كانت هناك مشكلة في حفظ هذا المرفق. إذا استمرت المشكلة ، يمكنك حفظها من خزانة الويب.</value>
</data> </data>
<data name="SaveAttachmentSuccess" xml:space="preserve"> <data name="SaveAttachmentSuccess" xml:space="preserve">
<value>تم حفظ المرفق بنجاح</value> <value>تم حفظ المرفق بنجاح</value>
@@ -1756,7 +1756,7 @@
<value>تمكين المزامنة عند التحديث</value> <value>تمكين المزامنة عند التحديث</value>
</data> </data>
<data name="EnableSyncOnRefreshDescription" xml:space="preserve"> <data name="EnableSyncOnRefreshDescription" xml:space="preserve">
<value>مزامنة الخزنة مع إيماءة السحب لأسفل.</value> <value>مزامنة الخزانة مع إيماءة السحب لأسفل.</value>
</data> </data>
<data name="LogInSso" xml:space="preserve"> <data name="LogInSso" xml:space="preserve">
<value>تسجيل الدخول الفردي للمؤسسة</value> <value>تسجيل الدخول الفردي للمؤسسة</value>
@@ -1774,7 +1774,7 @@
<value>تعيين كلمة المرور الرئيسية</value> <value>تعيين كلمة المرور الرئيسية</value>
</data> </data>
<data name="SetMasterPasswordSummary" xml:space="preserve"> <data name="SetMasterPasswordSummary" xml:space="preserve">
<value>من أجل إكمال تسجيل الدخول باستخدام SSO، يرجى تعيين كلمة مرور رئيسية للوصول وحماية خزنتك.</value> <value>من أجل إكمال تسجيل الدخول باستخدام SSO، يرجى تعيين كلمة مرور رئيسية للوصول وحماية خزانتك.</value>
</data> </data>
<data name="MasterPasswordPolicyInEffect" xml:space="preserve"> <data name="MasterPasswordPolicyInEffect" xml:space="preserve">
<value>1 - تتطلب سياسة واحدة أو أكثر من سياسات المؤسسة كلمة مرورك الرئيسية لتلبية المتطلبات التالية:</value> <value>1 - تتطلب سياسة واحدة أو أكثر من سياسات المؤسسة كلمة مرورك الرئيسية لتلبية المتطلبات التالية:</value>
@@ -1823,7 +1823,7 @@
<value>يحتاج Bitwarden إلى الاهتمام - قم بتمكين "السحب" في "خدمات الملء التلقائي" من إعدادات Bitwarden</value> <value>يحتاج Bitwarden إلى الاهتمام - قم بتمكين "السحب" في "خدمات الملء التلقائي" من إعدادات Bitwarden</value>
</data> </data>
<data name="PasskeyManagement" xml:space="preserve"> <data name="PasskeyManagement" xml:space="preserve">
<value>Passkey management</value> <value>إدارة مفتاح المرور</value>
</data> </data>
<data name="AutofillServices" xml:space="preserve"> <data name="AutofillServices" xml:space="preserve">
<value>خدمات التعبئة التلقائية</value> <value>خدمات التعبئة التلقائية</value>
@@ -2138,16 +2138,16 @@
<value>هذه المؤسسة لديها سياسة الشركة التي ستقوم تلقائياً بتسجيلك في إعادة تعيين كلمة المرور. التسجيل سيسمح لمسؤولي المؤسسة بتغيير كلمة المرور الرئيسية الخاصة بك.</value> <value>هذه المؤسسة لديها سياسة الشركة التي ستقوم تلقائياً بتسجيلك في إعادة تعيين كلمة المرور. التسجيل سيسمح لمسؤولي المؤسسة بتغيير كلمة المرور الرئيسية الخاصة بك.</value>
</data> </data>
<data name="VaultTimeoutPolicyInEffect" xml:space="preserve"> <data name="VaultTimeoutPolicyInEffect" xml:space="preserve">
<value>سياسات مؤسستك تؤثر على مهلة الخزنة الخاص بك. الحد الأقصى المسموح به لمهلة الخزنة هو {0} ساعة و {1} دقيقة</value> <value>سياسات مؤسستك تؤثر على مهلة الخزانة الخاص بك. الحد الأقصى المسموح به لمهلة الخزانة هو {0} ساعة و {1} دقيقة.</value>
</data> </data>
<data name="VaultTimeoutPolicyWithActionInEffect" xml:space="preserve"> <data name="VaultTimeoutPolicyWithActionInEffect" xml:space="preserve">
<value>سياسات مؤسستك تؤثر على مهلة خزنتك. الحد الأقصى المسموح به لمهلة الخزنة هو {0} ساعة(ساعات) و {1} دقيقة(دقائق). يتم تعيين إجراء مهلة المخزن الخاص بك إلى {2}.</value> <value>سياسات مؤسستك تؤثر على مهلة خزانتك. الحد الأقصى المسموح به لمهلة الخزنة هو {0} ساعة(ساعات) و {1} دقيقة(دقائق). يتم تعيين إجراء مهلة المخزن الخاص بك إلى {2}.</value>
</data> </data>
<data name="VaultTimeoutActionPolicyInEffect" xml:space="preserve"> <data name="VaultTimeoutActionPolicyInEffect" xml:space="preserve">
<value>سياسات مؤسستك قامت بتعيين إجراء مهلة خزنتك إلى {0}.</value> <value>سياسات مؤسستك قامت بتعيين إجراء مهلة خزانتك إلى {0}.</value>
</data> </data>
<data name="VaultTimeoutToLarge" xml:space="preserve"> <data name="VaultTimeoutToLarge" xml:space="preserve">
<value>مهلة خزنتك تتجاوز القيود التي تضعها مؤسستك.</value> <value>مهلة خزانتك تتجاوز القيود التي تضعها مؤسستك.</value>
</data> </data>
<data name="DisablePersonalVaultExportPolicyInEffect" xml:space="preserve"> <data name="DisablePersonalVaultExportPolicyInEffect" xml:space="preserve">
<value>واحدة أو أكثر من سياسات المؤسسة تمنعك من تصدير خزانتك الشخصية.</value> <value>واحدة أو أكثر من سياسات المؤسسة تمنعك من تصدير خزانتك الشخصية.</value>
@@ -2258,16 +2258,16 @@
<value>كلمة المرور مخفية، انقر للإظهار.</value> <value>كلمة المرور مخفية، انقر للإظهار.</value>
</data> </data>
<data name="FilterByVault" xml:space="preserve"> <data name="FilterByVault" xml:space="preserve">
<value>تصفية العناصر حسب الخزنات</value> <value>تصفية العناصر حسب الخزانات</value>
</data> </data>
<data name="AllVaults" xml:space="preserve"> <data name="AllVaults" xml:space="preserve">
<value>جميع الخزنات</value> <value>جميع الخزانات</value>
</data> </data>
<data name="Vaults" xml:space="preserve"> <data name="Vaults" xml:space="preserve">
<value>الخزنات</value> <value>الخزانات</value>
</data> </data>
<data name="VaultFilterDescription" xml:space="preserve"> <data name="VaultFilterDescription" xml:space="preserve">
<value>الخزنة: {0}</value> <value>الخزانة: {0}</value>
</data> </data>
<data name="All" xml:space="preserve"> <data name="All" xml:space="preserve">
<value>الكل</value> <value>الكل</value>
@@ -2307,7 +2307,7 @@
حدد إضافة TOTP لتخزين المفتاح بأمان</value> حدد إضافة TOTP لتخزين المفتاح بأمان</value>
</data> </data>
<data name="NeverLockWarning" xml:space="preserve"> <data name="NeverLockWarning" xml:space="preserve">
<value>تعيين خيارات قفل الخاص بك إلى "مطلقا" يبقي خزنتك متاحةً لأي شخص لديه حق الوصول إلى جهازك. إذا كنت تستخدم هذا الخيار، يجب أن تتأكد من الحفاظ على حماية جهازك بشكل صحيح.</value> <value>تعيين خيارات قفل الخاص بك إلى "مطلقا" يبقي خزانتك متاحةً لأي شخص لديه حق الوصول إلى جهازك. إذا كنت تستخدم هذا الخيار، يجب أن تتأكد من الحفاظ على حماية جهازك بشكل صحيح.</value>
</data> </data>
<data name="EnvironmentPageUrlsError" xml:space="preserve"> <data name="EnvironmentPageUrlsError" xml:space="preserve">
<value>واحد أو أكثر من عناوين URL التي تم إدخالها غير صالحة. الرجاء مراجعتها ومحاولة الحفظ مرة أخرى.</value> <value>واحد أو أكثر من عناوين URL التي تم إدخالها غير صالحة. الرجاء مراجعتها ومحاولة الحفظ مرة أخرى.</value>
@@ -2516,7 +2516,7 @@
<value>تم إرسال إشعار إلى جهازك.</value> <value>تم إرسال إشعار إلى جهازك.</value>
</data> </data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve"> <data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>الرجاء التأكد من أن الخزنة الخاصة بك غير مقفلة وأن عبارة بصمة الإصبع تتطابق على الجهاز الآخر.</value> <value>الرجاء التأكد من أن الخزانة الخاصة بك غير مقفلة وأن عبارة بصمة الإصبع تتطابق على الجهاز الآخر.</value>
</data> </data>
<data name="ResendNotification" xml:space="preserve"> <data name="ResendNotification" xml:space="preserve">
<value>إعادة إرسال الإشعار</value> <value>إعادة إرسال الإشعار</value>
@@ -2627,7 +2627,7 @@
<value>المنطقة</value> <value>المنطقة</value>
</data> </data>
<data name="UpdateWeakMasterPasswordWarning" xml:space="preserve"> <data name="UpdateWeakMasterPasswordWarning" xml:space="preserve">
<value>كلمة المرور الرئيسية الخاصة بك لا تفي بواحدة أو أكثر من سياسات مؤسستك. من أجل الوصول إلى الخزنة، يجب عليك تحديث كلمة المرور الرئيسية الآن. سيتم تسجيل خروجك من الجلسة الحالية، مما يتطلب منك تسجيل الدخول مرة أخرى. وقد تظل الجلسات النشطة على أجهزة أخرى نشطة لمدة تصل إلى ساعة واحدة.</value> <value>كلمة المرور الرئيسية الخاصة بك لا تفي بواحدة أو أكثر من سياسات مؤسستك. من أجل الوصول إلى الخزانة، يجب عليك تحديث كلمة المرور الرئيسية الآن. سيتم تسجيل خروجك من الجلسة الحالية، مما يتطلب منك تسجيل الدخول مرة أخرى. وقد تظل الجلسات النشطة على أجهزة أخرى نشطة لمدة تصل إلى ساعة واحدة.</value>
</data> </data>
<data name="CurrentMasterPassword" xml:space="preserve"> <data name="CurrentMasterPassword" xml:space="preserve">
<value>كلمة المرور الرئيسية الحالية</value> <value>كلمة المرور الرئيسية الحالية</value>
@@ -2702,7 +2702,7 @@
<value>تسجيل الدخول كـ {0}</value> <value>تسجيل الدخول كـ {0}</value>
</data> </data>
<data name="VaultTimeoutActionChangedToLogOut" xml:space="preserve"> <data name="VaultTimeoutActionChangedToLogOut" xml:space="preserve">
<value>تَغيير إجراء مهلة المخزن لتسجيل الخروج</value> <value>تَغيير إجراء مهلة خزانتك لتسجيل الخروج</value>
</data> </data>
<data name="BlockAutoFill" xml:space="preserve"> <data name="BlockAutoFill" xml:space="preserve">
<value>حظر التعبئة التلقائية</value> <value>حظر التعبئة التلقائية</value>
@@ -2760,7 +2760,7 @@
<value>جارٍ تسجيل الدخول</value> <value>جارٍ تسجيل الدخول</value>
</data> </data>
<data name="Vault" xml:space="preserve"> <data name="Vault" xml:space="preserve">
<value>الخزنة</value> <value>الخزانة</value>
</data> </data>
<data name="Appearance" xml:space="preserve"> <data name="Appearance" xml:space="preserve">
<value>المظهر</value> <value>المظهر</value>
@@ -2809,7 +2809,7 @@
<value>{0} ساعات</value> <value>{0} ساعات</value>
</data> </data>
<data name="PasskeyManagementExplanationLong" xml:space="preserve"> <data name="PasskeyManagementExplanationLong" xml:space="preserve">
<value>Use Bitwarden to save new passkeys and log in with passkeys stored in your vault.</value> <value>استخدم Bitwarden لحفظ مفاتيح المرور الجديدة وتسجيل الدخول باستخدام مفاتيح المرور المخزنة في خزانتك.</value>
</data> </data>
<data name="AutofillServicesExplanationLong" xml:space="preserve"> <data name="AutofillServicesExplanationLong" xml:space="preserve">
<value>يتم استخدام إطار التعبئة التلقائية لأندرويد للمساعدة في ملء معلومات تسجيل الدخول في تطبيقات أخرى على جهازك.</value> <value>يتم استخدام إطار التعبئة التلقائية لأندرويد للمساعدة في ملء معلومات تسجيل الدخول في تطبيقات أخرى على جهازك.</value>
@@ -2840,7 +2840,7 @@
<value>هل تريد المتابعة إلى متجر التطبيقات؟</value> <value>هل تريد المتابعة إلى متجر التطبيقات؟</value>
</data> </data>
<data name="ContinueToDeviceSettings" xml:space="preserve"> <data name="ContinueToDeviceSettings" xml:space="preserve">
<value>Continue to device Settings?</value> <value>هل تريد المتابعة إلى إعدادات الجهاز؟</value>
</data> </data>
<data name="TwoStepLoginDescriptionLong" xml:space="preserve"> <data name="TwoStepLoginDescriptionLong" xml:space="preserve">
<value>اجعل حسابك أكثر أمنا من خلال إعداد تسجيل الدخول بخطوتين في تطبيق Bitwarden على شبكة الإنترنت.</value> <value>اجعل حسابك أكثر أمنا من خلال إعداد تسجيل الدخول بخطوتين في تطبيق Bitwarden على شبكة الإنترنت.</value>
@@ -2865,7 +2865,7 @@
<value>استكشف المزيد من الميزات لحساب Bitwarden الخاص بك على تطبيق الويب.</value> <value>استكشف المزيد من الميزات لحساب Bitwarden الخاص بك على تطبيق الويب.</value>
</data> </data>
<data name="LearnAboutOrganizationsDescriptionLong" xml:space="preserve"> <data name="LearnAboutOrganizationsDescriptionLong" xml:space="preserve">
<value>يتيح لك Bitwarden مشاركة عناصر خزنتك مع الآخرين باستخدام حساب المؤسسة. تعرف على المزيد على موقع bitwarden.com على شبكة الإنترنت.</value> <value>يتيح لك Bitwarden مشاركة عناصر خزانتك مع الآخرين باستخدام حساب المؤسسة. تعرف على المزيد على موقع bitwarden.com على شبكة الإنترنت.</value>
</data> </data>
<data name="RateAppDescriptionLong" xml:space="preserve"> <data name="RateAppDescriptionLong" xml:space="preserve">
<value>ساعد الآخرين في معرفة ما إذا كان Bitwarden مناسبا لهم. قم بزيارة متجر التطبيقات وترك التقييم الآن.</value> <value>ساعد الآخرين في معرفة ما إذا كان Bitwarden مناسبا لهم. قم بزيارة متجر التطبيقات وترك التقييم الآن.</value>
@@ -2893,25 +2893,25 @@
<value>أعدنّ ميزة إلغاء القُفْل لتغيير إجراء مهلة المخزن الخاص بك.</value> <value>أعدنّ ميزة إلغاء القُفْل لتغيير إجراء مهلة المخزن الخاص بك.</value>
</data> </data>
<data name="ChooseALoginToSaveThisPasskeyTo" xml:space="preserve"> <data name="ChooseALoginToSaveThisPasskeyTo" xml:space="preserve">
<value>Choose a login to save this passkey to</value> <value>اختر تسجيل الدخول لحفظ مفتاح المرور هذا إلى</value>
</data> </data>
<data name="SavePasskeyAsNewLogin" xml:space="preserve"> <data name="SavePasskeyAsNewLogin" xml:space="preserve">
<value>Save passkey as new login</value> <value>حفظ مفتاح المرور كتسجيل دخول جديد</value>
</data> </data>
<data name="SavePasskey" xml:space="preserve"> <data name="SavePasskey" xml:space="preserve">
<value>Save passkey</value> <value>حفظ مفتاح المرور</value>
</data> </data>
<data name="PasskeysForX" xml:space="preserve"> <data name="PasskeysForX" xml:space="preserve">
<value>Passkeys for {0}</value> <value>مفاتيح المرور لـ {0}</value>
</data> </data>
<data name="PasswordsForX" xml:space="preserve"> <data name="PasswordsForX" xml:space="preserve">
<value>Passwords for {0}</value> <value>كلمات المرور لـ {0}</value>
</data> </data>
<data name="OverwritePasskey" xml:space="preserve"> <data name="OverwritePasskey" xml:space="preserve">
<value>Overwrite passkey?</value> <value>الكتابة فوق مفتاح المرور؟</value>
</data> </data>
<data name="ThisItemAlreadyContainsAPasskeyAreYouSureYouWantToOverwriteTheCurrentPasskey" xml:space="preserve"> <data name="ThisItemAlreadyContainsAPasskeyAreYouSureYouWantToOverwriteTheCurrentPasskey" xml:space="preserve">
<value>This item already contains a passkey. Are you sure you want to overwrite the current passkey?</value> <value>هذا العنصر يحتوي بالفعل على مفتاح مرور. هل أنت متأكد من أنك تريد الكتابة فوق مفتاح المرور الحالي؟</value>
</data> </data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve"> <data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>تسجيل الدخول لـ Duo من خطوتين مطلوب لحسابك. </value> <value>تسجيل الدخول لـ Duo من خطوتين مطلوب لحسابك. </value>
@@ -2923,71 +2923,74 @@
<value>تشغيل Duo</value> <value>تشغيل Duo</value>
</data> </data>
<data name="VerificationRequiredByX" xml:space="preserve"> <data name="VerificationRequiredByX" xml:space="preserve">
<value>Verification required by {0}</value> <value>التحقق مطلوب من قِبَل {0}</value>
</data> </data>
<data name="VerificationRequiredForThisActionSetUpAnUnlockMethodInBitwardenToContinue" xml:space="preserve"> <data name="VerificationRequiredForThisActionSetUpAnUnlockMethodInBitwardenToContinue" xml:space="preserve">
<value>Verification required for this action. Set up an unlock method in Bitwarden to continue.</value> <value>التحقق مطلوب لهذا الإجراء. قم بإعداد طريقة إلغاء القفل في Bitwarden للمتابعة.</value>
</data> </data>
<data name="ErrorCreatingPasskey" xml:space="preserve"> <data name="ErrorCreatingPasskey" xml:space="preserve">
<value>Error creating passkey</value> <value>خطأ في إنشاء مفتاح المرور</value>
</data> </data>
<data name="ErrorReadingPasskey" xml:space="preserve"> <data name="ErrorReadingPasskey" xml:space="preserve">
<value>Error reading passkey</value> <value>خطأ في قراءة مفتاح المرور</value>
</data> </data>
<data name="ThereWasAProblemCreatingAPasskeyForXTryAgainLater" xml:space="preserve"> <data name="ThereWasAProblemCreatingAPasskeyForXTryAgainLater" xml:space="preserve">
<value>There was a problem creating a passkey for {0}. Try again later.</value> <value>حدثت مشكلة في إنشاء مفتاح مرور لـ {0}. حاول مرة أخرى لاحقاً.</value>
<comment>The parameter is the RpId</comment> <comment>The parameter is the RpId</comment>
</data> </data>
<data name="ThereWasAProblemReadingAPasskeyForXTryAgainLater" xml:space="preserve"> <data name="ThereWasAProblemReadingAPasskeyForXTryAgainLater" xml:space="preserve">
<value>There was a problem reading your passkey for {0}. Try again later.</value> <value>حدثت مشكلة في قراءة مفتاح المرور الخاص بك لـ {0}. حاول مرة أخرى لاحقاً.</value>
<comment>The parameter is the RpId</comment> <comment>The parameter is the RpId</comment>
</data> </data>
<data name="VerifyingIdentityEllipsis" xml:space="preserve"> <data name="VerifyingIdentityEllipsis" xml:space="preserve">
<value>Verifying identity...</value> <value>التحقق من الهوية...</value>
</data> </data>
<data name="Passwords" xml:space="preserve"> <data name="Passwords" xml:space="preserve">
<value>Passwords</value> <value>كلمات المرور</value>
</data> </data>
<data name="UnknownAccount" xml:space="preserve"> <data name="UnknownAccount" xml:space="preserve">
<value>Unknown account</value> <value>حساب غير معروف</value>
</data> </data>
<data name="SetUpAutofill" xml:space="preserve"> <data name="SetUpAutofill" xml:space="preserve">
<value>Set up auto-fill</value> <value>إعداد الملء التلقائي</value>
</data> </data>
<data name="GetInstantAccessToYourPasswordsAndPasskeys" xml:space="preserve"> <data name="GetInstantAccessToYourPasswordsAndPasskeys" xml:space="preserve">
<value>Get instant access to your passwords and passkeys!</value> <value>احصل على الوصول الفوري إلى كلمات المرور ومفاتيح المرور الخاصة بك!</value>
</data> </data>
<data name="SetUpAutoFillDescriptionLong" xml:space="preserve"> <data name="SetUpAutoFillDescriptionLong" xml:space="preserve">
<value>To set up password auto-fill and passkey management, set Bitwarden as your preferred provider in the iOS Settings.</value> <value>لإعداد ملء كلمة المرور التلقائي وإدارة مفتاح المرور، عيّن Bitwarden كموفر مفضل لك في إعدادات iOS.</value>
</data> </data>
<data name="FirstDotGoToYourDeviceSettingsPasswordsPasswordOptions" xml:space="preserve"> <data name="FirstDotGoToYourDeviceSettingsPasswordsPasswordOptions" xml:space="preserve">
<value>1. Go to your device's Settings &gt; Passwords &gt; Password Options</value> <value>1. انتقل إلى إعدادات جهازك &gt; كلمات المرور &gt; خيارات كلمة المرور</value>
</data> </data>
<data name="SecondDotTurnOnAutoFill" xml:space="preserve"> <data name="SecondDotTurnOnAutoFill" xml:space="preserve">
<value>2. Turn on AutoFill</value> <value>2. تشغيل التعبئة التلقائية</value>
</data> </data>
<data name="ThirdDotSelectBitwardenToUseForPasswordsAndPasskeys" xml:space="preserve"> <data name="ThirdDotSelectBitwardenToUseForPasswordsAndPasskeys" xml:space="preserve">
<value>3. Select "Bitwarden" to use for passwords and passkeys</value> <value>3. حدد "Bitwarden" لاستخدامه لكلمات المرور ومفاتيح المرور</value>
</data> </data>
<data name="YourPasskeyWillBeSavedToYourBitwardenVault" xml:space="preserve"> <data name="YourPasskeyWillBeSavedToYourBitwardenVault" xml:space="preserve">
<value>Your passkey will be saved to your Bitwarden vault</value> <value>سيتم حفظ مفتاح المرور الخاص بك في مخزن Bitwarden الخاص بك</value>
</data> </data>
<data name="YourPasskeyWillBeSavedToYourBitwardenVaultForX" xml:space="preserve"> <data name="YourPasskeyWillBeSavedToYourBitwardenVaultForX" xml:space="preserve">
<value>Your passkey will be saved to your Bitwarden vault for {0}</value> <value>سيتم حفظ مفتاح المرور الخاص بك في مخزن Bitwarden الخاص بك لـ {0}</value>
</data>
<data name="OrganizationUnassignedItemsMessageUSEUDescriptionLong" xml:space="preserve">
<value>Unassigned organization items are no longer visible in the All Vaults view and only accessible via the Admin Console. Assign these items to a collection from the Admin Console to make them visible.</value>
</data>
<data name="OrganizationUnassignedItemsMessageSelfHost041624DescriptionLong" xml:space="preserve">
<value>On May 16, 2024, unassigned organization items will no longer be visible in the All Vaults view and only accessible via the Admin Console. Assign these items to a collection from the Admin Console to make them visible.</value>
</data>
<data name="RemindMeLater" xml:space="preserve">
<value>Remind me later</value>
</data>
<data name="Notice" xml:space="preserve">
<value>Notice</value>
</data> </data>
<data name="PasskeysNotSupportedForThisApp" xml:space="preserve"> <data name="PasskeysNotSupportedForThisApp" xml:space="preserve">
<value>Passkeys not supported for this app</value> <value>مفاتيح المرور غير مدعومة لهذا التطبيق</value>
</data>
<data name="PasskeyOperationFailedBecauseBrowserIsNotPrivileged" xml:space="preserve">
<value>فشلت عملية مفتاح المرور لأن المتصفح ليس لديه امتيازات</value>
</data>
<data name="PasskeyOperationFailedBecauseBrowserSignatureDoesNotMatch" xml:space="preserve">
<value>فشلت عملية مفتاح المرور لأن توقيع المتصفح غير مطابق</value>
</data>
<data name="PasskeyOperationFailedBecauseOfMissingAssetLinks" xml:space="preserve">
<value>فشلت عملية مفتاح المرور بسبب عدم وجود روابط أصلية</value>
</data>
<data name="PasskeyOperationFailedBecauseAppNotFoundInAssetLinks" xml:space="preserve">
<value>فشلت عملية مفتاح المرور لأن التطبيق لم يتم العثور عليه في روابط أصلية</value>
</data>
<data name="PasskeyOperationFailedBecauseAppCouldNotBeVerified" xml:space="preserve">
<value>فشلت عملية مفتاح المرور لأنه تعذر التحقق من التطبيق</value>
</data> </data>
</root> </root>

View File

@@ -296,7 +296,7 @@
<comment>Text to define that there are more options things to see.</comment> <comment>Text to define that there are more options things to see.</comment>
</data> </data>
<data name="MyVault" xml:space="preserve"> <data name="MyVault" xml:space="preserve">
<value>Anbarım</value> <value>Seyfim</value>
<comment>The title for the vault page.</comment> <comment>The title for the vault page.</comment>
</data> </data>
<data name="Authenticator" xml:space="preserve"> <data name="Authenticator" xml:space="preserve">
@@ -364,14 +364,14 @@
<comment>Label for a uri/url.</comment> <comment>Label for a uri/url.</comment>
</data> </data>
<data name="UseFingerprintToUnlock" xml:space="preserve"> <data name="UseFingerprintToUnlock" xml:space="preserve">
<value>Kilidi barmaq izi ilə açın</value> <value>Kilidi açmaq üçün barmaq izi istifadə et</value>
</data> </data>
<data name="Username" xml:space="preserve"> <data name="Username" xml:space="preserve">
<value>İstifadəçi adı</value> <value>İstifadəçi adı</value>
<comment>Label for a username.</comment> <comment>Label for a username.</comment>
</data> </data>
<data name="ValidationFieldRequired" xml:space="preserve"> <data name="ValidationFieldRequired" xml:space="preserve">
<value>{0} sahəsi lazımlıdır.</value> <value>{0} xanası tələb olunur.</value>
<comment>Validation message for when a form field is left blank and is required to be entered.</comment> <comment>Validation message for when a form field is left blank and is required to be entered.</comment>
</data> </data>
<data name="ValueHasBeenCopied" xml:space="preserve"> <data name="ValueHasBeenCopied" xml:space="preserve">
@@ -422,7 +422,7 @@
<value>Avto-doldurma xidməti</value> <value>Avto-doldurma xidməti</value>
</data> </data>
<data name="SetBitwardenAsPasskeyManagerDescription" xml:space="preserve"> <data name="SetBitwardenAsPasskeyManagerDescription" xml:space="preserve">
<value>Set Bitwarden as your passkey provider in device settings.</value> <value>Cihaz ayarlarında "Bitwarden"i keçid açarı provayderiniz olaraq ayarlayın.</value>
</data> </data>
<data name="AvoidAmbiguousCharacters" xml:space="preserve"> <data name="AvoidAmbiguousCharacters" xml:space="preserve">
<value>Anlaşılmaz simvollardan çəkinin</value> <value>Anlaşılmaz simvollardan çəkinin</value>
@@ -431,7 +431,7 @@
<value>Bitwarden tətbiq uzantısı</value> <value>Bitwarden tətbiq uzantısı</value>
</data> </data>
<data name="BitwardenAppExtensionAlert2" xml:space="preserve"> <data name="BitwardenAppExtensionAlert2" xml:space="preserve">
<value>Anbarınıza yeni hesab əlavə etməyin ən asan yolu, Bitwarden tətbiq uzantısıdır. Bu uzantı haqqında daha ətraflı məlumat üçün "Ayarlar" ekranına gedin.</value> <value>Seyfinizə yeni bir giriş əlavə etməyin ən asan yolu, Bitwarden tətbiq uzantısıdır. Bu uzantı haqqında daha ətraflı məlumat üçün "Ayarlar" ekranına gedin.</value>
</data> </data>
<data name="BitwardenAppExtensionDescription" xml:space="preserve"> <data name="BitwardenAppExtensionDescription" xml:space="preserve">
<value>Giriş məlumatlarının avto-doldurulması üçün Safari-də və digər tətbiqlərdə Bitwarden-i istifadə edin.</value> <value>Giriş məlumatlarının avto-doldurulması üçün Safari-də və digər tətbiqlərdə Bitwarden-i istifadə edin.</value>
@@ -446,7 +446,7 @@
<value>E-poçtu dəyişdir</value> <value>E-poçtu dəyişdir</value>
</data> </data>
<data name="ChangeEmailConfirmation" xml:space="preserve"> <data name="ChangeEmailConfirmation" xml:space="preserve">
<value>E-poçt ünvanınızı bitwarden.com veb anbarında dəyişdirə bilərsiniz. İndi saytı ziyarət etmək istəyirsiniz?</value> <value>E-poçt ünvanınızı bitwarden.com veb seyfində dəyişdirə bilərsiniz. İndi saytı ziyarət etmək istəyirsiniz?</value>
</data> </data>
<data name="ChangeMasterPassword" xml:space="preserve"> <data name="ChangeMasterPassword" xml:space="preserve">
<value>Ana parolu dəyişdir</value> <value>Ana parolu dəyişdir</value>
@@ -468,7 +468,7 @@
<value>Elementə düzəliş et</value> <value>Elementə düzəliş et</value>
</data> </data>
<data name="EnableAutomaticSyncing" xml:space="preserve"> <data name="EnableAutomaticSyncing" xml:space="preserve">
<value>Avto-sinxr icazə ver</value> <value>Avto-sinxrn icazə ver</value>
</data> </data>
<data name="EnterEmailForHint" xml:space="preserve"> <data name="EnterEmailForHint" xml:space="preserve">
<value>Ana parol məsləhətini alacağınız hesabınızın e-poçt ünvanını daxil edin.</value> <value>Ana parol məsləhətini alacağınız hesabınızın e-poçt ünvanını daxil edin.</value>
@@ -520,7 +520,7 @@
<value>Elementləri daxilə köçür</value> <value>Elementləri daxilə köçür</value>
</data> </data>
<data name="ImportItemsConfirmation" xml:space="preserve"> <data name="ImportItemsConfirmation" xml:space="preserve">
<value>bitwarden.com veb anbarından elementləri toplu formada daxilə köçürə bilərsiniz. Veb saytı indi ziyarət etmək istəyirsiniz?</value> <value>bitwarden.com veb seyfindən elementləri toplu formada daxilə köçürə bilərsiniz. Veb saytı indi ziyarət etmək istəyirsiniz?</value>
</data> </data>
<data name="ImportItemsDescription" xml:space="preserve"> <data name="ImportItemsDescription" xml:space="preserve">
<value>Digər parol idarəetmə tətbiqlərindəki elementləri cəld və toplu formada daxilə köçürün.</value> <value>Digər parol idarəetmə tətbiqlərindəki elementləri cəld və toplu formada daxilə köçürün.</value>
@@ -550,20 +550,20 @@
<value>Dərhal</value> <value>Dərhal</value>
</data> </data>
<data name="VaultTimeout" xml:space="preserve"> <data name="VaultTimeout" xml:space="preserve">
<value>Anbara müraciət bitəcək</value> <value>Seyf vaxtının bitməsi</value>
</data> </data>
<data name="VaultTimeoutAction" xml:space="preserve"> <data name="VaultTimeoutAction" xml:space="preserve">
<value>Anbara müraciət vaxtının bitmə əməliyyatı</value> <value>Seyf vaxtının bitmə əməliyyatı</value>
</data> </data>
<data name="VaultTimeoutLogOutConfirmation" xml:space="preserve"> <data name="VaultTimeoutLogOutConfirmation" xml:space="preserve">
<value>Çıxış edəndə, anbarınıza bütün müraciətiniz dayanacaq və vaxt bitməsindən sonra onlayn kimlik doğrulaması tələb olunacaq. Bu ayarı istifadə etmək istədiyinizə əminsiniz?</value> <value>Çıxış etdikdə, seyfinizə bütün müraciətiniz dayanacaq və vaxt bitməsindən sonra onlayn kimlik doğrulaması tələb olunacaq. Bu ayarı istifadə etmək istədiyinizə əminsiniz?</value>
</data> </data>
<data name="LoggingIn" xml:space="preserve"> <data name="LoggingIn" xml:space="preserve">
<value>Giriş edilir...</value> <value>Giriş edilir...</value>
<comment>Message shown when interacting with the server</comment> <comment>Message shown when interacting with the server</comment>
</data> </data>
<data name="LoginOrCreateNewAccount" xml:space="preserve"> <data name="LoginOrCreateNewAccount" xml:space="preserve">
<value>Güvənli anbarınıza müraciət etmək üçün giriş edin və ya yeni bir hesab yaradın.</value> <value>Güvənli seyfinizə müraciət etmək üçün giriş edin və ya yeni bir hesab yaradın.</value>
</data> </data>
<data name="Manage" xml:space="preserve"> <data name="Manage" xml:space="preserve">
<value>İdarə et</value> <value>İdarə et</value>
@@ -572,7 +572,7 @@
<value>Parol təsdiqləmə doğru deyil.</value> <value>Parol təsdiqləmə doğru deyil.</value>
</data> </data>
<data name="MasterPasswordDescription" xml:space="preserve"> <data name="MasterPasswordDescription" xml:space="preserve">
<value>Ana parol, anbarınıza müraciət etmək üçün istifadə edəcəyiniz şifrədir. Ana parolu yadda saxlamaq çox vacibdir. Unutsanız, parolu bərpa etməyin heç bir yolu yoxdur.</value> <value>Ana parol, seyfinizə müraciət etmək üçün istifadə edəcəyiniz paroldur. Ana parolu yadda saxlamaq çox vacibdir. Unutsanız, parolu bərpa etməyin heç bir yolu yoxdur.</value>
</data> </data>
<data name="MasterPasswordHint" xml:space="preserve"> <data name="MasterPasswordHint" xml:space="preserve">
<value>Ana parol məsləhəti (ixtiyari)</value> <value>Ana parol məsləhəti (ixtiyari)</value>
@@ -604,13 +604,13 @@
<value>Yeni element yaradıldı.</value> <value>Yeni element yaradıldı.</value>
</data> </data>
<data name="NoFavorites" xml:space="preserve"> <data name="NoFavorites" xml:space="preserve">
<value>Anbarınızda heç bir sevimli yoxdur.</value> <value>Seyfinizdə heç bir sevimli yoxdur.</value>
</data> </data>
<data name="NoItems" xml:space="preserve"> <data name="NoItems" xml:space="preserve">
<value>Anbarınızda heç bir element yoxdur.</value> <value>Seyfinizdə heç bir element yoxdur.</value>
</data> </data>
<data name="NoItemsTap" xml:space="preserve"> <data name="NoItemsTap" xml:space="preserve">
<value>Anbarınızda bu veb sayt/tətbiq üçün heç bir element yoxdur. Əlavə etmək üçün toxunun.</value> <value>Seyfinizdə bu veb sayt/tətbiq üçün heç bir element yoxdur. Əlavə etmək üçün toxunun.</value>
</data> </data>
<data name="NoUsernamePasswordConfigured" xml:space="preserve"> <data name="NoUsernamePasswordConfigured" xml:space="preserve">
<value>Bu hesaba aid istifadəçi adı və ya parol yoxdur.</value> <value>Bu hesaba aid istifadəçi adı və ya parol yoxdur.</value>
@@ -644,7 +644,7 @@
<value>Hazırkı parolun üzərinə yazmaq istədiyinizə əminsiniz?</value> <value>Hazırkı parolun üzərinə yazmaq istədiyinizə əminsiniz?</value>
</data> </data>
<data name="PushNotificationAlert" xml:space="preserve"> <data name="PushNotificationAlert" xml:space="preserve">
<value>Bitwarden, ani bildirişləri istifadə edərək anbarınızın avtomatik sinxronlaşdırılmasını təmin edir. Mümkün olan ən yaxşı təcrübəni təqdim etmək üçün, sizdən ani bildirişləri fəallaşdırmağı soruşduqda növbəti ekranda "İcazə ver"i seçin.</value> <value>Bitwarden, ani bildirişləri istifadə edərək seyfinizi avtomatik olaraq sinxron tutur. Mümkün olan ən yaxşı təcrübə üçün, sizdən ani bildirişlərə icazə vermək istənildikdə lütfən istək pəncərəsində "İcazə ver"i seçin.</value>
<comment>Push notifications for apple products</comment> <comment>Push notifications for apple products</comment>
</data> </data>
<data name="RateTheApp" xml:space="preserve"> <data name="RateTheApp" xml:space="preserve">
@@ -660,7 +660,7 @@
<value>Ana parolu yenidən yaz</value> <value>Ana parolu yenidən yaz</value>
</data> </data>
<data name="SearchVault" xml:space="preserve"> <data name="SearchVault" xml:space="preserve">
<value>Anbarda axtar</value> <value>Seyfdə axtar</value>
</data> </data>
<data name="Security" xml:space="preserve"> <data name="Security" xml:space="preserve">
<value>Güvənlik</value> <value>Güvənlik</value>
@@ -695,7 +695,7 @@
<value>Sinxr uğursuz oldu</value> <value>Sinxr uğursuz oldu</value>
</data> </data>
<data name="SyncVaultNow" xml:space="preserve"> <data name="SyncVaultNow" xml:space="preserve">
<value>Anbarı indi sinxronlaşdır</value> <value>Seyfi indi sinxronlaşdır</value>
</data> </data>
<data name="TouchID" xml:space="preserve"> <data name="TouchID" xml:space="preserve">
<value>Touch ID</value> <value>Touch ID</value>
@@ -705,10 +705,10 @@
<value>İki mərhələli giriş</value> <value>İki mərhələli giriş</value>
</data> </data>
<data name="UnlockWith" xml:space="preserve"> <data name="UnlockWith" xml:space="preserve">
<value>{0} ilə kilidi açın</value> <value>Kilidi {0} ilə </value>
</data> </data>
<data name="UnlockWithPIN" xml:space="preserve"> <data name="UnlockWithPIN" xml:space="preserve">
<value>PIN kod ilə kilidiın</value> <value>Kilidi PIN kodla aç</value>
</data> </data>
<data name="Validating" xml:space="preserve"> <data name="Validating" xml:space="preserve">
<value>Doğrulanır</value> <value>Doğrulanır</value>
@@ -721,7 +721,7 @@
<value>Elementə bax</value> <value>Elementə bax</value>
</data> </data>
<data name="WebVault" xml:space="preserve"> <data name="WebVault" xml:space="preserve">
<value>Bitwarden veb anbarı</value> <value>Bitwarden veb seyfi</value>
</data> </data>
<data name="Lost2FAApp" xml:space="preserve"> <data name="Lost2FAApp" xml:space="preserve">
<value>Kimlik doğrulayıcı tətbiqini itirmisiniz?</value> <value>Kimlik doğrulayıcı tətbiqini itirmisiniz?</value>
@@ -744,14 +744,14 @@
<comment>This is used for the autofill service. ex. "Logins for twitter.com"</comment> <comment>This is used for the autofill service. ex. "Logins for twitter.com"</comment>
</data> </data>
<data name="NoItemsForUri" xml:space="preserve"> <data name="NoItemsForUri" xml:space="preserve">
<value>Anbarınızda {0} üçün heç bir element yoxdur.</value> <value>Seyfinizdə {0} üçün heç bir element yoxdur.</value>
<comment>This is used for the autofill service. ex. "There are no items in your vault for twitter.com".</comment> <comment>This is used for the autofill service. ex. "There are no items in your vault for twitter.com".</comment>
</data> </data>
<data name="BitwardenAutofillServiceOverlay" xml:space="preserve"> <data name="BitwardenAutofillServiceOverlay" xml:space="preserve">
<value>Bir giriş xanası seçdikdə və Bitwarden avto-doldurma örtüyünü gördükdə, avto-doldurma xidmətini başlatmaq üçün buna toxuna bilərsiniz.</value> <value>Bir giriş xanası seçdikdə və Bitwarden avto-doldurma örtüyünü gördükdə, avto-doldurma xidmətini başlatmaq üçün buna toxuna bilərsiniz.</value>
</data> </data>
<data name="BitwardenAutofillServiceNotificationContent" xml:space="preserve"> <data name="BitwardenAutofillServiceNotificationContent" xml:space="preserve">
<value>Anbarınızdakı bir elementi avto-doldurmaq üçün bu bildirişə toxunun.</value> <value>Bir elementi seyfinizdən avto-doldurmaq üçün bu bildirişə toxunun.</value>
</data> </data>
<data name="BitwardenAutofillServiceOpenAccessibilitySettings" xml:space="preserve"> <data name="BitwardenAutofillServiceOpenAccessibilitySettings" xml:space="preserve">
<value>Əlçatımlılıq Ayarlarını aç</value> <value>Əlçatımlılıq Ayarlarını aç</value>
@@ -778,7 +778,7 @@
<value>Vəziyyət</value> <value>Vəziyyət</value>
</data> </data>
<data name="BitwardenAutofillServiceAlert2" xml:space="preserve"> <data name="BitwardenAutofillServiceAlert2" xml:space="preserve">
<value>Anbarınıza yeni hesab əlavə etməyin ən asan yolu, Bitwarden avto-doldurma xidmətidir. Bu xidmət haqqında daha ətraflı məlumat üçün "Ayarlar" ekranına gedin.</value> <value>Seyfinizə yeni bir giriş əlavə etməyin ən asan yolu, Bitwarden Avto-doldurma Xidmətidir. Bitwarden Avto-doldurma Xidmətini istifadə etməklə bağlı daha ətraflı məlumat üçün "Ayarlar" ekranına gedin.</value>
</data> </data>
<data name="Autofill" xml:space="preserve"> <data name="Autofill" xml:space="preserve">
<value>Avto-doldurma</value> <value>Avto-doldurma</value>
@@ -949,7 +949,7 @@ Skan prosesi avtomatik baş tutacaq.</value>
<value>Şifrələmə açarınızı güncəlləyənə qədər bu özəlliyi istifadə edə bilməzsiniz.</value> <value>Şifrələmə açarınızı güncəlləyənə qədər bu özəlliyi istifadə edə bilməzsiniz.</value>
</data> </data>
<data name="EncryptionKeyMigrationRequiredDescriptionLong" xml:space="preserve"> <data name="EncryptionKeyMigrationRequiredDescriptionLong" xml:space="preserve">
<value>Şifrələmə açarının daşınması tələb olunur. Şifrələmə açarınızı güncəlləmək üçün lütfən veb anbar üzərindən giriş edin.</value> <value>Şifrələmə açarının daşınması tələb olunur. Şifrələmə açarınızı güncəlləmək üçün lütfən veb seyfinizə giriş edin.</value>
</data> </data>
<data name="LearnMore" xml:space="preserve"> <data name="LearnMore" xml:space="preserve">
<value>Daha ətraflı</value> <value>Daha ətraflı</value>
@@ -984,13 +984,13 @@ Skan prosesi avtomatik baş tutacaq.</value>
<value>Server URL-si</value> <value>Server URL-si</value>
</data> </data>
<data name="WebVaultUrl" xml:space="preserve"> <data name="WebVaultUrl" xml:space="preserve">
<value>Veb anbar server URL-si</value> <value>Veb seyf server URL-si</value>
</data> </data>
<data name="BitwardenAutofillServiceNotificationContentOld" xml:space="preserve"> <data name="BitwardenAutofillServiceNotificationContentOld" xml:space="preserve">
<value>Anbarınızdakı elementlərə baxmaq üçün bu bildirişə toxunun.</value> <value>Seyfinizdəki elementlərə baxmaq üçün bu bildirişə toxunun.</value>
</data> </data>
<data name="CustomFields" xml:space="preserve"> <data name="CustomFields" xml:space="preserve">
<value>Özəl sahələr</value> <value>Özəl xanalar</value>
</data> </data>
<data name="CopyNumber" xml:space="preserve"> <data name="CopyNumber" xml:space="preserve">
<value>Nömrəni kopyala</value> <value>Nömrəni kopyala</value>
@@ -1149,10 +1149,10 @@ Skan prosesi avtomatik baş tutacaq.</value>
<value>Bitwarden ilə avto-doldurma</value> <value>Bitwarden ilə avto-doldurma</value>
</data> </data>
<data name="VaultIsLocked" xml:space="preserve"> <data name="VaultIsLocked" xml:space="preserve">
<value>Anbar kilidlənib</value> <value>Seyf kilidlənib</value>
</data> </data>
<data name="GoToMyVault" xml:space="preserve"> <data name="GoToMyVault" xml:space="preserve">
<value>Anbarıma get</value> <value>Seyfimə get</value>
</data> </data>
<data name="Collections" xml:space="preserve"> <data name="Collections" xml:space="preserve">
<value>Kolleksiyalar</value> <value>Kolleksiyalar</value>
@@ -1170,7 +1170,7 @@ Skan prosesi avtomatik baş tutacaq.</value>
<value>Avto-doldurma əlçatımlılıq xidməti</value> <value>Avto-doldurma əlçatımlılıq xidməti</value>
</data> </data>
<data name="AutofillServiceDescription" xml:space="preserve"> <data name="AutofillServiceDescription" xml:space="preserve">
<value>Bitwarden avto-doldurma xidməti, giriş məlumatlarının cihazınızdakı digər tətbiqlərdə doldurmasına kömək etməsi üçün Android Avto-doldurma Çərçivəsini istifadə edir.</value> <value>Bitwarden avto-doldurma xidməti, cihazınızdakı digər tətbiqlərə giriş məlumatlarını doldurmağa kömək en Android Avto-doldurma Çərçivəsini istifadə edir.</value>
</data> </data>
<data name="BitwardenAutofillServiceDescription" xml:space="preserve"> <data name="BitwardenAutofillServiceDescription" xml:space="preserve">
<value>Giriş məlumatlarını digər tətbiqlərdə doldurmaq üçün Bitwarden avto-doldurma xidmətini istifadə edin.</value> <value>Giriş məlumatlarını digər tətbiqlərdə doldurmaq üçün Bitwarden avto-doldurma xidmətini istifadə edin.</value>
@@ -1195,13 +1195,13 @@ Skan prosesi avtomatik baş tutacaq.</value>
<value>Windows Hello</value> <value>Windows Hello</value>
</data> </data>
<data name="BitwardenCredentialProviderGoToSettings" xml:space="preserve"> <data name="BitwardenCredentialProviderGoToSettings" xml:space="preserve">
<value>We were unable to automatically open the Android credential provider settings menu for you. You can navigate to the credential provider settings menu manually from Android Settings &gt; System &gt; Passwords &amp; accounts &gt; Passwords, passkeys and data services.</value> <value>Android kimlik məlumatı provayder ayarları menyusunu sizin üçün avtomatik aça bilmədik. Bu menyunu tapmaq üçün Android Ayarları &gt; Sistem &gt; Parollar və hesablar &gt; Parollar, keçid açarları və data xidmətləri bölməsində tapa bilərsiniz.</value>
</data> </data>
<data name="BitwardenAutofillGoToSettings" xml:space="preserve"> <data name="BitwardenAutofillGoToSettings" xml:space="preserve">
<value>Android avto-doldurma ayarları menyusunu avtomatik aça bilmədik. Bu menyunu tapmaq üçün Android Ayarları &gt; Sistem &gt; Dillər və giriş &gt; Qabaqcıl &gt; "Avto-doldurma xidməti"nə gedin.</value> <value>Android avto-doldurma ayarları menyusunu avtomatik aça bilmədik. Bu menyunu tapmaq üçün Android Ayarları &gt; Sistem &gt; Dillər və giriş &gt; Qabaqcıl &gt; "Avto-doldurma xidməti"nə gedin.</value>
</data> </data>
<data name="CustomFieldName" xml:space="preserve"> <data name="CustomFieldName" xml:space="preserve">
<value>Özəl sahə adı</value> <value>Özəl xana adı</value>
</data> </data>
<data name="FieldTypeBoolean" xml:space="preserve"> <data name="FieldTypeBoolean" xml:space="preserve">
<value>Boolean</value> <value>Boolean</value>
@@ -1216,10 +1216,10 @@ Skan prosesi avtomatik baş tutacaq.</value>
<value>Mətn</value> <value>Mətn</value>
</data> </data>
<data name="NewCustomField" xml:space="preserve"> <data name="NewCustomField" xml:space="preserve">
<value>Yeni özəl sahə</value> <value>Yeni özəl xana</value>
</data> </data>
<data name="SelectTypeField" xml:space="preserve"> <data name="SelectTypeField" xml:space="preserve">
<value>Necə bir özəl sahə əlavə etmək istəyirsiniz?</value> <value>Necə bir özəl xana əlavə etmək istəyirsiniz?</value>
</data> </data>
<data name="Remove" xml:space="preserve"> <data name="Remove" xml:space="preserve">
<value>Çıxart</value> <value>Çıxart</value>
@@ -1301,7 +1301,7 @@ Skan prosesi avtomatik baş tutacaq.</value>
<value>İstifadə etməyi düşünmürsünüzsə, digər Avto-doldurma tətbiqlərini Ayarlarda sıradan çıxartmağı tövsiyə edirik.</value> <value>İstifadə etməyi düşünmürsünüzsə, digər Avto-doldurma tətbiqlərini Ayarlarda sıradan çıxartmağı tövsiyə edirik.</value>
</data> </data>
<data name="BitwardenAutofillDescription" xml:space="preserve"> <data name="BitwardenAutofillDescription" xml:space="preserve">
<value>Parollarınızın cəld avto-doldurulması üçün anbarınıza birbaşa klaviaturanızdan müraciət edin.</value> <value>Parolları cəld avto-doldurmaq üçün seyfinizə birbaşa klaviaturanızdan müraciət edin.</value>
</data> </data>
<data name="AutofillTurnOn" xml:space="preserve"> <data name="AutofillTurnOn" xml:space="preserve">
<value>Cihazınızda parolun avto-doldurulması üçün aşağıdakı təlimatları izləyin:</value> <value>Cihazınızda parolun avto-doldurulması üçün aşağıdakı təlimatları izləyin:</value>
@@ -1325,7 +1325,7 @@ Skan prosesi avtomatik baş tutacaq.</value>
<value>Parolun avto-doldurulması</value> <value>Parolun avto-doldurulması</value>
</data> </data>
<data name="BitwardenAutofillAlert2" xml:space="preserve"> <data name="BitwardenAutofillAlert2" xml:space="preserve">
<value>Anbarınıza yeni giriş məlumatlarını əlavə etməyin ən asan yolu, Bitwarden parol avto-doldurma uzantısıdır. Bu uzantı haqqında daha ətraflı məlumat almaq üçün "Ayarlar" ekranına gedin.</value> <value>Seyfinizə yeni bir giriş əlavə etməyin ən asan yolu, Bitwarden Parol Avto-doldurma uzantısıdır. Bitwarden Parol Avto-doldurma uzantısı haqqında daha ətraflı məlumat üçün "Ayarlar" ekranına gedin.</value>
</data> </data>
<data name="InvalidEmail" xml:space="preserve"> <data name="InvalidEmail" xml:space="preserve">
<value>Yararsız e-poçt ünvanı.</value> <value>Yararsız e-poçt ünvanı.</value>
@@ -1468,10 +1468,10 @@ Skan prosesi avtomatik baş tutacaq.</value>
<comment>A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing.</comment> <comment>A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing.</comment>
</data> </data>
<data name="LearnOrgConfirmation" xml:space="preserve"> <data name="LearnOrgConfirmation" xml:space="preserve">
<value>Bitwarden, bir təşkilat hesabı istifadə edərək anbar elementlərinizi başqaları ilə paylaşmağınıza icazə verər. Daha ətraflı məlumat üçün bitwarden.com saytını ziyarət etmək istəyirsiniz?</value> <value>Bitwarden, bir təşkilat hesabı istifadə edərək seyf elementlərinizi başqaları ilə paylaşmağınıza icazə verir. Daha ətraflı məlumat üçün bitwarden.com saytını ziyarət etmək istəyirsiniz?</value>
</data> </data>
<data name="ExportVault" xml:space="preserve"> <data name="ExportVault" xml:space="preserve">
<value>Anbarı xaricə köçür</value> <value>Seyfi xaricə köçür</value>
</data> </data>
<data name="LockNow" xml:space="preserve"> <data name="LockNow" xml:space="preserve">
<value>İndi kilidlə</value> <value>İndi kilidlə</value>
@@ -1483,7 +1483,7 @@ Skan prosesi avtomatik baş tutacaq.</value>
<value>Kilidi aç</value> <value>Kilidi aç</value>
</data> </data>
<data name="UnlockVault" xml:space="preserve"> <data name="UnlockVault" xml:space="preserve">
<value>Anbar kilidini aç</value> <value>Seyfin kilidini aç</value>
</data> </data>
<data name="ThirtyMinutes" xml:space="preserve"> <data name="ThirtyMinutes" xml:space="preserve">
<value>30 dəqiqə</value> <value>30 dəqiqə</value>
@@ -1496,13 +1496,13 @@ Skan prosesi avtomatik baş tutacaq.</value>
<comment>ex: Logged in as user@example.com on bitwarden.com.</comment> <comment>ex: Logged in as user@example.com on bitwarden.com.</comment>
</data> </data>
<data name="VaultLockedMasterPassword" xml:space="preserve"> <data name="VaultLockedMasterPassword" xml:space="preserve">
<value>Anbarınız kilidlənib. Davam etmək üçün ana parolunuzu doğrulayın.</value> <value>Seyfiniz kilidlənib. Davam etmək üçün ana parolunuzu doğrulayın.</value>
</data> </data>
<data name="VaultLockedPIN" xml:space="preserve"> <data name="VaultLockedPIN" xml:space="preserve">
<value>Anbarınız kilidlənib. Davam etmək üçün PIN kodunuzu doğrulayın.</value> <value>Seyfiniz kilidlənib. Davam etmək üçün PIN kodunuzu doğrulayın.</value>
</data> </data>
<data name="VaultLockedIdentity" xml:space="preserve"> <data name="VaultLockedIdentity" xml:space="preserve">
<value>Anbarınız kilidlənib. Davam etmək üçün kimliyinizi doğrulayın.</value> <value>Seyfiniz kilidlənib. Davam etmək üçün kimliyinizi doğrulayın.</value>
</data> </data>
<data name="Dark" xml:space="preserve"> <data name="Dark" xml:space="preserve">
<value>Tünd</value> <value>Tünd</value>
@@ -1540,7 +1540,7 @@ Skan prosesi avtomatik baş tutacaq.</value>
<comment>Default URI match detection for auto-fill.</comment> <comment>Default URI match detection for auto-fill.</comment>
</data> </data>
<data name="DefaultUriMatchDetectionDescription" xml:space="preserve"> <data name="DefaultUriMatchDetectionDescription" xml:space="preserve">
<value>Avto-doldurma kimi əməliyyatları icra edərkən giriş etmə prosesi üçün URI uyuşma aşkarlamasının idarə edliəcəyi ilkin yolu seçin.</value> <value>Avto-doldurma kimi əməliyyatları icra edərkən giriş etmə prosesi üçün URI uyuşma aşkarlamasının idarə ediləcəyi ilkin yolu seçin.</value>
</data> </data>
<data name="Theme" xml:space="preserve"> <data name="Theme" xml:space="preserve">
<value>Tema</value> <value>Tema</value>
@@ -1586,13 +1586,13 @@ Skan prosesi avtomatik baş tutacaq.</value>
<value>Giriş əlavə etmək üçün soruş</value> <value>Giriş əlavə etmək üçün soruş</value>
</data> </data>
<data name="AskToAddLoginDescription" xml:space="preserve"> <data name="AskToAddLoginDescription" xml:space="preserve">
<value>Anbarınızda yoxdursa, bir element əlavə etyi soruşun.</value> <value>Seyfinizdə tapılmayan elementin əlavə edilsi soruşulsun.</value>
</data> </data>
<data name="OnRestart" xml:space="preserve"> <data name="OnRestart" xml:space="preserve">
<value>Tətbiq yenidən başladılanda</value> <value>Tətbiq yenidən başladılanda</value>
</data> </data>
<data name="AutofillServiceNotEnabled" xml:space="preserve"> <data name="AutofillServiceNotEnabled" xml:space="preserve">
<value>Avto-doldurma, veb sayt və tətbiqlərdən Bitwarden anbarınıza güvənli şəkildə müraciət etməyinizi asanlaşdırır. Deyəsən, Bitwarden üçün avto-doldurma xidmətini qurmamısınız. "Ayarlar" ekranında Bitwarden üçün avto-doldurma xidmətini qurun.</value> <value>Avto-doldurma, digər veb sayt və tətbiqlərdən Bitwarden seyfinizə güvənli şəkildə müraciət etməyinizi asanlaşdırır. Deyəsən, Bitwarden üçün avto-doldurma xidmətini qurmamısınız. "Ayarlar" ekranında Bitwarden üçün avto-doldurma xidmətini qurun.</value>
</data> </data>
<data name="ThemeAppliedOnRestart" xml:space="preserve"> <data name="ThemeAppliedOnRestart" xml:space="preserve">
<value>Tema dəyişiklikləriniz tətbiq yenidən başladılanda tətbiq ediləcək.</value> <value>Tema dəyişiklikləriniz tətbiq yenidən başladılanda tətbiq ediləcək.</value>
@@ -1623,7 +1623,7 @@ Skan prosesi avtomatik baş tutacaq.</value>
<value>Biometrik</value> <value>Biometrik</value>
</data> </data>
<data name="UseBiometricsToUnlock" xml:space="preserve"> <data name="UseBiometricsToUnlock" xml:space="preserve">
<value>Kilidi biometriklə aç</value> <value>Kilidi açmaq üçün biometrik istifadə et</value>
</data> </data>
<data name="AccessibilityOverlayPermissionAlert" xml:space="preserve"> <data name="AccessibilityOverlayPermissionAlert" xml:space="preserve">
<value>Bitwarden diqqətinizi tələb edir - Bitwarden ayarlarında "Avto-doldurma əlçatımlılıq xidməti"nə baxın</value> <value>Bitwarden diqqətinizi tələb edir - Bitwarden ayarlarında "Avto-doldurma əlçatımlılıq xidməti"nə baxın</value>
@@ -1650,7 +1650,7 @@ Skan prosesi avtomatik baş tutacaq.</value>
<value>Fayl formatı</value> <value>Fayl formatı</value>
</data> </data>
<data name="ExportVaultMasterPasswordDescription" xml:space="preserve"> <data name="ExportVaultMasterPasswordDescription" xml:space="preserve">
<value>Anbar datanızı xaricə köçürmək üçün ana parolunuzu daxil edin.</value> <value>Seyf datanızı xaricə köçürmək üçün ana parolunuzu daxil edin.</value>
</data> </data>
<data name="SendVerificationCodeToEmail" xml:space="preserve"> <data name="SendVerificationCodeToEmail" xml:space="preserve">
<value>Doğrulama kodunu e-poçtunuza göndərin</value> <value>Doğrulama kodunu e-poçtunuza göndərin</value>
@@ -1671,17 +1671,17 @@ Skan prosesi avtomatik baş tutacaq.</value>
<value>Hesab şifrələmə açarları, hər Bitwarden istifadəçi hesabı üçün unikaldır, buna görə də şifrələnmiş bir xaricə köçürməni, fərqli bir hesaba köçürə bilməzsiniz.</value> <value>Hesab şifrələmə açarları, hər Bitwarden istifadəçi hesabı üçün unikaldır, buna görə də şifrələnmiş bir xaricə köçürməni, fərqli bir hesaba köçürə bilməzsiniz.</value>
</data> </data>
<data name="ExportVaultConfirmationTitle" xml:space="preserve"> <data name="ExportVaultConfirmationTitle" xml:space="preserve">
<value>Anbarın xaricə köçürülməsini təsdiqlə</value> <value>Seyfi xaricə köçürməyi təsdiqlə</value>
<comment>Title for the alert to confirm vault exports.</comment> <comment>Title for the alert to confirm vault exports.</comment>
</data> </data>
<data name="Warning" xml:space="preserve"> <data name="Warning" xml:space="preserve">
<value>Xəbərdarlıq</value> <value>Xəbərdarlıq</value>
</data> </data>
<data name="ExportVaultFailure" xml:space="preserve"> <data name="ExportVaultFailure" xml:space="preserve">
<value>Anbarınızın xaricə köçürülməsi zamanı problem yarandı. Əgər problem davam edərsə, veb anbarından xaricə köçürməli olacaqsınız.</value> <value>Seyfin xaricə köçürülməsi zamanı problem yarandı. Əgər problem davam edərsə, veb seyfinizdən xaricə köçürməli olacaqsınız.</value>
</data> </data>
<data name="ExportVaultSuccess" xml:space="preserve"> <data name="ExportVaultSuccess" xml:space="preserve">
<value>Anbar uğurla xaricə köçürüldü</value> <value>Seyf uğurla xaricə köçürüldü</value>
</data> </data>
<data name="Clone" xml:space="preserve"> <data name="Clone" xml:space="preserve">
<value>Klonla</value> <value>Klonla</value>
@@ -1695,7 +1695,7 @@ Skan prosesi avtomatik baş tutacaq.</value>
<comment>Button text for an open operation (verb).</comment> <comment>Button text for an open operation (verb).</comment>
</data> </data>
<data name="UnableToSaveAttachment" xml:space="preserve"> <data name="UnableToSaveAttachment" xml:space="preserve">
<value>Bu qoşmanı saxlayarkən problem yarandı. Əgər problem davam edərsə, veb anbarından saxlaya bilərsiniz.</value> <value>Bu qoşmanı saxlayarkən problem yarandı. Əgər problem davam edərsə, veb seyfdən saxlaya bilərsiniz.</value>
</data> </data>
<data name="SaveAttachmentSuccess" xml:space="preserve"> <data name="SaveAttachmentSuccess" xml:space="preserve">
<value>Qoşma uğurla saxlanıldı</value> <value>Qoşma uğurla saxlanıldı</value>
@@ -1704,7 +1704,7 @@ Skan prosesi avtomatik baş tutacaq.</value>
<value>Avto-doldurma qutusunu istifadə etmək üçün lütfən "Bitwarden" ayarlarında "Avto-doldurma əlçatımlılıq xidməti"ni fəallaşdırın.</value> <value>Avto-doldurma qutusunu istifadə etmək üçün lütfən "Bitwarden" ayarlarında "Avto-doldurma əlçatımlılıq xidməti"ni fəallaşdırın.</value>
</data> </data>
<data name="AutofillTileUriNotFound" xml:space="preserve"> <data name="AutofillTileUriNotFound" xml:space="preserve">
<value>Heç bir parol sahəsi aşkarlanmadı</value> <value>Parol xanası aşkarlanmadı</value>
</data> </data>
<data name="SoftDeleting" xml:space="preserve"> <data name="SoftDeleting" xml:space="preserve">
<value>Tullantı qutusuna göndərilir...</value> <value>Tullantı qutusuna göndərilir...</value>
@@ -1753,16 +1753,16 @@ Skan prosesi avtomatik baş tutacaq.</value>
<value>Ana parolun doğrulanması gözlənildiyi üçün bu hesab üzrə avto-doldurma biometrik kilid açma sıradan çıxarıldı.</value> <value>Ana parolun doğrulanması gözlənildiyi üçün bu hesab üzrə avto-doldurma biometrik kilid açma sıradan çıxarıldı.</value>
</data> </data>
<data name="EnableSyncOnRefresh" xml:space="preserve"> <data name="EnableSyncOnRefresh" xml:space="preserve">
<value>Təzələmə zamanı sinxr icazə ver</value> <value>Təzələmə zamanı sinxrn icazə ver</value>
</data> </data>
<data name="EnableSyncOnRefreshDescription" xml:space="preserve"> <data name="EnableSyncOnRefreshDescription" xml:space="preserve">
<value>Barmağınızla aşağı çəkdikdə anbarı sinxronlaşdır.</value> <value>Barmağınızla aşağı çəkdikdə seyfi sinxronlaşdır.</value>
</data> </data>
<data name="LogInSso" xml:space="preserve"> <data name="LogInSso" xml:space="preserve">
<value>Müəssisə üçün tək daxil olma</value> <value>Müəssisə üçün vahid daxil olma</value>
</data> </data>
<data name="LogInSsoSummary" xml:space="preserve"> <data name="LogInSsoSummary" xml:space="preserve">
<value>Təşkilatınızın tək daxil olma portalını istifadə edərək daha tez giriş edə bilərsiniz. Başlatmaq üçün lütfən təşkilatınızın identifikatorunu daxil edin.</value> <value>Təşkilatınızın vahid daxil olma portalını istifadə edərək cəld giriş edin. Başlatmaq üçün lütfən təşkilatınızın identifikatorunu daxil edin.</value>
</data> </data>
<data name="OrgIdentifier" xml:space="preserve"> <data name="OrgIdentifier" xml:space="preserve">
<value>Təşkilat identifikatoru</value> <value>Təşkilat identifikatoru</value>
@@ -1774,7 +1774,7 @@ Skan prosesi avtomatik baş tutacaq.</value>
<value>Ana parolu ayarla</value> <value>Ana parolu ayarla</value>
</data> </data>
<data name="SetMasterPasswordSummary" xml:space="preserve"> <data name="SetMasterPasswordSummary" xml:space="preserve">
<value>SSO ilə giriş prosesini tamamlamaq üçün lütfən anbarınıza müraciət etmək və onu qorumaq üçün bir ana parol ayarlayın.</value> <value>SSO ilə giriş prosesini tamamlamaq üçün lütfən seyfinizə müraciət edəcək və onu qoruyacaq bir ana parol təyin edin.</value>
</data> </data>
<data name="MasterPasswordPolicyInEffect" xml:space="preserve"> <data name="MasterPasswordPolicyInEffect" xml:space="preserve">
<value>Bir və ya daha çox təşkilat siyasəti, aşağıdakı tələbləri qarşılamaq üçün ana parolunuzu tələb edir:</value> <value>Bir və ya daha çox təşkilat siyasəti, aşağıdakı tələbləri qarşılamaq üçün ana parolunuzu tələb edir:</value>
@@ -1822,16 +1822,16 @@ Skan prosesi avtomatik baş tutacaq.</value>
<value>Bitwarden diqqətinizi tələb edir - Bitwarden Ayarlarında "Avto-doldurma xidməti"ndə "Üzərindən göstər"i işə salın</value> <value>Bitwarden diqqətinizi tələb edir - Bitwarden Ayarlarında "Avto-doldurma xidməti"ndə "Üzərindən göstər"i işə salın</value>
</data> </data>
<data name="PasskeyManagement" xml:space="preserve"> <data name="PasskeyManagement" xml:space="preserve">
<value>Passkey management</value> <value>Keçid açarını idarəetmə</value>
</data> </data>
<data name="AutofillServices" xml:space="preserve"> <data name="AutofillServices" xml:space="preserve">
<value>Avto-doldurma xidmətləri</value> <value>Avto-doldurma xidmətləri</value>
</data> </data>
<data name="InlineAutofill" xml:space="preserve"> <data name="InlineAutofill" xml:space="preserve">
<value>Sətir daxili avto-doldurmanı istifadə edin</value> <value>Sətirdaxili avto-doldurmanı istifadə et</value>
</data> </data>
<data name="InlineAutofillDescription" xml:space="preserve"> <data name="InlineAutofillDescription" xml:space="preserve">
<value>Seçdiyiniz IME (klaviatura) dəstəkləyirsə sətir daxili avto-doldurmanı istifadə edə bilərsiniz. Əgər konfiqurasiyanız dəstəkləmirsə (və ya bu seçim sıradan çıxarılıbsa) ilkin Avto-doldurma qutusu istifadə ediləcəkdir.</value> <value>Seçdiyiniz IME (klaviatura) dəstəkləyirsə sətirdaxili avto-doldurmanı istifadə edin. Əgər konfiqurasiyanız dəstəkləmirsə (və ya bu seçim söndürülübsə) ilkin Avto-doldurma örtüyü istifadə ediləcəkdir.</value>
</data> </data>
<data name="Accessibility" xml:space="preserve"> <data name="Accessibility" xml:space="preserve">
<value>Əlçatımlılığı istifadə et</value> <value>Əlçatımlılığı istifadə et</value>
@@ -1843,16 +1843,16 @@ Skan prosesi avtomatik baş tutacaq.</value>
<value>Saytda və vebdə giriş məlumatlarınızı avto-doldurmaq üçün Bitwarden Əlçatımlılıq Xidmətini istifadə edin. ("Üzərində göstər" seçimi açıq olmalıdır)</value> <value>Saytda və vebdə giriş məlumatlarınızı avto-doldurmaq üçün Bitwarden Əlçatımlılıq Xidmətini istifadə edin. ("Üzərində göstər" seçimi açıq olmalıdır)</value>
</data> </data>
<data name="AccessibilityDescription3" xml:space="preserve"> <data name="AccessibilityDescription3" xml:space="preserve">
<value>Avto-doldurma cəld əməliyyat qutusunu istifadə etmək üçün Bitwarden əlçatımlılıq xidmətini istifadə edin və/və ya "Üzərində göstər"i (əgər fəaldırsa) istifadə edərək açılan bir pəncərə göstərə bilərsiniz.</value> <value>Avto-doldurma Cəld Əməliyyat Xanasını istifadə etmək üçün Bitwarden Əlçatımlılıq Xidmətini istifadə edin və/və ya "Üzərində göstər"i (əgər ıqdırsa) istifadə edərək açılan bir pəncərə göstərin.</value>
</data> </data>
<data name="AccessibilityDescription4" xml:space="preserve"> <data name="AccessibilityDescription4" xml:space="preserve">
<value>Avto-doldurma cəld əməliyyat qutusunu istifadə etmək və ya "Üzərində göstər"i (əgər fəaldırsa) istifadə edərək Avto-doldurma xidmətini təqlid etmək tələb olunur.</value> <value>Avto-doldurma Cəld Əməliyyat Xanasını istifadə etmək və ya "Üzərində göstər"i (əgər ıqdırsa) istifadə edərək Avto-doldurma xidmətini təqlid etmək üçün tələb olunur.</value>
</data> </data>
<data name="DrawOver" xml:space="preserve"> <data name="DrawOver" xml:space="preserve">
<value>"Üzərində göstər"i istifadə edin</value> <value>"Üzərində göstər"i istifadə edin</value>
</data> </data>
<data name="DrawOverDescription" xml:space="preserve"> <data name="DrawOverDescription" xml:space="preserve">
<value>Giriş xanalarını seçdikdə Bitwarden Əlçatımlılıq Xidmətinin açılan pəncərə göstərməsinə icazə verir.</value> <value>Giriş xanaları seçildikdə, Bitwarden Əlçatımlılıq Xidmətinin açılan bir pəncərə göstərməsinə icazə verir.</value>
</data> </data>
<data name="DrawOverDescription2" xml:space="preserve"> <data name="DrawOverDescription2" xml:space="preserve">
<value>İşə salındıqda Bitwarden Əlçatımlılıq Xidməti, giriş məlumatlarınızın avto-doldurmasına kömək etmək üçün giriş xanaları seçildikdə açılan pəncərə göstərəcək.</value> <value>İşə salındıqda Bitwarden Əlçatımlılıq Xidməti, giriş məlumatlarınızın avto-doldurmasına kömək etmək üçün giriş xanaları seçildikdə açılan pəncərə göstərəcək.</value>
@@ -1861,7 +1861,7 @@ Skan prosesi avtomatik baş tutacaq.</value>
<value>Fəal olsa, əlçatımlılıq, Android Avto-doldurma Çərçivəsini dəstəkləməyən köhnə tətbiqlərdə Avto-doldurma Xidmətini təqlid etməsi üçün açılan bir pəncərə göstərəcək.</value> <value>Fəal olsa, əlçatımlılıq, Android Avto-doldurma Çərçivəsini dəstəkləməyən köhnə tətbiqlərdə Avto-doldurma Xidmətini təqlid etməsi üçün açılan bir pəncərə göstərəcək.</value>
</data> </data>
<data name="PersonalOwnershipSubmitError" xml:space="preserve"> <data name="PersonalOwnershipSubmitError" xml:space="preserve">
<value>Müəssisə Siyasətinə görə, elementləri şəxsi anbarınızda saxlamağınız məhdudlaşdırılıb. Sahiblik seçimini təşkilat olaraq dəyişdirin və mövcud kolleksiyalar arasından seçim edin.</value> <value>Müəssisə siyasətinə görə, elementləri şəxsi seyfinizdə saxlamağınız məhdudlaşdırılıb. Sahiblik seçimini təşkilat olaraq dəyişdirin və mövcud kolleksiyalar arasından seçim edin.</value>
</data> </data>
<data name="PersonalOwnershipPolicyInEffect" xml:space="preserve"> <data name="PersonalOwnershipPolicyInEffect" xml:space="preserve">
<value>Bir təşkilat siyasəti, sahiblik seçimlərinizə təsir edir.</value> <value>Bir təşkilat siyasəti, sahiblik seçimlərinizə təsir edir.</value>
@@ -2067,7 +2067,7 @@ Skan prosesi avtomatik baş tutacaq.</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment> <comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data> </data>
<data name="SendFileEmailVerificationRequired" xml:space="preserve"> <data name="SendFileEmailVerificationRequired" xml:space="preserve">
<value>Faylları "Send" ilə istifadə etmək üçün e-poçtunuzu doğrulamalısınız. E-poçtunuzu veb anbarında doğrulaya bilərsiniz.</value> <value>Faylları "Send" ilə istifadə etmək üçün e-poçtunuzu doğrulamalısınız. E-poçtunuzu veb seyfdə doğrulaya bilərsiniz.</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment> <comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data> </data>
<data name="PasswordPrompt" xml:space="preserve"> <data name="PasswordPrompt" xml:space="preserve">
@@ -2092,7 +2092,7 @@ Skan prosesi avtomatik baş tutacaq.</value>
<value>Ana parolu güncəllə</value> <value>Ana parolu güncəllə</value>
</data> </data>
<data name="UpdateMasterPasswordWarning" xml:space="preserve"> <data name="UpdateMasterPasswordWarning" xml:space="preserve">
<value>Ana parolunuz təzəlikcə təşkilatınızdakı bir administrator tərəfindən dəyişdirildi. Anbara müraciət üçün Ana parolunuzu indi güncəlləməlisiniz. Davam etsəniz, hazırkı seansdan çıxış etmiş və təkrar giriş etməli olacaqsınız. Digər cihazlardakı aktiv seanslar bir saata qədər aktiv qalmağa davam edə bilər.</value> <value>Ana parolunuz təzəlikcə təşkilatınızdakı bir administrator tərəfindən dəyişdirildi. Seyfə müraciət üçün Ana parolunuzu indi güncəlləməlisiniz. Davam etsəniz, hazırkı seansdan çıxış etmiş və təkrar giriş etməli olacaqsınız. Digər cihazlardakı aktiv seanslar bir saata qədər aktiv qalmağa davam edə bilər.</value>
</data> </data>
<data name="UpdatingPassword" xml:space="preserve"> <data name="UpdatingPassword" xml:space="preserve">
<value>Parol yenilənir</value> <value>Parol yenilənir</value>
@@ -2137,19 +2137,19 @@ Skan prosesi avtomatik baş tutacaq.</value>
<value>Bu təşkilat, sizi "parol sıfırlama"da avtomatik olaraq qeydiyyata alan müəssisə siyasətinə sahibdir. Qeydiyyat, təşkilat administratorlarına ana parolunuzu dəyişdirmə icazəsi verəcək.</value> <value>Bu təşkilat, sizi "parol sıfırlama"da avtomatik olaraq qeydiyyata alan müəssisə siyasətinə sahibdir. Qeydiyyat, təşkilat administratorlarına ana parolunuzu dəyişdirmə icazəsi verəcək.</value>
</data> </data>
<data name="VaultTimeoutPolicyInEffect" xml:space="preserve"> <data name="VaultTimeoutPolicyInEffect" xml:space="preserve">
<value>Təşkilatınızın siyasətləri, anbarınızın vaxt bitişinə təsir edir. Anbar vaxt bitişi üçün icazə verilən maksimum vaxt {0} saat {1} dəqiqədir</value> <value>Təşkilatınızın siyasətləri, icazə verilən maksimum seyf bitmə vaxtını {0} saat {1} dəqiqə olaraq ayarladı.</value>
</data> </data>
<data name="VaultTimeoutPolicyWithActionInEffect" xml:space="preserve"> <data name="VaultTimeoutPolicyWithActionInEffect" xml:space="preserve">
<value>Təşkilatınızın siyasətləri, anbarınızın vaxt bitişinə təsir edir. Anbar vaxt bitişi üçün icazə verilən maksimum vaxt {0} saat {1} dəqiqədir. Anbar vaxt bitişi əməliyyatı {2} olaraq ayarlandı.</value> <value>Təşkilatınızın siyasətləri, seyfinizin bitmə vaxtına təsir edir. İcazə verilən maksimum seyf bitmə vaxtı {0} saat {1} dəqiqədir. Seyf vaxt bit əməliyyatı {2} olaraq ayarlandı.</value>
</data> </data>
<data name="VaultTimeoutActionPolicyInEffect" xml:space="preserve"> <data name="VaultTimeoutActionPolicyInEffect" xml:space="preserve">
<value>Təşkilatınızın siyasətləri, anbar vaxt bitişi əməliyyatınızı {0} olaraq ayarladı.</value> <value>Təşkilatınızın siyasətləri, seyfinizin vaxt bit əməliyyatını {0} olaraq ayarladı.</value>
</data> </data>
<data name="VaultTimeoutToLarge" xml:space="preserve"> <data name="VaultTimeoutToLarge" xml:space="preserve">
<value>Anbar vaxt bitişi, təşkilatınız tərəfindən ayarlanan məhdudiyyətləri aşır.</value> <value>Seyfin bitmə vaxtı, təşkilatınız tərəfindən ayarlanan məhdudiyyətləri aşır.</value>
</data> </data>
<data name="DisablePersonalVaultExportPolicyInEffect" xml:space="preserve"> <data name="DisablePersonalVaultExportPolicyInEffect" xml:space="preserve">
<value>Bir və ya daha çox təşkilat siyasəti, fərdi anbarınızı xaricə köçürməyinizi əngəlləyir.</value> <value>Bir və ya daha çox təşkilat siyasəti, fərdi seyfinizi xaricə köçürməyinizi əngəlləyir.</value>
</data> </data>
<data name="AddAccount" xml:space="preserve"> <data name="AddAccount" xml:space="preserve">
<value>Hesab əlavə et</value> <value>Hesab əlavə et</value>
@@ -2257,16 +2257,16 @@ Skan prosesi avtomatik baş tutacaq.</value>
<value>Parol görünmür, göstərmək üçün toxunun.</value> <value>Parol görünmür, göstərmək üçün toxunun.</value>
</data> </data>
<data name="FilterByVault" xml:space="preserve"> <data name="FilterByVault" xml:space="preserve">
<value>Elementləri anbara görə filtrlə</value> <value>Elementləri seyfə görə filtrlə</value>
</data> </data>
<data name="AllVaults" xml:space="preserve"> <data name="AllVaults" xml:space="preserve">
<value>Bütün anbarlar</value> <value>Bütün seyflər</value>
</data> </data>
<data name="Vaults" xml:space="preserve"> <data name="Vaults" xml:space="preserve">
<value>Anbarlar</value> <value>Seyflər</value>
</data> </data>
<data name="VaultFilterDescription" xml:space="preserve"> <data name="VaultFilterDescription" xml:space="preserve">
<value>Anbar: {0}</value> <value>Seyf: {0}</value>
</data> </data>
<data name="All" xml:space="preserve"> <data name="All" xml:space="preserve">
<value>Hamısı</value> <value>Hamısı</value>
@@ -2305,7 +2305,7 @@ Skan prosesi avtomatik baş tutacaq.</value>
<value>Açar uğurla daxil edildikdən sonra, açarı güvənli şəkildə saxlamaq üçün "TOTP əlavə et"i seçin</value> <value>Açar uğurla daxil edildikdən sonra, açarı güvənli şəkildə saxlamaq üçün "TOTP əlavə et"i seçin</value>
</data> </data>
<data name="NeverLockWarning" xml:space="preserve"> <data name="NeverLockWarning" xml:space="preserve">
<value>Kilid seçimlərini "Heç vaxt" olaraq ayarlamaq, anbarınızı cihazınıza müraciəti olan hər kəsə əlçatan edir. Bu seçimi istifadə etsəniz, cihazınızı düzgün qoruduğunuza əmin olmalısınız.</value> <value>Kilid seçimlərini "Heç vaxt" olaraq ayarlamaq, seyfinizi cihazınıza müraciəti olan hər kəsə əlçatan edir. Bu seçimi istifadə etsəniz, cihazınızı düzgün qoruduğunuza əmin olmalısınız.</value>
</data> </data>
<data name="EnvironmentPageUrlsError" xml:space="preserve"> <data name="EnvironmentPageUrlsError" xml:space="preserve">
<value>Daxil edilən bir və ya daha çox URL yararsızdır. Lütfən nəzər salın və yenidən saxlamağa çalışın.</value> <value>Daxil edilən bir və ya daha çox URL yararsızdır. Lütfən nəzər salın və yenidən saxlamağa çalışın.</value>
@@ -2473,7 +2473,7 @@ Skan prosesi avtomatik baş tutacaq.</value>
<value>Əlçatımlılıq Xidməti açıqlaması</value> <value>Əlçatımlılıq Xidməti açıqlaması</value>
</data> </data>
<data name="AccessibilityDisclosureText" xml:space="preserve"> <data name="AccessibilityDisclosureText" xml:space="preserve">
<value>Bitwarden, tətbiqlərdə və veb saytlarda giriş xanalarını axtarmaq üçün Əlçatımlılıq Xidmətini istifadə edir, daha sonra tətbiq və ya sayt üçün uyuşma tapdıqda istifadəçi adı və parolun daxil edilməsi üçün müvafiq sahə kimliklərini yaradır. Xidmət tərəfindən bizə təqdim edilən məlumatların heç birini saxlamırıq, kimlik məlumatlarının daxil edilməsindən kənar ekrandakı hər hansısa elementə nəzarət etməyə cəhd etmirik.</value> <value>Bitwarden, tətbiqlərdə və veb saytlarda giriş xanalarını axtarmaq üçün Əlçatımlılıq Xidmətini istifadə edir, daha sonra tətbiq və ya sayt üçün uyuşma tapdıqda istifadəçi adı və parolun daxil edilməsi üçün müvafiq xana kimliklərini yaradır. Xidmət tərəfindən bizə təqdim edilən məlumatların heç birini saxlamırıq, kimlik məlumatlarının daxil edilməsindən kənar ekrandakı hər hansısa elementə nəzarət etməyə cəhd etmirik.</value>
</data> </data>
<data name="Accept" xml:space="preserve"> <data name="Accept" xml:space="preserve">
<value>Qəbul et</value> <value>Qəbul et</value>
@@ -2514,7 +2514,7 @@ Bu hesaba keçmək istəyirsiniz?</value>
<value>Cihazınıza bir bildiriş göndərildi.</value> <value>Cihazınıza bir bildiriş göndərildi.</value>
</data> </data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve"> <data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Lütfən anbarınızın kilidinin açıq olduğuna və Barmaq izi ifadəsinin digər cihazla uyuşduğuna əmin olun.</value> <value>Lütfən seyfinizin kilidinin açıq olduğuna və Barmaq izi ifadəsinin digər cihazla uyuşduğuna əmin olun.</value>
</data> </data>
<data name="ResendNotification" xml:space="preserve"> <data name="ResendNotification" xml:space="preserve">
<value>Bildirişi təkrar göndər</value> <value>Bildirişi təkrar göndər</value>
@@ -2529,7 +2529,7 @@ Bu hesaba keçmək istəyirsiniz?</value>
<value>Bu tələb artıq yararsızdır</value> <value>Bu tələb artıq yararsızdır</value>
</data> </data>
<data name="PendingLogInRequests" xml:space="preserve"> <data name="PendingLogInRequests" xml:space="preserve">
<value>Giriş tələbləri gözlənilir</value> <value>Gözlənilən giriş tələbləri</value>
</data> </data>
<data name="DeclineAllRequests" xml:space="preserve"> <data name="DeclineAllRequests" xml:space="preserve">
<value>Bütün tələbləri rədd et</value> <value>Bütün tələbləri rədd et</value>
@@ -2601,7 +2601,7 @@ Bu hesaba keçmək istəyirsiniz?</value>
<value>Açarı, mövcud və ya yeni bir elementə əlavə edin</value> <value>Açarı, mövcud və ya yeni bir elementə əlavə edin</value>
</data> </data>
<data name="ThereAreNoItemsInYourVaultThatMatchX" xml:space="preserve"> <data name="ThereAreNoItemsInYourVaultThatMatchX" xml:space="preserve">
<value>Anbarınızda {0} ilə uyuşan heç bir element yoxdur</value> <value>Seyfinizdə "{0}" ilə uyuşan heç bir element yoxdur</value>
</data> </data>
<data name="SearchForAnItemOrAddANewItem" xml:space="preserve"> <data name="SearchForAnItemOrAddANewItem" xml:space="preserve">
<value>Bir element axtarın və ya yenisini əlavə edin</value> <value>Bir element axtarın və ya yenisini əlavə edin</value>
@@ -2625,7 +2625,7 @@ Bu hesaba keçmək istəyirsiniz?</value>
<value>Bölgə</value> <value>Bölgə</value>
</data> </data>
<data name="UpdateWeakMasterPasswordWarning" xml:space="preserve"> <data name="UpdateWeakMasterPasswordWarning" xml:space="preserve">
<value>Ana parolunuz təşkilatınızdakı siyasətlərdən birinə və ya bir neçəsinə uyğun gəlmir. Anbara müraciət üçün ana parolunuzu indi güncəlləməlisiniz. Davam etsəniz, hazırkı seansdan çıxış etmiş və təkrar giriş etməli olacaqsınız. Digər cihazlardakı aktiv seanslar bir saata qədər aktiv qalmağa davam edə bilər.</value> <value>Ana parolunuz təşkilatınızdakı siyasətlərdən birinə və ya bir neçəsinə uyğun gəlmir. Seyfə müraciət üçün ana parolunuzu indi güncəlləməlisiniz. Davam etsəniz, hazırkı seansdan çıxış etmiş və təkrar giriş etməli olacaqsınız. Digər cihazlardakı aktiv seanslar bir saata qədər aktiv qalmağa davam edə bilər.</value>
</data> </data>
<data name="CurrentMasterPassword" xml:space="preserve"> <data name="CurrentMasterPassword" xml:space="preserve">
<value>Hazırkı ana parol</value> <value>Hazırkı ana parol</value>
@@ -2700,7 +2700,7 @@ Bu hesaba keçmək istəyirsiniz?</value>
<value>{0} olaraq giriş edilir</value> <value>{0} olaraq giriş edilir</value>
</data> </data>
<data name="VaultTimeoutActionChangedToLogOut" xml:space="preserve"> <data name="VaultTimeoutActionChangedToLogOut" xml:space="preserve">
<value>Anbar vaxt bitməsi əməliyyatııxış et" olaraq dəyişdirildi</value> <value>Seyfin vaxt bitmə əməliyyatııxış et" olaraq dəyişdirildi</value>
</data> </data>
<data name="BlockAutoFill" xml:space="preserve"> <data name="BlockAutoFill" xml:space="preserve">
<value>Avto-doldurmanı əngəllə</value> <value>Avto-doldurmanı əngəllə</value>
@@ -2758,7 +2758,7 @@ Bu hesaba keçmək istəyirsiniz?</value>
<value>Giriş edilir</value> <value>Giriş edilir</value>
</data> </data>
<data name="Vault" xml:space="preserve"> <data name="Vault" xml:space="preserve">
<value>Anbar</value> <value>Seyf</value>
</data> </data>
<data name="Appearance" xml:space="preserve"> <data name="Appearance" xml:space="preserve">
<value>Görünüş</value> <value>Görünüş</value>
@@ -2807,13 +2807,13 @@ Bu hesaba keçmək istəyirsiniz?</value>
<value>{0} saat</value> <value>{0} saat</value>
</data> </data>
<data name="PasskeyManagementExplanationLong" xml:space="preserve"> <data name="PasskeyManagementExplanationLong" xml:space="preserve">
<value>Use Bitwarden to save new passkeys and log in with passkeys stored in your vault.</value> <value>Yeni keçid açarlarını saxlamaq və seyfinizdəki keçid açarları ilə giriş etmək üçün Bitwarden-i istifadə edin.</value>
</data> </data>
<data name="AutofillServicesExplanationLong" xml:space="preserve"> <data name="AutofillServicesExplanationLong" xml:space="preserve">
<value>Android Avto-doldurma Çərçivəsi, giriş məlumatlarını cihazınızdakı digər tətbiqlərə doldurmağa kömək etmək üçün istifadə olunur.</value> <value>Android Avto-doldurma Çərçivəsi, cihazınızdakı digər tətbiqlərə giriş məlumatlarının doldurulmasına kömək etmək üçün istifadə olunur.</value>
</data> </data>
<data name="UseInlineAutofillExplanationLong" xml:space="preserve"> <data name="UseInlineAutofillExplanationLong" xml:space="preserve">
<value>Seçdiyiniz klaviatura dəstəkləyirsə sətir daxili avto-doldurmanı istifadə edin. Əks halda, ilkin örtük istifadə edin.</value> <value>Seçdiyiniz klaviatura dəstəkləyirsə sətirdaxili avto-doldurmanı istifadə edin. Əks halda, ilkin örtük istifadə edin.</value>
</data> </data>
<data name="AdditionalOptions" xml:space="preserve"> <data name="AdditionalOptions" xml:space="preserve">
<value>Əlavə seçimlər</value> <value>Əlavə seçimlər</value>
@@ -2838,7 +2838,7 @@ Bu hesaba keçmək istəyirsiniz?</value>
<value>Tətbiq mağazası ilə davam edilsin?</value> <value>Tətbiq mağazası ilə davam edilsin?</value>
</data> </data>
<data name="ContinueToDeviceSettings" xml:space="preserve"> <data name="ContinueToDeviceSettings" xml:space="preserve">
<value>Continue to device Settings?</value> <value>Cihaz Ayarlarına davam edilsin?</value>
</data> </data>
<data name="TwoStepLoginDescriptionLong" xml:space="preserve"> <data name="TwoStepLoginDescriptionLong" xml:space="preserve">
<value>Bitwarden veb tətbiqində iki addımlı girişi quraraq hesabınızı daha güvənli edin.</value> <value>Bitwarden veb tətbiqində iki addımlı girişi quraraq hesabınızı daha güvənli edin.</value>
@@ -2847,7 +2847,7 @@ Bu hesaba keçmək istəyirsiniz?</value>
<value>Ana parolunuzu Bitwarden veb tətbiqində dəyişdirə bilərsiniz.</value> <value>Ana parolunuzu Bitwarden veb tətbiqində dəyişdirə bilərsiniz.</value>
</data> </data>
<data name="YouCanImportDataToYourVaultOnX" xml:space="preserve"> <data name="YouCanImportDataToYourVaultOnX" xml:space="preserve">
<value>Datanı {0} üzərindən anbarınıza köçürə bilərsiniz.</value> <value>Datanı {0} üzərindən seyfinizə köçürə bilərsiniz.</value>
<comment>The parameter is an URL, like vault.bitwarden.com.</comment> <comment>The parameter is an URL, like vault.bitwarden.com.</comment>
</data> </data>
<data name="LearnMoreAboutHowToUseBitwardenOnTheHelpCenter" xml:space="preserve"> <data name="LearnMoreAboutHowToUseBitwardenOnTheHelpCenter" xml:space="preserve">
@@ -2863,7 +2863,7 @@ Bu hesaba keçmək istəyirsiniz?</value>
<value>Veb tətbiqində Bitwarden hesabınızın daha çox özəlliyini kəşf edin.</value> <value>Veb tətbiqində Bitwarden hesabınızın daha çox özəlliyini kəşf edin.</value>
</data> </data>
<data name="LearnAboutOrganizationsDescriptionLong" xml:space="preserve"> <data name="LearnAboutOrganizationsDescriptionLong" xml:space="preserve">
<value>Bitwarden, bir təşkilat hesabı istifadə edərək anbar elementlərinizi başqaları ilə paylaşmağınıza icazə verər. bitwarden.com veb saytında ətraflı öyrənin.</value> <value>Bitwarden, bir təşkilatı istifadə edərək seyf elementlərinizi başqaları ilə paylaşmağınıza imkan verir. Daha ətraflı məlumat üçün bitwarden.com saytını ziyarət edin.</value>
</data> </data>
<data name="RateAppDescriptionLong" xml:space="preserve"> <data name="RateAppDescriptionLong" xml:space="preserve">
<value>Başqalarının Bitwarden-in onlar üçün uyğun olub-olmadığını öyrənməkdə kömək edin. Tətbiq mağazasını ziyarət edin və tətbiqimizi qiymətləndirin.</value> <value>Başqalarının Bitwarden-in onlar üçün uyğun olub-olmadığını öyrənməkdə kömək edin. Tətbiq mağazasını ziyarət edin və tətbiqimizi qiymətləndirin.</value>
@@ -2888,28 +2888,28 @@ Bu hesaba keçmək istəyirsiniz?</value>
<value>Təşkilatınız bir ana parol ayarlamağı tələb edir.</value> <value>Təşkilatınız bir ana parol ayarlamağı tələb edir.</value>
</data> </data>
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve"> <data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
<value>Anbar vaxt bitməsi əməliyyatınızı dəyişdirmək üçün bir kilid açma seçimi qurun.</value> <value>Seyf vaxt bitmə əməliyyatınızı dəyişdirmək üçün bir kilid açma seçimi qurun.</value>
</data> </data>
<data name="ChooseALoginToSaveThisPasskeyTo" xml:space="preserve"> <data name="ChooseALoginToSaveThisPasskeyTo" xml:space="preserve">
<value>Choose a login to save this passkey to</value> <value>Bu keçid açarını saxlayacaq bir giriş seçin</value>
</data> </data>
<data name="SavePasskeyAsNewLogin" xml:space="preserve"> <data name="SavePasskeyAsNewLogin" xml:space="preserve">
<value>Save passkey as new login</value> <value>Keçid açarını yeni bir giriş olaraq saxla</value>
</data> </data>
<data name="SavePasskey" xml:space="preserve"> <data name="SavePasskey" xml:space="preserve">
<value>Save passkey</value> <value>Keçid açarını saxla</value>
</data> </data>
<data name="PasskeysForX" xml:space="preserve"> <data name="PasskeysForX" xml:space="preserve">
<value>Passkeys for {0}</value> <value>{0} üçün keçid açarları</value>
</data> </data>
<data name="PasswordsForX" xml:space="preserve"> <data name="PasswordsForX" xml:space="preserve">
<value>Passwords for {0}</value> <value>{0} parolları</value>
</data> </data>
<data name="OverwritePasskey" xml:space="preserve"> <data name="OverwritePasskey" xml:space="preserve">
<value>Overwrite passkey?</value> <value>Keçid açarının üzərinə yazılsın?</value>
</data> </data>
<data name="ThisItemAlreadyContainsAPasskeyAreYouSureYouWantToOverwriteTheCurrentPasskey" xml:space="preserve"> <data name="ThisItemAlreadyContainsAPasskeyAreYouSureYouWantToOverwriteTheCurrentPasskey" xml:space="preserve">
<value>This item already contains a passkey. Are you sure you want to overwrite the current passkey?</value> <value>Bu elementdə artıq bir keçid açarı var. Hazırkı keçid açarının üzərinə yazmaq istədiyinizə əminsiniz?</value>
</data> </data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve"> <data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>Hesabınız üçün Duo iki addımlı giriş tələb olunur. </value> <value>Hesabınız üçün Duo iki addımlı giriş tələb olunur. </value>
@@ -2921,71 +2921,74 @@ Bu hesaba keçmək istəyirsiniz?</value>
<value>Duo-nu başlat</value> <value>Duo-nu başlat</value>
</data> </data>
<data name="VerificationRequiredByX" xml:space="preserve"> <data name="VerificationRequiredByX" xml:space="preserve">
<value>Verification required by {0}</value> <value>{0} tərəfindən doğrulanma tələb olunur</value>
</data> </data>
<data name="VerificationRequiredForThisActionSetUpAnUnlockMethodInBitwardenToContinue" xml:space="preserve"> <data name="VerificationRequiredForThisActionSetUpAnUnlockMethodInBitwardenToContinue" xml:space="preserve">
<value>Verification required for this action. Set up an unlock method in Bitwarden to continue.</value> <value>Bu əməliyyat üçün doğrulama tələb olunur. Davam etmək üçün "Bitwarden"də bir kilid açma üsulu qurun.</value>
</data> </data>
<data name="ErrorCreatingPasskey" xml:space="preserve"> <data name="ErrorCreatingPasskey" xml:space="preserve">
<value>Error creating passkey</value> <value>Keçid açarını yaratma xətası</value>
</data> </data>
<data name="ErrorReadingPasskey" xml:space="preserve"> <data name="ErrorReadingPasskey" xml:space="preserve">
<value>Error reading passkey</value> <value>Keçid açarını oxuma xətası</value>
</data> </data>
<data name="ThereWasAProblemCreatingAPasskeyForXTryAgainLater" xml:space="preserve"> <data name="ThereWasAProblemCreatingAPasskeyForXTryAgainLater" xml:space="preserve">
<value>There was a problem creating a passkey for {0}. Try again later.</value> <value>{0} üçün keçid açarı yaradılarkən bir problem baş verdi. Daha sonra yenidən sınayın.</value>
<comment>The parameter is the RpId</comment> <comment>The parameter is the RpId</comment>
</data> </data>
<data name="ThereWasAProblemReadingAPasskeyForXTryAgainLater" xml:space="preserve"> <data name="ThereWasAProblemReadingAPasskeyForXTryAgainLater" xml:space="preserve">
<value>There was a problem reading your passkey for {0}. Try again later.</value> <value>{0} üçün keçid açarınız oxunarkən bir problem baş verdi. Daha sonra yenidən sınayın.</value>
<comment>The parameter is the RpId</comment> <comment>The parameter is the RpId</comment>
</data> </data>
<data name="VerifyingIdentityEllipsis" xml:space="preserve"> <data name="VerifyingIdentityEllipsis" xml:space="preserve">
<value>Verifying identity...</value> <value>Kimlik doğrulanır...</value>
</data> </data>
<data name="Passwords" xml:space="preserve"> <data name="Passwords" xml:space="preserve">
<value>Passwords</value> <value>Parollar</value>
</data> </data>
<data name="UnknownAccount" xml:space="preserve"> <data name="UnknownAccount" xml:space="preserve">
<value>Unknown account</value> <value>Bilinməyən hesab</value>
</data> </data>
<data name="SetUpAutofill" xml:space="preserve"> <data name="SetUpAutofill" xml:space="preserve">
<value>Set up auto-fill</value> <value>Avto-doldurmanı qur</value>
</data> </data>
<data name="GetInstantAccessToYourPasswordsAndPasskeys" xml:space="preserve"> <data name="GetInstantAccessToYourPasswordsAndPasskeys" xml:space="preserve">
<value>Get instant access to your passwords and passkeys!</value> <value>Parollarınıza və keçid açarlarınıza dərhal müraciət edin!</value>
</data> </data>
<data name="SetUpAutoFillDescriptionLong" xml:space="preserve"> <data name="SetUpAutoFillDescriptionLong" xml:space="preserve">
<value>To set up password auto-fill and passkey management, set Bitwarden as your preferred provider in the iOS Settings.</value> <value>Parolların avto-doldurulmasını və keçid açarlarının idarə edilməsini qurmaq üçün iOS Ayarlarında "Bitwarden"i tərcih edilən provayderiniz olaraq ayarlayın.</value>
</data> </data>
<data name="FirstDotGoToYourDeviceSettingsPasswordsPasswordOptions" xml:space="preserve"> <data name="FirstDotGoToYourDeviceSettingsPasswordsPasswordOptions" xml:space="preserve">
<value>1. Go to your device's Settings &gt; Passwords &gt; Password Options</value> <value>1. Cihazda Ayarlar &gt; Parollar &gt; "Parol seçimləri"nə gedin</value>
</data> </data>
<data name="SecondDotTurnOnAutoFill" xml:space="preserve"> <data name="SecondDotTurnOnAutoFill" xml:space="preserve">
<value>2. Turn on AutoFill</value> <value>2. Avto-doldurmanı işə salın</value>
</data> </data>
<data name="ThirdDotSelectBitwardenToUseForPasswordsAndPasskeys" xml:space="preserve"> <data name="ThirdDotSelectBitwardenToUseForPasswordsAndPasskeys" xml:space="preserve">
<value>3. Select "Bitwarden" to use for passwords and passkeys</value> <value>3. Parollar və keçid açarları üçün istifadə etmək məqsədilə "Bitwarden"i seçin</value>
</data> </data>
<data name="YourPasskeyWillBeSavedToYourBitwardenVault" xml:space="preserve"> <data name="YourPasskeyWillBeSavedToYourBitwardenVault" xml:space="preserve">
<value>Your passkey will be saved to your Bitwarden vault</value> <value>Keçid açarınız Bitwarden seyfinizdə saxlanılacaq</value>
</data> </data>
<data name="YourPasskeyWillBeSavedToYourBitwardenVaultForX" xml:space="preserve"> <data name="YourPasskeyWillBeSavedToYourBitwardenVaultForX" xml:space="preserve">
<value>Your passkey will be saved to your Bitwarden vault for {0}</value> <value>Keçid açarınız {0} üçün Bitwarden seyfinizdə saxlanılacaq</value>
</data>
<data name="OrganizationUnassignedItemsMessageUSEUDescriptionLong" xml:space="preserve">
<value>Təyin edilməmiş təşkilat elementləri artıq Bütün Anbarlar görünüşündə görünməyəndir və yalnız Admin Konsolu vasitəsilə əlçatandır. Bu elementləri görünən etmək üçün Admin Konsolundan bir kolleksiyaya təyin edin.</value>
</data>
<data name="OrganizationUnassignedItemsMessageSelfHost041624DescriptionLong" xml:space="preserve">
<value>16 May 2024-cü ildən etibarən təyin edilməmiş təşkilat elementləri artıq Bütün Anbarlar görünüşündə görünməyən və yalnız Admin Konsolu vasitəsilə əlçatan olacaq. Bu elementləri görünən etmək üçün Admin Konsolundan bir kolleksiyaya təyin edin.</value>
</data>
<data name="RemindMeLater" xml:space="preserve">
<value>Daha sonra xatırlat</value>
</data>
<data name="Notice" xml:space="preserve">
<value>Xəbərdarlıq</value>
</data> </data>
<data name="PasskeysNotSupportedForThisApp" xml:space="preserve"> <data name="PasskeysNotSupportedForThisApp" xml:space="preserve">
<value>Passkeys not supported for this app</value> <value>Keçid açarları bu tətbiq üçün dəstəklənmir</value>
</data>
<data name="PasskeyOperationFailedBecauseBrowserIsNotPrivileged" xml:space="preserve">
<value>Brauzer, imtiyazlı olmadığı üçün keçid açarı əməliyyatı uğursuz oldu</value>
</data>
<data name="PasskeyOperationFailedBecauseBrowserSignatureDoesNotMatch" xml:space="preserve">
<value>Brauzer imzası uyuşmadığı üçün keçid açarı əməliyyatı uğursuz oldu</value>
</data>
<data name="PasskeyOperationFailedBecauseOfMissingAssetLinks" xml:space="preserve">
<value>Əskik varlıq keçidlərinə görə keçid açarı əməliyyatı uğursuz oldu</value>
</data>
<data name="PasskeyOperationFailedBecauseAppNotFoundInAssetLinks" xml:space="preserve">
<value>Varlıq keçidlərində tətbiq tapılmadığına görə keçid açarı əməliyyatı uğursuz oldu</value>
</data>
<data name="PasskeyOperationFailedBecauseAppCouldNotBeVerified" xml:space="preserve">
<value>Tətbiq doğrulana bilmədiyi üçün keçid açarı əməliyyatı uğursuz oldu</value>
</data> </data>
</root> </root>

View File

@@ -2650,10 +2650,10 @@
<value>Запомніць гэту прыладу</value> <value>Запомніць гэту прыладу</value>
</data> </data>
<data name="Passkey" xml:space="preserve"> <data name="Passkey" xml:space="preserve">
<value>Passkey</value> <value>Ключ доступу</value>
</data> </data>
<data name="Passkeys" xml:space="preserve"> <data name="Passkeys" xml:space="preserve">
<value>Passkeys</value> <value>Ключы доступу</value>
</data> </data>
<data name="Application" xml:space="preserve"> <data name="Application" xml:space="preserve">
<value>Праграма</value> <value>Праграма</value>
@@ -2974,19 +2974,22 @@
<data name="YourPasskeyWillBeSavedToYourBitwardenVaultForX" xml:space="preserve"> <data name="YourPasskeyWillBeSavedToYourBitwardenVaultForX" xml:space="preserve">
<value>Your passkey will be saved to your Bitwarden vault for {0}</value> <value>Your passkey will be saved to your Bitwarden vault for {0}</value>
</data> </data>
<data name="OrganizationUnassignedItemsMessageUSEUDescriptionLong" xml:space="preserve">
<value>Unassigned organization items are no longer visible in the All Vaults view and only accessible via the Admin Console. Assign these items to a collection from the Admin Console to make them visible.</value>
</data>
<data name="OrganizationUnassignedItemsMessageSelfHost041624DescriptionLong" xml:space="preserve">
<value>On May 16, 2024, unassigned organization items will no longer be visible in the All Vaults view and only accessible via the Admin Console. Assign these items to a collection from the Admin Console to make them visible.</value>
</data>
<data name="RemindMeLater" xml:space="preserve">
<value>Remind me later</value>
</data>
<data name="Notice" xml:space="preserve">
<value>Notice</value>
</data>
<data name="PasskeysNotSupportedForThisApp" xml:space="preserve"> <data name="PasskeysNotSupportedForThisApp" xml:space="preserve">
<value>Passkeys not supported for this app</value> <value>Passkeys not supported for this app</value>
</data> </data>
<data name="PasskeyOperationFailedBecauseBrowserIsNotPrivileged" xml:space="preserve">
<value>Passkey operation failed because browser is not privileged</value>
</data>
<data name="PasskeyOperationFailedBecauseBrowserSignatureDoesNotMatch" xml:space="preserve">
<value>Passkey operation failed because browser signature does not match</value>
</data>
<data name="PasskeyOperationFailedBecauseOfMissingAssetLinks" xml:space="preserve">
<value>Passkey operation failed because of missing asset links</value>
</data>
<data name="PasskeyOperationFailedBecauseAppNotFoundInAssetLinks" xml:space="preserve">
<value>Passkey operation failed because app not found in asset links</value>
</data>
<data name="PasskeyOperationFailedBecauseAppCouldNotBeVerified" xml:space="preserve">
<value>Passkey operation failed because app could not be verified</value>
</data>
</root> </root>

View File

@@ -422,7 +422,7 @@
<value>Услуга за автоматично дописване</value> <value>Услуга за автоматично дописване</value>
</data> </data>
<data name="SetBitwardenAsPasskeyManagerDescription" xml:space="preserve"> <data name="SetBitwardenAsPasskeyManagerDescription" xml:space="preserve">
<value>Set Bitwarden as your passkey provider in device settings.</value> <value>Задайте Битуорден за свой доставчик за секретни ключове в настройките на устройството.</value>
</data> </data>
<data name="AvoidAmbiguousCharacters" xml:space="preserve"> <data name="AvoidAmbiguousCharacters" xml:space="preserve">
<value>Без нееднозначни знаци</value> <value>Без нееднозначни знаци</value>
@@ -1101,7 +1101,7 @@
<value>Г-ца</value> <value>Г-ца</value>
</data> </data>
<data name="Mx" xml:space="preserve"> <data name="Mx" xml:space="preserve">
<value>Mx</value> <value>Предпочитам да не посочвам</value>
</data> </data>
<data name="November" xml:space="preserve"> <data name="November" xml:space="preserve">
<value>ноември</value> <value>ноември</value>
@@ -1195,7 +1195,7 @@
<value>Идентификация чрез Уиндоус (Windows Hello)</value> <value>Идентификация чрез Уиндоус (Windows Hello)</value>
</data> </data>
<data name="BitwardenCredentialProviderGoToSettings" xml:space="preserve"> <data name="BitwardenCredentialProviderGoToSettings" xml:space="preserve">
<value>We were unable to automatically open the Android credential provider settings menu for you. You can navigate to the credential provider settings menu manually from Android Settings &gt; System &gt; Passwords &amp; accounts &gt; Passwords, passkeys and data services.</value> <value>Екранът с настройките за доставчик на идентификационни данни не може да се отвори автоматично. Може да го достигнете през: Настройки → Системни (Общо управление) → Пароли, кодове за достъп и автоматично попълване.</value>
</data> </data>
<data name="BitwardenAutofillGoToSettings" xml:space="preserve"> <data name="BitwardenAutofillGoToSettings" xml:space="preserve">
<value>Екранът за настройките за автоматично дописване не може да се отвори автоматично. Може да го достигнете през: Настройки (Android Settings) → Системни (System) → Езици и вход (Languages and input) → Допълнителни (Advanced) → Услуга за дописване (Autofill service).</value> <value>Екранът за настройките за автоматично дописване не може да се отвори автоматично. Може да го достигнете през: Настройки (Android Settings) → Системни (System) → Езици и вход (Languages and input) → Допълнителни (Advanced) → Услуга за дописване (Autofill service).</value>
@@ -1822,7 +1822,7 @@
<value>Битуорден има нужда от внимание. Отворете „Изобразяване отгоре“ в „Услуга за автоматично дописване“ в настройките му.</value> <value>Битуорден има нужда от внимание. Отворете „Изобразяване отгоре“ в „Услуга за автоматично дописване“ в настройките му.</value>
</data> </data>
<data name="PasskeyManagement" xml:space="preserve"> <data name="PasskeyManagement" xml:space="preserve">
<value>Passkey management</value> <value>Управление на секретни ключове</value>
</data> </data>
<data name="AutofillServices" xml:space="preserve"> <data name="AutofillServices" xml:space="preserve">
<value>Услуга за автоматично дописване</value> <value>Услуга за автоматично дописване</value>
@@ -2584,16 +2584,16 @@
<value>Проверяване в известните случаи на изтекли данни за тази парола</value> <value>Проверяване в известните случаи на изтекли данни за тази парола</value>
</data> </data>
<data name="ExposedMasterPassword" xml:space="preserve"> <data name="ExposedMasterPassword" xml:space="preserve">
<value>Exposed Master Password</value> <value>Разобличена главна парола</value>
</data> </data>
<data name="PasswordFoundInADataBreachAlertDescription" xml:space="preserve"> <data name="PasswordFoundInADataBreachAlertDescription" xml:space="preserve">
<value>Password found in a data breach. Use a unique password to protect your account. Are you sure you want to use an exposed password?</value> <value>Паролата е намерена в пробив на данни. Използвайте уникална парола, за да защитите Вашия акаунт. Наистина ли искате да използвате слаба парола?</value>
</data> </data>
<data name="WeakAndExposedMasterPassword" xml:space="preserve"> <data name="WeakAndExposedMasterPassword" xml:space="preserve">
<value>Weak and Exposed Master Password</value> <value>Слаба и разобличена главна парола</value>
</data> </data>
<data name="WeakPasswordIdentifiedAndFoundInADataBreachAlertDescription" xml:space="preserve"> <data name="WeakPasswordIdentifiedAndFoundInADataBreachAlertDescription" xml:space="preserve">
<value>Weak password identified and found in a data breach. Use a strong and unique password to protect your account. Are you sure you want to use this password?</value> <value>Разпозната е слаба парола, която присъства в известен случай на изтекли данни. Използвайте сложна и уникална парола, за да защитите Вашия акаунт. Наистина ли искате да използвате тази парола?</value>
</data> </data>
<data name="OrganizationSsoIdentifierRequired" xml:space="preserve"> <data name="OrganizationSsoIdentifierRequired" xml:space="preserve">
<value>Идентификаторът за еднократн идентификация на организация е задължителен.</value> <value>Идентификаторът за еднократн идентификация на организация е задължителен.</value>
@@ -2808,7 +2808,7 @@
<value>{0} часа</value> <value>{0} часа</value>
</data> </data>
<data name="PasskeyManagementExplanationLong" xml:space="preserve"> <data name="PasskeyManagementExplanationLong" xml:space="preserve">
<value>Use Bitwarden to save new passkeys and log in with passkeys stored in your vault.</value> <value>Използване на Битуорден за запазване на новите секретни ключове и вписване с такива запазени в трезора.</value>
</data> </data>
<data name="AutofillServicesExplanationLong" xml:space="preserve"> <data name="AutofillServicesExplanationLong" xml:space="preserve">
<value>Подсистемата за автоматично попълване на Андроид се използва за попълване на данните за вход в други приложения на устройството.</value> <value>Подсистемата за автоматично попълване на Андроид се използва за попълване на данните за вход в други приложения на устройството.</value>
@@ -2839,7 +2839,7 @@
<value>Продължаване към магазина за приложения?</value> <value>Продължаване към магазина за приложения?</value>
</data> </data>
<data name="ContinueToDeviceSettings" xml:space="preserve"> <data name="ContinueToDeviceSettings" xml:space="preserve">
<value>Continue to device Settings?</value> <value>Продължаване към настройките на устройството?</value>
</data> </data>
<data name="TwoStepLoginDescriptionLong" xml:space="preserve"> <data name="TwoStepLoginDescriptionLong" xml:space="preserve">
<value>Подобрете защитата на регистрацията си, като настроите двустепенното удостоверяване в уеб приложението на Битуорден.</value> <value>Подобрете защитата на регистрацията си, като настроите двустепенното удостоверяване в уеб приложението на Битуорден.</value>
@@ -2892,25 +2892,25 @@
<value>Задайте начин за отключване, за да може да промените действието при изтичане на времето за достъп до трезора.</value> <value>Задайте начин за отключване, за да може да промените действието при изтичане на времето за достъп до трезора.</value>
</data> </data>
<data name="ChooseALoginToSaveThisPasskeyTo" xml:space="preserve"> <data name="ChooseALoginToSaveThisPasskeyTo" xml:space="preserve">
<value>Choose a login to save this passkey to</value> <value>Изберете елемент, в който да запазите този секретен ключ</value>
</data> </data>
<data name="SavePasskeyAsNewLogin" xml:space="preserve"> <data name="SavePasskeyAsNewLogin" xml:space="preserve">
<value>Save passkey as new login</value> <value>Запазване на секретния ключ като нов елемент за вписване</value>
</data> </data>
<data name="SavePasskey" xml:space="preserve"> <data name="SavePasskey" xml:space="preserve">
<value>Save passkey</value> <value>Запазване на секретния ключ</value>
</data> </data>
<data name="PasskeysForX" xml:space="preserve"> <data name="PasskeysForX" xml:space="preserve">
<value>Passkeys for {0}</value> <value>Секретни ключове за {0}</value>
</data> </data>
<data name="PasswordsForX" xml:space="preserve"> <data name="PasswordsForX" xml:space="preserve">
<value>Passwords for {0}</value> <value>Пароли за {0}</value>
</data> </data>
<data name="OverwritePasskey" xml:space="preserve"> <data name="OverwritePasskey" xml:space="preserve">
<value>Overwrite passkey?</value> <value>Да се замени ли секретният ключ?</value>
</data> </data>
<data name="ThisItemAlreadyContainsAPasskeyAreYouSureYouWantToOverwriteTheCurrentPasskey" xml:space="preserve"> <data name="ThisItemAlreadyContainsAPasskeyAreYouSureYouWantToOverwriteTheCurrentPasskey" xml:space="preserve">
<value>This item already contains a passkey. Are you sure you want to overwrite the current passkey?</value> <value>Този елемент вече съдържа секретен ключ. Наистина ли искате да замените текущия секретен ключ?</value>
</data> </data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve"> <data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>Вашата регистрация изисква двустепенно удостоверяване чрез Duo. </value> <value>Вашата регистрация изисква двустепенно удостоверяване чрез Duo. </value>
@@ -2922,71 +2922,74 @@
<value>Стартиране на Duo</value> <value>Стартиране на Duo</value>
</data> </data>
<data name="VerificationRequiredByX" xml:space="preserve"> <data name="VerificationRequiredByX" xml:space="preserve">
<value>Verification required by {0}</value> <value>Изисква се потвърждение от {0}</value>
</data> </data>
<data name="VerificationRequiredForThisActionSetUpAnUnlockMethodInBitwardenToContinue" xml:space="preserve"> <data name="VerificationRequiredForThisActionSetUpAnUnlockMethodInBitwardenToContinue" xml:space="preserve">
<value>Verification required for this action. Set up an unlock method in Bitwarden to continue.</value> <value>Това действие изисква потвърждение. Настройте метод за отключване в Битуорден, за да продължите.</value>
</data> </data>
<data name="ErrorCreatingPasskey" xml:space="preserve"> <data name="ErrorCreatingPasskey" xml:space="preserve">
<value>Error creating passkey</value> <value>Грешка при създаването на секретен ключ</value>
</data> </data>
<data name="ErrorReadingPasskey" xml:space="preserve"> <data name="ErrorReadingPasskey" xml:space="preserve">
<value>Error reading passkey</value> <value>Грешка при четенето на секретен ключ</value>
</data> </data>
<data name="ThereWasAProblemCreatingAPasskeyForXTryAgainLater" xml:space="preserve"> <data name="ThereWasAProblemCreatingAPasskeyForXTryAgainLater" xml:space="preserve">
<value>There was a problem creating a passkey for {0}. Try again later.</value> <value>Възникна грешка при създаването на секретен ключ за {0}. Опитайте отново по-късно.</value>
<comment>The parameter is the RpId</comment> <comment>The parameter is the RpId</comment>
</data> </data>
<data name="ThereWasAProblemReadingAPasskeyForXTryAgainLater" xml:space="preserve"> <data name="ThereWasAProblemReadingAPasskeyForXTryAgainLater" xml:space="preserve">
<value>There was a problem reading your passkey for {0}. Try again later.</value> <value>Възникна грешка при прочитането на секретния ключ за {0}. Опитайте отново по-късно.</value>
<comment>The parameter is the RpId</comment> <comment>The parameter is the RpId</comment>
</data> </data>
<data name="VerifyingIdentityEllipsis" xml:space="preserve"> <data name="VerifyingIdentityEllipsis" xml:space="preserve">
<value>Verifying identity...</value> <value>Потвърждаване на самоличността…</value>
</data> </data>
<data name="Passwords" xml:space="preserve"> <data name="Passwords" xml:space="preserve">
<value>Passwords</value> <value>Пароли</value>
</data> </data>
<data name="UnknownAccount" xml:space="preserve"> <data name="UnknownAccount" xml:space="preserve">
<value>Unknown account</value> <value>Неизвестна регистрация</value>
</data> </data>
<data name="SetUpAutofill" xml:space="preserve"> <data name="SetUpAutofill" xml:space="preserve">
<value>Set up auto-fill</value> <value>Настройте автоматичното попълване</value>
</data> </data>
<data name="GetInstantAccessToYourPasswordsAndPasskeys" xml:space="preserve"> <data name="GetInstantAccessToYourPasswordsAndPasskeys" xml:space="preserve">
<value>Get instant access to your passwords and passkeys!</value> <value>Незабавен достъп до паролите и секретните ключове!</value>
</data> </data>
<data name="SetUpAutoFillDescriptionLong" xml:space="preserve"> <data name="SetUpAutoFillDescriptionLong" xml:space="preserve">
<value>To set up password auto-fill and passkey management, set Bitwarden as your preferred provider in the iOS Settings.</value> <value>За да настроите автоматичното попълване на пароли и управлението на секретни ключове, задайте Битуорден като предпочитан доставчик за това в настройките на iOS.</value>
</data> </data>
<data name="FirstDotGoToYourDeviceSettingsPasswordsPasswordOptions" xml:space="preserve"> <data name="FirstDotGoToYourDeviceSettingsPasswordsPasswordOptions" xml:space="preserve">
<value>1. Go to your device's Settings &gt; Passwords &gt; Password Options</value> <value>1. Идете в Настройките на устройството &gt; Пароли &gt; Настройки за паролите</value>
</data> </data>
<data name="SecondDotTurnOnAutoFill" xml:space="preserve"> <data name="SecondDotTurnOnAutoFill" xml:space="preserve">
<value>2. Turn on AutoFill</value> <value>2. Включете автоматичното попълване</value>
</data> </data>
<data name="ThirdDotSelectBitwardenToUseForPasswordsAndPasskeys" xml:space="preserve"> <data name="ThirdDotSelectBitwardenToUseForPasswordsAndPasskeys" xml:space="preserve">
<value>3. Select "Bitwarden" to use for passwords and passkeys</value> <value>3. Изберете, че искате да използвате „Битуорден“ за пароли и секретни ключове</value>
</data> </data>
<data name="YourPasskeyWillBeSavedToYourBitwardenVault" xml:space="preserve"> <data name="YourPasskeyWillBeSavedToYourBitwardenVault" xml:space="preserve">
<value>Your passkey will be saved to your Bitwarden vault</value> <value>Секретният ключ ще бъде запазен в трезора на Битуорден</value>
</data> </data>
<data name="YourPasskeyWillBeSavedToYourBitwardenVaultForX" xml:space="preserve"> <data name="YourPasskeyWillBeSavedToYourBitwardenVaultForX" xml:space="preserve">
<value>Your passkey will be saved to your Bitwarden vault for {0}</value> <value>Секретният ключ ще бъде запазен в трезора на Битуорден за {0}</value>
</data>
<data name="OrganizationUnassignedItemsMessageUSEUDescriptionLong" xml:space="preserve">
<value>Неразпределените елементи на организацията вече не се виждат в изгледа с „Всички трезори“, а са достъпни само през Административната конзола. Добавете тези елементи към някоя колекция в Административната конзола, за да станат видими.</value>
</data>
<data name="OrganizationUnassignedItemsMessageSelfHost041624DescriptionLong" xml:space="preserve">
<value>От 16 май 2024г. неразпределените елементи на организациите вече няма се виждат в изгледа с „Всички трезори“, а ще бъдат достъпни само през Административната конзола. Добавете тези елементи към някоя колекция в Административната конзола, за да станат видими.</value>
</data>
<data name="RemindMeLater" xml:space="preserve">
<value>Напомнете ми по-късно</value>
</data>
<data name="Notice" xml:space="preserve">
<value>Известие</value>
</data> </data>
<data name="PasskeysNotSupportedForThisApp" xml:space="preserve"> <data name="PasskeysNotSupportedForThisApp" xml:space="preserve">
<value>Passkeys not supported for this app</value> <value>За това приложение не се поддържат секретни ключове</value>
</data>
<data name="PasskeyOperationFailedBecauseBrowserIsNotPrivileged" xml:space="preserve">
<value>Операцията със секретния ключ беше неуспешна, тъй като потребителят не може да бъде потвърден.</value>
</data>
<data name="PasskeyOperationFailedBecauseBrowserSignatureDoesNotMatch" xml:space="preserve">
<value>Операцията със секретния ключ беше неуспешна, тъй като подписът в браузъра не съвпада</value>
</data>
<data name="PasskeyOperationFailedBecauseOfMissingAssetLinks" xml:space="preserve">
<value>Операцията със секретния ключ беше неуспешна, поради липсващи връзки към ресурси</value>
</data>
<data name="PasskeyOperationFailedBecauseAppNotFoundInAssetLinks" xml:space="preserve">
<value>Операцията със секретния ключ беше неуспешна, тъй като приложението не е намерено измежду връзките към ресурси</value>
</data>
<data name="PasskeyOperationFailedBecauseAppCouldNotBeVerified" xml:space="preserve">
<value>Операцията със секретния ключ беше неуспешна, тъй като приложението не може да бъде потвърдено</value>
</data> </data>
</root> </root>

View File

@@ -2769,7 +2769,7 @@ Do you want to switch to this account?</value>
<value>Account security</value> <value>Account security</value>
</data> </data>
<data name="BitwardenHelpCenter" xml:space="preserve"> <data name="BitwardenHelpCenter" xml:space="preserve">
<value>Bitwarden Help Center</value> <value>Bitwarden help center</value>
</data> </data>
<data name="ContactBitwardenSupport" xml:space="preserve"> <data name="ContactBitwardenSupport" xml:space="preserve">
<value>Contact Bitwarden support</value> <value>Contact Bitwarden support</value>
@@ -2975,19 +2975,22 @@ Do you want to switch to this account?</value>
<data name="YourPasskeyWillBeSavedToYourBitwardenVaultForX" xml:space="preserve"> <data name="YourPasskeyWillBeSavedToYourBitwardenVaultForX" xml:space="preserve">
<value>Your passkey will be saved to your Bitwarden vault for {0}</value> <value>Your passkey will be saved to your Bitwarden vault for {0}</value>
</data> </data>
<data name="OrganizationUnassignedItemsMessageUSEUDescriptionLong" xml:space="preserve">
<value>Unassigned organization items are no longer visible in the All Vaults view and only accessible via the Admin Console. Assign these items to a collection from the Admin Console to make them visible.</value>
</data>
<data name="OrganizationUnassignedItemsMessageSelfHost041624DescriptionLong" xml:space="preserve">
<value>On May 16, 2024, unassigned organization items will no longer be visible in the All Vaults view and only accessible via the Admin Console. Assign these items to a collection from the Admin Console to make them visible.</value>
</data>
<data name="RemindMeLater" xml:space="preserve">
<value>Remind me later</value>
</data>
<data name="Notice" xml:space="preserve">
<value>Notice</value>
</data>
<data name="PasskeysNotSupportedForThisApp" xml:space="preserve"> <data name="PasskeysNotSupportedForThisApp" xml:space="preserve">
<value>Passkeys not supported for this app</value> <value>Passkeys not supported for this app</value>
</data> </data>
<data name="PasskeyOperationFailedBecauseBrowserIsNotPrivileged" xml:space="preserve">
<value>Passkey operation failed because browser is not privileged</value>
</data>
<data name="PasskeyOperationFailedBecauseBrowserSignatureDoesNotMatch" xml:space="preserve">
<value>Passkey operation failed because browser signature does not match</value>
</data>
<data name="PasskeyOperationFailedBecauseOfMissingAssetLinks" xml:space="preserve">
<value>Passkey operation failed because of missing asset links</value>
</data>
<data name="PasskeyOperationFailedBecauseAppNotFoundInAssetLinks" xml:space="preserve">
<value>Passkey operation failed because app not found in asset links</value>
</data>
<data name="PasskeyOperationFailedBecauseAppCouldNotBeVerified" xml:space="preserve">
<value>Passkey operation failed because app could not be verified</value>
</data>
</root> </root>

View File

@@ -190,7 +190,7 @@
<comment>Full label for a email address.</comment> <comment>Full label for a email address.</comment>
</data> </data>
<data name="EmailUs" xml:space="preserve"> <data name="EmailUs" xml:space="preserve">
<value>Pošaljite nam E-Mail </value> <value>Pošaljite nam E-Mail</value>
</data> </data>
<data name="EmailUsDescription" xml:space="preserve"> <data name="EmailUsDescription" xml:space="preserve">
<value>Pošaljite nam E-Mail direktno da biste dobili pomoć ili ostavili povratne informacije.</value> <value>Pošaljite nam E-Mail direktno da biste dobili pomoć ili ostavili povratne informacije.</value>
@@ -203,7 +203,7 @@
<comment>Title for your favorite items in the vault.</comment> <comment>Title for your favorite items in the vault.</comment>
</data> </data>
<data name="FileBugReport" xml:space="preserve"> <data name="FileBugReport" xml:space="preserve">
<value>Podnesite izvještaj o greški </value> <value>Podnesite izvještaj o greški</value>
</data> </data>
<data name="FileBugReportDescription" xml:space="preserve"> <data name="FileBugReportDescription" xml:space="preserve">
<value>Prijavi problem u našem GitHub repozitoriju.</value> <value>Prijavi problem u našem GitHub repozitoriju.</value>
@@ -394,7 +394,7 @@
<value>Prikaz</value> <value>Prikaz</value>
</data> </data>
<data name="VisitOurWebsite" xml:space="preserve"> <data name="VisitOurWebsite" xml:space="preserve">
<value>Posjetite našu Web Stranicu </value> <value>Posjetite našu Web Stranicu</value>
</data> </data>
<data name="Website" xml:space="preserve"> <data name="Website" xml:space="preserve">
<value>Web stranica</value> <value>Web stranica</value>
@@ -502,7 +502,7 @@
<value>Dodirnite Bitwarden ikonu u meniju da biste pokrenuli dodatak.</value> <value>Dodirnite Bitwarden ikonu u meniju da biste pokrenuli dodatak.</value>
</data> </data>
<data name="ExtensionTurnOn" xml:space="preserve"> <data name="ExtensionTurnOn" xml:space="preserve">
<value> Da biste uključili Bitwarden u Safari-ju i drugim aplikacijama, dodirnite ikonu „više“ u donjem redu menija.</value> <value>Da biste uključili Bitwarden u Safari-ju i drugim aplikacijama, dodirnite ikonu „više“ u donjem redu menija.</value>
</data> </data>
<data name="Favorite" xml:space="preserve"> <data name="Favorite" xml:space="preserve">
<value>Omiljene</value> <value>Omiljene</value>
@@ -1301,13 +1301,13 @@ Skeniranje će biti izvršeno automatski.</value>
<value>Preporučeno je onemogućiti bilo koje druge aplikacije za automatsko popunjavanje lozinki u Postavkama uređaja ukoliko ih ne planirate koristiti.</value> <value>Preporučeno je onemogućiti bilo koje druge aplikacije za automatsko popunjavanje lozinki u Postavkama uređaja ukoliko ih ne planirate koristiti.</value>
</data> </data>
<data name="BitwardenAutofillDescription" xml:space="preserve"> <data name="BitwardenAutofillDescription" xml:space="preserve">
<value>Pristupite vašem trezoru direktno putem vaše tastature da brže unesete vaše lozinke. </value> <value>Pristupite vašem trezoru direktno putem vaše tastature da brže unesete vaše lozinke.</value>
</data> </data>
<data name="AutofillTurnOn" xml:space="preserve"> <data name="AutofillTurnOn" xml:space="preserve">
<value>Da bi omogućili automatsko popunjavanje lozinki na vašem uređaju, molimo vas da pratite sljedeće upute:</value> <value>Da bi omogućili automatsko popunjavanje lozinki na vašem uređaju, molimo vas da pratite sljedeće upute:</value>
</data> </data>
<data name="AutofillTurnOn1" xml:space="preserve"> <data name="AutofillTurnOn1" xml:space="preserve">
<value>1. Otvorite Postavke na Vašem uređaju </value> <value>1. Otvorite Postavke na Vašem uređaju</value>
</data> </data>
<data name="AutofillTurnOn2" xml:space="preserve"> <data name="AutofillTurnOn2" xml:space="preserve">
<value>2. Otvorite "Lozinke"</value> <value>2. Otvorite "Lozinke"</value>
@@ -1316,7 +1316,7 @@ Skeniranje će biti izvršeno automatski.</value>
<value>3. Pritisnite "Auto ispuna lozinki"</value> <value>3. Pritisnite "Auto ispuna lozinki"</value>
</data> </data>
<data name="AutofillTurnOn4" xml:space="preserve"> <data name="AutofillTurnOn4" xml:space="preserve">
<value>4. Uključite automatsko ispunjavanje </value> <value>4. Uključite automatsko ispunjavanje</value>
</data> </data>
<data name="AutofillTurnOn5" xml:space="preserve"> <data name="AutofillTurnOn5" xml:space="preserve">
<value>5. Odaberite Bitwarden</value> <value>5. Odaberite Bitwarden</value>
@@ -1340,7 +1340,7 @@ Skeniranje će biti izvršeno automatski.</value>
<value>Prijave</value> <value>Prijave</value>
</data> </data>
<data name="SecureNotes" xml:space="preserve"> <data name="SecureNotes" xml:space="preserve">
<value>Sigurna zabilješke </value> <value>Sigurna zabilješke</value>
</data> </data>
<data name="AllItems" xml:space="preserve"> <data name="AllItems" xml:space="preserve">
<value>Sve spremljene lozinke</value> <value>Sve spremljene lozinke</value>
@@ -1446,14 +1446,14 @@ Skeniranje će biti izvršeno automatski.</value>
<value>Šifra</value> <value>Šifra</value>
</data> </data>
<data name="WordSeparator" xml:space="preserve"> <data name="WordSeparator" xml:space="preserve">
<value>Odvajač riječi </value> <value>Odvajač riječi</value>
</data> </data>
<data name="Clear" xml:space="preserve"> <data name="Clear" xml:space="preserve">
<value>Obriši</value> <value>Obriši</value>
<comment>To clear something out. example: To clear browser history.</comment> <comment>To clear something out. example: To clear browser history.</comment>
</data> </data>
<data name="Generator" xml:space="preserve"> <data name="Generator" xml:space="preserve">
<value>Generator </value> <value>Generator</value>
<comment>Short for "Password Generator"</comment> <comment>Short for "Password Generator"</comment>
</data> </data>
<data name="NoFoldersToList" xml:space="preserve"> <data name="NoFoldersToList" xml:space="preserve">
@@ -1477,7 +1477,7 @@ Skeniranje će biti izvršeno automatski.</value>
<value>Zaključaj odmah</value> <value>Zaključaj odmah</value>
</data> </data>
<data name="PIN" xml:space="preserve"> <data name="PIN" xml:space="preserve">
<value>PIN </value> <value>PIN</value>
</data> </data>
<data name="Unlock" xml:space="preserve"> <data name="Unlock" xml:space="preserve">
<value>Otključaj</value> <value>Otključaj</value>
@@ -1528,7 +1528,7 @@ Skeniranje će biti izvršeno automatski.</value>
<value>2 minute</value> <value>2 minute</value>
</data> </data>
<data name="ClearClipboard" xml:space="preserve"> <data name="ClearClipboard" xml:space="preserve">
<value>Očisti međumemoriju </value> <value>Očisti međumemoriju</value>
<comment>Clipboard is the operating system thing where you copy/paste data to on your device.</comment> <comment>Clipboard is the operating system thing where you copy/paste data to on your device.</comment>
</data> </data>
<data name="ClearClipboardDescription" xml:space="preserve"> <data name="ClearClipboardDescription" xml:space="preserve">
@@ -1684,7 +1684,7 @@ Skeniranje će biti izvršeno automatski.</value>
<value>Trezor uspješno izvezen</value> <value>Trezor uspješno izvezen</value>
</data> </data>
<data name="Clone" xml:space="preserve"> <data name="Clone" xml:space="preserve">
<value>Kopiraj identično </value> <value>Kopiraj identično</value>
<comment>Clone an entity (verb).</comment> <comment>Clone an entity (verb).</comment>
</data> </data>
<data name="PasswordGeneratorPolicyInEffect" xml:space="preserve"> <data name="PasswordGeneratorPolicyInEffect" xml:space="preserve">
@@ -1727,7 +1727,7 @@ Skeniranje će biti izvršeno automatski.</value>
<comment>Confirmation message after successfully restoring a soft-deleted item</comment> <comment>Confirmation message after successfully restoring a soft-deleted item</comment>
</data> </data>
<data name="Trash" xml:space="preserve"> <data name="Trash" xml:space="preserve">
<value>Smeće </value> <value>Smeće</value>
<comment>(noun) Location of deleted items which have not yet been permanently deleted</comment> <comment>(noun) Location of deleted items which have not yet been permanently deleted</comment>
</data> </data>
<data name="SearchTrash" xml:space="preserve"> <data name="SearchTrash" xml:space="preserve">
@@ -1837,7 +1837,7 @@ Skeniranje će biti izvršeno automatski.</value>
<value>Koristi pristupačnost</value> <value>Koristi pristupačnost</value>
</data> </data>
<data name="AccessibilityDescription" xml:space="preserve"> <data name="AccessibilityDescription" xml:space="preserve">
<value>Koristi uslugu Bitwarden pristupačnosti za auto-ispunu tvojih prijava u aplikacijama i na webu. Kada je uključeno, prilikom odabira polja za prijavu, prikazati će se iskočni okvir. </value> <value>Koristi uslugu Bitwarden pristupačnosti za auto-ispunu tvojih prijava u aplikacijama i na webu. Kada je uključeno, prilikom odabira polja za prijavu, prikazati će se iskočni okvir.</value>
</data> </data>
<data name="AccessibilityDescription2" xml:space="preserve"> <data name="AccessibilityDescription2" xml:space="preserve">
<value>Koristi uslugu Bitwarden pristupačnosti za auto-ispunu tvojih prijava u aplikacijama i na webu (Zahtijeva uključenu opciju „Koristi preklapanje”).</value> <value>Koristi uslugu Bitwarden pristupačnosti za auto-ispunu tvojih prijava u aplikacijama i na webu (Zahtijeva uključenu opciju „Koristi preklapanje”).</value>
@@ -1924,7 +1924,7 @@ Skeniranje će biti izvršeno automatski.</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment> <comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data> </data>
<data name="PendingDelete" xml:space="preserve"> <data name="PendingDelete" xml:space="preserve">
<value>Brisanje na čekanju </value> <value>Brisanje na čekanju</value>
</data> </data>
<data name="ExpirationDate" xml:space="preserve"> <data name="ExpirationDate" xml:space="preserve">
<value>Rok upotrebe</value> <value>Rok upotrebe</value>
@@ -1966,7 +1966,7 @@ Skeniranje će biti izvršeno automatski.</value>
<value>Sigurno želiš ukloniti lozinku?</value> <value>Sigurno želiš ukloniti lozinku?</value>
</data> </data>
<data name="RemovingSendPassword" xml:space="preserve"> <data name="RemovingSendPassword" xml:space="preserve">
<value>Uklanjanje lozinke </value> <value>Uklanjanje lozinke</value>
</data> </data>
<data name="SendPasswordRemoved" xml:space="preserve"> <data name="SendPasswordRemoved" xml:space="preserve">
<value>Lozinka je uklonjena.</value> <value>Lozinka je uklonjena.</value>
@@ -2149,13 +2149,13 @@ Skeniranje će biti izvršeno automatski.</value>
<value>Vrijeme isteka premašuje ograničenje koju je postavila tvoja organizacija.</value> <value>Vrijeme isteka premašuje ograničenje koju je postavila tvoja organizacija.</value>
</data> </data>
<data name="DisablePersonalVaultExportPolicyInEffect" xml:space="preserve"> <data name="DisablePersonalVaultExportPolicyInEffect" xml:space="preserve">
<value>Jedno ili više pravila organizacija onemogućuje izvoz osobnog trezora. </value> <value>Jedno ili više pravila organizacija onemogućuje izvoz osobnog trezora.</value>
</data> </data>
<data name="AddAccount" xml:space="preserve"> <data name="AddAccount" xml:space="preserve">
<value>Dodaj račun</value> <value>Dodaj račun</value>
</data> </data>
<data name="AccountUnlocked" xml:space="preserve"> <data name="AccountUnlocked" xml:space="preserve">
<value>Otključano </value> <value>Otključano</value>
</data> </data>
<data name="AccountLocked" xml:space="preserve"> <data name="AccountLocked" xml:space="preserve">
<value>Zaključano</value> <value>Zaključano</value>
@@ -2164,13 +2164,13 @@ Skeniranje će biti izvršeno automatski.</value>
<value>Odjavljeno</value> <value>Odjavljeno</value>
</data> </data>
<data name="AccountSwitchedAutomatically" xml:space="preserve"> <data name="AccountSwitchedAutomatically" xml:space="preserve">
<value>Prebačeni ste na sljedeći dostupan račun </value> <value>Prebačeni ste na sljedeći dostupan račun</value>
</data> </data>
<data name="AccountLockedSuccessfully" xml:space="preserve"> <data name="AccountLockedSuccessfully" xml:space="preserve">
<value>Račun zaključan </value> <value>Račun zaključan</value>
</data> </data>
<data name="AccountLoggedOutSuccessfully" xml:space="preserve"> <data name="AccountLoggedOutSuccessfully" xml:space="preserve">
<value>Uspješno odjavljeni sa računa </value> <value>Uspješno odjavljeni sa računa</value>
</data> </data>
<data name="AccountRemovedSuccessfully" xml:space="preserve"> <data name="AccountRemovedSuccessfully" xml:space="preserve">
<value>Račun je uspješno uklonjen</value> <value>Račun je uspješno uklonjen</value>
@@ -2206,7 +2206,7 @@ Skeniranje će biti izvršeno automatski.</value>
<value>Kopiraj link od Send-a prilikom spremanja</value> <value>Kopiraj link od Send-a prilikom spremanja</value>
</data> </data>
<data name="SendingCode" xml:space="preserve"> <data name="SendingCode" xml:space="preserve">
<value>Kod se šalje </value> <value>Kod se šalje</value>
</data> </data>
<data name="Verifying" xml:space="preserve"> <data name="Verifying" xml:space="preserve">
<value>Provjera u toku</value> <value>Provjera u toku</value>
@@ -2767,7 +2767,7 @@ Skeniranje će biti izvršeno automatski.</value>
<value>Account security</value> <value>Account security</value>
</data> </data>
<data name="BitwardenHelpCenter" xml:space="preserve"> <data name="BitwardenHelpCenter" xml:space="preserve">
<value>Bitwarden Help Center</value> <value>Bitwarden help center</value>
</data> </data>
<data name="ContactBitwardenSupport" xml:space="preserve"> <data name="ContactBitwardenSupport" xml:space="preserve">
<value>Contact Bitwarden support</value> <value>Contact Bitwarden support</value>
@@ -2973,19 +2973,22 @@ Skeniranje će biti izvršeno automatski.</value>
<data name="YourPasskeyWillBeSavedToYourBitwardenVaultForX" xml:space="preserve"> <data name="YourPasskeyWillBeSavedToYourBitwardenVaultForX" xml:space="preserve">
<value>Your passkey will be saved to your Bitwarden vault for {0}</value> <value>Your passkey will be saved to your Bitwarden vault for {0}</value>
</data> </data>
<data name="OrganizationUnassignedItemsMessageUSEUDescriptionLong" xml:space="preserve">
<value>Unassigned organization items are no longer visible in the All Vaults view and only accessible via the Admin Console. Assign these items to a collection from the Admin Console to make them visible.</value>
</data>
<data name="OrganizationUnassignedItemsMessageSelfHost041624DescriptionLong" xml:space="preserve">
<value>On May 16, 2024, unassigned organization items will no longer be visible in the All Vaults view and only accessible via the Admin Console. Assign these items to a collection from the Admin Console to make them visible.</value>
</data>
<data name="RemindMeLater" xml:space="preserve">
<value>Remind me later</value>
</data>
<data name="Notice" xml:space="preserve">
<value>Notice</value>
</data>
<data name="PasskeysNotSupportedForThisApp" xml:space="preserve"> <data name="PasskeysNotSupportedForThisApp" xml:space="preserve">
<value>Passkeys not supported for this app</value> <value>Passkeys not supported for this app</value>
</data> </data>
<data name="PasskeyOperationFailedBecauseBrowserIsNotPrivileged" xml:space="preserve">
<value>Passkey operation failed because browser is not privileged</value>
</data>
<data name="PasskeyOperationFailedBecauseBrowserSignatureDoesNotMatch" xml:space="preserve">
<value>Passkey operation failed because browser signature does not match</value>
</data>
<data name="PasskeyOperationFailedBecauseOfMissingAssetLinks" xml:space="preserve">
<value>Passkey operation failed because of missing asset links</value>
</data>
<data name="PasskeyOperationFailedBecauseAppNotFoundInAssetLinks" xml:space="preserve">
<value>Passkey operation failed because app not found in asset links</value>
</data>
<data name="PasskeyOperationFailedBecauseAppCouldNotBeVerified" xml:space="preserve">
<value>Passkey operation failed because app could not be verified</value>
</data>
</root> </root>

View File

@@ -422,7 +422,7 @@
<value>Servei d'emplenament automàtic</value> <value>Servei d'emplenament automàtic</value>
</data> </data>
<data name="SetBitwardenAsPasskeyManagerDescription" xml:space="preserve"> <data name="SetBitwardenAsPasskeyManagerDescription" xml:space="preserve">
<value>Set Bitwarden as your passkey provider in device settings.</value> <value>Estableix Bitwarden com a proveïdor de claus de pas a la configuració del dispositiu.</value>
</data> </data>
<data name="AvoidAmbiguousCharacters" xml:space="preserve"> <data name="AvoidAmbiguousCharacters" xml:space="preserve">
<value>Eviteu caràcters ambigus</value> <value>Eviteu caràcters ambigus</value>
@@ -1195,7 +1195,7 @@ L'escaneig es farà automàticament.</value>
<value>Windows Hello</value> <value>Windows Hello</value>
</data> </data>
<data name="BitwardenCredentialProviderGoToSettings" xml:space="preserve"> <data name="BitwardenCredentialProviderGoToSettings" xml:space="preserve">
<value>We were unable to automatically open the Android credential provider settings menu for you. You can navigate to the credential provider settings menu manually from Android Settings &gt; System &gt; Passwords &amp; accounts &gt; Passwords, passkeys and data services.</value> <value>No hem pogut obrir automàticament el menú de configuració del proveïdor de credencials d'Android. Podeu navegar fins al menú de configuració del proveïdor de credencials manualment des de Configuració d'Android &gt; Sistema &gt; Contrasenyes i comptes &gt; Contrasenyes, claus de pas i serveis de dades.</value>
</data> </data>
<data name="BitwardenAutofillGoToSettings" xml:space="preserve"> <data name="BitwardenAutofillGoToSettings" xml:space="preserve">
<value>No hem pogut obrir automàticament el menú de configuració de l'emplenament automàtic d'Android. Podeu anar manualment des de la configuració d'Android &gt; Sistema &gt; Idiomes i entrada &gt; Avançat &gt; Servei d'emplenament automàtic.</value> <value>No hem pogut obrir automàticament el menú de configuració de l'emplenament automàtic d'Android. Podeu anar manualment des de la configuració d'Android &gt; Sistema &gt; Idiomes i entrada &gt; Avançat &gt; Servei d'emplenament automàtic.</value>
@@ -1822,7 +1822,7 @@ L'escaneig es farà automàticament.</value>
<value>Bitwarden necessita atenció: activeu l'opció "Dibuixa-sobre" a "Serveis d'emplenament automàtic" a Configuració de Bitwarden</value> <value>Bitwarden necessita atenció: activeu l'opció "Dibuixa-sobre" a "Serveis d'emplenament automàtic" a Configuració de Bitwarden</value>
</data> </data>
<data name="PasskeyManagement" xml:space="preserve"> <data name="PasskeyManagement" xml:space="preserve">
<value>Passkey management</value> <value>Gestió de claus de pas</value>
</data> </data>
<data name="AutofillServices" xml:space="preserve"> <data name="AutofillServices" xml:space="preserve">
<value>Serveis d'emplenament automàtic</value> <value>Serveis d'emplenament automàtic</value>
@@ -2808,7 +2808,7 @@ Voleu canviar a aquest compte?</value>
<value>{0} hores</value> <value>{0} hores</value>
</data> </data>
<data name="PasskeyManagementExplanationLong" xml:space="preserve"> <data name="PasskeyManagementExplanationLong" xml:space="preserve">
<value>Use Bitwarden to save new passkeys and log in with passkeys stored in your vault.</value> <value>Utilitzeu Bitwarden per guardar claus de pas noves i iniciar sessió amb les claus emmagatzemades a la vostra caixa forta.</value>
</data> </data>
<data name="AutofillServicesExplanationLong" xml:space="preserve"> <data name="AutofillServicesExplanationLong" xml:space="preserve">
<value>El marc d'emplenament automàtic d'Android s'utilitza per ajudar a omplir la informació d'inici de sessió a altres aplicacions del vostre dispositiu.</value> <value>El marc d'emplenament automàtic d'Android s'utilitza per ajudar a omplir la informació d'inici de sessió a altres aplicacions del vostre dispositiu.</value>
@@ -2839,7 +2839,7 @@ Voleu canviar a aquest compte?</value>
<value>Voleu continuar cap a l'app store?</value> <value>Voleu continuar cap a l'app store?</value>
</data> </data>
<data name="ContinueToDeviceSettings" xml:space="preserve"> <data name="ContinueToDeviceSettings" xml:space="preserve">
<value>Continue to device Settings?</value> <value>Voleu continuar a la configuració del dispositiu?</value>
</data> </data>
<data name="TwoStepLoginDescriptionLong" xml:space="preserve"> <data name="TwoStepLoginDescriptionLong" xml:space="preserve">
<value>Fes que el vostre compte siga més segur configurant l'inici de sessió en dos passos a l'aplicació web de Bitwarden.</value> <value>Fes que el vostre compte siga més segur configurant l'inici de sessió en dos passos a l'aplicació web de Bitwarden.</value>
@@ -2892,25 +2892,25 @@ Voleu canviar a aquest compte?</value>
<value>Configura una opció de desbloqueig per canviar l'acció de temps d'espera de la caixa forta.</value> <value>Configura una opció de desbloqueig per canviar l'acció de temps d'espera de la caixa forta.</value>
</data> </data>
<data name="ChooseALoginToSaveThisPasskeyTo" xml:space="preserve"> <data name="ChooseALoginToSaveThisPasskeyTo" xml:space="preserve">
<value>Choose a login to save this passkey to</value> <value>Trieu un inici de sessió per guardar aquesta clau de pas</value>
</data> </data>
<data name="SavePasskeyAsNewLogin" xml:space="preserve"> <data name="SavePasskeyAsNewLogin" xml:space="preserve">
<value>Save passkey as new login</value> <value>Guarda la clau de pas com a nou inici de sessió</value>
</data> </data>
<data name="SavePasskey" xml:space="preserve"> <data name="SavePasskey" xml:space="preserve">
<value>Save passkey</value> <value>Guarda la clau de pas</value>
</data> </data>
<data name="PasskeysForX" xml:space="preserve"> <data name="PasskeysForX" xml:space="preserve">
<value>Passkeys for {0}</value> <value>Claus de pas per a {0}</value>
</data> </data>
<data name="PasswordsForX" xml:space="preserve"> <data name="PasswordsForX" xml:space="preserve">
<value>Passwords for {0}</value> <value>Contrasenyes per a {0}</value>
</data> </data>
<data name="OverwritePasskey" xml:space="preserve"> <data name="OverwritePasskey" xml:space="preserve">
<value>Overwrite passkey?</value> <value>Sobreescriure la clau de pas?</value>
</data> </data>
<data name="ThisItemAlreadyContainsAPasskeyAreYouSureYouWantToOverwriteTheCurrentPasskey" xml:space="preserve"> <data name="ThisItemAlreadyContainsAPasskeyAreYouSureYouWantToOverwriteTheCurrentPasskey" xml:space="preserve">
<value>This item already contains a passkey. Are you sure you want to overwrite the current passkey?</value> <value>Aquest element ja conté una clau de pas. Esteu segur que voleu sobreescriure la actual?</value>
</data> </data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve"> <data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>Es requereix l'inici de sessió en dos passos de DUO al vostre compte. </value> <value>Es requereix l'inici de sessió en dos passos de DUO al vostre compte. </value>
@@ -2922,71 +2922,74 @@ Voleu canviar a aquest compte?</value>
<value>Inicia DUO</value> <value>Inicia DUO</value>
</data> </data>
<data name="VerificationRequiredByX" xml:space="preserve"> <data name="VerificationRequiredByX" xml:space="preserve">
<value>Verification required by {0}</value> <value>Verificació requerida per {0}</value>
</data> </data>
<data name="VerificationRequiredForThisActionSetUpAnUnlockMethodInBitwardenToContinue" xml:space="preserve"> <data name="VerificationRequiredForThisActionSetUpAnUnlockMethodInBitwardenToContinue" xml:space="preserve">
<value>Verification required for this action. Set up an unlock method in Bitwarden to continue.</value> <value>Verificació necessària per a aquesta acció. Configura un mètode de desbloqueig a Bitwarden per continuar.</value>
</data> </data>
<data name="ErrorCreatingPasskey" xml:space="preserve"> <data name="ErrorCreatingPasskey" xml:space="preserve">
<value>Error creating passkey</value> <value>S'ha produït un error en crear la clau de pas</value>
</data> </data>
<data name="ErrorReadingPasskey" xml:space="preserve"> <data name="ErrorReadingPasskey" xml:space="preserve">
<value>Error reading passkey</value> <value>S'ha produït un error en llegir la clau de pas</value>
</data> </data>
<data name="ThereWasAProblemCreatingAPasskeyForXTryAgainLater" xml:space="preserve"> <data name="ThereWasAProblemCreatingAPasskeyForXTryAgainLater" xml:space="preserve">
<value>There was a problem creating a passkey for {0}. Try again later.</value> <value>S'ha produït un problema en crear una contrasenya per a {0}. Torneu-ho a provar més tard.</value>
<comment>The parameter is the RpId</comment> <comment>The parameter is the RpId</comment>
</data> </data>
<data name="ThereWasAProblemReadingAPasskeyForXTryAgainLater" xml:space="preserve"> <data name="ThereWasAProblemReadingAPasskeyForXTryAgainLater" xml:space="preserve">
<value>There was a problem reading your passkey for {0}. Try again later.</value> <value>S'ha produït un problema en llegir la clau de pas per a {0}. Torneu-ho a provar més tard.</value>
<comment>The parameter is the RpId</comment> <comment>The parameter is the RpId</comment>
</data> </data>
<data name="VerifyingIdentityEllipsis" xml:space="preserve"> <data name="VerifyingIdentityEllipsis" xml:space="preserve">
<value>Verifying identity...</value> <value>S'està verificant la identitat...</value>
</data> </data>
<data name="Passwords" xml:space="preserve"> <data name="Passwords" xml:space="preserve">
<value>Passwords</value> <value>Contrasenyes</value>
</data> </data>
<data name="UnknownAccount" xml:space="preserve"> <data name="UnknownAccount" xml:space="preserve">
<value>Unknown account</value> <value>Compte desconegut</value>
</data> </data>
<data name="SetUpAutofill" xml:space="preserve"> <data name="SetUpAutofill" xml:space="preserve">
<value>Set up auto-fill</value> <value>Configura l'emplenament automàtic</value>
</data> </data>
<data name="GetInstantAccessToYourPasswordsAndPasskeys" xml:space="preserve"> <data name="GetInstantAccessToYourPasswordsAndPasskeys" xml:space="preserve">
<value>Get instant access to your passwords and passkeys!</value> <value>Obteniu accés instantani a les vostres contrasenyes i claus de pas!</value>
</data> </data>
<data name="SetUpAutoFillDescriptionLong" xml:space="preserve"> <data name="SetUpAutoFillDescriptionLong" xml:space="preserve">
<value>To set up password auto-fill and passkey management, set Bitwarden as your preferred provider in the iOS Settings.</value> <value>Per configurar l'emplenament automàtic de contrasenyes i la gestió de claus de pas, configureu Bitwarden com a proveïdor preferit a la configuració d'iOS.</value>
</data> </data>
<data name="FirstDotGoToYourDeviceSettingsPasswordsPasswordOptions" xml:space="preserve"> <data name="FirstDotGoToYourDeviceSettingsPasswordsPasswordOptions" xml:space="preserve">
<value>1. Go to your device's Settings &gt; Passwords &gt; Password Options</value> <value>1. Aneu a la configuració del dispositiu &gt; Contrasenyes &gt; Opcions de contrasenya</value>
</data> </data>
<data name="SecondDotTurnOnAutoFill" xml:space="preserve"> <data name="SecondDotTurnOnAutoFill" xml:space="preserve">
<value>2. Turn on AutoFill</value> <value>2. Activeu l'emplenament automàtic</value>
</data> </data>
<data name="ThirdDotSelectBitwardenToUseForPasswordsAndPasskeys" xml:space="preserve"> <data name="ThirdDotSelectBitwardenToUseForPasswordsAndPasskeys" xml:space="preserve">
<value>3. Select "Bitwarden" to use for passwords and passkeys</value> <value>3. Seleccioneu "Bitwarden" per utilitzar-lo per a les contrasenyes i les claus de pas</value>
</data> </data>
<data name="YourPasskeyWillBeSavedToYourBitwardenVault" xml:space="preserve"> <data name="YourPasskeyWillBeSavedToYourBitwardenVault" xml:space="preserve">
<value>Your passkey will be saved to your Bitwarden vault</value> <value>La clau d'accés es guardarà a la caixa forta de Bitwarden</value>
</data> </data>
<data name="YourPasskeyWillBeSavedToYourBitwardenVaultForX" xml:space="preserve"> <data name="YourPasskeyWillBeSavedToYourBitwardenVaultForX" xml:space="preserve">
<value>Your passkey will be saved to your Bitwarden vault for {0}</value> <value>La clau d'accés es guardarà a la caixa forta de Bitwarden per a {0}</value>
</data>
<data name="OrganizationUnassignedItemsMessageUSEUDescriptionLong" xml:space="preserve">
<value>Unassigned organization items are no longer visible in the All Vaults view and only accessible via the Admin Console. Assign these items to a collection from the Admin Console to make them visible.</value>
</data>
<data name="OrganizationUnassignedItemsMessageSelfHost041624DescriptionLong" xml:space="preserve">
<value>On May 16, 2024, unassigned organization items will no longer be visible in the All Vaults view and only accessible via the Admin Console. Assign these items to a collection from the Admin Console to make them visible.</value>
</data>
<data name="RemindMeLater" xml:space="preserve">
<value>Remind me later</value>
</data>
<data name="Notice" xml:space="preserve">
<value>Notice</value>
</data> </data>
<data name="PasskeysNotSupportedForThisApp" xml:space="preserve"> <data name="PasskeysNotSupportedForThisApp" xml:space="preserve">
<value>Passkeys not supported for this app</value> <value>Les claus de pas no són compatibles amb aquesta aplicació</value>
</data>
<data name="PasskeyOperationFailedBecauseBrowserIsNotPrivileged" xml:space="preserve">
<value>L'operació de la clau de pas ha fallat perquè el navegador no té privilegis</value>
</data>
<data name="PasskeyOperationFailedBecauseBrowserSignatureDoesNotMatch" xml:space="preserve">
<value>L'operació de la clau de pas ha fallat perquè la signatura del navegador no coincideix</value>
</data>
<data name="PasskeyOperationFailedBecauseOfMissingAssetLinks" xml:space="preserve">
<value>L'operació de la clau de pas ha fallat perquè falten enllaços de recursos</value>
</data>
<data name="PasskeyOperationFailedBecauseAppNotFoundInAssetLinks" xml:space="preserve">
<value>L'operació de la clau de pas ha fallat perquè l'aplicació no s'ha trobat als enllaços de recursos</value>
</data>
<data name="PasskeyOperationFailedBecauseAppCouldNotBeVerified" xml:space="preserve">
<value>L'operació de la clau de pas ha fallat perquè l'aplicació no s'ha pogut verificar</value>
</data> </data>
</root> </root>

View File

@@ -422,7 +422,7 @@
<value>Služba automatického vyplňování</value> <value>Služba automatického vyplňování</value>
</data> </data>
<data name="SetBitwardenAsPasskeyManagerDescription" xml:space="preserve"> <data name="SetBitwardenAsPasskeyManagerDescription" xml:space="preserve">
<value>Set Bitwarden as your passkey provider in device settings.</value> <value>Nastaví Bitwarden jako poskytovatele přístupového hesla v nastavení zařízení.</value>
</data> </data>
<data name="AvoidAmbiguousCharacters" xml:space="preserve"> <data name="AvoidAmbiguousCharacters" xml:space="preserve">
<value>Nepoužívat zaměnitelné znaky</value> <value>Nepoužívat zaměnitelné znaky</value>
@@ -502,7 +502,7 @@
<value>Pro spuštění rozšíření klepněte na ikonu Bitwardenu v menu.</value> <value>Pro spuštění rozšíření klepněte na ikonu Bitwardenu v menu.</value>
</data> </data>
<data name="ExtensionTurnOn" xml:space="preserve"> <data name="ExtensionTurnOn" xml:space="preserve">
<value>Pro zapnutí Bitwardenu v prohlížeči Safari a dalších aplikacích klepněte na ikonu "Další v dolní části menu.</value> <value>Pro zapnutí Bitwardenu v prohlížeči Safari a dalších aplikacích klepněte na ikonu "Další" v dolní části menu.</value>
</data> </data>
<data name="Favorite" xml:space="preserve"> <data name="Favorite" xml:space="preserve">
<value>Oblíbené</value> <value>Oblíbené</value>
@@ -901,7 +901,7 @@ Načtení proběhne automaticky.</value>
<value>Načíst QR kód</value> <value>Načíst QR kód</value>
</data> </data>
<data name="Camera" xml:space="preserve"> <data name="Camera" xml:space="preserve">
<value>Fotoaparát</value> <value>Kamera</value>
</data> </data>
<data name="Photos" xml:space="preserve"> <data name="Photos" xml:space="preserve">
<value>Fotky</value> <value>Fotky</value>
@@ -1195,7 +1195,7 @@ Načtení proběhne automaticky.</value>
<value>Windows Hello</value> <value>Windows Hello</value>
</data> </data>
<data name="BitwardenCredentialProviderGoToSettings" xml:space="preserve"> <data name="BitwardenCredentialProviderGoToSettings" xml:space="preserve">
<value>We were unable to automatically open the Android credential provider settings menu for you. You can navigate to the credential provider settings menu manually from Android Settings &gt; System &gt; Passwords &amp; accounts &gt; Passwords, passkeys and data services.</value> <value>Obrazovku nastavení automatického vyplňování Android se nepodařilo otevřít. Nastavení můžete otevřít ručně z Nastavení systému Android &gt; Systém &gt; Hesla a účty &gt; Hesla, přístupové klíče a datové služby.</value>
</data> </data>
<data name="BitwardenAutofillGoToSettings" xml:space="preserve"> <data name="BitwardenAutofillGoToSettings" xml:space="preserve">
<value>Obrazovku nastavení automatického vyplňování Android se nepodařilo otevřít. Nastavení můžete otevřít ručně z Nastavení systému Android &gt; Systém &gt; Jazyky a zadávání &gt; Rozšířená nastavení &gt; Služba automatického vyplňování.</value> <value>Obrazovku nastavení automatického vyplňování Android se nepodařilo otevřít. Nastavení můžete otevřít ručně z Nastavení systému Android &gt; Systém &gt; Jazyky a zadávání &gt; Rozšířená nastavení &gt; Služba automatického vyplňování.</value>
@@ -1822,7 +1822,7 @@ Načtení proběhne automaticky.</value>
<value>Bitwarden vyžaduje pozornost Povolte volbu "Zobrazit přes ostatní aplikace" ve "Službách automatického vyplňování“ v nastavení aplikace Bitwarden</value> <value>Bitwarden vyžaduje pozornost Povolte volbu "Zobrazit přes ostatní aplikace" ve "Službách automatického vyplňování“ v nastavení aplikace Bitwarden</value>
</data> </data>
<data name="PasskeyManagement" xml:space="preserve"> <data name="PasskeyManagement" xml:space="preserve">
<value>Passkey management</value> <value>Správa přístupových klíčů</value>
</data> </data>
<data name="AutofillServices" xml:space="preserve"> <data name="AutofillServices" xml:space="preserve">
<value>Služby automatického vyplňování</value> <value>Služby automatického vyplňování</value>
@@ -2544,7 +2544,7 @@ Chcete se přepnout na tento účet?</value>
<value>Žádné čekající žádosti</value> <value>Žádné čekající žádosti</value>
</data> </data>
<data name="EnableCamerPermissionToUseTheScanner" xml:space="preserve"> <data name="EnableCamerPermissionToUseTheScanner" xml:space="preserve">
<value>Pro použití skeneru musíte povolit přístup k fotoaparátu</value> <value>Pro použití skeneru musíte povolit přístup ke kameře</value>
</data> </data>
<data name="Language" xml:space="preserve"> <data name="Language" xml:space="preserve">
<value>Jazyk</value> <value>Jazyk</value>
@@ -2767,7 +2767,7 @@ Chcete se přepnout na tento účet?</value>
<value>Zabezpečení účtu</value> <value>Zabezpečení účtu</value>
</data> </data>
<data name="BitwardenHelpCenter" xml:space="preserve"> <data name="BitwardenHelpCenter" xml:space="preserve">
<value>Centrum nápovědy Bitwarden</value> <value>Centrum nápovědy Bitwardenu</value>
</data> </data>
<data name="ContactBitwardenSupport" xml:space="preserve"> <data name="ContactBitwardenSupport" xml:space="preserve">
<value>Kontakt na podporu Bitwarden</value> <value>Kontakt na podporu Bitwarden</value>
@@ -2807,7 +2807,7 @@ Chcete se přepnout na tento účet?</value>
<value>{0} hodin</value> <value>{0} hodin</value>
</data> </data>
<data name="PasskeyManagementExplanationLong" xml:space="preserve"> <data name="PasskeyManagementExplanationLong" xml:space="preserve">
<value>Use Bitwarden to save new passkeys and log in with passkeys stored in your vault.</value> <value>Použijte Bitwarden pro ukládání nových přístupových klíčů a přihlašování se pomocí přístupových klíčů uložených ve Vašem trezoru.</value>
</data> </data>
<data name="AutofillServicesExplanationLong" xml:space="preserve"> <data name="AutofillServicesExplanationLong" xml:space="preserve">
<value>Android Autofill Framework se používá k vyplnění přihlašovacích údajů do jiných aplikací na Vašem zařízení.</value> <value>Android Autofill Framework se používá k vyplnění přihlašovacích údajů do jiných aplikací na Vašem zařízení.</value>
@@ -2838,7 +2838,7 @@ Chcete se přepnout na tento účet?</value>
<value>Pokračovat do obchodu s aplikacemi?</value> <value>Pokračovat do obchodu s aplikacemi?</value>
</data> </data>
<data name="ContinueToDeviceSettings" xml:space="preserve"> <data name="ContinueToDeviceSettings" xml:space="preserve">
<value>Continue to device Settings?</value> <value>Pokračovat do nastavení zařízení?</value>
</data> </data>
<data name="TwoStepLoginDescriptionLong" xml:space="preserve"> <data name="TwoStepLoginDescriptionLong" xml:space="preserve">
<value>Vytvořte svůj účet bezpečnějším nastavením dvoufázového přihlášení ve webové aplikaci Bitwarden.</value> <value>Vytvořte svůj účet bezpečnějším nastavením dvoufázového přihlášení ve webové aplikaci Bitwarden.</value>
@@ -2891,25 +2891,25 @@ Chcete se přepnout na tento účet?</value>
<value>Nastavte volbu odemknutí, abyste změnili časový limit Vašeho trezoru.</value> <value>Nastavte volbu odemknutí, abyste změnili časový limit Vašeho trezoru.</value>
</data> </data>
<data name="ChooseALoginToSaveThisPasskeyTo" xml:space="preserve"> <data name="ChooseALoginToSaveThisPasskeyTo" xml:space="preserve">
<value>Choose a login to save this passkey to</value> <value>Vyberte přihlášení pro uložení tohoto přístupového klíče</value>
</data> </data>
<data name="SavePasskeyAsNewLogin" xml:space="preserve"> <data name="SavePasskeyAsNewLogin" xml:space="preserve">
<value>Save passkey as new login</value> <value>Uložit přístupový klíč jako nové přihlášení</value>
</data> </data>
<data name="SavePasskey" xml:space="preserve"> <data name="SavePasskey" xml:space="preserve">
<value>Save passkey</value> <value>Uložit přístupový klíč</value>
</data> </data>
<data name="PasskeysForX" xml:space="preserve"> <data name="PasskeysForX" xml:space="preserve">
<value>Passkeys for {0}</value> <value>Přístupové klíče pro {0}</value>
</data> </data>
<data name="PasswordsForX" xml:space="preserve"> <data name="PasswordsForX" xml:space="preserve">
<value>Passwords for {0}</value> <value>Hesla pro {0}</value>
</data> </data>
<data name="OverwritePasskey" xml:space="preserve"> <data name="OverwritePasskey" xml:space="preserve">
<value>Overwrite passkey?</value> <value>Přepsat přístupový klíč?</value>
</data> </data>
<data name="ThisItemAlreadyContainsAPasskeyAreYouSureYouWantToOverwriteTheCurrentPasskey" xml:space="preserve"> <data name="ThisItemAlreadyContainsAPasskeyAreYouSureYouWantToOverwriteTheCurrentPasskey" xml:space="preserve">
<value>This item already contains a passkey. Are you sure you want to overwrite the current passkey?</value> <value>Tato položka již obsahuje přístupový klíč. Jste si jisti, že chcete přepsat aktuální přístupový klíč?</value>
</data> </data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve"> <data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>Pro Váš účet je vyžadováno dvoufázové přihlášení DUO. </value> <value>Pro Váš účet je vyžadováno dvoufázové přihlášení DUO. </value>
@@ -2921,71 +2921,74 @@ Chcete se přepnout na tento účet?</value>
<value>Spustit DUO</value> <value>Spustit DUO</value>
</data> </data>
<data name="VerificationRequiredByX" xml:space="preserve"> <data name="VerificationRequiredByX" xml:space="preserve">
<value>Verification required by {0}</value> <value>Je vyžadováno ověření od {0}</value>
</data> </data>
<data name="VerificationRequiredForThisActionSetUpAnUnlockMethodInBitwardenToContinue" xml:space="preserve"> <data name="VerificationRequiredForThisActionSetUpAnUnlockMethodInBitwardenToContinue" xml:space="preserve">
<value>Verification required for this action. Set up an unlock method in Bitwarden to continue.</value> <value>Pro tuto akci je vyžadováno ověření. Pro pokračování nastavte metodu odemknutí v Bitwardenu.</value>
</data> </data>
<data name="ErrorCreatingPasskey" xml:space="preserve"> <data name="ErrorCreatingPasskey" xml:space="preserve">
<value>Error creating passkey</value> <value>Chyba při vytváření přístupového klíče</value>
</data> </data>
<data name="ErrorReadingPasskey" xml:space="preserve"> <data name="ErrorReadingPasskey" xml:space="preserve">
<value>Error reading passkey</value> <value>Chyba při čtení přístupového klíče</value>
</data> </data>
<data name="ThereWasAProblemCreatingAPasskeyForXTryAgainLater" xml:space="preserve"> <data name="ThereWasAProblemCreatingAPasskeyForXTryAgainLater" xml:space="preserve">
<value>There was a problem creating a passkey for {0}. Try again later.</value> <value>Při vytváření přístupového klíče pro {0} došlo k chybě. Zkuste to znovu později.</value>
<comment>The parameter is the RpId</comment> <comment>The parameter is the RpId</comment>
</data> </data>
<data name="ThereWasAProblemReadingAPasskeyForXTryAgainLater" xml:space="preserve"> <data name="ThereWasAProblemReadingAPasskeyForXTryAgainLater" xml:space="preserve">
<value>There was a problem reading your passkey for {0}. Try again later.</value> <value>Při čtení přístupového klíče pro {0} došlo k chybě. Zkuste to znovu později.</value>
<comment>The parameter is the RpId</comment> <comment>The parameter is the RpId</comment>
</data> </data>
<data name="VerifyingIdentityEllipsis" xml:space="preserve"> <data name="VerifyingIdentityEllipsis" xml:space="preserve">
<value>Verifying identity...</value> <value>Ověřování identity...</value>
</data> </data>
<data name="Passwords" xml:space="preserve"> <data name="Passwords" xml:space="preserve">
<value>Passwords</value> <value>Hesla</value>
</data> </data>
<data name="UnknownAccount" xml:space="preserve"> <data name="UnknownAccount" xml:space="preserve">
<value>Unknown account</value> <value>Neznámý účet</value>
</data> </data>
<data name="SetUpAutofill" xml:space="preserve"> <data name="SetUpAutofill" xml:space="preserve">
<value>Set up auto-fill</value> <value>Nastavit automatické vyplňování</value>
</data> </data>
<data name="GetInstantAccessToYourPasswordsAndPasskeys" xml:space="preserve"> <data name="GetInstantAccessToYourPasswordsAndPasskeys" xml:space="preserve">
<value>Get instant access to your passwords and passkeys!</value> <value>Získejte okamžitý přístup ke svým heslům a přístupovým klíčům!</value>
</data> </data>
<data name="SetUpAutoFillDescriptionLong" xml:space="preserve"> <data name="SetUpAutoFillDescriptionLong" xml:space="preserve">
<value>To set up password auto-fill and passkey management, set Bitwarden as your preferred provider in the iOS Settings.</value> <value>Pro nastavení automatického vyplňování hesla a správy přístupových klíčů nastavte Bitwarden jako preferovaného poskytovatele v nastavení iOS.</value>
</data> </data>
<data name="FirstDotGoToYourDeviceSettingsPasswordsPasswordOptions" xml:space="preserve"> <data name="FirstDotGoToYourDeviceSettingsPasswordsPasswordOptions" xml:space="preserve">
<value>1. Go to your device's Settings &gt; Passwords &gt; Password Options</value> <value>1. Přejděte do nastavení &gt; Hesla &gt; Volby hesla</value>
</data> </data>
<data name="SecondDotTurnOnAutoFill" xml:space="preserve"> <data name="SecondDotTurnOnAutoFill" xml:space="preserve">
<value>2. Turn on AutoFill</value> <value>2. Zapněte volbu "Automatické vyplňování hesel a přístupových klíčů"</value>
</data> </data>
<data name="ThirdDotSelectBitwardenToUseForPasswordsAndPasskeys" xml:space="preserve"> <data name="ThirdDotSelectBitwardenToUseForPasswordsAndPasskeys" xml:space="preserve">
<value>3. Select "Bitwarden" to use for passwords and passkeys</value> <value>3. V sekci "Používat hesla a přístupové klíče z:" zvolte "Bitwarden"</value>
</data> </data>
<data name="YourPasskeyWillBeSavedToYourBitwardenVault" xml:space="preserve"> <data name="YourPasskeyWillBeSavedToYourBitwardenVault" xml:space="preserve">
<value>Your passkey will be saved to your Bitwarden vault</value> <value>Váš přístupový klíč bude uložen do Vašeho trezoru na Bitwardenu</value>
</data> </data>
<data name="YourPasskeyWillBeSavedToYourBitwardenVaultForX" xml:space="preserve"> <data name="YourPasskeyWillBeSavedToYourBitwardenVaultForX" xml:space="preserve">
<value>Your passkey will be saved to your Bitwarden vault for {0}</value> <value>Váš přístupový klíč bude pro {0} uložen do Vašeho trezoru na Bitwardenu</value>
</data>
<data name="OrganizationUnassignedItemsMessageUSEUDescriptionLong" xml:space="preserve">
<value>Nepřiřazené položky organizace již nejsou viditelné ve Vašem zobrazení všech trezorů a jsou nyní přístupné jen v konzoli správce. Přiřaďte tyto položky do kolekce z konzole pro správce, aby byly viditelné.</value>
</data>
<data name="OrganizationUnassignedItemsMessageSelfHost041624DescriptionLong" xml:space="preserve">
<value>Dne 16. května 2024 již nebudou nepřiřazené položky organizace viditelné v zobrazení Všechny trezory a budou přístupné jen prostřednictvím konzoly správce. Přiřaďte tyto položky do kolekce z konzoly pro správce, aby byly viditelné.</value>
</data>
<data name="RemindMeLater" xml:space="preserve">
<value>Připomenout později</value>
</data>
<data name="Notice" xml:space="preserve">
<value>Upozornění</value>
</data> </data>
<data name="PasskeysNotSupportedForThisApp" xml:space="preserve"> <data name="PasskeysNotSupportedForThisApp" xml:space="preserve">
<value>Passkeys not supported for this app</value> <value>Přístupové klíče nejsou pro tuto aplikaci podporovány</value>
</data>
<data name="PasskeyOperationFailedBecauseBrowserIsNotPrivileged" xml:space="preserve">
<value>Operace přístupového klíče se nezdařila, protože prohlížeč nemá oprávnění</value>
</data>
<data name="PasskeyOperationFailedBecauseBrowserSignatureDoesNotMatch" xml:space="preserve">
<value>Operace přístupového klíče se nezdařila, protože se neshoduje s podpisem prohlížeče</value>
</data>
<data name="PasskeyOperationFailedBecauseOfMissingAssetLinks" xml:space="preserve">
<value>Operace přístupového klíče selhala z důvodu chybějících odkazů na aktiva</value>
</data>
<data name="PasskeyOperationFailedBecauseAppNotFoundInAssetLinks" xml:space="preserve">
<value>Operace přístupového klíče se nezdařila, protože v odkazech na aktivum nebyla nalezena aplikace</value>
</data>
<data name="PasskeyOperationFailedBecauseAppCouldNotBeVerified" xml:space="preserve">
<value>Operace přístupového klíče se nezdařila, protože aplikaci nelze ověřit</value>
</data> </data>
</root> </root>

View File

@@ -385,7 +385,7 @@
<value>Gwirio'r prif gyfrinair</value> <value>Gwirio'r prif gyfrinair</value>
</data> </data>
<data name="VerifyPIN" xml:space="preserve"> <data name="VerifyPIN" xml:space="preserve">
<value>Verify PIN</value> <value>Gwirio'r PIN</value>
</data> </data>
<data name="Version" xml:space="preserve"> <data name="Version" xml:space="preserve">
<value>Fersiwn</value> <value>Fersiwn</value>
@@ -446,7 +446,7 @@
<value>Newid ebost</value> <value>Newid ebost</value>
</data> </data>
<data name="ChangeEmailConfirmation" xml:space="preserve"> <data name="ChangeEmailConfirmation" xml:space="preserve">
<value>You can change your email address on the bitwarden.com web vault. Do you want to visit the website now?</value> <value>Gallwch newid eich cyfeiriad ebost yng nghell we bitwarden.com. Hoffech chi fynd i'r wefan nawr?</value>
</data> </data>
<data name="ChangeMasterPassword" xml:space="preserve"> <data name="ChangeMasterPassword" xml:space="preserve">
<value>Newid y prif gyfrinair</value> <value>Newid y prif gyfrinair</value>
@@ -610,7 +610,7 @@
<value>Does dim eitemau yn eich cell.</value> <value>Does dim eitemau yn eich cell.</value>
</data> </data>
<data name="NoItemsTap" xml:space="preserve"> <data name="NoItemsTap" xml:space="preserve">
<value>There are no items in your vault for this website/app. Tap to add one.</value> <value>Does dim eitemau yn eich cell ar gyfer y gwasanaeth hwn. Tapiwch i ychwanegu un.</value>
</data> </data>
<data name="NoUsernamePasswordConfigured" xml:space="preserve"> <data name="NoUsernamePasswordConfigured" xml:space="preserve">
<value>Does dim enw defnyddiwr na chyfrinair i'r manylyn mewngofnodi hwn.</value> <value>Does dim enw defnyddiwr na chyfrinair i'r manylyn mewngofnodi hwn.</value>
@@ -702,7 +702,7 @@
<comment>What Apple calls their fingerprint reader.</comment> <comment>What Apple calls their fingerprint reader.</comment>
</data> </data>
<data name="TwoStepLogin" xml:space="preserve"> <data name="TwoStepLogin" xml:space="preserve">
<value>Mewngofnodi dau agm</value> <value>Mewngofnodi dau gam</value>
</data> </data>
<data name="UnlockWith" xml:space="preserve"> <data name="UnlockWith" xml:space="preserve">
<value>Datgloi â {0}</value> <value>Datgloi â {0}</value>
@@ -1468,7 +1468,7 @@ Scanning will happen automatically.</value>
<comment>A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing.</comment> <comment>A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing.</comment>
</data> </data>
<data name="LearnOrgConfirmation" xml:space="preserve"> <data name="LearnOrgConfirmation" xml:space="preserve">
<value>Bitwarden allows you to share your vault items with others by using an organization account. Would you like to visit the bitwarden.com website to learn more?</value> <value>Mae Bitwarden yn caniatáu i chi rannu eitemau o'ch cell â phobl eraill drwy ddefnyddio cyfrif sefydliad. Hoffech chi fynd i wefan bitwarden.com i ddysgu mwy?</value>
</data> </data>
<data name="ExportVault" xml:space="preserve"> <data name="ExportVault" xml:space="preserve">
<value>Allforio'r gell</value> <value>Allforio'r gell</value>
@@ -2769,7 +2769,7 @@ Do you want to switch to this account?</value>
<value>Diogelwch eich cyfrif</value> <value>Diogelwch eich cyfrif</value>
</data> </data>
<data name="BitwardenHelpCenter" xml:space="preserve"> <data name="BitwardenHelpCenter" xml:space="preserve">
<value>Bitwarden Help Center</value> <value>Bitwarden help center</value>
</data> </data>
<data name="ContactBitwardenSupport" xml:space="preserve"> <data name="ContactBitwardenSupport" xml:space="preserve">
<value>Contact Bitwarden support</value> <value>Contact Bitwarden support</value>
@@ -2943,7 +2943,7 @@ Do you want to switch to this account?</value>
<comment>The parameter is the RpId</comment> <comment>The parameter is the RpId</comment>
</data> </data>
<data name="VerifyingIdentityEllipsis" xml:space="preserve"> <data name="VerifyingIdentityEllipsis" xml:space="preserve">
<value>Verifying identity...</value> <value>Yn giwrio eich hunaniaeth...</value>
</data> </data>
<data name="Passwords" xml:space="preserve"> <data name="Passwords" xml:space="preserve">
<value>Passwords</value> <value>Passwords</value>
@@ -2975,19 +2975,22 @@ Do you want to switch to this account?</value>
<data name="YourPasskeyWillBeSavedToYourBitwardenVaultForX" xml:space="preserve"> <data name="YourPasskeyWillBeSavedToYourBitwardenVaultForX" xml:space="preserve">
<value>Your passkey will be saved to your Bitwarden vault for {0}</value> <value>Your passkey will be saved to your Bitwarden vault for {0}</value>
</data> </data>
<data name="OrganizationUnassignedItemsMessageUSEUDescriptionLong" xml:space="preserve">
<value>Unassigned organization items are no longer visible in the All Vaults view and only accessible via the Admin Console. Assign these items to a collection from the Admin Console to make them visible.</value>
</data>
<data name="OrganizationUnassignedItemsMessageSelfHost041624DescriptionLong" xml:space="preserve">
<value>On May 16, 2024, unassigned organization items will no longer be visible in the All Vaults view and only accessible via the Admin Console. Assign these items to a collection from the Admin Console to make them visible.</value>
</data>
<data name="RemindMeLater" xml:space="preserve">
<value>Remind me later</value>
</data>
<data name="Notice" xml:space="preserve">
<value>Notice</value>
</data>
<data name="PasskeysNotSupportedForThisApp" xml:space="preserve"> <data name="PasskeysNotSupportedForThisApp" xml:space="preserve">
<value>Passkeys not supported for this app</value> <value>Passkeys not supported for this app</value>
</data> </data>
<data name="PasskeyOperationFailedBecauseBrowserIsNotPrivileged" xml:space="preserve">
<value>Passkey operation failed because browser is not privileged</value>
</data>
<data name="PasskeyOperationFailedBecauseBrowserSignatureDoesNotMatch" xml:space="preserve">
<value>Passkey operation failed because browser signature does not match</value>
</data>
<data name="PasskeyOperationFailedBecauseOfMissingAssetLinks" xml:space="preserve">
<value>Passkey operation failed because of missing asset links</value>
</data>
<data name="PasskeyOperationFailedBecauseAppNotFoundInAssetLinks" xml:space="preserve">
<value>Passkey operation failed because app not found in asset links</value>
</data>
<data name="PasskeyOperationFailedBecauseAppCouldNotBeVerified" xml:space="preserve">
<value>Passkey operation failed because app could not be verified</value>
</data>
</root> </root>

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