1
0
mirror of https://github.com/bitwarden/mobile synced 2026-01-21 20:03:16 +00:00

Compare commits

...

18 Commits

Author SHA1 Message Date
Alexey Zilber
d8ac0adf83 Merge remote-tracking branch 'origin/master' into CLOUDOPS-202_Google-Account-Migration 2022-11-21 15:27:24 +08:00
github-actions[bot]
164b8970d3 Autosync the updated translations (#2198)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2022-11-18 04:39:37 +01:00
André Bispo
34fd30e157 [SG-831] Pull Down Sync does not retrieve pending AuthRequests (#2196)
* [SG-831] Pull to refresh forces refresh.

* [SG-831] Expose sync login request method to be used independently

* [SG-831] Change sync order
2022-11-17 16:02:34 +00:00
André Bispo
8e09f0cc15 [SG-808] Change navigation on remove account after logout by timeout (#2193) 2022-11-16 12:38:45 +00:00
André Bispo
693a4ef776 [SG-816] Get all login requests and pick the most recent (#2191)
* [SG-816] Get all login requests anfd pick the most recent

* [SG-816] Add check if active user has approve login with device active

* [SG-816] Build fix. Fix response model.

* [SG-816] Move code to sync service
2022-11-15 17:36:21 +00:00
André Bispo
0992a989d4 [SG-778] Adjust mobile client to handle previously-responded-to passwordless request (#2190)
* [SG-778] Add properties to response model

* [SG-778] Add validation for request already answered

* [SG-778] Remove unnecessary properties

* [SG-778] Remove unnecessary assignments
2022-11-15 14:17:26 +00:00
Todd Martin
1b137a8a8a Added check to make sure it doesn't set a deployment on a Dry Run. (#2188) 2022-11-14 13:43:45 -05:00
André Bispo
7e8e86a77a [SG-813] Not You? crashes app after vault logout timeout (#2184)
* Merge branch 'master' into feature/SG-174-login-with-device

* [SG-813] Fix merge

* [SG-813] rename HomePage parameter name

* [SG-813] Added NavParams for home page on account switching.

* [SG-813] Remove account showing when adding new account.

* [SG-813] Add account switch pop up if email already exists

* [SG-813] Add default account avatar to HomePage

* [SG-813] Code format

* [SG-813] Remove unused import

* [SG-813] Renamed checkNavigateLogin to shouldCheckRememberEmail

* [SG-813] Move prompt account switch to account manager service

* [SG-813] Remove Account button appears if email is the same as the ActiveUser

* [SG-813] Fix code duplicate

* [SG-813] Fix for android RemoveAccount button

* [SG-813] Code format
2022-11-11 18:14:30 +00:00
Robyn MacCallum
20c1e2d7f2 Add syncCompleted to check to get passwordless requests (#2186) 2022-11-11 12:33:17 -05:00
github-actions[bot]
7870c2706b Autosync the updated translations (#2185)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2022-11-11 12:34:15 +01:00
Patrick
5a5f50605b Update AppResources.resx (#2181) 2022-11-10 13:44:18 -05:00
Robyn MacCallum
0106732cbd [SG-808] Only show 'remove account' option if user is in Accounts list (#2179)
* Only show 'remove account' option if user is in Accounts list

* Condense existing email logic

* Add line break

* Condense to local variable

* Cleanup spacing
2022-11-10 07:06:17 -05:00
André Bispo
9ae269dd57 [SG-174] Login with Device Request - Mobile (#2167)
* [SG-174] Add new login request services to Api

* [SG-174] Fix typo

* [SG-174] Enable login with device button.

* [SG-174] Add new login request page and viewmodel

* [SG-174] Add new text resources

* [SG-174] Add new RSA Decrypt method with string param

* [SG-174] Change create login request method

* [SG-174] Add new method to auth service to login passwordless

* [SG-174] Refactor login helper method to work with passwordless

* [SG-174] Fix service registration

* [SG-174] Update token request to support passwordless

* [SG-174] Update Api service with passwordless methods

* [SG-174] Fix App csproj references

* [SG-174] Remove unnecessary argument

* [SG-174] dotnet format

* [SG-174] Fixed iOS Extensions

* [SG-174] Change Command to ICommand

* [SG-174] Change Gesture Recognizer to Command

* [SG-174] Fix close action

* [SG-174] Code format

* [SG-174] Fix android frame shadow bug

* [SG-174] PR fixes
2022-11-09 16:25:48 +00:00
Opeyemi
04ed47d545 Devops 1039 update release flow dry run step names (#2177) 2022-11-08 22:44:50 +00:00
Opeyemi
6160535c03 add run-name for release to include workflow trigger (#2174) 2022-11-08 20:27:22 +00:00
André Bispo
8d92373c88 [SG-806] add try catch on initAsync (#2173) 2022-11-07 13:41:02 +00:00
André Bispo
6bfc8f7d49 [SG-802] Add if check on notification tap. (#2172) 2022-11-07 13:40:48 +00:00
Alexey Zilber
44dfe0022c Abstracting out Package name in uploader and workflow. 2022-11-03 13:47:52 +08:00
106 changed files with 2258 additions and 320 deletions

View File

@@ -11,6 +11,9 @@ on:
workflow_dispatch:
inputs: {}
env:
BASE_PKG_NAME: com.x8bit.bitwarden
jobs:
cloc:
name: CLOC
@@ -174,11 +177,11 @@ jobs:
UPLOAD_KEYSTORE_PASSWORD: ${{ secrets.UPLOAD_KEYSTORE_PASSWORD }}
run: |
$androidPath = $($env:GITHUB_WORKSPACE + "/src/Android/Android.csproj");
$packageName = "com.x8bit.bitwarden";
$packageName = "";
if ("${{ matrix.variant }}" -ne "prod")
{
$packageName = "com.x8bit.bitwarden.${{ matrix.variant }}";
$packageName = "${{ env.BASE_PKG_NAME }}.${{ matrix.variant }}";
}
Write-Output "########################################"
Write-Output "##### Sign Google Play Bundle Release Configuration"
@@ -219,24 +222,24 @@ jobs:
if: ${{ matrix.variant == 'prod' }}
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
with:
name: com.x8bit.bitwarden.aab
path: ./com.x8bit.bitwarden.aab
name: ${{ env.BASE_PKG_NAME }}.aab
path: ./${{ env.BASE_PKG_NAME }}.aab
if-no-files-found: error
- name: Upload Prod .apk artifact
if: ${{ matrix.variant == 'prod' }}
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
with:
name: com.x8bit.bitwarden.apk
path: ./com.x8bit.bitwarden.apk
name: ${{ env.BASE_PKG_NAME }}.apk
path: ./${{ env.BASE_PKG_NAME }}.apk
if-no-files-found: error
- name: Upload Other .apk artifact
if: ${{ matrix.variant != 'prod' }}
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
with:
name: com.x8bit.bitwarden.${{ matrix.variant }}.apk
path: ./com.x8bit.bitwarden.${{ matrix.variant }}.apk
name: ${{ env.BASE_PKG_NAME }}.${{ matrix.variant }}.apk
path: ./${{ env.BASE_PKG_NAME }}.${{ matrix.variant }}.apk
if-no-files-found: error
- name: Deploy to Play Store
@@ -248,10 +251,10 @@ jobs:
run: |
PUBLISHER_PATH="$GITHUB_WORKSPACE/store/google/Publisher/bin/Release/netcoreapp3.1/Publisher.dll"
CREDS_PATH="$HOME/secrets/play_creds.json"
AAB_PATH="$GITHUB_WORKSPACE/com.x8bit.bitwarden.aab"
AAB_PATH="$GITHUB_WORKSPACE/${{env:BASE_PKG_NAME}}.aab"
TRACK="internal"
dotnet $PUBLISHER_PATH $CREDS_PATH $AAB_PATH $TRACK
dotnet $PUBLISHER_PATH $CREDS_PATH $AAB_PATH $TRACK ${{env:BASE_PKG_NAME}}
shell: bash
@@ -424,8 +427,8 @@ jobs:
Write-Output "##### Copy FDroid apk to project root"
Write-Output "########################################"
$signedApkPath = $($env:GITHUB_WORKSPACE + "/src/Android/bin/FDroid/com.x8bit.bitwarden-Signed.apk");
$signedApkDestPath = $($env:GITHUB_WORKSPACE + "/com.x8bit.bitwarden-fdroid.apk");
$signedApkPath = $($env:GITHUB_WORKSPACE + "/src/Android/bin/FDroid/$env:BASE_PKG_NAME-Signed.apk");
$signedApkDestPath = $($env:GITHUB_WORKSPACE + "/$env:BASE_PKG_NAME-fdroid.apk");
Copy-Item $signedApkPath $signedApkDestPath
shell: pwsh
@@ -433,8 +436,8 @@ jobs:
- name: Upload F-Droid .apk artifact
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
with:
name: com.x8bit.bitwarden-fdroid.apk
path: ./com.x8bit.bitwarden-fdroid.apk
name: ${{ env.BASE_PKG_NAME }}.apk
path: ./${{ env.BASE_PKG_NAME }}.apk
if-no-files-found: error

View File

@@ -1,5 +1,6 @@
---
name: Release
run-name: Release ${{ inputs.release_type }}
on:
workflow_dispatch:
@@ -19,6 +20,9 @@ on:
default: true
type: boolean
env:
BASE_PKG_NAME: com.x8bit.bitwarden
jobs:
release:
name: Create Release
@@ -54,6 +58,7 @@ jobs:
echo "::set-output name=branch-name::$BRANCH_NAME"
- name: Create GitHub deployment
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
uses: chrnorm/deployment-action@1b599fe41a0ef1f95191e7f2eec4743f2d7dfc48
id: deployment
with:
@@ -72,7 +77,7 @@ jobs:
workflow_conclusion: success
branch: ${{ steps.branch.outputs.branch-name }}
- name: Download all artifacts
- name: Dry Run - Download all artifacts
if: ${{ github.event.inputs.release_type == 'Dry Run' }}
uses: dawidd6/action-download-artifact@575b1e4167df67acf7e692af784566618b23c71e # v2.17.10
with:
@@ -87,9 +92,9 @@ jobs:
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
uses: ncipollo/release-action@40bb172bd05f266cf9ba4ff965cb61e9ee5f6d01 # v1.9.0
with:
artifacts: "./com.x8bit.bitwarden.aab/com.x8bit.bitwarden.aab,
./com.x8bit.bitwarden.apk/com.x8bit.bitwarden.apk,
./com.x8bit.bitwarden-fdroid.apk/com.x8bit.bitwarden-fdroid.apk,
artifacts: "./${{ BASE_PKG_NAME }}.aab/${{ BASE_PKG_NAME }}.aab,
./${{ BASE_PKG_NAME }}.apk/${{ BASE_PKG_NAME }}.apk,
./${{ BASE_PKG_NAME }}-fdroid.apk/${{ BASE_PKG_NAME }}-fdroid.apk,
./Bitwarden iOS.zip"
commit: ${{ github.sha }}
tag: v${{ steps.version.outputs.version }}
@@ -99,7 +104,7 @@ jobs:
draft: true
- name: Update deployment status to Success
if: ${{ success() }}
if: ${{ github.event.inputs.release_type != 'Dry Run' && success() }}
uses: chrnorm/deployment-status@07b3930847f65e71c9c6802ff5a402f6dfb46b86
with:
token: '${{ secrets.GITHUB_TOKEN }}'
@@ -107,7 +112,7 @@ jobs:
deployment-id: ${{ steps.deployment.outputs.deployment_id }}
- name: Update deployment status to Failure
if: ${{ failure() }}
if: ${{ github.event.inputs.release_type != 'Dry Run' && failure() }}
uses: chrnorm/deployment-status@07b3930847f65e71c9c6802ff5a402f6dfb46b86
with:
token: '${{ secrets.GITHUB_TOKEN }}'
@@ -131,16 +136,16 @@ jobs:
workflow: build.yml
workflow_conclusion: success
branch: ${{ needs.release.outputs.branch-name }}
name: com.x8bit.bitwarden-fdroid.apk
name: ${{ BASE_PKG_NAME }}-fdroid.apk
- name: Download F-Droid .apk artifact
- name: Dry Run - Download F-Droid .apk artifact
if: ${{ github.event.inputs.release_type == 'Dry Run' }}
uses: dawidd6/action-download-artifact@575b1e4167df67acf7e692af784566618b23c71e # v2.17.10
with:
workflow: build.yml
workflow_conclusion: success
branch: master
name: com.x8bit.bitwarden-fdroid.apk
name: ${{ BASE_PKG_NAME }}-fdroid.apk
- name: Set up Node
uses: actions/setup-node@1f8c6b94b26d0feae1e387ca63ccbdc44d27b561 # v2.5.1
@@ -196,7 +201,7 @@ jobs:
echo "keystorepass=\"$FDROID_STORE_KEYSTORE_PASSWORD\"" >>config.py
echo "local_copy_dir=\"$TEMP_DIR\"" >>config.py
mkdir -p repo
mv $GITHUB_WORKSPACE/com.x8bit.bitwarden-fdroid.apk ./repo/
mv $GITHUB_WORKSPACE/${{ BASE_PKG_NAME }}-fdroid.apk ./repo/
fdroid update
fdroid server update
cd ..

View File

@@ -9,5 +9,6 @@ namespace Bit.App.Abstractions
void Init(Func<AppOptions> getOptionsFunc, IAccountsManagerHost accountsManagerHost);
Task NavigateOnAccountChangeAsync(bool? isAuthed = null);
Task LogOutAsync(string userId, bool userInitiated, bool expired);
Task PromptToSwitchToExistingAccountAsync(string userId);
}
}

View File

@@ -125,6 +125,9 @@
<Compile Update="Pages\Accounts\LoginPasswordlessPage.xaml.cs">
<DependentUpon>LoginPasswordlessPage.xaml</DependentUpon>
</Compile>
<Compile Update="Pages\Accounts\LoginPasswordlessRequestPage.xaml.cs">
<DependentUpon>LoginPasswordlessRequestPage.xaml</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>

View File

@@ -145,7 +145,9 @@ namespace Bit.App
new NavigationPage(new RemoveMasterPasswordPage()));
});
}
else if (message.Command == Constants.PasswordlessLoginRequestKey || message.Command == "unlocked" || message.Command == AccountsManagerMessageCommands.ACCOUNT_SWITCH_COMPLETED)
else if (message.Command == Constants.PasswordlessLoginRequestKey
|| message.Command == "unlocked"
|| message.Command == AccountsManagerMessageCommands.ACCOUNT_SWITCH_COMPLETED)
{
lock (_processingLoginRequestLock)
{
@@ -202,11 +204,11 @@ namespace Bit.App
FingerprintPhrase = loginRequestData.RequestFingerprint,
RequestDate = loginRequestData.CreationDate,
DeviceType = loginRequestData.RequestDeviceType,
Origin = loginRequestData.Origin,
Origin = loginRequestData.Origin
});
await _stateService.SetPasswordlessLoginNotificationAsync(null);
_pushNotificationService.DismissLocalNotification(Constants.PasswordlessNotificationId);
if (loginRequestData.CreationDate.ToUniversalTime().AddMinutes(Constants.PasswordlessNotificationTimeoutInMinutes) > DateTime.UtcNow)
if (!loginRequestData.IsExpired)
{
await Device.InvokeOnMainThreadAsync(() => Application.Current.MainPage.Navigation.PushModalAsync(new NavigationPage(page)));
}
@@ -457,7 +459,14 @@ namespace Bit.App
switch (navTarget)
{
case NavigationTarget.HomeLogin:
Current.MainPage = new NavigationPage(new HomePage(Options));
if (navParams is HomeNavigationParams homeParams)
{
Current.MainPage = new NavigationPage(new HomePage(Options, homeParams.ShouldCheckRememberEmail));
}
else
{
Current.MainPage = new NavigationPage(new HomePage(Options));
}
break;
case NavigationTarget.Login:
if (navParams is LoginNavigationParams loginParams)

View File

@@ -8,6 +8,7 @@
Padding="1"
StyleClass="btn-icon-secondary"
BackgroundColor="{Binding IconLabelBorderColor, Source={x:Reference _iconLabelButton}}"
BorderColor="Transparent"
HasShadow="False">
<Frame.GestureRecognizers>
<TapGestureRecognizer Command="{Binding ButtonCommand, Source={x:Reference _iconLabelButton}}" />
@@ -17,6 +18,7 @@
Padding="0"
CornerRadius="{Binding CornerRadius, Source={x:Reference _iconLabelButton}}"
BackgroundColor="{Binding IconLabelBackgroundColor, Source={x:Reference _iconLabelButton}}"
BorderColor="Transparent"
IsClippedToBounds="True"
HasShadow="False">
<StackLayout

View File

@@ -19,7 +19,7 @@ namespace Bit.App.Controls
nameof(Label), typeof(string), typeof(IconLabelButton));
public static readonly BindableProperty ButtonCommandProperty = BindableProperty.Create(
nameof(ButtonCommand), typeof(Command), typeof(IconLabelButton));
nameof(ButtonCommand), typeof(ICommand), typeof(IconLabelButton));
public static readonly BindableProperty IconLabelColorProperty = BindableProperty.Create(
nameof(IconLabelColor), typeof(Color), typeof(IconLabelButton), Color.White);

View File

@@ -15,14 +15,14 @@ namespace Bit.App.Pages
private readonly AppOptions _appOptions;
private IBroadcasterService _broadcasterService;
public HomePage(AppOptions appOptions = null, bool checkRememberedEmail = true)
public HomePage(AppOptions appOptions = null, bool shouldCheckRememberEmail = true)
{
_broadcasterService = ServiceContainer.Resolve<IBroadcasterService>("broadcasterService");
_appOptions = appOptions;
InitializeComponent();
_vm = BindingContext as HomeViewModel;
_vm.Page = this;
_vm.CheckHasRememberedEmail = checkRememberedEmail;
_vm.ShouldCheckRememberEmail = shouldCheckRememberEmail;
_vm.ShowCancelButton = _appOptions?.IosExtension ?? false;
_vm.StartLoginAction = async () => await StartLoginAsync();
_vm.StartRegisterAction = () => Device.BeginInvokeOnMainThread(async () => await StartRegisterAsync());
@@ -59,7 +59,7 @@ namespace Bit.App.Pages
if (!_appOptions?.HideAccountSwitcher ?? false)
{
_vm.AvatarImageSource = await GetAvatarImageSourceAsync();
_vm.AvatarImageSource = await GetAvatarImageSourceAsync(false);
}
_broadcasterService.Subscribe(nameof(HomePage), (message) =>
{

View File

@@ -1,5 +1,6 @@
using System;
using System.Threading.Tasks;
using Bit.App.Abstractions;
using Bit.App.Controls;
using Bit.App.Resources;
using Bit.App.Utilities;
@@ -24,13 +25,17 @@ namespace Bit.App.Pages
private bool _canLogin;
private IPlatformUtilsService _platformUtilsService;
private ILogger _logger;
private IEnvironmentService _environmentService;
private IAccountsManager _accountManager;
public HomeViewModel()
{
_stateService = ServiceContainer.Resolve<IStateService>("stateService");
_messagingService = ServiceContainer.Resolve<IMessagingService>("messagingService");
_stateService = ServiceContainer.Resolve<IStateService>();
_messagingService = ServiceContainer.Resolve<IMessagingService>();
_platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>();
_logger = ServiceContainer.Resolve<ILogger>("logger");
_logger = ServiceContainer.Resolve<ILogger>();
_environmentService = ServiceContainer.Resolve<IEnvironmentService>();
_accountManager = ServiceContainer.Resolve<IAccountsManager>();
PageTitle = AppResources.Bitwarden;
@@ -68,7 +73,7 @@ namespace Bit.App.Pages
public bool CanContinue => !string.IsNullOrEmpty(Email);
public bool CheckHasRememberedEmail { get; set; }
public bool ShouldCheckRememberEmail { get; set; }
public FormattedString CreateAccountText
{
@@ -107,11 +112,11 @@ namespace Bit.App.Pages
public void CheckNavigateLoginStep()
{
if (CheckHasRememberedEmail && RememberEmail)
if (ShouldCheckRememberEmail && RememberEmail)
{
StartLoginAction();
}
CheckHasRememberedEmail = false;
ShouldCheckRememberEmail = false;
}
public async Task ContinueToLoginStepAsync()
@@ -132,6 +137,16 @@ namespace Bit.App.Pages
return;
}
await _stateService.SetRememberedEmailAsync(RememberEmail ? Email : null);
var userId = await _stateService.GetUserIdAsync(Email);
if (!string.IsNullOrWhiteSpace(userId))
{
var userEnvUrls = await _stateService.GetEnvironmentUrlsAsync(userId);
if (userEnvUrls?.Base == _environmentService.BaseUrl)
{
await _accountManager.PromptToSwitchToExistingAccountAsync(userId);
return;
}
}
StartLoginAction();
}
catch (Exception ex)

View File

@@ -110,8 +110,8 @@
VerticalOptions="CenterAndExpand"
Icon="{Binding Source={x:Static core:BitwardenIcons.Device}}"
Label="{u:I18n LogInWithAnotherDevice}"
ButtonCommand="{Binding LogInCommand}"
IsVisible="False"/>
ButtonCommand="{Binding LogInWithDeviceCommand}"
IsVisible="{Binding IsKnownDevice}"/>
<controls:IconLabelButton
HorizontalOptions="Fill"
VerticalOptions="CenterAndExpand"

View File

@@ -3,6 +3,7 @@ using System.Threading.Tasks;
using Bit.App.Models;
using Bit.App.Utilities;
using Bit.Core.Abstractions;
using Bit.Core.Services;
using Bit.Core.Utilities;
using Xamarin.CommunityToolkit.ObjectModel;
using Xamarin.Forms;
@@ -26,9 +27,9 @@ namespace Bit.App.Pages
_vm.Page = this;
_vm.StartTwoFactorAction = () => Device.BeginInvokeOnMainThread(async () => await StartTwoFactorAsync());
_vm.LogInSuccessAction = () => Device.BeginInvokeOnMainThread(async () => await LogInSuccessAsync());
_vm.LogInWithDeviceAction = () => StartLoginWithDeviceAsync().FireAndForget();
_vm.StartSsoLoginAction = () => Device.BeginInvokeOnMainThread(async () => await StartSsoLoginAsync());
_vm.UpdateTempPasswordAction =
() => Device.BeginInvokeOnMainThread(async () => await UpdateTempPasswordAsync());
_vm.UpdateTempPasswordAction = () => Device.BeginInvokeOnMainThread(async () => await UpdateTempPasswordAsync());
_vm.CloseAction = async () =>
{
await _accountListOverlay.HideAsync();
@@ -53,11 +54,6 @@ namespace Bit.App.Pages
ToolbarItems.Add(_getPasswordHint);
}
if (Device.RuntimePlatform == Device.Android && !_vm.IsEmailEnabled)
{
ToolbarItems.Add(_removeAccount);
}
if (_appOptions?.IosExtension ?? false)
{
_vm.ShowCancelButton = true;
@@ -77,16 +73,20 @@ namespace Bit.App.Pages
_mainContent.Content = _mainLayout;
_accountAvatar?.OnAppearing();
await _vm.InitAsync();
if (!_appOptions?.HideAccountSwitcher ?? false)
{
_vm.AvatarImageSource = await GetAvatarImageSourceAsync();
_vm.AvatarImageSource = await GetAvatarImageSourceAsync(_vm.EmailIsInSavedAccounts);
}
await _vm.InitAsync();
if (!_inputFocused)
{
RequestFocus(_masterPassword);
_inputFocused = true;
}
if (Device.RuntimePlatform == Device.Android && !_vm.CanRemoveAccount)
{
ToolbarItems.Add(_removeAccount);
}
}
protected override bool OnBackButtonPressed()
@@ -122,6 +122,12 @@ namespace Bit.App.Pages
}
}
private async Task StartLoginWithDeviceAsync()
{
var page = new LoginPasswordlessRequestPage(_vm.Email, _appOptions);
await Navigation.PushModalAsync(new NavigationPage(page));
}
private async Task StartSsoLoginAsync()
{
var page = new LoginSsoPage(_appOptions);

View File

@@ -1,4 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Input;
using Bit.App.Abstractions;
@@ -6,9 +8,11 @@ using Bit.App.Controls;
using Bit.App.Models;
using Bit.App.Resources;
using Bit.App.Utilities;
using Bit.App.Utilities.AccountManagement;
using Bit.Core;
using Bit.Core.Abstractions;
using Bit.Core.Exceptions;
using Bit.Core.Models.View;
using Bit.Core.Services;
using Bit.Core.Utilities;
using Xamarin.CommunityToolkit.ObjectModel;
@@ -29,6 +33,7 @@ namespace Bit.App.Pages
private readonly ILogger _logger;
private readonly IApiService _apiService;
private readonly IAppIdService _appIdService;
private readonly IAccountsManager _accountManager;
private bool _showPassword;
private bool _showCancelButton;
private string _email;
@@ -49,11 +54,13 @@ namespace Bit.App.Pages
_logger = ServiceContainer.Resolve<ILogger>("logger");
_apiService = ServiceContainer.Resolve<IApiService>();
_appIdService = ServiceContainer.Resolve<IAppIdService>();
_accountManager = ServiceContainer.Resolve<IAccountsManager>();
PageTitle = AppResources.Bitwarden;
TogglePasswordCommand = new Command(TogglePassword);
LogInCommand = new Command(async () => await LogInAsync());
MoreCommand = new AsyncCommand(MoreAsync, onException: _logger.Exception, allowsMultipleExecutions: false);
LogInWithDeviceCommand = new AsyncCommand(() => Device.InvokeOnMainThreadAsync(LogInWithDeviceAction), onException: _logger.Exception, allowsMultipleExecutions: false);
AccountSwitchingOverlayViewModel = new AccountSwitchingOverlayViewModel(_stateService, _messagingService, _logger)
{
@@ -107,22 +114,25 @@ namespace Bit.App.Pages
set => SetProperty(ref _isKnownDevice, value);
}
public bool IsIosExtension { get; set; }
public AccountSwitchingOverlayViewModel AccountSwitchingOverlayViewModel { get; }
public Command LogInCommand { get; }
public Command TogglePasswordCommand { get; }
public ICommand MoreCommand { get; internal set; }
public ICommand LogInWithDeviceCommand { get; }
public string ShowPasswordIcon => ShowPassword ? BitwardenIcons.EyeSlash : BitwardenIcons.Eye;
public string PasswordVisibilityAccessibilityText => ShowPassword ? AppResources.PasswordIsVisibleTapToHide : AppResources.PasswordIsNotVisibleTapToShow;
public string LoggingInAsText => string.Format(AppResources.LoggingInAsX, Email);
public bool IsIosExtension { get; set; }
public bool CanRemoveAccount { get; set; }
public Action StartTwoFactorAction { get; set; }
public Action LogInSuccessAction { get; set; }
public Action LogInWithDeviceAction { get; set; }
public Action UpdateTempPasswordAction { get; set; }
public Action StartSsoLoginAction { get; set; }
public Action CloseAction { get; set; }
public bool EmailIsInSavedAccounts => _stateService.AccountViews != null && _stateService.AccountViews.Any(e => e.Email == Email);
protected override II18nService i18nService => _i18nService;
protected override IEnvironmentService environmentService => _environmentService;
protected override IDeviceActionService deviceActionService => _deviceActionService;
@@ -130,14 +140,23 @@ namespace Bit.App.Pages
public async Task InitAsync()
{
await _deviceActionService.ShowLoadingAsync(AppResources.Loading);
if (string.IsNullOrWhiteSpace(Email))
try
{
Email = await _stateService.GetRememberedEmailAsync();
await _deviceActionService.ShowLoadingAsync(AppResources.Loading);
await AccountSwitchingOverlayViewModel.RefreshAccountViewsAsync();
if (string.IsNullOrWhiteSpace(Email))
{
Email = await _stateService.GetRememberedEmailAsync();
}
var deviceIdentifier = await _appIdService.GetAppIdAsync();
IsKnownDevice = await _apiService.GetKnownDeviceAsync(Email, deviceIdentifier);
CanRemoveAccount = await _stateService.GetActiveUserEmailAsync() != Email;
await _deviceActionService.HideLoadingAsync();
}
catch (Exception ex)
{
HandleException(ex);
}
var deviceIdentifier = await _appIdService.GetAppIdAsync();
IsKnownDevice = await _apiService.GetKnownDeviceAsync(Email, deviceIdentifier);
await _deviceActionService.HideLoadingAsync();
}
public async Task LogInAsync(bool showLoading = true, bool checkForExistingAccount = false)
@@ -180,7 +199,7 @@ namespace Bit.App.Pages
var userEnvUrls = await _stateService.GetEnvironmentUrlsAsync(userId);
if (userEnvUrls?.Base == _environmentService.BaseUrl)
{
await PromptToSwitchToExistingAccountAsync(userId);
await _accountManager.PromptToSwitchToExistingAccountAsync(userId);
return;
}
}
@@ -237,7 +256,7 @@ namespace Bit.App.Pages
private async Task MoreAsync()
{
var buttons = IsEmailEnabled
var buttons = IsEmailEnabled || CanRemoveAccount
? new[] { AppResources.GetPasswordHint }
: new[] { AppResources.GetPasswordHint, AppResources.RemoveAccount };
var selection = await _deviceActionService.DisplayActionSheetAsync(AppResources.Options, AppResources.Cancel, null, buttons);
@@ -287,16 +306,14 @@ namespace Bit.App.Pages
}
}
private async Task PromptToSwitchToExistingAccountAsync(string userId)
private void HandleException(Exception ex)
{
var switchToAccount = await _platformUtilsService.ShowDialogAsync(
AppResources.SwitchToAlreadyAddedAccountConfirmation,
AppResources.AccountAlreadyAdded, AppResources.Yes, AppResources.Cancel);
if (switchToAccount)
Xamarin.Essentials.MainThread.InvokeOnMainThreadAsync(async () =>
{
await _stateService.SetActiveUserAsync(userId);
_messagingService.Send("switchedAccount");
}
await _deviceActionService.HideLoadingAsync();
await _platformUtilsService.ShowDialogAsync(AppResources.GenericErrorMessage);
}).FireAndForget();
_logger.Exception(ex);
}
}
}

View File

@@ -0,0 +1,76 @@
<?xml version="1.0" encoding="UTF-8" ?>
<pages:BaseContentPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Bit.App.Pages.LoginPasswordlessRequestPage"
xmlns:pages="clr-namespace:Bit.App.Pages"
xmlns:controls="clr-namespace:Bit.App.Controls"
xmlns:u="clr-namespace:Bit.App.Utilities"
x:DataType="pages:LoginPasswordlessRequestViewModel"
Title="{Binding PageTitle}">
<ContentPage.BindingContext>
<pages:LoginPasswordlessRequestViewModel />
</ContentPage.BindingContext>
<ContentPage.ToolbarItems>
<ToolbarItem Text="{u:I18n Close}" Command="{Binding CloseCommand}" Order="Primary" Priority="-1" x:Name="_closeItem"/>
</ContentPage.ToolbarItems>
<ScrollView>
<StackLayout
Padding="7, 0, 7, 20">
<Label
Text="{u:I18n LogInInitiated}"
FontSize="Title"
FontAttributes="Bold"
Margin="0,14,0,21"/>
<Label
Text="{u:I18n ANotificationHasBeenSentToYourDevice}"
FontSize="Small"
Margin="0,0,0,10"/>
<Label
Text="{u:I18n PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice}"
FontSize="Small"
Margin="0,0,0,24"/>
<Label
Text="{u:I18n FingerprintPhrase}"
FontSize="Small"
FontAttributes="Bold"/>
<controls:MonoLabel
FormattedText="{Binding FingerprintPhrase}"
FontSize="Medium"
TextColor="{DynamicResource FingerprintPhrase}"/>
<Label
Text="{u:I18n ResendNotification}"
StyleClass="text-md"
HorizontalOptions="Start"
Margin="0,40,0,0"
TextColor="{DynamicResource HyperlinkColor}">
<Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding CreatePasswordlessLoginCommand}" />
</Label.GestureRecognizers>
</Label>
<StackLayout
Orientation="Horizontal"
Margin="0,30,0,0">
<Label
Text="{u:I18n NeedAnotherOption}"
FontSize="Small"
VerticalTextAlignment="End"/>
<Label
Text="{u:I18n ViewAllLoginOptions}"
StyleClass="text-md"
VerticalTextAlignment="End"
VerticalOptions="CenterAndExpand"
Margin="5, 0"
TextColor="{DynamicResource HyperlinkColor}">
<Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding CloseCommand}" />
</Label.GestureRecognizers>
</Label>
</StackLayout>
</StackLayout>
</ScrollView>
</pages:BaseContentPage>

View File

@@ -0,0 +1,65 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Bit.App.Models;
using Bit.App.Utilities;
using Xamarin.Forms;
namespace Bit.App.Pages
{
public partial class LoginPasswordlessRequestPage : BaseContentPage
{
private LoginPasswordlessRequestViewModel _vm;
private readonly AppOptions _appOptions;
public LoginPasswordlessRequestPage(string email, AppOptions appOptions = null)
{
InitializeComponent();
_appOptions = appOptions;
_vm = BindingContext as LoginPasswordlessRequestViewModel;
_vm.Page = this;
_vm.Email = email;
_vm.StartTwoFactorAction = () => Device.BeginInvokeOnMainThread(async () => await StartTwoFactorAsync());
_vm.LogInSuccessAction = () => Device.BeginInvokeOnMainThread(async () => await LogInSuccessAsync());
_vm.UpdateTempPasswordAction = () => Device.BeginInvokeOnMainThread(async () => await UpdateTempPasswordAsync());
_vm.CloseAction = () => { Navigation.PopModalAsync(); };
_vm.CreatePasswordlessLoginCommand.Execute(null);
}
protected override void OnAppearing()
{
base.OnAppearing();
_vm.StartCheckLoginRequestStatus();
}
protected override void OnDisappearing()
{
base.OnDisappearing();
_vm.StopCheckLoginRequestStatus();
}
private async Task StartTwoFactorAsync()
{
var page = new TwoFactorPage(false, _appOptions);
await Navigation.PushModalAsync(new NavigationPage(page));
}
private async Task LogInSuccessAsync()
{
if (AppHelpers.SetAlternateMainPage(_appOptions))
{
return;
}
var previousPage = await AppHelpers.ClearPreviousPage();
Application.Current.MainPage = new TabsPage(_appOptions, previousPage);
}
private async Task UpdateTempPasswordAsync()
{
var page = new UpdateTempPasswordPage();
await Navigation.PushModalAsync(new NavigationPage(page));
}
}
}

View File

@@ -0,0 +1,194 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Input;
using Bit.App.Abstractions;
using Bit.App.Resources;
using Bit.App.Utilities;
using Bit.Core;
using Bit.Core.Abstractions;
using Bit.Core.Enums;
using Bit.Core.Models.Domain;
using Bit.Core.Services;
using Bit.Core.Utilities;
using Xamarin.CommunityToolkit.ObjectModel;
using Xamarin.Essentials;
using Xamarin.Forms;
namespace Bit.App.Pages
{
public class LoginPasswordlessRequestViewModel : CaptchaProtectedViewModel
{
private const int REQUEST_TIME_UPDATE_PERIOD_IN_SECONDS = 4;
private IDeviceActionService _deviceActionService;
private IAuthService _authService;
private ISyncService _syncService;
private II18nService _i18nService;
private IStateService _stateService;
private IPlatformUtilsService _platformUtilsService;
private IEnvironmentService _environmentService;
private ILogger _logger;
protected override II18nService i18nService => _i18nService;
protected override IEnvironmentService environmentService => _environmentService;
protected override IDeviceActionService deviceActionService => _deviceActionService;
protected override IPlatformUtilsService platformUtilsService => _platformUtilsService;
private CancellationTokenSource _checkLoginRequestStatusCts;
private Task _checkLoginRequestStatusTask;
private string _fingerprintPhrase;
private string _email;
private string _requestId;
private string _requestAccessCode;
// Item1 publicKey, Item2 privateKey
private Tuple<byte[], byte[]> _requestKeyPair;
public LoginPasswordlessRequestViewModel()
{
_deviceActionService = ServiceContainer.Resolve<IDeviceActionService>();
_platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>();
_environmentService = ServiceContainer.Resolve<IEnvironmentService>();
_authService = ServiceContainer.Resolve<IAuthService>();
_syncService = ServiceContainer.Resolve<ISyncService>();
_i18nService = ServiceContainer.Resolve<II18nService>();
_stateService = ServiceContainer.Resolve<IStateService>();
_logger = ServiceContainer.Resolve<ILogger>();
PageTitle = AppResources.LogInWithAnotherDevice;
CreatePasswordlessLoginCommand = new AsyncCommand(CreatePasswordlessLoginAsync,
onException: ex => HandleException(ex),
allowsMultipleExecutions: false);
CloseCommand = new AsyncCommand(() => Device.InvokeOnMainThreadAsync(CloseAction),
onException: _logger.Exception,
allowsMultipleExecutions: false);
}
public Action StartTwoFactorAction { get; set; }
public Action LogInSuccessAction { get; set; }
public Action UpdateTempPasswordAction { get; set; }
public Action CloseAction { get; set; }
public ICommand CreatePasswordlessLoginCommand { get; }
public ICommand CloseCommand { get; }
public string FingerprintPhrase
{
get => _fingerprintPhrase;
set => SetProperty(ref _fingerprintPhrase, value);
}
public string Email
{
get => _email;
set => SetProperty(ref _email, value);
}
public void StartCheckLoginRequestStatus()
{
try
{
_checkLoginRequestStatusCts?.Cancel();
_checkLoginRequestStatusCts = new CancellationTokenSource();
_checkLoginRequestStatusTask = new TimerTask(_logger, CheckLoginRequestStatus, _checkLoginRequestStatusCts).RunPeriodic(TimeSpan.FromSeconds(REQUEST_TIME_UPDATE_PERIOD_IN_SECONDS));
}
catch (Exception ex)
{
_logger.Exception(ex);
}
}
public void StopCheckLoginRequestStatus()
{
try
{
_checkLoginRequestStatusCts?.Cancel();
_checkLoginRequestStatusCts?.Dispose();
_checkLoginRequestStatusCts = null;
}
catch (Exception ex)
{
_logger.Exception(ex);
}
}
private async Task CheckLoginRequestStatus()
{
if (string.IsNullOrEmpty(_requestId) || string.IsNullOrEmpty(_requestAccessCode))
{
return;
}
try
{
var response = await _authService.GetPasswordlessLoginResponseAsync(_requestId, _requestAccessCode);
if (response.RequestApproved == null || !response.RequestApproved.Value)
{
return;
}
StopCheckLoginRequestStatus();
var authResult = await _authService.LogInPasswordlessAsync(Email, _requestAccessCode, _requestId, _requestKeyPair.Item2, response.Key, response.MasterPasswordHash);
await AppHelpers.ResetInvalidUnlockAttemptsAsync();
if (await HandleCaptchaAsync(authResult.CaptchaSiteKey, authResult.CaptchaNeeded, CheckLoginRequestStatus))
{
return;
}
if (authResult.TwoFactor)
{
StartTwoFactorAction?.Invoke();
}
else if (authResult.ForcePasswordReset)
{
UpdateTempPasswordAction?.Invoke();
}
else
{
_syncService.FullSyncAsync(true).FireAndForget();
LogInSuccessAction?.Invoke();
}
}
catch (Exception ex)
{
StartCheckLoginRequestStatus();
HandleException(ex);
}
}
private async Task CreatePasswordlessLoginAsync()
{
await Device.InvokeOnMainThreadAsync(() => _deviceActionService.ShowLoadingAsync(AppResources.Loading));
var response = await _authService.PasswordlessCreateLoginRequestAsync(_email);
if (response != null)
{
FingerprintPhrase = response.RequestFingerprint;
_requestId = response.Id;
_requestAccessCode = response.RequestAccessCode;
_requestKeyPair = response.RequestKeyPair;
}
await _deviceActionService.HideLoadingAsync();
}
private void HandleException(Exception ex)
{
Xamarin.Essentials.MainThread.InvokeOnMainThreadAsync(async () =>
{
await _deviceActionService.HideLoadingAsync();
await _platformUtilsService.ShowDialogAsync(AppResources.GenericErrorMessage);
}).FireAndForget();
_logger.Exception(ex);
}
}
}

View File

@@ -100,7 +100,7 @@ namespace Bit.App.Pages
private async Task UpdateRequestTime()
{
TriggerPropertyChanged(nameof(TimeOfRequestText));
if (DateTime.UtcNow > LoginRequest?.RequestDate.ToUniversalTime().AddMinutes(Constants.PasswordlessNotificationTimeoutInMinutes))
if (LoginRequest?.IsExpired ?? false)
{
StopRequestTimeUpdater();
await _platformUtilsService.ShowDialogAsync(AppResources.LoginRequestHasAlreadyExpired);
@@ -110,13 +110,21 @@ namespace Bit.App.Pages
private async Task PasswordlessLoginAsync(bool approveRequest)
{
if (LoginRequest.RequestDate.ToUniversalTime().AddMinutes(Constants.PasswordlessNotificationTimeoutInMinutes) <= DateTime.UtcNow)
if (LoginRequest.IsExpired)
{
await _platformUtilsService.ShowDialogAsync(AppResources.LoginRequestHasAlreadyExpired);
await Page.Navigation.PopModalAsync();
return;
}
var loginRequestData = await _authService.GetPasswordlessLoginRequestByIdAsync(LoginRequest.Id);
if (loginRequestData.RequestApproved.HasValue && loginRequestData.ResponseDate.HasValue)
{
await _platformUtilsService.ShowDialogAsync(AppResources.ThisRequestIsNoLongerValid);
await Page.Navigation.PopModalAsync();
return;
}
await _deviceActionService.ShowLoadingAsync(AppResources.Loading);
await _authService.PasswordlessLoginAsync(LoginRequest.Id, LoginRequest.PubKey, approveRequest);
await _deviceActionService.HideLoadingAsync();
@@ -171,5 +179,7 @@ namespace Bit.App.Pages
public string DeviceType { get; set; }
public string IpAddress { get; set; }
public bool IsExpired => RequestDate.ToUniversalTime().AddMinutes(Constants.PasswordlessNotificationTimeoutInMinutes) < DateTime.UtcNow;
}
}

View File

@@ -16,6 +16,22 @@ namespace Bit.App.Pages
protected abstract IPlatformUtilsService platformUtilsService { get; }
protected string _captchaToken = null;
protected async Task<bool> HandleCaptchaAsync(string captchaSiteKey, bool needsCaptcha, Func<Task> onSuccess)
{
if (!needsCaptcha)
{
_captchaToken = null;
return false;
}
if (await HandleCaptchaAsync(captchaSiteKey))
{
await onSuccess();
_captchaToken = null;
}
return true;
}
protected async Task<bool> HandleCaptchaAsync(string CaptchaSiteKey)
{
var callbackUri = "bitwarden://captcha-callback";

View File

@@ -90,6 +90,7 @@ namespace Bit.App.Pages
try
{
await _deviceActionService.ShowLoadingAsync(AppResources.Syncing);
await _syncService.SyncPasswordlessLoginRequestsAsync();
var success = await _syncService.FullSyncAsync(true);
await _deviceActionService.HideLoadingAsync();
if (success)

View File

@@ -189,6 +189,7 @@ namespace Bit.App.Pages
if (await _stateService.GetSyncOnRefreshAsync() && Refreshing && !SyncRefreshing)
{
SyncRefreshing = true;
await _syncService.SyncPasswordlessLoginRequestsAsync();
await _syncService.FullSyncAsync(false);
return;
}

View File

@@ -481,6 +481,15 @@ namespace Bit.App.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to A notification has been sent to your device..
/// </summary>
public static string ANotificationHasBeenSentToYourDevice {
get {
return ResourceManager.GetString("ANotificationHasBeenSentToYourDevice", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to API access token.
/// </summary>
@@ -3480,6 +3489,15 @@ namespace Bit.App.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to Log in initiated.
/// </summary>
public static string LogInInitiated {
get {
return ResourceManager.GetString("LogInInitiated", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Login.
/// </summary>
@@ -3966,6 +3984,15 @@ namespace Bit.App.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to Need another option?.
/// </summary>
public static string NeedAnotherOption {
get {
return ResourceManager.GetString("NeedAnotherOption", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Never.
/// </summary>
@@ -4705,6 +4732,15 @@ namespace Bit.App.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to Please make sure your vault is unlocked and the Fingerprint phrase matches on the other device..
/// </summary>
public static string PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice {
get {
return ResourceManager.GetString("PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Plus addressed email.
/// </summary>
@@ -5003,6 +5039,15 @@ namespace Bit.App.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to Resend notification.
/// </summary>
public static string ResendNotification {
get {
return ResourceManager.GetString("ResendNotification", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to This organization has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organization administrators to change your master password..
/// </summary>
@@ -5831,6 +5876,15 @@ namespace Bit.App.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to This request is no longer valid.
/// </summary>
public static string ThisRequestIsNoLongerValid {
get {
return ResourceManager.GetString("ThisRequestIsNoLongerValid", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to 3 days.
/// </summary>
@@ -6542,6 +6596,15 @@ namespace Bit.App.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to View all log in options.
/// </summary>
public static string ViewAllLoginOptions {
get {
return ResourceManager.GetString("ViewAllLoginOptions", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to View item.
/// </summary>

View File

@@ -2485,9 +2485,30 @@ Do you want to switch to this account?</value>
<value>Not you?</value>
</data>
<data name="LogInWithMasterPassword" xml:space="preserve">
<value>Log In with master password</value>
<value>Log in with master password</value>
</data>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Log In with another device</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Log in initiated</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>A notification has been sent to your device.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Please make sure your vault is unlocked and the Fingerprint phrase matches on the other device.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Resend notification</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Need another option?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>View all log in options</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>This request is no longer valid</value>
</data>
</root>

View File

@@ -2474,21 +2474,42 @@
هل تريد التبديل إلى هذا الحساب؟</value>
</data>
<data name="NewAroundHere" xml:space="preserve">
<value>New around here?</value>
<value>جديد هنا؟</value>
</data>
<data name="GetMasterPasswordwordHint" xml:space="preserve">
<value>Get master password hint</value>
<value>احصل على تلميح كلمة المرور الرئيسية</value>
</data>
<data name="LoggingInAsX" xml:space="preserve">
<value>Logging in as {0}</value>
<value>تسجيل الدخول كـ {0}</value>
</data>
<data name="NotYou" xml:space="preserve">
<value>Not you?</value>
<value>ليس أنت؟</value>
</data>
<data name="LogInWithMasterPassword" xml:space="preserve">
<value>Log In with master password</value>
<value>تسجيل الدخول باستخدام كلمة المرور الرئيسية</value>
</data>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Log In with another device</value>
<value>تسجيل الدخول باستخدام جهاز آخر</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Log in initiated</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>A notification has been sent to your device.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Please make sure your vault is unlocked and the Fingerprint phrase matches on the other device.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Resend notification</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Need another option?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>View all log in options</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>This request is no longer valid</value>
</data>
</root>

View File

@@ -2489,4 +2489,25 @@ Bu hesaba keçmək istəyirsiniz?</value>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Başqa cihazla giriş et</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Giriş etmə başladıldı</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>Cihazınıza bir bildiriş göndərildi.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Zəhmət olmasa anbarınızın kilidinin açıq olduğuna və Barmaq izi ifadəsinin digər cihazda uyğun gəldiyinə əmin olun.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Bildirişi təkrar göndər</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Başqa bir seçimə ehtiyacınız var?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>Bütün giriş etmə seçimlərinə bax</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>Bu tələb artıq yararsızdır</value>
</data>
</root>

View File

@@ -349,7 +349,7 @@
<value>Адправіць</value>
</data>
<data name="Sync" xml:space="preserve">
<value>Сінхранізавана</value>
<value>Сінхранізаваць</value>
<comment>The title for the sync page.</comment>
</data>
<data name="ThankYou" xml:space="preserve">
@@ -1622,7 +1622,7 @@
<value>Біяметрычныя праверка</value>
</data>
<data name="Biometrics" xml:space="preserve">
<value>Біяметрыяй</value>
<value>біяметрыяй</value>
</data>
<data name="UseBiometricsToUnlock" xml:space="preserve">
<value>Выкарыстоўваць біяметрычныя даныя для разблакіроўкі</value>
@@ -2490,4 +2490,25 @@
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Увайсці з іншай прылады</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Ініцыяваны ўваход</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>Апавяшчэнне было адпраўлена на вашу прыладу.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Пераканайцеся, што ваша сховішча разблакіравана, а фраза адбітка пальца супадае з іншай прыладай.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Адправіць апавяшчэнне паўторна</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Неабходны іншы варыянт?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>Паглядзець усе варыянты ўваходу</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>Гэты запыт больш не дзейнічае</value>
</data>
</root>

View File

@@ -2491,4 +2491,25 @@ select Add TOTP to store the key safely</value>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Вписване с друго устройство</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Вписването е стартирано</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>Към устройството Ви е изпратено известие.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Уверете се, че трезорът Ви е отключен и че Уникалната фраза съвпада с другото устройство.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Повторно изпращане на известието</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Предпочитате друг вариант?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>Вижте всички възможности за вписване</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>Тази зявка вече не е приложима</value>
</data>
</root>

View File

@@ -1762,7 +1762,7 @@ Scanning will happen automatically.</value>
<value>Syncing vault with pull down gesture.</value>
</data>
<data name="LogInSso" xml:space="preserve">
<value>Enterprise Single Sign-On</value>
<value>Enterprise single sign-on</value>
</data>
<data name="LogInSsoSummary" xml:space="preserve">
<value>Quickly log in using your organization's single sign-on portal. Please enter your organization's identifier to begin.</value>
@@ -2486,9 +2486,30 @@ Do you want to switch to this account?</value>
<value>Not you?</value>
</data>
<data name="LogInWithMasterPassword" xml:space="preserve">
<value>Log In with master password</value>
<value>Log in with master password</value>
</data>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Log In with another device</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Log in initiated</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>A notification has been sent to your device.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Please make sure your vault is unlocked and the Fingerprint phrase matches on the other device.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Resend notification</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Need another option?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>View all log in options</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>This request is no longer valid</value>
</data>
</root>

View File

@@ -2485,9 +2485,30 @@ Do you want to switch to this account?</value>
<value>Not you?</value>
</data>
<data name="LogInWithMasterPassword" xml:space="preserve">
<value>Log In with master password</value>
<value>Log in with master password</value>
</data>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Log In with another device</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Log in initiated</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>A notification has been sent to your device.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Please make sure your vault is unlocked and the Fingerprint phrase matches on the other device.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Resend notification</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Need another option?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>View all log in options</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>This request is no longer valid</value>
</data>
</root>

View File

@@ -2485,9 +2485,30 @@ Voleu canviar a aquest compte?</value>
<value>No sou vosaltres?</value>
</data>
<data name="LogInWithMasterPassword" xml:space="preserve">
<value>Inicia sessió amb la teua contrasenya mestra</value>
<value>Inicia sessió amb la contrasenya mestra</value>
</data>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Inicia sessió amb un altre dispositiu</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>S'ha iniciat la sessió</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>S'ha enviat una notificació al vostre dispositiu.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Assegureu-vos que la vostra caixa forta estiga desbloquejada i que la frase d'empremta digital coincidisca amb l'altre dispositiu.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Torna a enviar la notificació</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Necessiteu una altra opció?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>Veure totes les opcions d'inici de sessió</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>Aquesta sol·licitud ja no és vàlida</value>
</data>
</root>

View File

@@ -1457,11 +1457,11 @@ Načtení proběhne automaticky.</value>
<value>Nejsou k dispozici žádné složky k zobrazení.</value>
</data>
<data name="FingerprintPhrase" xml:space="preserve">
<value>Fráze otisku prstu</value>
<value>Fráze otisku účtu</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>
</data>
<data name="YourAccountsFingerprint" xml:space="preserve">
<value>Fráze otisku prstu vašeho účtu</value>
<value>Fráze otisku vašeho účtu</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>
</data>
<data name="LearnOrgConfirmation" xml:space="preserve">
@@ -2468,26 +2468,47 @@ select Add TOTP to store the key safely</value>
<value>Požadavek na přihlášení již vypršel.</value>
</data>
<data name="LoginAttemptFromXDoYouWantToSwitchToThisAccount" xml:space="preserve">
<value>Login attempt from:
<value>Pokus o přihlášení z:
{0}
Do you want to switch to this account?</value>
Chcete se přepnout na tento účet?</value>
</data>
<data name="NewAroundHere" xml:space="preserve">
<value>New around here?</value>
<value>Jste tu noví?</value>
</data>
<data name="GetMasterPasswordwordHint" xml:space="preserve">
<value>Get master password hint</value>
<value>Získat nápovědu pro hlavní heslo</value>
</data>
<data name="LoggingInAsX" xml:space="preserve">
<value>Logging in as {0}</value>
<value>Přihlášování jako {0}</value>
</data>
<data name="NotYou" xml:space="preserve">
<value>Not you?</value>
<value>Nejste to vy?</value>
</data>
<data name="LogInWithMasterPassword" xml:space="preserve">
<value>Log In with master password</value>
<value>Přihlásit se pomocí hlavního hesla</value>
</data>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Log In with another device</value>
<value>Přihlásit se pomocí jiného zařízení</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Přihlášení zahájeno</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>Na vaše zařízení bylo odesláno oznámení.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Ujistěte se, že je váš trezor odemčen a fráze otisku prstu se shodují s druhým zařízením.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Odeslat oznámení znovu</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Potřebujete jinou možnost?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>Zobrazit všechny možnosti přihlášení</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>Tento požadavek již není platný</value>
</data>
</root>

View File

@@ -2490,4 +2490,25 @@ Vil du skifte til denne konto?</value>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Log ind med en anden enhed</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Indlogning påbegyndt</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>En notifikation er sendt til din enhed.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Sørg for, at din boks er oplåst, samt at Fingeraftrykssætningen på den anden enhed matcher.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Gensend notifikation</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Behov for en anden mulighed?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>Vis alle indlogningsmuligheder</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>Anmodningen er ikke længere gyldig</value>
</data>
</root>

View File

@@ -229,7 +229,7 @@
<value>Ordner</value>
</data>
<data name="FolderUpdated" xml:space="preserve">
<value>Ordner wurde aktualisiert</value>
<value>Ordner aktualisiert</value>
</data>
<data name="GoToWebsite" xml:space="preserve">
<value>Webseite besuchen</value>
@@ -342,7 +342,7 @@
<comment>Reveal a hidden value (password).</comment>
</data>
<data name="ItemDeleted" xml:space="preserve">
<value>Eintrag wurde gelöscht</value>
<value>Eintrag gelöscht</value>
<comment>Confirmation message after successfully deleting a login.</comment>
</data>
<data name="Submit" xml:space="preserve">
@@ -416,7 +416,7 @@
<value>Neuer Eintrag</value>
</data>
<data name="AppExtension" xml:space="preserve">
<value>App Erweiterung</value>
<value>App-Erweiterung</value>
</data>
<data name="AutofillAccessibilityDescription" xml:space="preserve">
<value>Verwende den Bitwarden Dienst in den Bedienungshilfen, um deine Zugangsdaten in Apps und im Web automatisch ausfüllen zu lassen.</value>
@@ -428,7 +428,7 @@
<value>Mehrdeutige Zeichen vermeiden</value>
</data>
<data name="BitwardenAppExtension" xml:space="preserve">
<value>Bitwarden App Erweiterung</value>
<value>Bitwarden App-Erweiterung</value>
</data>
<data name="BitwardenAppExtensionAlert2" xml:space="preserve">
<value>Die einfachste Möglichkeit, neue Anmeldedaten zu Ihrem Tresor hinzuzufügen, ist die Bitwarden App Erweiterung. Erfahren Sie mehr über die Bitwarden App Erweiterung, indem Sie zu dem "Einstellungen"-Bildschirm navigieren.</value>
@@ -477,13 +477,13 @@
<value>Gebe die E-Mail Adresse deines Kontos ein, um den Hinweis für dein Master-Passwort zu erhalten.</value>
</data>
<data name="ExntesionReenable" xml:space="preserve">
<value>App Erweiterung wieder aktivieren</value>
<value>App-Erweiterung wieder aktivieren</value>
</data>
<data name="ExtensionAlmostDone" xml:space="preserve">
<value>Fast geschafft!</value>
</data>
<data name="ExtensionEnable" xml:space="preserve">
<value>App Erweiterung aktivieren</value>
<value>App-Erweiterung aktivieren</value>
</data>
<data name="ExtensionInSafari" xml:space="preserve">
<value>In Safari findest du Bitwarden unter dem Teilen-Symbol (Hinweis: scrolle auf der untersten Zeile des Menüs nach rechts).</value>
@@ -647,7 +647,7 @@
<value>Bist du sicher, dass du das aktuelle Passwort überschreiben möchtest?</value>
</data>
<data name="PushNotificationAlert" xml:space="preserve">
<value>Bitwarden aktualisiert deinen Tresor mit Pushbenachrichtigungen. Für die bestmögliche Benutzererfahrung tippe im folgenden Dialogfenster auf "Ok", um Pushbenachrichtigungen zu aktivieren.</value>
<value>Bitwarden aktualisiert deinen Tresor mit Push-Benachrichtigungen. Für die bestmögliche Benutzererfahrung tippe im folgenden Dialogfenster auf "Ok", um Push-Benachrichtigungen zu aktivieren.</value>
<comment>Push notifications for apple products</comment>
</data>
<data name="RateTheApp" xml:space="preserve">
@@ -705,10 +705,10 @@
<comment>What Apple calls their fingerprint reader.</comment>
</data>
<data name="TwoStepLogin" xml:space="preserve">
<value>Zwei-Faktor Authentifizierung</value>
<value>Zwei-Faktor-Authentifizierung</value>
</data>
<data name="TwoStepLoginConfirmation" xml:space="preserve">
<value>Mit der Zwei-Faktor Authentifizierung wird dein Account zusätzlich abgesichert, da jede Anmeldung durch einen Sicherheitscode, eine Authentifizierungs-App, SMS, einen Anruf oder eine E-Mail verifiziert werden muss. Die Zwei-Faktor Authentifizierung kann im Bitwarden.com Web-Tresor aktiviert werden. Möchtest du die Seite jetzt öffnen?</value>
<value>Mit der Zwei-Faktor-Authentifizierung wird dein Account zusätzlich abgesichert, da jede Anmeldung durch einen Sicherheitscode, eine Authentifizierungs-App, SMS, einen Anruf oder eine E-Mail verifiziert werden muss. Die Zwei-Faktor-Authentifizierung kann im Web-Tresor unter bitwarden.com aktiviert werden. Möchtest du die Seite jetzt öffnen?</value>
</data>
<data name="UnlockWith" xml:space="preserve">
<value>Mit {0} entsperren</value>
@@ -831,7 +831,7 @@
<comment>For 2FA whenever there are no available providers on this device.</comment>
</data>
<data name="NoTwoStepAvailable" xml:space="preserve">
<value>Dieses Konto hat eine aktive Zwei-Faktor Authentifizierung, allerdings wird keiner der konfigurierten Zwei-Faktor Anbieter von diesem Gerät unterstützt. Bitte nutzen Sie ein unterstütztes Gerät und / oder fügen Sie zusätzliche Anbieter hinzu, die von mehr Geräten unterstützt werden (wie eine Authentifizierungs-App).</value>
<value>Dieses Konto hat eine aktive Zwei-Faktor-Authentifizierung, allerdings wird keiner der konfigurierten Zwei-Faktor-Anbieter von diesem Gerät unterstützt. Bitte nutzen Sie ein unterstütztes Gerät und / oder fügen Sie zusätzliche Anbieter hinzu, die von mehr Geräten unterstützt werden (wie eine Authentifizierungs-App).</value>
</data>
<data name="RecoveryCodeTitle" xml:space="preserve">
<value>Wiederherstellungscode</value>
@@ -1726,7 +1726,7 @@ Das Scannen erfolgt automatisch.</value>
<comment>Message shown when interacting with the server</comment>
</data>
<data name="ItemRestored" xml:space="preserve">
<value>Eintrag wurde wiederhergestellt</value>
<value>Eintrag wiederhergestellt</value>
<comment>Confirmation message after successfully restoring a soft-deleted item</comment>
</data>
<data name="Trash" xml:space="preserve">
@@ -2489,4 +2489,25 @@ Möchtest du zu diesem Konto wechseln?</value>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Mit einem anderen Gerät anmelden</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Anmeldung initiiert</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>Eine Benachrichtigung wurde an dein Gerät gesendet.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Bitte stelle sicher, dass dein Tresor entsperrt ist und die Fingerabdruck-Phrase mit dem anderen Gerät übereinstimmt.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Benachrichtigung erneut senden</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Brauchst du eine andere Option?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>Alle Anmelde-Optionen anzeigen</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>Diese Anfrage ist nicht mehr gültig</value>
</data>
</root>

View File

@@ -2485,9 +2485,30 @@ Do you want to switch to this account?</value>
<value>Not you?</value>
</data>
<data name="LogInWithMasterPassword" xml:space="preserve">
<value>Log In with master password</value>
<value>Log in with master password</value>
</data>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Log In with another device</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Log in initiated</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>A notification has been sent to your device.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Please make sure your vault is unlocked and the Fingerprint phrase matches on the other device.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Resend notification</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Need another option?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>View all log in options</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>This request is no longer valid</value>
</data>
</root>

View File

@@ -2499,4 +2499,25 @@ Do you want to switch to this account?</value>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Log in with another device</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Log in initiated</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>A notification has been sent to your device.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Please make sure your vault is unlocked and the Fingerprint phrase matches on the other device.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Resend notification</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Need another option?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>View all log in options</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>This request is no longer valid</value>
</data>
</root>

View File

@@ -2499,9 +2499,30 @@ Do you want to switch to this account?</value>
<value>Not you?</value>
</data>
<data name="LogInWithMasterPassword" xml:space="preserve">
<value>Log In with master password</value>
<value>Log in with master password</value>
</data>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Log In with another device</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Log in initiated</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>A notification has been sent to your device.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Please make sure your vault is unlocked and the Fingerprint phrase matches on the other device.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Resend notification</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Need another option?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>View all log in options</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>This request is no longer valid</value>
</data>
</root>

View File

@@ -2491,4 +2491,25 @@ seleccione Agregar TOTP para almacenar la clave de forma segura</value>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Iniciar sesión con otro dispositivo</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Inicio de sesión en proceso</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>Se ha enviado una notificación a tu dispositivo.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Por favor, asegúrese de que su bóveda está desbloqueada y la frase de huella dactilar coincide en el otro dispositivo.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Enviar nueva notificación</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>¿Necesitas otra opción?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>Ver todas las opciones de inicio de sesión</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>Esta solicitud ya no es válida</value>
</data>
</root>

View File

@@ -2490,4 +2490,25 @@ Soovid selle konto peale lülituda?</value>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Logi sisse läbi teise seadme</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Sisselogimine on käivitatud</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>Sinu seadmesse saadeti teavitus.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Veendu, et hoidla on lahti lukustatud ja sõrmejälje fraasid seadmete vahel ühtivad.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Saada märguanne uuesti</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Soovid teist valikut kasutada?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>Vaata kõiki valikuid</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>See päring ei ole enam kehtiv</value>
</data>
</root>

View File

@@ -1575,7 +1575,7 @@
<comment>'Nord' is the name of a specific color scheme. It should not be translated.</comment>
</data>
<data name="SolarizedDark" xml:space="preserve">
<value>Solarized Dark</value>
<value>Solarized iluna</value>
<comment>'Solarized Dark' is the name of a specific color scheme. It should not be translated.</comment>
</data>
<data name="AutofillBlockedUris" xml:space="preserve">
@@ -2464,29 +2464,50 @@
<value>Baztertu</value>
</data>
<data name="LoginRequestHasAlreadyExpired" xml:space="preserve">
<value>Login request has already expired.</value>
<value>Sarbide eskaera iraungi da.</value>
</data>
<data name="LoginAttemptFromXDoYouWantToSwitchToThisAccount" xml:space="preserve">
<value>Login attempt from:
<value>Saio hasiera saiakera hemendik:
{0}
Do you want to switch to this account?</value>
Kontu honetara aldatu nahi duzu?</value>
</data>
<data name="NewAroundHere" xml:space="preserve">
<value>New around here?</value>
<value>Berria hemendik?</value>
</data>
<data name="GetMasterPasswordwordHint" xml:space="preserve">
<value>Get master password hint</value>
<value>Jaso pasahitz nagusiaren pista</value>
</data>
<data name="LoggingInAsX" xml:space="preserve">
<value>Logging in as {0}</value>
<value>{0} bezala hasi saioa</value>
</data>
<data name="NotYou" xml:space="preserve">
<value>Not you?</value>
<value>Ez zara zu?</value>
</data>
<data name="LogInWithMasterPassword" xml:space="preserve">
<value>Log In with master password</value>
<value>Hasi saioa pasahitz nagusiarekin</value>
</data>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Log In with another device</value>
<value>Hasi saioa beste gailu batekin</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Saioa hastea martxan da</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>Jakinarazpen bat bidali da zure gailura.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Mesedez, ziurtatu kutxa gotorra desblokeatuta dagoela eta hatz-marka digitalaren esaldia bat datorrela beste gailuarekin.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Berbidali jakinarazpena</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Beste aukerarik behar al duzu?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>Ikusi erregistro guztiak ezarpenetan</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>This request is no longer valid</value>
</data>
</root>

View File

@@ -2491,4 +2491,25 @@
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>با دستگاه دیگری وارد شوید</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Log in initiated</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>A notification has been sent to your device.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Please make sure your vault is unlocked and the Fingerprint phrase matches on the other device.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Resend notification</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Need another option?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>View all log in options</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>This request is no longer valid</value>
</data>
</root>

View File

@@ -1762,7 +1762,7 @@ Koodi luetaan automaattisesti.</value>
<value>Synkronoidaan holvi alasveto-eleellä.</value>
</data>
<data name="LogInSso" xml:space="preserve">
<value>Kertakirjautuminen (SSO)</value>
<value>Yrityksen kertakirjautuminen (SSO)</value>
</data>
<data name="LogInSsoSummary" xml:space="preserve">
<value>Kirjaudu sisään käyttäen organisaatiosi kertakirjautumista (SSO). Syötä organisaatiosi tunniste aloittaaksesi.</value>
@@ -1810,7 +1810,8 @@ Koodi luetaan automaattisesti.</value>
<value>Ladataan</value>
</data>
<data name="AcceptPolicies" xml:space="preserve">
<value>Aktivoimalla tämän valinnan hyväksyt seuraavat: </value>
<value>Valitsemalla tämän hyväksyt seuraavat:
</value>
</data>
<data name="AcceptPoliciesError" xml:space="preserve">
<value>Palveluehtoja ja tietosuojakäytäntöä ei ole vahvistettu.</value>
@@ -2482,7 +2483,7 @@ Haluatko vaihtaa tähän tiliin?</value>
<value>Kirjaudutaan tunnuksella {0}</value>
</data>
<data name="NotYou" xml:space="preserve">
<value>Etkö se ole sinä?</value>
<value>Etkö se ollut sinä?</value>
</data>
<data name="LogInWithMasterPassword" xml:space="preserve">
<value>Kirjaudu pääsalasanalla</value>
@@ -2490,4 +2491,25 @@ Haluatko vaihtaa tähän tiliin?</value>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Kirjaudu toisella laitteella</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Kirjautuminen aloitettu</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>Laitteellesi on lähetetty ilmoitus.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Varmista, että holvisi on avattu ja tunnistelauseke täsmää toisella laitteella.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Lähetä ilmoitus uudelleen</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Tarvitsetko toisen vaihtoehdon?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>Näytä kaikki kirjautumisvaihtoehdot</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>Pyyntö ei ole enää voimassa.</value>
</data>
</root>

View File

@@ -1762,7 +1762,7 @@ Scanning will happen automatically.</value>
<value>Syncing vault with pull down gesture.</value>
</data>
<data name="LogInSso" xml:space="preserve">
<value>Enterprise Single Sign-On</value>
<value>Enterprise single sign-on</value>
</data>
<data name="LogInSsoSummary" xml:space="preserve">
<value>Quickly log in using your organization's single sign-on portal. Please enter your organization's identifier to begin.</value>
@@ -2486,9 +2486,30 @@ Do you want to switch to this account?</value>
<value>Not you?</value>
</data>
<data name="LogInWithMasterPassword" xml:space="preserve">
<value>Log In with master password</value>
<value>Log in with master password</value>
</data>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Log In with another device</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Log in initiated</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>A notification has been sent to your device.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Please make sure your vault is unlocked and the Fingerprint phrase matches on the other device.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Resend notification</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Need another option?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>View all log in options</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>This request is no longer valid</value>
</data>
</root>

View File

@@ -2490,4 +2490,25 @@ Voulez-vous basculer vers ce compte ?</value>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Connectez-vous avec un autre appareil</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Connexion initiée</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>Une notification a été envoyée à votre appareil.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Veuillez vous assurer que votre coffre est déverrouillé et que l'empreinte digitale est identique sur l'autre appareil.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Renvoyer la notification</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Besoin d'une autre option ?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>Voir toutes les options de connexion</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>Cette demande n'est plus valide</value>
</data>
</root>

View File

@@ -2488,9 +2488,30 @@ Do you want to switch to this account?</value>
<value>Not you?</value>
</data>
<data name="LogInWithMasterPassword" xml:space="preserve">
<value>Log In with master password</value>
<value>Log in with master password</value>
</data>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Log In with another device</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Log in initiated</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>A notification has been sent to your device.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Please make sure your vault is unlocked and the Fingerprint phrase matches on the other device.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Resend notification</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Need another option?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>View all log in options</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>This request is no longer valid</value>
</data>
</root>

View File

@@ -1763,7 +1763,7 @@ Scanning will happen automatically.</value>
<value>Syncing vault with pull down gesture.</value>
</data>
<data name="LogInSso" xml:space="preserve">
<value>Enterprise Single Sign-On</value>
<value>Enterprise single sign-on</value>
</data>
<data name="LogInSsoSummary" xml:space="preserve">
<value>Quickly log in using your organization's single sign-on portal. Please enter your organization's identifier to begin.</value>
@@ -2487,9 +2487,30 @@ Do you want to switch to this account?</value>
<value>Not you?</value>
</data>
<data name="LogInWithMasterPassword" xml:space="preserve">
<value>Log In with master password</value>
<value>Log in with master password</value>
</data>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Log In with another device</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Log in initiated</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>A notification has been sent to your device.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Please make sure your vault is unlocked and the Fingerprint phrase matches on the other device.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Resend notification</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Need another option?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>View all log in options</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>This request is no longer valid</value>
</data>
</root>

View File

@@ -657,7 +657,7 @@
<value>Razmotri da nam pomogneš dobrom recenzijom!</value>
</data>
<data name="RegeneratePassword" xml:space="preserve">
<value>Obnovi lozinku</value>
<value>Ponovno generiraj lozinku</value>
</data>
<data name="RetypeMasterPassword" xml:space="preserve">
<value>Ponovno upiši glavnu lozinku</value>
@@ -1901,7 +1901,7 @@
<value>Datoteka koju želiš poslati</value>
</data>
<data name="FileTypeIsSelected" xml:space="preserve">
<value>Odabran je datotečni Send.</value>
<value>Odabrana je vrsta datoteke.</value>
</data>
<data name="FileTypeIsNotSelected" xml:space="preserve">
<value>Vrsta datoteke nije odabrana, dodirnite za odabir.</value>
@@ -2062,7 +2062,7 @@
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="SendFilePremiumRequired" xml:space="preserve">
<value>Kod besplatnog računa moguće je dijeljenje samo teksta. Za slanje datoteka potrebno je Premium članstvo.</value>
<value>Kod besplatnog računa moguće je dijeljenje samo teksta. Za slanje datoteka potrebno je premium članstvo.</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="SendFileEmailVerificationRequired" xml:space="preserve">
@@ -2445,7 +2445,7 @@
<value>Koristi konfigurirani catch-all sandučić svoje domene.</value>
</data>
<data name="ForwardedEmailDescription" xml:space="preserve">
<value>Kreiraj pseudonim e-pošte s vanjskom uslugom prosljeđivanja.</value>
<value>Generiraj pseudonim e-pošte s vanjskom uslugom prosljeđivanja.</value>
</data>
<data name="Random" xml:space="preserve">
<value>Nasumično</value>
@@ -2488,4 +2488,25 @@
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Prijava drugim uređajem</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Prijava pokrenuta</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>Obavijest je poslana na tvoj uređaj.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Provjeri je li trezor otključan i slaže li se jedinstvena fraza s drugim uređajem.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Ponovno pošalji obavijest</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Trebaš drugu opciju?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>Pogledaj sve mogućnosti prijave</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>This request is no longer valid</value>
</data>
</root>

View File

@@ -1761,7 +1761,7 @@
<value>A széf szinkronizálása lehúzó művelettel.</value>
</data>
<data name="LogInSso" xml:space="preserve">
<value>Vállalati önálló bejelentkezés</value>
<value>Vállalati egyszeri bejelentkezés</value>
</data>
<data name="LogInSsoSummary" xml:space="preserve">
<value>Gyors bejelentkezés a szervezeti önálló bejelentkező portálba. A kezdéshez meg kell adni a szervezeti azonosítót.</value>
@@ -2489,4 +2489,25 @@ Szeretnénk átváltani erre a fiókra?</value>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Bejelentkezés más eszközzel</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>A bejelentkezés elindításra került.</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>A rendszer értesítést küldött az eszközre.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Ellenőrizzük, hogy a széf feloldásra került és az Ujjlenyomat kifejezés egyezik a másik eszközön levővel.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Értesítés újraküldése</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Másik opció szükséges?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>Összes bejelentkezési opció megtekintése</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>A kérés már nem érvényes.</value>
</data>
</root>

View File

@@ -2485,9 +2485,30 @@ Do you want to switch to this account?</value>
<value>Not you?</value>
</data>
<data name="LogInWithMasterPassword" xml:space="preserve">
<value>Log In with master password</value>
<value>Log in with master password</value>
</data>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Log In with another device</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Log in initiated</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>A notification has been sent to your device.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Please make sure your vault is unlocked and the Fingerprint phrase matches on the other device.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Resend notification</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Need another option?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>View all log in options</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>This request is no longer valid</value>
</data>
</root>

View File

@@ -1575,7 +1575,7 @@
<comment>'Nord' is the name of a specific color scheme. It should not be translated.</comment>
</data>
<data name="SolarizedDark" xml:space="preserve">
<value>Solarized Dark</value>
<value>Solarizzato scuro</value>
<comment>'Solarized Dark' is the name of a specific color scheme. It should not be translated.</comment>
</data>
<data name="AutofillBlockedUris" xml:space="preserve">
@@ -2468,26 +2468,47 @@ seleziona Aggiungi TOTP per salvare la chiave in modo sicuro</value>
<value>La richiesta di accesso è già scaduta.</value>
</data>
<data name="LoginAttemptFromXDoYouWantToSwitchToThisAccount" xml:space="preserve">
<value>Login attempt from:
<value>Tentativo di accesso da:
{0}
Do you want to switch to this account?</value>
Vuoi passare a questo account?</value>
</data>
<data name="NewAroundHere" xml:space="preserve">
<value>New around here?</value>
<value>Nuovo da queste parti?</value>
</data>
<data name="GetMasterPasswordwordHint" xml:space="preserve">
<value>Get master password hint</value>
<value>Ottieni l'indizio della password principale</value>
</data>
<data name="LoggingInAsX" xml:space="preserve">
<value>Logging in as {0}</value>
<value>Accesso come {0}</value>
</data>
<data name="NotYou" xml:space="preserve">
<value>Not you?</value>
<value>Non sei tu?</value>
</data>
<data name="LogInWithMasterPassword" xml:space="preserve">
<value>Log In with master password</value>
<value>Accedi con la password principale</value>
</data>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Log In with another device</value>
<value>Accedi con un altro dispositivo</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Login avviato</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>Una notifica è stata inviata al tuo dispositivo.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Assicurati che la tua cassaforte sia sbloccata e che la "frase impronta" corrisponda sull'altro dispositivo.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Invia nuova notifica</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Hai bisogno di un'altra opzione?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>Visualizza tutte le opzioni di accesso</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>La richiesta non è più valida</value>
</data>
</root>

View File

@@ -2490,4 +2490,25 @@
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>別のデバイスでログイン</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>ログイン開始</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>デバイスに通知を送信しました。</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>保管庫がロックされていることと、パスフレーズが他のデバイスと一致していることを確認してください。</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>通知を再送信する</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>別の選択肢が必要ですか?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>すべてのログインオプションを表示</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>このリクエストは無効になりました</value>
</data>
</root>

View File

@@ -1762,7 +1762,7 @@ Scanning will happen automatically.</value>
<value>Syncing vault with pull down gesture.</value>
</data>
<data name="LogInSso" xml:space="preserve">
<value>Enterprise Single Sign-On</value>
<value>Enterprise single sign-on</value>
</data>
<data name="LogInSsoSummary" xml:space="preserve">
<value>Quickly log in using your organization's single sign-on portal. Please enter your organization's identifier to begin.</value>
@@ -2486,9 +2486,30 @@ Do you want to switch to this account?</value>
<value>Not you?</value>
</data>
<data name="LogInWithMasterPassword" xml:space="preserve">
<value>Log In with master password</value>
<value>Log in with master password</value>
</data>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Log In with another device</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Log in initiated</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>A notification has been sent to your device.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Please make sure your vault is unlocked and the Fingerprint phrase matches on the other device.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Resend notification</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Need another option?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>View all log in options</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>This request is no longer valid</value>
</data>
</root>

View File

@@ -2486,9 +2486,30 @@ Do you want to switch to this account?</value>
<value>Not you?</value>
</data>
<data name="LogInWithMasterPassword" xml:space="preserve">
<value>Log In with master password</value>
<value>Log in with master password</value>
</data>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Log In with another device</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Log in initiated</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>A notification has been sent to your device.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Please make sure your vault is unlocked and the Fingerprint phrase matches on the other device.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Resend notification</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Need another option?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>View all log in options</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>This request is no longer valid</value>
</data>
</root>

View File

@@ -2485,9 +2485,30 @@ Do you want to switch to this account?</value>
<value>Not you?</value>
</data>
<data name="LogInWithMasterPassword" xml:space="preserve">
<value>Log In with master password</value>
<value>Log in with master password</value>
</data>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Log In with another device</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Log in initiated</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>A notification has been sent to your device.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Please make sure your vault is unlocked and the Fingerprint phrase matches on the other device.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Resend notification</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Need another option?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>View all log in options</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>This request is no longer valid</value>
</data>
</root>

View File

@@ -1762,7 +1762,7 @@ Scanning will happen automatically.</value>
<value>Syncing vault with pull down gesture.</value>
</data>
<data name="LogInSso" xml:space="preserve">
<value>Enterprise Single Sign-On</value>
<value>Enterprise single sign-on</value>
</data>
<data name="LogInSsoSummary" xml:space="preserve">
<value>Quickly log in using your organization's single sign-on portal. Please enter your organization's identifier to begin.</value>
@@ -2486,9 +2486,30 @@ Do you want to switch to this account?</value>
<value>Not you?</value>
</data>
<data name="LogInWithMasterPassword" xml:space="preserve">
<value>Log In with master password</value>
<value>Log in with master password</value>
</data>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Log In with another device</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Log in initiated</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>A notification has been sent to your device.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Please make sure your vault is unlocked and the Fingerprint phrase matches on the other device.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Resend notification</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Need another option?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>View all log in options</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>This request is no longer valid</value>
</data>
</root>

View File

@@ -2490,4 +2490,25 @@ Vai pārslēgties uz šo kontu?</value>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Pierakstīties ar citu ierīci</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Uzsākta pierakstīšanās</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>Uz ierīci ir nosūtīts paziņojums.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Jāpārliecinās, ka glabātava ir atslēgta un atpazīšanas vārdkopa ir tāda pati arī citā ierīcē.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Atkārtoti nosūtīt paziņojumu</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Nepieciešama cita iespēja?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>Apskatīt visas pierakstīšanās iespējas</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>Šis pieprasījums vairs nav derīgs</value>
</data>
</root>

View File

@@ -2485,9 +2485,30 @@ Do you want to switch to this account?</value>
<value>Not you?</value>
</data>
<data name="LogInWithMasterPassword" xml:space="preserve">
<value>Log In with master password</value>
<value>Log in with master password</value>
</data>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Log In with another device</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Log in initiated</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>A notification has been sent to your device.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Please make sure your vault is unlocked and the Fingerprint phrase matches on the other device.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Resend notification</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Need another option?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>View all log in options</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>This request is no longer valid</value>
</data>
</root>

View File

@@ -1576,7 +1576,7 @@ Skanning skjer automatisk.</value>
<comment>'Nord' is the name of a specific color scheme. It should not be translated.</comment>
</data>
<data name="SolarizedDark" xml:space="preserve">
<value>Solarized Dark</value>
<value>Solarisert mørk</value>
<comment>'Solarized Dark' is the name of a specific color scheme. It should not be translated.</comment>
</data>
<data name="AutofillBlockedUris" xml:space="preserve">
@@ -2469,26 +2469,47 @@ velg Legg til TOTP for å lagre nøkkelen sikkert</value>
<value>Innloggingsforespørselen har allerede utløpt.</value>
</data>
<data name="LoginAttemptFromXDoYouWantToSwitchToThisAccount" xml:space="preserve">
<value>Login attempt from:
<value>Innloggingsforsøk:
{0}
Do you want to switch to this account?</value>
Vil du bytte til denne kontoen?</value>
</data>
<data name="NewAroundHere" xml:space="preserve">
<value>New around here?</value>
<value>Nytt rundt her?</value>
</data>
<data name="GetMasterPasswordwordHint" xml:space="preserve">
<value>Get master password hint</value>
<value>Få et hint om superpassordet</value>
</data>
<data name="LoggingInAsX" xml:space="preserve">
<value>Logging in as {0}</value>
<value>Logger inn som {0}</value>
</data>
<data name="NotYou" xml:space="preserve">
<value>Not you?</value>
<value>Ikke du?</value>
</data>
<data name="LogInWithMasterPassword" xml:space="preserve">
<value>Log In with master password</value>
<value>Logg inn med hovedpassord</value>
</data>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Log In with another device</value>
<value>Logg inn med en annen enhet</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Log in initiated</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>A notification has been sent to your device.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Please make sure your vault is unlocked and the Fingerprint phrase matches on the other device.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Resend notification</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Need another option?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>View all log in options</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>This request is no longer valid</value>
</data>
</root>

View File

@@ -2490,4 +2490,25 @@ Wilt u naar dit account wisselen?</value>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Inloggen met een ander apparaat</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Log in initiated</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>A notification has been sent to your device.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Please make sure your vault is unlocked and the Fingerprint phrase matches on the other device.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Resend notification</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Need another option?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>View all log in options</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>Dit verzoek is niet langer geldig</value>
</data>
</root>

View File

@@ -1762,7 +1762,7 @@ Scanning will happen automatically.</value>
<value>Syncing vault with pull down gesture.</value>
</data>
<data name="LogInSso" xml:space="preserve">
<value>Enterprise Single Sign-On</value>
<value>Enterprise single sign-on</value>
</data>
<data name="LogInSsoSummary" xml:space="preserve">
<value>Quickly log in using your organization's single sign-on portal. Please enter your organization's identifier to begin.</value>
@@ -2486,9 +2486,30 @@ Do you want to switch to this account?</value>
<value>Not you?</value>
</data>
<data name="LogInWithMasterPassword" xml:space="preserve">
<value>Log In with master password</value>
<value>Log in with master password</value>
</data>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Log In with another device</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Log in initiated</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>A notification has been sent to your device.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Please make sure your vault is unlocked and the Fingerprint phrase matches on the other device.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Resend notification</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Need another option?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>View all log in options</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>This request is no longer valid</value>
</data>
</root>

View File

@@ -2490,4 +2490,25 @@ Czy chcesz przełączyć się na to konto?</value>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Logowanie innym urządzeniem</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Logowanie rozpoczęte</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>Powiadomienie zostało wysłane na urządzenie.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Upewnij się, że sejf jest odblokowany, a unikalny identyfikator konta pasuje do drugiego urządzenia.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Wyślij ponownie powiadomienie</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Potrzebujesz innego sposobu?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>Zobacz wszystkie sposoby logowania</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>Ta prośba nie jest już ważna</value>
</data>
</root>

View File

@@ -2491,4 +2491,25 @@ Você deseja mudar para esta conta?</value>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Entrar com outro dispositivo</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Login iniciado</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>Uma notificação foi enviada para seu dispositivo.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Por favor, certifique-se de que o seu cofre esteja desbloqueado e a frase de identificação corresponda ao outro dispositivo.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Reenviar notificação</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Precisa de outra opção?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>Ver todas as opções de login</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>Este pedido não é mais válido</value>
</data>
</root>

View File

@@ -2490,4 +2490,25 @@ Deseja mudar para esta conta?</value>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Iniciar sessão com outro dispositivo</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Log in initiated</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>A notification has been sent to your device.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Please make sure your vault is unlocked and the Fingerprint phrase matches on the other device.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Resend notification</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Need another option?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>View all log in options</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>Este pedido já não é válido</value>
</data>
</root>

View File

@@ -1762,7 +1762,7 @@ Scanning will happen automatically.</value>
<value>Syncing vault with pull down gesture.</value>
</data>
<data name="LogInSso" xml:space="preserve">
<value>Enterprise Single Sign-On</value>
<value>Enterprise single sign-on</value>
</data>
<data name="LogInSsoSummary" xml:space="preserve">
<value>Quickly log in using your organization's single sign-on portal. Please enter your organization's identifier to begin.</value>
@@ -2486,9 +2486,30 @@ Do you want to switch to this account?</value>
<value>Not you?</value>
</data>
<data name="LogInWithMasterPassword" xml:space="preserve">
<value>Log In with master password</value>
<value>Log in with master password</value>
</data>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Log In with another device</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Log in initiated</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>A notification has been sent to your device.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Please make sure your vault is unlocked and the Fingerprint phrase matches on the other device.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Resend notification</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Need another option?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>View all log in options</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>This request is no longer valid</value>
</data>
</root>

View File

@@ -2490,4 +2490,25 @@ Doriți să comutați la acest cont?</value>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Autentificați-vă cu un alt dispozitiv</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Log in initiated</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>A notification has been sent to your device.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Please make sure your vault is unlocked and the Fingerprint phrase matches on the other device.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Resend notification</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Need another option?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>View all log in options</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>This request is no longer valid</value>
</data>
</root>

View File

@@ -705,10 +705,10 @@
<comment>What Apple calls their fingerprint reader.</comment>
</data>
<data name="TwoStepLogin" xml:space="preserve">
<value>Двухфакторная аутентификация</value>
<value>Двухэтапная аутентификация</value>
</data>
<data name="TwoStepLoginConfirmation" xml:space="preserve">
<value>Двухэтапная аутентификация повышает защиту вашего аккаунта, требуя подтверждения входа на другом устройстве, например, с помощью ключа безопасности, приложения-аутентификатора, SMS, телефонного звонка или email. Двухфакторная аутентификация включается на bitwarden.com. Перейти на сайт сейчас?</value>
<value>Двухэтапная аутентификация делает аккаунт более защищенным, поскольку требуется подтверждение входа при помощи другого устройства, например, ключа безопасности, приложения-аутентификатора, SMS, телефонного звонка или электронной почты. Двухэтапная аутентификация включается на bitwarden.com. Перейти на сайт сейчас?</value>
</data>
<data name="UnlockWith" xml:space="preserve">
<value>Разблокировка {0}</value>
@@ -831,7 +831,7 @@
<comment>For 2FA whenever there are no available providers on this device.</comment>
</data>
<data name="NoTwoStepAvailable" xml:space="preserve">
<value>Для этой учетной записи включена двухфакторная аутентификация, однако ни один из настроенных вариантов аутентификации не поддерживается на этом устройстве. Используйте поддерживаемое устройство и/или добавьте другие варианты, которые поддерживаются на большинстве устройств (например, приложение-аутентификатор).</value>
<value>У этой учетной записи включена двухэтапная аутентификация, однако ни один из настроенных вариантов не поддерживается на этом устройстве. Используйте поддерживаемое устройство и/или добавьте другие варианты, которые поддерживаются на большинстве устройств (например, приложение-аутентификатор).</value>
</data>
<data name="RecoveryCodeTitle" xml:space="preserve">
<value>Код восстановления</value>
@@ -846,10 +846,10 @@
<comment>For 2FA</comment>
</data>
<data name="TwoStepLoginOptions" xml:space="preserve">
<value>Настройки двухфакторной аутентификации</value>
<value>Настройки двухэтапной аутентификации</value>
</data>
<data name="UseAnotherTwoStepMethod" xml:space="preserve">
<value>Использовать другой метод двухфакторной аутентификации</value>
<value>Использовать другой метод двухэтапной аутентификации</value>
</data>
<data name="VerificationEmailNotSent" xml:space="preserve">
<value>Не удалось отправить письмо подтверждения. Повторить.</value>
@@ -919,7 +919,7 @@
<value>Если к вашему логину прикреплен ключ аутентификации, то код подтверждения TOTP будет скопирован при автозаполнении логина.</value>
</data>
<data name="CopyTotpAutomatically" xml:space="preserve">
<value>Копировать TOTP автоматически</value>
<value>Скопировать TOTP автоматически</value>
</data>
<data name="PremiumRequired" xml:space="preserve">
<value>Для использования этой функции требуется Премиум.</value>
@@ -1471,7 +1471,7 @@
<value>Экспортировать хранилище</value>
</data>
<data name="LockNow" xml:space="preserve">
<value>Заблокировать сейчас</value>
<value>Заблокировать</value>
</data>
<data name="PIN" xml:space="preserve">
<value>PIN-код</value>
@@ -1614,10 +1614,10 @@
<value>Общие</value>
</data>
<data name="ToggleVisibility" xml:space="preserve">
<value>Изменить видимость</value>
<value>Вкл/выкл видимость</value>
</data>
<data name="LoginExpired" xml:space="preserve">
<value>Истек срок действия вашей сессии.</value>
<value>Истек срок действия вашего сеанса.</value>
</data>
<data name="BiometricsDirection" xml:space="preserve">
<value>Биометрическая верификация.</value>
@@ -1635,7 +1635,7 @@
<value>3. На экране настроек приложений Android для Bitwarden перейдите в раздел "Отображение поверх других приложений" (в разделе "Дополнительно") и коснитесь переключателя, чтобы включить поддержку наложения.</value>
</data>
<data name="OverlayPermission" xml:space="preserve">
<value>Разрешения</value>
<value>Разрешение</value>
</data>
<data name="BitwardenAutofillServiceOpenOverlayPermissionSettings" xml:space="preserve">
<value>Открыть настройки разрешения наложения</value>
@@ -1762,7 +1762,7 @@
<value>Синхронизация хранилища жестом смахивания вниз.</value>
</data>
<data name="LogInSso" xml:space="preserve">
<value>Единая корпоративная авторизация (SSO)</value>
<value>Единая корпоративная авторизация</value>
</data>
<data name="LogInSsoSummary" xml:space="preserve">
<value>Авторизуйтесь при помощи единого корпоративного портала. Чтобы начать, введите идентификатор вашей организации.</value>
@@ -2092,7 +2092,7 @@
<value>Обновить мастер-пароль</value>
</data>
<data name="UpdateMasterPasswordWarning" xml:space="preserve">
<value>Мастер-пароль недавно был изменен администратором вашей организации. Чтобы получить доступ к хранилищу, вы должны обновить мастер-пароль сейчас. В результате текущая сессия будет завершена, потребуется повторный вход. Активные сессии на других устройствах могут оставаться активными в течение одного часа.</value>
<value>Мастер-пароль недавно был изменен администратором вашей организации. Чтобы получить доступ к хранилищу, вы должны обновить мастер-пароль сейчас. В результате текущий сеанс будет завершен, потребуется повторный вход. Активные сеансы на других устройствах могут оставаться активными в течение одного часа.</value>
</data>
<data name="UpdatingPassword" xml:space="preserve">
<value>Обновление пароля</value>
@@ -2490,4 +2490,25 @@
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Войти с другого устройства</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Вход инициирован</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>На ваше устройство отправлено уведомление.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Убедитесь, что ваше хранилище разблокировано, а фраза отпечатка соответствует другому устройству.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Отправить уведомление повторно</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Нужен другой вариант?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>Посмотреть все варианты авторизации</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>Этот запрос больше не действителен</value>
</data>
</root>

View File

@@ -1762,7 +1762,7 @@ Scanning will happen automatically.</value>
<value>Syncing vault with pull down gesture.</value>
</data>
<data name="LogInSso" xml:space="preserve">
<value>Enterprise Single Sign-On</value>
<value>Enterprise single sign-on</value>
</data>
<data name="LogInSsoSummary" xml:space="preserve">
<value>Quickly log in using your organization's single sign-on portal. Please enter your organization's identifier to begin.</value>
@@ -2486,9 +2486,30 @@ Do you want to switch to this account?</value>
<value>Not you?</value>
</data>
<data name="LogInWithMasterPassword" xml:space="preserve">
<value>Log In with master password</value>
<value>Log in with master password</value>
</data>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Log In with another device</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Log in initiated</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>A notification has been sent to your device.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Please make sure your vault is unlocked and the Fingerprint phrase matches on the other device.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Resend notification</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Need another option?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>View all log in options</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>This request is no longer valid</value>
</data>
</root>

View File

@@ -1762,7 +1762,7 @@ Skenovanie prebehne automaticky.</value>
<value>Synchronizácia trezora potiahnutím nadol</value>
</data>
<data name="LogInSso" xml:space="preserve">
<value>Prihlásenie cez prihlasovací formulár spoločnosti (SSO)</value>
<value>Jednotné prihlásenie pre podniky (SSO)</value>
</data>
<data name="LogInSsoSummary" xml:space="preserve">
<value>Prihláste sa prostredníctvom prihlasovacieho portálu (SSO) vašej organizácie. Najskôr zadajte identifikátor vašej organizácie.</value>
@@ -2490,4 +2490,25 @@ Chcete prepnúť na toto konto?</value>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Prihlásenie pomocou iného zariadenia</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Iniciované prihlásenie</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>Do vášho zariadenia bolo odoslané upozornenie.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Skontrolujte, či je trezor odomknutý, a či sa fráza odtlačku prsta zhoduje na druhom zariadení.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Znova odoslať upozornenie</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Potrebujete inú možnosť?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>Zobraziť všetky možnosti prihlásenia</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>Táto požiadavka už nie je platná</value>
</data>
</root>

View File

@@ -1762,7 +1762,7 @@ Scanning will happen automatically.</value>
<value>Syncing vault with pull down gesture.</value>
</data>
<data name="LogInSso" xml:space="preserve">
<value>Enterprise Single Sign-On</value>
<value>Enterprise single sign-on</value>
</data>
<data name="LogInSsoSummary" xml:space="preserve">
<value>Quickly log in using your organization's single sign-on portal. Please enter your organization's identifier to begin.</value>
@@ -2486,9 +2486,30 @@ Do you want to switch to this account?</value>
<value>Not you?</value>
</data>
<data name="LogInWithMasterPassword" xml:space="preserve">
<value>Log In with master password</value>
<value>Log in with master password</value>
</data>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Log In with another device</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Log in initiated</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>A notification has been sent to your device.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Please make sure your vault is unlocked and the Fingerprint phrase matches on the other device.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Resend notification</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Need another option?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>View all log in options</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>This request is no longer valid</value>
</data>
</root>

View File

@@ -1576,7 +1576,7 @@
<comment>'Nord' is the name of a specific color scheme. It should not be translated.</comment>
</data>
<data name="SolarizedDark" xml:space="preserve">
<value>Solarized Dark</value>
<value>Solarized црно</value>
<comment>'Solarized Dark' is the name of a specific color scheme. It should not be translated.</comment>
</data>
<data name="AutofillBlockedUris" xml:space="preserve">
@@ -2395,7 +2395,7 @@
<value>„Ухвати све“ е-порука</value>
</data>
<data name="ForwardedEmailAlias" xml:space="preserve">
<value>Forwarded email alias</value>
<value>Прослеђен псеудоним е-поште</value>
</data>
<data name="RandomWord" xml:space="preserve">
<value>Случајна реч</value>
@@ -2443,10 +2443,10 @@
<value>Непозната {0} грешка.</value>
</data>
<data name="PlusAddressedEmailDescription" xml:space="preserve">
<value>Use your email provider's subaddress capabilities</value>
<value>Користите могућности подадресе вашег добављача е-поште</value>
</data>
<data name="CatchAllEmailDescription" xml:space="preserve">
<value>Use your domain's configured catch-all inbox.</value>
<value>Користите подешено catch-all пријемно сандуче вашег домена.</value>
</data>
<data name="ForwardedEmailDescription" xml:space="preserve">
<value>Генеришите псеудоним е-поште помоћу екстерне услуге прослеђивања.</value>
@@ -2455,10 +2455,10 @@
<value>Случајно</value>
</data>
<data name="AccessibilityServiceDisclosure" xml:space="preserve">
<value>Accessibility Service Disclosure</value>
<value>Откривање услуге приступачности</value>
</data>
<data name="AccessibilityDisclosureText" xml:space="preserve">
<value>Bitwarden uses the Accessibility Service to search for login fields in apps and websites, then establish the appropriate field IDs for entering a username &amp; password when a match for the app or site is found. We do not store any of the information presented to us by the service, nor do we make any attempt to control any on-screen elements beyond text entry of credentials.</value>
<value>Битварден користи услугу приступачности да тражи поља за пријаву у апликацијама и веб локацијама, а затим успоставља одговарајуће ИД-ове поља за уношење корисничког имена и лозинке када се пронађе подударање за апликацију или сајт. Не чувамо ниједну информацију коју нам пружа услуга, нити покушавамо да контролишемо било које елементе на екрану осим уноса текста акредитива.</value>
</data>
<data name="Accept" xml:space="preserve">
<value>Прихвати</value>
@@ -2475,21 +2475,42 @@
Да ли желите да пређете на овај налог?</value>
</data>
<data name="NewAroundHere" xml:space="preserve">
<value>New around here?</value>
<value>Нов овде?</value>
</data>
<data name="GetMasterPasswordwordHint" xml:space="preserve">
<value>Get master password hint</value>
<value>Добити савет за Главну Лозинку</value>
</data>
<data name="LoggingInAsX" xml:space="preserve">
<value>Logging in as {0}</value>
<value>Пријављивање као {0}</value>
</data>
<data name="NotYou" xml:space="preserve">
<value>Not you?</value>
<value>Не ти?</value>
</data>
<data name="LogInWithMasterPassword" xml:space="preserve">
<value>Log In with master password</value>
<value>Пријавите се са главном лозинком</value>
</data>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Log In with another device</value>
<value>Пријавите се са другим уређајем</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Пријава је покренута</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>Обавештење је послато на ваш уређај.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Уверите се да је ваш сеф откључан и да се фраза отиска прста подудара на другом уређају.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Поново послати обавештење</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Треба Вам друга опције?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>Погледајте сав извештај у опције</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>Овај захтев више не важи</value>
</data>
</root>

View File

@@ -2492,4 +2492,25 @@ Vill du byta till detta konto?</value>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Logga in med en annan enhet</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Inloggning påbörjad</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>En avisering har skickats till din enhet.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Se till att ditt valv är upplåst och att fingeravtrycksfrasen matchar på den andra enheten.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Skicka avisering igen</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Behöver du fler alternativ?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>Visa alla inloggningsalternativ</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>This request is no longer valid</value>
</data>
</root>

View File

@@ -2486,9 +2486,30 @@ Do you want to switch to this account?</value>
<value>Not you?</value>
</data>
<data name="LogInWithMasterPassword" xml:space="preserve">
<value>Log In with master password</value>
<value>Log in with master password</value>
</data>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Log In with another device</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Log in initiated</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>A notification has been sent to your device.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Please make sure your vault is unlocked and the Fingerprint phrase matches on the other device.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Resend notification</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Need another option?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>View all log in options</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>This request is no longer valid</value>
</data>
</root>

View File

@@ -1769,7 +1769,7 @@ Scanning will happen automatically.</value>
<value>Syncing vault with pull down gesture.</value>
</data>
<data name="LogInSso" xml:space="preserve">
<value>Enterprise Single Sign-On</value>
<value>Enterprise single sign-on</value>
</data>
<data name="LogInSsoSummary" xml:space="preserve">
<value>Quickly log in using your organization's single sign-on portal. Please enter your organization's identifier to begin.</value>
@@ -2493,9 +2493,30 @@ Do you want to switch to this account?</value>
<value>Not you?</value>
</data>
<data name="LogInWithMasterPassword" xml:space="preserve">
<value>Log In with master password</value>
<value>Log in with master password</value>
</data>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Log In with another device</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Log in initiated</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>A notification has been sent to your device.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Please make sure your vault is unlocked and the Fingerprint phrase matches on the other device.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Resend notification</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Need another option?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>View all log in options</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>This request is no longer valid</value>
</data>
</root>

View File

@@ -2489,4 +2489,25 @@ Bu hesaba geçmek ister misiniz?</value>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Başka bir cihazla giriş yap</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Giriş başlatıldı</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>Cihazınıza bir bildirim gönderildi.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Lütfen kasanızın kilidinin açık olduğundan ve parmak izi ifadesinin diğer cihazla eşleştiğinden emin olun.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Bildirimi yeniden gönder</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Başka bir seçeneğe mi ihtiyacınız var?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>Tüm giriş seçeneklerini gör</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>Bu istek artık geçerli değil</value>
</data>
</root>

View File

@@ -708,7 +708,7 @@
<value>Двоетапна перевірка</value>
</data>
<data name="TwoStepLoginConfirmation" xml:space="preserve">
<value>Двоетапна перевірка робить ваш обліковий запис більш захищеним, вимагаючи підтвердження входу з використанням іншого пристрою, наприклад, за допомогою коду безпеки, програми авторизації, SMS, телефонного виклику, або е-пошти. Ви можете увімкнути двоетапну перевірку в сховищі на bitwarden.com. Хочете перейти на вебсайт зараз?</value>
<value>Двоетапна перевірка дає змогу надійніше захистити ваш обліковий запис, вимагаючи підтвердження входу з використанням іншого пристрою, наприклад, за допомогою коду безпеки, програми авторизації, SMS, телефонного виклику, або е-пошти. Ви можете налаштувати двоетапну перевірку в сховищі на bitwarden.com. Хочете перейти на вебсайт зараз?</value>
</data>
<data name="UnlockWith" xml:space="preserve">
<value>Розблокування з {0}</value>
@@ -2490,4 +2490,25 @@
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Увійти з іншого пристрою</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Ініційовано вхід</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>Сповіщення було надіслано на ваш пристрій.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Переконайтеся, що ваше сховище розблоковане, а фраза відбитка збігається з іншим пристроєм.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Надіслати сповіщення ще раз</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Потрібен інший варіант?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>Переглянути всі варіанти входу</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>Цей запит більше недійсний</value>
</data>
</root>

View File

@@ -2485,9 +2485,30 @@ Do you want to switch to this account?</value>
<value>Not you?</value>
</data>
<data name="LogInWithMasterPassword" xml:space="preserve">
<value>Log In with master password</value>
<value>Log in with master password</value>
</data>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Log In with another device</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Log in initiated</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>A notification has been sent to your device.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Please make sure your vault is unlocked and the Fingerprint phrase matches on the other device.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Resend notification</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Need another option?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>View all log in options</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>This request is no longer valid</value>
</data>
</root>

View File

@@ -2490,4 +2490,25 @@
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>使用其他设备登录</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>登录已发起</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>通知已发送到您的设备。</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>请确保您的密码库已解锁,并且指纹短语与其他设备上的相匹配。</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>重新发送通知</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>需要其他选项吗?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>查看所有登录选项</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>请求已失效</value>
</data>
</root>

View File

@@ -1762,7 +1762,7 @@
<value>使用下拉手勢同步密碼庫。</value>
</data>
<data name="LogInSso" xml:space="preserve">
<value>企業單一登入</value>
<value>企業單一登入SSO</value>
</data>
<data name="LogInSsoSummary" xml:space="preserve">
<value>若要使用組織的單一登入入口快速登入。請先輸入您的組織識別碼。</value>
@@ -2490,4 +2490,25 @@
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>使用其他裝置登入</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>登入已發起</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>通知已傳送至您的裝置。</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Please make sure your vault is unlocked and the Fingerprint phrase matches on the other device.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>重新傳送通知</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Need another option?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>檢視所有登入選項</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>此請求已失效</value>
</data>
</root>

View File

@@ -228,7 +228,8 @@ namespace Bit.App.Services
if (data is PasswordlessNotificationData passwordlessNotificationData)
{
var notificationUserId = await _stateService.Value.GetUserIdAsync(passwordlessNotificationData.UserEmail);
if (notificationUserId != null)
var notificationSaved = await _stateService.Value.GetPasswordlessLoginNotificationAsync();
if (notificationUserId != null && notificationSaved != null)
{
await _stateService.Value.SetActiveUserAsync(notificationUserId);
_messagingService.Value.Send(AccountsManagerMessageCommands.SWITCHED_ACCOUNT);

View File

@@ -7,6 +7,7 @@ using Bit.Core.Abstractions;
using Bit.Core.Enums;
using Bit.Core.Models.Domain;
using Bit.Core.Utilities;
using Xamarin.Essentials;
using Xamarin.Forms;
namespace Bit.App.Utilities.AccountManagement
@@ -103,11 +104,12 @@ namespace Bit.App.Utilities.AccountManagement
// var orgIdentifier = await _stateService.GetOrgIdentifierAsync();
var email = await _stateService.GetEmailAsync();
_accountsManagerHost.Navigate(NavigationTarget.Login, new LoginNavigationParams(email));
await _stateService.SetRememberedEmailAsync(email);
_accountsManagerHost.Navigate(NavigationTarget.HomeLogin, new HomeNavigationParams(true));
}
else
{
_accountsManagerHost.Navigate(NavigationTarget.HomeLogin);
_accountsManagerHost.Navigate(NavigationTarget.HomeLogin, new HomeNavigationParams(false));
}
}
}
@@ -183,7 +185,7 @@ namespace Bit.App.Utilities.AccountManagement
await Device.InvokeOnMainThreadAsync(() =>
{
Options.HideAccountSwitcher = false;
_accountsManagerHost.Navigate(NavigationTarget.HomeLogin);
_accountsManagerHost.Navigate(NavigationTarget.HomeLogin, new HomeNavigationParams(false));
});
}
@@ -218,5 +220,17 @@ namespace Bit.App.Utilities.AccountManagement
_messagingService.Send(AccountsManagerMessageCommands.ACCOUNT_SWITCH_COMPLETED);
});
}
public async Task PromptToSwitchToExistingAccountAsync(string userId)
{
var switchToAccount = await _platformUtilsService.ShowDialogAsync(
AppResources.SwitchToAlreadyAddedAccountConfirmation,
AppResources.AccountAlreadyAdded, AppResources.Yes, AppResources.Cancel);
if (switchToAccount)
{
await _stateService.SetActiveUserAsync(userId);
_messagingService.Send("switchedAccount");
}
}
}
}

View File

@@ -0,0 +1,14 @@
using Bit.App.Abstractions;
namespace Bit.App.Utilities.AccountManagement
{
public class HomeNavigationParams : INavigationParams
{
public HomeNavigationParams(bool shouldCheckRememberEmail)
{
ShouldCheckRememberEmail = shouldCheckRememberEmail;
}
public bool ShouldCheckRememberEmail { get; }
}
}

View File

@@ -83,8 +83,11 @@ namespace Bit.Core.Abstractions
Task<SendResponse> PutSendAsync(string id, SendRequest request);
Task<SendResponse> PutSendRemovePasswordAsync(string id);
Task DeleteSendAsync(string id);
Task<List<PasswordlessLoginResponse>> GetAuthRequestAsync();
Task<PasswordlessLoginResponse> GetAuthRequestAsync(string id);
Task<PasswordlessLoginResponse> GetAuthResponseAsync(string id, string accessCode);
Task<PasswordlessLoginResponse> PutAuthRequestAsync(string id, string key, string masterPasswordHash, string deviceIdentifier, bool requestApproved);
Task<PasswordlessLoginResponse> PostCreateRequestAsync(PasswordlessCreateLoginRequest passwordlessCreateLoginRequest);
Task<string> GetUsernameFromAsync(ForwardedEmailServiceType service, UsernameGeneratorConfig config);
Task<bool> GetKnownDeviceAsync(string email, string deviceIdentifier);
}

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Threading.Tasks;
using Bit.Core.Enums;
using Bit.Core.Models.Domain;
using Bit.Core.Models.Request;
using Bit.Core.Models.Response;
namespace Bit.Core.Abstractions
@@ -26,9 +27,13 @@ namespace Bit.Core.Abstractions
Task<AuthResult> LogInSsoAsync(string code, string codeVerifier, string redirectUrl, string orgId);
Task<AuthResult> LogInCompleteAsync(string email, string masterPassword, TwoFactorProviderType twoFactorProvider, string twoFactorToken, bool? remember = null);
Task<AuthResult> LogInTwoFactorAsync(TwoFactorProviderType twoFactorProvider, string twoFactorToken, string captchaToken, bool? remember = null);
Task<AuthResult> LogInPasswordlessAsync(string email, string accessCode, string authRequestId, byte[] decryptionKey, string userKeyCiphered, string localHashedPasswordCiphered);
Task<List<PasswordlessLoginResponse>> GetPasswordlessLoginRequestsAsync();
Task<PasswordlessLoginResponse> GetPasswordlessLoginRequestByIdAsync(string id);
Task<PasswordlessLoginResponse> GetPasswordlessLoginResponseAsync(string id, string accessCode);
Task<PasswordlessLoginResponse> PasswordlessLoginAsync(string id, string pubKey, bool requestApproved);
Task<PasswordlessLoginResponse> PasswordlessCreateLoginRequestAsync(string email);
void LogOut(Action callback);
void Init();

View File

@@ -46,6 +46,7 @@ namespace Bit.Core.Abstractions
Task<int> RandomNumberAsync(int min, int max);
Task<Tuple<SymmetricCryptoKey, EncString>> RemakeEncKeyAsync(SymmetricCryptoKey key);
Task<EncString> RsaEncryptAsync(byte[] data, byte[] publicKey = null);
Task<byte[]> RsaDecryptAsync(string encValue, byte[] privateKey = null);
Task SetEncKeyAsync(string encKey);
Task SetEncPrivateKeyAsync(string encPrivateKey);
Task SetKeyAsync(SymmetricCryptoKey key);

View File

@@ -13,6 +13,7 @@ namespace Bit.Core.Abstractions
{
List<AccountView> AccountViews { get; }
Task<string> GetActiveUserIdAsync();
Task<string> GetActiveUserEmailAsync();
Task<bool> IsActiveAccountAsync(string userId = null);
Task SetActiveUserAsync(string userId);
Task CheckExtensionActiveUserAndSwitchIfNeededAsync();

View File

@@ -14,5 +14,7 @@ namespace Bit.Core.Abstractions
Task<bool> SyncDeleteFolderAsync(SyncFolderNotification notification);
Task<bool> SyncUpsertCipherAsync(SyncCipherNotification notification, bool isEdit);
Task<bool> SyncUpsertFolderAsync(SyncFolderNotification notification, bool isEdit);
// Passwordless code will be moved to an independent service in future techdept
Task SyncPasswordlessLoginRequestsAsync();
}
}

View File

@@ -0,0 +1,34 @@
using System;
namespace Bit.Core.Models.Request
{
public class PasswordlessCreateLoginRequest
{
public PasswordlessCreateLoginRequest(string email, string publicKey, string deviceIdentifier, string accessCode, AuthRequestType? type, string fingerprintPhrase)
{
Email = email ?? throw new ArgumentNullException(nameof(email));
PublicKey = publicKey ?? throw new ArgumentNullException(nameof(publicKey));
DeviceIdentifier = deviceIdentifier ?? throw new ArgumentNullException(nameof(deviceIdentifier));
AccessCode = accessCode ?? throw new ArgumentNullException(nameof(accessCode));
Type = type;
FingerprintPhrase = fingerprintPhrase ?? throw new ArgumentNullException(nameof(fingerprintPhrase));
}
public string Email { get; set; }
public string PublicKey { get; set; }
public string DeviceIdentifier { get; set; }
public string AccessCode { get; set; }
public AuthRequestType? Type { get; set; }
public string FingerprintPhrase { get; set; }
}
public enum AuthRequestType : byte
{
AuthenticateAndUnlock = 0,
Unlock = 1
}
}

View File

@@ -15,13 +15,14 @@ namespace Bit.Core.Models.Request
public string CodeVerifier { get; set; }
public string RedirectUri { get; set; }
public string Token { get; set; }
public string AuthRequestId { get; set; }
public TwoFactorProviderType? Provider { get; set; }
public bool? Remember { get; set; }
public string CaptchaToken { get; set; }
public DeviceRequest Device { get; set; }
public TokenRequest(string[] credentials, string[] codes, TwoFactorProviderType? provider, string token,
bool? remember, string captchaToken, DeviceRequest device = null)
bool? remember, string captchaToken, DeviceRequest device = null, string authRequestId = null)
{
if (credentials != null && credentials.Length > 1)
{
@@ -39,6 +40,7 @@ namespace Bit.Core.Models.Request
Remember = remember;
Device = device;
CaptchaToken = captchaToken;
AuthRequestId = authRequestId;
}
public Dictionary<string, string> ToIdentityToken(string clientId)
@@ -67,6 +69,11 @@ namespace Bit.Core.Models.Request
throw new Exception("must provide credentials or codes");
}
if (AuthRequestId != null)
{
obj.Add("authRequest", AuthRequestId);
}
if (Device != null)
{
obj.Add("deviceType", ((int)Device.Type).ToString());

View File

@@ -1,5 +1,7 @@
using System;
using System.Collections.Generic;
using Bit.Core.Enums;
using Bit.Core.Models.Data;
namespace Bit.Core.Models.Response
{
@@ -13,7 +15,19 @@ namespace Bit.Core.Models.Response
public string Key { get; set; }
public string MasterPasswordHash { get; set; }
public DateTime CreationDate { get; set; }
public bool RequestApproved { get; set; }
public DateTime? ResponseDate { get; set; }
public bool? RequestApproved { get; set; }
public string Origin { get; set; }
public string RequestAccessCode { get; set; }
public Tuple<byte[], byte[]> RequestKeyPair { get; set; }
public bool IsAnswered => RequestApproved != null && ResponseDate != null;
public bool IsExpired => CreationDate.ToUniversalTime().AddMinutes(Constants.PasswordlessNotificationTimeoutInMinutes) < DateTime.UtcNow;
}
public class PasswordlessLoginsResponse
{
public List<PasswordlessLoginResponse> Data { get; set; }
}
}

View File

@@ -536,11 +536,27 @@ namespace Bit.Core.Services
#region PasswordlessLogin
public async Task<List<PasswordlessLoginResponse>> GetAuthRequestAsync()
{
var response = await SendAsync<object, PasswordlessLoginsResponse>(HttpMethod.Get, $"/auth-requests/", null, true, true);
return response.Data;
}
public Task<PasswordlessLoginResponse> GetAuthRequestAsync(string id)
{
return SendAsync<object, PasswordlessLoginResponse>(HttpMethod.Get, $"/auth-requests/{id}", null, true, true);
}
public Task<PasswordlessLoginResponse> GetAuthResponseAsync(string id, string accessCode)
{
return SendAsync<object, PasswordlessLoginResponse>(HttpMethod.Get, $"/auth-requests/{id}/response?code={accessCode}", null, false, true);
}
public Task<PasswordlessLoginResponse> PostCreateRequestAsync(PasswordlessCreateLoginRequest passwordlessCreateLoginRequest)
{
return SendAsync<object, PasswordlessLoginResponse>(HttpMethod.Post, $"/auth-requests", passwordlessCreateLoginRequest, false, true);
}
public Task<PasswordlessLoginResponse> PutAuthRequestAsync(string id, string encKey, string encMasterPasswordHash, string deviceIdentifier, bool requestApproved)
{
var request = new PasswordlessLoginRequest(encKey, encMasterPasswordHash, deviceIdentifier, requestApproved);

View File

@@ -24,8 +24,8 @@ namespace Bit.Core.Services
private readonly IPlatformUtilsService _platformUtilsService;
private readonly IMessagingService _messagingService;
private readonly IKeyConnectorService _keyConnectorService;
private readonly IPasswordGenerationService _passwordGenerationService;
private readonly bool _setCryptoKeys;
private SymmetricCryptoKey _key;
public AuthService(
@@ -40,6 +40,7 @@ namespace Bit.Core.Services
IMessagingService messagingService,
IVaultTimeoutService vaultTimeoutService,
IKeyConnectorService keyConnectorService,
IPasswordGenerationService passwordGenerationService,
bool setCryptoKeys = true)
{
_cryptoService = cryptoService;
@@ -52,6 +53,7 @@ namespace Bit.Core.Services
_platformUtilsService = platformUtilsService;
_messagingService = messagingService;
_keyConnectorService = keyConnectorService;
_passwordGenerationService = passwordGenerationService;
_setCryptoKeys = setCryptoKeys;
TwoFactorProviders = new Dictionary<TwoFactorProviderType, TwoFactorProvider>();
@@ -137,6 +139,14 @@ namespace Bit.Core.Services
null, captchaToken);
}
public async Task<AuthResult> LogInPasswordlessAsync(string email, string accessCode, string authRequestId, byte[] decryptionKey, string userKeyCiphered, string localHashedPasswordCiphered)
{
var decKey = await _cryptoService.RsaDecryptAsync(userKeyCiphered, decryptionKey);
var decPasswordHash = await _cryptoService.RsaDecryptAsync(localHashedPasswordCiphered, decryptionKey);
return await LogInHelperAsync(email, accessCode, Encoding.UTF8.GetString(decPasswordHash), null, null, null, new SymmetricCryptoKey(decKey), null, null,
null, null, authRequestId: authRequestId);
}
public async Task<AuthResult> LogInSsoAsync(string code, string codeVerifier, string redirectUrl, string orgId)
{
SelectedTwoFactorProviderType = null;
@@ -286,7 +296,7 @@ namespace Bit.Core.Services
private async Task<AuthResult> LogInHelperAsync(string email, string hashedPassword, string localHashedPassword,
string code, string codeVerifier, string redirectUrl, SymmetricCryptoKey key,
TwoFactorProviderType? twoFactorProvider = null, string twoFactorToken = null, bool? remember = null,
string captchaToken = null, string orgId = null)
string captchaToken = null, string orgId = null, string authRequestId = null)
{
var storedTwoFactorToken = await _tokenService.GetTwoFactorTokenAsync(email);
var appId = await _appIdService.GetAppIdAsync();
@@ -322,6 +332,10 @@ namespace Bit.Core.Services
request = new TokenRequest(emailPassword, codeCodeVerifier, TwoFactorProviderType.Remember,
storedTwoFactorToken, false, captchaToken, deviceRequest);
}
else if (authRequestId != null)
{
request = new TokenRequest(emailPassword, null, null, null, false, null, deviceRequest, authRequestId);
}
else
{
request = new TokenRequest(emailPassword, codeCodeVerifier, null, null, false, captchaToken, deviceRequest);
@@ -471,11 +485,21 @@ namespace Bit.Core.Services
SelectedTwoFactorProviderType = null;
}
public async Task<List<PasswordlessLoginResponse>> GetPasswordlessLoginRequestsAsync()
{
return await _apiService.GetAuthRequestAsync();
}
public async Task<PasswordlessLoginResponse> GetPasswordlessLoginRequestByIdAsync(string id)
{
return await _apiService.GetAuthRequestAsync(id);
}
public async Task<PasswordlessLoginResponse> GetPasswordlessLoginResponseAsync(string id, string accessCode)
{
return await _apiService.GetAuthResponseAsync(id, accessCode);
}
public async Task<PasswordlessLoginResponse> PasswordlessLoginAsync(string id, string pubKey, bool requestApproved)
{
var publicKey = CoreHelpers.Base64UrlDecode(pubKey);
@@ -485,5 +509,25 @@ namespace Bit.Core.Services
var deviceId = await _appIdService.GetAppIdAsync();
return await _apiService.PutAuthRequestAsync(id, encryptedKey.EncryptedString, encryptedMasterPassword.EncryptedString, deviceId, requestApproved);
}
public async Task<PasswordlessLoginResponse> PasswordlessCreateLoginRequestAsync(string email)
{
var deviceId = await _appIdService.GetAppIdAsync();
var keyPair = await _cryptoFunctionService.RsaGenerateKeyPairAsync(2048);
var generatedFingerprintPhrase = await _cryptoService.GetFingerprintAsync(email, keyPair.Item1);
var fingerprintPhrase = string.Join("-", generatedFingerprintPhrase);
var publicB64 = Convert.ToBase64String(keyPair.Item1);
var accessCode = await _passwordGenerationService.GeneratePasswordAsync(new PasswordGenerationOptions(true) { Length = 25 });
var passwordlessCreateLoginRequest = new PasswordlessCreateLoginRequest(email, publicB64, deviceId, accessCode, AuthRequestType.AuthenticateAndUnlock, fingerprintPhrase);
var response = await _apiService.PostCreateRequestAsync(passwordlessCreateLoginRequest);
if (response != null)
{
response.RequestKeyPair = keyPair;
response.RequestAccessCode = accessCode;
}
return response;
}
}
}

View File

@@ -723,7 +723,7 @@ namespace Bit.Core.Services
return await _cryptoFunctionService.AesDecryptAsync(data, iv, theKey.EncKey);
}
private async Task<byte[]> RsaDecryptAsync(string encValue)
public async Task<byte[]> RsaDecryptAsync(string encValue, byte[] privateKey = null)
{
var headerPieces = encValue.Split('.');
EncryptionType? encType = null;
@@ -750,7 +750,12 @@ namespace Bit.Core.Services
}
var data = Convert.FromBase64String(encPieces[0]);
var privateKey = await GetPrivateKeyAsync();
if (privateKey is null)
{
privateKey = await GetPrivateKeyAsync();
}
if (privateKey == null)
{
throw new Exception("No private key.");

View File

@@ -46,6 +46,12 @@ namespace Bit.Core.Services
return activeUserId;
}
public async Task<string> GetActiveUserEmailAsync()
{
var activeUserId = await GetActiveUserIdAsync();
return await GetEmailAsync(activeUserId);
}
public async Task<bool> IsActiveAccountAsync(string userId = null)
{
if (userId == null)

View File

@@ -24,6 +24,7 @@ namespace Bit.Core.Services
private readonly IPolicyService _policyService;
private readonly ISendService _sendService;
private readonly IKeyConnectorService _keyConnectorService;
private readonly ILogger _logger;
private readonly Func<Tuple<string, bool, bool>, Task> _logoutCallbackAsync;
public SyncService(
@@ -39,6 +40,7 @@ namespace Bit.Core.Services
IPolicyService policyService,
ISendService sendService,
IKeyConnectorService keyConnectorService,
ILogger logger,
Func<Tuple<string, bool, bool>, Task> logoutCallbackAsync)
{
_stateService = stateService;
@@ -53,6 +55,7 @@ namespace Bit.Core.Services
_policyService = policyService;
_sendService = sendService;
_keyConnectorService = keyConnectorService;
_logger = logger;
_logoutCallbackAsync = logoutCallbackAsync;
}
@@ -382,5 +385,45 @@ namespace Bit.Core.Services
new Dictionary<string, SendData>();
await _sendService.ReplaceAsync(sends);
}
public async Task SyncPasswordlessLoginRequestsAsync()
{
try
{
var userId = await _stateService.GetActiveUserIdAsync();
// if the user has not enabled passwordless logins ignore requests
if (!await _stateService.GetApprovePasswordlessLoginsAsync(userId))
{
return;
}
var loginRequests = await _apiService.GetAuthRequestAsync();
if (loginRequests == null || !loginRequests.Any())
{
return;
}
var validLoginRequest = loginRequests.Where(l => !l.IsAnswered && !l.IsExpired)
.OrderByDescending(x => x.CreationDate)
.FirstOrDefault();
if (validLoginRequest is null)
{
return;
}
await _stateService.SetPasswordlessLoginNotificationAsync(new PasswordlessRequestNotification()
{
Id = validLoginRequest.Id,
UserId = userId
});
_messagingService.Send(Constants.PasswordlessLoginRequestKey);
}
catch (Exception ex)
{
_logger.Exception(ex);
}
}
}
}

View File

@@ -29,6 +29,8 @@ namespace Bit.Core.Utilities
var messagingService = Resolve<IMessagingService>("messagingService");
var cryptoFunctionService = Resolve<ICryptoFunctionService>("cryptoFunctionService");
var cryptoService = Resolve<ICryptoService>("cryptoService");
var logger = Resolve<ILogger>();
SearchService searchService = null;
var tokenService = new TokenService(stateService);
@@ -67,7 +69,7 @@ namespace Bit.Core.Utilities
});
var syncService = new SyncService(stateService, apiService, settingsService, folderService, cipherService,
cryptoService, collectionService, organizationService, messagingService, policyService, sendService,
keyConnectorService, (extras) =>
keyConnectorService, logger, (extras) =>
{
messagingService.Send("logout", extras);
return Task.CompletedTask;
@@ -77,7 +79,7 @@ namespace Bit.Core.Utilities
var totpService = new TotpService(cryptoFunctionService);
var authService = new AuthService(cryptoService, cryptoFunctionService, apiService, stateService,
tokenService, appIdService, i18nService, platformUtilsService, messagingService, vaultTimeoutService,
keyConnectorService);
keyConnectorService, passwordGenerationService);
var exportService = new ExportService(folderService, cipherService, cryptoService);
var auditService = new AuditService(cryptoFunctionService, apiService);
var environmentService = new EnvironmentService(apiService, stateService);

View File

@@ -425,10 +425,10 @@ namespace Bit.iOS.Autofill
}
}
private void LaunchHomePage(bool checkRememberedEmail = true)
private void LaunchHomePage(bool shouldCheckRememberEmail = true)
{
var appOptions = new AppOptions { IosExtension = true };
var homePage = new HomePage(appOptions, checkRememberedEmail: checkRememberedEmail);
var homePage = new HomePage(appOptions, shouldCheckRememberEmail);
var app = new App.App(appOptions);
ThemeManager.SetTheme(app.Resources);
ThemeManager.ApplyResourcesTo(homePage);
@@ -457,8 +457,8 @@ namespace Bit.iOS.Autofill
ThemeManager.ApplyResourcesTo(environmentPage);
if (environmentPage.BindingContext is EnvironmentPageViewModel vm)
{
vm.SubmitSuccessAction = () => DismissViewController(false, () => LaunchHomePage(checkRememberedEmail: false));
vm.CloseAction = () => DismissViewController(false, () => LaunchHomePage(checkRememberedEmail: false));
vm.SubmitSuccessAction = () => DismissViewController(false, () => LaunchHomePage(shouldCheckRememberEmail: false));
vm.CloseAction = () => DismissViewController(false, () => LaunchHomePage(shouldCheckRememberEmail: false));
}
var navigationPage = new NavigationPage(environmentPage);
@@ -476,7 +476,7 @@ namespace Bit.iOS.Autofill
if (registerPage.BindingContext is RegisterPageViewModel vm)
{
vm.RegistrationSuccess = () => DismissViewController(false, () => LaunchLoginFlow(vm.Email));
vm.CloseAction = () => DismissViewController(false, () => LaunchHomePage(checkRememberedEmail: false));
vm.CloseAction = () => DismissViewController(false, () => LaunchHomePage(shouldCheckRememberEmail: false));
}
var navigationPage = new NavigationPage(registerPage);
@@ -497,8 +497,9 @@ namespace Bit.iOS.Autofill
vm.StartTwoFactorAction = () => DismissViewController(false, () => LaunchTwoFactorFlow(false));
vm.UpdateTempPasswordAction = () => DismissViewController(false, () => LaunchUpdateTempPasswordFlow());
vm.StartSsoLoginAction = () => DismissViewController(false, () => LaunchLoginSsoFlow());
vm.LogInWithDeviceAction = () => DismissViewController(false, () => LaunchLoginWithDevice(email));
vm.LogInSuccessAction = () => DismissLockAndContinue();
vm.CloseAction = () => DismissViewController(false, () => LaunchHomePage(checkRememberedEmail: false));
vm.CloseAction = () => DismissViewController(false, () => LaunchHomePage(shouldCheckRememberEmail: false));
}
var navigationPage = new NavigationPage(loginPage);
@@ -509,6 +510,29 @@ namespace Bit.iOS.Autofill
LogoutIfAuthed();
}
private void LaunchLoginWithDevice(string email = null)
{
var appOptions = new AppOptions { IosExtension = true };
var app = new App.App(appOptions);
var loginWithDevicePage = new LoginPasswordlessRequestPage(email, appOptions);
ThemeManager.SetTheme(app.Resources);
ThemeManager.ApplyResourcesTo(loginWithDevicePage);
if (loginWithDevicePage.BindingContext is LoginPasswordlessRequestViewModel vm)
{
vm.StartTwoFactorAction = () => DismissViewController(false, () => LaunchTwoFactorFlow(false));
vm.UpdateTempPasswordAction = () => DismissViewController(false, () => LaunchUpdateTempPasswordFlow());
vm.LogInSuccessAction = () => DismissLockAndContinue();
vm.CloseAction = () => DismissViewController(false, () => LaunchHomePage());
}
var navigationPage = new NavigationPage(loginWithDevicePage);
var loginController = navigationPage.CreateViewController();
loginController.ModalPresentationStyle = UIModalPresentationStyle.FullScreen;
PresentViewController(loginController, true, null);
LogoutIfAuthed();
}
private void LaunchLoginSsoFlow()
{
var loginPage = new LoginSsoPage();
@@ -604,7 +628,14 @@ namespace Bit.iOS.Autofill
switch (navTarget)
{
case NavigationTarget.HomeLogin:
DismissViewController(false, () => LaunchHomePage());
if (navParams is HomeNavigationParams homeParams)
{
DismissViewController(false, () => LaunchHomePage(homeParams.ShouldCheckRememberEmail));
}
else
{
DismissViewController(false, () => LaunchHomePage());
}
break;
case NavigationTarget.Login:
if (navParams is LoginNavigationParams loginParams)

View File

@@ -446,10 +446,10 @@ namespace Bit.iOS.Extension
});
}
private void LaunchHomePage(bool checkRememberedEmail = true)
private void LaunchHomePage(bool shouldCheckRememberEmail = true)
{
var appOptions = new AppOptions { IosExtension = true };
var homePage = new HomePage(appOptions, checkRememberedEmail: checkRememberedEmail);
var homePage = new HomePage(appOptions, shouldCheckRememberEmail);
var app = new App.App(appOptions);
ThemeManager.SetTheme(app.Resources);
ThemeManager.ApplyResourcesTo(homePage);
@@ -478,8 +478,8 @@ namespace Bit.iOS.Extension
ThemeManager.ApplyResourcesTo(environmentPage);
if (environmentPage.BindingContext is EnvironmentPageViewModel vm)
{
vm.SubmitSuccessAction = () => DismissViewController(false, () => LaunchHomePage(checkRememberedEmail: false));
vm.CloseAction = () => DismissViewController(false, () => LaunchHomePage(checkRememberedEmail: false));
vm.SubmitSuccessAction = () => DismissViewController(false, () => LaunchHomePage(shouldCheckRememberEmail: false));
vm.CloseAction = () => DismissViewController(false, () => LaunchHomePage(shouldCheckRememberEmail: false));
}
var navigationPage = new NavigationPage(environmentPage);
@@ -497,7 +497,7 @@ namespace Bit.iOS.Extension
if (registerPage.BindingContext is RegisterPageViewModel vm)
{
vm.RegistrationSuccess = () => DismissViewController(false, () => LaunchLoginFlow(vm.Email));
vm.CloseAction = () => DismissViewController(false, () => LaunchHomePage(checkRememberedEmail: false));
vm.CloseAction = () => DismissViewController(false, () => LaunchHomePage(shouldCheckRememberEmail: false));
}
var navigationPage = new NavigationPage(registerPage);
@@ -518,8 +518,9 @@ namespace Bit.iOS.Extension
vm.StartTwoFactorAction = () => DismissViewController(false, () => LaunchTwoFactorFlow(false));
vm.UpdateTempPasswordAction = () => DismissViewController(false, () => LaunchUpdateTempPasswordFlow());
vm.StartSsoLoginAction = () => DismissViewController(false, () => LaunchLoginSsoFlow());
vm.LogInWithDeviceAction = () => DismissViewController(false, () => LaunchLoginWithDevice(email));
vm.LogInSuccessAction = () => DismissLockAndContinue();
vm.CloseAction = () => DismissViewController(false, () => LaunchHomePage(checkRememberedEmail: false));
vm.CloseAction = () => DismissViewController(false, () => LaunchHomePage(shouldCheckRememberEmail: false));
}
var navigationPage = new NavigationPage(loginPage);
@@ -530,6 +531,29 @@ namespace Bit.iOS.Extension
LogoutIfAuthed();
}
private void LaunchLoginWithDevice(string email = null)
{
var appOptions = new AppOptions { IosExtension = true };
var app = new App.App(appOptions);
var loginWithDevicePage = new LoginPasswordlessRequestPage(email, appOptions);
ThemeManager.SetTheme(app.Resources);
ThemeManager.ApplyResourcesTo(loginWithDevicePage);
if (loginWithDevicePage.BindingContext is LoginPasswordlessRequestViewModel vm)
{
vm.StartTwoFactorAction = () => DismissViewController(false, () => LaunchTwoFactorFlow(false));
vm.UpdateTempPasswordAction = () => DismissViewController(false, () => LaunchUpdateTempPasswordFlow());
vm.LogInSuccessAction = () => DismissLockAndContinue();
vm.CloseAction = () => DismissViewController(false, () => LaunchHomePage());
}
var navigationPage = new NavigationPage(loginWithDevicePage);
var loginController = navigationPage.CreateViewController();
loginController.ModalPresentationStyle = UIModalPresentationStyle.FullScreen;
PresentViewController(loginController, true, null);
LogoutIfAuthed();
}
private void LaunchLoginSsoFlow()
{
var loginPage = new LoginSsoPage();

View File

@@ -287,9 +287,9 @@ namespace Bit.iOS.ShareExtension
return _app;
}
private void LaunchHomePage(bool checkRememberedEmail = true)
private void LaunchHomePage(bool shouldCheckRememberEmail = true)
{
var homePage = new HomePage(_appOptions.Value, checkRememberedEmail: checkRememberedEmail);
var homePage = new HomePage(_appOptions.Value, shouldCheckRememberEmail);
SetupAppAndApplyResources(homePage);
if (homePage.BindingContext is HomeViewModel vm)
{
@@ -311,8 +311,8 @@ namespace Bit.iOS.ShareExtension
ThemeManager.ApplyResourcesTo(environmentPage);
if (environmentPage.BindingContext is EnvironmentPageViewModel vm)
{
vm.SubmitSuccessAction = () => DismissAndLaunch(() => LaunchHomePage(checkRememberedEmail: false));
vm.CloseAction = () => DismissAndLaunch(() => LaunchHomePage(checkRememberedEmail: false));
vm.SubmitSuccessAction = () => DismissAndLaunch(() => LaunchHomePage(shouldCheckRememberEmail: false));
vm.CloseAction = () => DismissAndLaunch(() => LaunchHomePage(shouldCheckRememberEmail: false));
}
NavigateToPage(environmentPage);
@@ -325,7 +325,7 @@ namespace Bit.iOS.ShareExtension
if (registerPage.BindingContext is RegisterPageViewModel vm)
{
vm.RegistrationSuccess = () => DismissAndLaunch(() => LaunchLoginFlow(vm.Email));
vm.CloseAction = () => DismissAndLaunch(() => LaunchHomePage(checkRememberedEmail: false));
vm.CloseAction = () => DismissAndLaunch(() => LaunchHomePage(shouldCheckRememberEmail: false));
}
NavigateToPage(registerPage);
}
@@ -339,17 +339,31 @@ namespace Bit.iOS.ShareExtension
vm.StartTwoFactorAction = () => DismissAndLaunch(() => LaunchTwoFactorFlow(false));
vm.UpdateTempPasswordAction = () => DismissAndLaunch(() => LaunchUpdateTempPasswordFlow());
vm.StartSsoLoginAction = () => DismissAndLaunch(() => LaunchLoginSsoFlow());
vm.LogInSuccessAction = () =>
{
DismissLockAndContinue();
};
vm.CloseAction = () => DismissAndLaunch(() => LaunchHomePage(checkRememberedEmail: false));
vm.LogInWithDeviceAction = () => DismissAndLaunch(() => LaunchLoginWithDevice(email));
vm.LogInSuccessAction = () => { DismissLockAndContinue(); };
vm.CloseAction = () => DismissAndLaunch(() => LaunchHomePage(shouldCheckRememberEmail: false));
}
NavigateToPage(loginPage);
LogoutIfAuthed();
}
private void LaunchLoginWithDevice(string email = null)
{
var loginWithDevicePage = new LoginPasswordlessRequestPage(email, _appOptions.Value);
SetupAppAndApplyResources(loginWithDevicePage);
if (loginWithDevicePage.BindingContext is LoginPasswordlessRequestViewModel vm)
{
vm.StartTwoFactorAction = () => DismissAndLaunch(() => LaunchTwoFactorFlow(false));
vm.UpdateTempPasswordAction = () => DismissAndLaunch(() => LaunchUpdateTempPasswordFlow());
vm.LogInSuccessAction = () => { DismissLockAndContinue(); };
vm.CloseAction = () => DismissAndLaunch(() => LaunchHomePage());
}
NavigateToPage(loginWithDevicePage);
LogoutIfAuthed();
}
private void LaunchLoginSsoFlow()
{
var loginPage = new LoginSsoPage();
@@ -427,7 +441,14 @@ namespace Bit.iOS.ShareExtension
switch (navTarget)
{
case NavigationTarget.HomeLogin:
ExecuteLaunch(() => LaunchHomePage());
if (navParams is HomeNavigationParams homeParams)
{
ExecuteLaunch(() => LaunchHomePage(homeParams.ShouldCheckRememberEmail));
}
else
{
ExecuteLaunch(() => LaunchHomePage());
}
break;
case NavigationTarget.Login:
if (navParams is LoginNavigationParams loginParams)

View File

@@ -146,8 +146,7 @@ Global Translations
Bitwarden translations exist in 40 languages and are growing, thanks to our global community.
Cross-Platform Applications
Secure and share sensitive data within your Bitwarden Vault from any browser, mobile device, or desktop OS, and more.
</value>
Secure and share sensitive data within your Bitwarden Vault from any browser, mobile device, or desktop OS, and more.</value>
<comment>Max 4000 characters</comment>
</data>
<data name="Keywords" xml:space="preserve">

View File

@@ -130,7 +130,7 @@ Upravljajte, spremajte, osigurajte i dijelite neograničen broj lozinki na neogr
Generirajte jake, jedinstvene i nasumične lozinke bazirane na sigurnosnim zahtjevima za svaku web stranicu koju često posjećujete.
Bitwarden Send omoguzćuje jednostavno i brzo slanje šifriranih podataka --- datoteki ili teksta -- direktno, bilo kome.
Bitwarden Send omoguzćuje jednostavno i brzo slanje šifriranih podataka --- datoteka ili teksta -- direktno, bilo kome.
Bitwarden nudi Teams i Enterprise planove za tvrtke kako biste sigurno mogli dijeliti lozinke s kolegama na poslu.
@@ -146,7 +146,8 @@ Svjetski dostupan
Bitwarden je, zahvaljujući našoj globalnoj zajednici, dostupan na više od 40 jezika.
Podržani svi OS
Osigurajte i sigurno dijelite osjetljive podatke sadržane u vašem Bitwarden trezoru iz bilo kojeg preglednika, mobilnog uređaja ili stolnog računala s bilo kojim OS.</value>
Osigurajte i sigurno dijelite osjetljive podatke sadržane u vašem Bitwarden trezoru iz bilo kojeg preglednika, mobilnog uređaja ili stolnog računala s bilo kojim OS.
</value>
<comment>Max 4000 characters</comment>
</data>
<data name="Keywords" xml:space="preserve">

View File

@@ -122,32 +122,31 @@
<comment>Max 30 characters</comment>
</data>
<data name="Description" xml:space="preserve">
<value>Bitwarden, Inc. is the parent company of 8bit Solutions LLC.
<value>Bitwarden, Inc. 8bit Solutions LLC の親会社です。
NAMED BEST PASSWORD MANAGER BY THE VERGE, U.S. NEWS &amp; WORLD REPORT, CNET, AND MORE.
The Verge、U.S. NEWS &amp; WORLD REPORTCNET などでベスト パスワード マネージャーに選ばれました。
Manage, store, secure, and share unlimited passwords across unlimited devices from anywhere. Bitwarden delivers open source password management solutions to everyone, whether at home, at work, or on the go.
どこからでも無制限のデバイスで無制限のパスワードを管理、保存、保護、共有します。 Bitwarden は、自宅、職場、外出先を問わず、オープンソースのパスワード管理ソリューションをすべての人に提供します。
Generate strong, unique, and random passwords based on security requirements for every website you frequent.
頻繁に使用するすべての Web サイトのセキュリティ要件に基づいて、強力で一意のランダムなパスワードを生成します。
Bitwarden Send quickly transmits encrypted information --- files and plaintext -- directly to anyone.
Bitwarden Send は、暗号化された情報 (ファイルと平文) を迅速に誰にでも直接送信します。
Bitwarden offers Teams and Enterprise plans for companies so you can securely share passwords with colleagues.
Bitwarden は企業向けに Teams および Enterprise プランを提供しているため、パスワードを同僚と安全に共有できます。
Why Choose Bitwarden:
Bitwarden を選ぶ理由:
World-Class Encryption
Passwords are protected with advanced end-to-end encryption (AES-256 bit, salted hashtag, and PBKDF2 SHA-256) so your data stays secure and private.
世界クラスの暗号化
パスワードは高度なエンド ツー エンドの暗号化 (AES-256 ビット、ソルト付きハッシュタグ、PBKDF2 SHA-256) で保護されるため、データは安全かつプライベートに保たれます。
Built-in Password Generator
Generate strong, unique, and random passwords based on security requirements for every website you frequent.
組み込みのパスワードジェネレーター
頻繁に使用するすべての Web サイトのセキュリティ要件に基づいて、強力で一意のランダムなパスワードを生成します。
Global Translations
Bitwarden translations exist in 40 languages and are growing, thanks to our global community.
グローバル翻訳
Bitwarden の翻訳は 40 の言語に存在し、グローバル コミュニティのおかげで成長を続けています。
Cross-Platform Applications
Secure and share sensitive data within your Bitwarden Vault from any browser, mobile device, or desktop OS, and more.
</value>
クロスプラットフォーム アプリケーション
ブラウザ、モバイル デバイス、デスクトップ OS などから Bitwarden Vault 内の機密データを保護して共有します。</value>
<comment>Max 4000 characters</comment>
</data>
<data name="Keywords" xml:space="preserve">

View File

@@ -122,31 +122,31 @@
<comment>Max 30 characters</comment>
</data>
<data name="Description" xml:space="preserve">
<value>Bitwarden, Inc. is the parent company of 8bit Solutions LLC.
<value>Bitwarden, Inc. er morselskapet til 8bit Solutions LLC.
NAMED BEST PASSWORD MANAGER BY THE VERGE, U.S. NEWS &amp; WORLD REPORT, CNET, AND MORE.
BESTE PASSORD MANAGER AV VERDIEN, NYHETER og ARBEID RAPPORT, KNET, OG MORES.
Manage, store, secure, and share unlimited passwords across unlimited devices from anywhere. Bitwarden delivers open source password management solutions to everyone, whether at home, at work, or on the go.
Håndtering, lagring, sikker, og deling av ubegrenset med passord på tvers av ubegrenset antall enheter fra hvor som helst. Bitwarden leverer passordbehandlingsløsninger med åpen kildekode til alle, enten hjemme, på jobb eller på farten.
Generate strong, unique, and random passwords based on security requirements for every website you frequent.
Generer sterke, unike, og tilfeldige passord basert på sikkerhetskrav for alle nettsteder du hyppiger.
Bitwarden Send quickly transmits encrypted information --- files and plaintext -- directly to anyone.
Bitwarden Sende raskt sender krypterte informasjonsfiler --- og klartekst -- direkte til alle.
Bitwarden offers Teams and Enterprise plans for companies so you can securely share passwords with colleagues.
Bitwarden tilbyr Lag og Enterprise planer for firmaer så du kan sikkert dele passord med kolleger.
Why Choose Bitwarden:
Hvorfor velge Bitwarden:
World-Class Encryption
Passwords are protected with advanced end-to-end encryption (AES-256 bit, salted hashtag, and PBKDF2 SHA-256) so your data stays secure and private.
Passord er beskyttet med avansert ende-til-ende-kryptering (AES-256 bit, Saltet hashtag, og PBKDF2 SHA-256) så dataene dine forblir sikre og private.
Built-in Password Generator
Generate strong, unique, and random passwords based on security requirements for every website you frequent.
Innebygd passordgenerator
Generer sterke, unike og tilfeldige passord basert på sikkerhetskrav for alle nettsteder du hyppiger.
Global Translations
Bitwarden translations exist in 40 languages and are growing, thanks to our global community.
Globale oversettelser
Bitwarden finnes på 40 språk og vokser igjen, takket være vårt globale nettsamfunn.
Cross-Platform Applications
Secure and share sensitive data within your Bitwarden Vault from any browser, mobile device, or desktop OS, and more.
Secure og del sensitive data i Bitwarden sitt hvelv fra enhver nettleser, mobil enhet eller desktop OS og mer
</value>
<comment>Max 4000 characters</comment>
</data>

View File

@@ -9,25 +9,34 @@ using Google.Apis.Services;
namespace Bit.Publisher
{
// static class to hold global variables, etc.
static class Globals
{
// global string
// private const string Package = "com.x8bit.bitwarden";
public static string Package;
}
public class Program
{
private const string Package = "com.x8bit.bitwarden";
private static string _aabFilePath;
private static string _credsFilePath;
private static string _track;
static void Main(string[] args)
{
if (args.Length < 3)
if (args.Length < 4)
{
throw new ArgumentException("Not enough arguments.");
throw new ArgumentException("Not enough arguments (needs 4), got: " + args.Length);
}
try
{
_credsFilePath = args[0];
_aabFilePath = args[1];
Globals.Package = args[3];
var track = args[2].Substring(0, 1).ToLower();
if (track == "a")
@@ -79,7 +88,7 @@ namespace Bit.Publisher
});
service.HttpClient.Timeout = TimeSpan.FromMinutes(3);
var editRequest = service.Edits.Insert(null, Package);
var editRequest = service.Edits.Insert(null, Globals.Package);
var edit = await editRequest.ExecuteAsync();
Console.WriteLine("Created edit with id {0}.", edit.Id);
@@ -87,7 +96,7 @@ namespace Bit.Publisher
Bundle aab = null;
using (var stream = new FileStream(_aabFilePath, FileMode.Open))
{
var uploadMedia = service.Edits.Bundles.Upload(Package, edit.Id, stream,
var uploadMedia = service.Edits.Bundles.Upload(Globals.Package, edit.Id, stream,
"application/octet-stream");
var progress = await uploadMedia.UploadAsync();
@@ -114,12 +123,12 @@ namespace Bit.Publisher
{
new TrackRelease { VersionCodes = new List<long?> { aab.VersionCode }, Status = "completed" }
}
}, Package, edit.Id, _track);
}, Globals.Package, edit.Id, _track);
var updatedTrack = await trackRequest.ExecuteAsync();
Console.WriteLine("Track {0} has been updated.", updatedTrack.TrackValue);
var commitRequest = service.Edits.Commit(Package, edit.Id);
var commitRequest = service.Edits.Commit(Globals.Package, edit.Id);
var commitEdit = await commitRequest.ExecuteAsync();
Console.WriteLine("App edit with id {0} has been comitted.", commitEdit.Id);
}

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