26 Commits

Author SHA1 Message Date
Burak Kaan Köse ef12e0ff3a Init translations before showing nwe version notification. 2026-04-25 22:48:31 +02:00
Burak Kaan Köse e7e201758e Handle expired subscriptions. 2026-04-25 22:48:15 +02:00
Burak Kaan Köse 55ae6e1f3a Initial v2 launch notification. 2026-04-25 16:12:49 +02:00
Burak Kaan Köse 3ea8b8ac46 Bulk updates for gmail. 2026-04-25 16:00:49 +02:00
Burak Kaan Köse 8fe40e9fe3 Potential gmail history id fix. 2026-04-23 15:00:55 +02:00
Burak Kaan Köse 6f82cd4f26 Save as eml, translation updates 2026-04-23 13:23:05 +02:00
Burak Kaan Köse 81e28129b7 Set default language based on Windows language. 2026-04-22 22:39:19 +02:00
Burak Kaan Köse 39cde10fab Fix signature settings persistence and editing 2026-04-22 13:25:07 +02:00
Burak Kaan Köse ed54eb0284 Beta 2.0.6.0 2026-04-22 13:11:33 +02:00
Burak Kaan Köse d66015bebd Fixed iCloud/Yahoo special providers and implemented more calendar metadata to support calendar colors in CalDav synchronizer. 2026-04-22 09:55:13 +02:00
Burak Kaan Köse 890bfc84f1 Allow Outlook reauth when UPN differs from mailbox 2026-04-22 01:43:53 +02:00
Burak Kaan Köse 59505d6985 Render mail categories in list items 2026-04-22 01:28:18 +02:00
Burak Kaan Köse 09820dda71 Add local mail pinning support 2026-04-21 23:17:08 +02:00
Burak Kaan Köse c0023614ad Harden junk mail image tracking protection 2026-04-21 22:21:59 +02:00
Burak Kaan Köse e0f517e993 Updated translations. 2026-04-20 23:20:08 +02:00
Burak Kaan Köse 66c556b587 Hide email address for calendar only accounts and fix startup crash. 2026-04-20 23:19:53 +02:00
Burak Kaan Köse 877fb0dbd4 Do not popup success sync message on executing requests. 2026-04-20 23:06:11 +02:00
Burak Kaan Köse 2ea65dc556 Remove the confirmamtion when compose page is dismissed after closing the window. 2026-04-20 22:51:20 +02:00
Burak Kaan Köse 23dce29ff8 Fix the issue with Chinese fonts on menu flyout items and appbar buttons in compose page. 2026-04-20 22:51:08 +02:00
Burak Kaan Köse 9292c963d5 Fix missing additional properties loading for mails. 2026-04-20 20:37:52 +02:00
Burak Kaan Köse 2b1676a4f7 Dispose mail webviews when closing the shell 2026-04-20 19:40:45 +02:00
Burak Kaan Köse d85812ed7b Add capability-first account and calendar setup flow 2026-04-20 19:38:37 +02:00
Burak Kaan Köse 54148716bb Fixing UI thread issues with bulk operations and request queue refactoring. 2026-04-20 02:18:23 +02:00
Burak Kaan Köse 3bd0b69429 Imap flow. 2026-04-19 20:13:09 +02:00
Burak Kaan Köse 496c7735f7 Add configurable thread item sorting 2026-04-19 16:26:30 +02:00
Burak Kaan Köse bfbc3d40b3 Make system tray icon optional 2026-04-19 10:47:42 +02:00
173 changed files with 8803 additions and 1020 deletions
+1 -1
View File
@@ -45,6 +45,6 @@ public class GmailAuthenticator : BaseAuthenticator, IGmailAuthenticator
return GoogleWebAuthorizationBroker.AuthorizeAsync(new ClientSecrets() return GoogleWebAuthorizationBroker.AuthorizeAsync(new ClientSecrets()
{ {
ClientId = ClientId ClientId = ClientId
}, AuthenticatorConfig.GmailScope, account.Id.ToString(), CancellationToken.None, new FileDataStore(AuthenticatorConfig.GmailTokenStoreIdentifier)); }, AuthenticatorConfig.GetGmailScope(account?.IsMailAccessGranted != false, account?.IsCalendarAccessGranted == true), account.Id.ToString(), CancellationToken.None, new FileDataStore(AuthenticatorConfig.GmailTokenStoreIdentifier));
} }
} }
+8 -15
View File
@@ -65,7 +65,10 @@ public class OutlookAuthenticator : BaseAuthenticator, IOutlookAuthenticator
_publicClientApplication = outlookAppBuilder.Build(); _publicClientApplication = outlookAppBuilder.Build();
} }
public string[] Scope => AuthenticatorConfig.OutlookScope; private string[] GetScope(MailAccount account)
=> AuthenticatorConfig.GetOutlookScope(
account?.IsMailAccessGranted != false,
account?.IsCalendarAccessGranted == true);
private async Task EnsureTokenCacheAttachedAsync() private async Task EnsureTokenCacheAttachedAsync()
{ {
@@ -91,7 +94,7 @@ public class OutlookAuthenticator : BaseAuthenticator, IOutlookAuthenticator
try try
{ {
var authResult = await _publicClientApplication.AcquireTokenSilent(Scope, storedAccount).ExecuteAsync(); var authResult = await _publicClientApplication.AcquireTokenSilent(GetScope(account), storedAccount).ExecuteAsync();
return new TokenInformationEx(authResult.AccessToken, authResult.Account.Username); return new TokenInformationEx(authResult.AccessToken, authResult.Account.Username);
} }
@@ -103,10 +106,6 @@ public class OutlookAuthenticator : BaseAuthenticator, IOutlookAuthenticator
return await GenerateTokenInformationAsync(account); return await GenerateTokenInformationAsync(account);
} }
catch (Exception)
{
throw;
}
} }
public async Task<TokenInformationEx> GenerateTokenInformationAsync(MailAccount account) public async Task<TokenInformationEx> GenerateTokenInformationAsync(MailAccount account)
@@ -122,17 +121,11 @@ public class OutlookAuthenticator : BaseAuthenticator, IOutlookAuthenticator
if (_nativeAppService.GetCoreWindowHwnd == null) throw new AuthenticationAttentionException(account); if (_nativeAppService.GetCoreWindowHwnd == null) throw new AuthenticationAttentionException(account);
AuthenticationResult authResult = await _publicClientApplication AuthenticationResult authResult = await _publicClientApplication
.AcquireTokenInteractive(Scope) .AcquireTokenInteractive(GetScope(account))
.ExecuteAsync(); .ExecuteAsync();
// If the account is null, it means it's the initial creation of it. // Microsoft 365 work/school tenants can use a sign-in UPN that differs from
// If not, make sure the authenticated user address matches the username. // the mailbox primary SMTP address, so interactive reauth must not reject them.
// When people refresh their token, accounts must match.
if (account?.Address != null && !account.Address.Equals(authResult.Account.Username, StringComparison.OrdinalIgnoreCase))
{
throw new AuthenticationException("Authenticated address does not match with your account address. If you are signing with a Office365, it is not officially supported yet.");
}
return new TokenInformationEx(authResult.AccessToken, authResult.Account.Username); return new TokenInformationEx(authResult.AccessToken, authResult.Account.Username);
} }
@@ -299,6 +299,9 @@ public partial class CalendarAppShellViewModel : CalendarBaseViewModel,
foreach (var account in accounts) foreach (var account in accounts)
{ {
if (!GroupedAccountCalendarViewModel.SupportsCalendar(account))
continue;
var accountCalendars = await _calendarService.GetAccountCalendarsAsync(account.Id).ConfigureAwait(false); var accountCalendars = await _calendarService.GetAccountCalendarsAsync(account.Id).ConfigureAwait(false);
var calendarViewModels = accountCalendars.Select(calendar => new AccountCalendarViewModel(account, calendar)).ToList(); var calendarViewModels = accountCalendars.Select(calendar => new AccountCalendarViewModel(account, calendar)).ToList();
var groupedAccountCalendarViewModel = new GroupedAccountCalendarViewModel(account, calendarViewModels); var groupedAccountCalendarViewModel = new GroupedAccountCalendarViewModel(account, calendarViewModels);
@@ -408,6 +408,9 @@ public partial class CalendarEventComposePageViewModel : CalendarBaseViewModel
foreach (var account in accounts) foreach (var account in accounts)
{ {
if (!GroupedAccountCalendarViewModel.SupportsCalendar(account))
continue;
var calendars = await _calendarService.GetAccountCalendarsAsync(account.Id).ConfigureAwait(false); var calendars = await _calendarService.GetAccountCalendarsAsync(account.Id).ConfigureAwait(false);
var viewModels = calendars var viewModels = calendars
.Select(calendar => new AccountCalendarViewModel(account, calendar)) .Select(calendar => new AccountCalendarViewModel(account, calendar))
@@ -17,6 +17,9 @@ public partial class GroupedAccountCalendarViewModel : ObservableObject
public MailAccount Account { get; } public MailAccount Account { get; }
public ObservableCollection<AccountCalendarViewModel> AccountCalendars { get; } public ObservableCollection<AccountCalendarViewModel> AccountCalendars { get; }
public static bool SupportsCalendar(MailAccount account)
=> account?.IsCalendarAccessGranted == true;
public GroupedAccountCalendarViewModel(MailAccount account, IEnumerable<AccountCalendarViewModel> calendarViewModels) public GroupedAccountCalendarViewModel(MailAccount account, IEnumerable<AccountCalendarViewModel> calendarViewModels)
{ {
Account = account; Account = account;
@@ -95,6 +98,7 @@ public partial class GroupedAccountCalendarViewModel : ObservableObject
public bool CanSynchronize => !IsSynchronizationInProgress; public bool CanSynchronize => !IsSynchronizationInProgress;
public bool IsSynchronizationProgressVisible => IsSynchronizationInProgress; public bool IsSynchronizationProgressVisible => IsSynchronizationInProgress;
public bool IsProgressIndeterminate => IsSynchronizationInProgress && TotalItemsToSync <= 0; public bool IsProgressIndeterminate => IsSynchronizationInProgress && TotalItemsToSync <= 0;
public string AccountAddressDisplay => string.IsNullOrWhiteSpace(Account?.Address) ? string.Empty : $" ({Account.Address})";
public double SynchronizationProgress public double SynchronizationProgress
{ {
@@ -198,5 +202,6 @@ public partial class GroupedAccountCalendarViewModel : ObservableObject
Account.MergedInboxId = updatedAccount.MergedInboxId; Account.MergedInboxId = updatedAccount.MergedInboxId;
AccountColorHex = updatedAccount.AccountColorHex; AccountColorHex = updatedAccount.AccountColorHex;
OnPropertyChanged(nameof(Account)); OnPropertyChanged(nameof(Account));
OnPropertyChanged(nameof(AccountAddressDisplay));
} }
} }
@@ -92,6 +92,11 @@ public class MailCopy
/// </summary> /// </summary>
public bool IsFlagged { get; set; } public bool IsFlagged { get; set; }
/// <summary>
/// Whether this mail should stay pinned to the top locally.
/// </summary>
public bool IsPinned { get; set; }
/// <summary> /// <summary>
/// To support Outlook. /// To support Outlook.
/// Gmail doesn't use it. /// Gmail doesn't use it.
@@ -167,6 +172,9 @@ public class MailCopy
[Ignore] [Ignore]
public Guid? ReadReceiptMessageUniqueId { get; set; } public Guid? ReadReceiptMessageUniqueId { get; set; }
[Ignore]
public List<MailCategory> Categories { get; set; } = [];
public IEnumerable<Guid> GetContainingIds() => [UniqueId]; public IEnumerable<Guid> GetContainingIds() => [UniqueId];
public override string ToString() => $"{Subject} <-> {Id}"; public override string ToString() => $"{Subject} <-> {Id}";
} }
@@ -78,6 +78,13 @@ public class MailAccount
/// </summary> /// </summary>
public SpecialImapProvider SpecialImapProvider { get; set; } public SpecialImapProvider SpecialImapProvider { get; set; }
/// <summary>
/// Gets or sets whether mail access is granted for this account.
/// When false, mail folders, aliases, compose flows, and mail synchronization are unavailable.
/// Default is true for legacy accounts to preserve existing behavior.
/// </summary>
public bool IsMailAccessGranted { get; set; } = true;
/// <summary> /// <summary>
/// Gets or sets whether calendar access is granted for this account. /// Gets or sets whether calendar access is granted for this account.
/// When false, synchronizers will not process EventMessages or calendar invitations. /// When false, synchronizers will not process EventMessages or calendar invitations.
+2 -1
View File
@@ -16,5 +16,6 @@ public enum AppLanguage
Greek, Greek,
PortugeseBrazil, PortugeseBrazil,
Italian, Italian,
Romanian Romanian,
Korean
} }
+16 -12
View File
@@ -20,17 +20,19 @@ public enum MailCopyChangeFlags
Importance = 1 << 11, Importance = 1 << 11,
IsRead = 1 << 12, IsRead = 1 << 12,
IsFlagged = 1 << 13, IsFlagged = 1 << 13,
IsFocused = 1 << 14, IsPinned = 1 << 14,
HasAttachments = 1 << 15, IsFocused = 1 << 15,
ItemType = 1 << 16, HasAttachments = 1 << 16,
DraftId = 1 << 17, ItemType = 1 << 17,
IsDraft = 1 << 18, DraftId = 1 << 18,
FileId = 1 << 19, IsDraft = 1 << 19,
AssignedFolder = 1 << 20, FileId = 1 << 20,
AssignedAccount = 1 << 21, AssignedFolder = 1 << 21,
SenderContact = 1 << 22, AssignedAccount = 1 << 22,
UniqueId = 1 << 23, SenderContact = 1 << 23,
ReadReceiptState = 1 << 24, UniqueId = 1 << 24,
ReadReceiptState = 1 << 25,
Categories = 1 << 26,
All = Id | All = Id |
FolderId | FolderId |
ThreadId | ThreadId |
@@ -45,6 +47,7 @@ public enum MailCopyChangeFlags
Importance | Importance |
IsRead | IsRead |
IsFlagged | IsFlagged |
IsPinned |
IsFocused | IsFocused |
HasAttachments | HasAttachments |
ItemType | ItemType |
@@ -55,5 +58,6 @@ public enum MailCopyChangeFlags
AssignedAccount | AssignedAccount |
SenderContact | SenderContact |
UniqueId | UniqueId |
ReadReceiptState ReadReceiptState |
Categories
} }
@@ -0,0 +1,8 @@
namespace Wino.Core.Domain.Enums;
public enum ThreeButtonDialogResult
{
Primary,
Secondary,
Cancel
}
@@ -3,8 +3,8 @@
public interface IAuthenticatorConfig public interface IAuthenticatorConfig
{ {
string OutlookAuthenticatorClientId { get; } string OutlookAuthenticatorClientId { get; }
string[] OutlookScope { get; } string[] GetOutlookScope(bool isMailAccessGranted, bool isCalendarAccessGranted);
string GmailAuthenticatorClientId { get; } string GmailAuthenticatorClientId { get; }
string[] GmailScope { get; } string[] GetGmailScope(bool isMailAccessGranted, bool isCalendarAccessGranted);
string GmailTokenStoreIdentifier { get; } string GmailTokenStoreIdentifier { get; }
} }
@@ -2,6 +2,8 @@
public interface IConfigurationService public interface IConfigurationService
{ {
bool Contains(string key);
void Set(string key, object value); void Set(string key, object value);
T Get<T>(string key, T defaultValue = default); T Get<T>(string key, T defaultValue = default);
@@ -23,6 +23,7 @@ public interface IMailCategoryService
Task AssignCategoryAsync(Guid categoryId, IEnumerable<Guid> mailCopyUniqueIds); Task AssignCategoryAsync(Guid categoryId, IEnumerable<Guid> mailCopyUniqueIds);
Task UnassignCategoryAsync(Guid categoryId, IEnumerable<Guid> mailCopyUniqueIds); Task UnassignCategoryAsync(Guid categoryId, IEnumerable<Guid> mailCopyUniqueIds);
Task<List<MailCategory>> GetCategoriesForMailAsync(Guid accountId, IEnumerable<Guid> mailCopyUniqueIds); Task<List<MailCategory>> GetCategoriesForMailAsync(Guid accountId, IEnumerable<Guid> mailCopyUniqueIds);
Task<IReadOnlyDictionary<Guid, IReadOnlyList<MailCategory>>> GetCategoriesByMailAsync(Guid accountId, IEnumerable<Guid> mailCopyUniqueIds);
Task<List<Guid>> GetAssignedCategoryIdsForAllAsync(IEnumerable<Guid> mailCopyUniqueIds); Task<List<Guid>> GetAssignedCategoryIdsForAllAsync(IEnumerable<Guid> mailCopyUniqueIds);
Task<List<string>> GetCategoryNamesForMailAsync(Guid mailCopyUniqueId); Task<List<string>> GetCategoryNamesForMailAsync(Guid mailCopyUniqueId);
Task<List<MailCopy>> GetMailCopiesForCategoryAsync(Guid categoryId); Task<List<MailCopy>> GetMailCopiesForCategoryAsync(Guid categoryId);
@@ -19,6 +19,12 @@ public interface IMailDialogService : IDialogServiceBase
{ {
void ShowReadOnlyCalendarMessage(); void ShowReadOnlyCalendarMessage();
Task<bool> ShowHardDeleteConfirmationAsync(); Task<bool> ShowHardDeleteConfirmationAsync();
Task<ThreeButtonDialogResult> ShowThreeButtonDialogAsync(string title,
string description,
string primaryButtonText,
string secondaryButtonText,
string cancelButtonText,
WinoCustomMessageDialogIcon? icon = null);
Task HandleSystemFolderConfigurationDialogAsync(Guid accountId, IFolderService folderService); Task HandleSystemFolderConfigurationDialogAsync(Guid accountId, IFolderService folderService);
// Custom dialogs // Custom dialogs
@@ -1,5 +1,7 @@
using System; using System;
using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Entities.Shared; using Wino.Core.Domain.Entities.Shared;
namespace Wino.Core.Domain.Interfaces; namespace Wino.Core.Domain.Interfaces;
@@ -27,4 +29,6 @@ public interface IMailItemDisplayInformation : INotifyPropertyChanged
bool HasReadReceiptTracking { get; } bool HasReadReceiptTracking { get; }
bool IsReadReceiptAcknowledged { get; } bool IsReadReceiptAcknowledged { get; }
string ReadReceiptDisplayText { get; } string ReadReceiptDisplayText { get; }
IReadOnlyList<MailCategory> Categories { get; }
bool HasCategories { get; }
} }
@@ -6,4 +6,5 @@ public interface IMailListItemSorting
{ {
DateTime SortingDate { get; } DateTime SortingDate { get; }
string SortingName { get; } string SortingName { get; }
bool IsPinned { get; }
} }
@@ -26,6 +26,7 @@ public interface IMailService
/// </summary> /// </summary>
Task<List<MailCopy>> GetMailItemsAsync(IEnumerable<string> mailCopyIds); Task<List<MailCopy>> GetMailItemsAsync(IEnumerable<string> mailCopyIds);
Task<List<MailCopy>> FetchMailsAsync(MailListInitializationOptions options, CancellationToken cancellationToken = default); Task<List<MailCopy>> FetchMailsAsync(MailListInitializationOptions options, CancellationToken cancellationToken = default);
Task<List<MailCopy>> FetchPinnedMailsAsync(MailListInitializationOptions options, CancellationToken cancellationToken = default);
/// <summary> /// <summary>
/// Deletes all mail copies for all folders. /// Deletes all mail copies for all folders.
@@ -33,14 +34,20 @@ public interface IMailService
/// <param name="accountId">Account to remove from</param> /// <param name="accountId">Account to remove from</param>
/// <param name="mailCopyId">Mail copy id to remove.</param> /// <param name="mailCopyId">Mail copy id to remove.</param>
Task DeleteMailAsync(Guid accountId, string mailCopyId); Task DeleteMailAsync(Guid accountId, string mailCopyId);
Task DeleteMailsAsync(Guid accountId, IEnumerable<string> mailCopyIds);
Task ChangeReadStatusAsync(string mailCopyId, bool isRead); Task ChangeReadStatusAsync(string mailCopyId, bool isRead);
Task ChangeFlagStatusAsync(string mailCopyId, bool isFlagged); Task ChangeFlagStatusAsync(string mailCopyId, bool isFlagged);
Task ChangePinnedStatusAsync(IEnumerable<Guid> uniqueMailIds, bool isPinned);
Task ApplyMailStateUpdatesAsync(IEnumerable<MailCopyStateUpdate> updates);
Task CreateAssignmentAsync(Guid accountId, string mailCopyId, string remoteFolderId); Task CreateAssignmentAsync(Guid accountId, string mailCopyId, string remoteFolderId);
Task DeleteAssignmentAsync(Guid accountId, string mailCopyId, string remoteFolderId); Task DeleteAssignmentAsync(Guid accountId, string mailCopyId, string remoteFolderId);
Task CreateAssignmentsAsync(Guid accountId, IEnumerable<MailFolderAssignmentUpdate> assignments);
Task DeleteAssignmentsAsync(Guid accountId, IEnumerable<MailFolderAssignmentUpdate> assignments);
Task<bool> CreateMailAsync(Guid accountId, NewMailItemPackage package); Task<bool> CreateMailAsync(Guid accountId, NewMailItemPackage package);
Task CreateMailsAsync(Guid accountId, IReadOnlyList<NewMailItemPackage> packages);
/// <summary> /// <summary>
/// Maps new mail item with the existing local draft copy. /// Maps new mail item with the existing local draft copy.
@@ -51,6 +51,11 @@ public interface INotificationBuilder
/// </summary> /// </summary>
void CreateStoreUpdateNotification(); void CreateStoreUpdateNotification();
/// <summary>
/// Shows the one-time release migration notification.
/// </summary>
void CreateReleaseMigrationNotification();
/// <summary> /// <summary>
/// Creates a calendar reminder toast for the specified calendar item. /// Creates a calendar reminder toast for the specified calendar item.
/// </summary> /// </summary>
@@ -62,6 +62,11 @@ public interface IPreferencesService : INotifyPropertyChanged
/// </summary> /// </summary>
bool IsStoreUpdateNotificationsEnabled { get; set; } bool IsStoreUpdateNotificationsEnabled { get; set; }
/// <summary>
/// Setting: Whether the system tray icon should be created while the shell is available.
/// </summary>
bool IsSystemTrayIconEnabled { get; set; }
/// <summary> /// <summary>
/// Setting: Whether the Wino account profile button in the shell title bar should be hidden. /// Setting: Whether the Wino account profile button in the shell title bar should be hidden.
/// </summary> /// </summary>
@@ -122,11 +127,21 @@ public interface IPreferencesService : INotifyPropertyChanged
/// </summary> /// </summary>
bool IsHardDeleteProtectionEnabled { get; set; } bool IsHardDeleteProtectionEnabled { get; set; }
/// <summary>
/// Setting: Show the empty-folder command for junk/spam folders.
/// </summary>
bool IsShowEmptyJunkFolderEnabled { get; set; }
/// <summary> /// <summary>
/// Setting: Thread mails into conversations. /// Setting: Thread mails into conversations.
/// </summary> /// </summary>
bool IsThreadingEnabled { get; set; } bool IsThreadingEnabled { get; set; }
/// <summary>
/// Setting: Whether the newest message in a conversation should appear first.
/// </summary>
bool IsNewestThreadMailFirst { get; set; }
/// <summary> /// <summary>
/// Setting: Show sender pictures in mail list. /// Setting: Show sender pictures in mail list.
/// </summary> /// </summary>
@@ -7,4 +7,6 @@ public record AccountCreationDialogResult(
string AccountName, string AccountName,
SpecialImapProviderDetails SpecialImapProviderDetails, SpecialImapProviderDetails SpecialImapProviderDetails,
string AccountColorHex, string AccountColorHex,
InitialSynchronizationRange InitialSynchronizationRange); InitialSynchronizationRange InitialSynchronizationRange,
bool IsMailAccessGranted,
bool IsCalendarAccessGranted);
@@ -1,10 +1,19 @@
using Wino.Core.Domain.Enums;
namespace Wino.Core.Domain.Models.Calendar; namespace Wino.Core.Domain.Models.Calendar;
public sealed class CalDavCalendar public sealed class CalDavCalendar
{ {
public string RemoteCalendarId { get; init; } = string.Empty; public string RemoteCalendarId { get; init; } = string.Empty;
public string Name { get; init; } = string.Empty; public string Name { get; init; } = string.Empty;
public string Description { get; init; } = string.Empty;
public string CTag { get; init; } = string.Empty; public string CTag { get; init; } = string.Empty;
public string SyncToken { get; init; } = string.Empty; public string SyncToken { get; init; } = string.Empty;
public string TimeZone { get; init; } = string.Empty;
public string BackgroundColorHex { get; init; } = string.Empty;
public bool IsReadOnly { get; init; }
public bool SupportsEvents { get; init; } = true;
public CalendarItemShowAs DefaultShowAs { get; init; } = CalendarItemShowAs.Busy;
public double? Order { get; init; }
} }
@@ -1,7 +1,8 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Wino.Core.Domain.Entities.Mail; using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Interfaces; using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.MailItem;
public class ListItemComparer : IComparer<object> public class ListItemComparer : IComparer<object>
{ {
@@ -9,14 +10,48 @@ public class ListItemComparer : IComparer<object>
public int Compare(object x, object y) public int Compare(object x, object y)
{ {
if (x is MailListGroupKey xGroupKey && y is MailListGroupKey yGroupKey)
{
if (xGroupKey.IsPinned != yGroupKey.IsPinned)
return yGroupKey.IsPinned.CompareTo(xGroupKey.IsPinned);
if (xGroupKey.IsPinned && yGroupKey.IsPinned)
return 0;
return CompareSortValues(xGroupKey.Value, yGroupKey.Value);
}
if (x is IMailListItemSorting xSorting && y is IMailListItemSorting ySorting) if (x is IMailListItemSorting xSorting && y is IMailListItemSorting ySorting)
return SortByName ? string.Compare(xSorting.SortingName, ySorting.SortingName, StringComparison.OrdinalIgnoreCase) : DateTime.Compare(ySorting.SortingDate, xSorting.SortingDate); {
else if (x is MailCopy xMail && y is MailCopy yMail) if (xSorting.IsPinned != ySorting.IsPinned)
return SortByName ? string.Compare(xMail.FromName, yMail.FromName, StringComparison.OrdinalIgnoreCase) : DateTime.Compare(yMail.CreationDate, xMail.CreationDate); return ySorting.IsPinned.CompareTo(xSorting.IsPinned);
else if (x is DateTime dateX && y is DateTime dateY)
return SortByName
? string.Compare(xSorting.SortingName, ySorting.SortingName, StringComparison.OrdinalIgnoreCase)
: DateTime.Compare(ySorting.SortingDate, xSorting.SortingDate);
}
if (x is MailCopy xMail && y is MailCopy yMail)
{
if (xMail.IsPinned != yMail.IsPinned)
return yMail.IsPinned.CompareTo(xMail.IsPinned);
return SortByName
? string.Compare(xMail.FromName, yMail.FromName, StringComparison.OrdinalIgnoreCase)
: DateTime.Compare(yMail.CreationDate, xMail.CreationDate);
}
return CompareSortValues(x, y);
}
private static int CompareSortValues(object x, object y)
{
if (x is DateTime dateX && y is DateTime dateY)
return DateTime.Compare(dateY, dateX); return DateTime.Compare(dateY, dateX);
else if (x is string stringX && y is string stringY)
if (x is string stringX && y is string stringY)
return stringY.CompareTo(stringX); return stringY.CompareTo(stringX);
return 0; return 0;
} }
} }
@@ -15,7 +15,7 @@ public class HtmlPreviewVisitor : MimeVisitor
{ {
private static readonly HashSet<string> BlockedTags = new(StringComparer.OrdinalIgnoreCase) private static readonly HashSet<string> BlockedTags = new(StringComparer.OrdinalIgnoreCase)
{ {
"script", "iframe", "frame", "frameset", "object", "embed", "applet", "base", "meta", "form" "script", "iframe", "frame", "frameset", "object", "embed", "applet", "base", "meta", "form", "link"
}; };
private static readonly HashSet<string> AllowedDataImageMimeTypes = new(StringComparer.OrdinalIgnoreCase) private static readonly HashSet<string> AllowedDataImageMimeTypes = new(StringComparer.OrdinalIgnoreCase)
@@ -0,0 +1,3 @@
namespace Wino.Core.Domain.Models.MailItem;
public sealed record MailCopyStateUpdate(string MailCopyId, bool? IsRead = null, bool? IsFlagged = null);
@@ -0,0 +1,3 @@
namespace Wino.Core.Domain.Models.MailItem;
public sealed record MailFolderAssignmentUpdate(string MailCopyId, string RemoteFolderId);
@@ -0,0 +1,6 @@
namespace Wino.Core.Domain.Models.MailItem;
public sealed record MailListGroupKey(bool IsPinned, object Value)
{
public static MailListGroupKey Pinned { get; } = new(true, null);
}
@@ -0,0 +1,26 @@
namespace Wino.Core.Domain.Models.Navigation;
public enum ProviderSelectionHostMode
{
Wizard,
SettingsAddAccount
}
public sealed class ProviderSelectionNavigationContext
{
public ProviderSelectionHostMode HostMode { get; init; } = ProviderSelectionHostMode.Wizard;
public static ProviderSelectionNavigationContext CreateForWizard()
=> new()
{
HostMode = ProviderSelectionHostMode.Wizard
};
public static ProviderSelectionNavigationContext CreateForSettingsAddAccount()
=> new()
{
HostMode = ProviderSelectionHostMode.SettingsAddAccount
};
public bool IsWizardHost => HostMode == ProviderSelectionHostMode.Wizard;
}
@@ -44,6 +44,6 @@ public class BatchCollection<TRequestType> : List<TRequestType>, IUIChangeReques
public BatchCollection(IEnumerable<TRequestType> collection) : base(collection) public BatchCollection(IEnumerable<TRequestType> collection) : base(collection)
{ {
} }
public void ApplyUIChanges() => ForEach(x => x.ApplyUIChanges()); public virtual void ApplyUIChanges() => ForEach(x => x.ApplyUIChanges());
public void RevertUIChanges() => ForEach(x => x.RevertUIChanges()); public virtual void RevertUIChanges() => ForEach(x => x.RevertUIChanges());
} }
@@ -141,7 +141,9 @@ public static class SettingsNavigationInfoProvider
public static SettingsNavigationItemInfo GetInfo(WinoPage pageType, string manageAccountsDescription = "") public static SettingsNavigationItemInfo GetInfo(WinoPage pageType, string manageAccountsDescription = "")
{ {
var rootPage = GetRootPage(pageType); var rootPage = GetRootPage(pageType);
return GetNavigationItems(manageAccountsDescription).First(item => item.PageType == rootPage); return GetNavigationItems(manageAccountsDescription)
.FirstOrDefault(item => item.PageType == rootPage)
?? GetNavigationItems(manageAccountsDescription).First(item => item.PageType == WinoPage.SettingOptionsPage);
} }
public static string GetPageTitle(WinoPage pageType) public static string GetPageTitle(WinoPage pageType)
@@ -180,6 +182,9 @@ public static class SettingsNavigationInfoProvider
WinoPage.MailCategoryManagementPage => WinoPage.ManageAccountsPage, WinoPage.MailCategoryManagementPage => WinoPage.ManageAccountsPage,
WinoPage.SignatureManagementPage => WinoPage.ManageAccountsPage, WinoPage.SignatureManagementPage => WinoPage.ManageAccountsPage,
WinoPage.ImapCalDavSettingsPage => WinoPage.ManageAccountsPage, WinoPage.ImapCalDavSettingsPage => WinoPage.ManageAccountsPage,
WinoPage.ProviderSelectionPage => WinoPage.ManageAccountsPage,
WinoPage.SpecialImapCredentialsPage => WinoPage.ManageAccountsPage,
WinoPage.AccountSetupProgressPage => WinoPage.ManageAccountsPage,
WinoPage.CreateEmailTemplatePage => WinoPage.EmailTemplatesPage, WinoPage.CreateEmailTemplatePage => WinoPage.EmailTemplatesPage,
WinoPage.CalendarSettingsPage => WinoPage.CalendarPreferenceSettingsPage, WinoPage.CalendarSettingsPage => WinoPage.CalendarPreferenceSettingsPage,
WinoPage.CalendarAccountSettingsPage => WinoPage.CalendarPreferenceSettingsPage, WinoPage.CalendarAccountSettingsPage => WinoPage.CalendarPreferenceSettingsPage,
@@ -45,6 +45,7 @@ public class WinoTranslationDictionary : Dictionary<string, string>
AppLanguage.Greek => "el_GR", AppLanguage.Greek => "el_GR",
AppLanguage.PortugeseBrazil => "pt_BR", AppLanguage.PortugeseBrazil => "pt_BR",
AppLanguage.Romanian => "ro_RO", AppLanguage.Romanian => "ro_RO",
AppLanguage.Korean => "ko_KR",
_ => "en_US", _ => "en_US",
}; };
} }
@@ -47,6 +47,11 @@
"AccountDetailsPage_CalendarListDescription": "Изберете календар, за да конфигурирате неговите настройки.", "AccountDetailsPage_CalendarListDescription": "Изберете календар, за да конфигурирате неговите настройки.",
"AccountDetailsPage_InitialSynchronization_Title": "Начална синхронизация", "AccountDetailsPage_InitialSynchronization_Title": "Начална синхронизация",
"AccountDetailsPage_InitialSynchronization_Description": "Wino синхронизира вашите имейли до {0} назад.", "AccountDetailsPage_InitialSynchronization_Description": "Wino синхронизира вашите имейли до {0} назад.",
"AccountDetailsPage_CapabilityTitle": "Свързани функции",
"AccountDetailsPage_CapabilityDescription": "Изберете дали този акаунт да се използва за поща, календар или и двете. Активирането на нова функция може да ви подтикне да се впишете отново.",
"AccountCapability_MailOnly": "Само поща",
"AccountCapability_CalendarOnly": "Само календар",
"AccountCapability_MailAndCalendar": "Поща и календар",
"AddHyperlink": "Добавяне", "AddHyperlink": "Добавяне",
"AppCloseBackgroundSynchronizationWarningTitle": "Синхронизация на заден план", "AppCloseBackgroundSynchronizationWarningTitle": "Синхронизация на заден план",
"AppCloseStartupLaunchDisabledWarningMessageFirstLine": "Приложението не е настроено да се стартира при стартиране на Windows.", "AppCloseStartupLaunchDisabledWarningMessageFirstLine": "Приложението не е настроено да се стартира при стартиране на Windows.",
@@ -76,6 +81,7 @@
"Buttons_ApplyTheme": "Прилагане на темата", "Buttons_ApplyTheme": "Прилагане на темата",
"Buttons_PopOut": "Извън прозореца", "Buttons_PopOut": "Извън прозореца",
"Buttons_Browse": "Преглед", "Buttons_Browse": "Преглед",
"Buttons_Back": "Назад",
"Buttons_Cancel": "Отказ", "Buttons_Cancel": "Отказ",
"Buttons_Close": "Затваряне", "Buttons_Close": "Затваряне",
"Buttons_Copy": "Копиране", "Buttons_Copy": "Копиране",
@@ -299,6 +305,8 @@
"DialogMessage_DeleteRecurringSeriesTitle": "Изтриване на повтаряща се серия", "DialogMessage_DeleteRecurringSeriesTitle": "Изтриване на повтаряща се серия",
"DialogMessage_DiscardDraftConfirmationMessage": "Тази чернова ще бъде отхвърлена. Искате ли да продължите?", "DialogMessage_DiscardDraftConfirmationMessage": "Тази чернова ще бъде отхвърлена. Искате ли да продължите?",
"DialogMessage_DiscardDraftConfirmationTitle": "Отхвърляне на черновата", "DialogMessage_DiscardDraftConfirmationTitle": "Отхвърляне на черновата",
"DialogMessage_CloseDraftWindowConfirmationMessage": "Черновикът все още е отворен. Запазете го преди да затворите прозореца?",
"DialogMessage_CloseDraftWindowConfirmationTitle": "Затвори прозореца",
"DialogMessage_EmptySubjectConfirmation": "Липсваща тема", "DialogMessage_EmptySubjectConfirmation": "Липсваща тема",
"DialogMessage_EmptySubjectConfirmationMessage": "Съобщението няма тема. Искате ли да продължите?", "DialogMessage_EmptySubjectConfirmationMessage": "Съобщението няма тема. Искате ли да продължите?",
"DialogMessage_EnableStartupLaunchDeniedMessage": "Можете да активирате автоматично стартиране от Настройки -> Предпочитания за приложението.", "DialogMessage_EnableStartupLaunchDeniedMessage": "Можете да активирате автоматично стартиране от Настройки -> Предпочитания за приложението.",
@@ -681,6 +689,10 @@
"NoMailSelected": "Не е избрано съобщение", "NoMailSelected": "Не е избрано съобщение",
"NoMessageCrieteria": "Няма съобщения, които да отговарят на критериите ви за търсене", "NoMessageCrieteria": "Няма съобщения, които да отговарят на критериите ви за търсене",
"NoMessageEmptyFolder": "Тази папка е празна", "NoMessageEmptyFolder": "Тази папка е празна",
"MailEmptyState_Title": "Няма акаунти за поща",
"MailEmptyState_Message": "Имате свързани акаунти за календар, но нито един от тях не е активен за поща. Добавете акаунт за поща или обновете съществуващ акаунт, за да използва поща.",
"MailEmptyState_AddAccount": "Добави акаунт",
"MailEmptyState_ManageAccounts": "Управление на акаунти",
"Notifications_MultipleNotificationsMessage": "Имате {0} нови съобщения.", "Notifications_MultipleNotificationsMessage": "Имате {0} нови съобщения.",
"Notifications_MultipleNotificationsTitle": "Нов имейл", "Notifications_MultipleNotificationsTitle": "Нов имейл",
"Notifications_WinoUpdatedMessage": "Вижте новата версия {0}", "Notifications_WinoUpdatedMessage": "Вижте новата версия {0}",
@@ -824,6 +836,8 @@
"SettingsDeleteAccount_Title": "Изтриване на този акаунт", "SettingsDeleteAccount_Title": "Изтриване на този акаунт",
"SettingsDeleteProtection_Description": "Should Wino ask you for confirmation every time you try to permanently delete a mail using Shift + Del keys?", "SettingsDeleteProtection_Description": "Should Wino ask you for confirmation every time you try to permanently delete a mail using Shift + Del keys?",
"SettingsDeleteProtection_Title": "Защита от окончателно изтриване", "SettingsDeleteProtection_Title": "Защита от окончателно изтриване",
"SettingsEmptyJunkFolderCommand_Description": "Покажи командата за изпразване на папка в папките Спам. Това действие няма да изисква потвърждение и ще изтрие всички имейли в папката за спам веднага.",
"SettingsEmptyJunkFolderCommand_Title": "Покажи командата за изпразване на папка Спам",
"SettingsDiagnostics_Description": "За разработчици", "SettingsDiagnostics_Description": "За разработчици",
"SettingsDiagnostics_DiagnosticId_Description": "Споделете този идентификационен номер с разработчиците, когато ви помолят, за да получите помощ за проблемите, с които се сблъсквате в Wino Mail.", "SettingsDiagnostics_DiagnosticId_Description": "Споделете този идентификационен номер с разработчиците, когато ви помолят, за да получите помощ за проблемите, с които се сблъсквате в Wino Mail.",
"SettingsDiagnostics_DiagnosticId_Title": "Идентификатор за диагностика", "SettingsDiagnostics_DiagnosticId_Title": "Идентификатор за диагностика",
@@ -1074,6 +1088,12 @@
"SettingsTaskbarBadge_Title": "Значка на лентата на задачите", "SettingsTaskbarBadge_Title": "Значка на лентата на задачите",
"SettingsThreads_Description": "Организиране на съобщенията в разговори.", "SettingsThreads_Description": "Организиране на съобщенията в разговори.",
"SettingsThreads_Title": "Групиране в разговори", "SettingsThreads_Title": "Групиране в разговори",
"SettingsThreads_Enabled_Description": "Групирайте свързаните съобщения в един разговор.",
"SettingsThreads_Enabled_Title": "Включване на групиране на разговорите по нишки",
"SettingsThreadOrder_Description": "Изберете как се подреждат елементите в разговорната нишка.",
"SettingsThreadOrder_Title": "Подреждане на елементи в нишката",
"SettingsThreadOrder_LastItemFirst": "Последният елемент първо",
"SettingsThreadOrder_FirstItemFirst": "Първият елемент първо",
"SettingsUnlinkAccounts_Description": "Премахване на връзката между акаунтите. Това няма да доведе до изтриване на акаунтите ви.", "SettingsUnlinkAccounts_Description": "Премахване на връзката между акаунтите. Това няма да доведе до изтриване на акаунтите ви.",
"SettingsUnlinkAccounts_Title": "Премахване на връзката между акаунтите", "SettingsUnlinkAccounts_Title": "Премахване на връзката между акаунтите",
"SettingsMailRendering_ActionLabels_Title": "Action labels", "SettingsMailRendering_ActionLabels_Title": "Action labels",
@@ -1339,6 +1359,7 @@
"WelcomeWindow_GetStartedButton": "Добави акаунт", "WelcomeWindow_GetStartedButton": "Добави акаунт",
"WelcomeWindow_GetStartedDescription": "Добавете своя акаунт Outlook, Gmail или IMAP, за да започнете с Wino Mail.", "WelcomeWindow_GetStartedDescription": "Добавете своя акаунт Outlook, Gmail или IMAP, за да започнете с Wino Mail.",
"WelcomeWindow_ImportFromWinoAccount": "Импортирайте от вашия Wino акаунт.", "WelcomeWindow_ImportFromWinoAccount": "Импортирайте от вашия Wino акаунт.",
"WelcomeWindow_ImportFromJsonFile": "Импортирай от JSON файл",
"WelcomeWindow_ImportInProgress": "Импортиране на синхронизирани настройки и акаунти...", "WelcomeWindow_ImportInProgress": "Импортиране на синхронизирани настройки и акаунти...",
"WelcomeWindow_ImportNoAccountsFound": "Не са намерени синхронизирани акаунти във вашия Wino акаунт. Ако имаше налични настройки, те са възстановени. Използвайте Започнете, за да добавите акаунт ръчно.", "WelcomeWindow_ImportNoAccountsFound": "Не са намерени синхронизирани акаунти във вашия Wino акаунт. Ако имаше налични настройки, те са възстановени. Използвайте Започнете, за да добавите акаунт ръчно.",
"WelcomeWindow_ImportDuplicateAccountsSkipped": "{0} синхронизирани акаунти вече са налични на това устройство. Ако е необходимо, използвайте Започнете, за да добавите още акаунт ръчно.", "WelcomeWindow_ImportDuplicateAccountsSkipped": "{0} синхронизирани акаунти вече са налични на това устройство. Ако е необходимо, използвайте Започнете, за да добавите още акаунт ръчно.",
@@ -1418,6 +1439,12 @@
"WinoAccount_Management_ExportDialog_AccountsDisclaimer": "Паролите, токените и друга чувствителна информация не се синхронират.", "WinoAccount_Management_ExportDialog_AccountsDisclaimer": "Паролите, токените и друга чувствителна информация не се синхронират.",
"WinoAccount_Management_ExportDialog_AccountsRelogin": "Импортираните акаунти на друг компютър ще трябва да влезете отново, преди да могат да се използват.", "WinoAccount_Management_ExportDialog_AccountsRelogin": "Импортираните акаунти на друг компютър ще трябва да влезете отново, преди да могат да се използват.",
"WinoAccount_Management_ExportDialog_InProgress": "Експортът на избраните от вас Wino данни...", "WinoAccount_Management_ExportDialog_InProgress": "Експортът на избраните от вас Wino данни...",
"WinoAccount_Management_LocalDataSectionTitle": "Прехвърляне с JSON файл",
"WinoAccount_Management_LocalDataSectionDescription": "Импортирайте от или експортирайте към локален JSON файл. Пароли, токени и друга чувствителна информация не са включени.",
"WinoAccount_Management_LocalDataImportAction": "Импортиране",
"WinoAccount_Management_LocalDataExportAction": "Експортиране",
"WinoAccount_Management_LocalDataSaved": "Запазихте експортираните данни на Wino в {0}.",
"WinoAccount_Management_LocalDataInvalidFile": "Избраният JSON файл не съдържа валиден Wino експорт.",
"WinoAccount_Management_LoadFailed": "Wino не успя да зареди най-новата информация за Wino акаунта.", "WinoAccount_Management_LoadFailed": "Wino не успя да зареди най-новата информация за Wino акаунта.",
"WinoAccount_Management_ActionFailed": "Заявката за Wino акаунт не може да бъде завършена.", "WinoAccount_Management_ActionFailed": "Заявката за Wino акаунт не може да бъде завършена.",
"WinoAccount_SettingsSection_Title": "Wino акаунт", "WinoAccount_SettingsSection_Title": "Wino акаунт",
@@ -1514,8 +1541,22 @@
"WelcomeWizard_Step3Title": "Завършване на настройката", "WelcomeWizard_Step3Title": "Завършване на настройката",
"ProviderSelection_Title": "Изберете вашия имейл доставчик", "ProviderSelection_Title": "Изберете вашия имейл доставчик",
"ProviderSelection_Subtitle": "Изберете доставчик по-долу, за да добавите вашия имейл акаунт към Wino Mail.", "ProviderSelection_Subtitle": "Изберете доставчик по-долу, за да добавите вашия имейл акаунт към Wino Mail.",
"ProviderSelection_StepProgress": "Стъпка {0} от 3",
"ProviderSelection_IdentityTitle": "Идентичност на акаунта",
"ProviderSelection_IdentityDescription": "Изберете как тази акаунт се появява във Wino.",
"ProviderSelection_ProviderSectionTitle": "Провайдер",
"ProviderSelection_ProviderSectionDescription": "Изберете услугата, която искате да свържете.",
"ProviderSelection_CapabilitySectionTitle": "Използвайте този акаунт за",
"ProviderSelection_CapabilitySectionDescription": "Изберете дали искате поща, календар или и двете.",
"ProviderSelection_CapabilityProviderDescription_OAuth": "В следващата стъпка сигурното вписване ще свърже акаунта ви. Ако активирате календар, Wino ще свърже автоматично Outlook Calendar или Google Calendar.",
"ProviderSelection_CapabilityProviderDescription_SpecialImap": "В следващата стъпка ще въведете идентификационните данни за доставчика. Пощата използва IMAP/SMTP, а календарът може да използва CalDAV или да остане локално на това устройство.",
"ProviderSelection_CapabilityProviderDescription_CustomServer": "В следващата стъпка ще въведете данните за сървъра си. Пощата използва IMAP/SMTP, а календарът може да използва CalDAV или да остане локално на това устройство.",
"ProviderSelection_AccountNameHeader": "Име на акаунт", "ProviderSelection_AccountNameHeader": "Име на акаунт",
"ProviderSelection_AccountNamePlaceholder": "напр. Personal, Work", "ProviderSelection_AccountNamePlaceholder": "напр. Personal, Work",
"ProviderSelection_UseForMail": "Поща",
"ProviderSelection_UseForCalendar": "Календар",
"ProviderSelection_CapabilityValidationMessage": "Изберете поне една възможност преди да продължите.",
"ProviderSelection_CalendarOnlyServerHint": "Ако продължите само с календар, следващата страница няма да изисква имейл адрес.",
"ProviderSelection_DisplayNameHeader": "Име за показване", "ProviderSelection_DisplayNameHeader": "Име за показване",
"ProviderSelection_DisplayNamePlaceholder": "напр. John Doe", "ProviderSelection_DisplayNamePlaceholder": "напр. John Doe",
"ProviderSelection_EmailHeader": "Имейл адрес", "ProviderSelection_EmailHeader": "Имейл адрес",
@@ -47,6 +47,11 @@
"AccountDetailsPage_CalendarListDescription": "Selecciona un calendari per configurar la seva configuració.", "AccountDetailsPage_CalendarListDescription": "Selecciona un calendari per configurar la seva configuració.",
"AccountDetailsPage_InitialSynchronization_Title": "Sincronització inicial", "AccountDetailsPage_InitialSynchronization_Title": "Sincronització inicial",
"AccountDetailsPage_InitialSynchronization_Description": "Wino ha sincronitzat els teus correus fins a {0} enrere.", "AccountDetailsPage_InitialSynchronization_Description": "Wino ha sincronitzat els teus correus fins a {0} enrere.",
"AccountDetailsPage_CapabilityTitle": "Característiques connectades",
"AccountDetailsPage_CapabilityDescription": "Trieu si aquest compte s'utilitza per a correu, calendari o tots dos. Habilitar una nova funció pot exigir que tornis a iniciar sessió.",
"AccountCapability_MailOnly": "Només correu",
"AccountCapability_CalendarOnly": "Només calendari",
"AccountCapability_MailAndCalendar": "Correu i Calendari",
"AddHyperlink": "Add", "AddHyperlink": "Add",
"AppCloseBackgroundSynchronizationWarningTitle": "Background Synchronization", "AppCloseBackgroundSynchronizationWarningTitle": "Background Synchronization",
"AppCloseStartupLaunchDisabledWarningMessageFirstLine": "Application has not been set to launch on Windows startup.", "AppCloseStartupLaunchDisabledWarningMessageFirstLine": "Application has not been set to launch on Windows startup.",
@@ -76,6 +81,7 @@
"Buttons_ApplyTheme": "Apply Theme", "Buttons_ApplyTheme": "Apply Theme",
"Buttons_PopOut": "Obrir en una finestra separada", "Buttons_PopOut": "Obrir en una finestra separada",
"Buttons_Browse": "Browse", "Buttons_Browse": "Browse",
"Buttons_Back": "Enrere",
"Buttons_Cancel": "Cancel", "Buttons_Cancel": "Cancel",
"Buttons_Close": "Close", "Buttons_Close": "Close",
"Buttons_Copy": "Copy", "Buttons_Copy": "Copy",
@@ -299,6 +305,8 @@
"DialogMessage_DeleteRecurringSeriesTitle": "Eliminar sèrie recurrent", "DialogMessage_DeleteRecurringSeriesTitle": "Eliminar sèrie recurrent",
"DialogMessage_DiscardDraftConfirmationMessage": "This draft will be discarded. Do you want to continue?", "DialogMessage_DiscardDraftConfirmationMessage": "This draft will be discarded. Do you want to continue?",
"DialogMessage_DiscardDraftConfirmationTitle": "Discard Draft", "DialogMessage_DiscardDraftConfirmationTitle": "Discard Draft",
"DialogMessage_CloseDraftWindowConfirmationMessage": "Encara hi ha un esborrany obert. Desa'l abans de tancar la finestra?",
"DialogMessage_CloseDraftWindowConfirmationTitle": "Tanca la finestra",
"DialogMessage_EmptySubjectConfirmation": "Missing Subject", "DialogMessage_EmptySubjectConfirmation": "Missing Subject",
"DialogMessage_EmptySubjectConfirmationMessage": "Message has no subject. Do you want to continue?", "DialogMessage_EmptySubjectConfirmationMessage": "Message has no subject. Do you want to continue?",
"DialogMessage_EnableStartupLaunchDeniedMessage": "You can enable startup launch from Settings -> App Preferences.", "DialogMessage_EnableStartupLaunchDeniedMessage": "You can enable startup launch from Settings -> App Preferences.",
@@ -681,6 +689,10 @@
"NoMailSelected": "No message selected", "NoMailSelected": "No message selected",
"NoMessageCrieteria": "No messages match your search criteria", "NoMessageCrieteria": "No messages match your search criteria",
"NoMessageEmptyFolder": "This folder is empty", "NoMessageEmptyFolder": "This folder is empty",
"MailEmptyState_Title": "No hi ha cap compte habilitat per al correu",
"MailEmptyState_Message": "Tens comptes connectats per al calendari, però cap d'ells està habilitat per al correu. Afegeix un compte de correu o actualitza un compte existent per utilitzar el correu.",
"MailEmptyState_AddAccount": "Afegeix un compte",
"MailEmptyState_ManageAccounts": "Gestiona els comptes",
"Notifications_MultipleNotificationsMessage": "You have {0} new messages.", "Notifications_MultipleNotificationsMessage": "You have {0} new messages.",
"Notifications_MultipleNotificationsTitle": "New Mail", "Notifications_MultipleNotificationsTitle": "New Mail",
"Notifications_WinoUpdatedMessage": "Checkout new version {0}", "Notifications_WinoUpdatedMessage": "Checkout new version {0}",
@@ -824,6 +836,8 @@
"SettingsDeleteAccount_Title": "Delete this account", "SettingsDeleteAccount_Title": "Delete this account",
"SettingsDeleteProtection_Description": "Should Wino ask you for confirmation every time you try to permanently delete a mail using Shift + Del keys?", "SettingsDeleteProtection_Description": "Should Wino ask you for confirmation every time you try to permanently delete a mail using Shift + Del keys?",
"SettingsDeleteProtection_Title": "Permanent Delete Protection", "SettingsDeleteProtection_Title": "Permanent Delete Protection",
"SettingsEmptyJunkFolderCommand_Description": "Mostra la comanda per buidar la carpeta de correu brossa. Aquesta acció no demanarà confirmació i eliminarà immediatament tots els correus de la carpeta de correu brossa.",
"SettingsEmptyJunkFolderCommand_Title": "Mostra la comanda per buidar la carpeta de correu brossa",
"SettingsDiagnostics_Description": "For developers", "SettingsDiagnostics_Description": "For developers",
"SettingsDiagnostics_DiagnosticId_Description": "Share this ID with the developers when asked to get help for the issues you experience in Wino Mail.", "SettingsDiagnostics_DiagnosticId_Description": "Share this ID with the developers when asked to get help for the issues you experience in Wino Mail.",
"SettingsDiagnostics_DiagnosticId_Title": "Diagnostic ID", "SettingsDiagnostics_DiagnosticId_Title": "Diagnostic ID",
@@ -1074,6 +1088,12 @@
"SettingsTaskbarBadge_Title": "Taskbar Badge", "SettingsTaskbarBadge_Title": "Taskbar Badge",
"SettingsThreads_Description": "Organize messages into conversation threads.", "SettingsThreads_Description": "Organize messages into conversation threads.",
"SettingsThreads_Title": "Conversation Threading", "SettingsThreads_Title": "Conversation Threading",
"SettingsThreads_Enabled_Description": "Agrupa els missatges relacionats en una única conversa.",
"SettingsThreads_Enabled_Title": "Activa el fil de converses",
"SettingsThreadOrder_Description": "Trieu com s'ordenen els elements dins d'un fil de conversa.",
"SettingsThreadOrder_Title": "Ordenació d'elements del fil de conversa",
"SettingsThreadOrder_LastItemFirst": "Últim element primer",
"SettingsThreadOrder_FirstItemFirst": "Primer element primer",
"SettingsUnlinkAccounts_Description": "Remove the link between accounts. his will not delete your accounts.", "SettingsUnlinkAccounts_Description": "Remove the link between accounts. his will not delete your accounts.",
"SettingsUnlinkAccounts_Title": "Unlink Accounts", "SettingsUnlinkAccounts_Title": "Unlink Accounts",
"SettingsMailRendering_ActionLabels_Title": "Action labels", "SettingsMailRendering_ActionLabels_Title": "Action labels",
@@ -1339,6 +1359,7 @@
"WelcomeWindow_GetStartedButton": "Comença afegint un compte", "WelcomeWindow_GetStartedButton": "Comença afegint un compte",
"WelcomeWindow_GetStartedDescription": "Afegeix el teu compte de Outlook, Gmail o IMAP per començar a utilitzar Wino Mail.", "WelcomeWindow_GetStartedDescription": "Afegeix el teu compte de Outlook, Gmail o IMAP per començar a utilitzar Wino Mail.",
"WelcomeWindow_ImportFromWinoAccount": "Importa des del teu compte Wino.", "WelcomeWindow_ImportFromWinoAccount": "Importa des del teu compte Wino.",
"WelcomeWindow_ImportFromJsonFile": "Importa des d'un fitxer JSON",
"WelcomeWindow_ImportInProgress": "S'importen les teves preferències i comptes sincronitzats.", "WelcomeWindow_ImportInProgress": "S'importen les teves preferències i comptes sincronitzats.",
"WelcomeWindow_ImportNoAccountsFound": "No s'han trobat comptes sincronitzats al teu compte Wino. Si hi havia preferències disponibles, s'han restaurat. Utilitza Comença per afegir un compte manualment.", "WelcomeWindow_ImportNoAccountsFound": "No s'han trobat comptes sincronitzats al teu compte Wino. Si hi havia preferències disponibles, s'han restaurat. Utilitza Comença per afegir un compte manualment.",
"WelcomeWindow_ImportDuplicateAccountsSkipped": "{0} comptes sincronitzats ja estan disponibles en aquest dispositiu. Utilitza Comença per afegir un altre compte manualment si és necessari.", "WelcomeWindow_ImportDuplicateAccountsSkipped": "{0} comptes sincronitzats ja estan disponibles en aquest dispositiu. Utilitza Comença per afegir un altre compte manualment si és necessari.",
@@ -1418,6 +1439,12 @@
"WinoAccount_Management_ExportDialog_AccountsDisclaimer": "Contrasenyes, tokens i altra informació sensible no es sincronitzen.", "WinoAccount_Management_ExportDialog_AccountsDisclaimer": "Contrasenyes, tokens i altra informació sensible no es sincronitzen.",
"WinoAccount_Management_ExportDialog_AccountsRelogin": "Els comptes importats en un altre PC encara necessitaran que inicis sessió de nou abans de poder utilitzar-los.", "WinoAccount_Management_ExportDialog_AccountsRelogin": "Els comptes importats en un altre PC encara necessitaran que inicis sessió de nou abans de poder utilitzar-los.",
"WinoAccount_Management_ExportDialog_InProgress": "S'està exportant les teves dades de Wino seleccionades.", "WinoAccount_Management_ExportDialog_InProgress": "S'està exportant les teves dades de Wino seleccionades.",
"WinoAccount_Management_LocalDataSectionTitle": "Transferir amb un fitxer JSON",
"WinoAccount_Management_LocalDataSectionDescription": "Importa des d'un fitxer JSON local o exporta a un fitxer JSON local. Contrasenyes, tokens i altra informació sensible no s'inclou.",
"WinoAccount_Management_LocalDataImportAction": "Importa",
"WinoAccount_Management_LocalDataExportAction": "Exporta",
"WinoAccount_Management_LocalDataSaved": "Les teves dades exportades de Wino s'han desat a {0}.",
"WinoAccount_Management_LocalDataInvalidFile": "El fitxer JSON seleccionat no conté una exportació vàlida de Wino.",
"WinoAccount_Management_LoadFailed": "No s'ha pogut carregar la darrera informació del compte Wino.", "WinoAccount_Management_LoadFailed": "No s'ha pogut carregar la darrera informació del compte Wino.",
"WinoAccount_Management_ActionFailed": "La sol·licitud del compte Wino no s'ha pogut completar.", "WinoAccount_Management_ActionFailed": "La sol·licitud del compte Wino no s'ha pogut completar.",
"WinoAccount_SettingsSection_Title": "Compte Wino", "WinoAccount_SettingsSection_Title": "Compte Wino",
@@ -1514,8 +1541,22 @@
"WelcomeWizard_Step3Title": "Finalitza la configuració", "WelcomeWizard_Step3Title": "Finalitza la configuració",
"ProviderSelection_Title": "Trieu el vostre proveïdor de correu electrònic", "ProviderSelection_Title": "Trieu el vostre proveïdor de correu electrònic",
"ProviderSelection_Subtitle": "Seleccioneu un proveïdor a continuació per afegir el vostre compte de correu a Wino Mail.", "ProviderSelection_Subtitle": "Seleccioneu un proveïdor a continuació per afegir el vostre compte de correu a Wino Mail.",
"ProviderSelection_StepProgress": "Pas {0} de 3",
"ProviderSelection_IdentityTitle": "Identitat del compte",
"ProviderSelection_IdentityDescription": "Trieu com apareix aquest compte dins de Wino.",
"ProviderSelection_ProviderSectionTitle": "Proveïdor",
"ProviderSelection_ProviderSectionDescription": "Trieu el servei que voleu connectar.",
"ProviderSelection_CapabilitySectionTitle": "Utilitza aquest compte per a",
"ProviderSelection_CapabilitySectionDescription": "Trieu si vols correu, calendar, o tots dos.",
"ProviderSelection_CapabilityProviderDescription_OAuth": "En el pròxim pas, l'inici de sessió segur connectarà el vostre compte. Si activeu el calendari, Wino també connectarà automàticament Outlook Calendar o Google Calendar.",
"ProviderSelection_CapabilityProviderDescription_SpecialImap": "En el proper pas, introduïu les vostres credencials del proveïdor. El correu fa servir IMAP/SMTP, i el calendari pot utilitzar CalDAV o quedar-se local en aquest dispositiu.",
"ProviderSelection_CapabilityProviderDescription_CustomServer": "En el proper pas, introduïu les dades del vostre servidor. El correu fa servir IMAP/SMTP, i el calendari pot utilitzar CalDAV o quedar-se local en aquest dispositiu.",
"ProviderSelection_AccountNameHeader": "Nom del compte", "ProviderSelection_AccountNameHeader": "Nom del compte",
"ProviderSelection_AccountNamePlaceholder": "p. ex. Personal, Treball", "ProviderSelection_AccountNamePlaceholder": "p. ex. Personal, Treball",
"ProviderSelection_UseForMail": "Correu",
"ProviderSelection_UseForCalendar": "Calendari",
"ProviderSelection_CapabilityValidationMessage": "Trieu almenys una capacitat abans de continuar.",
"ProviderSelection_CalendarOnlyServerHint": "Si continues amb només el calendari, la següent pàgina no requerirà una adreça de correu.",
"ProviderSelection_DisplayNameHeader": "Nom a mostrar", "ProviderSelection_DisplayNameHeader": "Nom a mostrar",
"ProviderSelection_DisplayNamePlaceholder": "p. ex. John Doe", "ProviderSelection_DisplayNamePlaceholder": "p. ex. John Doe",
"ProviderSelection_EmailHeader": "Adreça de correu electrònic", "ProviderSelection_EmailHeader": "Adreça de correu electrònic",
@@ -47,6 +47,11 @@
"AccountDetailsPage_CalendarListDescription": "Vyberte kalendář pro konfiguraci jeho nastavení.", "AccountDetailsPage_CalendarListDescription": "Vyberte kalendář pro konfiguraci jeho nastavení.",
"AccountDetailsPage_InitialSynchronization_Title": "První synchronizace", "AccountDetailsPage_InitialSynchronization_Title": "První synchronizace",
"AccountDetailsPage_InitialSynchronization_Description": "Wino synchronizoval vaše e-maily až do {0}.", "AccountDetailsPage_InitialSynchronization_Description": "Wino synchronizoval vaše e-maily až do {0}.",
"AccountDetailsPage_CapabilityTitle": "Připojené funkce",
"AccountDetailsPage_CapabilityDescription": "Vyberte, zda se tento účet použije pro poštu, kalendář nebo obojí. Aktivace nové funkce může vyžadovat opětovné přihlášení.",
"AccountCapability_MailOnly": "Pouze pošta",
"AccountCapability_CalendarOnly": "Pouze kalendář",
"AccountCapability_MailAndCalendar": "Pošta a Kalendář",
"AddHyperlink": "Přidat", "AddHyperlink": "Přidat",
"AppCloseBackgroundSynchronizationWarningTitle": "Synchronizace na pozadí", "AppCloseBackgroundSynchronizationWarningTitle": "Synchronizace na pozadí",
"AppCloseStartupLaunchDisabledWarningMessageFirstLine": "Application has not been set to launch on Windows startup.", "AppCloseStartupLaunchDisabledWarningMessageFirstLine": "Application has not been set to launch on Windows startup.",
@@ -76,6 +81,7 @@
"Buttons_ApplyTheme": "Použít motiv", "Buttons_ApplyTheme": "Použít motiv",
"Buttons_PopOut": "Otevřít v novém okně", "Buttons_PopOut": "Otevřít v novém okně",
"Buttons_Browse": "Procházet", "Buttons_Browse": "Procházet",
"Buttons_Back": "Zpět",
"Buttons_Cancel": "Zrušit", "Buttons_Cancel": "Zrušit",
"Buttons_Close": "Zavřít", "Buttons_Close": "Zavřít",
"Buttons_Copy": "Kopírovat", "Buttons_Copy": "Kopírovat",
@@ -299,6 +305,8 @@
"DialogMessage_DeleteRecurringSeriesTitle": "Smazat opakující se sérii", "DialogMessage_DeleteRecurringSeriesTitle": "Smazat opakující se sérii",
"DialogMessage_DiscardDraftConfirmationMessage": "Tento koncept bude zahozen. Chcete pokračovat?", "DialogMessage_DiscardDraftConfirmationMessage": "Tento koncept bude zahozen. Chcete pokračovat?",
"DialogMessage_DiscardDraftConfirmationTitle": "Zahodit koncept", "DialogMessage_DiscardDraftConfirmationTitle": "Zahodit koncept",
"DialogMessage_CloseDraftWindowConfirmationMessage": "Rozpracovaný návrh je stále otevřený. Chcete jej před zavřením okna uložit?",
"DialogMessage_CloseDraftWindowConfirmationTitle": "Zavřít okno",
"DialogMessage_EmptySubjectConfirmation": "Chybějící Předmět", "DialogMessage_EmptySubjectConfirmation": "Chybějící Předmět",
"DialogMessage_EmptySubjectConfirmationMessage": "Zpráva nemá Předmět. Chcete pokračovat?", "DialogMessage_EmptySubjectConfirmationMessage": "Zpráva nemá Předmět. Chcete pokračovat?",
"DialogMessage_EnableStartupLaunchDeniedMessage": "You can enable startup launch from Settings -> App Preferences.", "DialogMessage_EnableStartupLaunchDeniedMessage": "You can enable startup launch from Settings -> App Preferences.",
@@ -681,6 +689,10 @@
"NoMailSelected": "Nebyly vybrány žádné zprávy", "NoMailSelected": "Nebyly vybrány žádné zprávy",
"NoMessageCrieteria": "Žádná zpráva neodpovídá kritériím vyhledávání", "NoMessageCrieteria": "Žádná zpráva neodpovídá kritériím vyhledávání",
"NoMessageEmptyFolder": "Tato složka je prázdná", "NoMessageEmptyFolder": "Tato složka je prázdná",
"MailEmptyState_Title": "Žádné účty povolené pro poštu",
"MailEmptyState_Message": "Máte účty pro kalendář, ale žádný z nich není povolen pro poštu. Přidejte poštovní účet nebo upravte existující účet, aby používal poštu.",
"MailEmptyState_AddAccount": "Přidat účet",
"MailEmptyState_ManageAccounts": "Spravovat účty",
"Notifications_MultipleNotificationsMessage": "You have {0} new messages.", "Notifications_MultipleNotificationsMessage": "You have {0} new messages.",
"Notifications_MultipleNotificationsTitle": "New Mail", "Notifications_MultipleNotificationsTitle": "New Mail",
"Notifications_WinoUpdatedMessage": "Vyzkoušejte novou verzi {0}", "Notifications_WinoUpdatedMessage": "Vyzkoušejte novou verzi {0}",
@@ -824,6 +836,8 @@
"SettingsDeleteAccount_Title": "Smazat tento účet", "SettingsDeleteAccount_Title": "Smazat tento účet",
"SettingsDeleteProtection_Description": "Should Wino ask you for confirmation every time you try to permanently delete a mail using Shift + Del keys?", "SettingsDeleteProtection_Description": "Should Wino ask you for confirmation every time you try to permanently delete a mail using Shift + Del keys?",
"SettingsDeleteProtection_Title": "Ochrana proti trvalému smazání", "SettingsDeleteProtection_Title": "Ochrana proti trvalému smazání",
"SettingsEmptyJunkFolderCommand_Description": "Zobrazit příkaz pro vyprázdnění složky ve složkách Nevyžádaná pošta (spam). Tato akce nepožádá o potvrzení a ihned smaže všechny e-maily ve složce spamu.",
"SettingsEmptyJunkFolderCommand_Title": "Zobrazit příkaz pro vyprázdnění složky spamu",
"SettingsDiagnostics_Description": "Pro vývojáře", "SettingsDiagnostics_Description": "Pro vývojáře",
"SettingsDiagnostics_DiagnosticId_Description": "Share this ID with the developers when asked to get help for the issues you experience in Wino Mail.", "SettingsDiagnostics_DiagnosticId_Description": "Share this ID with the developers when asked to get help for the issues you experience in Wino Mail.",
"SettingsDiagnostics_DiagnosticId_Title": "Diagnostic ID", "SettingsDiagnostics_DiagnosticId_Title": "Diagnostic ID",
@@ -1074,6 +1088,12 @@
"SettingsTaskbarBadge_Title": "Taskbar Badge", "SettingsTaskbarBadge_Title": "Taskbar Badge",
"SettingsThreads_Description": "Uspořádat zprávy do konverzačních vláken.", "SettingsThreads_Description": "Uspořádat zprávy do konverzačních vláken.",
"SettingsThreads_Title": "Vlákna konverzací", "SettingsThreads_Title": "Vlákna konverzací",
"SettingsThreads_Enabled_Description": "Seskupovat související zprávy do jedné konverzace.",
"SettingsThreads_Enabled_Title": "Povolit vlákna konverací",
"SettingsThreadOrder_Description": "Zvolte, jak budou položky seřazeny v konverzačním vláknu.",
"SettingsThreadOrder_Title": "Řazení položek konverzačního vlákna",
"SettingsThreadOrder_LastItemFirst": "Poslední položka jako první",
"SettingsThreadOrder_FirstItemFirst": "První položka jako první",
"SettingsUnlinkAccounts_Description": "Remove the link between accounts. his will not delete your accounts.", "SettingsUnlinkAccounts_Description": "Remove the link between accounts. his will not delete your accounts.",
"SettingsUnlinkAccounts_Title": "Rozpojit účty", "SettingsUnlinkAccounts_Title": "Rozpojit účty",
"SettingsMailRendering_ActionLabels_Title": "Action labels", "SettingsMailRendering_ActionLabels_Title": "Action labels",
@@ -1339,6 +1359,7 @@
"WelcomeWindow_GetStartedButton": "Začněte přidáním účtu", "WelcomeWindow_GetStartedButton": "Začněte přidáním účtu",
"WelcomeWindow_GetStartedDescription": "Přidejte svůj účet Outlook, Gmail nebo IMAP a začněte s Wino Mail.", "WelcomeWindow_GetStartedDescription": "Přidejte svůj účet Outlook, Gmail nebo IMAP a začněte s Wino Mail.",
"WelcomeWindow_ImportFromWinoAccount": "Importovat z vašeho Wino účtu", "WelcomeWindow_ImportFromWinoAccount": "Importovat z vašeho Wino účtu",
"WelcomeWindow_ImportFromJsonFile": "Importovat z JSON souboru",
"WelcomeWindow_ImportInProgress": "Importuji synchronizované preference a účty...", "WelcomeWindow_ImportInProgress": "Importuji synchronizované preference a účty...",
"WelcomeWindow_ImportNoAccountsFound": "Ve vašem Wino účtu nebyly nalezeny žádné synchronizované účty. Pokud byly k dispozici preference, byly obnoveny. Pro ruční přidání účtu použijte možnost Začít.", "WelcomeWindow_ImportNoAccountsFound": "Ve vašem Wino účtu nebyly nalezeny žádné synchronizované účty. Pokud byly k dispozici preference, byly obnoveny. Pro ruční přidání účtu použijte možnost Začít.",
"WelcomeWindow_ImportDuplicateAccountsSkipped": "{0} synchronizovaných účtů je již k dispozici na tomto zařízení. Pokud je potřeba, použijte možnost Začít pro ruční přidání dalšího účtu.", "WelcomeWindow_ImportDuplicateAccountsSkipped": "{0} synchronizovaných účtů je již k dispozici na tomto zařízení. Pokud je potřeba, použijte možnost Začít pro ruční přidání dalšího účtu.",
@@ -1418,6 +1439,12 @@
"WinoAccount_Management_ExportDialog_AccountsDisclaimer": "Hesla, tokeny a další citlivé údaje se nesynchronizují.", "WinoAccount_Management_ExportDialog_AccountsDisclaimer": "Hesla, tokeny a další citlivé údaje se nesynchronizují.",
"WinoAccount_Management_ExportDialog_AccountsRelogin": "Importované účty na jiném počítači budou i nadále vyžadovat opětovné přihlášení před jejich použitím.", "WinoAccount_Management_ExportDialog_AccountsRelogin": "Importované účty na jiném počítači budou i nadále vyžadovat opětovné přihlášení před jejich použitím.",
"WinoAccount_Management_ExportDialog_InProgress": "Probíhá export vybraných dat Wino.", "WinoAccount_Management_ExportDialog_InProgress": "Probíhá export vybraných dat Wino.",
"WinoAccount_Management_LocalDataSectionTitle": "Přenos pomocí JSON souboru",
"WinoAccount_Management_LocalDataSectionDescription": "Importovat z nebo exportovat do místního JSON souboru. Hesla, tokeny a další citlivé údaje nejsou zahrnuty.",
"WinoAccount_Management_LocalDataImportAction": "Importovat",
"WinoAccount_Management_LocalDataExportAction": "Exportovat",
"WinoAccount_Management_LocalDataSaved": "Exportovaná data Wino byla uložena do {0}.",
"WinoAccount_Management_LocalDataInvalidFile": "Vybraný JSON soubor neobsahuje platný export Wino.",
"WinoAccount_Management_LoadFailed": "Nepodařilo se načíst nejnovější informace o účtu Wino.", "WinoAccount_Management_LoadFailed": "Nepodařilo se načíst nejnovější informace o účtu Wino.",
"WinoAccount_Management_ActionFailed": "Požadavek na účet Wino nebyl dokončen.", "WinoAccount_Management_ActionFailed": "Požadavek na účet Wino nebyl dokončen.",
"WinoAccount_SettingsSection_Title": "Wino účet", "WinoAccount_SettingsSection_Title": "Wino účet",
@@ -1514,8 +1541,22 @@
"WelcomeWizard_Step3Title": "Dokončit nastavení", "WelcomeWizard_Step3Title": "Dokončit nastavení",
"ProviderSelection_Title": "Zvolte poskytovatele e-mailu", "ProviderSelection_Title": "Zvolte poskytovatele e-mailu",
"ProviderSelection_Subtitle": "Vyberte níže uvedeného poskytovatele a přidejte si svůj e-mailový účet do Wino Mail.", "ProviderSelection_Subtitle": "Vyberte níže uvedeného poskytovatele a přidejte si svůj e-mailový účet do Wino Mail.",
"ProviderSelection_StepProgress": "Krok {0} z 3",
"ProviderSelection_IdentityTitle": "Identita účtu",
"ProviderSelection_IdentityDescription": "Zvolte, jak se tento účet bude zobrazovat ve Wino.",
"ProviderSelection_ProviderSectionTitle": "Poskytovatel",
"ProviderSelection_ProviderSectionDescription": "Vyberte službu, ke které se chcete připojit.",
"ProviderSelection_CapabilitySectionTitle": "Použít tento účet pro",
"ProviderSelection_CapabilitySectionDescription": "Vyberte, zda chcete používat poštu, kalendář, nebo obojí.",
"ProviderSelection_CapabilityProviderDescription_OAuth": "V dalším kroku zabezpečené přihlášení propojí váš účet. Pokud povolíte kalendář, Wino také automaticky propojí Kalendář Outlooku nebo Kalendář Google.",
"ProviderSelection_CapabilityProviderDescription_SpecialImap": "V dalším kroku zadáte údaje poskytovatele. Pošta používá IMAP/SMTP a kalendář může používat CalDAV nebo zůstat místní na tomto zařízení.",
"ProviderSelection_CapabilityProviderDescription_CustomServer": "V dalším kroku zadáte údaje o serveru. Pošta používá IMAP/SMTP a kalendář může používat CalDAV nebo zůstat místní na tomto zařízení.",
"ProviderSelection_AccountNameHeader": "Název účtu", "ProviderSelection_AccountNameHeader": "Název účtu",
"ProviderSelection_AccountNamePlaceholder": "např. Osobní, Pracovní", "ProviderSelection_AccountNamePlaceholder": "např. Osobní, Pracovní",
"ProviderSelection_UseForMail": "Pošta",
"ProviderSelection_UseForCalendar": "Kalendář",
"ProviderSelection_CapabilityValidationMessage": "Zvolte alespoň jednu možnost před pokračováním.",
"ProviderSelection_CalendarOnlyServerHint": "Pokud budete pokračovat pouze s kalendářem, další stránka nebude vyžadovat e-mailovou adresu.",
"ProviderSelection_DisplayNameHeader": "Zobrazené jméno", "ProviderSelection_DisplayNameHeader": "Zobrazené jméno",
"ProviderSelection_DisplayNamePlaceholder": "např. Jan Novák", "ProviderSelection_DisplayNamePlaceholder": "např. Jan Novák",
"ProviderSelection_EmailHeader": "E-mailová adresa", "ProviderSelection_EmailHeader": "E-mailová adresa",
@@ -47,6 +47,11 @@
"AccountDetailsPage_CalendarListDescription": "Vælg en kalender for at konfigurere dens indstillinger.", "AccountDetailsPage_CalendarListDescription": "Vælg en kalender for at konfigurere dens indstillinger.",
"AccountDetailsPage_InitialSynchronization_Title": "Første synkronisering", "AccountDetailsPage_InitialSynchronization_Title": "Første synkronisering",
"AccountDetailsPage_InitialSynchronization_Description": "Wino har synkroniseret dine mails helt tilbage til {0}.", "AccountDetailsPage_InitialSynchronization_Description": "Wino har synkroniseret dine mails helt tilbage til {0}.",
"AccountDetailsPage_CapabilityTitle": "Forbundne funktioner",
"AccountDetailsPage_CapabilityDescription": "Vælg om denne konto skal bruges til mail, kalender eller begge dele. Hvis du aktiverer en ny funktion, kan det bede dig logge ind igen.",
"AccountCapability_MailOnly": "Kun mail",
"AccountCapability_CalendarOnly": "Kun kalender",
"AccountCapability_MailAndCalendar": "Mail og Kalender",
"AddHyperlink": "Add", "AddHyperlink": "Add",
"AppCloseBackgroundSynchronizationWarningTitle": "Background Synchronization", "AppCloseBackgroundSynchronizationWarningTitle": "Background Synchronization",
"AppCloseStartupLaunchDisabledWarningMessageFirstLine": "Application has not been set to launch on Windows startup.", "AppCloseStartupLaunchDisabledWarningMessageFirstLine": "Application has not been set to launch on Windows startup.",
@@ -76,6 +81,7 @@
"Buttons_ApplyTheme": "Apply Theme", "Buttons_ApplyTheme": "Apply Theme",
"Buttons_PopOut": "Pop ud", "Buttons_PopOut": "Pop ud",
"Buttons_Browse": "Browse", "Buttons_Browse": "Browse",
"Buttons_Back": "Tilbage",
"Buttons_Cancel": "Cancel", "Buttons_Cancel": "Cancel",
"Buttons_Close": "Close", "Buttons_Close": "Close",
"Buttons_Copy": "Copy", "Buttons_Copy": "Copy",
@@ -299,6 +305,8 @@
"DialogMessage_DeleteRecurringSeriesTitle": "Slet tilbagevendende serie", "DialogMessage_DeleteRecurringSeriesTitle": "Slet tilbagevendende serie",
"DialogMessage_DiscardDraftConfirmationMessage": "This draft will be discarded. Do you want to continue?", "DialogMessage_DiscardDraftConfirmationMessage": "This draft will be discarded. Do you want to continue?",
"DialogMessage_DiscardDraftConfirmationTitle": "Discard Draft", "DialogMessage_DiscardDraftConfirmationTitle": "Discard Draft",
"DialogMessage_CloseDraftWindowConfirmationMessage": "Et udkast er stadig åbent. Gem det, før du lukker vinduet?",
"DialogMessage_CloseDraftWindowConfirmationTitle": "Luk vinduet",
"DialogMessage_EmptySubjectConfirmation": "Missing Subject", "DialogMessage_EmptySubjectConfirmation": "Missing Subject",
"DialogMessage_EmptySubjectConfirmationMessage": "Message has no subject. Do you want to continue?", "DialogMessage_EmptySubjectConfirmationMessage": "Message has no subject. Do you want to continue?",
"DialogMessage_EnableStartupLaunchDeniedMessage": "You can enable startup launch from Settings -> App Preferences.", "DialogMessage_EnableStartupLaunchDeniedMessage": "You can enable startup launch from Settings -> App Preferences.",
@@ -681,6 +689,10 @@
"NoMailSelected": "No message selected", "NoMailSelected": "No message selected",
"NoMessageCrieteria": "No messages match your search criteria", "NoMessageCrieteria": "No messages match your search criteria",
"NoMessageEmptyFolder": "This folder is empty", "NoMessageEmptyFolder": "This folder is empty",
"MailEmptyState_Title": "Ingen konti med mail aktiveret",
"MailEmptyState_Message": "Du har konti tilsluttet til kalender, men ingen af dem er aktiveret til mail. Tilføj en mailkonto eller opdater en eksisterende konto for at bruge mail.",
"MailEmptyState_AddAccount": "Tilføj konto",
"MailEmptyState_ManageAccounts": "Administrer konti",
"Notifications_MultipleNotificationsMessage": "You have {0} new messages.", "Notifications_MultipleNotificationsMessage": "You have {0} new messages.",
"Notifications_MultipleNotificationsTitle": "New Mail", "Notifications_MultipleNotificationsTitle": "New Mail",
"Notifications_WinoUpdatedMessage": "Checkout new version {0}", "Notifications_WinoUpdatedMessage": "Checkout new version {0}",
@@ -824,6 +836,8 @@
"SettingsDeleteAccount_Title": "Delete this account", "SettingsDeleteAccount_Title": "Delete this account",
"SettingsDeleteProtection_Description": "Should Wino ask you for confirmation every time you try to permanently delete a mail using Shift + Del keys?", "SettingsDeleteProtection_Description": "Should Wino ask you for confirmation every time you try to permanently delete a mail using Shift + Del keys?",
"SettingsDeleteProtection_Title": "Permanent Delete Protection", "SettingsDeleteProtection_Title": "Permanent Delete Protection",
"SettingsEmptyJunkFolderCommand_Description": "Vis kommandoen til at tøm mappen i Junk/Spam-mapperne. Denne handling vil ikke bede om bekræftelse og vil straks slette alle mails i spam-mappen.",
"SettingsEmptyJunkFolderCommand_Title": "Vis kommandoen til at tømme spam-mappen",
"SettingsDiagnostics_Description": "For developers", "SettingsDiagnostics_Description": "For developers",
"SettingsDiagnostics_DiagnosticId_Description": "Share this ID with the developers when asked to get help for the issues you experience in Wino Mail.", "SettingsDiagnostics_DiagnosticId_Description": "Share this ID with the developers when asked to get help for the issues you experience in Wino Mail.",
"SettingsDiagnostics_DiagnosticId_Title": "Diagnostic ID", "SettingsDiagnostics_DiagnosticId_Title": "Diagnostic ID",
@@ -1074,6 +1088,12 @@
"SettingsTaskbarBadge_Title": "Taskbar Badge", "SettingsTaskbarBadge_Title": "Taskbar Badge",
"SettingsThreads_Description": "Organize messages into conversation threads.", "SettingsThreads_Description": "Organize messages into conversation threads.",
"SettingsThreads_Title": "Conversation Threading", "SettingsThreads_Title": "Conversation Threading",
"SettingsThreads_Enabled_Description": "Grupper relaterede meddelelser i en enkelt samtale.",
"SettingsThreads_Enabled_Title": "Aktivér samtale-trådning",
"SettingsThreadOrder_Description": "Vælg hvordan elementer ordnes i en samtale-tråd.",
"SettingsThreadOrder_Title": "Sortering af tråd-elementer",
"SettingsThreadOrder_LastItemFirst": "Sidste element først",
"SettingsThreadOrder_FirstItemFirst": "Første element først",
"SettingsUnlinkAccounts_Description": "Remove the link between accounts. his will not delete your accounts.", "SettingsUnlinkAccounts_Description": "Remove the link between accounts. his will not delete your accounts.",
"SettingsUnlinkAccounts_Title": "Unlink Accounts", "SettingsUnlinkAccounts_Title": "Unlink Accounts",
"SettingsMailRendering_ActionLabels_Title": "Action labels", "SettingsMailRendering_ActionLabels_Title": "Action labels",
@@ -1339,6 +1359,7 @@
"WelcomeWindow_GetStartedButton": "Kom i gang ved at tilføje en konto", "WelcomeWindow_GetStartedButton": "Kom i gang ved at tilføje en konto",
"WelcomeWindow_GetStartedDescription": "Tilføj din Outlook-, Gmail- eller IMAP-konto for at komme i gang med Wino Mail.", "WelcomeWindow_GetStartedDescription": "Tilføj din Outlook-, Gmail- eller IMAP-konto for at komme i gang med Wino Mail.",
"WelcomeWindow_ImportFromWinoAccount": "Importer fra din Wino-konto", "WelcomeWindow_ImportFromWinoAccount": "Importer fra din Wino-konto",
"WelcomeWindow_ImportFromJsonFile": "Importér fra en JSON-fil",
"WelcomeWindow_ImportInProgress": "Importerere dine synkroniserede præferencer og konti...", "WelcomeWindow_ImportInProgress": "Importerere dine synkroniserede præferencer og konti...",
"WelcomeWindow_ImportNoAccountsFound": "Ingen synkroniserede konti blev fundet i din Wino-konto. Hvis præferencer var tilgængelige, blev de gendannet. Brug Kom i gang til manuelt at tilføje en konto.", "WelcomeWindow_ImportNoAccountsFound": "Ingen synkroniserede konti blev fundet i din Wino-konto. Hvis præferencer var tilgængelige, blev de gendannet. Brug Kom i gang til manuelt at tilføje en konto.",
"WelcomeWindow_ImportDuplicateAccountsSkipped": "{0} synkroniserede konti er allerede tilgængelige på denne enhed. Brug Kom i gang til manuelt at tilføje en anden konto, hvis det er nødvendigt.", "WelcomeWindow_ImportDuplicateAccountsSkipped": "{0} synkroniserede konti er allerede tilgængelige på denne enhed. Brug Kom i gang til manuelt at tilføje en anden konto, hvis det er nødvendigt.",
@@ -1418,6 +1439,12 @@
"WinoAccount_Management_ExportDialog_AccountsDisclaimer": "Adgangskoder, tokens og andre følsomme oplysninger synkroniseres ikke.", "WinoAccount_Management_ExportDialog_AccountsDisclaimer": "Adgangskoder, tokens og andre følsomme oplysninger synkroniseres ikke.",
"WinoAccount_Management_ExportDialog_AccountsRelogin": "Importerede konti på en anden PC kræver stadig, at du logger ind igen, før de kan bruges.", "WinoAccount_Management_ExportDialog_AccountsRelogin": "Importerede konti på en anden PC kræver stadig, at du logger ind igen, før de kan bruges.",
"WinoAccount_Management_ExportDialog_InProgress": "Eksporterer dine valgte Wino-data...", "WinoAccount_Management_ExportDialog_InProgress": "Eksporterer dine valgte Wino-data...",
"WinoAccount_Management_LocalDataSectionTitle": "Overfør data med en JSON-fil",
"WinoAccount_Management_LocalDataSectionDescription": "Importér fra eller eksporter til en lokal JSON-fil. Adgangskoder, tokens og anden følsom information er ikke inkluderet.",
"WinoAccount_Management_LocalDataImportAction": "Importér",
"WinoAccount_Management_LocalDataExportAction": "Eksportér",
"WinoAccount_Management_LocalDataSaved": "Dine eksporterede Wino-data er gemt til {0}.",
"WinoAccount_Management_LocalDataInvalidFile": "Den valgte JSON-fil indeholder ikke en gyldig Wino-eksport.",
"WinoAccount_Management_LoadFailed": "Wino kunne ikke indlæse de seneste oplysninger om Wino-kontoen.", "WinoAccount_Management_LoadFailed": "Wino kunne ikke indlæse de seneste oplysninger om Wino-kontoen.",
"WinoAccount_Management_ActionFailed": "Anmodningen til Wino-kontoen kunne ikke gennemføres.", "WinoAccount_Management_ActionFailed": "Anmodningen til Wino-kontoen kunne ikke gennemføres.",
"WinoAccount_SettingsSection_Title": "Wino-konto", "WinoAccount_SettingsSection_Title": "Wino-konto",
@@ -1514,8 +1541,22 @@
"WelcomeWizard_Step3Title": "Afslut opsætningen", "WelcomeWizard_Step3Title": "Afslut opsætningen",
"ProviderSelection_Title": "Vælg din e-mail-udbyder", "ProviderSelection_Title": "Vælg din e-mail-udbyder",
"ProviderSelection_Subtitle": "Vælg en udbyder nedenfor for at tilføje din e-mail-konto til Wino Mail.", "ProviderSelection_Subtitle": "Vælg en udbyder nedenfor for at tilføje din e-mail-konto til Wino Mail.",
"ProviderSelection_StepProgress": "Trin {0} af 3",
"ProviderSelection_IdentityTitle": "Kontoidentitet",
"ProviderSelection_IdentityDescription": "Vælg hvordan denne konto vises i Wino.",
"ProviderSelection_ProviderSectionTitle": "Udbyder",
"ProviderSelection_ProviderSectionDescription": "Vælg den tjeneste, du vil oprette forbindelse til.",
"ProviderSelection_CapabilitySectionTitle": "Brug denne konto til",
"ProviderSelection_CapabilitySectionDescription": "Vælg om du vil bruge mail, kalender eller begge dele.",
"ProviderSelection_CapabilityProviderDescription_OAuth": "På næste trin vil et sikkert login forbinde din konto. Hvis du aktiverer kalender, vil Wino også automatisk oprette forbindelse til Outlook Kalender eller Google Kalender.",
"ProviderSelection_CapabilityProviderDescription_SpecialImap": "På næste trin indtaster du dine udbyderoplysninger. Mail bruger IMAP/SMTP, og kalender kan bruge CalDAV eller forblive lokalt på denne enhed.",
"ProviderSelection_CapabilityProviderDescription_CustomServer": "På næste trin indtaster du dine serveroplysninger. Mail bruger IMAP/SMTP, og kalender kan bruge CalDAV eller forblive lokalt på denne enhed.",
"ProviderSelection_AccountNameHeader": "Konto navn", "ProviderSelection_AccountNameHeader": "Konto navn",
"ProviderSelection_AccountNamePlaceholder": "f.eks. Personlig, Arbejde", "ProviderSelection_AccountNamePlaceholder": "f.eks. Personlig, Arbejde",
"ProviderSelection_UseForMail": "Mail",
"ProviderSelection_UseForCalendar": "Kalender",
"ProviderSelection_CapabilityValidationMessage": "Vælg mindst én funktion, før du fortsætter.",
"ProviderSelection_CalendarOnlyServerHint": "Hvis du fortsætter med kalender alene, kræver næste side ikke en e-mailadresse.",
"ProviderSelection_DisplayNameHeader": "Vis navn", "ProviderSelection_DisplayNameHeader": "Vis navn",
"ProviderSelection_DisplayNamePlaceholder": "f.eks. John Doe", "ProviderSelection_DisplayNamePlaceholder": "f.eks. John Doe",
"ProviderSelection_EmailHeader": "E-mailadresse", "ProviderSelection_EmailHeader": "E-mailadresse",
@@ -47,6 +47,11 @@
"AccountDetailsPage_CalendarListDescription": "Wähle einen Kalender aus, um dessen Einstellungen zu konfigurieren.", "AccountDetailsPage_CalendarListDescription": "Wähle einen Kalender aus, um dessen Einstellungen zu konfigurieren.",
"AccountDetailsPage_InitialSynchronization_Title": "Erste Synchronisierung", "AccountDetailsPage_InitialSynchronization_Title": "Erste Synchronisierung",
"AccountDetailsPage_InitialSynchronization_Description": "Wino hat Ihre E-Mails bis {0} synchronisiert.", "AccountDetailsPage_InitialSynchronization_Description": "Wino hat Ihre E-Mails bis {0} synchronisiert.",
"AccountDetailsPage_CapabilityTitle": "Verbundene Funktionen",
"AccountDetailsPage_CapabilityDescription": "Wählen Sie aus, ob dieses Konto für Mail, Kalender oder beides verwendet wird. Wenn Sie eine neue Funktion aktivieren, müssen Sie sich möglicherweise erneut anmelden.",
"AccountCapability_MailOnly": "Nur Mail",
"AccountCapability_CalendarOnly": "Nur Kalender",
"AccountCapability_MailAndCalendar": "Mail + Kalender",
"AddHyperlink": "Hinzufügen", "AddHyperlink": "Hinzufügen",
"AppCloseBackgroundSynchronizationWarningTitle": "Hintergrundsynchronisierung", "AppCloseBackgroundSynchronizationWarningTitle": "Hintergrundsynchronisierung",
"AppCloseStartupLaunchDisabledWarningMessageFirstLine": "Die Anwendung wird beim Start von Windows nicht gestartet.", "AppCloseStartupLaunchDisabledWarningMessageFirstLine": "Die Anwendung wird beim Start von Windows nicht gestartet.",
@@ -76,6 +81,7 @@
"Buttons_ApplyTheme": "Thema anwenden", "Buttons_ApplyTheme": "Thema anwenden",
"Buttons_PopOut": "In neues Fenster öffnen", "Buttons_PopOut": "In neues Fenster öffnen",
"Buttons_Browse": "Durchsuchen", "Buttons_Browse": "Durchsuchen",
"Buttons_Back": "Zurück",
"Buttons_Cancel": "Abbrechen", "Buttons_Cancel": "Abbrechen",
"Buttons_Close": "Schließen", "Buttons_Close": "Schließen",
"Buttons_Copy": "Kopieren", "Buttons_Copy": "Kopieren",
@@ -299,6 +305,8 @@
"DialogMessage_DeleteRecurringSeriesTitle": "Wiederkehrende Serie löschen", "DialogMessage_DeleteRecurringSeriesTitle": "Wiederkehrende Serie löschen",
"DialogMessage_DiscardDraftConfirmationMessage": "Dieser Entwurf wird verworfen. Möchten Sie fortfahren?", "DialogMessage_DiscardDraftConfirmationMessage": "Dieser Entwurf wird verworfen. Möchten Sie fortfahren?",
"DialogMessage_DiscardDraftConfirmationTitle": "Entwurf verwerfen", "DialogMessage_DiscardDraftConfirmationTitle": "Entwurf verwerfen",
"DialogMessage_CloseDraftWindowConfirmationMessage": "Ein Entwurf ist noch geöffnet. Speichern Sie ihn, bevor Sie das Fenster schließen?",
"DialogMessage_CloseDraftWindowConfirmationTitle": "Fenster schließen",
"DialogMessage_EmptySubjectConfirmation": "Betreff fehlt", "DialogMessage_EmptySubjectConfirmation": "Betreff fehlt",
"DialogMessage_EmptySubjectConfirmationMessage": "Nachricht hat keinen Betreff. Möchten Sie fortfahren?", "DialogMessage_EmptySubjectConfirmationMessage": "Nachricht hat keinen Betreff. Möchten Sie fortfahren?",
"DialogMessage_EnableStartupLaunchDeniedMessage": "Sie können den Autostart unter Einstellungen -> App-Einstellungen aktivieren.", "DialogMessage_EnableStartupLaunchDeniedMessage": "Sie können den Autostart unter Einstellungen -> App-Einstellungen aktivieren.",
@@ -681,6 +689,10 @@
"NoMailSelected": "Keine Nachricht ausgewählt", "NoMailSelected": "Keine Nachricht ausgewählt",
"NoMessageCrieteria": "Keine Nachrichten entsprechen Ihren Suchkriterien", "NoMessageCrieteria": "Keine Nachrichten entsprechen Ihren Suchkriterien",
"NoMessageEmptyFolder": "Dieser Ordner ist leer", "NoMessageEmptyFolder": "Dieser Ordner ist leer",
"MailEmptyState_Title": "Keine Mail-fähigen Konten",
"MailEmptyState_Message": "Sie haben Konten verbunden, die für den Kalender verwendet werden, aber keines davon ist für Mail aktiviert. Fügen Sie ein Mail-Konto hinzu oder aktualisieren Sie ein bestehendes Konto, um Mail zu verwenden.",
"MailEmptyState_AddAccount": "Konto hinzufügen",
"MailEmptyState_ManageAccounts": "Konten verwalten",
"Notifications_MultipleNotificationsMessage": "Sie haben {0} neue Nachrichten.", "Notifications_MultipleNotificationsMessage": "Sie haben {0} neue Nachrichten.",
"Notifications_MultipleNotificationsTitle": "Neue Mail", "Notifications_MultipleNotificationsTitle": "Neue Mail",
"Notifications_WinoUpdatedMessage": "Neue Version {0} herunterladen", "Notifications_WinoUpdatedMessage": "Neue Version {0} herunterladen",
@@ -824,6 +836,8 @@
"SettingsDeleteAccount_Title": "Dieses Konto löschen", "SettingsDeleteAccount_Title": "Dieses Konto löschen",
"SettingsDeleteProtection_Description": "Sollte Wino jedes Mal nachfragen, wenn Sie eine Mail mit Umschalten + Entfernen permanent löschen möchten?", "SettingsDeleteProtection_Description": "Sollte Wino jedes Mal nachfragen, wenn Sie eine Mail mit Umschalten + Entfernen permanent löschen möchten?",
"SettingsDeleteProtection_Title": "Schutz vor permanenter Löschung", "SettingsDeleteProtection_Title": "Schutz vor permanenter Löschung",
"SettingsEmptyJunkFolderCommand_Description": "Zeige den Befehl zum Leeren des Junk-/Spam-Ordners an. Diese Aktion wird keine Bestätigung erfordern und löscht sofort alle E-Mails im Spam-Ordner.",
"SettingsEmptyJunkFolderCommand_Title": "Befehl zum Leeren des Spam-Ordners anzeigen",
"SettingsDiagnostics_Description": "Für Entwickler", "SettingsDiagnostics_Description": "Für Entwickler",
"SettingsDiagnostics_DiagnosticId_Description": "Teilen Sie diese ID mit den Entwicklern, wenn Sie um Hilfe bei Problemen in Wino Mail gebeten werden.", "SettingsDiagnostics_DiagnosticId_Description": "Teilen Sie diese ID mit den Entwicklern, wenn Sie um Hilfe bei Problemen in Wino Mail gebeten werden.",
"SettingsDiagnostics_DiagnosticId_Title": "Diagnose-ID", "SettingsDiagnostics_DiagnosticId_Title": "Diagnose-ID",
@@ -1074,6 +1088,12 @@
"SettingsTaskbarBadge_Title": "Taskleisten-Symbol", "SettingsTaskbarBadge_Title": "Taskleisten-Symbol",
"SettingsThreads_Description": "Nachrichten in Unterhaltungsthreads organisieren.", "SettingsThreads_Description": "Nachrichten in Unterhaltungsthreads organisieren.",
"SettingsThreads_Title": "Unterhaltungsthreading", "SettingsThreads_Title": "Unterhaltungsthreading",
"SettingsThreads_Enabled_Description": "Verwandte Nachrichten zu einer einzigen Unterhaltung bündeln.",
"SettingsThreads_Enabled_Title": "Unterhaltungen bündeln aktivieren",
"SettingsThreadOrder_Description": "Wählen Sie aus, wie Elemente in einem Thread sortiert werden.",
"SettingsThreadOrder_Title": "Thread-Elemente sortieren",
"SettingsThreadOrder_LastItemFirst": "Letztes Element zuerst",
"SettingsThreadOrder_FirstItemFirst": "Erstes Element zuerst",
"SettingsUnlinkAccounts_Description": "Entfernen Sie den Link zwischen den Konten. Dies wird Ihre Konten nicht löschen.", "SettingsUnlinkAccounts_Description": "Entfernen Sie den Link zwischen den Konten. Dies wird Ihre Konten nicht löschen.",
"SettingsUnlinkAccounts_Title": "Konten trennen", "SettingsUnlinkAccounts_Title": "Konten trennen",
"SettingsMailRendering_ActionLabels_Title": "Aktions-Labels", "SettingsMailRendering_ActionLabels_Title": "Aktions-Labels",
@@ -1339,6 +1359,7 @@
"WelcomeWindow_GetStartedButton": "Konto hinzufügen und loslegen", "WelcomeWindow_GetStartedButton": "Konto hinzufügen und loslegen",
"WelcomeWindow_GetStartedDescription": "Fügen Sie Ihr Outlook-, Gmail- oder IMAP-Konto hinzu, um mit Wino Mail zu beginnen.", "WelcomeWindow_GetStartedDescription": "Fügen Sie Ihr Outlook-, Gmail- oder IMAP-Konto hinzu, um mit Wino Mail zu beginnen.",
"WelcomeWindow_ImportFromWinoAccount": "Aus Ihrem Wino-Konto importieren", "WelcomeWindow_ImportFromWinoAccount": "Aus Ihrem Wino-Konto importieren",
"WelcomeWindow_ImportFromJsonFile": "Aus einer JSON-Datei importieren",
"WelcomeWindow_ImportInProgress": "Import Ihrer synchronisierten Einstellungen und Konten läuft.", "WelcomeWindow_ImportInProgress": "Import Ihrer synchronisierten Einstellungen und Konten läuft.",
"WelcomeWindow_ImportNoAccountsFound": "Es wurden keine synchronisierten Konten in Ihrem Wino-Konto gefunden. Falls Einstellungen verfügbar waren, wurden sie wiederhergestellt. Verwenden Sie Loslegen, um manuell ein Konto hinzuzufügen.", "WelcomeWindow_ImportNoAccountsFound": "Es wurden keine synchronisierten Konten in Ihrem Wino-Konto gefunden. Falls Einstellungen verfügbar waren, wurden sie wiederhergestellt. Verwenden Sie Loslegen, um manuell ein Konto hinzuzufügen.",
"WelcomeWindow_ImportDuplicateAccountsSkipped": "{0} synchronisierte Konten sind auf diesem Gerät bereits verfügbar. Verwenden Sie Loslegen, um bei Bedarf manuell ein weiteres Konto hinzuzufügen.", "WelcomeWindow_ImportDuplicateAccountsSkipped": "{0} synchronisierte Konten sind auf diesem Gerät bereits verfügbar. Verwenden Sie Loslegen, um bei Bedarf manuell ein weiteres Konto hinzuzufügen.",
@@ -1418,6 +1439,12 @@
"WinoAccount_Management_ExportDialog_AccountsDisclaimer": "Passwörter, Tokens und andere sensible Informationen werden nicht synchronisiert.", "WinoAccount_Management_ExportDialog_AccountsDisclaimer": "Passwörter, Tokens und andere sensible Informationen werden nicht synchronisiert.",
"WinoAccount_Management_ExportDialog_AccountsRelogin": "Auf einem anderen PC importierte Konten müssen sich weiterhin erneut anmelden, bevor sie verwendet werden können.", "WinoAccount_Management_ExportDialog_AccountsRelogin": "Auf einem anderen PC importierte Konten müssen sich weiterhin erneut anmelden, bevor sie verwendet werden können.",
"WinoAccount_Management_ExportDialog_InProgress": "Exportieren Sie Ihre ausgewählten Wino-Daten.", "WinoAccount_Management_ExportDialog_InProgress": "Exportieren Sie Ihre ausgewählten Wino-Daten.",
"WinoAccount_Management_LocalDataSectionTitle": "Übertragung mit einer JSON-Datei",
"WinoAccount_Management_LocalDataSectionDescription": "Importieren Sie aus oder exportieren Sie in eine lokale JSON-Datei. Passwörter, Tokens und andere sensible Informationen sind nicht enthalten.",
"WinoAccount_Management_LocalDataImportAction": "Importieren",
"WinoAccount_Management_LocalDataExportAction": "Exportieren",
"WinoAccount_Management_LocalDataSaved": "Ihre exportierten Wino-Daten wurden in {0} gespeichert.",
"WinoAccount_Management_LocalDataInvalidFile": "Die ausgewählte JSON-Datei enthält keinen gültigen Wino-Export.",
"WinoAccount_Management_LoadFailed": "Wino konnte die neuesten Informationen zum Wino-Konto nicht laden.", "WinoAccount_Management_LoadFailed": "Wino konnte die neuesten Informationen zum Wino-Konto nicht laden.",
"WinoAccount_Management_ActionFailed": "Die Wino-Konto-Anfrage konnte nicht abgeschlossen werden.", "WinoAccount_Management_ActionFailed": "Die Wino-Konto-Anfrage konnte nicht abgeschlossen werden.",
"WinoAccount_SettingsSection_Title": "Wino-Konto", "WinoAccount_SettingsSection_Title": "Wino-Konto",
@@ -1514,8 +1541,22 @@
"WelcomeWizard_Step3Title": "Einrichtung abschließen", "WelcomeWizard_Step3Title": "Einrichtung abschließen",
"ProviderSelection_Title": "E-Mail-Anbieter auswählen", "ProviderSelection_Title": "E-Mail-Anbieter auswählen",
"ProviderSelection_Subtitle": "Wählen Sie unten einen Anbieter aus, um Ihr E-Mail-Konto zu Wino Mail hinzuzufügen.", "ProviderSelection_Subtitle": "Wählen Sie unten einen Anbieter aus, um Ihr E-Mail-Konto zu Wino Mail hinzuzufügen.",
"ProviderSelection_StepProgress": "Schritt {0} von 3",
"ProviderSelection_IdentityTitle": "Kontenidentität",
"ProviderSelection_IdentityDescription": "Wählen Sie aus, wie dieses Konto in Wino angezeigt wird.",
"ProviderSelection_ProviderSectionTitle": "Anbieter",
"ProviderSelection_ProviderSectionDescription": "Wählen Sie den Dienst aus, den Sie verbinden möchten.",
"ProviderSelection_CapabilitySectionTitle": "Verwendung dieses Kontos für",
"ProviderSelection_CapabilitySectionDescription": "Wählen Sie aus, ob Sie Mail, Kalender oder beides verwenden möchten.",
"ProviderSelection_CapabilityProviderDescription_OAuth": "Im nächsten Schritt wird sicheres Sign-in Ihr Konto verbinden. Wenn Sie Kalender aktivieren, verbindet Wino automatisch Outlook-Kalender oder Google Kalender.",
"ProviderSelection_CapabilityProviderDescription_SpecialImap": "Im nächsten Schritt geben Sie Ihre Anmeldeinformationen des Anbieters ein. Mail verwendet IMAP/SMTP, und Kalender kann CalDAV verwenden oder lokal auf diesem Gerät bleiben.",
"ProviderSelection_CapabilityProviderDescription_CustomServer": "Im nächsten Schritt geben Sie Ihre Serverdaten ein. Mail verwendet IMAP/SMTP, und Kalender kann CalDAV verwenden oder lokal auf diesem Gerät bleiben.",
"ProviderSelection_AccountNameHeader": "Kontoname", "ProviderSelection_AccountNameHeader": "Kontoname",
"ProviderSelection_AccountNamePlaceholder": "z. B. Privat, Arbeit", "ProviderSelection_AccountNamePlaceholder": "z. B. Privat, Arbeit",
"ProviderSelection_UseForMail": "Mail",
"ProviderSelection_UseForCalendar": "Kalender",
"ProviderSelection_CapabilityValidationMessage": "Wählen Sie vor dem Fortfahren mindestens eine Funktion.",
"ProviderSelection_CalendarOnlyServerHint": "Wenn Sie nur Kalender verwenden, ist auf der nächsten Seite keine E-Mail-Adresse erforderlich.",
"ProviderSelection_DisplayNameHeader": "Anzeigename", "ProviderSelection_DisplayNameHeader": "Anzeigename",
"ProviderSelection_DisplayNamePlaceholder": "z. B. John Doe", "ProviderSelection_DisplayNamePlaceholder": "z. B. John Doe",
"ProviderSelection_EmailHeader": "E-Mail-Adresse", "ProviderSelection_EmailHeader": "E-Mail-Adresse",
@@ -47,6 +47,11 @@
"AccountDetailsPage_CalendarListDescription": "Επιλέξτε ένα ημερολόγιο για να ορίσετε τις ρυθμίσεις του.", "AccountDetailsPage_CalendarListDescription": "Επιλέξτε ένα ημερολόγιο για να ορίσετε τις ρυθμίσεις του.",
"AccountDetailsPage_InitialSynchronization_Title": "Αρχικός συγχρονισμός", "AccountDetailsPage_InitialSynchronization_Title": "Αρχικός συγχρονισμός",
"AccountDetailsPage_InitialSynchronization_Description": "Ο Wino συγχρόνισε τα μηνύματά σας μέχρι το {0} πίσω.", "AccountDetailsPage_InitialSynchronization_Description": "Ο Wino συγχρόνισε τα μηνύματά σας μέχρι το {0} πίσω.",
"AccountDetailsPage_CapabilityTitle": "Συνδεδεμένες δυνατότητες",
"AccountDetailsPage_CapabilityDescription": "Επιλέξτε αν ο λογαριασμός αυτός χρησιμοποιείται για αλληλογραφία, ημερολόγιο ή και τα δύο. Η ενεργοποίηση μιας νέας δυνατότητας ενδέχεται να σας ζητήσει να συνδεθείτε ξανά.",
"AccountCapability_MailOnly": "Μόνο Αλληλογραφία",
"AccountCapability_CalendarOnly": "Μόνο Ημερολόγιο",
"AccountCapability_MailAndCalendar": "Αλληλογραφία + Ημερολόγιο",
"AddHyperlink": "Προσθήκη", "AddHyperlink": "Προσθήκη",
"AppCloseBackgroundSynchronizationWarningTitle": "Συγχρονισμός Παρασκηνίου", "AppCloseBackgroundSynchronizationWarningTitle": "Συγχρονισμός Παρασκηνίου",
"AppCloseStartupLaunchDisabledWarningMessageFirstLine": "Η εφαρμογή δεν έχει οριστεί για εκκίνηση κατά την έναρξη των Windows.", "AppCloseStartupLaunchDisabledWarningMessageFirstLine": "Η εφαρμογή δεν έχει οριστεί για εκκίνηση κατά την έναρξη των Windows.",
@@ -76,6 +81,7 @@
"Buttons_ApplyTheme": "Εφαρμογή Θέματος", "Buttons_ApplyTheme": "Εφαρμογή Θέματος",
"Buttons_PopOut": "Άνοιγμα σε νέο παράθυρο", "Buttons_PopOut": "Άνοιγμα σε νέο παράθυρο",
"Buttons_Browse": "Περιήγηση", "Buttons_Browse": "Περιήγηση",
"Buttons_Back": "Πίσω",
"Buttons_Cancel": "Ακύρωση", "Buttons_Cancel": "Ακύρωση",
"Buttons_Close": "Κλείσιμο", "Buttons_Close": "Κλείσιμο",
"Buttons_Copy": "Αντιγραφή", "Buttons_Copy": "Αντιγραφή",
@@ -299,6 +305,8 @@
"DialogMessage_DeleteRecurringSeriesTitle": "Διαγραφή Επαναλαμβανόμενης Σειράς", "DialogMessage_DeleteRecurringSeriesTitle": "Διαγραφή Επαναλαμβανόμενης Σειράς",
"DialogMessage_DiscardDraftConfirmationMessage": "Αυτό το πρόχειρο θα απορριφθεί. Θέλετε να συνεχίσετε;", "DialogMessage_DiscardDraftConfirmationMessage": "Αυτό το πρόχειρο θα απορριφθεί. Θέλετε να συνεχίσετε;",
"DialogMessage_DiscardDraftConfirmationTitle": "Απόρριψη προχείρου", "DialogMessage_DiscardDraftConfirmationTitle": "Απόρριψη προχείρου",
"DialogMessage_CloseDraftWindowConfirmationMessage": "Ένα προσχέδιο παραμένει ανοιχτό. Αποθηκεύστε το προτού κλείσετε το παράθυρο;",
"DialogMessage_CloseDraftWindowConfirmationTitle": "Κλείσιμο Παραθύρου",
"DialogMessage_EmptySubjectConfirmation": "Χωρίς Θέμα", "DialogMessage_EmptySubjectConfirmation": "Χωρίς Θέμα",
"DialogMessage_EmptySubjectConfirmationMessage": "Το μήνυμα δεν έχει θέμα. Θέλετε να συνεχίσετε;", "DialogMessage_EmptySubjectConfirmationMessage": "Το μήνυμα δεν έχει θέμα. Θέλετε να συνεχίσετε;",
"DialogMessage_EnableStartupLaunchDeniedMessage": "Μπορείτε να ενεργοποιήσετε την εκκίνηση κατά την έναρξη από τις Ρυθμίσεις -> Προτιμήσεις εφαρμογών.", "DialogMessage_EnableStartupLaunchDeniedMessage": "Μπορείτε να ενεργοποιήσετε την εκκίνηση κατά την έναρξη από τις Ρυθμίσεις -> Προτιμήσεις εφαρμογών.",
@@ -681,6 +689,10 @@
"NoMailSelected": "Δεν επιλέχθηκε μήνυμα", "NoMailSelected": "Δεν επιλέχθηκε μήνυμα",
"NoMessageCrieteria": "Κανένα μήνυμα δεν ταιριάζει με τα κριτήρια αναζήτησής σας", "NoMessageCrieteria": "Κανένα μήνυμα δεν ταιριάζει με τα κριτήρια αναζήτησής σας",
"NoMessageEmptyFolder": "Αυτός ο φάκελος είναι κενός", "NoMessageEmptyFolder": "Αυτός ο φάκελος είναι κενός",
"MailEmptyState_Title": "Δεν υπάρχουν λογαριασμοί με δυνατότητα αλληλογραφίας",
"MailEmptyState_Message": "Έχετε λογαριασμούς συνδεδεμένους για το ημερολόγιο, αλλά κανένας από αυτούς δεν είναι ενεργοποιημένος για αλληλογραφία. Προσθέστε έναν λογαριασμό αλληλογραφίας ή ενημερώστε έναν υπάρχοντα λογαριασμό ώστε να χρησιμοποιεί αλληλογραφία.",
"MailEmptyState_AddAccount": "Προσθήκη λογαριασμού",
"MailEmptyState_ManageAccounts": "Διαχείριση λογαριασμών",
"Notifications_MultipleNotificationsMessage": "Έχετε {0} νέα μηνύματα.", "Notifications_MultipleNotificationsMessage": "Έχετε {0} νέα μηνύματα.",
"Notifications_MultipleNotificationsTitle": "Νέα Αλληλογραφία", "Notifications_MultipleNotificationsTitle": "Νέα Αλληλογραφία",
"Notifications_WinoUpdatedMessage": "Ρίξτε μια ματιά στη νέα έκδοση {0}", "Notifications_WinoUpdatedMessage": "Ρίξτε μια ματιά στη νέα έκδοση {0}",
@@ -824,6 +836,8 @@
"SettingsDeleteAccount_Title": "Διαγραφή αυτού του λογαριασμού", "SettingsDeleteAccount_Title": "Διαγραφή αυτού του λογαριασμού",
"SettingsDeleteProtection_Description": "Should Wino ask you for confirmation every time you try to permanently delete a mail using Shift + Del keys?", "SettingsDeleteProtection_Description": "Should Wino ask you for confirmation every time you try to permanently delete a mail using Shift + Del keys?",
"SettingsDeleteProtection_Title": "Προστασία Μόνιμης Διαγραφής", "SettingsDeleteProtection_Title": "Προστασία Μόνιμης Διαγραφής",
"SettingsEmptyJunkFolderCommand_Description": "Εμφάνιση της εντολής εκκένωσης φακέλου στους φακέλους Junk/Spam. Αυτή η ενέργεια δεν θα ζητήσει επιβεβαίωση και θα διαγράψει αμέσως όλα τα ηλεκτρονικά μηνύματα στον φάκελο Spam.",
"SettingsEmptyJunkFolderCommand_Title": "Εμφάνιση εντολής εκκένωσης φακέλου Spam",
"SettingsDiagnostics_Description": "Για προγραμματιστές", "SettingsDiagnostics_Description": "Για προγραμματιστές",
"SettingsDiagnostics_DiagnosticId_Description": "Μοιραστείτε αυτό το ID με τους προγραμματιστές όταν σας ζητηθεί να λάβετε βοήθεια για τα θέματα που αντιμετωπίζετε στο Wino Mail.", "SettingsDiagnostics_DiagnosticId_Description": "Μοιραστείτε αυτό το ID με τους προγραμματιστές όταν σας ζητηθεί να λάβετε βοήθεια για τα θέματα που αντιμετωπίζετε στο Wino Mail.",
"SettingsDiagnostics_DiagnosticId_Title": "Διαγνωστικό ID", "SettingsDiagnostics_DiagnosticId_Title": "Διαγνωστικό ID",
@@ -1074,6 +1088,12 @@
"SettingsTaskbarBadge_Title": "Σήμα Γραμμής Εργασιών", "SettingsTaskbarBadge_Title": "Σήμα Γραμμής Εργασιών",
"SettingsThreads_Description": "Οργάνωση μηνυμάτων σε νήματα συνομιλίας.", "SettingsThreads_Description": "Οργάνωση μηνυμάτων σε νήματα συνομιλίας.",
"SettingsThreads_Title": "Νηματοποίηση Συζήτησης", "SettingsThreads_Title": "Νηματοποίηση Συζήτησης",
"SettingsThreads_Enabled_Description": "Ομαδοποιήστε σχετικά μηνύματα σε μια ενιαία συνομιλία.",
"SettingsThreads_Enabled_Title": "Ενεργοποίηση ομαδοποίησης συνομιλιών",
"SettingsThreadOrder_Description": "Επιλέξτε πώς ταξινομούνται τα στοιχεία εντός μιας συνομιλίας.",
"SettingsThreadOrder_Title": "Ταξινόμηση στοιχείων συνομιλίας",
"SettingsThreadOrder_LastItemFirst": "Τελευταίο στοιχείο πρώτο",
"SettingsThreadOrder_FirstItemFirst": "Πρώτο στοιχείο πρώτο",
"SettingsUnlinkAccounts_Description": "Αφαιρέστε τη σύνδεση μεταξύ των λογαριασμών. Δε θα διαγράψει τους λογαριασμούς σας.", "SettingsUnlinkAccounts_Description": "Αφαιρέστε τη σύνδεση μεταξύ των λογαριασμών. Δε θα διαγράψει τους λογαριασμούς σας.",
"SettingsUnlinkAccounts_Title": "Αποδέσμευση Λογαριασμών", "SettingsUnlinkAccounts_Title": "Αποδέσμευση Λογαριασμών",
"SettingsMailRendering_ActionLabels_Title": "Action labels", "SettingsMailRendering_ActionLabels_Title": "Action labels",
@@ -1339,6 +1359,7 @@
"WelcomeWindow_GetStartedButton": "Ξεκινήστε προσθέτοντας έναν λογαριασμό", "WelcomeWindow_GetStartedButton": "Ξεκινήστε προσθέτοντας έναν λογαριασμό",
"WelcomeWindow_GetStartedDescription": "Προσθέστε τον λογαριασμό σας Outlook, Gmail ή IMAP για να ξεκινήσετε με το Wino Mail.", "WelcomeWindow_GetStartedDescription": "Προσθέστε τον λογαριασμό σας Outlook, Gmail ή IMAP για να ξεκινήσετε με το Wino Mail.",
"WelcomeWindow_ImportFromWinoAccount": "Εισαγωγή από τον λογαριασμό σας Wino", "WelcomeWindow_ImportFromWinoAccount": "Εισαγωγή από τον λογαριασμό σας Wino",
"WelcomeWindow_ImportFromJsonFile": "Εισαγωγή από αρχείο JSON",
"WelcomeWindow_ImportInProgress": "Εισαγωγή των συγχρονισμένων προτιμήσεων και λογαριασμών σας...", "WelcomeWindow_ImportInProgress": "Εισαγωγή των συγχρονισμένων προτιμήσεων και λογαριασμών σας...",
"WelcomeWindow_ImportNoAccountsFound": "Δεν βρέθηκαν συγχρονισμένοι λογαριασμοί σε αυτόν τον λογαριασμό Wino. Εάν υπήρχαν προτιμήσεις, επαναφέρθηκαν. Χρησιμοποιήστε το Ξεκινήστε για να προσθέσετε έναν λογαριασμό χειροκίνητα.", "WelcomeWindow_ImportNoAccountsFound": "Δεν βρέθηκαν συγχρονισμένοι λογαριασμοί σε αυτόν τον λογαριασμό Wino. Εάν υπήρχαν προτιμήσεις, επαναφέρθηκαν. Χρησιμοποιήστε το Ξεκινήστε για να προσθέσετε έναν λογαριασμό χειροκίνητα.",
"WelcomeWindow_ImportDuplicateAccountsSkipped": "{0} συγχρονισμένοι λογαριασμοί είναι ήδη διαθέσιμοι σε αυτήν τη συσκευή. Χρησιμοποιήστε το Ξεκινήστε για να προσθέσετε ακόμη έναν λογαριασμό χειροκίνητα εάν χρειάζεται.", "WelcomeWindow_ImportDuplicateAccountsSkipped": "{0} συγχρονισμένοι λογαριασμοί είναι ήδη διαθέσιμοι σε αυτήν τη συσκευή. Χρησιμοποιήστε το Ξεκινήστε για να προσθέσετε ακόμη έναν λογαριασμό χειροκίνητα εάν χρειάζεται.",
@@ -1418,6 +1439,12 @@
"WinoAccount_Management_ExportDialog_AccountsDisclaimer": "Κωδικοί πρόσβασης, διακριτικά και άλλες ευαίσθητες πληροφορίες δεν συγχρονίζονται.", "WinoAccount_Management_ExportDialog_AccountsDisclaimer": "Κωδικοί πρόσβασης, διακριτικά και άλλες ευαίσθητες πληροφορίες δεν συγχρονίζονται.",
"WinoAccount_Management_ExportDialog_AccountsRelogin": "Οι εισαγόμενοι λογαριασμοί σε άλλον υπολογιστή θα χρειαστεί να συνδεθείτε ξανά πριν μπορέσουν να χρησιμοποιηθούν.", "WinoAccount_Management_ExportDialog_AccountsRelogin": "Οι εισαγόμενοι λογαριασμοί σε άλλον υπολογιστή θα χρειαστεί να συνδεθείτε ξανά πριν μπορέσουν να χρησιμοποιηθούν.",
"WinoAccount_Management_ExportDialog_InProgress": "Εξάγονται τα επιλεγμένα δεδομένα Wino.", "WinoAccount_Management_ExportDialog_InProgress": "Εξάγονται τα επιλεγμένα δεδομένα Wino.",
"WinoAccount_Management_LocalDataSectionTitle": "Μεταφορά με αρχείο JSON",
"WinoAccount_Management_LocalDataSectionDescription": "Εισαγωγή από ή εξαγωγή σε ένα τοπικό αρχείο JSON. Οι κωδικοί πρόσβασης, τα διακριτικά και άλλες ευαίσθητες πληροφορίες δεν περιλαμβάνονται.",
"WinoAccount_Management_LocalDataImportAction": "Εισαγωγή",
"WinoAccount_Management_LocalDataExportAction": "Εξαγωγή",
"WinoAccount_Management_LocalDataSaved": "Αποθηκεύσατε τα εξαγόμενα δεδομένα Wino στο {0}.",
"WinoAccount_Management_LocalDataInvalidFile": "Το επιλεγμένο αρχείο JSON δεν περιέχει έγκυρη εξαγωγή του Wino.",
"WinoAccount_Management_LoadFailed": "Το Wino δεν μπόρεσε να φορτώσει τις τελευταίες πληροφορίες του Λογαριασμού Wino.", "WinoAccount_Management_LoadFailed": "Το Wino δεν μπόρεσε να φορτώσει τις τελευταίες πληροφορίες του Λογαριασμού Wino.",
"WinoAccount_Management_ActionFailed": "Το αίτημα Λογαριασμού Wino δεν μπόρεσε να ολοκληρωθεί.", "WinoAccount_Management_ActionFailed": "Το αίτημα Λογαριασμού Wino δεν μπόρεσε να ολοκληρωθεί.",
"WinoAccount_SettingsSection_Title": "Λογαριασμός Wino", "WinoAccount_SettingsSection_Title": "Λογαριασμός Wino",
@@ -1514,8 +1541,22 @@
"WelcomeWizard_Step3Title": "Ολοκλήρωση Ρύθμισης", "WelcomeWizard_Step3Title": "Ολοκλήρωση Ρύθμισης",
"ProviderSelection_Title": "Επιλέξτε τον πάροχο email σας", "ProviderSelection_Title": "Επιλέξτε τον πάροχο email σας",
"ProviderSelection_Subtitle": "Επιλέξτε έναν πάροχο παρακάτω για να προσθέσετε τον λογαριασμό email σας στο Wino Mail.", "ProviderSelection_Subtitle": "Επιλέξτε έναν πάροχο παρακάτω για να προσθέσετε τον λογαριασμό email σας στο Wino Mail.",
"ProviderSelection_StepProgress": "Βήμα {0} από 3",
"ProviderSelection_IdentityTitle": "Ταυτότητα λογαριασμού",
"ProviderSelection_IdentityDescription": "Επιλέξτε πώς θα εμφανίζεται αυτός ο λογαριασμός μέσα στο Wino.",
"ProviderSelection_ProviderSectionTitle": "Πάροχος",
"ProviderSelection_ProviderSectionDescription": "Επιλέξτε την υπηρεσία που θέλετε να συνδέσετε.",
"ProviderSelection_CapabilitySectionTitle": "Χρήση αυτού του λογαριασμού για",
"ProviderSelection_CapabilitySectionDescription": "Επιλέξτε αν θέλετε αλληλογραφία, ημερολόγιο ή και τα δύο.",
"ProviderSelection_CapabilityProviderDescription_OAuth": "Στο επόμενο βήμα, μια ασφαλής σύνδεση θα συνδέσει τον λογαριασμό σας. Εάν ενεργοποιήσετε το ημερολόγιο, το Wino θα συνδέσει αυτόματα το Outlook Calendar ή το Google Calendar.",
"ProviderSelection_CapabilityProviderDescription_SpecialImap": "Στο επόμενο βήμα θα εισάγετε τα διαπιστευτήρια παροχέα σας. Το IMAP/SMTP χρησιμοποιείται για το mail, και το ημερολόγιο μπορεί να χρησιμοποιήσει CalDAV ή να παραμείνει τοπικά σε αυτή τη συσκευή.",
"ProviderSelection_CapabilityProviderDescription_CustomServer": "Στο επόμενο βήμα θα εισάγετε τις ρυθμίσεις διακομιστή σας. Το Mail χρησιμοποιεί IMAP/SMTP, και το ημερολόγιο μπορεί να χρησιμοποιήσει CalDAV ή να παραμείνει τοπικά σε αυτή τη συσκευή.",
"ProviderSelection_AccountNameHeader": "Όνομα Λογαριασμού", "ProviderSelection_AccountNameHeader": "Όνομα Λογαριασμού",
"ProviderSelection_AccountNamePlaceholder": "π.χ. Προσωπικό, Εργασία", "ProviderSelection_AccountNamePlaceholder": "π.χ. Προσωπικό, Εργασία",
"ProviderSelection_UseForMail": "Αλληλογραφία",
"ProviderSelection_UseForCalendar": "Ημερολόγιο",
"ProviderSelection_CapabilityValidationMessage": "Επιλέξτε τουλάχιστον μια δυνατότητα πριν συνεχίσετε.",
"ProviderSelection_CalendarOnlyServerHint": "Αν συνεχίσετε μόνο με το ημερολόγιο, η επόμενη σελίδα δεν θα απαιτεί διεύθυνση email.",
"ProviderSelection_DisplayNameHeader": "Όνομα εμφάνισης", "ProviderSelection_DisplayNameHeader": "Όνομα εμφάνισης",
"ProviderSelection_DisplayNamePlaceholder": "π.χ. John Doe", "ProviderSelection_DisplayNamePlaceholder": "π.χ. John Doe",
"ProviderSelection_EmailHeader": "Διεύθυνση Ηλεκτρονικού Ταχυδρομείου", "ProviderSelection_EmailHeader": "Διεύθυνση Ηλεκτρονικού Ταχυδρομείου",
@@ -47,6 +47,11 @@
"AccountDetailsPage_CalendarListDescription": "Select a calendar to configure its settings", "AccountDetailsPage_CalendarListDescription": "Select a calendar to configure its settings",
"AccountDetailsPage_InitialSynchronization_Title": "Initial synchronization", "AccountDetailsPage_InitialSynchronization_Title": "Initial synchronization",
"AccountDetailsPage_InitialSynchronization_Description": "Wino synchronized your mails until {0} going back.", "AccountDetailsPage_InitialSynchronization_Description": "Wino synchronized your mails until {0} going back.",
"AccountDetailsPage_CapabilityTitle": "Connected features",
"AccountDetailsPage_CapabilityDescription": "Choose whether this account is used for mail, calendar, or both. Enabling a new feature may ask you to sign in again.",
"AccountCapability_MailOnly": "Mail only",
"AccountCapability_CalendarOnly": "Calendar only",
"AccountCapability_MailAndCalendar": "Mail + Calendar",
"AddHyperlink": "Add", "AddHyperlink": "Add",
"AppCloseBackgroundSynchronizationWarningTitle": "Background Synchronization", "AppCloseBackgroundSynchronizationWarningTitle": "Background Synchronization",
"AppCloseStartupLaunchDisabledWarningMessageFirstLine": "Application has not been set to launch on Windows startup.", "AppCloseStartupLaunchDisabledWarningMessageFirstLine": "Application has not been set to launch on Windows startup.",
@@ -76,6 +81,7 @@
"Buttons_ApplyTheme": "Apply Theme", "Buttons_ApplyTheme": "Apply Theme",
"Buttons_PopOut": "Pop out", "Buttons_PopOut": "Pop out",
"Buttons_Browse": "Browse", "Buttons_Browse": "Browse",
"Buttons_Back": "Back",
"Buttons_Cancel": "Cancel", "Buttons_Cancel": "Cancel",
"Buttons_Close": "Close", "Buttons_Close": "Close",
"Buttons_Copy": "Copy", "Buttons_Copy": "Copy",
@@ -86,11 +92,13 @@
"Buttons_Discard": "Discard", "Buttons_Discard": "Discard",
"Buttons_Dismiss": "Dismiss", "Buttons_Dismiss": "Dismiss",
"Buttons_Edit": "Edit", "Buttons_Edit": "Edit",
"Buttons_EML": "EML",
"Buttons_EnableImageRendering": "Enable", "Buttons_EnableImageRendering": "Enable",
"Buttons_Multiselect": "Select Multiple", "Buttons_Multiselect": "Select Multiple",
"Buttons_Manage": "Manage", "Buttons_Manage": "Manage",
"Buttons_No": "No", "Buttons_No": "No",
"Buttons_Open": "Open", "Buttons_Open": "Open",
"Buttons_PDF": "PDF",
"Buttons_Purchase": "Purchase", "Buttons_Purchase": "Purchase",
"Buttons_RateWino": "Rate Wino", "Buttons_RateWino": "Rate Wino",
"Buttons_Reset": "Reset", "Buttons_Reset": "Reset",
@@ -299,6 +307,8 @@
"DialogMessage_DeleteRecurringSeriesTitle": "Delete Recurring Series", "DialogMessage_DeleteRecurringSeriesTitle": "Delete Recurring Series",
"DialogMessage_DiscardDraftConfirmationMessage": "This draft will be discarded. Do you want to continue?", "DialogMessage_DiscardDraftConfirmationMessage": "This draft will be discarded. Do you want to continue?",
"DialogMessage_DiscardDraftConfirmationTitle": "Discard Draft", "DialogMessage_DiscardDraftConfirmationTitle": "Discard Draft",
"DialogMessage_CloseDraftWindowConfirmationMessage": "A draft is still open. Save it before closing the window?",
"DialogMessage_CloseDraftWindowConfirmationTitle": "Close Window",
"DialogMessage_EmptySubjectConfirmation": "Missing Subject", "DialogMessage_EmptySubjectConfirmation": "Missing Subject",
"DialogMessage_EmptySubjectConfirmationMessage": "Message has no subject. Do you want to continue?", "DialogMessage_EmptySubjectConfirmationMessage": "Message has no subject. Do you want to continue?",
"DialogMessage_EnableStartupLaunchDeniedMessage": "You can enable startup launch from Settings -> App Preferences.", "DialogMessage_EnableStartupLaunchDeniedMessage": "You can enable startup launch from Settings -> App Preferences.",
@@ -438,7 +448,7 @@
"IMAPAdvancedSetupDialog_ValidationAuthMethodRequired": "Authentication method is required", "IMAPAdvancedSetupDialog_ValidationAuthMethodRequired": "Authentication method is required",
"IMAPAdvancedSetupDialog_ValidationConnectionSecurityRequired": "Connection security type is required", "IMAPAdvancedSetupDialog_ValidationConnectionSecurityRequired": "Connection security type is required",
"IMAPAdvancedSetupDialog_ValidationDisplayNameRequired": "Display name is required", "IMAPAdvancedSetupDialog_ValidationDisplayNameRequired": "Display name is required",
"IMAPAdvancedSetupDialog_ValidationEmailInvalid": "Please enter a valid email address", "IMAPAdvancedSetupDialog_ValidationEmailInvalid": "Please enter a valid mailbox address, such as user@example.com or user@localhost",
"IMAPAdvancedSetupDialog_ValidationEmailRequired": "Email address is required", "IMAPAdvancedSetupDialog_ValidationEmailRequired": "Email address is required",
"IMAPAdvancedSetupDialog_ValidationErrorTitle": "Please check the following:", "IMAPAdvancedSetupDialog_ValidationErrorTitle": "Please check the following:",
"IMAPAdvancedSetupDialog_ValidationIncomingPortInvalid": "Incoming port must be between 1-65535", "IMAPAdvancedSetupDialog_ValidationIncomingPortInvalid": "Incoming port must be between 1-65535",
@@ -485,7 +495,7 @@
"IMAPSetupDialog_IMAPSettings": "IMAP Server Settings", "IMAPSetupDialog_IMAPSettings": "IMAP Server Settings",
"IMAPSetupDialog_SMTPSettings": "SMTP Server Settings", "IMAPSetupDialog_SMTPSettings": "SMTP Server Settings",
"IMAPSetupDialog_MailAddress": "Email address", "IMAPSetupDialog_MailAddress": "Email address",
"IMAPSetupDialog_MailAddressPlaceholder": "someone@example.com", "IMAPSetupDialog_MailAddressPlaceholder": "someone@example.com or user@localhost",
"IMAPSetupDialog_OutgoingMailServer": "Outgoing (SMTP) mail server", "IMAPSetupDialog_OutgoingMailServer": "Outgoing (SMTP) mail server",
"IMAPSetupDialog_OutgoingMailServerPassword": "Outgoing server password", "IMAPSetupDialog_OutgoingMailServerPassword": "Outgoing server password",
"IMAPSetupDialog_OutgoingMailServerPort": "Port", "IMAPSetupDialog_OutgoingMailServerPort": "Port",
@@ -502,7 +512,7 @@
"ImapCalDavSettingsPage_TitleEdit": "Edit IMAP and Calendar Settings", "ImapCalDavSettingsPage_TitleEdit": "Edit IMAP and Calendar Settings",
"ImapCalDavSettingsPage_Subtitle": "Configure IMAP/SMTP and optional calendar synchronization for this account.", "ImapCalDavSettingsPage_Subtitle": "Configure IMAP/SMTP and optional calendar synchronization for this account.",
"ImapCalDavSettingsPage_BasicSectionTitle": "Basic setup", "ImapCalDavSettingsPage_BasicSectionTitle": "Basic setup",
"ImapCalDavSettingsPage_BasicSectionDescription": "Enter your identity and credentials. Wino can try to detect server settings automatically.", "ImapCalDavSettingsPage_BasicSectionDescription": "Enter your identity and credentials. Wino supports manual addresses such as user@localhost and can try to detect server settings automatically.",
"ImapCalDavSettingsPage_BasicTab": "Basic", "ImapCalDavSettingsPage_BasicTab": "Basic",
"ImapCalDavSettingsPage_EnableCalendarSupport": "Enable calendar support", "ImapCalDavSettingsPage_EnableCalendarSupport": "Enable calendar support",
"ImapCalDavSettingsPage_AutoDiscoverButton": "Autodiscover mail settings", "ImapCalDavSettingsPage_AutoDiscoverButton": "Autodiscover mail settings",
@@ -587,6 +597,9 @@
"Info_MessageCorruptedTitle": "Error", "Info_MessageCorruptedTitle": "Error",
"Info_MissingFolderMessage": "{0} doesn't exist for this account.", "Info_MissingFolderMessage": "{0} doesn't exist for this account.",
"Info_MissingFolderTitle": "Missing Folder", "Info_MissingFolderTitle": "Missing Folder",
"Info_EMLSaveFailedTitle": "Failed to save EML file",
"Info_EMLSaveSuccessMessage": "EML file is saved to {0}",
"Info_EMLSaveSuccessTitle": "Success",
"Info_PDFSaveFailedTitle": "Failed to save PDF file", "Info_PDFSaveFailedTitle": "Failed to save PDF file",
"Info_PDFSaveSuccessMessage": "PDF file is saved to {0}", "Info_PDFSaveSuccessMessage": "PDF file is saved to {0}",
"Info_PDFSaveSuccessTitle": "Success", "Info_PDFSaveSuccessTitle": "Success",
@@ -681,12 +694,18 @@
"NoMailSelected": "No message selected", "NoMailSelected": "No message selected",
"NoMessageCrieteria": "No messages match your search criteria", "NoMessageCrieteria": "No messages match your search criteria",
"NoMessageEmptyFolder": "This folder is empty", "NoMessageEmptyFolder": "This folder is empty",
"MailEmptyState_Title": "No mail-enabled accounts",
"MailEmptyState_Message": "You have accounts connected for calendar, but none of them are enabled for mail. Add a mail account or update an existing account to use mail.",
"MailEmptyState_AddAccount": "Add account",
"MailEmptyState_ManageAccounts": "Manage accounts",
"Notifications_MultipleNotificationsMessage": "You have {0} new messages.", "Notifications_MultipleNotificationsMessage": "You have {0} new messages.",
"Notifications_MultipleNotificationsTitle": "New Mail", "Notifications_MultipleNotificationsTitle": "New Mail",
"Notifications_WinoUpdatedMessage": "Checkout new version {0}", "Notifications_WinoUpdatedMessage": "Checkout new version {0}",
"Notifications_WinoUpdatedTitle": "Wino Mail has been updated.", "Notifications_WinoUpdatedTitle": "Wino Mail has been updated.",
"Notifications_StoreUpdateAvailableTitle": "Update available", "Notifications_StoreUpdateAvailableTitle": "Update available",
"Notifications_StoreUpdateAvailableMessage": "A newer version of Wino Mail is ready to install from Microsoft Store.", "Notifications_StoreUpdateAvailableMessage": "A newer version of Wino Mail is ready to install from Microsoft Store.",
"Notifications_ReleaseMigrationTitle": "New Wino Mail & Calendar",
"Notifications_ReleaseMigrationMessage": "Wino Mail got updated to the next version. Please re-create your accounts and start using the next version including calendar, mail templates, shortcuts, and a bunch of other improvements.",
"OnlineSearchFailed_Message": "Failed to perform search\n{0}\n\nListing offline mails.", "OnlineSearchFailed_Message": "Failed to perform search\n{0}\n\nListing offline mails.",
"OnlineSearchTry_Line1": "Can't find what you are looking for?", "OnlineSearchTry_Line1": "Can't find what you are looking for?",
"OnlineSearchTry_Line2": "Try online search.", "OnlineSearchTry_Line2": "Try online search.",
@@ -702,8 +721,8 @@
"ProviderDetail_Gmail_Description": "Google Account", "ProviderDetail_Gmail_Description": "Google Account",
"ProviderDetail_iCloud_Description": "Apple iCloud Account", "ProviderDetail_iCloud_Description": "Apple iCloud Account",
"ProviderDetail_iCloud_Title": "iCloud", "ProviderDetail_iCloud_Title": "iCloud",
"ProviderDetail_IMAP_Description": "Custom IMAP/SMTP server", "ProviderDetail_IMAP_Description": "IMAP/SMTP mail with CalDAV or local calendar",
"ProviderDetail_IMAP_Title": "IMAP Server", "ProviderDetail_IMAP_Title": "Custom server",
"ProviderDetail_Yahoo_Description": "Yahoo Account", "ProviderDetail_Yahoo_Description": "Yahoo Account",
"ProviderDetail_Yahoo_Title": "Yahoo Mail", "ProviderDetail_Yahoo_Title": "Yahoo Mail",
"QuickEventDialog_EventName": "Event name", "QuickEventDialog_EventName": "Event name",
@@ -824,6 +843,8 @@
"SettingsDeleteAccount_Title": "Delete this account", "SettingsDeleteAccount_Title": "Delete this account",
"SettingsDeleteProtection_Description": "Should Wino ask you for confirmation every time you try to permanently delete a mail using Shift + Del keys?", "SettingsDeleteProtection_Description": "Should Wino ask you for confirmation every time you try to permanently delete a mail using Shift + Del keys?",
"SettingsDeleteProtection_Title": "Permanent Delete Protection", "SettingsDeleteProtection_Title": "Permanent Delete Protection",
"SettingsEmptyJunkFolderCommand_Description": "Show the empty-folder command in Junk/Spam folders. This action will not ask for confirmation and will delete all mails in the spam folder immediately.",
"SettingsEmptyJunkFolderCommand_Title": "Show empty spam folder command",
"SettingsDiagnostics_Description": "For developers", "SettingsDiagnostics_Description": "For developers",
"SettingsDiagnostics_DiagnosticId_Description": "Share this ID with the developers when asked to get help for the issues you experience in Wino Mail.", "SettingsDiagnostics_DiagnosticId_Description": "Share this ID with the developers when asked to get help for the issues you experience in Wino Mail.",
"SettingsDiagnostics_DiagnosticId_Title": "Diagnostic ID", "SettingsDiagnostics_DiagnosticId_Title": "Diagnostic ID",
@@ -1074,6 +1095,12 @@
"SettingsTaskbarBadge_Title": "Taskbar Badge", "SettingsTaskbarBadge_Title": "Taskbar Badge",
"SettingsThreads_Description": "Organize messages into conversation threads.", "SettingsThreads_Description": "Organize messages into conversation threads.",
"SettingsThreads_Title": "Conversation Threading", "SettingsThreads_Title": "Conversation Threading",
"SettingsThreads_Enabled_Description": "Group related messages into a single conversation.",
"SettingsThreads_Enabled_Title": "Enable conversation threading",
"SettingsThreadOrder_Description": "Choose how items are ordered inside a conversation thread.",
"SettingsThreadOrder_Title": "Thread item sorting",
"SettingsThreadOrder_LastItemFirst": "Last item first",
"SettingsThreadOrder_FirstItemFirst": "First item first",
"SettingsUnlinkAccounts_Description": "Remove the link between accounts. his will not delete your accounts.", "SettingsUnlinkAccounts_Description": "Remove the link between accounts. his will not delete your accounts.",
"SettingsUnlinkAccounts_Title": "Unlink Accounts", "SettingsUnlinkAccounts_Title": "Unlink Accounts",
"SettingsMailRendering_ActionLabels_Title": "Action labels", "SettingsMailRendering_ActionLabels_Title": "Action labels",
@@ -1421,8 +1448,8 @@
"WinoAccount_Management_ExportDialog_InProgress": "Exporting your selected Wino data...", "WinoAccount_Management_ExportDialog_InProgress": "Exporting your selected Wino data...",
"WinoAccount_Management_LocalDataSectionTitle": "Transfer with a JSON file", "WinoAccount_Management_LocalDataSectionTitle": "Transfer with a JSON file",
"WinoAccount_Management_LocalDataSectionDescription": "Import from or export to a local JSON file. Passwords, tokens, and other sensitive information are not included.", "WinoAccount_Management_LocalDataSectionDescription": "Import from or export to a local JSON file. Passwords, tokens, and other sensitive information are not included.",
"WinoAccount_Management_LocalDataImportAction": "Import JSON", "WinoAccount_Management_LocalDataImportAction": "Import",
"WinoAccount_Management_LocalDataExportAction": "Export JSON", "WinoAccount_Management_LocalDataExportAction": "Export",
"WinoAccount_Management_LocalDataSaved": "Saved your exported Wino data to {0}.", "WinoAccount_Management_LocalDataSaved": "Saved your exported Wino data to {0}.",
"WinoAccount_Management_LocalDataInvalidFile": "The selected JSON file doesn't contain a valid Wino export.", "WinoAccount_Management_LocalDataInvalidFile": "The selected JSON file doesn't contain a valid Wino export.",
"WinoAccount_Management_LoadFailed": "Wino could not load the latest Wino Account information.", "WinoAccount_Management_LoadFailed": "Wino could not load the latest Wino Account information.",
@@ -1521,8 +1548,22 @@
"WelcomeWizard_Step3Title": "Finish Setup", "WelcomeWizard_Step3Title": "Finish Setup",
"ProviderSelection_Title": "Choose your email provider", "ProviderSelection_Title": "Choose your email provider",
"ProviderSelection_Subtitle": "Select a provider below to add your email account to Wino Mail.", "ProviderSelection_Subtitle": "Select a provider below to add your email account to Wino Mail.",
"ProviderSelection_StepProgress": "Step {0} of 3",
"ProviderSelection_IdentityTitle": "Account identity",
"ProviderSelection_IdentityDescription": "Choose how this account appears inside Wino.",
"ProviderSelection_ProviderSectionTitle": "Provider",
"ProviderSelection_ProviderSectionDescription": "Select the service you want to connect.",
"ProviderSelection_CapabilitySectionTitle": "Use this account for",
"ProviderSelection_CapabilitySectionDescription": "Choose whether you want mail, calendar, or both.",
"ProviderSelection_CapabilityProviderDescription_OAuth": "On the next step, secure sign-in will connect your account. If you enable calendar, Wino will also connect Outlook Calendar or Google Calendar automatically.",
"ProviderSelection_CapabilityProviderDescription_SpecialImap": "On the next step, you'll enter your provider credentials. Mail uses IMAP/SMTP, and calendar can use CalDAV or stay local on this device.",
"ProviderSelection_CapabilityProviderDescription_CustomServer": "On the next step, you'll enter your server details. Mail uses IMAP/SMTP, and calendar can use CalDAV or stay local on this device.",
"ProviderSelection_AccountNameHeader": "Account Name", "ProviderSelection_AccountNameHeader": "Account Name",
"ProviderSelection_AccountNamePlaceholder": "e.g. Personal, Work", "ProviderSelection_AccountNamePlaceholder": "e.g. Personal, Work",
"ProviderSelection_UseForMail": "Mail",
"ProviderSelection_UseForCalendar": "Calendar",
"ProviderSelection_CapabilityValidationMessage": "Choose at least one capability before continuing.",
"ProviderSelection_CalendarOnlyServerHint": "If you continue with calendar only, the next page will not require an email address.",
"ProviderSelection_DisplayNameHeader": "Display Name", "ProviderSelection_DisplayNameHeader": "Display Name",
"ProviderSelection_DisplayNamePlaceholder": "e.g. John Doe", "ProviderSelection_DisplayNamePlaceholder": "e.g. John Doe",
"ProviderSelection_EmailHeader": "E-mail Address", "ProviderSelection_EmailHeader": "E-mail Address",
@@ -47,6 +47,11 @@
"AccountDetailsPage_CalendarListDescription": "Selecciona un calendario para configurar sus ajustes", "AccountDetailsPage_CalendarListDescription": "Selecciona un calendario para configurar sus ajustes",
"AccountDetailsPage_InitialSynchronization_Title": "Sincronización inicial", "AccountDetailsPage_InitialSynchronization_Title": "Sincronización inicial",
"AccountDetailsPage_InitialSynchronization_Description": "Wino ha sincronizado tus correos hasta {0} atrás.", "AccountDetailsPage_InitialSynchronization_Description": "Wino ha sincronizado tus correos hasta {0} atrás.",
"AccountDetailsPage_CapabilityTitle": "Características conectadas",
"AccountDetailsPage_CapabilityDescription": "Elija si esta cuenta se utilizará para correo, calendario o ambos. Al habilitar una nueva función podría pedirle que vuelva a iniciar sesión.",
"AccountCapability_MailOnly": "Solo correo",
"AccountCapability_CalendarOnly": "Solo calendario",
"AccountCapability_MailAndCalendar": "Correo y Calendario",
"AddHyperlink": "Añadir", "AddHyperlink": "Añadir",
"AppCloseBackgroundSynchronizationWarningTitle": "Sincronización en segundo plano", "AppCloseBackgroundSynchronizationWarningTitle": "Sincronización en segundo plano",
"AppCloseStartupLaunchDisabledWarningMessageFirstLine": "La aplicación no está configurada para iniciarse con Windows.", "AppCloseStartupLaunchDisabledWarningMessageFirstLine": "La aplicación no está configurada para iniciarse con Windows.",
@@ -76,6 +81,7 @@
"Buttons_ApplyTheme": "Aplicar Tema", "Buttons_ApplyTheme": "Aplicar Tema",
"Buttons_PopOut": "Desanclar", "Buttons_PopOut": "Desanclar",
"Buttons_Browse": "Buscar", "Buttons_Browse": "Buscar",
"Buttons_Back": "Atrás",
"Buttons_Cancel": "Cancelar", "Buttons_Cancel": "Cancelar",
"Buttons_Close": "Cerrar", "Buttons_Close": "Cerrar",
"Buttons_Copy": "Copiar", "Buttons_Copy": "Copiar",
@@ -299,6 +305,8 @@
"DialogMessage_DeleteRecurringSeriesTitle": "Eliminar serie recurrente", "DialogMessage_DeleteRecurringSeriesTitle": "Eliminar serie recurrente",
"DialogMessage_DiscardDraftConfirmationMessage": "Este borrador se descartará. ¿Desea continuar?", "DialogMessage_DiscardDraftConfirmationMessage": "Este borrador se descartará. ¿Desea continuar?",
"DialogMessage_DiscardDraftConfirmationTitle": "Descartar borrador", "DialogMessage_DiscardDraftConfirmationTitle": "Descartar borrador",
"DialogMessage_CloseDraftWindowConfirmationMessage": "Aún hay un borrador abierto. ¿Desea guardarlo antes de cerrar la ventana?",
"DialogMessage_CloseDraftWindowConfirmationTitle": "Cerrar ventana",
"DialogMessage_EmptySubjectConfirmation": "Sin asunto", "DialogMessage_EmptySubjectConfirmation": "Sin asunto",
"DialogMessage_EmptySubjectConfirmationMessage": "El mensaje no tiene asunto. ¿Desea continuar?", "DialogMessage_EmptySubjectConfirmationMessage": "El mensaje no tiene asunto. ¿Desea continuar?",
"DialogMessage_EnableStartupLaunchDeniedMessage": "Puedes habilitar esta opción en cualquier momento desde Ajustes > Configuración de la aplicación.", "DialogMessage_EnableStartupLaunchDeniedMessage": "Puedes habilitar esta opción en cualquier momento desde Ajustes > Configuración de la aplicación.",
@@ -681,6 +689,10 @@
"NoMailSelected": "Ningún mensaje seleccionado", "NoMailSelected": "Ningún mensaje seleccionado",
"NoMessageCrieteria": "Ningún mensaje coincide con su criterio de búsqueda", "NoMessageCrieteria": "Ningún mensaje coincide con su criterio de búsqueda",
"NoMessageEmptyFolder": "Esta carpeta está vacía", "NoMessageEmptyFolder": "Esta carpeta está vacía",
"MailEmptyState_Title": "No hay cuentas habilitadas para correo",
"MailEmptyState_Message": "Tiene cuentas conectadas para el calendario, pero ninguna está habilitada para el correo. Añada una cuenta de correo o actualice una cuenta existente para usar el correo.",
"MailEmptyState_AddAccount": "Añadir cuenta",
"MailEmptyState_ManageAccounts": "Gestionar cuentas",
"Notifications_MultipleNotificationsMessage": "Tienes {0} mensaje(s) nuevo(s).", "Notifications_MultipleNotificationsMessage": "Tienes {0} mensaje(s) nuevo(s).",
"Notifications_MultipleNotificationsTitle": "Mensajes nuevos", "Notifications_MultipleNotificationsTitle": "Mensajes nuevos",
"Notifications_WinoUpdatedMessage": "Comprobar nueva versión {0}", "Notifications_WinoUpdatedMessage": "Comprobar nueva versión {0}",
@@ -824,6 +836,8 @@
"SettingsDeleteAccount_Title": "Eliminar esta cuenta", "SettingsDeleteAccount_Title": "Eliminar esta cuenta",
"SettingsDeleteProtection_Description": "¿Debería Wino pedirte confirmación cada vez que intentas eliminar un correo usando las teclas Shift + Supr?", "SettingsDeleteProtection_Description": "¿Debería Wino pedirte confirmación cada vez que intentas eliminar un correo usando las teclas Shift + Supr?",
"SettingsDeleteProtection_Title": "Protección de Eliminación Permanente", "SettingsDeleteProtection_Title": "Protección de Eliminación Permanente",
"SettingsEmptyJunkFolderCommand_Description": "Mostrar el comando para vaciar la carpeta en las carpetas de correo no deseado. Esta acción no solicitará confirmación y eliminará todos los correos de la carpeta de correo no deseado de inmediato.",
"SettingsEmptyJunkFolderCommand_Title": "Mostrar el comando para vaciar la carpeta de correo no deseado",
"SettingsDiagnostics_Description": "Para desarrolladores", "SettingsDiagnostics_Description": "Para desarrolladores",
"SettingsDiagnostics_DiagnosticId_Description": "Comparte este ID con los desarrolladores cuando se les pida ayuda para los problemas que experimentas en Wino Mail.", "SettingsDiagnostics_DiagnosticId_Description": "Comparte este ID con los desarrolladores cuando se les pida ayuda para los problemas que experimentas en Wino Mail.",
"SettingsDiagnostics_DiagnosticId_Title": "ID de Diagnóstico", "SettingsDiagnostics_DiagnosticId_Title": "ID de Diagnóstico",
@@ -1074,6 +1088,12 @@
"SettingsTaskbarBadge_Title": "Insignia de la barra de tareas", "SettingsTaskbarBadge_Title": "Insignia de la barra de tareas",
"SettingsThreads_Description": "Organizar mensajes en hilos de conversación.", "SettingsThreads_Description": "Organizar mensajes en hilos de conversación.",
"SettingsThreads_Title": "Hilos de conversación", "SettingsThreads_Title": "Hilos de conversación",
"SettingsThreads_Enabled_Description": "Agrupa mensajes relacionados en una sola conversación.",
"SettingsThreads_Enabled_Title": "Habilitar el hilo de conversación",
"SettingsThreadOrder_Description": "Elija cómo se ordenan los elementos dentro de un hilo de conversación.",
"SettingsThreadOrder_Title": "Orden de elementos del hilo",
"SettingsThreadOrder_LastItemFirst": "Último elemento primero",
"SettingsThreadOrder_FirstItemFirst": "Primer elemento primero",
"SettingsUnlinkAccounts_Description": "Eliminar el enlace entre cuentas. No eliminará sus cuentas.", "SettingsUnlinkAccounts_Description": "Eliminar el enlace entre cuentas. No eliminará sus cuentas.",
"SettingsUnlinkAccounts_Title": "Desvincular Cuentas", "SettingsUnlinkAccounts_Title": "Desvincular Cuentas",
"SettingsMailRendering_ActionLabels_Title": "Etiquetas de acción", "SettingsMailRendering_ActionLabels_Title": "Etiquetas de acción",
@@ -1339,6 +1359,7 @@
"WelcomeWindow_GetStartedButton": "Comienza añadiendo una cuenta", "WelcomeWindow_GetStartedButton": "Comienza añadiendo una cuenta",
"WelcomeWindow_GetStartedDescription": "Agrega tu cuenta de Outlook, Gmail o IMAP para empezar a usar Wino Mail.", "WelcomeWindow_GetStartedDescription": "Agrega tu cuenta de Outlook, Gmail o IMAP para empezar a usar Wino Mail.",
"WelcomeWindow_ImportFromWinoAccount": "Importar desde tu cuenta de Wino", "WelcomeWindow_ImportFromWinoAccount": "Importar desde tu cuenta de Wino",
"WelcomeWindow_ImportFromJsonFile": "Importar desde un archivo JSON",
"WelcomeWindow_ImportInProgress": "Importando tus preferencias y cuentas sincronizadas...", "WelcomeWindow_ImportInProgress": "Importando tus preferencias y cuentas sincronizadas...",
"WelcomeWindow_ImportNoAccountsFound": "No se encontraron cuentas sincronizadas en su Cuenta de Wino. Si las preferencias estaban disponibles, se restauraron. Usa Comenzar para añadir una cuenta manualmente.", "WelcomeWindow_ImportNoAccountsFound": "No se encontraron cuentas sincronizadas en su Cuenta de Wino. Si las preferencias estaban disponibles, se restauraron. Usa Comenzar para añadir una cuenta manualmente.",
"WelcomeWindow_ImportDuplicateAccountsSkipped": "{0} cuentas sincronizadas ya están disponibles en este dispositivo. Usa Comenzar para añadir otra cuenta manualmente si es necesario.", "WelcomeWindow_ImportDuplicateAccountsSkipped": "{0} cuentas sincronizadas ya están disponibles en este dispositivo. Usa Comenzar para añadir otra cuenta manualmente si es necesario.",
@@ -1418,6 +1439,12 @@
"WinoAccount_Management_ExportDialog_AccountsDisclaimer": "Las contraseñas, los tokens y otra información sensible no se sincronizan.", "WinoAccount_Management_ExportDialog_AccountsDisclaimer": "Las contraseñas, los tokens y otra información sensible no se sincronizan.",
"WinoAccount_Management_ExportDialog_AccountsRelogin": "Las cuentas importadas en otro PC seguirán requiriéndote iniciar sesión de nuevo antes de poder usarlas.", "WinoAccount_Management_ExportDialog_AccountsRelogin": "Las cuentas importadas en otro PC seguirán requiriéndote iniciar sesión de nuevo antes de poder usarlas.",
"WinoAccount_Management_ExportDialog_InProgress": "Exportando tus datos de Wino seleccionados...", "WinoAccount_Management_ExportDialog_InProgress": "Exportando tus datos de Wino seleccionados...",
"WinoAccount_Management_LocalDataSectionTitle": "Transferir con un archivo JSON",
"WinoAccount_Management_LocalDataSectionDescription": "Importar desde o exportar a un archivo JSON local. Contraseñas, tokens y otra información sensible no se incluyen.",
"WinoAccount_Management_LocalDataImportAction": "Importar",
"WinoAccount_Management_LocalDataExportAction": "Exportar",
"WinoAccount_Management_LocalDataSaved": "Guardó sus datos exportados de Wino en {0}.",
"WinoAccount_Management_LocalDataInvalidFile": "El archivo JSON seleccionado no contiene una exportación válida de Wino.",
"WinoAccount_Management_LoadFailed": "No se pudo cargar la información más reciente de la cuenta de Wino.", "WinoAccount_Management_LoadFailed": "No se pudo cargar la información más reciente de la cuenta de Wino.",
"WinoAccount_Management_ActionFailed": "No se pudo completar la solicitud de la cuenta de Wino.", "WinoAccount_Management_ActionFailed": "No se pudo completar la solicitud de la cuenta de Wino.",
"WinoAccount_SettingsSection_Title": "Cuenta de Wino", "WinoAccount_SettingsSection_Title": "Cuenta de Wino",
@@ -1514,8 +1541,22 @@
"WelcomeWizard_Step3Title": "Finalizar configuración", "WelcomeWizard_Step3Title": "Finalizar configuración",
"ProviderSelection_Title": "Selecciona tu proveedor de correo", "ProviderSelection_Title": "Selecciona tu proveedor de correo",
"ProviderSelection_Subtitle": "Selecciona un proveedor a continuación para añadir tu cuenta de correo a Wino Mail.", "ProviderSelection_Subtitle": "Selecciona un proveedor a continuación para añadir tu cuenta de correo a Wino Mail.",
"ProviderSelection_StepProgress": "Paso {0} de 3",
"ProviderSelection_IdentityTitle": "Identidad de la cuenta",
"ProviderSelection_IdentityDescription": "Elija cómo aparecerá esta cuenta dentro de Wino.",
"ProviderSelection_ProviderSectionTitle": "Proveedor",
"ProviderSelection_ProviderSectionDescription": "Seleccione el servicio que desea conectar.",
"ProviderSelection_CapabilitySectionTitle": "Usar esta cuenta para",
"ProviderSelection_CapabilitySectionDescription": "Elija si desea correo, calendario o ambos.",
"ProviderSelection_CapabilityProviderDescription_OAuth": "En el siguiente paso, el inicio de sesión seguro conectará su cuenta. Si habilita el calendario, Wino también conectará automáticamente Outlook Calendar o Google Calendar.",
"ProviderSelection_CapabilityProviderDescription_SpecialImap": "En el siguiente paso, introducirá sus credenciales del proveedor. El correo utiliza IMAP/SMTP, y el calendario puede usar CalDAV o permanecer local en este dispositivo.",
"ProviderSelection_CapabilityProviderDescription_CustomServer": "En el siguiente paso, introducirá los detalles de su servidor. El correo utiliza IMAP/SMTP, y el calendario puede usar CalDAV o permanecer local en este dispositivo.",
"ProviderSelection_AccountNameHeader": "Nombre de la cuenta", "ProviderSelection_AccountNameHeader": "Nombre de la cuenta",
"ProviderSelection_AccountNamePlaceholder": "p. ej. Personal, Trabajo", "ProviderSelection_AccountNamePlaceholder": "p. ej. Personal, Trabajo",
"ProviderSelection_UseForMail": "Correo",
"ProviderSelection_UseForCalendar": "Calendario",
"ProviderSelection_CapabilityValidationMessage": "Elija al menos una capacidad antes de continuar.",
"ProviderSelection_CalendarOnlyServerHint": "Si continúa solo con el calendario, la página siguiente no requerirá una dirección de correo electrónico.",
"ProviderSelection_DisplayNameHeader": "Nombre para mostrar", "ProviderSelection_DisplayNameHeader": "Nombre para mostrar",
"ProviderSelection_DisplayNamePlaceholder": "p. ej. John Doe", "ProviderSelection_DisplayNamePlaceholder": "p. ej. John Doe",
"ProviderSelection_EmailHeader": "Correo electrónico", "ProviderSelection_EmailHeader": "Correo electrónico",
@@ -47,6 +47,11 @@
"AccountDetailsPage_CalendarListDescription": "Valitse kalenteri määrittääksesi sen asetukset", "AccountDetailsPage_CalendarListDescription": "Valitse kalenteri määrittääksesi sen asetukset",
"AccountDetailsPage_InitialSynchronization_Title": "Ensisynkronointi", "AccountDetailsPage_InitialSynchronization_Title": "Ensisynkronointi",
"AccountDetailsPage_InitialSynchronization_Description": "Wino synkronoi sähköpostisi {0} taaksepäin.", "AccountDetailsPage_InitialSynchronization_Description": "Wino synkronoi sähköpostisi {0} taaksepäin.",
"AccountDetailsPage_CapabilityTitle": "Yhdistetyt ominaisuudet",
"AccountDetailsPage_CapabilityDescription": "Valitse, käytetäänkö tätä tiliä sähköpostiin, kalenteriin vai molempiin. Ominaisuuden käyttöönotto saattaa pyytää sinua kirjautumaan sisään uudelleen.",
"AccountCapability_MailOnly": "Vain sähköposti",
"AccountCapability_CalendarOnly": "Vain kalenteri",
"AccountCapability_MailAndCalendar": "Sähköposti ja Kalenteri",
"AddHyperlink": "Lisää", "AddHyperlink": "Lisää",
"AppCloseBackgroundSynchronizationWarningTitle": "Background Synchronization", "AppCloseBackgroundSynchronizationWarningTitle": "Background Synchronization",
"AppCloseStartupLaunchDisabledWarningMessageFirstLine": "Application has not been set to launch on Windows startup.", "AppCloseStartupLaunchDisabledWarningMessageFirstLine": "Application has not been set to launch on Windows startup.",
@@ -76,6 +81,7 @@
"Buttons_ApplyTheme": "Vaihda teemaa", "Buttons_ApplyTheme": "Vaihda teemaa",
"Buttons_PopOut": "Avaa erillisessä ikkunassa", "Buttons_PopOut": "Avaa erillisessä ikkunassa",
"Buttons_Browse": "Selaa", "Buttons_Browse": "Selaa",
"Buttons_Back": "Takaisin",
"Buttons_Cancel": "Peruuta", "Buttons_Cancel": "Peruuta",
"Buttons_Close": "Sulje", "Buttons_Close": "Sulje",
"Buttons_Copy": "Kopioi", "Buttons_Copy": "Kopioi",
@@ -299,6 +305,8 @@
"DialogMessage_DeleteRecurringSeriesTitle": "Poista toistuva sarja", "DialogMessage_DeleteRecurringSeriesTitle": "Poista toistuva sarja",
"DialogMessage_DiscardDraftConfirmationMessage": "Luonnos hylätään. Haluatko jatkaa?", "DialogMessage_DiscardDraftConfirmationMessage": "Luonnos hylätään. Haluatko jatkaa?",
"DialogMessage_DiscardDraftConfirmationTitle": "Hylkää luonnos", "DialogMessage_DiscardDraftConfirmationTitle": "Hylkää luonnos",
"DialogMessage_CloseDraftWindowConfirmationMessage": "Luonnos on vielä auki. Tallenna se ennen ikkunan sulkemista?",
"DialogMessage_CloseDraftWindowConfirmationTitle": "Sulje ikkuna",
"DialogMessage_EmptySubjectConfirmation": "Aihe puuttuu", "DialogMessage_EmptySubjectConfirmation": "Aihe puuttuu",
"DialogMessage_EmptySubjectConfirmationMessage": "Viestillä ei ole aihetta. Haluatko jatkaa?", "DialogMessage_EmptySubjectConfirmationMessage": "Viestillä ei ole aihetta. Haluatko jatkaa?",
"DialogMessage_EnableStartupLaunchDeniedMessage": "You can enable startup launch from Settings -> App Preferences.", "DialogMessage_EnableStartupLaunchDeniedMessage": "You can enable startup launch from Settings -> App Preferences.",
@@ -681,6 +689,10 @@
"NoMailSelected": "Ei viestiä valittuna", "NoMailSelected": "Ei viestiä valittuna",
"NoMessageCrieteria": "Mikään viesti ei vastaa hakuasi", "NoMessageCrieteria": "Mikään viesti ei vastaa hakuasi",
"NoMessageEmptyFolder": "Kansio tyhjä", "NoMessageEmptyFolder": "Kansio tyhjä",
"MailEmptyState_Title": "Ei sähköpostia tukevia tilejä",
"MailEmptyState_Message": "Sinulla on tilejä, jotka on yhdistetty kalenteriin, mutta mikään niistä ei ole käytössä sähköpostin kannalta. Lisää sähköpostitili tai päivitä jokin olemassa oleva tili käyttämään sähköpostia.",
"MailEmptyState_AddAccount": "Lisää tili",
"MailEmptyState_ManageAccounts": "Hallitse tilejä",
"Notifications_MultipleNotificationsMessage": "You have {0} new messages.", "Notifications_MultipleNotificationsMessage": "You have {0} new messages.",
"Notifications_MultipleNotificationsTitle": "New Mail", "Notifications_MultipleNotificationsTitle": "New Mail",
"Notifications_WinoUpdatedMessage": "Tarkasta uusi versio {0}", "Notifications_WinoUpdatedMessage": "Tarkasta uusi versio {0}",
@@ -824,6 +836,8 @@
"SettingsDeleteAccount_Title": "Delete this account", "SettingsDeleteAccount_Title": "Delete this account",
"SettingsDeleteProtection_Description": "Should Wino ask you for confirmation every time you try to permanently delete a mail using Shift + Del keys?", "SettingsDeleteProtection_Description": "Should Wino ask you for confirmation every time you try to permanently delete a mail using Shift + Del keys?",
"SettingsDeleteProtection_Title": "Permanent Delete Protection", "SettingsDeleteProtection_Title": "Permanent Delete Protection",
"SettingsEmptyJunkFolderCommand_Description": "Näytä roskapostikansioiden tyhjennyskomento. Tämä toimenpide ei kysy vahvistusta ja poistaa välittömästi kaikki sähköpostit roskapostikansioista.",
"SettingsEmptyJunkFolderCommand_Title": "Näytä roskapostikansioiden tyhjennyskomento",
"SettingsDiagnostics_Description": "For developers", "SettingsDiagnostics_Description": "For developers",
"SettingsDiagnostics_DiagnosticId_Description": "Share this ID with the developers when asked to get help for the issues you experience in Wino Mail.", "SettingsDiagnostics_DiagnosticId_Description": "Share this ID with the developers when asked to get help for the issues you experience in Wino Mail.",
"SettingsDiagnostics_DiagnosticId_Title": "Diagnostic ID", "SettingsDiagnostics_DiagnosticId_Title": "Diagnostic ID",
@@ -1074,6 +1088,12 @@
"SettingsTaskbarBadge_Title": "Taskbar Badge", "SettingsTaskbarBadge_Title": "Taskbar Badge",
"SettingsThreads_Description": "Organize messages into conversation threads.", "SettingsThreads_Description": "Organize messages into conversation threads.",
"SettingsThreads_Title": "Conversation Threading", "SettingsThreads_Title": "Conversation Threading",
"SettingsThreads_Enabled_Description": "Ryhmittele liittyvät viestit yhdeksi keskusteluksi.",
"SettingsThreads_Enabled_Title": "Ota keskusteluketjutus käyttöön",
"SettingsThreadOrder_Description": "Valitse, miten kohteet järjestetään keskusteluketjussa.",
"SettingsThreadOrder_Title": "Ketjun kohteiden lajittelu",
"SettingsThreadOrder_LastItemFirst": "Viimeinen kohde ensin",
"SettingsThreadOrder_FirstItemFirst": "Ensimmäinen kohde ensin",
"SettingsUnlinkAccounts_Description": "Remove the link between accounts. his will not delete your accounts.", "SettingsUnlinkAccounts_Description": "Remove the link between accounts. his will not delete your accounts.",
"SettingsUnlinkAccounts_Title": "Unlink Accounts", "SettingsUnlinkAccounts_Title": "Unlink Accounts",
"SettingsMailRendering_ActionLabels_Title": "Action labels", "SettingsMailRendering_ActionLabels_Title": "Action labels",
@@ -1339,6 +1359,7 @@
"WelcomeWindow_GetStartedButton": "Aloita lisäämällä tilin", "WelcomeWindow_GetStartedButton": "Aloita lisäämällä tilin",
"WelcomeWindow_GetStartedDescription": "Lisää Outlook-, Gmail- tai IMAP-tili aloittaaksesi Wino Mailin käytön.", "WelcomeWindow_GetStartedDescription": "Lisää Outlook-, Gmail- tai IMAP-tili aloittaaksesi Wino Mailin käytön.",
"WelcomeWindow_ImportFromWinoAccount": "Tuo Wino-tililtäsi", "WelcomeWindow_ImportFromWinoAccount": "Tuo Wino-tililtäsi",
"WelcomeWindow_ImportFromJsonFile": "Tuo JSON-tiedosto",
"WelcomeWindow_ImportInProgress": "Tuodaan synkronoitujen asetusten ja tilien tiedot...", "WelcomeWindow_ImportInProgress": "Tuodaan synkronoitujen asetusten ja tilien tiedot...",
"WelcomeWindow_ImportNoAccountsFound": "Wino-tililläsi ei löytynyt synkronoituja tilejä. Jos asetukset olivat käytettävissä, ne palautettiin. Käytä Aloita tilin lisäämisen manuaalisesti.", "WelcomeWindow_ImportNoAccountsFound": "Wino-tililläsi ei löytynyt synkronoituja tilejä. Jos asetukset olivat käytettävissä, ne palautettiin. Käytä Aloita tilin lisäämisen manuaalisesti.",
"WelcomeWindow_ImportDuplicateAccountsSkipped": "{0} synkronoitua tiliä on jo käytettävissä tässä laitteessa. Käytä Aloita tilin lisääminen manuaalisesti, jos tarvitset toisen tilin.", "WelcomeWindow_ImportDuplicateAccountsSkipped": "{0} synkronoitua tiliä on jo käytettävissä tässä laitteessa. Käytä Aloita tilin lisääminen manuaalisesti, jos tarvitset toisen tilin.",
@@ -1418,6 +1439,12 @@
"WinoAccount_Management_ExportDialog_AccountsDisclaimer": "Salasanat, tunnukset ja muut arkaluonteiset tiedot eivät synkronoidu.", "WinoAccount_Management_ExportDialog_AccountsDisclaimer": "Salasanat, tunnukset ja muut arkaluonteiset tiedot eivät synkronoidu.",
"WinoAccount_Management_ExportDialog_AccountsRelogin": "Toisella tietokoneella tuodut tilit vaativat vielä uudelleen kirjautumisen ennen kuin niitä voidaan käyttää.", "WinoAccount_Management_ExportDialog_AccountsRelogin": "Toisella tietokoneella tuodut tilit vaativat vielä uudelleen kirjautumisen ennen kuin niitä voidaan käyttää.",
"WinoAccount_Management_ExportDialog_InProgress": "Viedään valitut Wino-tiedot...", "WinoAccount_Management_ExportDialog_InProgress": "Viedään valitut Wino-tiedot...",
"WinoAccount_Management_LocalDataSectionTitle": "Siirrä JSON-tiedoston avulla",
"WinoAccount_Management_LocalDataSectionDescription": "Tuo tai vie paikalliseen JSON-tiedostoon. Salasanat, tokenit ja muut arkaluontoiset tiedot eivät sisälly.",
"WinoAccount_Management_LocalDataImportAction": "Tuo",
"WinoAccount_Management_LocalDataExportAction": "Vie",
"WinoAccount_Management_LocalDataSaved": "Tallensin vietyt Wino-tiedot kohteeseen {0}.",
"WinoAccount_Management_LocalDataInvalidFile": "Valittu JSON-tiedosto ei sisällä kelvollista Wino-vientiä.",
"WinoAccount_Management_LoadFailed": "Wino ei voinut ladata uusinta Wino-tilin tietoa.", "WinoAccount_Management_LoadFailed": "Wino ei voinut ladata uusinta Wino-tilin tietoa.",
"WinoAccount_Management_ActionFailed": "Wino-tilin pyyntöä ei voitu suorittaa.", "WinoAccount_Management_ActionFailed": "Wino-tilin pyyntöä ei voitu suorittaa.",
"WinoAccount_SettingsSection_Title": "Wino-tili", "WinoAccount_SettingsSection_Title": "Wino-tili",
@@ -1514,8 +1541,22 @@
"WelcomeWizard_Step3Title": "Viimeistele asennus", "WelcomeWizard_Step3Title": "Viimeistele asennus",
"ProviderSelection_Title": "Valitse sähköpostipalveluntarjoajasi", "ProviderSelection_Title": "Valitse sähköpostipalveluntarjoajasi",
"ProviderSelection_Subtitle": "Valitse alla oleva palveluntarjoaja lisätäksesi sähköpostitilisi Wino Mailiin.", "ProviderSelection_Subtitle": "Valitse alla oleva palveluntarjoaja lisätäksesi sähköpostitilisi Wino Mailiin.",
"ProviderSelection_StepProgress": "Vaihe {0} / 3",
"ProviderSelection_IdentityTitle": "Tilin identiteetti",
"ProviderSelection_IdentityDescription": "Valitse, miltä tili näyttää Wino-sovelluksessa.",
"ProviderSelection_ProviderSectionTitle": "Palveluntarjoaja",
"ProviderSelection_ProviderSectionDescription": "Valitse yhdistettävä palvelu.",
"ProviderSelection_CapabilitySectionTitle": "Käytä tätä tiliä seuraaviin",
"ProviderSelection_CapabilitySectionDescription": "Valitse, haluatko käyttää sähköpostia, kalenteria vai molempia.",
"ProviderSelection_CapabilityProviderDescription_OAuth": "Seuraavassa vaiheessa turvallinen sisäänkirjautuminen yhdistää tilisi. Jos otat kalenterin käyttöön, Wino yhdistää automaattisesti Outlook Kalenterin tai Google Kalenterin.",
"ProviderSelection_CapabilityProviderDescription_SpecialImap": "Seuraavassa vaiheessa syötät palveluntarjoajan tunnistetiedot. Sähköposti käyttää IMAP/SMTP, ja kalenteri voi käyttää CalDAV:ia tai pysyä paikallisena tässä laitteessa.",
"ProviderSelection_CapabilityProviderDescription_CustomServer": "Seuraavassa vaiheessa syötät palvelimen tiedot. Sähköposti käyttää IMAP/SMTP, ja kalenteri voi käyttää CalDAV:ia tai pysyä paikallisena tässä laitteessa.",
"ProviderSelection_AccountNameHeader": "Tilin nimi", "ProviderSelection_AccountNameHeader": "Tilin nimi",
"ProviderSelection_AccountNamePlaceholder": "esim. Henkilökohtainen, Työ", "ProviderSelection_AccountNamePlaceholder": "esim. Henkilökohtainen, Työ",
"ProviderSelection_UseForMail": "Sähköposti",
"ProviderSelection_UseForCalendar": "Kalenteri",
"ProviderSelection_CapabilityValidationMessage": "Jatkaaksesi valitse vähintään yksi ominaisuus.",
"ProviderSelection_CalendarOnlyServerHint": "Jos jatkat vain kalenterin kanssa, seuraavalla sivulla sähköpostiosoitetta ei tarvita.",
"ProviderSelection_DisplayNameHeader": "Näytettävä nimi", "ProviderSelection_DisplayNameHeader": "Näytettävä nimi",
"ProviderSelection_DisplayNamePlaceholder": "esim. John Doe", "ProviderSelection_DisplayNamePlaceholder": "esim. John Doe",
"ProviderSelection_EmailHeader": "Sähköpostiosoite", "ProviderSelection_EmailHeader": "Sähköpostiosoite",
@@ -47,6 +47,11 @@
"AccountDetailsPage_CalendarListDescription": "Sélectionnez un calendrier pour configurer ses paramètres.", "AccountDetailsPage_CalendarListDescription": "Sélectionnez un calendrier pour configurer ses paramètres.",
"AccountDetailsPage_InitialSynchronization_Title": "Synchronisation initiale", "AccountDetailsPage_InitialSynchronization_Title": "Synchronisation initiale",
"AccountDetailsPage_InitialSynchronization_Description": "Wino a synchronisé vos messages jusqu'au {0} en remontant.", "AccountDetailsPage_InitialSynchronization_Description": "Wino a synchronisé vos messages jusqu'au {0} en remontant.",
"AccountDetailsPage_CapabilityTitle": "Fonctionnalités connectées",
"AccountDetailsPage_CapabilityDescription": "Choisissez si ce compte est utilisé pour le courrier, le calendrier, ou les deux. L'activation d'une nouvelle fonctionnalité peut vous demander de vous reconnecter.",
"AccountCapability_MailOnly": "Courrier uniquement",
"AccountCapability_CalendarOnly": "Calendrier uniquement",
"AccountCapability_MailAndCalendar": "Courrier + Calendrier",
"AddHyperlink": "Ajouter", "AddHyperlink": "Ajouter",
"AppCloseBackgroundSynchronizationWarningTitle": "Synchronisation en arrière-plan", "AppCloseBackgroundSynchronizationWarningTitle": "Synchronisation en arrière-plan",
"AppCloseStartupLaunchDisabledWarningMessageFirstLine": "L'application n'a pas été configurée pour être lancée au démarrage de Windows.", "AppCloseStartupLaunchDisabledWarningMessageFirstLine": "L'application n'a pas été configurée pour être lancée au démarrage de Windows.",
@@ -76,6 +81,7 @@
"Buttons_ApplyTheme": "Appliquer le thème", "Buttons_ApplyTheme": "Appliquer le thème",
"Buttons_PopOut": "Détacher", "Buttons_PopOut": "Détacher",
"Buttons_Browse": "Parcourir", "Buttons_Browse": "Parcourir",
"Buttons_Back": "Retour",
"Buttons_Cancel": "Annuler", "Buttons_Cancel": "Annuler",
"Buttons_Close": "Fermer", "Buttons_Close": "Fermer",
"Buttons_Copy": "Copier", "Buttons_Copy": "Copier",
@@ -299,6 +305,8 @@
"DialogMessage_DeleteRecurringSeriesTitle": "Supprimer la série récurrente", "DialogMessage_DeleteRecurringSeriesTitle": "Supprimer la série récurrente",
"DialogMessage_DiscardDraftConfirmationMessage": "Ce brouillon sera supprimé. Voulez-vous continuer ?", "DialogMessage_DiscardDraftConfirmationMessage": "Ce brouillon sera supprimé. Voulez-vous continuer ?",
"DialogMessage_DiscardDraftConfirmationTitle": "Supprimer le brouillon", "DialogMessage_DiscardDraftConfirmationTitle": "Supprimer le brouillon",
"DialogMessage_CloseDraftWindowConfirmationMessage": "Un brouillon est encore ouvert. Enregistrez-le avant de fermer la fenêtre ?",
"DialogMessage_CloseDraftWindowConfirmationTitle": "Fermer la fenêtre",
"DialogMessage_EmptySubjectConfirmation": "Objet manquant", "DialogMessage_EmptySubjectConfirmation": "Objet manquant",
"DialogMessage_EmptySubjectConfirmationMessage": "Le message n'a pas d'objet. Voulez-vous continuer ?", "DialogMessage_EmptySubjectConfirmationMessage": "Le message n'a pas d'objet. Voulez-vous continuer ?",
"DialogMessage_EnableStartupLaunchDeniedMessage": "Vous pouvez activer le lancement au démarrage depuis Paramètres -> Préférences de l'application.", "DialogMessage_EnableStartupLaunchDeniedMessage": "Vous pouvez activer le lancement au démarrage depuis Paramètres -> Préférences de l'application.",
@@ -681,6 +689,10 @@
"NoMailSelected": "Aucun message sélectionné", "NoMailSelected": "Aucun message sélectionné",
"NoMessageCrieteria": "Aucun message ne correspond à vos critères de recherche", "NoMessageCrieteria": "Aucun message ne correspond à vos critères de recherche",
"NoMessageEmptyFolder": "Ce dossier est vide", "NoMessageEmptyFolder": "Ce dossier est vide",
"MailEmptyState_Title": "Aucun compte activé pour le courrier",
"MailEmptyState_Message": "Vous avez des comptes connectés au calendrier, mais aucun dentre eux nest activé pour le courrier. Ajoutez un compte de courrier ou mettez à jour un compte existant pour utiliser le courrier.",
"MailEmptyState_AddAccount": "Ajouter un compte",
"MailEmptyState_ManageAccounts": "Gérer les comptes",
"Notifications_MultipleNotificationsMessage": "Vous avez {0} nouveaux messages.", "Notifications_MultipleNotificationsMessage": "Vous avez {0} nouveaux messages.",
"Notifications_MultipleNotificationsTitle": "Nouveau message", "Notifications_MultipleNotificationsTitle": "Nouveau message",
"Notifications_WinoUpdatedMessage": "Vérifier la nouvelle version {0}", "Notifications_WinoUpdatedMessage": "Vérifier la nouvelle version {0}",
@@ -824,6 +836,8 @@
"SettingsDeleteAccount_Title": "Supprimer ce compte", "SettingsDeleteAccount_Title": "Supprimer ce compte",
"SettingsDeleteProtection_Description": "Should Wino ask you for confirmation every time you try to permanently delete a mail using Shift + Del keys?", "SettingsDeleteProtection_Description": "Should Wino ask you for confirmation every time you try to permanently delete a mail using Shift + Del keys?",
"SettingsDeleteProtection_Title": "Protection contre la suppression permanente", "SettingsDeleteProtection_Title": "Protection contre la suppression permanente",
"SettingsEmptyJunkFolderCommand_Description": "Afficher la commande de vidage du dossier dans les dossiers de courrier indésirable. Cette action ne demandera pas de confirmation et supprimera immédiatement tous les courriels du dossier de courrier indésirable.",
"SettingsEmptyJunkFolderCommand_Title": "Afficher la commande pour vider le dossier de courrier indésirable",
"SettingsDiagnostics_Description": "Pour les développeurs", "SettingsDiagnostics_Description": "Pour les développeurs",
"SettingsDiagnostics_DiagnosticId_Description": "Partagez cet identifiant avec les développeurs lorsqu'ils vous aideront à résoudre les problèmes que vous rencontrez dans Wino Mail.", "SettingsDiagnostics_DiagnosticId_Description": "Partagez cet identifiant avec les développeurs lorsqu'ils vous aideront à résoudre les problèmes que vous rencontrez dans Wino Mail.",
"SettingsDiagnostics_DiagnosticId_Title": "ID de diagnostic", "SettingsDiagnostics_DiagnosticId_Title": "ID de diagnostic",
@@ -1074,6 +1088,12 @@
"SettingsTaskbarBadge_Title": "Badge de la barre de tâches", "SettingsTaskbarBadge_Title": "Badge de la barre de tâches",
"SettingsThreads_Description": "Organiser les messages en fils de conversation.", "SettingsThreads_Description": "Organiser les messages en fils de conversation.",
"SettingsThreads_Title": "Affichage en mode conversation", "SettingsThreads_Title": "Affichage en mode conversation",
"SettingsThreads_Enabled_Description": "Regrouper les messages liés en une seule conversation.",
"SettingsThreads_Enabled_Title": "Activer le fil de discussion",
"SettingsThreadOrder_Description": "Choisissez l'ordre des éléments dans un fil de discussion.",
"SettingsThreadOrder_Title": "Tri des éléments du fil de discussion",
"SettingsThreadOrder_LastItemFirst": "Dernier élément en premier",
"SettingsThreadOrder_FirstItemFirst": "Premier élément en premier",
"SettingsUnlinkAccounts_Description": "Supprimer le lien entre les comptes. Cela ne supprimera pas vos comptes.", "SettingsUnlinkAccounts_Description": "Supprimer le lien entre les comptes. Cela ne supprimera pas vos comptes.",
"SettingsUnlinkAccounts_Title": "Dissocier les comptes", "SettingsUnlinkAccounts_Title": "Dissocier les comptes",
"SettingsMailRendering_ActionLabels_Title": "Action labels", "SettingsMailRendering_ActionLabels_Title": "Action labels",
@@ -1339,6 +1359,7 @@
"WelcomeWindow_GetStartedButton": "Commencer en ajoutant un compte", "WelcomeWindow_GetStartedButton": "Commencer en ajoutant un compte",
"WelcomeWindow_GetStartedDescription": "Ajoutez votre compte Outlook, Gmail ou IMAP pour commencer avec Wino Mail.", "WelcomeWindow_GetStartedDescription": "Ajoutez votre compte Outlook, Gmail ou IMAP pour commencer avec Wino Mail.",
"WelcomeWindow_ImportFromWinoAccount": "Importer depuis votre compte Wino", "WelcomeWindow_ImportFromWinoAccount": "Importer depuis votre compte Wino",
"WelcomeWindow_ImportFromJsonFile": "Importer à partir d'un fichier JSON",
"WelcomeWindow_ImportInProgress": "Importation de vos préférences et comptes synchronisés...", "WelcomeWindow_ImportInProgress": "Importation de vos préférences et comptes synchronisés...",
"WelcomeWindow_ImportNoAccountsFound": "Aucun compte synchronisé n'a été trouvé dans votre compte Wino. Si des préférences étaient disponibles, elles ont été restaurées. Utilisez Commencer pour ajouter manuellement un compte.", "WelcomeWindow_ImportNoAccountsFound": "Aucun compte synchronisé n'a été trouvé dans votre compte Wino. Si des préférences étaient disponibles, elles ont été restaurées. Utilisez Commencer pour ajouter manuellement un compte.",
"WelcomeWindow_ImportDuplicateAccountsSkipped": "{0} comptes synchronisés sont déjà disponibles sur cet appareil. Utilisez Commencer pour en ajouter un autre manuellement si nécessaire.", "WelcomeWindow_ImportDuplicateAccountsSkipped": "{0} comptes synchronisés sont déjà disponibles sur cet appareil. Utilisez Commencer pour en ajouter un autre manuellement si nécessaire.",
@@ -1418,6 +1439,12 @@
"WinoAccount_Management_ExportDialog_AccountsDisclaimer": "Les mots de passe, jetons et autres informations sensibles ne sont pas synchronisés.", "WinoAccount_Management_ExportDialog_AccountsDisclaimer": "Les mots de passe, jetons et autres informations sensibles ne sont pas synchronisés.",
"WinoAccount_Management_ExportDialog_AccountsRelogin": "Les comptes importés sur un autre PC devront quand même être reconnectés avant de pouvoir être utilisés.", "WinoAccount_Management_ExportDialog_AccountsRelogin": "Les comptes importés sur un autre PC devront quand même être reconnectés avant de pouvoir être utilisés.",
"WinoAccount_Management_ExportDialog_InProgress": "Exportation de vos données Wino sélectionnées...", "WinoAccount_Management_ExportDialog_InProgress": "Exportation de vos données Wino sélectionnées...",
"WinoAccount_Management_LocalDataSectionTitle": "Transfert via un fichier JSON",
"WinoAccount_Management_LocalDataSectionDescription": "Importer ou exporter vers un fichier JSON local. Les mots de passe, jetons et autres informations sensibles ne sont pas incluses.",
"WinoAccount_Management_LocalDataImportAction": "Importer",
"WinoAccount_Management_LocalDataExportAction": "Exporter",
"WinoAccount_Management_LocalDataSaved": "Vos données Wino exportées ont été sauvegardées dans {0}.",
"WinoAccount_Management_LocalDataInvalidFile": "Le fichier JSON sélectionné ne contient pas d'export Wino valide.",
"WinoAccount_Management_LoadFailed": "Wino n'a pas pu charger les dernières informations du compte Wino.", "WinoAccount_Management_LoadFailed": "Wino n'a pas pu charger les dernières informations du compte Wino.",
"WinoAccount_Management_ActionFailed": "La requête du compte Wino n'a pas pu être complétée.", "WinoAccount_Management_ActionFailed": "La requête du compte Wino n'a pas pu être complétée.",
"WinoAccount_SettingsSection_Title": "Compte Wino", "WinoAccount_SettingsSection_Title": "Compte Wino",
@@ -1514,8 +1541,22 @@
"WelcomeWizard_Step3Title": "Terminer la configuration", "WelcomeWizard_Step3Title": "Terminer la configuration",
"ProviderSelection_Title": "Choisissez votre fournisseur de messagerie", "ProviderSelection_Title": "Choisissez votre fournisseur de messagerie",
"ProviderSelection_Subtitle": "Sélectionnez un fournisseur ci-dessous pour ajouter votre compte de messagerie à Wino Mail.", "ProviderSelection_Subtitle": "Sélectionnez un fournisseur ci-dessous pour ajouter votre compte de messagerie à Wino Mail.",
"ProviderSelection_StepProgress": "Étape {0} sur 3",
"ProviderSelection_IdentityTitle": "Identité du compte",
"ProviderSelection_IdentityDescription": "Choisissez comment ce compte apparaît dans Wino.",
"ProviderSelection_ProviderSectionTitle": "Fournisseur",
"ProviderSelection_ProviderSectionDescription": "Sélectionnez le service que vous souhaitez connecter.",
"ProviderSelection_CapabilitySectionTitle": "Utiliser ce compte pour",
"ProviderSelection_CapabilitySectionDescription": "Choisissez si vous souhaitez le courrier, le calendrier, ou les deux.",
"ProviderSelection_CapabilityProviderDescription_OAuth": "À l'étape suivante, une connexion sécurisée reliera votre compte. Si vous activez le calendrier, Wino connectera automatiquement Outlook Calendar ou Google Calendar.",
"ProviderSelection_CapabilityProviderDescription_SpecialImap": "À l'étape suivante, vous saisirez vos identifiants du fournisseur. Le courrier utilise IMAP/SMTP, et le calendrier peut utiliser CalDAV ou rester local sur cet appareil.",
"ProviderSelection_CapabilityProviderDescription_CustomServer": "À l'étape suivante, vous saisirez les détails du serveur. Le courrier utilise IMAP/SMTP, et le calendrier peut utiliser CalDAV ou rester local sur cet appareil.",
"ProviderSelection_AccountNameHeader": "Nom du compte", "ProviderSelection_AccountNameHeader": "Nom du compte",
"ProviderSelection_AccountNamePlaceholder": "par ex. Personnel, Professionnel", "ProviderSelection_AccountNamePlaceholder": "par ex. Personnel, Professionnel",
"ProviderSelection_UseForMail": "Courrier",
"ProviderSelection_UseForCalendar": "Calendrier",
"ProviderSelection_CapabilityValidationMessage": "Choisissez au moins une capacité avant de continuer.",
"ProviderSelection_CalendarOnlyServerHint": "Si vous continuez avec le calendrier uniquement, la page suivante ne nécessitera pas d'adresse e-mail.",
"ProviderSelection_DisplayNameHeader": "Nom affiché", "ProviderSelection_DisplayNameHeader": "Nom affiché",
"ProviderSelection_DisplayNamePlaceholder": "par ex. John Doe", "ProviderSelection_DisplayNamePlaceholder": "par ex. John Doe",
"ProviderSelection_EmailHeader": "Adresse e-mail", "ProviderSelection_EmailHeader": "Adresse e-mail",
@@ -47,6 +47,11 @@
"AccountDetailsPage_CalendarListDescription": "Selecciona un calendario para configurar as súas configuracións.", "AccountDetailsPage_CalendarListDescription": "Selecciona un calendario para configurar as súas configuracións.",
"AccountDetailsPage_InitialSynchronization_Title": "Sincronización inicial", "AccountDetailsPage_InitialSynchronization_Title": "Sincronización inicial",
"AccountDetailsPage_InitialSynchronization_Description": "Wino sincronizou os teus correos ata {0} no pasado.", "AccountDetailsPage_InitialSynchronization_Description": "Wino sincronizou os teus correos ata {0} no pasado.",
"AccountDetailsPage_CapabilityTitle": "Características conectadas",
"AccountDetailsPage_CapabilityDescription": "Elixe se esta conta se usa para correo, calendario ou para ambos. Activar unha nova función pode pedirche que inicies sesión de novo.",
"AccountCapability_MailOnly": "Só correo",
"AccountCapability_CalendarOnly": "Só calendario",
"AccountCapability_MailAndCalendar": "Correo e Calendario",
"AddHyperlink": "Engadir", "AddHyperlink": "Engadir",
"AppCloseBackgroundSynchronizationWarningTitle": "Sincronización en segundo plano", "AppCloseBackgroundSynchronizationWarningTitle": "Sincronización en segundo plano",
"AppCloseStartupLaunchDisabledWarningMessageFirstLine": "Application has not been set to launch on Windows startup.", "AppCloseStartupLaunchDisabledWarningMessageFirstLine": "Application has not been set to launch on Windows startup.",
@@ -76,6 +81,7 @@
"Buttons_ApplyTheme": "Aplicar tema", "Buttons_ApplyTheme": "Aplicar tema",
"Buttons_PopOut": "Abrir en nova xanela", "Buttons_PopOut": "Abrir en nova xanela",
"Buttons_Browse": "Procurar", "Buttons_Browse": "Procurar",
"Buttons_Back": "Atrás",
"Buttons_Cancel": "Anular", "Buttons_Cancel": "Anular",
"Buttons_Close": "Pechar", "Buttons_Close": "Pechar",
"Buttons_Copy": "Copiar", "Buttons_Copy": "Copiar",
@@ -299,6 +305,8 @@
"DialogMessage_DeleteRecurringSeriesTitle": "Eliminar serie recurrente", "DialogMessage_DeleteRecurringSeriesTitle": "Eliminar serie recurrente",
"DialogMessage_DiscardDraftConfirmationMessage": "O borrador será eliminado. Quere continuar?", "DialogMessage_DiscardDraftConfirmationMessage": "O borrador será eliminado. Quere continuar?",
"DialogMessage_DiscardDraftConfirmationTitle": "Eliminar borrador", "DialogMessage_DiscardDraftConfirmationTitle": "Eliminar borrador",
"DialogMessage_CloseDraftWindowConfirmationMessage": "Un borrador aínda está aberto. Garda-o antes de pechar a xanela?",
"DialogMessage_CloseDraftWindowConfirmationTitle": "Pechar a xanela",
"DialogMessage_EmptySubjectConfirmation": "Missing Subject", "DialogMessage_EmptySubjectConfirmation": "Missing Subject",
"DialogMessage_EmptySubjectConfirmationMessage": "A mensaxe non ten asunto. Queres continuar?", "DialogMessage_EmptySubjectConfirmationMessage": "A mensaxe non ten asunto. Queres continuar?",
"DialogMessage_EnableStartupLaunchDeniedMessage": "You can enable startup launch from Settings -> App Preferences.", "DialogMessage_EnableStartupLaunchDeniedMessage": "You can enable startup launch from Settings -> App Preferences.",
@@ -681,6 +689,10 @@
"NoMailSelected": "No message selected", "NoMailSelected": "No message selected",
"NoMessageCrieteria": "No messages match your search criteria", "NoMessageCrieteria": "No messages match your search criteria",
"NoMessageEmptyFolder": "This folder is empty", "NoMessageEmptyFolder": "This folder is empty",
"MailEmptyState_Title": "Non hai contas habilitadas para correo",
"MailEmptyState_Message": "Tes contas conectadas para calendario, pero ningunha delas está habilitada para correo. Engade unha conta de correo ou actualiza unha conta existente para usar correo.",
"MailEmptyState_AddAccount": "Engadir conta",
"MailEmptyState_ManageAccounts": "Xestionar contas",
"Notifications_MultipleNotificationsMessage": "You have {0} new messages.", "Notifications_MultipleNotificationsMessage": "You have {0} new messages.",
"Notifications_MultipleNotificationsTitle": "New Mail", "Notifications_MultipleNotificationsTitle": "New Mail",
"Notifications_WinoUpdatedMessage": "Checkout new version {0}", "Notifications_WinoUpdatedMessage": "Checkout new version {0}",
@@ -824,6 +836,8 @@
"SettingsDeleteAccount_Title": "Delete this account", "SettingsDeleteAccount_Title": "Delete this account",
"SettingsDeleteProtection_Description": "Should Wino ask you for confirmation every time you try to permanently delete a mail using Shift + Del keys?", "SettingsDeleteProtection_Description": "Should Wino ask you for confirmation every time you try to permanently delete a mail using Shift + Del keys?",
"SettingsDeleteProtection_Title": "Permanent Delete Protection", "SettingsDeleteProtection_Title": "Permanent Delete Protection",
"SettingsEmptyJunkFolderCommand_Description": "Mostrar o comando para baleirar a carpeta de correo lixo. Esta acción non pedirá confirmación e eliminará de inmediato todos os correos da carpeta de correo lixo.",
"SettingsEmptyJunkFolderCommand_Title": "Mostrar o comando para baleirar a carpeta de correo lixo",
"SettingsDiagnostics_Description": "For developers", "SettingsDiagnostics_Description": "For developers",
"SettingsDiagnostics_DiagnosticId_Description": "Share this ID with the developers when asked to get help for the issues you experience in Wino Mail.", "SettingsDiagnostics_DiagnosticId_Description": "Share this ID with the developers when asked to get help for the issues you experience in Wino Mail.",
"SettingsDiagnostics_DiagnosticId_Title": "Diagnostic ID", "SettingsDiagnostics_DiagnosticId_Title": "Diagnostic ID",
@@ -1074,6 +1088,12 @@
"SettingsTaskbarBadge_Title": "Taskbar Badge", "SettingsTaskbarBadge_Title": "Taskbar Badge",
"SettingsThreads_Description": "Organize messages into conversation threads.", "SettingsThreads_Description": "Organize messages into conversation threads.",
"SettingsThreads_Title": "Conversation Threading", "SettingsThreads_Title": "Conversation Threading",
"SettingsThreads_Enabled_Description": "Agrupa as mensaxes relacionadas nunha única conversa.",
"SettingsThreads_Enabled_Title": "Habilitar o fío da conversa",
"SettingsThreadOrder_Description": "Elixe como se ordenan os elementos dentro do fío de conversa.",
"SettingsThreadOrder_Title": "Ordenación de elementos do fío",
"SettingsThreadOrder_LastItemFirst": "O último elemento primeiro",
"SettingsThreadOrder_FirstItemFirst": "O primeiro elemento primeiro",
"SettingsUnlinkAccounts_Description": "Remove the link between accounts. his will not delete your accounts.", "SettingsUnlinkAccounts_Description": "Remove the link between accounts. his will not delete your accounts.",
"SettingsUnlinkAccounts_Title": "Unlink Accounts", "SettingsUnlinkAccounts_Title": "Unlink Accounts",
"SettingsMailRendering_ActionLabels_Title": "Action labels", "SettingsMailRendering_ActionLabels_Title": "Action labels",
@@ -1339,6 +1359,7 @@
"WelcomeWindow_GetStartedButton": "Comeza engadindo unha conta", "WelcomeWindow_GetStartedButton": "Comeza engadindo unha conta",
"WelcomeWindow_GetStartedDescription": "Engade a túa conta de Outlook, Gmail ou IMAP para comezar a usar Wino Mail", "WelcomeWindow_GetStartedDescription": "Engade a túa conta de Outlook, Gmail ou IMAP para comezar a usar Wino Mail",
"WelcomeWindow_ImportFromWinoAccount": "Importar desde a túa Conta Wino", "WelcomeWindow_ImportFromWinoAccount": "Importar desde a túa Conta Wino",
"WelcomeWindow_ImportFromJsonFile": "Importar desde un arquivo JSON",
"WelcomeWindow_ImportInProgress": "Importando as túas preferencias e contas sincronizadas...", "WelcomeWindow_ImportInProgress": "Importando as túas preferencias e contas sincronizadas...",
"WelcomeWindow_ImportNoAccountsFound": "Non se atoparon contas sincronizadas na túa Conta Wino. Se as preferencias estaban dispoñibles, foron restauradas. Usa Comeza para engadir unha conta manualmente", "WelcomeWindow_ImportNoAccountsFound": "Non se atoparon contas sincronizadas na túa Conta Wino. Se as preferencias estaban dispoñibles, foron restauradas. Usa Comeza para engadir unha conta manualmente",
"WelcomeWindow_ImportDuplicateAccountsSkipped": "{0} contas sincronizadas xa están dispoñibles neste dispositivo. Usa Comeza para engadir outra conta manualmente se é necesario", "WelcomeWindow_ImportDuplicateAccountsSkipped": "{0} contas sincronizadas xa están dispoñibles neste dispositivo. Usa Comeza para engadir outra conta manualmente se é necesario",
@@ -1418,6 +1439,12 @@
"WinoAccount_Management_ExportDialog_AccountsDisclaimer": "Contrasinais, tokens e outra información sensible non se sincronizan.", "WinoAccount_Management_ExportDialog_AccountsDisclaimer": "Contrasinais, tokens e outra información sensible non se sincronizan.",
"WinoAccount_Management_ExportDialog_AccountsRelogin": "As contas importadas noutro PC seguirán a necesitar que inicies sesión de novo antes de poder usalas.", "WinoAccount_Management_ExportDialog_AccountsRelogin": "As contas importadas noutro PC seguirán a necesitar que inicies sesión de novo antes de poder usalas.",
"WinoAccount_Management_ExportDialog_InProgress": "Exportando os datos de Wino seleccionados", "WinoAccount_Management_ExportDialog_InProgress": "Exportando os datos de Wino seleccionados",
"WinoAccount_Management_LocalDataSectionTitle": "Transferir cun arquivo JSON",
"WinoAccount_Management_LocalDataSectionDescription": "Importar desde ou exportar a un arquivo JSON local. Contrasinais, tokens e outras informacións sensibles non están incluídas.",
"WinoAccount_Management_LocalDataImportAction": "Importar",
"WinoAccount_Management_LocalDataExportAction": "Exportar",
"WinoAccount_Management_LocalDataSaved": "Os teus datos exportados de Wino gardáronse en {0}.",
"WinoAccount_Management_LocalDataInvalidFile": "O ficheiro JSON seleccionado non contén unha exportación válida de Wino.",
"WinoAccount_Management_LoadFailed": "Wino non conseguiu carregar a información máis recente da Conta Wino.", "WinoAccount_Management_LoadFailed": "Wino non conseguiu carregar a información máis recente da Conta Wino.",
"WinoAccount_Management_ActionFailed": "A solicitude da Conta Wino non puido completarse.", "WinoAccount_Management_ActionFailed": "A solicitude da Conta Wino non puido completarse.",
"WinoAccount_SettingsSection_Title": "Conta Wino", "WinoAccount_SettingsSection_Title": "Conta Wino",
@@ -1514,8 +1541,22 @@
"WelcomeWizard_Step3Title": "Rematar a configuración", "WelcomeWizard_Step3Title": "Rematar a configuración",
"ProviderSelection_Title": "Elixe o teu provedor de correo", "ProviderSelection_Title": "Elixe o teu provedor de correo",
"ProviderSelection_Subtitle": "Selecciona un provedor a continuación para engadir a túa conta de correo a Wino Mail.", "ProviderSelection_Subtitle": "Selecciona un provedor a continuación para engadir a túa conta de correo a Wino Mail.",
"ProviderSelection_StepProgress": "Fase {0} de 3",
"ProviderSelection_IdentityTitle": "Identidade da conta",
"ProviderSelection_IdentityDescription": "Elixe como aparecerá esta conta dentro de Wino.",
"ProviderSelection_ProviderSectionTitle": "Provedor",
"ProviderSelection_ProviderSectionDescription": "Selecciona o servizo que queres conectar.",
"ProviderSelection_CapabilitySectionTitle": "Usar esta conta para",
"ProviderSelection_CapabilitySectionDescription": "Elixe se queres correo, calendario ou ambos.",
"ProviderSelection_CapabilityProviderDescription_OAuth": "No seguinte paso, o inicio de sesión seguro conectará a túa conta. Se habilitas o calendario, Wino conectará automaticamente Outlook Calendar ou Google Calendar.",
"ProviderSelection_CapabilityProviderDescription_SpecialImap": "No seguinte paso, introducirás as credenciais do provedor. O correo usa IMAP/SMTP, e o calendario pode usar CalDAV ou permanecer local neste dispositivo.",
"ProviderSelection_CapabilityProviderDescription_CustomServer": "No seguinte paso, introducirás os datos do servidor. O correo usa IMAP/SMTP, e o calendario pode usar CalDAV ou permanecer local neste dispositivo.",
"ProviderSelection_AccountNameHeader": "Nome da conta", "ProviderSelection_AccountNameHeader": "Nome da conta",
"ProviderSelection_AccountNamePlaceholder": "p. ex. Persoal, Laboral", "ProviderSelection_AccountNamePlaceholder": "p. ex. Persoal, Laboral",
"ProviderSelection_UseForMail": "Correo",
"ProviderSelection_UseForCalendar": "Calendario",
"ProviderSelection_CapabilityValidationMessage": "Elixe polo menos unha capacidade antes de continuar.",
"ProviderSelection_CalendarOnlyServerHint": "Se continúas só co calendario, a seguinte páxina non requirirá unha dirección de correo.",
"ProviderSelection_DisplayNameHeader": "Nome para amosar", "ProviderSelection_DisplayNameHeader": "Nome para amosar",
"ProviderSelection_DisplayNamePlaceholder": "p. ex. John Doe", "ProviderSelection_DisplayNamePlaceholder": "p. ex. John Doe",
"ProviderSelection_EmailHeader": "Enderezo de correo electrónico", "ProviderSelection_EmailHeader": "Enderezo de correo electrónico",
@@ -47,6 +47,11 @@
"AccountDetailsPage_CalendarListDescription": "Pilih kalender untuk mengonfigurasi pengaturannya", "AccountDetailsPage_CalendarListDescription": "Pilih kalender untuk mengonfigurasi pengaturannya",
"AccountDetailsPage_InitialSynchronization_Title": "Sinkronisasi awal", "AccountDetailsPage_InitialSynchronization_Title": "Sinkronisasi awal",
"AccountDetailsPage_InitialSynchronization_Description": "Wino telah menyinkronkan surel Anda hingga {0} ke belakang.", "AccountDetailsPage_InitialSynchronization_Description": "Wino telah menyinkronkan surel Anda hingga {0} ke belakang.",
"AccountDetailsPage_CapabilityTitle": "Fitur yang Terhubung",
"AccountDetailsPage_CapabilityDescription": "Pilih apakah akun ini digunakan untuk email, kalender, atau keduanya. Mengaktifkan fitur baru mungkin meminta Anda untuk masuk lagi.",
"AccountCapability_MailOnly": "Hanya Email",
"AccountCapability_CalendarOnly": "Hanya Kalender",
"AccountCapability_MailAndCalendar": "Email dan Kalender",
"AddHyperlink": "Tambahkan", "AddHyperlink": "Tambahkan",
"AppCloseBackgroundSynchronizationWarningTitle": "Penyelarasan Latar Belakang", "AppCloseBackgroundSynchronizationWarningTitle": "Penyelarasan Latar Belakang",
"AppCloseStartupLaunchDisabledWarningMessageFirstLine": "Aplikasi tidak diatur untuk berjalan saat Windows dimulai.", "AppCloseStartupLaunchDisabledWarningMessageFirstLine": "Aplikasi tidak diatur untuk berjalan saat Windows dimulai.",
@@ -76,6 +81,7 @@
"Buttons_ApplyTheme": "Terapkan Tema", "Buttons_ApplyTheme": "Terapkan Tema",
"Buttons_PopOut": "Buka jendela terpisah", "Buttons_PopOut": "Buka jendela terpisah",
"Buttons_Browse": "Telusuri", "Buttons_Browse": "Telusuri",
"Buttons_Back": "Kembali",
"Buttons_Cancel": "Batal", "Buttons_Cancel": "Batal",
"Buttons_Close": "Tutup", "Buttons_Close": "Tutup",
"Buttons_Copy": "Salin", "Buttons_Copy": "Salin",
@@ -299,6 +305,8 @@
"DialogMessage_DeleteRecurringSeriesTitle": "Hapus Seri Berulang", "DialogMessage_DeleteRecurringSeriesTitle": "Hapus Seri Berulang",
"DialogMessage_DiscardDraftConfirmationMessage": "Konsep ini akan dibuang. Apakah Anda ingin melanjutkan?", "DialogMessage_DiscardDraftConfirmationMessage": "Konsep ini akan dibuang. Apakah Anda ingin melanjutkan?",
"DialogMessage_DiscardDraftConfirmationTitle": "Buang Konsep", "DialogMessage_DiscardDraftConfirmationTitle": "Buang Konsep",
"DialogMessage_CloseDraftWindowConfirmationMessage": "Sebuah draf masih terbuka. Simpan sebelum menutup jendela?",
"DialogMessage_CloseDraftWindowConfirmationTitle": "Tutup Jendela",
"DialogMessage_EmptySubjectConfirmation": "Tidak Ada Perihal", "DialogMessage_EmptySubjectConfirmation": "Tidak Ada Perihal",
"DialogMessage_EmptySubjectConfirmationMessage": "Pesan tidak memiliki perihal. Apakah Anda ingin melanjutkan?", "DialogMessage_EmptySubjectConfirmationMessage": "Pesan tidak memiliki perihal. Apakah Anda ingin melanjutkan?",
"DialogMessage_EnableStartupLaunchDeniedMessage": "Anda dapat menyalakan Luncurkan ketika Mulai di Pengaturan -> Pengaturan Aplikasi.", "DialogMessage_EnableStartupLaunchDeniedMessage": "Anda dapat menyalakan Luncurkan ketika Mulai di Pengaturan -> Pengaturan Aplikasi.",
@@ -681,6 +689,10 @@
"NoMailSelected": "Tidak ada pesan yang dipilih", "NoMailSelected": "Tidak ada pesan yang dipilih",
"NoMessageCrieteria": "Tidak ada pesan yang sesuai kriteria", "NoMessageCrieteria": "Tidak ada pesan yang sesuai kriteria",
"NoMessageEmptyFolder": "Folder ini kosong", "NoMessageEmptyFolder": "Folder ini kosong",
"MailEmptyState_Title": "Tidak ada akun yang mendukung email",
"MailEmptyState_Message": "Anda memiliki akun yang terhubung untuk kalender, tetapi tidak ada yang diaktifkan untuk email.Tambahkan akun email atau perbarui akun yang ada untuk menggunakan email.",
"MailEmptyState_AddAccount": "Tambahkan akun",
"MailEmptyState_ManageAccounts": "Kelola akun",
"Notifications_MultipleNotificationsMessage": "Anda memiliki {0} pesan baru.", "Notifications_MultipleNotificationsMessage": "Anda memiliki {0} pesan baru.",
"Notifications_MultipleNotificationsTitle": "Pesan Baru", "Notifications_MultipleNotificationsTitle": "Pesan Baru",
"Notifications_WinoUpdatedMessage": "Versi baru terpasang {0}", "Notifications_WinoUpdatedMessage": "Versi baru terpasang {0}",
@@ -824,6 +836,8 @@
"SettingsDeleteAccount_Title": "Hapus akun ini", "SettingsDeleteAccount_Title": "Hapus akun ini",
"SettingsDeleteProtection_Description": "Should Wino ask you for confirmation every time you try to permanently delete a mail using Shift + Del keys?", "SettingsDeleteProtection_Description": "Should Wino ask you for confirmation every time you try to permanently delete a mail using Shift + Del keys?",
"SettingsDeleteProtection_Title": "Perlindungan Hapus Permanen", "SettingsDeleteProtection_Title": "Perlindungan Hapus Permanen",
"SettingsEmptyJunkFolderCommand_Description": "Tampilkan perintah kosongkan folder pada folder Junk/Spam. Tindakan ini tidak akan meminta konfirmasi dan akan menghapus semua email di folder spam segera.",
"SettingsEmptyJunkFolderCommand_Title": "Perintah kosongkan folder Spam",
"SettingsDiagnostics_Description": "Untuk pengembang", "SettingsDiagnostics_Description": "Untuk pengembang",
"SettingsDiagnostics_DiagnosticId_Description": "Share this ID with the developers when asked to get help for the issues you experience in Wino Mail.", "SettingsDiagnostics_DiagnosticId_Description": "Share this ID with the developers when asked to get help for the issues you experience in Wino Mail.",
"SettingsDiagnostics_DiagnosticId_Title": "Diagnostic ID", "SettingsDiagnostics_DiagnosticId_Title": "Diagnostic ID",
@@ -1074,6 +1088,12 @@
"SettingsTaskbarBadge_Title": "Lencana Bilah Tugas", "SettingsTaskbarBadge_Title": "Lencana Bilah Tugas",
"SettingsThreads_Description": "Kelompokkan pesan menjadi utas.", "SettingsThreads_Description": "Kelompokkan pesan menjadi utas.",
"SettingsThreads_Title": "Utas Percakapan", "SettingsThreads_Title": "Utas Percakapan",
"SettingsThreads_Enabled_Description": "Gabungkan pesan terkait menjadi satu percakapan.",
"SettingsThreads_Enabled_Title": "Aktifkan pengelompokan percakapan",
"SettingsThreadOrder_Description": "Pilih bagaimana item diurutkan di dalam percakapan.",
"SettingsThreadOrder_Title": "Pengurutan item percakapan",
"SettingsThreadOrder_LastItemFirst": "Item terakhir pertama",
"SettingsThreadOrder_FirstItemFirst": "Item pertama dulu",
"SettingsUnlinkAccounts_Description": "Hapus tautan antara akun. Ini tidak akan menghapus akun Anda.", "SettingsUnlinkAccounts_Description": "Hapus tautan antara akun. Ini tidak akan menghapus akun Anda.",
"SettingsUnlinkAccounts_Title": "Lepaskan Tautan Akun", "SettingsUnlinkAccounts_Title": "Lepaskan Tautan Akun",
"SettingsMailRendering_ActionLabels_Title": "Action labels", "SettingsMailRendering_ActionLabels_Title": "Action labels",
@@ -1339,6 +1359,7 @@
"WelcomeWindow_GetStartedButton": "Mulai dengan menambahkan akun", "WelcomeWindow_GetStartedButton": "Mulai dengan menambahkan akun",
"WelcomeWindow_GetStartedDescription": "Tambahkan akun Outlook, Gmail, atau IMAP Anda untuk memulai dengan Wino Mail.", "WelcomeWindow_GetStartedDescription": "Tambahkan akun Outlook, Gmail, atau IMAP Anda untuk memulai dengan Wino Mail.",
"WelcomeWindow_ImportFromWinoAccount": "Impor dari Akun Wino Anda", "WelcomeWindow_ImportFromWinoAccount": "Impor dari Akun Wino Anda",
"WelcomeWindow_ImportFromJsonFile": "Impor dari file JSON",
"WelcomeWindow_ImportInProgress": "Mengimpor preferensi dan akun yang tersinkronkan...", "WelcomeWindow_ImportInProgress": "Mengimpor preferensi dan akun yang tersinkronkan...",
"WelcomeWindow_ImportNoAccountsFound": "Tidak ada akun yang tersinkronisasi ditemukan di Akun Wino Anda. Jika preferensi tersedia, mereka telah dipulihkan. Gunakan Mulai untuk menambahkan akun secara manual.", "WelcomeWindow_ImportNoAccountsFound": "Tidak ada akun yang tersinkronisasi ditemukan di Akun Wino Anda. Jika preferensi tersedia, mereka telah dipulihkan. Gunakan Mulai untuk menambahkan akun secara manual.",
"WelcomeWindow_ImportDuplicateAccountsSkipped": "{0} akun yang tersinkronisasi sudah tersedia di perangkat ini. Gunakan Mulai untuk menambahkan akun lain secara manual jika diperlukan.", "WelcomeWindow_ImportDuplicateAccountsSkipped": "{0} akun yang tersinkronisasi sudah tersedia di perangkat ini. Gunakan Mulai untuk menambahkan akun lain secara manual jika diperlukan.",
@@ -1418,6 +1439,12 @@
"WinoAccount_Management_ExportDialog_AccountsDisclaimer": "Kata sandi, token, dan informasi sensitif lainnya tidak disinkronkan.", "WinoAccount_Management_ExportDialog_AccountsDisclaimer": "Kata sandi, token, dan informasi sensitif lainnya tidak disinkronkan.",
"WinoAccount_Management_ExportDialog_AccountsRelogin": "Akun yang diimpor di PC lain masih perlu Anda masuk lagi sebelum dapat digunakan.", "WinoAccount_Management_ExportDialog_AccountsRelogin": "Akun yang diimpor di PC lain masih perlu Anda masuk lagi sebelum dapat digunakan.",
"WinoAccount_Management_ExportDialog_InProgress": "Sedang mengekspor data Wino yang Anda pilih...", "WinoAccount_Management_ExportDialog_InProgress": "Sedang mengekspor data Wino yang Anda pilih...",
"WinoAccount_Management_LocalDataSectionTitle": "Transfer dengan file JSON",
"WinoAccount_Management_LocalDataSectionDescription": "Impor dari atau ekspor ke file JSON lokal. Kata sandi, token, dan informasi sensitif lainnya tidak disertakan.",
"WinoAccount_Management_LocalDataImportAction": "Impor",
"WinoAccount_Management_LocalDataExportAction": "Ekspor",
"WinoAccount_Management_LocalDataSaved": "Data Wino yang diekspor telah disimpan ke {0}.",
"WinoAccount_Management_LocalDataInvalidFile": "File JSON yang dipilih tidak berisi ekspor Wino yang valid.",
"WinoAccount_Management_LoadFailed": "Wino tidak dapat memuat informasi Akun Wino terbaru.", "WinoAccount_Management_LoadFailed": "Wino tidak dapat memuat informasi Akun Wino terbaru.",
"WinoAccount_Management_ActionFailed": "Permintaan Akun Wino tidak dapat diselesaikan.", "WinoAccount_Management_ActionFailed": "Permintaan Akun Wino tidak dapat diselesaikan.",
"WinoAccount_SettingsSection_Title": "Akun Wino", "WinoAccount_SettingsSection_Title": "Akun Wino",
@@ -1514,8 +1541,22 @@
"WelcomeWizard_Step3Title": "Selesaikan Pengaturan", "WelcomeWizard_Step3Title": "Selesaikan Pengaturan",
"ProviderSelection_Title": "Pilih penyedia email Anda", "ProviderSelection_Title": "Pilih penyedia email Anda",
"ProviderSelection_Subtitle": "Pilih penyedia di bawah ini untuk menambahkan akun email Anda ke Wino Mail.", "ProviderSelection_Subtitle": "Pilih penyedia di bawah ini untuk menambahkan akun email Anda ke Wino Mail.",
"ProviderSelection_StepProgress": "Langkah {0} dari 3",
"ProviderSelection_IdentityTitle": "Identitas akun",
"ProviderSelection_IdentityDescription": "Pilih bagaimana akun ini ditampilkan di dalam Wino.",
"ProviderSelection_ProviderSectionTitle": "Penyedia",
"ProviderSelection_ProviderSectionDescription": "Pilih layanan yang ingin Anda hubungkan.",
"ProviderSelection_CapabilitySectionTitle": "Gunakan akun ini untuk",
"ProviderSelection_CapabilitySectionDescription": "Pilih apakah Anda ingin email, kalender, atau keduanya.",
"ProviderSelection_CapabilityProviderDescription_OAuth": "Pada langkah berikutnya, proses masuk yang aman akan menghubungkan akun Anda. Jika Anda mengaktifkan kalender, Wino juga akan secara otomatis menghubungkan Outlook Calendar atau Google Calendar.",
"ProviderSelection_CapabilityProviderDescription_SpecialImap": "Pada langkah berikutnya, Anda akan memasukkan kredensial penyedia Anda. Email menggunakan IMAP/SMTP, dan kalender dapat menggunakan CalDAV atau tetap lokal di perangkat ini.",
"ProviderSelection_CapabilityProviderDescription_CustomServer": "Pada langkah berikutnya, Anda akan memasukkan detail server Anda. Email menggunakan IMAP/SMTP, dan kalender dapat menggunakan CalDAV atau tetap lokal di perangkat ini.",
"ProviderSelection_AccountNameHeader": "Nama Akun", "ProviderSelection_AccountNameHeader": "Nama Akun",
"ProviderSelection_AccountNamePlaceholder": "contoh: Pribadi, Kerja", "ProviderSelection_AccountNamePlaceholder": "contoh: Pribadi, Kerja",
"ProviderSelection_UseForMail": "Email",
"ProviderSelection_UseForCalendar": "Kalender",
"ProviderSelection_CapabilityValidationMessage": "Pilih setidaknya satu kemampuan sebelum melanjutkan.",
"ProviderSelection_CalendarOnlyServerHint": "Jika Anda melanjutkan dengan kalender saja, halaman berikutnya tidak akan memerlukan alamat email.",
"ProviderSelection_DisplayNameHeader": "Nama Tampilan", "ProviderSelection_DisplayNameHeader": "Nama Tampilan",
"ProviderSelection_DisplayNamePlaceholder": "contoh: John Doe", "ProviderSelection_DisplayNamePlaceholder": "contoh: John Doe",
"ProviderSelection_EmailHeader": "Alamat Email", "ProviderSelection_EmailHeader": "Alamat Email",
@@ -47,6 +47,11 @@
"AccountDetailsPage_CalendarListDescription": "Seleziona un calendario per configurarne le impostazioni.", "AccountDetailsPage_CalendarListDescription": "Seleziona un calendario per configurarne le impostazioni.",
"AccountDetailsPage_InitialSynchronization_Title": "Sincronizzazione iniziale", "AccountDetailsPage_InitialSynchronization_Title": "Sincronizzazione iniziale",
"AccountDetailsPage_InitialSynchronization_Description": "Wino ha sincronizzato la tua posta fino a {0} nel passato.", "AccountDetailsPage_InitialSynchronization_Description": "Wino ha sincronizzato la tua posta fino a {0} nel passato.",
"AccountDetailsPage_CapabilityTitle": "Funzionalità connesse",
"AccountDetailsPage_CapabilityDescription": "Scegli se questo account viene utilizzato per la posta, il calendario o entrambi. Attivando una nuova funzionalità potrebbe chiederti di accedere nuovamente.",
"AccountCapability_MailOnly": "Solo posta",
"AccountCapability_CalendarOnly": "Solo calendario",
"AccountCapability_MailAndCalendar": "Posta e Calendario",
"AddHyperlink": "Aggiungi", "AddHyperlink": "Aggiungi",
"AppCloseBackgroundSynchronizationWarningTitle": "Sincronizzazione dietro le quinte", "AppCloseBackgroundSynchronizationWarningTitle": "Sincronizzazione dietro le quinte",
"AppCloseStartupLaunchDisabledWarningMessageFirstLine": "L'applicazione non è stata impostata per avviarsi all'avvio di Windows.", "AppCloseStartupLaunchDisabledWarningMessageFirstLine": "L'applicazione non è stata impostata per avviarsi all'avvio di Windows.",
@@ -76,6 +81,7 @@
"Buttons_ApplyTheme": "Applica tema", "Buttons_ApplyTheme": "Applica tema",
"Buttons_PopOut": "Apri in una nuova finestra", "Buttons_PopOut": "Apri in una nuova finestra",
"Buttons_Browse": "Sfoglia", "Buttons_Browse": "Sfoglia",
"Buttons_Back": "Indietro",
"Buttons_Cancel": "Annulla", "Buttons_Cancel": "Annulla",
"Buttons_Close": "Chiudi", "Buttons_Close": "Chiudi",
"Buttons_Copy": "Copia", "Buttons_Copy": "Copia",
@@ -299,6 +305,8 @@
"DialogMessage_DeleteRecurringSeriesTitle": "Elimina serie ricorrente", "DialogMessage_DeleteRecurringSeriesTitle": "Elimina serie ricorrente",
"DialogMessage_DiscardDraftConfirmationMessage": "Questa bozza sarà scartata. Vuoi continuare?", "DialogMessage_DiscardDraftConfirmationMessage": "Questa bozza sarà scartata. Vuoi continuare?",
"DialogMessage_DiscardDraftConfirmationTitle": "Scarta bozza", "DialogMessage_DiscardDraftConfirmationTitle": "Scarta bozza",
"DialogMessage_CloseDraftWindowConfirmationMessage": "Una bozza è ancora aperta. Salvala prima di chiudere la finestra?",
"DialogMessage_CloseDraftWindowConfirmationTitle": "Chiudi finestra",
"DialogMessage_EmptySubjectConfirmation": "Oggetto mancante", "DialogMessage_EmptySubjectConfirmation": "Oggetto mancante",
"DialogMessage_EmptySubjectConfirmationMessage": "Il messaggio non ha oggetto. Vuoi continuare?", "DialogMessage_EmptySubjectConfirmationMessage": "Il messaggio non ha oggetto. Vuoi continuare?",
"DialogMessage_EnableStartupLaunchDeniedMessage": "È possibile abilitare l'avvio da Impostazioni -> Preferenze app.", "DialogMessage_EnableStartupLaunchDeniedMessage": "È possibile abilitare l'avvio da Impostazioni -> Preferenze app.",
@@ -681,6 +689,10 @@
"NoMailSelected": "Nessun messaggio selezionato", "NoMailSelected": "Nessun messaggio selezionato",
"NoMessageCrieteria": "Nessun messaggio corrisponde ai tuoi criteri di ricerca", "NoMessageCrieteria": "Nessun messaggio corrisponde ai tuoi criteri di ricerca",
"NoMessageEmptyFolder": "Questa cartella è vuota", "NoMessageEmptyFolder": "Questa cartella è vuota",
"MailEmptyState_Title": "Nessun account abilitato per la posta",
"MailEmptyState_Message": "Hai account collegati al calendario, ma nessuno è abilitato per la posta. Aggiungi un account di posta o aggiorna un account esistente per utilizzare la posta.",
"MailEmptyState_AddAccount": "Aggiungi account",
"MailEmptyState_ManageAccounts": "Gestisci account",
"Notifications_MultipleNotificationsMessage": "Hai {0} nuovi messaggi.", "Notifications_MultipleNotificationsMessage": "Hai {0} nuovi messaggi.",
"Notifications_MultipleNotificationsTitle": "Nuova posta", "Notifications_MultipleNotificationsTitle": "Nuova posta",
"Notifications_WinoUpdatedMessage": "Controlla la nuova versione {0}", "Notifications_WinoUpdatedMessage": "Controlla la nuova versione {0}",
@@ -824,6 +836,8 @@
"SettingsDeleteAccount_Title": "Elimina questo account", "SettingsDeleteAccount_Title": "Elimina questo account",
"SettingsDeleteProtection_Description": "Dovrebbe Wino chiederti la conferma ogni volta che provi a eliminare definitivamente un messaggio utilizzando Maiusc + Canc?", "SettingsDeleteProtection_Description": "Dovrebbe Wino chiederti la conferma ogni volta che provi a eliminare definitivamente un messaggio utilizzando Maiusc + Canc?",
"SettingsDeleteProtection_Title": "Protezione eliminazione permanente", "SettingsDeleteProtection_Title": "Protezione eliminazione permanente",
"SettingsEmptyJunkFolderCommand_Description": "Mostra il comando per svuotare le cartelle Junk/Spam. Questa azione non richiederà alcuna conferma e eliminerà immediatamente tutte le email nelle cartelle Junk/Spam.",
"SettingsEmptyJunkFolderCommand_Title": "Mostra il comando per svuotare la cartella Junk/Spam",
"SettingsDiagnostics_Description": "Per gli sviluppatori", "SettingsDiagnostics_Description": "Per gli sviluppatori",
"SettingsDiagnostics_DiagnosticId_Description": "Condividi questo ID con gli sviluppatori quando richiesto per ricevere aiuto in merito ai problemi che hai con Wino Mail.", "SettingsDiagnostics_DiagnosticId_Description": "Condividi questo ID con gli sviluppatori quando richiesto per ricevere aiuto in merito ai problemi che hai con Wino Mail.",
"SettingsDiagnostics_DiagnosticId_Title": "ID diagnostica", "SettingsDiagnostics_DiagnosticId_Title": "ID diagnostica",
@@ -1074,6 +1088,12 @@
"SettingsTaskbarBadge_Title": "In barra attività come", "SettingsTaskbarBadge_Title": "In barra attività come",
"SettingsThreads_Description": "Organizza i messaggi in gruppi di conversazione.", "SettingsThreads_Description": "Organizza i messaggi in gruppi di conversazione.",
"SettingsThreads_Title": "Raggruppamento conversazioni", "SettingsThreads_Title": "Raggruppamento conversazioni",
"SettingsThreads_Enabled_Description": "Raggruppa i messaggi correlati in una singola conversazione.",
"SettingsThreads_Enabled_Title": "Abilita la visualizzazione a thread delle conversazioni.",
"SettingsThreadOrder_Description": "Scegli come vengono ordinati gli elementi all'interno di una conversazione a thread.",
"SettingsThreadOrder_Title": "Ordinamento degli elementi della conversazione",
"SettingsThreadOrder_LastItemFirst": "Ultimo elemento per primo",
"SettingsThreadOrder_FirstItemFirst": "Primo elemento per primo",
"SettingsUnlinkAccounts_Description": "Rimuovi il collegamento tra gli account. Questo non eliminerà i tuoi account.", "SettingsUnlinkAccounts_Description": "Rimuovi il collegamento tra gli account. Questo non eliminerà i tuoi account.",
"SettingsUnlinkAccounts_Title": "Scollega account", "SettingsUnlinkAccounts_Title": "Scollega account",
"SettingsMailRendering_ActionLabels_Title": "Etichette azioni", "SettingsMailRendering_ActionLabels_Title": "Etichette azioni",
@@ -1339,6 +1359,7 @@
"WelcomeWindow_GetStartedButton": "Inizia aggiungendo un account", "WelcomeWindow_GetStartedButton": "Inizia aggiungendo un account",
"WelcomeWindow_GetStartedDescription": "Aggiungi il tuo account Outlook, Gmail o IMAP per iniziare a usare Wino Mail.", "WelcomeWindow_GetStartedDescription": "Aggiungi il tuo account Outlook, Gmail o IMAP per iniziare a usare Wino Mail.",
"WelcomeWindow_ImportFromWinoAccount": "Importa dal tuo account Wino", "WelcomeWindow_ImportFromWinoAccount": "Importa dal tuo account Wino",
"WelcomeWindow_ImportFromJsonFile": "Importa da un file JSON",
"WelcomeWindow_ImportInProgress": "Importazione delle preferenze e degli account sincronizzati in corso...", "WelcomeWindow_ImportInProgress": "Importazione delle preferenze e degli account sincronizzati in corso...",
"WelcomeWindow_ImportNoAccountsFound": "Nessun account sincronizzato è stato trovato nel tuo account Wino. Se erano disponibili le preferenze, sono state ripristinate. Usa Inizia per aggiungere manualmente un account.", "WelcomeWindow_ImportNoAccountsFound": "Nessun account sincronizzato è stato trovato nel tuo account Wino. Se erano disponibili le preferenze, sono state ripristinate. Usa Inizia per aggiungere manualmente un account.",
"WelcomeWindow_ImportDuplicateAccountsSkipped": "{0} account sincronizzati sono già disponibili su questo dispositivo. Usa Inizia per aggiungere manualmente un altro account se necessario.", "WelcomeWindow_ImportDuplicateAccountsSkipped": "{0} account sincronizzati sono già disponibili su questo dispositivo. Usa Inizia per aggiungere manualmente un altro account se necessario.",
@@ -1418,6 +1439,12 @@
"WinoAccount_Management_ExportDialog_AccountsDisclaimer": "Le password, i token e altre informazioni sensibili non sono sincronizzati.", "WinoAccount_Management_ExportDialog_AccountsDisclaimer": "Le password, i token e altre informazioni sensibili non sono sincronizzati.",
"WinoAccount_Management_ExportDialog_AccountsRelogin": "Gli account importati su un altro PC richiederanno comunque di effettuare nuovamente l'accesso prima che possano essere utilizzati.", "WinoAccount_Management_ExportDialog_AccountsRelogin": "Gli account importati su un altro PC richiederanno comunque di effettuare nuovamente l'accesso prima che possano essere utilizzati.",
"WinoAccount_Management_ExportDialog_InProgress": "Esportazione dei dati Wino selezionati in corso...", "WinoAccount_Management_ExportDialog_InProgress": "Esportazione dei dati Wino selezionati in corso...",
"WinoAccount_Management_LocalDataSectionTitle": "Trasferisci con un file JSON",
"WinoAccount_Management_LocalDataSectionDescription": "Importa o esporta in un file JSON locale. password, token e altre informazioni sensibili non sono inclusi.",
"WinoAccount_Management_LocalDataImportAction": "Importa",
"WinoAccount_Management_LocalDataExportAction": "Esporta",
"WinoAccount_Management_LocalDataSaved": "Hai salvato i dati esportati di Wino in {0}.",
"WinoAccount_Management_LocalDataInvalidFile": "Il file JSON selezionato non contiene un'esportazione Wino valida.",
"WinoAccount_Management_LoadFailed": "Impossibile caricare le ultime informazioni dell'Account Wino.", "WinoAccount_Management_LoadFailed": "Impossibile caricare le ultime informazioni dell'Account Wino.",
"WinoAccount_Management_ActionFailed": "La richiesta dell'Account Wino non può essere completata.", "WinoAccount_Management_ActionFailed": "La richiesta dell'Account Wino non può essere completata.",
"WinoAccount_SettingsSection_Title": "Account Wino", "WinoAccount_SettingsSection_Title": "Account Wino",
@@ -1514,8 +1541,22 @@
"WelcomeWizard_Step3Title": "Completa la configurazione", "WelcomeWizard_Step3Title": "Completa la configurazione",
"ProviderSelection_Title": "Scegli il provider di posta elettronica", "ProviderSelection_Title": "Scegli il provider di posta elettronica",
"ProviderSelection_Subtitle": "Seleziona un provider qui sotto per aggiungere il tuo account di posta a Wino Mail.", "ProviderSelection_Subtitle": "Seleziona un provider qui sotto per aggiungere il tuo account di posta a Wino Mail.",
"ProviderSelection_StepProgress": "Fase {0} di 3",
"ProviderSelection_IdentityTitle": "Identità dell'account",
"ProviderSelection_IdentityDescription": "Scegli come apparirà questo account in Wino.",
"ProviderSelection_ProviderSectionTitle": "Fornitore",
"ProviderSelection_ProviderSectionDescription": "Seleziona il servizio che vuoi connettere.",
"ProviderSelection_CapabilitySectionTitle": "Usa questo account per",
"ProviderSelection_CapabilitySectionDescription": "Scegli se vuoi posta, calendario o entrambi.",
"ProviderSelection_CapabilityProviderDescription_OAuth": "Nel passaggio successivo, l'autenticazione sicura collegherà il tuo account. Se abiliti il calendario, Wino collegherà automaticamente anche Outlook Calendar o Google Calendar.",
"ProviderSelection_CapabilityProviderDescription_SpecialImap": "Nel passaggio successivo inserirai le credenziali del provider. La posta utilizza IMAP/SMTP, e il calendario può utilizzare CalDAV o rimanere locale su questo dispositivo.",
"ProviderSelection_CapabilityProviderDescription_CustomServer": "Nel passaggio successivo inserirai i dettagli del server. La posta utilizza IMAP/SMTP, e il calendario può utilizzare CalDAV o rimanere locale su questo dispositivo.",
"ProviderSelection_AccountNameHeader": "Nome account", "ProviderSelection_AccountNameHeader": "Nome account",
"ProviderSelection_AccountNamePlaceholder": "ad es. Personale, Lavoro", "ProviderSelection_AccountNamePlaceholder": "ad es. Personale, Lavoro",
"ProviderSelection_UseForMail": "Posta",
"ProviderSelection_UseForCalendar": "Calendario",
"ProviderSelection_CapabilityValidationMessage": "Seleziona almeno una funzionalità prima di procedere.",
"ProviderSelection_CalendarOnlyServerHint": "Se prosegui con solo calendario, la pagina successiva non richiederà un indirizzo email.",
"ProviderSelection_DisplayNameHeader": "Nome visualizzato", "ProviderSelection_DisplayNameHeader": "Nome visualizzato",
"ProviderSelection_DisplayNamePlaceholder": "es. John Doe", "ProviderSelection_DisplayNamePlaceholder": "es. John Doe",
"ProviderSelection_EmailHeader": "Indirizzo e-mail", "ProviderSelection_EmailHeader": "Indirizzo e-mail",
@@ -47,6 +47,11 @@
"AccountDetailsPage_CalendarListDescription": "設定を構成するカレンダーを選択してください。", "AccountDetailsPage_CalendarListDescription": "設定を構成するカレンダーを選択してください。",
"AccountDetailsPage_InitialSynchronization_Title": "初期同期", "AccountDetailsPage_InitialSynchronization_Title": "初期同期",
"AccountDetailsPage_InitialSynchronization_Description": "Wino は {0} まで遡ってメールを同期しました。", "AccountDetailsPage_InitialSynchronization_Description": "Wino は {0} まで遡ってメールを同期しました。",
"AccountDetailsPage_CapabilityTitle": "接続機能",
"AccountDetailsPage_CapabilityDescription": "このアカウントをメール、カレンダー、または両方に使用するかを選択します。新機能を有効にすると、再度サインインを求められることがあります。",
"AccountCapability_MailOnly": "メールのみ",
"AccountCapability_CalendarOnly": "カレンダーのみ",
"AccountCapability_MailAndCalendar": "メール+カレンダー",
"AddHyperlink": "追加", "AddHyperlink": "追加",
"AppCloseBackgroundSynchronizationWarningTitle": "Background Synchronization", "AppCloseBackgroundSynchronizationWarningTitle": "Background Synchronization",
"AppCloseStartupLaunchDisabledWarningMessageFirstLine": "Application has not been set to launch on Windows startup.", "AppCloseStartupLaunchDisabledWarningMessageFirstLine": "Application has not been set to launch on Windows startup.",
@@ -76,6 +81,7 @@
"Buttons_ApplyTheme": "テーマを適用", "Buttons_ApplyTheme": "テーマを適用",
"Buttons_PopOut": "ポップアウト", "Buttons_PopOut": "ポップアウト",
"Buttons_Browse": "閲覧", "Buttons_Browse": "閲覧",
"Buttons_Back": "戻る",
"Buttons_Cancel": "キャンセル", "Buttons_Cancel": "キャンセル",
"Buttons_Close": "閉じる", "Buttons_Close": "閉じる",
"Buttons_Copy": "コピー", "Buttons_Copy": "コピー",
@@ -299,6 +305,8 @@
"DialogMessage_DeleteRecurringSeriesTitle": "繰り返しシリーズを削除", "DialogMessage_DeleteRecurringSeriesTitle": "繰り返しシリーズを削除",
"DialogMessage_DiscardDraftConfirmationMessage": "この下書きは破棄されます。続行しますか?", "DialogMessage_DiscardDraftConfirmationMessage": "この下書きは破棄されます。続行しますか?",
"DialogMessage_DiscardDraftConfirmationTitle": "下書きを破棄", "DialogMessage_DiscardDraftConfirmationTitle": "下書きを破棄",
"DialogMessage_CloseDraftWindowConfirmationMessage": "下書きがまだ開いています。ウィンドウを閉じる前に保存しますか?",
"DialogMessage_CloseDraftWindowConfirmationTitle": "ウィンドウを閉じる",
"DialogMessage_EmptySubjectConfirmation": "Missing Subject", "DialogMessage_EmptySubjectConfirmation": "Missing Subject",
"DialogMessage_EmptySubjectConfirmationMessage": "Message has no subject. Do you want to continue?", "DialogMessage_EmptySubjectConfirmationMessage": "Message has no subject. Do you want to continue?",
"DialogMessage_EnableStartupLaunchDeniedMessage": "You can enable startup launch from Settings -> App Preferences.", "DialogMessage_EnableStartupLaunchDeniedMessage": "You can enable startup launch from Settings -> App Preferences.",
@@ -681,6 +689,10 @@
"NoMailSelected": "No message selected", "NoMailSelected": "No message selected",
"NoMessageCrieteria": "No messages match your search criteria", "NoMessageCrieteria": "No messages match your search criteria",
"NoMessageEmptyFolder": "This folder is empty", "NoMessageEmptyFolder": "This folder is empty",
"MailEmptyState_Title": "メールが有効なアカウントがありません",
"MailEmptyState_Message": "カレンダー用に接続されているアカウントはありますが、メール用として有効になっているものはありません。メールアカウントを追加するか、既存のアカウントを更新してメールを使用してください。",
"MailEmptyState_AddAccount": "アカウントを追加",
"MailEmptyState_ManageAccounts": "アカウントを管理",
"Notifications_MultipleNotificationsMessage": "You have {0} new messages.", "Notifications_MultipleNotificationsMessage": "You have {0} new messages.",
"Notifications_MultipleNotificationsTitle": "New Mail", "Notifications_MultipleNotificationsTitle": "New Mail",
"Notifications_WinoUpdatedMessage": "Checkout new version {0}", "Notifications_WinoUpdatedMessage": "Checkout new version {0}",
@@ -824,6 +836,8 @@
"SettingsDeleteAccount_Title": "Delete this account", "SettingsDeleteAccount_Title": "Delete this account",
"SettingsDeleteProtection_Description": "Should Wino ask you for confirmation every time you try to permanently delete a mail using Shift + Del keys?", "SettingsDeleteProtection_Description": "Should Wino ask you for confirmation every time you try to permanently delete a mail using Shift + Del keys?",
"SettingsDeleteProtection_Title": "Permanent Delete Protection", "SettingsDeleteProtection_Title": "Permanent Delete Protection",
"SettingsEmptyJunkFolderCommand_Description": "迷惑メール フォルダーの「空にする」コマンドを表示します。この操作は確認を求めず、迷惑メール フォルダー内のすべてのメールを即座に削除します。",
"SettingsEmptyJunkFolderCommand_Title": "迷惑メール フォルダーを空にするコマンドを表示",
"SettingsDiagnostics_Description": "For developers", "SettingsDiagnostics_Description": "For developers",
"SettingsDiagnostics_DiagnosticId_Description": "Share this ID with the developers when asked to get help for the issues you experience in Wino Mail.", "SettingsDiagnostics_DiagnosticId_Description": "Share this ID with the developers when asked to get help for the issues you experience in Wino Mail.",
"SettingsDiagnostics_DiagnosticId_Title": "Diagnostic ID", "SettingsDiagnostics_DiagnosticId_Title": "Diagnostic ID",
@@ -1074,6 +1088,12 @@
"SettingsTaskbarBadge_Title": "Taskbar Badge", "SettingsTaskbarBadge_Title": "Taskbar Badge",
"SettingsThreads_Description": "Organize messages into conversation threads.", "SettingsThreads_Description": "Organize messages into conversation threads.",
"SettingsThreads_Title": "Conversation Threading", "SettingsThreads_Title": "Conversation Threading",
"SettingsThreads_Enabled_Description": "関連するメッセージを1つの会話にまとめます。",
"SettingsThreads_Enabled_Title": "会話のスレッド化を有効にする",
"SettingsThreadOrder_Description": "会話スレッド内のアイテムの並べ替え方法を選択します。",
"SettingsThreadOrder_Title": "スレッド内アイテムの並べ替え",
"SettingsThreadOrder_LastItemFirst": "最後のアイテムを先頭に表示",
"SettingsThreadOrder_FirstItemFirst": "最初のアイテムを先頭に表示",
"SettingsUnlinkAccounts_Description": "Remove the link between accounts. his will not delete your accounts.", "SettingsUnlinkAccounts_Description": "Remove the link between accounts. his will not delete your accounts.",
"SettingsUnlinkAccounts_Title": "Unlink Accounts", "SettingsUnlinkAccounts_Title": "Unlink Accounts",
"SettingsMailRendering_ActionLabels_Title": "Action labels", "SettingsMailRendering_ActionLabels_Title": "Action labels",
@@ -1339,6 +1359,7 @@
"WelcomeWindow_GetStartedButton": "アカウントを追加して始める", "WelcomeWindow_GetStartedButton": "アカウントを追加して始める",
"WelcomeWindow_GetStartedDescription": "Wino Mail を始めるには、Outlook、Gmail、または IMAP アカウントを追加してください。", "WelcomeWindow_GetStartedDescription": "Wino Mail を始めるには、Outlook、Gmail、または IMAP アカウントを追加してください。",
"WelcomeWindow_ImportFromWinoAccount": "Wino アカウントからインポート", "WelcomeWindow_ImportFromWinoAccount": "Wino アカウントからインポート",
"WelcomeWindow_ImportFromJsonFile": "JSONファイルからインポート",
"WelcomeWindow_ImportInProgress": "同期された設定とアカウントをインポートしています...", "WelcomeWindow_ImportInProgress": "同期された設定とアカウントをインポートしています...",
"WelcomeWindow_ImportNoAccountsFound": "Wino アカウントに同期されたアカウントは見つかりませんでした。設定が利用可能だった場合、それらは復元されました。アカウントを手動で追加するには、はじめるを使ってください。", "WelcomeWindow_ImportNoAccountsFound": "Wino アカウントに同期されたアカウントは見つかりませんでした。設定が利用可能だった場合、それらは復元されました。アカウントを手動で追加するには、はじめるを使ってください。",
"WelcomeWindow_ImportDuplicateAccountsSkipped": "{0} 個の同期済みアカウントはすでにこのデバイスにあります。必要に応じて、別のアカウントを手動で追加するにははじめるを使用してください。", "WelcomeWindow_ImportDuplicateAccountsSkipped": "{0} 個の同期済みアカウントはすでにこのデバイスにあります。必要に応じて、別のアカウントを手動で追加するにははじめるを使用してください。",
@@ -1418,6 +1439,12 @@
"WinoAccount_Management_ExportDialog_AccountsDisclaimer": "パスワード、トークン、その他の機密情報は同期されません。", "WinoAccount_Management_ExportDialog_AccountsDisclaimer": "パスワード、トークン、その他の機密情報は同期されません。",
"WinoAccount_Management_ExportDialog_AccountsRelogin": "他のPCでインポートされたアカウントを使用するには、再度サインインする必要があります。", "WinoAccount_Management_ExportDialog_AccountsRelogin": "他のPCでインポートされたアカウントを使用するには、再度サインインする必要があります。",
"WinoAccount_Management_ExportDialog_InProgress": "選択した Wino データをエクスポートしています...", "WinoAccount_Management_ExportDialog_InProgress": "選択した Wino データをエクスポートしています...",
"WinoAccount_Management_LocalDataSectionTitle": "JSONファイルで転送",
"WinoAccount_Management_LocalDataSectionDescription": "ローカルJSONファイルからのインポートまたはエクスポートを行います。パスワード、トークン、その他の機密情報は含まれません。",
"WinoAccount_Management_LocalDataImportAction": "インポート",
"WinoAccount_Management_LocalDataExportAction": "エクスポート",
"WinoAccount_Management_LocalDataSaved": "エクスポートしたWinoデータを {0} に保存しました。",
"WinoAccount_Management_LocalDataInvalidFile": "選択したJSONファイルには有効なWinoエクスポートが含まれていません。",
"WinoAccount_Management_LoadFailed": "Wino は最新の Wino アカウント情報を読み込めませんでした。", "WinoAccount_Management_LoadFailed": "Wino は最新の Wino アカウント情報を読み込めませんでした。",
"WinoAccount_Management_ActionFailed": "Wino アカウントのリクエストを完了できませんでした。", "WinoAccount_Management_ActionFailed": "Wino アカウントのリクエストを完了できませんでした。",
"WinoAccount_SettingsSection_Title": "Wino アカウント", "WinoAccount_SettingsSection_Title": "Wino アカウント",
@@ -1514,8 +1541,22 @@
"WelcomeWizard_Step3Title": "設定を完了", "WelcomeWizard_Step3Title": "設定を完了",
"ProviderSelection_Title": "メールプロバイダを選択", "ProviderSelection_Title": "メールプロバイダを選択",
"ProviderSelection_Subtitle": "以下のプロバイダを選択して、Wino Mail にメールアカウントを追加します。", "ProviderSelection_Subtitle": "以下のプロバイダを選択して、Wino Mail にメールアカウントを追加します。",
"ProviderSelection_StepProgress": "ステップ {0} / 3",
"ProviderSelection_IdentityTitle": "アカウントの識別情報",
"ProviderSelection_IdentityDescription": "このアカウントがWino内でどのように表示されるかを選択します。",
"ProviderSelection_ProviderSectionTitle": "プロバイダ",
"ProviderSelection_ProviderSectionDescription": "接続したいサービスを選択します。",
"ProviderSelection_CapabilitySectionTitle": "このアカウントを使用する用途",
"ProviderSelection_CapabilitySectionDescription": "メール、カレンダー、または両方を使用するかを選択します。",
"ProviderSelection_CapabilityProviderDescription_OAuth": "次のステップで安全なサインインがあなたのアカウントを接続します。カレンダーを有効にすると、Winoは自動的にOutlook CalendarまたはGoogle Calendarにも接続します。",
"ProviderSelection_CapabilityProviderDescription_SpecialImap": "次のステップで、プロバイダの認証情報を入力します。メールはIMAP/SMTPを使用します。カレンダーはCalDAVを使用するか、このデバイスでローカルに保存します。",
"ProviderSelection_CapabilityProviderDescription_CustomServer": "次のステップでサーバー情報を入力します。メールはIMAP/SMTPを使用します。カレンダーはCalDAVを使用するか、このデバイスにローカルで保存します。",
"ProviderSelection_AccountNameHeader": "アカウント名", "ProviderSelection_AccountNameHeader": "アカウント名",
"ProviderSelection_AccountNamePlaceholder": "例: Personal、Work", "ProviderSelection_AccountNamePlaceholder": "例: Personal、Work",
"ProviderSelection_UseForMail": "メール",
"ProviderSelection_UseForCalendar": "カレンダー",
"ProviderSelection_CapabilityValidationMessage": "続行する前に、少なくとも1つの機能を選択してください。",
"ProviderSelection_CalendarOnlyServerHint": "カレンダーのみで続行する場合、次のページではメールアドレスを必要としません。",
"ProviderSelection_DisplayNameHeader": "表示名", "ProviderSelection_DisplayNameHeader": "表示名",
"ProviderSelection_DisplayNamePlaceholder": "例: John Doe", "ProviderSelection_DisplayNamePlaceholder": "例: John Doe",
"ProviderSelection_EmailHeader": "メールアドレス", "ProviderSelection_EmailHeader": "メールアドレス",
File diff suppressed because it is too large Load Diff
@@ -47,6 +47,11 @@
"AccountDetailsPage_CalendarListDescription": "Pasirinkite kalendorių, kad sukonfigūruotumėte jo nustatymus.", "AccountDetailsPage_CalendarListDescription": "Pasirinkite kalendorių, kad sukonfigūruotumėte jo nustatymus.",
"AccountDetailsPage_InitialSynchronization_Title": "Pradinė sinchronizacija", "AccountDetailsPage_InitialSynchronization_Title": "Pradinė sinchronizacija",
"AccountDetailsPage_InitialSynchronization_Description": "Wino sinchronizavo jūsų laiškus iki {0}.", "AccountDetailsPage_InitialSynchronization_Description": "Wino sinchronizavo jūsų laiškus iki {0}.",
"AccountDetailsPage_CapabilityTitle": "Prisijungtos funkcijos",
"AccountDetailsPage_CapabilityDescription": "Pasirinkite, ar ši paskyra bus naudojama el. paštu, kalendoriui ar abiem. Įjungus naują funkciją gali tekti prisijungti dar kartą.",
"AccountCapability_MailOnly": "Tik el. paštas",
"AccountCapability_CalendarOnly": "Tik kalendorius",
"AccountCapability_MailAndCalendar": "El. paštas ir kalendorius",
"AddHyperlink": "Add", "AddHyperlink": "Add",
"AppCloseBackgroundSynchronizationWarningTitle": "Background Synchronization", "AppCloseBackgroundSynchronizationWarningTitle": "Background Synchronization",
"AppCloseStartupLaunchDisabledWarningMessageFirstLine": "Application has not been set to launch on Windows startup.", "AppCloseStartupLaunchDisabledWarningMessageFirstLine": "Application has not been set to launch on Windows startup.",
@@ -76,6 +81,7 @@
"Buttons_ApplyTheme": "Apply Theme", "Buttons_ApplyTheme": "Apply Theme",
"Buttons_PopOut": "Iššokti", "Buttons_PopOut": "Iššokti",
"Buttons_Browse": "Browse", "Buttons_Browse": "Browse",
"Buttons_Back": "Atgal",
"Buttons_Cancel": "Cancel", "Buttons_Cancel": "Cancel",
"Buttons_Close": "Close", "Buttons_Close": "Close",
"Buttons_Copy": "Copy", "Buttons_Copy": "Copy",
@@ -299,6 +305,8 @@
"DialogMessage_DeleteRecurringSeriesTitle": "Ištrinti pakartojančią seriją", "DialogMessage_DeleteRecurringSeriesTitle": "Ištrinti pakartojančią seriją",
"DialogMessage_DiscardDraftConfirmationMessage": "This draft will be discarded. Do you want to continue?", "DialogMessage_DiscardDraftConfirmationMessage": "This draft will be discarded. Do you want to continue?",
"DialogMessage_DiscardDraftConfirmationTitle": "Discard Draft", "DialogMessage_DiscardDraftConfirmationTitle": "Discard Draft",
"DialogMessage_CloseDraftWindowConfirmationMessage": "Juodraštis vis dar atviras. Išsaugoti prieš uždarant langą?",
"DialogMessage_CloseDraftWindowConfirmationTitle": "Uždaryti langą",
"DialogMessage_EmptySubjectConfirmation": "Missing Subject", "DialogMessage_EmptySubjectConfirmation": "Missing Subject",
"DialogMessage_EmptySubjectConfirmationMessage": "Message has no subject. Do you want to continue?", "DialogMessage_EmptySubjectConfirmationMessage": "Message has no subject. Do you want to continue?",
"DialogMessage_EnableStartupLaunchDeniedMessage": "You can enable startup launch from Settings -> App Preferences.", "DialogMessage_EnableStartupLaunchDeniedMessage": "You can enable startup launch from Settings -> App Preferences.",
@@ -681,6 +689,10 @@
"NoMailSelected": "No message selected", "NoMailSelected": "No message selected",
"NoMessageCrieteria": "No messages match your search criteria", "NoMessageCrieteria": "No messages match your search criteria",
"NoMessageEmptyFolder": "This folder is empty", "NoMessageEmptyFolder": "This folder is empty",
"MailEmptyState_Title": "Nėra el. paštą palaikančių paskyrų",
"MailEmptyState_Message": "Turite paskyras, skirtas kalendoriui, bet nė viena iš jų nepalaiko el. pašto. Pridėkite el. pašto paskyrą arba atnaujinkite esamą paskyrą, kad naudotumėte el. paštą.",
"MailEmptyState_AddAccount": "Pridėti paskyrą",
"MailEmptyState_ManageAccounts": "Valdyti paskyras",
"Notifications_MultipleNotificationsMessage": "You have {0} new messages.", "Notifications_MultipleNotificationsMessage": "You have {0} new messages.",
"Notifications_MultipleNotificationsTitle": "New Mail", "Notifications_MultipleNotificationsTitle": "New Mail",
"Notifications_WinoUpdatedMessage": "Checkout new version {0}", "Notifications_WinoUpdatedMessage": "Checkout new version {0}",
@@ -824,6 +836,8 @@
"SettingsDeleteAccount_Title": "Delete this account", "SettingsDeleteAccount_Title": "Delete this account",
"SettingsDeleteProtection_Description": "Should Wino ask you for confirmation every time you try to permanently delete a mail using Shift + Del keys?", "SettingsDeleteProtection_Description": "Should Wino ask you for confirmation every time you try to permanently delete a mail using Shift + Del keys?",
"SettingsDeleteProtection_Title": "Permanent Delete Protection", "SettingsDeleteProtection_Title": "Permanent Delete Protection",
"SettingsEmptyJunkFolderCommand_Description": "Rodyti komandą Išvalyti šlamšto aplanką šlamšto aplankuose. Šis veiksmas nepaprašys patvirtinimo ir nedelsiant ištrins visus el. laiškus šlamšto aplanke.",
"SettingsEmptyJunkFolderCommand_Title": "Rodyti komandą Išvalyti šlamšto aplanką",
"SettingsDiagnostics_Description": "For developers", "SettingsDiagnostics_Description": "For developers",
"SettingsDiagnostics_DiagnosticId_Description": "Share this ID with the developers when asked to get help for the issues you experience in Wino Mail.", "SettingsDiagnostics_DiagnosticId_Description": "Share this ID with the developers when asked to get help for the issues you experience in Wino Mail.",
"SettingsDiagnostics_DiagnosticId_Title": "Diagnostic ID", "SettingsDiagnostics_DiagnosticId_Title": "Diagnostic ID",
@@ -1074,6 +1088,12 @@
"SettingsTaskbarBadge_Title": "Taskbar Badge", "SettingsTaskbarBadge_Title": "Taskbar Badge",
"SettingsThreads_Description": "Organize messages into conversation threads.", "SettingsThreads_Description": "Organize messages into conversation threads.",
"SettingsThreads_Title": "Conversation Threading", "SettingsThreads_Title": "Conversation Threading",
"SettingsThreads_Enabled_Description": "Susijusius pranešimus sugrupuoti į vieną pokalbį.",
"SettingsThreads_Enabled_Title": "Įjungti pokalbių gijas",
"SettingsThreadOrder_Description": "Pasirinkite, kaip elementai rūšiuojami pokalbių gijoje.",
"SettingsThreadOrder_Title": "Pokalbių gijų rūšiavimas",
"SettingsThreadOrder_LastItemFirst": "Paskutinis elementas pirmas",
"SettingsThreadOrder_FirstItemFirst": "Pirmasis elementas pirmas",
"SettingsUnlinkAccounts_Description": "Remove the link between accounts. his will not delete your accounts.", "SettingsUnlinkAccounts_Description": "Remove the link between accounts. his will not delete your accounts.",
"SettingsUnlinkAccounts_Title": "Unlink Accounts", "SettingsUnlinkAccounts_Title": "Unlink Accounts",
"SettingsMailRendering_ActionLabels_Title": "Action labels", "SettingsMailRendering_ActionLabels_Title": "Action labels",
@@ -1339,6 +1359,7 @@
"WelcomeWindow_GetStartedButton": "Pradėti pridėdami paskyrą", "WelcomeWindow_GetStartedButton": "Pradėti pridėdami paskyrą",
"WelcomeWindow_GetStartedDescription": "Pridėkite paskyrą Outlook, Gmail arba IMAP, kad pradėtumėte naudotis Wino Mail.", "WelcomeWindow_GetStartedDescription": "Pridėkite paskyrą Outlook, Gmail arba IMAP, kad pradėtumėte naudotis Wino Mail.",
"WelcomeWindow_ImportFromWinoAccount": "Importuoti iš jūsų Wino paskyros", "WelcomeWindow_ImportFromWinoAccount": "Importuoti iš jūsų Wino paskyros",
"WelcomeWindow_ImportFromJsonFile": "Importuoti iš JSON failo",
"WelcomeWindow_ImportInProgress": "Importuojami jūsų sinchronizuoti nustatymai ir paskyros...", "WelcomeWindow_ImportInProgress": "Importuojami jūsų sinchronizuoti nustatymai ir paskyros...",
"WelcomeWindow_ImportNoAccountsFound": "Nerasta sinchronizuotų paskyrų jūsų Wino paskyroje. Jei buvo nustatymų, jie buvo atstatyti. Naudokite Pradėti, kad pridėtumėte paskyrą rankiniu būdu.", "WelcomeWindow_ImportNoAccountsFound": "Nerasta sinchronizuotų paskyrų jūsų Wino paskyroje. Jei buvo nustatymų, jie buvo atstatyti. Naudokite Pradėti, kad pridėtumėte paskyrą rankiniu būdu.",
"WelcomeWindow_ImportDuplicateAccountsSkipped": "{0} sinchronizuotų paskyrų jau yra šiame įrenginyje. Jei reikia, naudokite Pradėti, kad pridėtumėte dar vieną paskyrą rankiniu būdu.", "WelcomeWindow_ImportDuplicateAccountsSkipped": "{0} sinchronizuotų paskyrų jau yra šiame įrenginyje. Jei reikia, naudokite Pradėti, kad pridėtumėte dar vieną paskyrą rankiniu būdu.",
@@ -1418,6 +1439,12 @@
"WinoAccount_Management_ExportDialog_AccountsDisclaimer": "Slaptažodžiai, tokenai ir kita jautri informacija nėra sinchronizuojama.", "WinoAccount_Management_ExportDialog_AccountsDisclaimer": "Slaptažodžiai, tokenai ir kita jautri informacija nėra sinchronizuojama.",
"WinoAccount_Management_ExportDialog_AccountsRelogin": "Importuotos paskyros kituose kompiuteriuose vis tiek reikės prisijungti iš naujo prieš jų naudojimą.", "WinoAccount_Management_ExportDialog_AccountsRelogin": "Importuotos paskyros kituose kompiuteriuose vis tiek reikės prisijungti iš naujo prieš jų naudojimą.",
"WinoAccount_Management_ExportDialog_InProgress": "Eksportuojami jūsų pasirinkti Wino duomenys...", "WinoAccount_Management_ExportDialog_InProgress": "Eksportuojami jūsų pasirinkti Wino duomenys...",
"WinoAccount_Management_LocalDataSectionTitle": "Perduoti su JSON failu",
"WinoAccount_Management_LocalDataSectionDescription": "Importuoti iš arba eksportuoti į vietinį JSON failą. Slaptažodžiai, tokenai ir kita jautri informacija nėra įtraukiama.",
"WinoAccount_Management_LocalDataImportAction": "Importuoti",
"WinoAccount_Management_LocalDataExportAction": "Eksportuoti",
"WinoAccount_Management_LocalDataSaved": "Išsaugojau jūsų eksportuotus Wino duomenis į {0}.",
"WinoAccount_Management_LocalDataInvalidFile": "Pasirinktas JSON failas neapima galiojančio Wino eksporto.",
"WinoAccount_Management_LoadFailed": "Wino negalėjo įkelti naujausios Wino paskyros informacijos.", "WinoAccount_Management_LoadFailed": "Wino negalėjo įkelti naujausios Wino paskyros informacijos.",
"WinoAccount_Management_ActionFailed": "Prašymas Wino paskyrai negalėjo būti užbaigtas.", "WinoAccount_Management_ActionFailed": "Prašymas Wino paskyrai negalėjo būti užbaigtas.",
"WinoAccount_SettingsSection_Title": "Wino paskyra", "WinoAccount_SettingsSection_Title": "Wino paskyra",
@@ -1514,8 +1541,22 @@
"WelcomeWizard_Step3Title": "Nustatymo užbaigimas", "WelcomeWizard_Step3Title": "Nustatymo užbaigimas",
"ProviderSelection_Title": "Pasirinkite savo el. pašto teikėją", "ProviderSelection_Title": "Pasirinkite savo el. pašto teikėją",
"ProviderSelection_Subtitle": "Pasirinkite teikėją žemiau, kad pridėtumėte savo el. pašto paskyrą prie Wino Mail.", "ProviderSelection_Subtitle": "Pasirinkite teikėją žemiau, kad pridėtumėte savo el. pašto paskyrą prie Wino Mail.",
"ProviderSelection_StepProgress": "Žingsnis {0} iš 3",
"ProviderSelection_IdentityTitle": "Paskyros tapatybė",
"ProviderSelection_IdentityDescription": "Pasirinkite, kaip ši paskyra pasirodys Wino viduje.",
"ProviderSelection_ProviderSectionTitle": "Paslaugų teikėjas",
"ProviderSelection_ProviderSectionDescription": "Pasirinkite paslaugą, kurią norite prijungti.",
"ProviderSelection_CapabilitySectionTitle": "Naudoti šią paskyrą",
"ProviderSelection_CapabilitySectionDescription": "Pasirinkite, ar norite el. paštą, kalendorių ar abiejų.",
"ProviderSelection_CapabilityProviderDescription_OAuth": "Kitoje pakopoje saugus prisijungimas sujungs jūsų paskyrą. Jei įjungs kalendorių, Wino automatiškai sujungs Outlook Calendar arba Google Calendar.",
"ProviderSelection_CapabilityProviderDescription_SpecialImap": "Kitoje pakopoje įvesite savo teikėjo prisijungimo duomenis. Paštas naudoja IMAP/SMTP, o kalendorius gali naudoti CalDAV arba likti šiame įrenginyje.",
"ProviderSelection_CapabilityProviderDescription_CustomServer": "Kitoje pakopoje įvesite serverio duomenis. El. paštas naudoja IMAP/SMTP, o kalendorius gali naudoti CalDAV arba likti šiame įrenginyje.",
"ProviderSelection_AccountNameHeader": "Paskyros pavadinimas", "ProviderSelection_AccountNameHeader": "Paskyros pavadinimas",
"ProviderSelection_AccountNamePlaceholder": "pvz. Asmeninė, Darbo", "ProviderSelection_AccountNamePlaceholder": "pvz. Asmeninė, Darbo",
"ProviderSelection_UseForMail": "El. paštas",
"ProviderSelection_UseForCalendar": "Kalendorius",
"ProviderSelection_CapabilityValidationMessage": "Prieš tęsiant pasirinkite bent vieną galimybę.",
"ProviderSelection_CalendarOnlyServerHint": "Jei tęsite tik kalendoriui, kitame puslapyje el. pašto adreso nereikės.",
"ProviderSelection_DisplayNameHeader": "Rodomas vardas", "ProviderSelection_DisplayNameHeader": "Rodomas vardas",
"ProviderSelection_DisplayNamePlaceholder": "pvz. Jonas Doe", "ProviderSelection_DisplayNamePlaceholder": "pvz. Jonas Doe",
"ProviderSelection_EmailHeader": "El. pašto adresas", "ProviderSelection_EmailHeader": "El. pašto adresas",
@@ -47,6 +47,11 @@
"AccountDetailsPage_CalendarListDescription": "Selecteer een kalender om de instellingen ervan te configureren.", "AccountDetailsPage_CalendarListDescription": "Selecteer een kalender om de instellingen ervan te configureren.",
"AccountDetailsPage_InitialSynchronization_Title": "Initiële synchronisatie", "AccountDetailsPage_InitialSynchronization_Title": "Initiële synchronisatie",
"AccountDetailsPage_InitialSynchronization_Description": "Wino heeft je e-mails gesynchroniseerd tot {0} terug.", "AccountDetailsPage_InitialSynchronization_Description": "Wino heeft je e-mails gesynchroniseerd tot {0} terug.",
"AccountDetailsPage_CapabilityTitle": "Verbonden functies",
"AccountDetailsPage_CapabilityDescription": "Kies of dit account wordt gebruikt voor e-mail, agenda, of beide. Het inschakelen van een nieuwe functie kan vereisen dat je opnieuw inlogt.",
"AccountCapability_MailOnly": "Alleen e-mail",
"AccountCapability_CalendarOnly": "Alleen agenda",
"AccountCapability_MailAndCalendar": "Mail en Agenda",
"AddHyperlink": "Toevoegen", "AddHyperlink": "Toevoegen",
"AppCloseBackgroundSynchronizationWarningTitle": "Achtergrondsynchronisatie", "AppCloseBackgroundSynchronizationWarningTitle": "Achtergrondsynchronisatie",
"AppCloseStartupLaunchDisabledWarningMessageFirstLine": "Applicatie is niet ingesteld om te laden bij het opstarten van Windows.", "AppCloseStartupLaunchDisabledWarningMessageFirstLine": "Applicatie is niet ingesteld om te laden bij het opstarten van Windows.",
@@ -76,6 +81,7 @@
"Buttons_ApplyTheme": "Thema toepassen", "Buttons_ApplyTheme": "Thema toepassen",
"Buttons_PopOut": "Pop-out", "Buttons_PopOut": "Pop-out",
"Buttons_Browse": "Bladeren", "Buttons_Browse": "Bladeren",
"Buttons_Back": "Terug",
"Buttons_Cancel": "Annuleren", "Buttons_Cancel": "Annuleren",
"Buttons_Close": "Sluiten", "Buttons_Close": "Sluiten",
"Buttons_Copy": "Kopiëren", "Buttons_Copy": "Kopiëren",
@@ -299,6 +305,8 @@
"DialogMessage_DeleteRecurringSeriesTitle": "Doorlopende serie verwijderen", "DialogMessage_DeleteRecurringSeriesTitle": "Doorlopende serie verwijderen",
"DialogMessage_DiscardDraftConfirmationMessage": "Dit concept zal worden verwijderd. Wilt u doorgaan?", "DialogMessage_DiscardDraftConfirmationMessage": "Dit concept zal worden verwijderd. Wilt u doorgaan?",
"DialogMessage_DiscardDraftConfirmationTitle": "Concept verwijderen", "DialogMessage_DiscardDraftConfirmationTitle": "Concept verwijderen",
"DialogMessage_CloseDraftWindowConfirmationMessage": "Er is nog een concept geopend. Sla het op voordat je het venster sluit?",
"DialogMessage_CloseDraftWindowConfirmationTitle": "Venster sluiten",
"DialogMessage_EmptySubjectConfirmation": "Onderwerp ontbreekt", "DialogMessage_EmptySubjectConfirmation": "Onderwerp ontbreekt",
"DialogMessage_EmptySubjectConfirmationMessage": "Het bericht heeft geen onderwerp. Wilt u doorgaan?", "DialogMessage_EmptySubjectConfirmationMessage": "Het bericht heeft geen onderwerp. Wilt u doorgaan?",
"DialogMessage_EnableStartupLaunchDeniedMessage": "U kunt laden bij opstarten inschakelen via Instellingen -> App voorkeuren.", "DialogMessage_EnableStartupLaunchDeniedMessage": "U kunt laden bij opstarten inschakelen via Instellingen -> App voorkeuren.",
@@ -681,6 +689,10 @@
"NoMailSelected": "Geen berichten geselecteerd", "NoMailSelected": "Geen berichten geselecteerd",
"NoMessageCrieteria": "Er zijn geen berichten die voldoen aan u zoekcriteria", "NoMessageCrieteria": "Er zijn geen berichten die voldoen aan u zoekcriteria",
"NoMessageEmptyFolder": "Deze map is leeg", "NoMessageEmptyFolder": "Deze map is leeg",
"MailEmptyState_Title": "Geen e-mailaccounts ingeschakeld.",
"MailEmptyState_Message": "Je hebt accounts verbonden voor agenda, maar geen van deze accounts is ingeschakeld voor e-mail. Voeg een e-mailaccount toe of werk een bestaand account bij om e-mail te gebruiken.",
"MailEmptyState_AddAccount": "Account toevoegen",
"MailEmptyState_ManageAccounts": "Accounts beheren",
"Notifications_MultipleNotificationsMessage": "U heeft {0} nieuwe berichten.", "Notifications_MultipleNotificationsMessage": "U heeft {0} nieuwe berichten.",
"Notifications_MultipleNotificationsTitle": "Nieuwe berichten", "Notifications_MultipleNotificationsTitle": "Nieuwe berichten",
"Notifications_WinoUpdatedMessage": "Bekijk de nieuwe versie {0}", "Notifications_WinoUpdatedMessage": "Bekijk de nieuwe versie {0}",
@@ -824,6 +836,8 @@
"SettingsDeleteAccount_Title": "Verwijder dit account", "SettingsDeleteAccount_Title": "Verwijder dit account",
"SettingsDeleteProtection_Description": "Moet Wino u om bevestiging vragen elke keer wanneer u een e-mail permanent verwijdert met de Shift + Del toetsen?", "SettingsDeleteProtection_Description": "Moet Wino u om bevestiging vragen elke keer wanneer u een e-mail permanent verwijdert met de Shift + Del toetsen?",
"SettingsDeleteProtection_Title": "Bescherming tegen permanent verwijderen", "SettingsDeleteProtection_Title": "Bescherming tegen permanent verwijderen",
"SettingsEmptyJunkFolderCommand_Description": "Toon het lege-map-commando in de Junk/Spam-mappen. Deze actie vraagt geen bevestiging en verwijdert onmiddellijk alle e-mails in de spam-map.",
"SettingsEmptyJunkFolderCommand_Title": "Toon leeg-map-commando",
"SettingsDiagnostics_Description": "Voor ontwikkelaars", "SettingsDiagnostics_Description": "Voor ontwikkelaars",
"SettingsDiagnostics_DiagnosticId_Description": "Deel dit ID met de ontwikkelaars wanneer er om hulp gevraagd wordt voor de problemen die u in Wino Mail ervaart.", "SettingsDiagnostics_DiagnosticId_Description": "Deel dit ID met de ontwikkelaars wanneer er om hulp gevraagd wordt voor de problemen die u in Wino Mail ervaart.",
"SettingsDiagnostics_DiagnosticId_Title": "Diagnostische ID", "SettingsDiagnostics_DiagnosticId_Title": "Diagnostische ID",
@@ -1074,6 +1088,12 @@
"SettingsTaskbarBadge_Title": "Taakbalk badge", "SettingsTaskbarBadge_Title": "Taakbalk badge",
"SettingsThreads_Description": "Voeg berichten samen tot gesprekken.", "SettingsThreads_Description": "Voeg berichten samen tot gesprekken.",
"SettingsThreads_Title": "Gesprekken", "SettingsThreads_Title": "Gesprekken",
"SettingsThreads_Enabled_Description": "Groepeer gerelateerde berichten in één gesprek.",
"SettingsThreads_Enabled_Title": "Gespreksdraad inschakelen",
"SettingsThreadOrder_Description": "Kies hoe items binnen een gesprek worden geordend.",
"SettingsThreadOrder_Title": "Sortering van gesprek-items",
"SettingsThreadOrder_LastItemFirst": "Laatste item eerst",
"SettingsThreadOrder_FirstItemFirst": "Eerste item eerst",
"SettingsUnlinkAccounts_Description": "Verwijder de koppeling tussen accounts. Dit zal niet uw accounts verwijderen.", "SettingsUnlinkAccounts_Description": "Verwijder de koppeling tussen accounts. Dit zal niet uw accounts verwijderen.",
"SettingsUnlinkAccounts_Title": "Ontkoppel accounts", "SettingsUnlinkAccounts_Title": "Ontkoppel accounts",
"SettingsMailRendering_ActionLabels_Title": "Actielabels", "SettingsMailRendering_ActionLabels_Title": "Actielabels",
@@ -1339,6 +1359,7 @@
"WelcomeWindow_GetStartedButton": "Beginnen met het toevoegen van een account.", "WelcomeWindow_GetStartedButton": "Beginnen met het toevoegen van een account.",
"WelcomeWindow_GetStartedDescription": "Voeg uw Outlook-, Gmail- of IMAP-account toe om aan de slag te gaan met Wino Mail.", "WelcomeWindow_GetStartedDescription": "Voeg uw Outlook-, Gmail- of IMAP-account toe om aan de slag te gaan met Wino Mail.",
"WelcomeWindow_ImportFromWinoAccount": "Importeren vanuit uw Wino-account", "WelcomeWindow_ImportFromWinoAccount": "Importeren vanuit uw Wino-account",
"WelcomeWindow_ImportFromJsonFile": "Importeren vanuit een JSON-bestand",
"WelcomeWindow_ImportInProgress": "Uw gesynchroniseerde voorkeuren en accounts worden geïmporteerd...", "WelcomeWindow_ImportInProgress": "Uw gesynchroniseerde voorkeuren en accounts worden geïmporteerd...",
"WelcomeWindow_ImportNoAccountsFound": "Er zijn geen gesynchroniseerde accounts gevonden in uw Wino-account. Als er voorkeuren beschikbaar waren, zijn ze hersteld. Gebruik Aan de slag om handmatig een account toe te voegen.", "WelcomeWindow_ImportNoAccountsFound": "Er zijn geen gesynchroniseerde accounts gevonden in uw Wino-account. Als er voorkeuren beschikbaar waren, zijn ze hersteld. Gebruik Aan de slag om handmatig een account toe te voegen.",
"WelcomeWindow_ImportDuplicateAccountsSkipped": "{0} gesynchroniseerde accounts zijn al beschikbaar op dit apparaat. Gebruik Aan de slag om indien nodig handmatig nog een account toe te voegen.", "WelcomeWindow_ImportDuplicateAccountsSkipped": "{0} gesynchroniseerde accounts zijn al beschikbaar op dit apparaat. Gebruik Aan de slag om indien nodig handmatig nog een account toe te voegen.",
@@ -1418,6 +1439,12 @@
"WinoAccount_Management_ExportDialog_AccountsDisclaimer": "Wachtwoorden, tokens en andere gevoelige informatie worden niet gesynchroniseerd.", "WinoAccount_Management_ExportDialog_AccountsDisclaimer": "Wachtwoorden, tokens en andere gevoelige informatie worden niet gesynchroniseerd.",
"WinoAccount_Management_ExportDialog_AccountsRelogin": "Geïmporteerde accounts op een andere pc vereisen nog steeds dat u zich opnieuw aanmeldt voordat ze kunnen worden gebruikt.", "WinoAccount_Management_ExportDialog_AccountsRelogin": "Geïmporteerde accounts op een andere pc vereisen nog steeds dat u zich opnieuw aanmeldt voordat ze kunnen worden gebruikt.",
"WinoAccount_Management_ExportDialog_InProgress": "Uw geselecteerde Wino-gegevens worden geëxporteerd...", "WinoAccount_Management_ExportDialog_InProgress": "Uw geselecteerde Wino-gegevens worden geëxporteerd...",
"WinoAccount_Management_LocalDataSectionTitle": "Overzetten met een JSON-bestand",
"WinoAccount_Management_LocalDataSectionDescription": "Importeer vanuit of exporteer naar een lokaal JSON-bestand. Wachtwoorden, tokens en andere gevoelige informatie worden niet opgenomen.",
"WinoAccount_Management_LocalDataImportAction": "Importeren",
"WinoAccount_Management_LocalDataExportAction": "Exporteren",
"WinoAccount_Management_LocalDataSaved": "Je geëxporteerde Wino-gegevens zijn opgeslagen naar {0}.",
"WinoAccount_Management_LocalDataInvalidFile": "Het geselecteerde JSON-bestand bevat geen geldige Wino-export.",
"WinoAccount_Management_LoadFailed": "Wino kon de nieuwste Wino Account-informatie niet laden.", "WinoAccount_Management_LoadFailed": "Wino kon de nieuwste Wino Account-informatie niet laden.",
"WinoAccount_Management_ActionFailed": "Het Wino Account-verzoek kon niet worden voltooid.", "WinoAccount_Management_ActionFailed": "Het Wino Account-verzoek kon niet worden voltooid.",
"WinoAccount_SettingsSection_Title": "Wino-account", "WinoAccount_SettingsSection_Title": "Wino-account",
@@ -1514,8 +1541,22 @@
"WelcomeWizard_Step3Title": "Configuratie voltooien", "WelcomeWizard_Step3Title": "Configuratie voltooien",
"ProviderSelection_Title": "Kies uw e-mailprovider", "ProviderSelection_Title": "Kies uw e-mailprovider",
"ProviderSelection_Subtitle": "Selecteer hieronder een provider om uw e-mailaccount toe te voegen aan Wino Mail.", "ProviderSelection_Subtitle": "Selecteer hieronder een provider om uw e-mailaccount toe te voegen aan Wino Mail.",
"ProviderSelection_StepProgress": "Stap {0} van 3",
"ProviderSelection_IdentityTitle": "Accountidentiteit",
"ProviderSelection_IdentityDescription": "Kies hoe dit account in Wino wordt weergegeven.",
"ProviderSelection_ProviderSectionTitle": "Provider",
"ProviderSelection_ProviderSectionDescription": "Selecteer de dienst die je wilt verbinden.",
"ProviderSelection_CapabilitySectionTitle": "Gebruik dit account voor",
"ProviderSelection_CapabilitySectionDescription": "Kies of je e-mail, agenda, of beide wilt gebruiken.",
"ProviderSelection_CapabilityProviderDescription_OAuth": "In de volgende stap wordt een beveiligde aanmelding uitgevoerd die je account verbindt. Als je agenda inschakelt, verbindt Wino automatisch Outlook Agenda of Google Agenda.",
"ProviderSelection_CapabilityProviderDescription_SpecialImap": "In de volgende stap voer je je provider-inloggegevens in. Mail gebruikt IMAP/SMTP, en agenda kan CalDAV gebruiken of lokaal op dit apparaat blijven.",
"ProviderSelection_CapabilityProviderDescription_CustomServer": "In de volgende stap voer je je servergegevens in. Mail gebruikt IMAP/SMTP, en agenda kan CalDAV gebruiken of lokaal op dit apparaat blijven.",
"ProviderSelection_AccountNameHeader": "Accountnaam", "ProviderSelection_AccountNameHeader": "Accountnaam",
"ProviderSelection_AccountNamePlaceholder": "bijv. Persoonlijk, Werk", "ProviderSelection_AccountNamePlaceholder": "bijv. Persoonlijk, Werk",
"ProviderSelection_UseForMail": "E-mail",
"ProviderSelection_UseForCalendar": "Agenda",
"ProviderSelection_CapabilityValidationMessage": "Kies ten minste één mogelijkheid voordat je verdergaat.",
"ProviderSelection_CalendarOnlyServerHint": "Als je doorgaat met alleen agenda, vereist de volgende pagina geen e-mailadres.",
"ProviderSelection_DisplayNameHeader": "Weergavenaam", "ProviderSelection_DisplayNameHeader": "Weergavenaam",
"ProviderSelection_DisplayNamePlaceholder": "bijv. John Doe", "ProviderSelection_DisplayNamePlaceholder": "bijv. John Doe",
"ProviderSelection_EmailHeader": "E-mailadres", "ProviderSelection_EmailHeader": "E-mailadres",
@@ -47,6 +47,11 @@
"AccountDetailsPage_CalendarListDescription": "Wybierz kalendarz, aby skonfigurować jego ustawienia.", "AccountDetailsPage_CalendarListDescription": "Wybierz kalendarz, aby skonfigurować jego ustawienia.",
"AccountDetailsPage_InitialSynchronization_Title": "Początkowa synchronizacja", "AccountDetailsPage_InitialSynchronization_Title": "Początkowa synchronizacja",
"AccountDetailsPage_InitialSynchronization_Description": "Wino zsynchronizował maile do {0} wstecz.", "AccountDetailsPage_InitialSynchronization_Description": "Wino zsynchronizował maile do {0} wstecz.",
"AccountDetailsPage_CapabilityTitle": "Funkcje połączone",
"AccountDetailsPage_CapabilityDescription": "Wybierz, czy to konto ma być używane do poczty, kalendarza, czy obu. Włączenie nowej funkcji może wymagać ponownego zalogowania.",
"AccountCapability_MailOnly": "Tylko Poczta",
"AccountCapability_CalendarOnly": "Tylko Kalendarz",
"AccountCapability_MailAndCalendar": "Poczta i Kalendarz",
"AddHyperlink": "Dodaj", "AddHyperlink": "Dodaj",
"AppCloseBackgroundSynchronizationWarningTitle": "Synchronizacja w tle", "AppCloseBackgroundSynchronizationWarningTitle": "Synchronizacja w tle",
"AppCloseStartupLaunchDisabledWarningMessageFirstLine": "Aplikacja nie została ustawiona do uruchamiania przy starcie systemu Windows.", "AppCloseStartupLaunchDisabledWarningMessageFirstLine": "Aplikacja nie została ustawiona do uruchamiania przy starcie systemu Windows.",
@@ -76,6 +81,7 @@
"Buttons_ApplyTheme": "Zastosuj motyw", "Buttons_ApplyTheme": "Zastosuj motyw",
"Buttons_PopOut": "Wysuń", "Buttons_PopOut": "Wysuń",
"Buttons_Browse": "Przeglądaj", "Buttons_Browse": "Przeglądaj",
"Buttons_Back": "Wstecz",
"Buttons_Cancel": "Anuluj", "Buttons_Cancel": "Anuluj",
"Buttons_Close": "Zamknij", "Buttons_Close": "Zamknij",
"Buttons_Copy": "Kopiuj", "Buttons_Copy": "Kopiuj",
@@ -299,6 +305,8 @@
"DialogMessage_DeleteRecurringSeriesTitle": "Usuń serię cykliczną", "DialogMessage_DeleteRecurringSeriesTitle": "Usuń serię cykliczną",
"DialogMessage_DiscardDraftConfirmationMessage": "Ta wersja robocza zostanie odrzucona. Czy chcesz kontynuować?", "DialogMessage_DiscardDraftConfirmationMessage": "Ta wersja robocza zostanie odrzucona. Czy chcesz kontynuować?",
"DialogMessage_DiscardDraftConfirmationTitle": "Porzuć wersje roboczą", "DialogMessage_DiscardDraftConfirmationTitle": "Porzuć wersje roboczą",
"DialogMessage_CloseDraftWindowConfirmationMessage": "Szkic jest nadal otwarty. Zapisz go przed zamknięciem okna?",
"DialogMessage_CloseDraftWindowConfirmationTitle": "Zamknij okno",
"DialogMessage_EmptySubjectConfirmation": "Brak tematu", "DialogMessage_EmptySubjectConfirmation": "Brak tematu",
"DialogMessage_EmptySubjectConfirmationMessage": "Wiadomość nie ma tematu. Czy chcesz kontynuować?", "DialogMessage_EmptySubjectConfirmationMessage": "Wiadomość nie ma tematu. Czy chcesz kontynuować?",
"DialogMessage_EnableStartupLaunchDeniedMessage": "Możesz włączyć uruchamianie automatyczne w Ustawieniach -> Preferencje Aplikacji.", "DialogMessage_EnableStartupLaunchDeniedMessage": "Możesz włączyć uruchamianie automatyczne w Ustawieniach -> Preferencje Aplikacji.",
@@ -681,6 +689,10 @@
"NoMailSelected": "Nie wybrano wiadomości", "NoMailSelected": "Nie wybrano wiadomości",
"NoMessageCrieteria": "Żadne wiadomości nie spełniają kryteriów wyszukiwania", "NoMessageCrieteria": "Żadne wiadomości nie spełniają kryteriów wyszukiwania",
"NoMessageEmptyFolder": "Ten katalog jest pusty", "NoMessageEmptyFolder": "Ten katalog jest pusty",
"MailEmptyState_Title": "Brak kont obsługujących pocztę",
"MailEmptyState_Message": "Masz konta podłączone do kalendarza, ale żadne z nich nie ma włączonej obsługi poczty. Dodaj konto pocztowe lub zaktualizuj istniejące konto, aby korzystać z poczty.",
"MailEmptyState_AddAccount": "Dodaj konto",
"MailEmptyState_ManageAccounts": "Zarządzaj kontami",
"Notifications_MultipleNotificationsMessage": "Masz {0} nowych wiadomości.", "Notifications_MultipleNotificationsMessage": "Masz {0} nowych wiadomości.",
"Notifications_MultipleNotificationsTitle": "New Mail", "Notifications_MultipleNotificationsTitle": "New Mail",
"Notifications_WinoUpdatedMessage": "Sprawdź nową wersję {0}", "Notifications_WinoUpdatedMessage": "Sprawdź nową wersję {0}",
@@ -824,6 +836,8 @@
"SettingsDeleteAccount_Title": "Usuń to konto", "SettingsDeleteAccount_Title": "Usuń to konto",
"SettingsDeleteProtection_Description": "Should Wino ask you for confirmation every time you try to permanently delete a mail using Shift + Del keys?", "SettingsDeleteProtection_Description": "Should Wino ask you for confirmation every time you try to permanently delete a mail using Shift + Del keys?",
"SettingsDeleteProtection_Title": "Ochrona przed trwałym usunięciem", "SettingsDeleteProtection_Title": "Ochrona przed trwałym usunięciem",
"SettingsEmptyJunkFolderCommand_Description": "Pokaż polecenie opróżniania pustego folderu w folderach Junk/Spam. Ta akcja nie poprosi o potwierdzenie i natychmiast usunie wszystkie wiadomości z folderu Spam.",
"SettingsEmptyJunkFolderCommand_Title": "Pokaż polecenie opróżniania pustego folderu Spam",
"SettingsDiagnostics_Description": "Dla programistów", "SettingsDiagnostics_Description": "Dla programistów",
"SettingsDiagnostics_DiagnosticId_Description": "Share this ID with the developers when asked to get help for the issues you experience in Wino Mail.", "SettingsDiagnostics_DiagnosticId_Description": "Share this ID with the developers when asked to get help for the issues you experience in Wino Mail.",
"SettingsDiagnostics_DiagnosticId_Title": "Diagnostic ID", "SettingsDiagnostics_DiagnosticId_Title": "Diagnostic ID",
@@ -1074,6 +1088,12 @@
"SettingsTaskbarBadge_Title": "Ikona paska zadań", "SettingsTaskbarBadge_Title": "Ikona paska zadań",
"SettingsThreads_Description": "Organizuj wiadomości w wątki konwersacji.", "SettingsThreads_Description": "Organizuj wiadomości w wątki konwersacji.",
"SettingsThreads_Title": "Wątkowanie konwersacji", "SettingsThreads_Title": "Wątkowanie konwersacji",
"SettingsThreads_Enabled_Description": "Łącz powiązane wiadomości w jedną rozmowę.",
"SettingsThreads_Enabled_Title": "Włącz wątki konwersacyjne",
"SettingsThreadOrder_Description": "Wybierz, jak elementy będą uporządkowane w wątku konwersacyjnym.",
"SettingsThreadOrder_Title": "Sortowanie elementów wątku",
"SettingsThreadOrder_LastItemFirst": "Ostatni element na początku",
"SettingsThreadOrder_FirstItemFirst": "Pierwszy element na początku",
"SettingsUnlinkAccounts_Description": "Usuń łącze pomiędzy kontami. To nie spowoduje usunięcie Twoich kont.", "SettingsUnlinkAccounts_Description": "Usuń łącze pomiędzy kontami. To nie spowoduje usunięcie Twoich kont.",
"SettingsUnlinkAccounts_Title": "Odłącz konto", "SettingsUnlinkAccounts_Title": "Odłącz konto",
"SettingsMailRendering_ActionLabels_Title": "Action labels", "SettingsMailRendering_ActionLabels_Title": "Action labels",
@@ -1339,6 +1359,7 @@
"WelcomeWindow_GetStartedButton": "Rozpocznij od dodania konta", "WelcomeWindow_GetStartedButton": "Rozpocznij od dodania konta",
"WelcomeWindow_GetStartedDescription": "Dodaj swoje konta Outlook, Gmail lub IMAP, aby rozpocząć z Wino Mail.", "WelcomeWindow_GetStartedDescription": "Dodaj swoje konta Outlook, Gmail lub IMAP, aby rozpocząć z Wino Mail.",
"WelcomeWindow_ImportFromWinoAccount": "Importuj z konta Wino", "WelcomeWindow_ImportFromWinoAccount": "Importuj z konta Wino",
"WelcomeWindow_ImportFromJsonFile": "Importuj z pliku JSON",
"WelcomeWindow_ImportInProgress": "Importowanie zsynchronizowanych ustawień i kont...", "WelcomeWindow_ImportInProgress": "Importowanie zsynchronizowanych ustawień i kont...",
"WelcomeWindow_ImportNoAccountsFound": "Nie znaleziono zsynchronizowanych kont w Twoim koncie Wino. Jeśli ustawienia były dostępne, zostały przywrócone. Aby dodać konto ręcznie, użyj Rozpocznij.", "WelcomeWindow_ImportNoAccountsFound": "Nie znaleziono zsynchronizowanych kont w Twoim koncie Wino. Jeśli ustawienia były dostępne, zostały przywrócone. Aby dodać konto ręcznie, użyj Rozpocznij.",
"WelcomeWindow_ImportDuplicateAccountsSkipped": "{0} zsynchronizowanych kont są już dostępne na tym urządzeniu. Aby dodać inne konto ręcznie, jeśli to potrzebne, użyj Rozpocznij.", "WelcomeWindow_ImportDuplicateAccountsSkipped": "{0} zsynchronizowanych kont są już dostępne na tym urządzeniu. Aby dodać inne konto ręcznie, jeśli to potrzebne, użyj Rozpocznij.",
@@ -1418,6 +1439,12 @@
"WinoAccount_Management_ExportDialog_AccountsDisclaimer": "Hasła, tokeny i inne wrażliwe dane nie są synchronizowane.", "WinoAccount_Management_ExportDialog_AccountsDisclaimer": "Hasła, tokeny i inne wrażliwe dane nie są synchronizowane.",
"WinoAccount_Management_ExportDialog_AccountsRelogin": "Zaimportowane konta na innym komputerze będą nadal wymagały ponownego zalogowania przed użyciem.", "WinoAccount_Management_ExportDialog_AccountsRelogin": "Zaimportowane konta na innym komputerze będą nadal wymagały ponownego zalogowania przed użyciem.",
"WinoAccount_Management_ExportDialog_InProgress": "Eksportowanie wybranych danych Wino...", "WinoAccount_Management_ExportDialog_InProgress": "Eksportowanie wybranych danych Wino...",
"WinoAccount_Management_LocalDataSectionTitle": "Przenoszenie danych za pomocą pliku JSON",
"WinoAccount_Management_LocalDataSectionDescription": "Importuj z lokalnego pliku JSON lub eksportuj do niego. Hasła, tokeny i inne poufne informacje nie są dołączane.",
"WinoAccount_Management_LocalDataImportAction": "Importuj",
"WinoAccount_Management_LocalDataExportAction": "Eksportuj",
"WinoAccount_Management_LocalDataSaved": "Zapisano wyeksportowane dane Wino do {0}.",
"WinoAccount_Management_LocalDataInvalidFile": "Wybrany plik JSON nie zawiera prawidłowego eksportu danych Wino.",
"WinoAccount_Management_LoadFailed": "Nie udało się załadować najnowszych informacji o koncie Wino.", "WinoAccount_Management_LoadFailed": "Nie udało się załadować najnowszych informacji o koncie Wino.",
"WinoAccount_Management_ActionFailed": "Żądanie konta Wino nie mogło zostać zakończone.", "WinoAccount_Management_ActionFailed": "Żądanie konta Wino nie mogło zostać zakończone.",
"WinoAccount_SettingsSection_Title": "Konto Wino", "WinoAccount_SettingsSection_Title": "Konto Wino",
@@ -1514,8 +1541,22 @@
"WelcomeWizard_Step3Title": "Zakończ konfigurację", "WelcomeWizard_Step3Title": "Zakończ konfigurację",
"ProviderSelection_Title": "Wybierz dostawcę poczty e-mail", "ProviderSelection_Title": "Wybierz dostawcę poczty e-mail",
"ProviderSelection_Subtitle": "Wybierz dostawcę poniżej, aby dodać swoje konto e-mail do Wino Mail.", "ProviderSelection_Subtitle": "Wybierz dostawcę poniżej, aby dodać swoje konto e-mail do Wino Mail.",
"ProviderSelection_StepProgress": "Krok {0} z 3",
"ProviderSelection_IdentityTitle": "Tożsamość konta",
"ProviderSelection_IdentityDescription": "Wybierz, jak to konto będzie wyświetlane w Wino.",
"ProviderSelection_ProviderSectionTitle": "Dostawca",
"ProviderSelection_ProviderSectionDescription": "Wybierz usługę, którą chcesz połączyć.",
"ProviderSelection_CapabilitySectionTitle": "Użyj tego konta do",
"ProviderSelection_CapabilitySectionDescription": "Wybierz, czy chcesz używać poczty, kalendarza, czy obu.",
"ProviderSelection_CapabilityProviderDescription_OAuth": "W następnym kroku bezpieczne logowanie połączy twoje konto. Jeśli włączysz kalendarz, Wino automatycznie połączy Outlook Calendar lub Google Calendar.",
"ProviderSelection_CapabilityProviderDescription_SpecialImap": "W kolejnym kroku wprowadzisz dane uwierzytelniające dostawcy. Poczta używa IMAP/SMTP, a kalendarz może korzystać z CalDAV lub pozostawać lokalny na tym urządzeniu.",
"ProviderSelection_CapabilityProviderDescription_CustomServer": "W następnym kroku wprowadzisz szczegóły serwera. Poczta używa IMAP/SMTP, a kalendarz może używać CalDAV lub zostać lokalny na tym urządzeniu.",
"ProviderSelection_AccountNameHeader": "Nazwa konta", "ProviderSelection_AccountNameHeader": "Nazwa konta",
"ProviderSelection_AccountNamePlaceholder": "np. Osobiste, Służbowe", "ProviderSelection_AccountNamePlaceholder": "np. Osobiste, Służbowe",
"ProviderSelection_UseForMail": "Poczta",
"ProviderSelection_UseForCalendar": "Kalendarz",
"ProviderSelection_CapabilityValidationMessage": "Wybierz co najmniej jedną funkcję przed kontynuowaniem.",
"ProviderSelection_CalendarOnlyServerHint": "Jeśli kontynuujesz wyłącznie z kalendarzem, na następnym kroku nie będzie wymagany adres e-mail.",
"ProviderSelection_DisplayNameHeader": "Nazwa wyświetlana", "ProviderSelection_DisplayNameHeader": "Nazwa wyświetlana",
"ProviderSelection_DisplayNamePlaceholder": "np. Jan Kowalski", "ProviderSelection_DisplayNamePlaceholder": "np. Jan Kowalski",
"ProviderSelection_EmailHeader": "Adres e-mail", "ProviderSelection_EmailHeader": "Adres e-mail",
@@ -47,6 +47,11 @@
"AccountDetailsPage_CalendarListDescription": "Selecione um calendário para configurar suas configurações.", "AccountDetailsPage_CalendarListDescription": "Selecione um calendário para configurar suas configurações.",
"AccountDetailsPage_InitialSynchronization_Title": "Sincronização inicial", "AccountDetailsPage_InitialSynchronization_Title": "Sincronização inicial",
"AccountDetailsPage_InitialSynchronization_Description": "Wino sincronizou seus e-mails até {0} no passado.", "AccountDetailsPage_InitialSynchronization_Description": "Wino sincronizou seus e-mails até {0} no passado.",
"AccountDetailsPage_CapabilityTitle": "Recursos conectados",
"AccountDetailsPage_CapabilityDescription": "Escolha se esta conta será usada para E-mail, Calendário ou ambos. Ativar um novo recurso pode exigir que você faça login novamente.",
"AccountCapability_MailOnly": "Somente E-mail",
"AccountCapability_CalendarOnly": "Somente Calendário",
"AccountCapability_MailAndCalendar": "E-mail + Calendário",
"AddHyperlink": "Adicionar", "AddHyperlink": "Adicionar",
"AppCloseBackgroundSynchronizationWarningTitle": "Sincronização em segundo plano", "AppCloseBackgroundSynchronizationWarningTitle": "Sincronização em segundo plano",
"AppCloseStartupLaunchDisabledWarningMessageFirstLine": "O aplicativo não foi configurado para iniciar com o Windows.", "AppCloseStartupLaunchDisabledWarningMessageFirstLine": "O aplicativo não foi configurado para iniciar com o Windows.",
@@ -76,6 +81,7 @@
"Buttons_ApplyTheme": "Aplicar Tema", "Buttons_ApplyTheme": "Aplicar Tema",
"Buttons_PopOut": "Abrir em nova janela", "Buttons_PopOut": "Abrir em nova janela",
"Buttons_Browse": "Navegar", "Buttons_Browse": "Navegar",
"Buttons_Back": "Voltar",
"Buttons_Cancel": "Cancelar", "Buttons_Cancel": "Cancelar",
"Buttons_Close": "Fechar", "Buttons_Close": "Fechar",
"Buttons_Copy": "Copiar", "Buttons_Copy": "Copiar",
@@ -299,6 +305,8 @@
"DialogMessage_DeleteRecurringSeriesTitle": "Excluir Série Recorrente", "DialogMessage_DeleteRecurringSeriesTitle": "Excluir Série Recorrente",
"DialogMessage_DiscardDraftConfirmationMessage": "Este rascunho será descartado. Você quer continuar?", "DialogMessage_DiscardDraftConfirmationMessage": "Este rascunho será descartado. Você quer continuar?",
"DialogMessage_DiscardDraftConfirmationTitle": "Descartar Rascunho", "DialogMessage_DiscardDraftConfirmationTitle": "Descartar Rascunho",
"DialogMessage_CloseDraftWindowConfirmationMessage": "Há um rascunho aberto. Salve-o antes de fechar a janela?",
"DialogMessage_CloseDraftWindowConfirmationTitle": "Fechar Janela",
"DialogMessage_EmptySubjectConfirmation": "Faltando Assunto", "DialogMessage_EmptySubjectConfirmation": "Faltando Assunto",
"DialogMessage_EmptySubjectConfirmationMessage": "Mensagem não possui assunto. Você deseja continuar?", "DialogMessage_EmptySubjectConfirmationMessage": "Mensagem não possui assunto. Você deseja continuar?",
"DialogMessage_EnableStartupLaunchDeniedMessage": "Você pode habilitar a inicialização em Configurações -> Preferências do Aplicativo.", "DialogMessage_EnableStartupLaunchDeniedMessage": "Você pode habilitar a inicialização em Configurações -> Preferências do Aplicativo.",
@@ -681,6 +689,10 @@
"NoMailSelected": "Nenhuma mensagem selecionada", "NoMailSelected": "Nenhuma mensagem selecionada",
"NoMessageCrieteria": "Nenhuma mensagem corresponde aos critérios da sua pesquisa", "NoMessageCrieteria": "Nenhuma mensagem corresponde aos critérios da sua pesquisa",
"NoMessageEmptyFolder": "Esta pasta está vazia", "NoMessageEmptyFolder": "Esta pasta está vazia",
"MailEmptyState_Title": "Nenhuma conta habilitada para E-mail",
"MailEmptyState_Message": "Você tem contas conectadas para calendário, mas nenhuma delas está habilitada para e-mail. Adicione uma conta de e-mail ou atualize uma conta existente para usar e-mail.",
"MailEmptyState_AddAccount": "Adicionar conta",
"MailEmptyState_ManageAccounts": "Gerenciar contas",
"Notifications_MultipleNotificationsMessage": "Você tem {0} novos emails.", "Notifications_MultipleNotificationsMessage": "Você tem {0} novos emails.",
"Notifications_MultipleNotificationsTitle": "Novo E-mail", "Notifications_MultipleNotificationsTitle": "Novo E-mail",
"Notifications_WinoUpdatedMessage": "Veja a nova versão {0}", "Notifications_WinoUpdatedMessage": "Veja a nova versão {0}",
@@ -824,6 +836,8 @@
"SettingsDeleteAccount_Title": "Apagar esta conta", "SettingsDeleteAccount_Title": "Apagar esta conta",
"SettingsDeleteProtection_Description": "O Wino deve solicitar confirmação sempre que você tentar excluir permanentemente um e-mail usando as teclas Shift + Del?", "SettingsDeleteProtection_Description": "O Wino deve solicitar confirmação sempre que você tentar excluir permanentemente um e-mail usando as teclas Shift + Del?",
"SettingsDeleteProtection_Title": "Proteção de exclusão permanente", "SettingsDeleteProtection_Title": "Proteção de exclusão permanente",
"SettingsEmptyJunkFolderCommand_Description": "Mostrar o comando para esvaziar a pasta nas pastas de Lixo/Spam. Esta ação não solicitará confirmação e excluirá imediatamente todas as mensagens na pasta de spam.",
"SettingsEmptyJunkFolderCommand_Title": "Mostrar o comando para esvaziar a pasta de Spam",
"SettingsDiagnostics_Description": "Para desenvolvedores", "SettingsDiagnostics_Description": "Para desenvolvedores",
"SettingsDiagnostics_DiagnosticId_Description": "Compartilhe esta identificação com os desenvolvedores quando solicitado para obter ajuda para os problemas que você experimentar no Wino Mail.", "SettingsDiagnostics_DiagnosticId_Description": "Compartilhe esta identificação com os desenvolvedores quando solicitado para obter ajuda para os problemas que você experimentar no Wino Mail.",
"SettingsDiagnostics_DiagnosticId_Title": "ID de diagnóstico", "SettingsDiagnostics_DiagnosticId_Title": "ID de diagnóstico",
@@ -1074,6 +1088,12 @@
"SettingsTaskbarBadge_Title": "Ícone da Barra de Tarefas", "SettingsTaskbarBadge_Title": "Ícone da Barra de Tarefas",
"SettingsThreads_Description": "Organizar mensagens em tópicos de conversa.", "SettingsThreads_Description": "Organizar mensagens em tópicos de conversa.",
"SettingsThreads_Title": "* Encadeamento de conversas", "SettingsThreads_Title": "* Encadeamento de conversas",
"SettingsThreads_Enabled_Description": "Agrupar mensagens relacionadas em uma única conversa.",
"SettingsThreads_Enabled_Title": "Ativar o encadeamento de conversas",
"SettingsThreadOrder_Description": "Escolha como os itens são ordenados dentro de uma conversa.",
"SettingsThreadOrder_Title": "Ordenação de itens da conversa",
"SettingsThreadOrder_LastItemFirst": "Último item primeiro",
"SettingsThreadOrder_FirstItemFirst": "Primeiro item primeiro",
"SettingsUnlinkAccounts_Description": "Remova o vínculo entre as contas. Isso não excluirá suas contas.", "SettingsUnlinkAccounts_Description": "Remova o vínculo entre as contas. Isso não excluirá suas contas.",
"SettingsUnlinkAccounts_Title": "Desvincular Contas", "SettingsUnlinkAccounts_Title": "Desvincular Contas",
"SettingsMailRendering_ActionLabels_Title": "Rótulos de ação", "SettingsMailRendering_ActionLabels_Title": "Rótulos de ação",
@@ -1339,6 +1359,7 @@
"WelcomeWindow_GetStartedButton": "Comece adicionando uma conta", "WelcomeWindow_GetStartedButton": "Comece adicionando uma conta",
"WelcomeWindow_GetStartedDescription": "Adicione sua conta do Outlook, Gmail ou IMAP para começar com o Wino Mail.", "WelcomeWindow_GetStartedDescription": "Adicione sua conta do Outlook, Gmail ou IMAP para começar com o Wino Mail.",
"WelcomeWindow_ImportFromWinoAccount": "Importar da sua Conta Wino", "WelcomeWindow_ImportFromWinoAccount": "Importar da sua Conta Wino",
"WelcomeWindow_ImportFromJsonFile": "Importar de um arquivo JSON",
"WelcomeWindow_ImportInProgress": "Importando suas preferências e contas sincronizadas...", "WelcomeWindow_ImportInProgress": "Importando suas preferências e contas sincronizadas...",
"WelcomeWindow_ImportNoAccountsFound": "Nenhuma conta sincronizada foi encontrada na sua Conta Wino. Se havia preferências disponíveis, elas foram restauradas. Use Começar para adicionar uma conta manualmente.", "WelcomeWindow_ImportNoAccountsFound": "Nenhuma conta sincronizada foi encontrada na sua Conta Wino. Se havia preferências disponíveis, elas foram restauradas. Use Começar para adicionar uma conta manualmente.",
"WelcomeWindow_ImportDuplicateAccountsSkipped": "{0} contas sincronizadas já estão disponíveis neste dispositivo. Use Começar para adicionar outra conta manualmente, se necessário.", "WelcomeWindow_ImportDuplicateAccountsSkipped": "{0} contas sincronizadas já estão disponíveis neste dispositivo. Use Começar para adicionar outra conta manualmente, se necessário.",
@@ -1418,6 +1439,12 @@
"WinoAccount_Management_ExportDialog_AccountsDisclaimer": "Senhas, tokens e outras informações sensíveis não são sincronizados.", "WinoAccount_Management_ExportDialog_AccountsDisclaimer": "Senhas, tokens e outras informações sensíveis não são sincronizados.",
"WinoAccount_Management_ExportDialog_AccountsRelogin": "Contas importadas em outro PC ainda precisarão que você faça login novamente antes que possam ser usadas.", "WinoAccount_Management_ExportDialog_AccountsRelogin": "Contas importadas em outro PC ainda precisarão que você faça login novamente antes que possam ser usadas.",
"WinoAccount_Management_ExportDialog_InProgress": "Exportando seus dados Wino selecionados...", "WinoAccount_Management_ExportDialog_InProgress": "Exportando seus dados Wino selecionados...",
"WinoAccount_Management_LocalDataSectionTitle": "Transferir com um arquivo JSON",
"WinoAccount_Management_LocalDataSectionDescription": "Importar de ou exportar para um arquivo JSON local. Senhas, tokens e outras informações sensíveis não são incluídas.",
"WinoAccount_Management_LocalDataImportAction": "Importar",
"WinoAccount_Management_LocalDataExportAction": "Exportar",
"WinoAccount_Management_LocalDataSaved": "Seus dados do Wino exportados foram salvos em {0}.",
"WinoAccount_Management_LocalDataInvalidFile": "O arquivo JSON selecionado não contém uma exportação válida do Wino.",
"WinoAccount_Management_LoadFailed": "Não foi possível carregar as informações mais recentes da Conta Wino.", "WinoAccount_Management_LoadFailed": "Não foi possível carregar as informações mais recentes da Conta Wino.",
"WinoAccount_Management_ActionFailed": "A solicitação da Conta Wino não pôde ser concluída.", "WinoAccount_Management_ActionFailed": "A solicitação da Conta Wino não pôde ser concluída.",
"WinoAccount_SettingsSection_Title": "Conta Wino", "WinoAccount_SettingsSection_Title": "Conta Wino",
@@ -1514,8 +1541,22 @@
"WelcomeWizard_Step3Title": "Concluir Configuração", "WelcomeWizard_Step3Title": "Concluir Configuração",
"ProviderSelection_Title": "Escolha seu provedor de e-mail", "ProviderSelection_Title": "Escolha seu provedor de e-mail",
"ProviderSelection_Subtitle": "Selecione um provedor abaixo para adicionar sua conta de e-mail ao Wino Mail.", "ProviderSelection_Subtitle": "Selecione um provedor abaixo para adicionar sua conta de e-mail ao Wino Mail.",
"ProviderSelection_StepProgress": "Etapa {0} de 3",
"ProviderSelection_IdentityTitle": "Identidade da conta",
"ProviderSelection_IdentityDescription": "Escolha como esta conta aparece dentro do Wino.",
"ProviderSelection_ProviderSectionTitle": "Provedor",
"ProviderSelection_ProviderSectionDescription": "Selecione o serviço que deseja conectar.",
"ProviderSelection_CapabilitySectionTitle": "Usar esta conta para",
"ProviderSelection_CapabilitySectionDescription": "Escolha se deseja E-mail, Calendário ou ambos.",
"ProviderSelection_CapabilityProviderDescription_OAuth": "Na próxima etapa, o login seguro conectará sua conta. Se você ativar o calendário, o Wino também conectará automaticamente o Outlook Calendar ou Google Calendar.",
"ProviderSelection_CapabilityProviderDescription_SpecialImap": "Na próxima etapa, você inserirá as credenciais do provedor. O e-mail usa IMAP/SMTP, e o calendário pode usar CalDAV ou permanecer local neste dispositivo.",
"ProviderSelection_CapabilityProviderDescription_CustomServer": "Na próxima etapa, você informará os detalhes do servidor. O e-mail usa IMAP/SMTP, e o calendário pode usar CalDAV ou permanecer local neste dispositivo.",
"ProviderSelection_AccountNameHeader": "Nome da Conta", "ProviderSelection_AccountNameHeader": "Nome da Conta",
"ProviderSelection_AccountNamePlaceholder": "ex.: Pessoal, Trabalho", "ProviderSelection_AccountNamePlaceholder": "ex.: Pessoal, Trabalho",
"ProviderSelection_UseForMail": "E-mail",
"ProviderSelection_UseForCalendar": "Calendário",
"ProviderSelection_CapabilityValidationMessage": "Escolha pelo menos uma capacidade antes de continuar.",
"ProviderSelection_CalendarOnlyServerHint": "Se você continuar apenas com o calendário, a próxima página não exigirá um endereço de e-mail.",
"ProviderSelection_DisplayNameHeader": "Nome para exibição", "ProviderSelection_DisplayNameHeader": "Nome para exibição",
"ProviderSelection_DisplayNamePlaceholder": "ex.: João da Silva", "ProviderSelection_DisplayNamePlaceholder": "ex.: João da Silva",
"ProviderSelection_EmailHeader": "Endereço de E-mail", "ProviderSelection_EmailHeader": "Endereço de E-mail",
@@ -47,6 +47,11 @@
"AccountDetailsPage_CalendarListDescription": "Selectați un calendar pentru a-i configura setările.", "AccountDetailsPage_CalendarListDescription": "Selectați un calendar pentru a-i configura setările.",
"AccountDetailsPage_InitialSynchronization_Title": "Sincronizare inițială", "AccountDetailsPage_InitialSynchronization_Title": "Sincronizare inițială",
"AccountDetailsPage_InitialSynchronization_Description": "Wino și-a sincronizat e-mailurile până la {0} înapoi.", "AccountDetailsPage_InitialSynchronization_Description": "Wino și-a sincronizat e-mailurile până la {0} înapoi.",
"AccountDetailsPage_CapabilityTitle": "Funcționalități conectate",
"AccountDetailsPage_CapabilityDescription": "Alege dacă acest cont este utilizat pentru mail, calendar sau ambele. Activarea unei noi funcționalități poate solicita autentificarea din nou.",
"AccountCapability_MailOnly": "Doar Mail",
"AccountCapability_CalendarOnly": "Doar Calendar",
"AccountCapability_MailAndCalendar": "Mail și Calendar",
"AddHyperlink": "Adăugare", "AddHyperlink": "Adăugare",
"AppCloseBackgroundSynchronizationWarningTitle": "Sincronizare în Fundal", "AppCloseBackgroundSynchronizationWarningTitle": "Sincronizare în Fundal",
"AppCloseStartupLaunchDisabledWarningMessageFirstLine": "Aplicația nu a fost setată să pornească la pornirea Windows.", "AppCloseStartupLaunchDisabledWarningMessageFirstLine": "Aplicația nu a fost setată să pornească la pornirea Windows.",
@@ -76,6 +81,7 @@
"Buttons_ApplyTheme": "Aplicați Tema", "Buttons_ApplyTheme": "Aplicați Tema",
"Buttons_PopOut": "Deschide într-o fereastră separată", "Buttons_PopOut": "Deschide într-o fereastră separată",
"Buttons_Browse": "Răsfoire", "Buttons_Browse": "Răsfoire",
"Buttons_Back": "Înapoi",
"Buttons_Cancel": "Anulare", "Buttons_Cancel": "Anulare",
"Buttons_Close": "Închidere", "Buttons_Close": "Închidere",
"Buttons_Copy": "Copiere", "Buttons_Copy": "Copiere",
@@ -299,6 +305,8 @@
"DialogMessage_DeleteRecurringSeriesTitle": "Șterge seria repetitivă", "DialogMessage_DeleteRecurringSeriesTitle": "Șterge seria repetitivă",
"DialogMessage_DiscardDraftConfirmationMessage": "Această schiță va fi eliminat. Doriți să continuați?", "DialogMessage_DiscardDraftConfirmationMessage": "Această schiță va fi eliminat. Doriți să continuați?",
"DialogMessage_DiscardDraftConfirmationTitle": "Eliminare Schiță", "DialogMessage_DiscardDraftConfirmationTitle": "Eliminare Schiță",
"DialogMessage_CloseDraftWindowConfirmationMessage": "O schiță este încă deschisă. Salvați-o înainte să închideți fereastra?",
"DialogMessage_CloseDraftWindowConfirmationTitle": "Închide fereastra",
"DialogMessage_EmptySubjectConfirmation": "Subiect Lipsă", "DialogMessage_EmptySubjectConfirmation": "Subiect Lipsă",
"DialogMessage_EmptySubjectConfirmationMessage": "Mesajul nu are subiect. Doriți să continuați?", "DialogMessage_EmptySubjectConfirmationMessage": "Mesajul nu are subiect. Doriți să continuați?",
"DialogMessage_EnableStartupLaunchDeniedMessage": "Puteți activa lansarea la pornire din Setări -> Preferințe Aplicație.", "DialogMessage_EnableStartupLaunchDeniedMessage": "Puteți activa lansarea la pornire din Setări -> Preferințe Aplicație.",
@@ -681,6 +689,10 @@
"NoMailSelected": "Niciun mesaj selectat", "NoMailSelected": "Niciun mesaj selectat",
"NoMessageCrieteria": "Niciun mesaj nu corespunde criteriilor dvs. de căutare", "NoMessageCrieteria": "Niciun mesaj nu corespunde criteriilor dvs. de căutare",
"NoMessageEmptyFolder": "Acest folder este gol", "NoMessageEmptyFolder": "Acest folder este gol",
"MailEmptyState_Title": "Nu există conturi cu funcționalitate de mail activată.",
"MailEmptyState_Message": "Aveți conturi conectate pentru calendar, dar niciunul dintre ele nu are funcționalitatea de mail activată. Adăugați un cont de mail sau actualizați un cont existent pentru a utiliza mail.",
"MailEmptyState_AddAccount": "Adaugă cont",
"MailEmptyState_ManageAccounts": "Gestionați conturi",
"Notifications_MultipleNotificationsMessage": "Aveți {0} mesaje noi.", "Notifications_MultipleNotificationsMessage": "Aveți {0} mesaje noi.",
"Notifications_MultipleNotificationsTitle": "Mesaj E-Mail Nou", "Notifications_MultipleNotificationsTitle": "Mesaj E-Mail Nou",
"Notifications_WinoUpdatedMessage": "Verificați versiunea nouă {0}", "Notifications_WinoUpdatedMessage": "Verificați versiunea nouă {0}",
@@ -824,6 +836,8 @@
"SettingsDeleteAccount_Title": "Ștergeți acest cont", "SettingsDeleteAccount_Title": "Ștergeți acest cont",
"SettingsDeleteProtection_Description": "Should Wino ask you for confirmation every time you try to permanently delete a mail using Shift + Del keys?", "SettingsDeleteProtection_Description": "Should Wino ask you for confirmation every time you try to permanently delete a mail using Shift + Del keys?",
"SettingsDeleteProtection_Title": "Protecție Ștergere Permanentă", "SettingsDeleteProtection_Title": "Protecție Ștergere Permanentă",
"SettingsEmptyJunkFolderCommand_Description": "Afișează comanda de golire a folderelor Junk/Spam. Această acțiune nu va solicita confirmare și va șterge imediat toate mesajele din folderul de spam.",
"SettingsEmptyJunkFolderCommand_Title": "Afișează comanda pentru golirea folderului de spam.",
"SettingsDiagnostics_Description": "Pentru dezvoltatori", "SettingsDiagnostics_Description": "Pentru dezvoltatori",
"SettingsDiagnostics_DiagnosticId_Description": "Partajați acest ID cu dezvoltatorii atunci când le cereți ajutor pentru problemele pe care le întâmpinați în Wino Mail.", "SettingsDiagnostics_DiagnosticId_Description": "Partajați acest ID cu dezvoltatorii atunci când le cereți ajutor pentru problemele pe care le întâmpinați în Wino Mail.",
"SettingsDiagnostics_DiagnosticId_Title": "ID de Diagnosticare", "SettingsDiagnostics_DiagnosticId_Title": "ID de Diagnosticare",
@@ -1074,6 +1088,12 @@
"SettingsTaskbarBadge_Title": "Insignă Bară de activități", "SettingsTaskbarBadge_Title": "Insignă Bară de activități",
"SettingsThreads_Description": "Organizați mesajele în fire de conversație.", "SettingsThreads_Description": "Organizați mesajele în fire de conversație.",
"SettingsThreads_Title": "Aranjare mesaje în conversație", "SettingsThreads_Title": "Aranjare mesaje în conversație",
"SettingsThreads_Enabled_Description": "Grupați mesajele legate într-o singură conversație.",
"SettingsThreads_Enabled_Title": "Activează firul de conversații",
"SettingsThreadOrder_Description": "Alegeți cum sunt ordonate elementele într-un fir de conversație.",
"SettingsThreadOrder_Title": "Sortarea elementelor firului de conversație",
"SettingsThreadOrder_LastItemFirst": "Ultimul element, primul.",
"SettingsThreadOrder_FirstItemFirst": "Primul element, primul.",
"SettingsUnlinkAccounts_Description": "Eliminați legătura dintre conturi. Acest lucru nu va șterge conturile dvs.", "SettingsUnlinkAccounts_Description": "Eliminați legătura dintre conturi. Acest lucru nu va șterge conturile dvs.",
"SettingsUnlinkAccounts_Title": "Deasociere Conturi", "SettingsUnlinkAccounts_Title": "Deasociere Conturi",
"SettingsMailRendering_ActionLabels_Title": "Action labels", "SettingsMailRendering_ActionLabels_Title": "Action labels",
@@ -1339,6 +1359,7 @@
"WelcomeWindow_GetStartedButton": "Începe", "WelcomeWindow_GetStartedButton": "Începe",
"WelcomeWindow_GetStartedDescription": "Adăugați contul dvs. Outlook, Gmail sau IMAP pentru a începe cu Wino Mail.", "WelcomeWindow_GetStartedDescription": "Adăugați contul dvs. Outlook, Gmail sau IMAP pentru a începe cu Wino Mail.",
"WelcomeWindow_ImportFromWinoAccount": "Importă din contul tău Wino", "WelcomeWindow_ImportFromWinoAccount": "Importă din contul tău Wino",
"WelcomeWindow_ImportFromJsonFile": "Importă dintr-un fișier JSON",
"WelcomeWindow_ImportInProgress": "Se importă preferințele și conturile sincronizate...", "WelcomeWindow_ImportInProgress": "Se importă preferințele și conturile sincronizate...",
"WelcomeWindow_ImportNoAccountsFound": "Nu au fost găsite conturi sincronizate în contul tău Wino. Dacă preferințele erau disponibile, acestea au fost restaurate. Folosește Începe pentru a adăuga un cont manual.", "WelcomeWindow_ImportNoAccountsFound": "Nu au fost găsite conturi sincronizate în contul tău Wino. Dacă preferințele erau disponibile, acestea au fost restaurate. Folosește Începe pentru a adăuga un cont manual.",
"WelcomeWindow_ImportDuplicateAccountsSkipped": "{0} conturi sincronizate sunt deja disponibile pe acest dispozitiv. Folosește Începe pentru a adăuga manual un alt cont, dacă este necesar.", "WelcomeWindow_ImportDuplicateAccountsSkipped": "{0} conturi sincronizate sunt deja disponibile pe acest dispozitiv. Folosește Începe pentru a adăuga manual un alt cont, dacă este necesar.",
@@ -1418,6 +1439,12 @@
"WinoAccount_Management_ExportDialog_AccountsDisclaimer": "/** placeholder **/", "WinoAccount_Management_ExportDialog_AccountsDisclaimer": "/** placeholder **/",
"WinoAccount_Management_ExportDialog_AccountsRelogin": "/** placeholder **/", "WinoAccount_Management_ExportDialog_AccountsRelogin": "/** placeholder **/",
"WinoAccount_Management_ExportDialog_InProgress": "/** placeholder **/", "WinoAccount_Management_ExportDialog_InProgress": "/** placeholder **/",
"WinoAccount_Management_LocalDataSectionTitle": "Transfer cu un fișier JSON",
"WinoAccount_Management_LocalDataSectionDescription": "Importați din sau exportați într-un fișier JSON local. Parolele, token-urile și alte informații sensibile nu sunt incluse.",
"WinoAccount_Management_LocalDataImportAction": "Importă",
"WinoAccount_Management_LocalDataExportAction": "Exportă",
"WinoAccount_Management_LocalDataSaved": "Datele exportate ale Wino au fost salvate în {0}.",
"WinoAccount_Management_LocalDataInvalidFile": "Fișierul JSON selectat nu conține un export Wino valid.",
"WinoAccount_Management_LoadFailed": "/** placeholder **/", "WinoAccount_Management_LoadFailed": "/** placeholder **/",
"WinoAccount_Management_ActionFailed": "/** placeholder **/", "WinoAccount_Management_ActionFailed": "/** placeholder **/",
"WinoAccount_SettingsSection_Title": "/** placeholder **/", "WinoAccount_SettingsSection_Title": "/** placeholder **/",
@@ -1514,8 +1541,22 @@
"WelcomeWizard_Step3Title": "Finalizați configurarea", "WelcomeWizard_Step3Title": "Finalizați configurarea",
"ProviderSelection_Title": "Alegeți furnizorul de e-mail", "ProviderSelection_Title": "Alegeți furnizorul de e-mail",
"ProviderSelection_Subtitle": "Selectați un furnizor mai jos pentru a adăuga contul dvs. de e-mail în Wino Mail.", "ProviderSelection_Subtitle": "Selectați un furnizor mai jos pentru a adăuga contul dvs. de e-mail în Wino Mail.",
"ProviderSelection_StepProgress": "Pasul {0} din 3",
"ProviderSelection_IdentityTitle": "Identitatea contului",
"ProviderSelection_IdentityDescription": "Alegeți cum va apărea acest cont în Wino.",
"ProviderSelection_ProviderSectionTitle": "Furnizor",
"ProviderSelection_ProviderSectionDescription": "Selectați serviciul pe care doriți să îl conectați.",
"ProviderSelection_CapabilitySectionTitle": "Folosirea acestui cont pentru",
"ProviderSelection_CapabilitySectionDescription": "Alegeți dacă doriți mail, calendar sau ambele.",
"ProviderSelection_CapabilityProviderDescription_OAuth": "În pasul următor, autentificarea securizată vă va conecta contul. Dacă activați calendarul, Wino se va conecta automat și la Outlook Calendar sau Google Calendar.",
"ProviderSelection_CapabilityProviderDescription_SpecialImap": "În pasul următor veți introduce acreditările furnizorului. Mail utilizează IMAP/SMTP, iar calendarul poate folosi CalDAV sau poate rămâne local pe acest dispozitiv.",
"ProviderSelection_CapabilityProviderDescription_CustomServer": "În pasul următor veți introduce detaliile serverului. Mail utilizează IMAP/SMTP, iar calendarul poate folosi CalDAV sau poate rămâne local pe acest dispozitiv.",
"ProviderSelection_AccountNameHeader": "Nume cont", "ProviderSelection_AccountNameHeader": "Nume cont",
"ProviderSelection_AccountNamePlaceholder": "ex. Personal, Birou", "ProviderSelection_AccountNamePlaceholder": "ex. Personal, Birou",
"ProviderSelection_UseForMail": "Poștă",
"ProviderSelection_UseForCalendar": "Calendar",
"ProviderSelection_CapabilityValidationMessage": "Alegeți cel puțin o capabilitate înainte de a continua.",
"ProviderSelection_CalendarOnlyServerHint": "Dacă continuați doar cu calendarul, pagina următoare nu va solicita o adresă de e-mail.",
"ProviderSelection_DisplayNameHeader": "Nume afișat", "ProviderSelection_DisplayNameHeader": "Nume afișat",
"ProviderSelection_DisplayNamePlaceholder": "ex. John Doe", "ProviderSelection_DisplayNamePlaceholder": "ex. John Doe",
"ProviderSelection_EmailHeader": "Adresă de e-mail", "ProviderSelection_EmailHeader": "Adresă de e-mail",
@@ -47,6 +47,11 @@
"AccountDetailsPage_CalendarListDescription": "Выберите календарь, чтобы настроить его параметры.", "AccountDetailsPage_CalendarListDescription": "Выберите календарь, чтобы настроить его параметры.",
"AccountDetailsPage_InitialSynchronization_Title": "Начальная синхронизация", "AccountDetailsPage_InitialSynchronization_Title": "Начальная синхронизация",
"AccountDetailsPage_InitialSynchronization_Description": "Wino синхронизировал вашу почту до {0} назад.", "AccountDetailsPage_InitialSynchronization_Description": "Wino синхронизировал вашу почту до {0} назад.",
"AccountDetailsPage_CapabilityTitle": "Подключенные функции",
"AccountDetailsPage_CapabilityDescription": "Выберите, будет ли эта учетная запись использоваться для почты, календаря или обоих. Включение новой функции может потребовать повторного входа в систему.",
"AccountCapability_MailOnly": "Только почта",
"AccountCapability_CalendarOnly": "Только календарь",
"AccountCapability_MailAndCalendar": "Почта и календарь",
"AddHyperlink": "Добавить", "AddHyperlink": "Добавить",
"AppCloseBackgroundSynchronizationWarningTitle": "Background Synchronization", "AppCloseBackgroundSynchronizationWarningTitle": "Background Synchronization",
"AppCloseStartupLaunchDisabledWarningMessageFirstLine": "Application has not been set to launch on Windows startup.", "AppCloseStartupLaunchDisabledWarningMessageFirstLine": "Application has not been set to launch on Windows startup.",
@@ -76,6 +81,7 @@
"Buttons_ApplyTheme": "Применить тему", "Buttons_ApplyTheme": "Применить тему",
"Buttons_PopOut": "Открыть в отдельном окне", "Buttons_PopOut": "Открыть в отдельном окне",
"Buttons_Browse": "Обзор", "Buttons_Browse": "Обзор",
"Buttons_Back": "Назад",
"Buttons_Cancel": "Отмена", "Buttons_Cancel": "Отмена",
"Buttons_Close": "Закрыть", "Buttons_Close": "Закрыть",
"Buttons_Copy": "Копировать", "Buttons_Copy": "Копировать",
@@ -299,6 +305,8 @@
"DialogMessage_DeleteRecurringSeriesTitle": "Удалить повторяющуюся серию", "DialogMessage_DeleteRecurringSeriesTitle": "Удалить повторяющуюся серию",
"DialogMessage_DiscardDraftConfirmationMessage": "Этот черновик будет удален. Вы хотите продолжить?", "DialogMessage_DiscardDraftConfirmationMessage": "Этот черновик будет удален. Вы хотите продолжить?",
"DialogMessage_DiscardDraftConfirmationTitle": "Удалить черновик", "DialogMessage_DiscardDraftConfirmationTitle": "Удалить черновик",
"DialogMessage_CloseDraftWindowConfirmationMessage": "Черновик всё ещё открыт. Сохранить его перед закрытием окна?",
"DialogMessage_CloseDraftWindowConfirmationTitle": "Закрыть окно",
"DialogMessage_EmptySubjectConfirmation": "Missing Subject", "DialogMessage_EmptySubjectConfirmation": "Missing Subject",
"DialogMessage_EmptySubjectConfirmationMessage": "Сообщение не имеет темы. Вы хотите продолжить?", "DialogMessage_EmptySubjectConfirmationMessage": "Сообщение не имеет темы. Вы хотите продолжить?",
"DialogMessage_EnableStartupLaunchDeniedMessage": "You can enable startup launch from Settings -> App Preferences.", "DialogMessage_EnableStartupLaunchDeniedMessage": "You can enable startup launch from Settings -> App Preferences.",
@@ -681,6 +689,10 @@
"NoMailSelected": "Не выбрано сообщение", "NoMailSelected": "Не выбрано сообщение",
"NoMessageCrieteria": "Нет сообщений, соответствующих критериям поиска", "NoMessageCrieteria": "Нет сообщений, соответствующих критериям поиска",
"NoMessageEmptyFolder": "Эта папка пуста", "NoMessageEmptyFolder": "Эта папка пуста",
"MailEmptyState_Title": "Нет учетных записей, поддерживающих почту",
"MailEmptyState_Message": "У вас подключены учетные записи для календаря, но ни одна из них не поддерживает почту. Добавьте учетную запись почты или обновите существующую учетную запись, чтобы использовать почту.",
"MailEmptyState_AddAccount": "Добавить учетную запись",
"MailEmptyState_ManageAccounts": "Управление учетными записями",
"Notifications_MultipleNotificationsMessage": "You have {0} new messages.", "Notifications_MultipleNotificationsMessage": "You have {0} new messages.",
"Notifications_MultipleNotificationsTitle": "New Mail", "Notifications_MultipleNotificationsTitle": "New Mail",
"Notifications_WinoUpdatedMessage": "Ознакомьтесь с новой версией {0}", "Notifications_WinoUpdatedMessage": "Ознакомьтесь с новой версией {0}",
@@ -824,6 +836,8 @@
"SettingsDeleteAccount_Title": "Удалить эту учетную запись", "SettingsDeleteAccount_Title": "Удалить эту учетную запись",
"SettingsDeleteProtection_Description": "Should Wino ask you for confirmation every time you try to permanently delete a mail using Shift + Del keys?", "SettingsDeleteProtection_Description": "Should Wino ask you for confirmation every time you try to permanently delete a mail using Shift + Del keys?",
"SettingsDeleteProtection_Title": "Защита от окончательного удаления", "SettingsDeleteProtection_Title": "Защита от окончательного удаления",
"SettingsEmptyJunkFolderCommand_Description": "Показать команду очистки пустой папки в папках Спам. Это действие не будет запрашивать подтверждение и сразу удалит все письма в папке спама.",
"SettingsEmptyJunkFolderCommand_Title": "Показать команду очистки пустой папки в папках Спам",
"SettingsDiagnostics_Description": "Для разработчиков", "SettingsDiagnostics_Description": "Для разработчиков",
"SettingsDiagnostics_DiagnosticId_Description": "Share this ID with the developers when asked to get help for the issues you experience in Wino Mail.", "SettingsDiagnostics_DiagnosticId_Description": "Share this ID with the developers when asked to get help for the issues you experience in Wino Mail.",
"SettingsDiagnostics_DiagnosticId_Title": "Diagnostic ID", "SettingsDiagnostics_DiagnosticId_Title": "Diagnostic ID",
@@ -1074,6 +1088,12 @@
"SettingsTaskbarBadge_Title": "Taskbar Badge", "SettingsTaskbarBadge_Title": "Taskbar Badge",
"SettingsThreads_Description": "Организуйте сообщения в беседы.", "SettingsThreads_Description": "Организуйте сообщения в беседы.",
"SettingsThreads_Title": "Беседы", "SettingsThreads_Title": "Беседы",
"SettingsThreads_Enabled_Description": "Сгруппировать связанные сообщения в одну переписку.",
"SettingsThreads_Enabled_Title": "Включить группировку переписки",
"SettingsThreadOrder_Description": "Выберите порядок сортировки элементов внутри переписки.",
"SettingsThreadOrder_Title": "Сортировка элементов переписки",
"SettingsThreadOrder_LastItemFirst": "Последний элемент первым",
"SettingsThreadOrder_FirstItemFirst": "Первый элемент первым",
"SettingsUnlinkAccounts_Description": "Remove the link between accounts. his will not delete your accounts.", "SettingsUnlinkAccounts_Description": "Remove the link between accounts. his will not delete your accounts.",
"SettingsUnlinkAccounts_Title": "Отвязать учетные записи", "SettingsUnlinkAccounts_Title": "Отвязать учетные записи",
"SettingsMailRendering_ActionLabels_Title": "Action labels", "SettingsMailRendering_ActionLabels_Title": "Action labels",
@@ -1339,6 +1359,7 @@
"WelcomeWindow_GetStartedButton": "Начать, добавив учетную запись", "WelcomeWindow_GetStartedButton": "Начать, добавив учетную запись",
"WelcomeWindow_GetStartedDescription": "Добавьте учетную запись Outlook, Gmail или IMAP, чтобы начать работу с Wino Mail.", "WelcomeWindow_GetStartedDescription": "Добавьте учетную запись Outlook, Gmail или IMAP, чтобы начать работу с Wino Mail.",
"WelcomeWindow_ImportFromWinoAccount": "Импорт из вашей учетной записи Wino", "WelcomeWindow_ImportFromWinoAccount": "Импорт из вашей учетной записи Wino",
"WelcomeWindow_ImportFromJsonFile": "Импорт из файла JSON",
"WelcomeWindow_ImportInProgress": "Импорт синхронизированных настроек и учетных записей...", "WelcomeWindow_ImportInProgress": "Импорт синхронизированных настроек и учетных записей...",
"WelcomeWindow_ImportNoAccountsFound": "В вашей учетной записи Wino не найдено синхронизированных учетных записей. Если настройки были доступны, они были восстановлены. Используйте Начать, чтобы добавить учетную запись вручную.", "WelcomeWindow_ImportNoAccountsFound": "В вашей учетной записи Wino не найдено синхронизированных учетных записей. Если настройки были доступны, они были восстановлены. Используйте Начать, чтобы добавить учетную запись вручную.",
"WelcomeWindow_ImportDuplicateAccountsSkipped": "{0} синхронизированных учетных записей уже доступны на этом устройстве. При необходимости используйте Начать, чтобы вручную добавить еще одну учетную запись.", "WelcomeWindow_ImportDuplicateAccountsSkipped": "{0} синхронизированных учетных записей уже доступны на этом устройстве. При необходимости используйте Начать, чтобы вручную добавить еще одну учетную запись.",
@@ -1418,6 +1439,12 @@
"WinoAccount_Management_ExportDialog_AccountsDisclaimer": "Пароли, токены и другие конфиденциальные данные не синхронизируются.", "WinoAccount_Management_ExportDialog_AccountsDisclaimer": "Пароли, токены и другие конфиденциальные данные не синхронизируются.",
"WinoAccount_Management_ExportDialog_AccountsRelogin": "Импортированные на другом ПК учетные записи по-прежнему потребуют повторного входа в систему перед использованием.", "WinoAccount_Management_ExportDialog_AccountsRelogin": "Импортированные на другом ПК учетные записи по-прежнему потребуют повторного входа в систему перед использованием.",
"WinoAccount_Management_ExportDialog_InProgress": "Выполняется экспорт выбранных данных Wino...", "WinoAccount_Management_ExportDialog_InProgress": "Выполняется экспорт выбранных данных Wino...",
"WinoAccount_Management_LocalDataSectionTitle": "Перенос с помощью файла JSON",
"WinoAccount_Management_LocalDataSectionDescription": "Импортируйте или экспортируйте локальный файл JSON. Пароли, токены и другая конфиденциальная информация не включаются.",
"WinoAccount_Management_LocalDataImportAction": "Импорт",
"WinoAccount_Management_LocalDataExportAction": "Экспорт",
"WinoAccount_Management_LocalDataSaved": "Сохранены экспортированные данные Wino в {0}.",
"WinoAccount_Management_LocalDataInvalidFile": "Выбранный файл JSON не содержит допустимого экспорта Wino.",
"WinoAccount_Management_LoadFailed": "Не удалось загрузить последнюю информацию об учетной записи Wino.", "WinoAccount_Management_LoadFailed": "Не удалось загрузить последнюю информацию об учетной записи Wino.",
"WinoAccount_Management_ActionFailed": "Запрос к учетной записи Wino не удалось выполнить.", "WinoAccount_Management_ActionFailed": "Запрос к учетной записи Wino не удалось выполнить.",
"WinoAccount_SettingsSection_Title": "Учетная запись Wino", "WinoAccount_SettingsSection_Title": "Учетная запись Wino",
@@ -1514,8 +1541,22 @@
"WelcomeWizard_Step3Title": "Завершение настройки", "WelcomeWizard_Step3Title": "Завершение настройки",
"ProviderSelection_Title": "Выберите поставщика электронной почты", "ProviderSelection_Title": "Выберите поставщика электронной почты",
"ProviderSelection_Subtitle": "Выберите ниже поставщика, чтобы добавить вашу учетную запись электронной почты в Wino Mail.", "ProviderSelection_Subtitle": "Выберите ниже поставщика, чтобы добавить вашу учетную запись электронной почты в Wino Mail.",
"ProviderSelection_StepProgress": "Шаг {0} из 3",
"ProviderSelection_IdentityTitle": "Идентификатор учетной записи",
"ProviderSelection_IdentityDescription": "Выберите, как эта учетная запись будет отображаться в Wino.",
"ProviderSelection_ProviderSectionTitle": "Провайдер",
"ProviderSelection_ProviderSectionDescription": "Выберите сервис, который вы хотите подключить.",
"ProviderSelection_CapabilitySectionTitle": "Использовать эту учетную запись для",
"ProviderSelection_CapabilitySectionDescription": "Выберите, хотите ли вы использовать почту, календарь или оба.",
"ProviderSelection_CapabilityProviderDescription_OAuth": "На следующем шаге безопасный вход подключит вашу учетную запись. Если вы включите календарь, Wino автоматически подключит календарь Outlook или Google Календарь.",
"ProviderSelection_CapabilityProviderDescription_SpecialImap": "На следующем шаге вы введёте учётные данные вашего провайдера. Почта использует IMAP/SMTP, а календарь может использовать CalDAV или оставаться локальным на этом устройстве.",
"ProviderSelection_CapabilityProviderDescription_CustomServer": "На следующем шаге вы введёте данные сервера. Почта использует IMAP/SMTP, а календарь может использовать CalDAV или оставаться локальным на этом устройстве.",
"ProviderSelection_AccountNameHeader": "Имя учетной записи", "ProviderSelection_AccountNameHeader": "Имя учетной записи",
"ProviderSelection_AccountNamePlaceholder": "например, Личное, Рабочее", "ProviderSelection_AccountNamePlaceholder": "например, Личное, Рабочее",
"ProviderSelection_UseForMail": "Почта",
"ProviderSelection_UseForCalendar": "Календарь",
"ProviderSelection_CapabilityValidationMessage": "Выберите как минимум одну возможность перед продолжением.",
"ProviderSelection_CalendarOnlyServerHint": "Если вы продолжите только с календарём, на следующей странице адрес электронной почты не потребуется.",
"ProviderSelection_DisplayNameHeader": "Отображаемое имя", "ProviderSelection_DisplayNameHeader": "Отображаемое имя",
"ProviderSelection_DisplayNamePlaceholder": "например, Иван Иванов", "ProviderSelection_DisplayNamePlaceholder": "например, Иван Иванов",
"ProviderSelection_EmailHeader": "Адрес электронной почты", "ProviderSelection_EmailHeader": "Адрес электронной почты",
@@ -47,6 +47,11 @@
"AccountDetailsPage_CalendarListDescription": "Vyberte kalendár na konfiguráciu jeho nastavení.", "AccountDetailsPage_CalendarListDescription": "Vyberte kalendár na konfiguráciu jeho nastavení.",
"AccountDetailsPage_InitialSynchronization_Title": "Počiatočná synchronizácia", "AccountDetailsPage_InitialSynchronization_Title": "Počiatočná synchronizácia",
"AccountDetailsPage_InitialSynchronization_Description": "Wino synchronizoval vašu poštu až do {0} späť.", "AccountDetailsPage_InitialSynchronization_Description": "Wino synchronizoval vašu poštu až do {0} späť.",
"AccountDetailsPage_CapabilityTitle": "Pripojené funkcie",
"AccountDetailsPage_CapabilityDescription": "Vyberte, či sa tento účet používa na poštu, kalendár alebo oboje. Aktivácia novej funkcie môže vyžadovať opätovné prihlásenie.",
"AccountCapability_MailOnly": "Iba pošta",
"AccountCapability_CalendarOnly": "Iba kalendár",
"AccountCapability_MailAndCalendar": "Pošta a kalendár",
"AddHyperlink": "Pridať", "AddHyperlink": "Pridať",
"AppCloseBackgroundSynchronizationWarningTitle": "Synchronizácia na pozadí", "AppCloseBackgroundSynchronizationWarningTitle": "Synchronizácia na pozadí",
"AppCloseStartupLaunchDisabledWarningMessageFirstLine": "Aplikácia sa nebude spúšťať pri spustení systému Windows.", "AppCloseStartupLaunchDisabledWarningMessageFirstLine": "Aplikácia sa nebude spúšťať pri spustení systému Windows.",
@@ -76,6 +81,7 @@
"Buttons_ApplyTheme": "Použiť motív", "Buttons_ApplyTheme": "Použiť motív",
"Buttons_PopOut": "Otvoriť v novom okne", "Buttons_PopOut": "Otvoriť v novom okne",
"Buttons_Browse": "Prehľadávať", "Buttons_Browse": "Prehľadávať",
"Buttons_Back": "Späť",
"Buttons_Cancel": "Zrušiť", "Buttons_Cancel": "Zrušiť",
"Buttons_Close": "Zavrieť", "Buttons_Close": "Zavrieť",
"Buttons_Copy": "Kopírovať", "Buttons_Copy": "Kopírovať",
@@ -299,6 +305,8 @@
"DialogMessage_DeleteRecurringSeriesTitle": "Odstrániť opakovanú sériu", "DialogMessage_DeleteRecurringSeriesTitle": "Odstrániť opakovanú sériu",
"DialogMessage_DiscardDraftConfirmationMessage": "Tento koncept sa zahodí. Chcete pokračovať?", "DialogMessage_DiscardDraftConfirmationMessage": "Tento koncept sa zahodí. Chcete pokračovať?",
"DialogMessage_DiscardDraftConfirmationTitle": "Zrušiť koncept", "DialogMessage_DiscardDraftConfirmationTitle": "Zrušiť koncept",
"DialogMessage_CloseDraftWindowConfirmationMessage": "Návrh je stále otvorený. Uložiť ho pred zatvorením okna?",
"DialogMessage_CloseDraftWindowConfirmationTitle": "Zatvoriť okno",
"DialogMessage_EmptySubjectConfirmation": "Chýbajúci predmet", "DialogMessage_EmptySubjectConfirmation": "Chýbajúci predmet",
"DialogMessage_EmptySubjectConfirmationMessage": "Správa nemá vyplnený predmet. Chcete pokračovať?", "DialogMessage_EmptySubjectConfirmationMessage": "Správa nemá vyplnený predmet. Chcete pokračovať?",
"DialogMessage_EnableStartupLaunchDeniedMessage": "Spúšťanie pri štarte môžete zapnúť v Nastavenia -> Nastavenia aplikácie.", "DialogMessage_EnableStartupLaunchDeniedMessage": "Spúšťanie pri štarte môžete zapnúť v Nastavenia -> Nastavenia aplikácie.",
@@ -681,6 +689,10 @@
"NoMailSelected": "Nie je vybraná žiadna správa", "NoMailSelected": "Nie je vybraná žiadna správa",
"NoMessageCrieteria": "Žiadne správy nezodpovedajú vašim kritériám vyhľadávania", "NoMessageCrieteria": "Žiadne správy nezodpovedajú vašim kritériám vyhľadávania",
"NoMessageEmptyFolder": "Tento priečinok je prázdny", "NoMessageEmptyFolder": "Tento priečinok je prázdny",
"MailEmptyState_Title": "Žiadne účty s poštou nie sú zapojené",
"MailEmptyState_Message": "Máte účty pripojené k kalendáru, ale žiadny z nich nemá povolenú poštu. Pridajte poštový účet alebo aktualizujte existujúci účet, aby používal poštu.",
"MailEmptyState_AddAccount": "Pridať účet",
"MailEmptyState_ManageAccounts": "Spravovať účty",
"Notifications_MultipleNotificationsMessage": "Máte nové správy: {0}.", "Notifications_MultipleNotificationsMessage": "Máte nové správy: {0}.",
"Notifications_MultipleNotificationsTitle": "Nová pošta", "Notifications_MultipleNotificationsTitle": "Nová pošta",
"Notifications_WinoUpdatedMessage": "Pozrite si novú verziu {0}", "Notifications_WinoUpdatedMessage": "Pozrite si novú verziu {0}",
@@ -824,6 +836,8 @@
"SettingsDeleteAccount_Title": "Odstrániť tento účet", "SettingsDeleteAccount_Title": "Odstrániť tento účet",
"SettingsDeleteProtection_Description": "Should Wino ask you for confirmation every time you try to permanently delete a mail using Shift + Del keys?", "SettingsDeleteProtection_Description": "Should Wino ask you for confirmation every time you try to permanently delete a mail using Shift + Del keys?",
"SettingsDeleteProtection_Title": "Ochrana pred trvalým odstránením", "SettingsDeleteProtection_Title": "Ochrana pred trvalým odstránením",
"SettingsEmptyJunkFolderCommand_Description": "Zobraziť príkaz na vyprázdnenie priečinka v priečinkoch Nevyžiadaná pošta / Spam. Táto akcia nepožaduje potvrdenie a okamžite vymaže všetky e-maily zo spamového priečinka.",
"SettingsEmptyJunkFolderCommand_Title": "Zobraziť príkaz na vyprázdnenie spamového priečinka",
"SettingsDiagnostics_Description": "Pre vývojárov", "SettingsDiagnostics_Description": "Pre vývojárov",
"SettingsDiagnostics_DiagnosticId_Description": "Zdieľajte toto ID s vývojármi, keď budete požiadaní o pomoc pri problémoch, ktoré sa vám vyskytnú v aplikácii Wino Mail.", "SettingsDiagnostics_DiagnosticId_Description": "Zdieľajte toto ID s vývojármi, keď budete požiadaní o pomoc pri problémoch, ktoré sa vám vyskytnú v aplikácii Wino Mail.",
"SettingsDiagnostics_DiagnosticId_Title": "Diagnostické ID", "SettingsDiagnostics_DiagnosticId_Title": "Diagnostické ID",
@@ -1074,6 +1088,12 @@
"SettingsTaskbarBadge_Title": "Odznak na paneli úloh", "SettingsTaskbarBadge_Title": "Odznak na paneli úloh",
"SettingsThreads_Description": "Usporiadanie správ do konverzácií.", "SettingsThreads_Description": "Usporiadanie správ do konverzácií.",
"SettingsThreads_Title": "Zobrazenie v režime konverzácie", "SettingsThreads_Title": "Zobrazenie v režime konverzácie",
"SettingsThreads_Enabled_Description": "Zoskupiť súvisiace správy do jednej konverzácie.",
"SettingsThreads_Enabled_Title": "Povoliť vlákna konverzácie",
"SettingsThreadOrder_Description": "Vyberte spôsob zoradenia položiek vo vlákne konverzácie.",
"SettingsThreadOrder_Title": "Zoradenie položiek vlákna",
"SettingsThreadOrder_LastItemFirst": "Posledná položka ako prvá",
"SettingsThreadOrder_FirstItemFirst": "Prvá položka ako prvá",
"SettingsUnlinkAccounts_Description": "Odstránenie prepojenia medzi účtami. Tým sa vaše účty neodstránia.", "SettingsUnlinkAccounts_Description": "Odstránenie prepojenia medzi účtami. Tým sa vaše účty neodstránia.",
"SettingsUnlinkAccounts_Title": "Odpojenie účtov", "SettingsUnlinkAccounts_Title": "Odpojenie účtov",
"SettingsMailRendering_ActionLabels_Title": "Action labels", "SettingsMailRendering_ActionLabels_Title": "Action labels",
@@ -1339,6 +1359,7 @@
"WelcomeWindow_GetStartedButton": "Začať pridaním účtu", "WelcomeWindow_GetStartedButton": "Začať pridaním účtu",
"WelcomeWindow_GetStartedDescription": "Pridajte svoj účet Outlook, Gmail alebo IMAP a začnite používať Wino Mail.", "WelcomeWindow_GetStartedDescription": "Pridajte svoj účet Outlook, Gmail alebo IMAP a začnite používať Wino Mail.",
"WelcomeWindow_ImportFromWinoAccount": "Importovať zo svojho Wino účtu", "WelcomeWindow_ImportFromWinoAccount": "Importovať zo svojho Wino účtu",
"WelcomeWindow_ImportFromJsonFile": "Importovať zo súboru JSON",
"WelcomeWindow_ImportInProgress": "Importujem synchronizované preferencie a účty...", "WelcomeWindow_ImportInProgress": "Importujem synchronizované preferencie a účty...",
"WelcomeWindow_ImportNoAccountsFound": "Nenašli sa žiadne synchronizované účty vo vašom Wino účte. Ak boli k dispozícii preferencie, boli obnovené. Použite možnosť Začať na manuálne pridanie účtu.", "WelcomeWindow_ImportNoAccountsFound": "Nenašli sa žiadne synchronizované účty vo vašom Wino účte. Ak boli k dispozícii preferencie, boli obnovené. Použite možnosť Začať na manuálne pridanie účtu.",
"WelcomeWindow_ImportDuplicateAccountsSkipped": "{0} synchronizovaných účtov je už k dispozícii na tomto zariadení. Ak potrebujete, použite možnosť Začať na ručné pridanie ďalšieho účtu.", "WelcomeWindow_ImportDuplicateAccountsSkipped": "{0} synchronizovaných účtov je už k dispozícii na tomto zariadení. Ak potrebujete, použite možnosť Začať na ručné pridanie ďalšieho účtu.",
@@ -1418,6 +1439,12 @@
"WinoAccount_Management_ExportDialog_AccountsDisclaimer": "Heslá, tokeny a ďalšie citlivé údaje nie sú synchronizované.", "WinoAccount_Management_ExportDialog_AccountsDisclaimer": "Heslá, tokeny a ďalšie citlivé údaje nie sú synchronizované.",
"WinoAccount_Management_ExportDialog_AccountsRelogin": "Importované účty na inom PC budú vyžadovať opätovné prihlásenie pred ich použitím.", "WinoAccount_Management_ExportDialog_AccountsRelogin": "Importované účty na inom PC budú vyžadovať opätovné prihlásenie pred ich použitím.",
"WinoAccount_Management_ExportDialog_InProgress": "Exportujem vybrané údaje Wino.", "WinoAccount_Management_ExportDialog_InProgress": "Exportujem vybrané údaje Wino.",
"WinoAccount_Management_LocalDataSectionTitle": "Prenos pomocou súboru JSON",
"WinoAccount_Management_LocalDataSectionDescription": "Importovať alebo exportovať do lokálneho súboru JSON. Heslá, tokeny a ďalšie citlivé informácie nie sú zahrnuté.",
"WinoAccount_Management_LocalDataImportAction": "Importovať",
"WinoAccount_Management_LocalDataExportAction": "Exportovať",
"WinoAccount_Management_LocalDataSaved": "Uložili ste exportované dáta Wino do {0}.",
"WinoAccount_Management_LocalDataInvalidFile": "Vybraný JSON súbor neobsahuje platný export Wino.",
"WinoAccount_Management_LoadFailed": "Wino nemohol načítať najnovšie informácie o Wino účte.", "WinoAccount_Management_LoadFailed": "Wino nemohol načítať najnovšie informácie o Wino účte.",
"WinoAccount_Management_ActionFailed": "Žiadosť o Wino účet nemohla byť dokončená.", "WinoAccount_Management_ActionFailed": "Žiadosť o Wino účet nemohla byť dokončená.",
"WinoAccount_SettingsSection_Title": "Wino účet", "WinoAccount_SettingsSection_Title": "Wino účet",
@@ -1514,8 +1541,22 @@
"WelcomeWizard_Step3Title": "Dokončiť nastavenie", "WelcomeWizard_Step3Title": "Dokončiť nastavenie",
"ProviderSelection_Title": "Vyberte si svojho poskytovateľa e-mailu", "ProviderSelection_Title": "Vyberte si svojho poskytovateľa e-mailu",
"ProviderSelection_Subtitle": "Vyberte nižšie uvedeného poskytovateľa a pridajte svoj e-mailový účet do Wino Mail.", "ProviderSelection_Subtitle": "Vyberte nižšie uvedeného poskytovateľa a pridajte svoj e-mailový účet do Wino Mail.",
"ProviderSelection_StepProgress": "Krok {0} z 3",
"ProviderSelection_IdentityTitle": "Identita účtu",
"ProviderSelection_IdentityDescription": "Vyberte, ako sa tento účet zobrazí vo Wino.",
"ProviderSelection_ProviderSectionTitle": "Poskytovateľ",
"ProviderSelection_ProviderSectionDescription": "Vyberte službu, ktorú chcete pripojiť.",
"ProviderSelection_CapabilitySectionTitle": "Použiť tento účet pre",
"ProviderSelection_CapabilitySectionDescription": "Vyberte, či chcete poštu, kalendár alebo oboje.",
"ProviderSelection_CapabilityProviderDescription_OAuth": "Na ďalšom kroku zabezpečené prihlásenie pripojí váš účet. Ak povolíte kalendár, Wino tiež automaticky pripojí Kalendár Outlook alebo Kalendár Google.",
"ProviderSelection_CapabilityProviderDescription_SpecialImap": "Na ďalšom kroku zadáte prihlasovacie údaje poskytovateľa. Pošta používa IMAP/SMTP a kalendár môže používať CalDav alebo zostať lokálny na tomto zariadení.",
"ProviderSelection_CapabilityProviderDescription_CustomServer": "Na ďalšom kroku zadáte údaje o serveri. Pošta používa IMAP/SMTP a kalendár môže používať CalDav alebo zostať lokálny na tomto zariadení.",
"ProviderSelection_AccountNameHeader": "Názov účtu", "ProviderSelection_AccountNameHeader": "Názov účtu",
"ProviderSelection_AccountNamePlaceholder": "napr. Osobný, Práca", "ProviderSelection_AccountNamePlaceholder": "napr. Osobný, Práca",
"ProviderSelection_UseForMail": "Pošta",
"ProviderSelection_UseForCalendar": "Kalendár",
"ProviderSelection_CapabilityValidationMessage": "Pred pokračovaním vyberte aspoň jednu možnosť.",
"ProviderSelection_CalendarOnlyServerHint": "Ak budete pokračovať iba s kalendárom, na ďalšej stránke nebude vyžadovaná e-mailová adresa.",
"ProviderSelection_DisplayNameHeader": "Zobrazené meno", "ProviderSelection_DisplayNameHeader": "Zobrazené meno",
"ProviderSelection_DisplayNamePlaceholder": "napr. Ján Novak", "ProviderSelection_DisplayNamePlaceholder": "napr. Ján Novak",
"ProviderSelection_EmailHeader": "E-mailová adresa", "ProviderSelection_EmailHeader": "E-mailová adresa",
@@ -47,6 +47,11 @@
"AccountDetailsPage_CalendarListDescription": "Ayarlarını yapılandırmak için bir takvim seçin.", "AccountDetailsPage_CalendarListDescription": "Ayarlarını yapılandırmak için bir takvim seçin.",
"AccountDetailsPage_InitialSynchronization_Title": "İlk senkronizasyon", "AccountDetailsPage_InitialSynchronization_Title": "İlk senkronizasyon",
"AccountDetailsPage_InitialSynchronization_Description": "Wino, {0} tarihine kadar geriye giderek maillerinizi senkronize etti.", "AccountDetailsPage_InitialSynchronization_Description": "Wino, {0} tarihine kadar geriye giderek maillerinizi senkronize etti.",
"AccountDetailsPage_CapabilityTitle": "Bağlı Özellikler",
"AccountDetailsPage_CapabilityDescription": "Bu hesabın posta, takvim için mi yoksa her ikisi için mi kullanılacağını seçin. Yeni bir özellik etkinleştirildiğinde yeniden oturum açmanız istenebilir.",
"AccountCapability_MailOnly": "Sadece Posta",
"AccountCapability_CalendarOnly": "Sadece Takvim",
"AccountCapability_MailAndCalendar": "Posta + Takvim",
"AddHyperlink": "Ekle", "AddHyperlink": "Ekle",
"AppCloseBackgroundSynchronizationWarningTitle": "Arkaplan Senkronizasyonu", "AppCloseBackgroundSynchronizationWarningTitle": "Arkaplan Senkronizasyonu",
"AppCloseStartupLaunchDisabledWarningMessageFirstLine": "Uygulama Windows açılırken çalıştırılacak şekilde ayarlanmadı.", "AppCloseStartupLaunchDisabledWarningMessageFirstLine": "Uygulama Windows açılırken çalıştırılacak şekilde ayarlanmadı.",
@@ -76,6 +81,7 @@
"Buttons_ApplyTheme": "Temayı Uygula", "Buttons_ApplyTheme": "Temayı Uygula",
"Buttons_PopOut": "Yeni pencerede aç", "Buttons_PopOut": "Yeni pencerede aç",
"Buttons_Browse": "Gözat", "Buttons_Browse": "Gözat",
"Buttons_Back": "Geri",
"Buttons_Cancel": "İptal Et", "Buttons_Cancel": "İptal Et",
"Buttons_Close": "Kapat", "Buttons_Close": "Kapat",
"Buttons_Copy": "Kopyala", "Buttons_Copy": "Kopyala",
@@ -299,6 +305,8 @@
"DialogMessage_DeleteRecurringSeriesTitle": "Tekrarlayan Seriyi Sil", "DialogMessage_DeleteRecurringSeriesTitle": "Tekrarlayan Seriyi Sil",
"DialogMessage_DiscardDraftConfirmationMessage": "Taslak yoksayılacaktır. Devam etmek istiyor musunuz?", "DialogMessage_DiscardDraftConfirmationMessage": "Taslak yoksayılacaktır. Devam etmek istiyor musunuz?",
"DialogMessage_DiscardDraftConfirmationTitle": "Taslağı Sil", "DialogMessage_DiscardDraftConfirmationTitle": "Taslağı Sil",
"DialogMessage_CloseDraftWindowConfirmationMessage": "Bir taslak hâlâ açık. Pencereyi kapatmadan önce kaydetmek ister misiniz?",
"DialogMessage_CloseDraftWindowConfirmationTitle": "Pencereyi Kapat",
"DialogMessage_EmptySubjectConfirmation": "Konu Eksik", "DialogMessage_EmptySubjectConfirmation": "Konu Eksik",
"DialogMessage_EmptySubjectConfirmationMessage": "Mesajın bir konusu yok. Devam etmek istiyor musunuz?", "DialogMessage_EmptySubjectConfirmationMessage": "Mesajın bir konusu yok. Devam etmek istiyor musunuz?",
"DialogMessage_EnableStartupLaunchDeniedMessage": "Oturum açma seçeneklerini Ayarlar -> Uygulama Tercihleri kısmından değiştirebilirsiniz.", "DialogMessage_EnableStartupLaunchDeniedMessage": "Oturum açma seçeneklerini Ayarlar -> Uygulama Tercihleri kısmından değiştirebilirsiniz.",
@@ -681,6 +689,10 @@
"NoMailSelected": "İleti seçilmedi", "NoMailSelected": "İleti seçilmedi",
"NoMessageCrieteria": "Kriterlere uygun mesaj bulunamadı", "NoMessageCrieteria": "Kriterlere uygun mesaj bulunamadı",
"NoMessageEmptyFolder": "Bu klasör boş", "NoMessageEmptyFolder": "Bu klasör boş",
"MailEmptyState_Title": "Posta için etkinleştirilmiş hesap yok",
"MailEmptyState_Message": "Takvim için bağlı hesaplarınız var, ancak bunlardan hiçbiri posta için etkinleştirilmedi. Bir posta hesabı ekleyin veya mevcut hesabı posta kullanacak şekilde güncelleyin.",
"MailEmptyState_AddAccount": "Hesap Ekle",
"MailEmptyState_ManageAccounts": "Hesapları Yönet",
"Notifications_MultipleNotificationsMessage": "{0} yeni mesajınız var.", "Notifications_MultipleNotificationsMessage": "{0} yeni mesajınız var.",
"Notifications_MultipleNotificationsTitle": "Yeni E-Posta", "Notifications_MultipleNotificationsTitle": "Yeni E-Posta",
"Notifications_WinoUpdatedMessage": "{0} sürümünü deneyin", "Notifications_WinoUpdatedMessage": "{0} sürümünü deneyin",
@@ -824,6 +836,8 @@
"SettingsDeleteAccount_Title": "Bu hesabı sil", "SettingsDeleteAccount_Title": "Bu hesabı sil",
"SettingsDeleteProtection_Description": "Should Wino ask you for confirmation every time you try to permanently delete a mail using Shift + Del keys?", "SettingsDeleteProtection_Description": "Should Wino ask you for confirmation every time you try to permanently delete a mail using Shift + Del keys?",
"SettingsDeleteProtection_Title": "Kalıcı Silme Koruması", "SettingsDeleteProtection_Title": "Kalıcı Silme Koruması",
"SettingsEmptyJunkFolderCommand_Description": "Gereksiz Posta/Spam klasörlerinde boş klasör komutunu göster. Bu işlem onay istemeyecek ve spam klasöründeki tüm mailleri hemen silecektir.",
"SettingsEmptyJunkFolderCommand_Title": "Boş Spam Klasörü Komutunu Göster",
"SettingsDiagnostics_Description": "Geliştiriciler için", "SettingsDiagnostics_Description": "Geliştiriciler için",
"SettingsDiagnostics_DiagnosticId_Description": "Bu ID'yi geliştiriciler ile paylaşarak Wino Mail ile yaşadığınız sorunlar hakkında çözümlere ulaşabilirsiniz.", "SettingsDiagnostics_DiagnosticId_Description": "Bu ID'yi geliştiriciler ile paylaşarak Wino Mail ile yaşadığınız sorunlar hakkında çözümlere ulaşabilirsiniz.",
"SettingsDiagnostics_DiagnosticId_Title": "Hata Ayıklama ID'si", "SettingsDiagnostics_DiagnosticId_Title": "Hata Ayıklama ID'si",
@@ -1074,6 +1088,12 @@
"SettingsTaskbarBadge_Title": "Sistem Çubuğu Balonu", "SettingsTaskbarBadge_Title": "Sistem Çubuğu Balonu",
"SettingsThreads_Description": "Bağlı mesajları tek bir liste halinde kategorize eder.", "SettingsThreads_Description": "Bağlı mesajları tek bir liste halinde kategorize eder.",
"SettingsThreads_Title": "Mesaj Gruplama", "SettingsThreads_Title": "Mesaj Gruplama",
"SettingsThreads_Enabled_Description": "İlişkili mesajları tek bir konuşmada grupla.",
"SettingsThreads_Enabled_Title": "İletilerin konuşma zincirini etkinleştir.",
"SettingsThreadOrder_Description": "Bir konuşma içindeki öğelerin nasıl sıralanacağını seçin.",
"SettingsThreadOrder_Title": "İleti Sıralaması",
"SettingsThreadOrder_LastItemFirst": "Son öğe önce",
"SettingsThreadOrder_FirstItemFirst": "İlk öğe önce",
"SettingsUnlinkAccounts_Description": "Hesap bağlantısını koparın. Bu işlem hesaplarınızı silmez.", "SettingsUnlinkAccounts_Description": "Hesap bağlantısını koparın. Bu işlem hesaplarınızı silmez.",
"SettingsUnlinkAccounts_Title": "Hesap Bağlantısını Kopar", "SettingsUnlinkAccounts_Title": "Hesap Bağlantısını Kopar",
"SettingsMailRendering_ActionLabels_Title": "Action labels", "SettingsMailRendering_ActionLabels_Title": "Action labels",
@@ -1339,6 +1359,7 @@
"WelcomeWindow_GetStartedButton": "Bir hesap ekleyerek başlayın", "WelcomeWindow_GetStartedButton": "Bir hesap ekleyerek başlayın",
"WelcomeWindow_GetStartedDescription": "Wino Mail'e başlamak için Outlook, Gmail veya IMAP hesabınızı ekleyin.", "WelcomeWindow_GetStartedDescription": "Wino Mail'e başlamak için Outlook, Gmail veya IMAP hesabınızı ekleyin.",
"WelcomeWindow_ImportFromWinoAccount": "Wino Hesabınızdan İçe Aktar", "WelcomeWindow_ImportFromWinoAccount": "Wino Hesabınızdan İçe Aktar",
"WelcomeWindow_ImportFromJsonFile": "JSON dosyasından içe aktar",
"WelcomeWindow_ImportInProgress": "Senkronize edilmiş tercihleriniz ve hesaplarınız içe aktarılıyor...", "WelcomeWindow_ImportInProgress": "Senkronize edilmiş tercihleriniz ve hesaplarınız içe aktarılıyor...",
"WelcomeWindow_ImportNoAccountsFound": "Wino Hesabınızda senkronize edilen hesap bulunamadı. Tercihler mevcutsa geri yüklendi. Bir hesabı manuel olarak eklemek için Başla'ya tıklayın.", "WelcomeWindow_ImportNoAccountsFound": "Wino Hesabınızda senkronize edilen hesap bulunamadı. Tercihler mevcutsa geri yüklendi. Bir hesabı manuel olarak eklemek için Başla'ya tıklayın.",
"WelcomeWindow_ImportDuplicateAccountsSkipped": "{0} senkronize edilmiş hesap bu cihazda zaten mevcut. Gerekirse başka bir hesap eklemek için Başla'ya tıklayın.", "WelcomeWindow_ImportDuplicateAccountsSkipped": "{0} senkronize edilmiş hesap bu cihazda zaten mevcut. Gerekirse başka bir hesap eklemek için Başla'ya tıklayın.",
@@ -1418,6 +1439,12 @@
"WinoAccount_Management_ExportDialog_AccountsDisclaimer": "Şifreler, erişim belirteçleri ve diğer hassas bilgiler senkronize edilmez.", "WinoAccount_Management_ExportDialog_AccountsDisclaimer": "Şifreler, erişim belirteçleri ve diğer hassas bilgiler senkronize edilmez.",
"WinoAccount_Management_ExportDialog_AccountsRelogin": "Başka bir PC'de içe aktarılan hesaplar, kullanılabilir hale gelmeden önce yine oturum açmanızı gerektirecek.", "WinoAccount_Management_ExportDialog_AccountsRelogin": "Başka bir PC'de içe aktarılan hesaplar, kullanılabilir hale gelmeden önce yine oturum açmanızı gerektirecek.",
"WinoAccount_Management_ExportDialog_InProgress": "Seçili Wino verileri dışa aktarılıyor...", "WinoAccount_Management_ExportDialog_InProgress": "Seçili Wino verileri dışa aktarılıyor...",
"WinoAccount_Management_LocalDataSectionTitle": "JSON Dosyası ile Aktarım",
"WinoAccount_Management_LocalDataSectionDescription": "Yerel bir JSON dosyasından içe aktarın veya dışa aktarın. Parolalar, erişim belirteçleri ve diğer hassas bilgiler dahil değildir.",
"WinoAccount_Management_LocalDataImportAction": "İçe aktar",
"WinoAccount_Management_LocalDataExportAction": "Dışa aktar",
"WinoAccount_Management_LocalDataSaved": "Dışa aktarılan Wino verinizi {0} konumuna kaydettiniz.",
"WinoAccount_Management_LocalDataInvalidFile": "Seçilen JSON dosyasında geçerli bir Wino dışa aktarımı bulunmuyor.",
"WinoAccount_Management_LoadFailed": "Wino en son Wino Hesap bilgilerini yükleyemedi.", "WinoAccount_Management_LoadFailed": "Wino en son Wino Hesap bilgilerini yükleyemedi.",
"WinoAccount_Management_ActionFailed": "Wino Hesap isteği tamamlanamadı.", "WinoAccount_Management_ActionFailed": "Wino Hesap isteği tamamlanamadı.",
"WinoAccount_SettingsSection_Title": "Wino Hesabı", "WinoAccount_SettingsSection_Title": "Wino Hesabı",
@@ -1514,8 +1541,22 @@
"WelcomeWizard_Step3Title": "Kurulumu Tamamla", "WelcomeWizard_Step3Title": "Kurulumu Tamamla",
"ProviderSelection_Title": "E-posta sağlayıcınızı seçin", "ProviderSelection_Title": "E-posta sağlayıcınızı seçin",
"ProviderSelection_Subtitle": "Aşağıdaki sağlayıcıyı seçerek e-posta hesabınızı Wino Mail'e ekleyin.", "ProviderSelection_Subtitle": "Aşağıdaki sağlayıcıyı seçerek e-posta hesabınızı Wino Mail'e ekleyin.",
"ProviderSelection_StepProgress": "3 adımın {0}. Adımı",
"ProviderSelection_IdentityTitle": "Hesap Kimliği",
"ProviderSelection_IdentityDescription": "Bu hesabın Wino'da nasıl görüneceğini seçin.",
"ProviderSelection_ProviderSectionTitle": "Sağlayıcı",
"ProviderSelection_ProviderSectionDescription": "Bağlamak istediğiniz hizmeti seçin.",
"ProviderSelection_CapabilitySectionTitle": "Bu hesap için kullanın",
"ProviderSelection_CapabilitySectionDescription": "Posta, takvim veya her ikisini birden kullanmak istiyorsanız seçin.",
"ProviderSelection_CapabilityProviderDescription_OAuth": "Bir sonraki adımda güvenli oturum açma hesabınızı bağlayacaktır. Takvim etkinleştirildiğinde, Wino Outlook Takvimi veya Google Takvimi'ni otomatik olarak bağlayacaktır.",
"ProviderSelection_CapabilityProviderDescription_SpecialImap": "Bir sonraki adımda sağlayıcı kimlik bilgilerinizi gireceksiniz. Posta IMAP/SMTP kullanır; takvim CalDAV kullanabilir veya bu cihazda yerel olarak kalabilir.",
"ProviderSelection_CapabilityProviderDescription_CustomServer": "Bir sonraki adımda sunucu bilgilerinizi gireceksiniz. Posta IMAP/SMTP kullanır; takvim CalDAV kullanabilir veya bu cihazda yerel olarak kalabilir.",
"ProviderSelection_AccountNameHeader": "Hesap Adı", "ProviderSelection_AccountNameHeader": "Hesap Adı",
"ProviderSelection_AccountNamePlaceholder": "örn. Kişisel, İş", "ProviderSelection_AccountNamePlaceholder": "örn. Kişisel, İş",
"ProviderSelection_UseForMail": "Posta",
"ProviderSelection_UseForCalendar": "Takvim",
"ProviderSelection_CapabilityValidationMessage": "Devam etmeden önce en az bir özellik seçin.",
"ProviderSelection_CalendarOnlyServerHint": "Yalnızca takvim ile devam ederseniz, sonraki sayfada bir e-posta adresi gerekmeyecektir.",
"ProviderSelection_DisplayNameHeader": "Görünen Ad", "ProviderSelection_DisplayNameHeader": "Görünen Ad",
"ProviderSelection_DisplayNamePlaceholder": "örn. John Doe", "ProviderSelection_DisplayNamePlaceholder": "örn. John Doe",
"ProviderSelection_EmailHeader": "E-posta Adresi", "ProviderSelection_EmailHeader": "E-posta Adresi",
@@ -47,6 +47,11 @@
"AccountDetailsPage_CalendarListDescription": "Виберіть календар, щоб налаштувати його параметри.", "AccountDetailsPage_CalendarListDescription": "Виберіть календар, щоб налаштувати його параметри.",
"AccountDetailsPage_InitialSynchronization_Title": "Початкова синхронізація", "AccountDetailsPage_InitialSynchronization_Title": "Початкова синхронізація",
"AccountDetailsPage_InitialSynchronization_Description": "Wino синхронізував ваші листи до {0} назад.", "AccountDetailsPage_InitialSynchronization_Description": "Wino синхронізував ваші листи до {0} назад.",
"AccountDetailsPage_CapabilityTitle": "Підключені функції",
"AccountDetailsPage_CapabilityDescription": "Виберіть, чи використовується цей обліковий запис для пошти, календаря або обох. Увімкнення нової функції може вимагати повторного входу.",
"AccountCapability_MailOnly": "Лише пошта",
"AccountCapability_CalendarOnly": "Лише календар",
"AccountCapability_MailAndCalendar": "Пошта та календар",
"AddHyperlink": "Додати", "AddHyperlink": "Додати",
"AppCloseBackgroundSynchronizationWarningTitle": "Фонова синхронізація", "AppCloseBackgroundSynchronizationWarningTitle": "Фонова синхронізація",
"AppCloseStartupLaunchDisabledWarningMessageFirstLine": "Програму не налаштовано на автозапуск під час запуску Windows.", "AppCloseStartupLaunchDisabledWarningMessageFirstLine": "Програму не налаштовано на автозапуск під час запуску Windows.",
@@ -76,6 +81,7 @@
"Buttons_ApplyTheme": "Застосувати тему", "Buttons_ApplyTheme": "Застосувати тему",
"Buttons_PopOut": "Відкрити у окремому вікні", "Buttons_PopOut": "Відкрити у окремому вікні",
"Buttons_Browse": "Огляд", "Buttons_Browse": "Огляд",
"Buttons_Back": "Назад",
"Buttons_Cancel": "Скасувати", "Buttons_Cancel": "Скасувати",
"Buttons_Close": "Закрити", "Buttons_Close": "Закрити",
"Buttons_Copy": "Копіювати", "Buttons_Copy": "Копіювати",
@@ -299,6 +305,8 @@
"DialogMessage_DeleteRecurringSeriesTitle": "Видалити повторювану серію", "DialogMessage_DeleteRecurringSeriesTitle": "Видалити повторювану серію",
"DialogMessage_DiscardDraftConfirmationMessage": "Цю чернетку буде відкинуто. Продовжити?", "DialogMessage_DiscardDraftConfirmationMessage": "Цю чернетку буде відкинуто. Продовжити?",
"DialogMessage_DiscardDraftConfirmationTitle": "Відкинути чернетку", "DialogMessage_DiscardDraftConfirmationTitle": "Відкинути чернетку",
"DialogMessage_CloseDraftWindowConfirmationMessage": "Чернетку ще відкрито. Зберегти її перед закриттям вікна?",
"DialogMessage_CloseDraftWindowConfirmationTitle": "Закрити вікно",
"DialogMessage_EmptySubjectConfirmation": "Теми не вказано", "DialogMessage_EmptySubjectConfirmation": "Теми не вказано",
"DialogMessage_EmptySubjectConfirmationMessage": "Повідомлення не має теми. Продовжити?", "DialogMessage_EmptySubjectConfirmationMessage": "Повідомлення не має теми. Продовжити?",
"DialogMessage_EnableStartupLaunchDeniedMessage": "Увімкнути автозапуск можна в Налаштуваннях -> Параметри програми.", "DialogMessage_EnableStartupLaunchDeniedMessage": "Увімкнути автозапуск можна в Налаштуваннях -> Параметри програми.",
@@ -681,6 +689,10 @@
"NoMailSelected": "Повідомлення не вибрано", "NoMailSelected": "Повідомлення не вибрано",
"NoMessageCrieteria": "Немає повідомлень, що відповідають критеріям пошуку", "NoMessageCrieteria": "Немає повідомлень, що відповідають критеріям пошуку",
"NoMessageEmptyFolder": "Ця тека порожня", "NoMessageEmptyFolder": "Ця тека порожня",
"MailEmptyState_Title": "Немає облікових записів, увімкнених для пошти",
"MailEmptyState_Message": "У вас підключені облікові записи для календаря, але жоден з них не увімкнено для пошти. Додайте обліковий запис пошти або оновіть існуючий обліковий запис, щоб використовувати пошту.",
"MailEmptyState_AddAccount": "Додати обліковий запис",
"MailEmptyState_ManageAccounts": "Керувати обліковими записами",
"Notifications_MultipleNotificationsMessage": "У вас {0} нових повідомлень.", "Notifications_MultipleNotificationsMessage": "У вас {0} нових повідомлень.",
"Notifications_MultipleNotificationsTitle": "Свіжа пошта", "Notifications_MultipleNotificationsTitle": "Свіжа пошта",
"Notifications_WinoUpdatedMessage": "Погляньте на нову версію {0}", "Notifications_WinoUpdatedMessage": "Погляньте на нову версію {0}",
@@ -824,6 +836,8 @@
"SettingsDeleteAccount_Title": "Видалити цей обліковий запис", "SettingsDeleteAccount_Title": "Видалити цей обліковий запис",
"SettingsDeleteProtection_Description": "Should Wino ask you for confirmation every time you try to permanently delete a mail using Shift + Del keys?", "SettingsDeleteProtection_Description": "Should Wino ask you for confirmation every time you try to permanently delete a mail using Shift + Del keys?",
"SettingsDeleteProtection_Title": "Захист від остаточного видалення", "SettingsDeleteProtection_Title": "Захист від остаточного видалення",
"SettingsEmptyJunkFolderCommand_Description": "Показати команду очищення порожньої папки у папках Небажана пошта/Спам. Ця дія не вимагатиме підтвердження і негайно видалить усі листи з папки зі спамом.",
"SettingsEmptyJunkFolderCommand_Title": "Показати команду очищення порожньої папки Спам",
"SettingsDiagnostics_Description": "Для розробників", "SettingsDiagnostics_Description": "Для розробників",
"SettingsDiagnostics_DiagnosticId_Description": "Поділіться цим ID з розробниками, коли попросять, щоб отримати допомогу щодо проблем, з якими Ви зіткнулися у Wino Mail.", "SettingsDiagnostics_DiagnosticId_Description": "Поділіться цим ID з розробниками, коли попросять, щоб отримати допомогу щодо проблем, з якими Ви зіткнулися у Wino Mail.",
"SettingsDiagnostics_DiagnosticId_Title": "ID діагностики", "SettingsDiagnostics_DiagnosticId_Title": "ID діагностики",
@@ -1074,6 +1088,12 @@
"SettingsTaskbarBadge_Title": "Значок на панелі завдань", "SettingsTaskbarBadge_Title": "Значок на панелі завдань",
"SettingsThreads_Description": "Організуйте повідомлення в ланцюжки розмов.", "SettingsThreads_Description": "Організуйте повідомлення в ланцюжки розмов.",
"SettingsThreads_Title": "Ланцюжки розмов", "SettingsThreads_Title": "Ланцюжки розмов",
"SettingsThreads_Enabled_Description": "Групуйте пов'язані повідомлення в одну розмову.",
"SettingsThreads_Enabled_Title": "Увімкнути групування розмов.",
"SettingsThreadOrder_Description": "Виберіть порядок сортування елементів у розмові.",
"SettingsThreadOrder_Title": "Сортування елементів розмови",
"SettingsThreadOrder_LastItemFirst": "Останній елемент першим",
"SettingsThreadOrder_FirstItemFirst": "Перший елемент першим",
"SettingsUnlinkAccounts_Description": "Видалити зв'язку між обліковими записами. Це не видалить самі облікові записи.", "SettingsUnlinkAccounts_Description": "Видалити зв'язку між обліковими записами. Це не видалить самі облікові записи.",
"SettingsUnlinkAccounts_Title": "Відв'язати облікові записи", "SettingsUnlinkAccounts_Title": "Відв'язати облікові записи",
"SettingsMailRendering_ActionLabels_Title": "Action labels", "SettingsMailRendering_ActionLabels_Title": "Action labels",
@@ -1339,6 +1359,7 @@
"WelcomeWindow_GetStartedButton": "Почати, додавши обліковий запис", "WelcomeWindow_GetStartedButton": "Почати, додавши обліковий запис",
"WelcomeWindow_GetStartedDescription": "Додайте ваш Outlook, Gmail або IMAP обліковий запис, щоб почати з Wino Mail.", "WelcomeWindow_GetStartedDescription": "Додайте ваш Outlook, Gmail або IMAP обліковий запис, щоб почати з Wino Mail.",
"WelcomeWindow_ImportFromWinoAccount": "Імпортувати з вашого облікового запису Wino", "WelcomeWindow_ImportFromWinoAccount": "Імпортувати з вашого облікового запису Wino",
"WelcomeWindow_ImportFromJsonFile": "Імпортувати з файлу JSON",
"WelcomeWindow_ImportInProgress": "Імпорт ваших синхронізованих налаштувань та облікових записів...", "WelcomeWindow_ImportInProgress": "Імпорт ваших синхронізованих налаштувань та облікових записів...",
"WelcomeWindow_ImportNoAccountsFound": "У вашому обліковому записі Wino не знайдено синхронізованих облікових записів. Якщо налаштування були доступні, вони відновлені. Використайте 'Почати', щоб додати обліковий запис вручну.", "WelcomeWindow_ImportNoAccountsFound": "У вашому обліковому записі Wino не знайдено синхронізованих облікових записів. Якщо налаштування були доступні, вони відновлені. Використайте 'Почати', щоб додати обліковий запис вручну.",
"WelcomeWindow_ImportDuplicateAccountsSkipped": "{0} синхронізованих облікових записів вже доступні на цьому пристрої. Використайте 'Почати', щоб додати ще один обліковий запис вручну, якщо потрібно.", "WelcomeWindow_ImportDuplicateAccountsSkipped": "{0} синхронізованих облікових записів вже доступні на цьому пристрої. Використайте 'Почати', щоб додати ще один обліковий запис вручну, якщо потрібно.",
@@ -1418,6 +1439,12 @@
"WinoAccount_Management_ExportDialog_AccountsDisclaimer": "Паролі, токени та інша чутлива інформація не синхронізуються.", "WinoAccount_Management_ExportDialog_AccountsDisclaimer": "Паролі, токени та інша чутлива інформація не синхронізуються.",
"WinoAccount_Management_ExportDialog_AccountsRelogin": "Імпортовані облікові записи на іншому ПК все ще потребуватимуть повторного входу перед їх використанням.", "WinoAccount_Management_ExportDialog_AccountsRelogin": "Імпортовані облікові записи на іншому ПК все ще потребуватимуть повторного входу перед їх використанням.",
"WinoAccount_Management_ExportDialog_InProgress": "Експорт ваших вибраних даних Wino...", "WinoAccount_Management_ExportDialog_InProgress": "Експорт ваших вибраних даних Wino...",
"WinoAccount_Management_LocalDataSectionTitle": "Перенесення за допомогою JSON-файлу",
"WinoAccount_Management_LocalDataSectionDescription": "Імпорт або експорт до локального файлу JSON. Паролі, токени та інша чутлива інформація не включаються.",
"WinoAccount_Management_LocalDataImportAction": "Імпортувати",
"WinoAccount_Management_LocalDataExportAction": "Експортувати",
"WinoAccount_Management_LocalDataSaved": "Збережено ваші дані Wino, експортовані до {0}.",
"WinoAccount_Management_LocalDataInvalidFile": "Вибраний файл JSON не містить дійсного експорту Wino.",
"WinoAccount_Management_LoadFailed": "Не вдалося завантажити останню інформацію про обліковий запис Wino.", "WinoAccount_Management_LoadFailed": "Не вдалося завантажити останню інформацію про обліковий запис Wino.",
"WinoAccount_Management_ActionFailed": "Запит до облікового запису Wino не вдалося виконати.", "WinoAccount_Management_ActionFailed": "Запит до облікового запису Wino не вдалося виконати.",
"WinoAccount_SettingsSection_Title": "Обліковий запис Wino", "WinoAccount_SettingsSection_Title": "Обліковий запис Wino",
@@ -1514,8 +1541,22 @@
"WelcomeWizard_Step3Title": "Завершити налаштування", "WelcomeWizard_Step3Title": "Завершити налаштування",
"ProviderSelection_Title": "Виберіть постачальника електронної пошти", "ProviderSelection_Title": "Виберіть постачальника електронної пошти",
"ProviderSelection_Subtitle": "Виберіть постачальника нижче, щоб додати свій обліковий ящик електронної пошти до Wino Mail.", "ProviderSelection_Subtitle": "Виберіть постачальника нижче, щоб додати свій обліковий ящик електронної пошти до Wino Mail.",
"ProviderSelection_StepProgress": "Крок {0} з 3",
"ProviderSelection_IdentityTitle": "Ідентифікація облікового запису",
"ProviderSelection_IdentityDescription": "Виберіть, як цей обліковий запис відображатиметься в Wino.",
"ProviderSelection_ProviderSectionTitle": "Провайдер",
"ProviderSelection_ProviderSectionDescription": "Виберіть службу, яку хочете підключити.",
"ProviderSelection_CapabilitySectionTitle": "Використовувати цей обліковий запис для",
"ProviderSelection_CapabilitySectionDescription": "Виберіть, чи хочете використовувати пошту, календар або обидва.",
"ProviderSelection_CapabilityProviderDescription_OAuth": "На наступному кроці безпечний вхід з'єднає ваш обліковий запис. Якщо увімкнено календар, Wino також автоматично підключить календар Outlook або Google Calendar.",
"ProviderSelection_CapabilityProviderDescription_SpecialImap": "На наступному кроці ви введете облікові дані провайдера. Пошта використовує IMAP/SMTP, а календар може використовувати CalDAV або залишитися локальним на цьому пристрої.",
"ProviderSelection_CapabilityProviderDescription_CustomServer": "На наступному кроці ви введете дані сервера. Пошта використовує IMAP/SMTP, а календар може використовувати CalDAV або залишитися локальним на цьому пристрої.",
"ProviderSelection_AccountNameHeader": "Назва облікового запису", "ProviderSelection_AccountNameHeader": "Назва облікового запису",
"ProviderSelection_AccountNamePlaceholder": "наприклад, Особистий, Робочий", "ProviderSelection_AccountNamePlaceholder": "наприклад, Особистий, Робочий",
"ProviderSelection_UseForMail": "Пошта",
"ProviderSelection_UseForCalendar": "Календар",
"ProviderSelection_CapabilityValidationMessage": "Виберіть хоча б одну можливість перед продовженням.",
"ProviderSelection_CalendarOnlyServerHint": "Якщо продовжити лише зcalendar, на наступній сторінці адреса електронної пошти не буде потрібна.",
"ProviderSelection_DisplayNameHeader": "Відображуване ім'я", "ProviderSelection_DisplayNameHeader": "Відображуване ім'я",
"ProviderSelection_DisplayNamePlaceholder": "наприклад, Іван Іванов", "ProviderSelection_DisplayNamePlaceholder": "наприклад, Іван Іванов",
"ProviderSelection_EmailHeader": "Електронна адреса", "ProviderSelection_EmailHeader": "Електронна адреса",
@@ -47,6 +47,11 @@
"AccountDetailsPage_CalendarListDescription": "选择日历以配置其设置", "AccountDetailsPage_CalendarListDescription": "选择日历以配置其设置",
"AccountDetailsPage_InitialSynchronization_Title": "初次同步", "AccountDetailsPage_InitialSynchronization_Title": "初次同步",
"AccountDetailsPage_InitialSynchronization_Description": "Wino 已将邮件同步到回溯到 {0} 的时间点。", "AccountDetailsPage_InitialSynchronization_Description": "Wino 已将邮件同步到回溯到 {0} 的时间点。",
"AccountDetailsPage_CapabilityTitle": "已连接的功能",
"AccountDetailsPage_CapabilityDescription": "选择此账户用于邮件、日历,或两者皆用。启用新功能可能会要求您重新登录。",
"AccountCapability_MailOnly": "仅邮件",
"AccountCapability_CalendarOnly": "仅日历",
"AccountCapability_MailAndCalendar": "邮件与日历",
"AddHyperlink": "添加", "AddHyperlink": "添加",
"AppCloseBackgroundSynchronizationWarningTitle": "后台同步", "AppCloseBackgroundSynchronizationWarningTitle": "后台同步",
"AppCloseStartupLaunchDisabledWarningMessageFirstLine": "应用尚未设置为随 Windows 自启。", "AppCloseStartupLaunchDisabledWarningMessageFirstLine": "应用尚未设置为随 Windows 自启。",
@@ -76,6 +81,7 @@
"Buttons_ApplyTheme": "应用主题", "Buttons_ApplyTheme": "应用主题",
"Buttons_PopOut": "弹出", "Buttons_PopOut": "弹出",
"Buttons_Browse": "浏览", "Buttons_Browse": "浏览",
"Buttons_Back": "返回",
"Buttons_Cancel": "取消", "Buttons_Cancel": "取消",
"Buttons_Close": "关闭", "Buttons_Close": "关闭",
"Buttons_Copy": "复制", "Buttons_Copy": "复制",
@@ -299,6 +305,8 @@
"DialogMessage_DeleteRecurringSeriesTitle": "删除重复系列", "DialogMessage_DeleteRecurringSeriesTitle": "删除重复系列",
"DialogMessage_DiscardDraftConfirmationMessage": "草稿将被删除。你想要继续吗?", "DialogMessage_DiscardDraftConfirmationMessage": "草稿将被删除。你想要继续吗?",
"DialogMessage_DiscardDraftConfirmationTitle": "舍弃草稿", "DialogMessage_DiscardDraftConfirmationTitle": "舍弃草稿",
"DialogMessage_CloseDraftWindowConfirmationMessage": "草稿仍未保存。在关闭窗口前保存吗?",
"DialogMessage_CloseDraftWindowConfirmationTitle": "关闭窗口",
"DialogMessage_EmptySubjectConfirmation": "缺少标题", "DialogMessage_EmptySubjectConfirmation": "缺少标题",
"DialogMessage_EmptySubjectConfirmationMessage": "邮件没有主题。您想要继续吗?", "DialogMessage_EmptySubjectConfirmationMessage": "邮件没有主题。您想要继续吗?",
"DialogMessage_EnableStartupLaunchDeniedMessage": "可以在「设置」-「应用设置」中启用自启动。", "DialogMessage_EnableStartupLaunchDeniedMessage": "可以在「设置」-「应用设置」中启用自启动。",
@@ -681,6 +689,10 @@
"NoMailSelected": "未选择任何邮件", "NoMailSelected": "未选择任何邮件",
"NoMessageCrieteria": "没有符合搜索条件的邮件", "NoMessageCrieteria": "没有符合搜索条件的邮件",
"NoMessageEmptyFolder": "此文件夹为空", "NoMessageEmptyFolder": "此文件夹为空",
"MailEmptyState_Title": "没有启用邮件的账户",
"MailEmptyState_Message": "您已连接日历账户,但没有任何账户启用邮件。请添加邮件账户,或更新现有账户以使用邮件。",
"MailEmptyState_AddAccount": "添加账户",
"MailEmptyState_ManageAccounts": "管理账户",
"Notifications_MultipleNotificationsMessage": "您有 {0} 条新消息。", "Notifications_MultipleNotificationsMessage": "您有 {0} 条新消息。",
"Notifications_MultipleNotificationsTitle": "新邮件", "Notifications_MultipleNotificationsTitle": "新邮件",
"Notifications_WinoUpdatedMessage": "检查新版本 {0}", "Notifications_WinoUpdatedMessage": "检查新版本 {0}",
@@ -824,6 +836,8 @@
"SettingsDeleteAccount_Title": "删除此账户", "SettingsDeleteAccount_Title": "删除此账户",
"SettingsDeleteProtection_Description": "Should Wino ask you for confirmation every time you try to permanently delete a mail using Shift + Del keys?", "SettingsDeleteProtection_Description": "Should Wino ask you for confirmation every time you try to permanently delete a mail using Shift + Del keys?",
"SettingsDeleteProtection_Title": "永久性删除保护", "SettingsDeleteProtection_Title": "永久性删除保护",
"SettingsEmptyJunkFolderCommand_Description": "在垃圾邮件/垃圾箱文件夹中显示清空文件夹命令。此操作不会要求确认,将立即删除垃圾邮件文件夹中的所有邮件。",
"SettingsEmptyJunkFolderCommand_Title": "显示清空垃圾邮件文件夹的命令",
"SettingsDiagnostics_Description": "开发者选项", "SettingsDiagnostics_Description": "开发者选项",
"SettingsDiagnostics_DiagnosticId_Description": "如需联系开发人员请求帮助,请提供此 ID。", "SettingsDiagnostics_DiagnosticId_Description": "如需联系开发人员请求帮助,请提供此 ID。",
"SettingsDiagnostics_DiagnosticId_Title": "诊断 ID", "SettingsDiagnostics_DiagnosticId_Title": "诊断 ID",
@@ -1074,6 +1088,12 @@
"SettingsTaskbarBadge_Title": "任务栏徽标", "SettingsTaskbarBadge_Title": "任务栏徽标",
"SettingsThreads_Description": "将邮件组织成对话主题。", "SettingsThreads_Description": "将邮件组织成对话主题。",
"SettingsThreads_Title": "邮件会话", "SettingsThreads_Title": "邮件会话",
"SettingsThreads_Enabled_Description": "将相关邮件聚合为一个对话。",
"SettingsThreads_Enabled_Title": "启用对话串联",
"SettingsThreadOrder_Description": "选择对话中条目的排序方式。",
"SettingsThreadOrder_Title": "对话项排序",
"SettingsThreadOrder_LastItemFirst": "最后一项在前",
"SettingsThreadOrder_FirstItemFirst": "第一项在前",
"SettingsUnlinkAccounts_Description": "删除账户之间的链接。这不会删除您的账户。", "SettingsUnlinkAccounts_Description": "删除账户之间的链接。这不会删除您的账户。",
"SettingsUnlinkAccounts_Title": "取消链接账户", "SettingsUnlinkAccounts_Title": "取消链接账户",
"SettingsMailRendering_ActionLabels_Title": "Action labels", "SettingsMailRendering_ActionLabels_Title": "Action labels",
@@ -1339,6 +1359,7 @@
"WelcomeWindow_GetStartedButton": "开始添加账户", "WelcomeWindow_GetStartedButton": "开始添加账户",
"WelcomeWindow_GetStartedDescription": "添加您的 Outlook、Gmail 或 IMAP 账户来开始使用 Wino Mail。", "WelcomeWindow_GetStartedDescription": "添加您的 Outlook、Gmail 或 IMAP 账户来开始使用 Wino Mail。",
"WelcomeWindow_ImportFromWinoAccount": "从您的 Wino 账户导入", "WelcomeWindow_ImportFromWinoAccount": "从您的 Wino 账户导入",
"WelcomeWindow_ImportFromJsonFile": "从 JSON 文件导入",
"WelcomeWindow_ImportInProgress": "正在导入同步的偏好设置和账户...", "WelcomeWindow_ImportInProgress": "正在导入同步的偏好设置和账户...",
"WelcomeWindow_ImportNoAccountsFound": "在 Wino 账户中未找到同步的账户。如果存在偏好设置,它们已被还原。使用“开始使用”手动添加账户。", "WelcomeWindow_ImportNoAccountsFound": "在 Wino 账户中未找到同步的账户。如果存在偏好设置,它们已被还原。使用“开始使用”手动添加账户。",
"WelcomeWindow_ImportDuplicateAccountsSkipped": "{0} 同步账户已在此设备上可用。如有需要,请使用“开始使用”手动再添加一个账户。", "WelcomeWindow_ImportDuplicateAccountsSkipped": "{0} 同步账户已在此设备上可用。如有需要,请使用“开始使用”手动再添加一个账户。",
@@ -1418,6 +1439,12 @@
"WinoAccount_Management_ExportDialog_AccountsDisclaimer": "密码、令牌和其他敏感信息不会同步。", "WinoAccount_Management_ExportDialog_AccountsDisclaimer": "密码、令牌和其他敏感信息不会同步。",
"WinoAccount_Management_ExportDialog_AccountsRelogin": "在另一台电脑上导入的账户仍需要您再次登录后才能使用。", "WinoAccount_Management_ExportDialog_AccountsRelogin": "在另一台电脑上导入的账户仍需要您再次登录后才能使用。",
"WinoAccount_Management_ExportDialog_InProgress": "正在导出您选择的 Wino 数据...", "WinoAccount_Management_ExportDialog_InProgress": "正在导出您选择的 Wino 数据...",
"WinoAccount_Management_LocalDataSectionTitle": "通过 JSON 文件传输",
"WinoAccount_Management_LocalDataSectionDescription": "从本地 JSON 文件导入或导出。密码、令牌和其他敏感信息不包含在内。",
"WinoAccount_Management_LocalDataImportAction": "导入",
"WinoAccount_Management_LocalDataExportAction": "导出",
"WinoAccount_Management_LocalDataSaved": "已将导出的 Wino 数据保存到 {0}。",
"WinoAccount_Management_LocalDataInvalidFile": "所选 JSON 文件不包含有效的 Wino 导出。",
"WinoAccount_Management_LoadFailed": "无法加载最新的 Wino 账户信息。", "WinoAccount_Management_LoadFailed": "无法加载最新的 Wino 账户信息。",
"WinoAccount_Management_ActionFailed": "Wino 账户请求无法完成。", "WinoAccount_Management_ActionFailed": "Wino 账户请求无法完成。",
"WinoAccount_SettingsSection_Title": "Wino 账户", "WinoAccount_SettingsSection_Title": "Wino 账户",
@@ -1514,8 +1541,22 @@
"WelcomeWizard_Step3Title": "完成设置", "WelcomeWizard_Step3Title": "完成设置",
"ProviderSelection_Title": "选择您的电子邮件提供商", "ProviderSelection_Title": "选择您的电子邮件提供商",
"ProviderSelection_Subtitle": "在下方选择一个提供商,以将您的电子邮件账户添加到 Wino Mail。", "ProviderSelection_Subtitle": "在下方选择一个提供商,以将您的电子邮件账户添加到 Wino Mail。",
"ProviderSelection_StepProgress": "步骤 {0} / 3",
"ProviderSelection_IdentityTitle": "账户身份",
"ProviderSelection_IdentityDescription": "选择此账户在 Wino 中的显示方式。",
"ProviderSelection_ProviderSectionTitle": "提供商",
"ProviderSelection_ProviderSectionDescription": "选择要连接的服务。",
"ProviderSelection_CapabilitySectionTitle": "将此账户用于",
"ProviderSelection_CapabilitySectionDescription": "选择要使用邮件、日历,还是两者都使用。",
"ProviderSelection_CapabilityProviderDescription_OAuth": "在下一步中,安全登录将连接您的账户。如果启用日历,Wino 也会自动连接 Outlook 日历或 Google 日历。",
"ProviderSelection_CapabilityProviderDescription_SpecialImap": "在下一步中,您将输入提供商凭据。邮件使用 IMAP/SMTP,日历可以使用 CalDAV,或在此设备上本地存储。",
"ProviderSelection_CapabilityProviderDescription_CustomServer": "在下一步中,您将输入服务器详细信息。邮件使用 IMAP/SMTP,日历可以使用 CalDAV,或在此设备上本地存储。",
"ProviderSelection_AccountNameHeader": "账户名", "ProviderSelection_AccountNameHeader": "账户名",
"ProviderSelection_AccountNamePlaceholder": "例如 个人、工作", "ProviderSelection_AccountNamePlaceholder": "例如 个人、工作",
"ProviderSelection_UseForMail": "邮件",
"ProviderSelection_UseForCalendar": "日历",
"ProviderSelection_CapabilityValidationMessage": "继续前请至少选择一个功能。",
"ProviderSelection_CalendarOnlyServerHint": "如果仅使用日历继续,下一页将不需要电子邮件地址。",
"ProviderSelection_DisplayNameHeader": "显示名称", "ProviderSelection_DisplayNameHeader": "显示名称",
"ProviderSelection_DisplayNamePlaceholder": "例如 约翰·多伊", "ProviderSelection_DisplayNamePlaceholder": "例如 约翰·多伊",
"ProviderSelection_EmailHeader": "电子邮件地址", "ProviderSelection_EmailHeader": "电子邮件地址",
@@ -0,0 +1,64 @@
using System;
using System.Net.Mail;
namespace Wino.Core.Domain.Validation;
public static class MailAccountAddressValidator
{
public static bool IsValid(string address)
{
if (string.IsNullOrWhiteSpace(address))
return false;
var trimmedAddress = address.Trim();
if (trimmedAddress.Contains('\r') || trimmedAddress.Contains('\n'))
return false;
try
{
var parsedAddress = new MailAddress(trimmedAddress);
return parsedAddress.Address.Equals(trimmedAddress, StringComparison.OrdinalIgnoreCase);
}
catch
{
return false;
}
}
public static bool TryGetDomain(string address, out string domain)
{
domain = string.Empty;
if (!IsValid(address))
return false;
var trimmedAddress = address.Trim();
var separatorIndex = trimmedAddress.LastIndexOf('@');
if (separatorIndex <= 0 || separatorIndex >= trimmedAddress.Length - 1)
return false;
domain = trimmedAddress[(separatorIndex + 1)..];
return !string.IsNullOrWhiteSpace(domain);
}
public static bool IsImplicitlyResolvableHost(string host)
{
if (string.IsNullOrWhiteSpace(host))
return false;
var normalizedHost = host.Trim().TrimEnd('.');
if (string.IsNullOrWhiteSpace(normalizedHost))
return false;
if (normalizedHost.Equals("localhost", StringComparison.OrdinalIgnoreCase))
return true;
var hostType = Uri.CheckHostName(normalizedHost);
if (hostType is UriHostNameType.IPv4 or UriHostNameType.IPv6)
return true;
return normalizedHost.IndexOf('.') < 0;
}
}
+3
View File
@@ -0,0 +1,3 @@
using Xunit;
[assembly: CollectionBehavior(DisableTestParallelization = true)]
@@ -15,6 +15,7 @@ public class HtmlPreviewVisitorTests
<html> <html>
<body onload="alert('x')"> <body onload="alert('x')">
<h1 onclick="evil()">hello</h1> <h1 onclick="evil()">hello</h1>
<link rel="stylesheet" href="https://tracker.example/mail.css" />
<script>alert('xss')</script> <script>alert('xss')</script>
<iframe src="https://malicious.example"></iframe> <iframe src="https://malicious.example"></iframe>
<object data="https://malicious.example/file.swf"></object> <object data="https://malicious.example/file.swf"></object>
@@ -34,6 +35,7 @@ public class HtmlPreviewVisitorTests
// Assert // Assert
output.Should().NotContain("<script", "script tags must be blocked in rendered html"); output.Should().NotContain("<script", "script tags must be blocked in rendered html");
output.Should().NotContain("<link", "external stylesheet tags must be blocked in rendered html");
output.Should().NotContain("<iframe", "iframe tags must be blocked in rendered html"); output.Should().NotContain("<iframe", "iframe tags must be blocked in rendered html");
output.Should().NotContain("<object", "object tags must be blocked in rendered html"); output.Should().NotContain("<object", "object tags must be blocked in rendered html");
output.Should().NotContain("onload=", "event handler attributes must be stripped"); output.Should().NotContain("onload=", "event handler attributes must be stripped");
@@ -83,7 +83,7 @@ public class AccountServiceTests : IAsyncLifetime
var secondAccountId = Guid.NewGuid(); var secondAccountId = Guid.NewGuid();
await _accountService.CreateAccountAsync( await _accountService.CreateAccountAsync(
CreateImapAccount(firstAccountId), CreateImapAccount(firstAccountId, "IMAP Test Account 1", "imap1@test.local"),
new CustomServerInformation new CustomServerInformation
{ {
Id = Guid.NewGuid(), Id = Guid.NewGuid(),
@@ -92,7 +92,7 @@ public class AccountServiceTests : IAsyncLifetime
}); });
await _accountService.CreateAccountAsync( await _accountService.CreateAccountAsync(
CreateImapAccount(secondAccountId), CreateImapAccount(secondAccountId, "IMAP Test Account 2", "imap2@test.local"),
new CustomServerInformation new CustomServerInformation
{ {
Id = Guid.NewGuid(), Id = Guid.NewGuid(),
@@ -119,13 +119,13 @@ public class AccountServiceTests : IAsyncLifetime
.BeGreaterThanOrEqualTo(50); .BeGreaterThanOrEqualTo(50);
} }
private static MailAccount CreateImapAccount(Guid accountId) private static MailAccount CreateImapAccount(Guid accountId, string name = "IMAP Test Account", string address = "imap@test.local")
{ {
return new MailAccount return new MailAccount
{ {
Id = accountId, Id = accountId,
Name = "IMAP Test Account", Name = name,
Address = "imap@test.local", Address = address,
SenderName = "IMAP Test", SenderName = "IMAP Test",
ProviderType = MailProviderType.IMAP4 ProviderType = MailProviderType.IMAP4
}; };
@@ -150,6 +150,41 @@ public class AutoDiscoveryServiceTests
uri.Should().Be(new Uri("https://dav.example.net/caldav/")); uri.Should().Be(new Uri("https://dav.example.net/caldav/"));
} }
[Fact]
public async Task GetAutoDiscoverySettings_ReturnsGuessedLocalhostSettings_ForManualLocalAccounts()
{
var handler = new StubHttpMessageHandler(request =>
{
var uri = request.RequestUri!.ToString();
if (uri.StartsWith("https://dns.google/resolve", StringComparison.OrdinalIgnoreCase))
{
return CreateJsonResponse("{\"Status\":0}", request);
}
return CreateStatusResponse(HttpStatusCode.NotFound, request);
});
using var client = new HttpClient(handler);
var sut = new AutoDiscoveryService(client);
var settings = await sut.GetAutoDiscoverySettings(new AutoDiscoveryMinimalSettings
{
Email = "user@localhost",
DisplayName = "User",
Password = "secret"
});
settings.Should().NotBeNull();
settings!.Domain.Should().Be("localhost");
settings.GetImapSettings()!.Address.Should().Be("localhost");
settings.GetImapSettings()!.Port.Should().Be(993);
settings.GetImapSettings()!.Username.Should().Be("user@localhost");
settings.GetSmptpSettings()!.Address.Should().Be("localhost");
settings.GetSmptpSettings()!.Port.Should().Be(587);
settings.GetSmptpSettings()!.Username.Should().Be("user@localhost");
}
private static HttpResponseMessage CreateXmlResponse(string xml, HttpRequestMessage request) private static HttpResponseMessage CreateXmlResponse(string xml, HttpRequestMessage request)
=> new(HttpStatusCode.OK) => new(HttpStatusCode.OK)
{ {
@@ -0,0 +1,53 @@
using FluentAssertions;
using HtmlAgilityPack;
using Wino.Services.Extensions;
using Xunit;
namespace Wino.Core.Tests.Services;
public class HtmlAgilityPackExtensionsTests
{
[Fact]
public void ClearImages_Should_Block_Remote_Image_References_But_Keep_Embedded_Ones()
{
// Arrange
var document = new HtmlDocument();
document.LoadHtml("""
<html>
<head>
<style>
.hero { background-image: url('https://tracker.example/bg.png'); color: red; }
</style>
</head>
<body background="https://tracker.example/body.png">
<img id="remote" src="https://tracker.example/pixel.png" />
<img id="embedded" src="data:image/png;base64,AAAA" />
<img id="responsive" srcset="https://tracker.example/1x.png 1x, data:image/png;base64,BBBB 2x" />
<div id="inline-style" style="background-image:url('https://tracker.example/inline.png');color:blue;">hello</div>
<v:fill id="vml" src="https://tracker.example/vml.png"></v:fill>
<svg>
<image id="svg-remote" href="https://tracker.example/vector.svg"></image>
<use id="svg-local" href="#icon"></use>
</svg>
</body>
</html>
""");
// Act
document.ClearImages();
var output = document.DocumentNode.OuterHtml;
// Assert
output.Should().Contain("id=\"embedded\" src=\"data:image/png;base64,AAAA\"", "embedded inline images should still render");
output.Should().NotContain("id=\"remote\" src=", "remote img sources should be removed");
output.Should().NotContain("background=\"https://tracker.example/body.png\"", "background attributes can be used as trackers");
output.Should().NotContain("srcset=", "responsive image candidates should be removed because they may fetch remote trackers");
output.Should().NotContain("https://tracker.example/inline.png", "inline CSS should not be allowed to fetch remote images");
output.Should().Contain("color:blue", "non-image inline styling should be preserved");
output.Should().NotContain("https://tracker.example/bg.png", "style blocks should not be allowed to fetch remote images");
output.Should().Contain("color: red", "safe CSS declarations should remain");
output.Should().NotContain("id=\"vml\" src=", "VML image references should be removed");
output.Should().NotContain("id=\"svg-remote\" href=", "SVG image references should not fetch remote content");
output.Should().Contain("id=\"svg-local\" href=\"#icon\"", "local fragment references should remain");
}
}
@@ -259,6 +259,26 @@ public class MailFetchingTests : IAsyncLifetime
result.Single().FolderId.Should().Be(_inboxFolder.Id, "a copy from the actively searched folder should win over newer non-searched copies"); result.Single().FolderId.Should().Be(_inboxFolder.Id, "a copy from the actively searched folder should win over newer non-searched copies");
} }
[Fact]
public async Task FetchPinnedMailsAsync_ReturnsPinnedMailsOutsideRegularPage()
{
var oldPinned = BuildMail(_inboxFolder.Id, DateTime.UtcNow.AddDays(-5));
oldPinned.IsPinned = true;
var recentMails = Enumerable.Range(0, 120)
.Select(i => BuildMail(_inboxFolder.Id, DateTime.UtcNow.AddMinutes(-i)))
.ToList();
await _databaseService.Connection.InsertAsync(oldPinned, typeof(MailCopy));
await _databaseService.Connection.InsertAllAsync(recentMails, typeof(MailCopy));
var options = BuildOptions([_inboxFolder], createThreads: false, take: 20);
var result = await _mailService.FetchPinnedMailsAsync(options);
result.Should().ContainSingle(mail => mail.UniqueId == oldPinned.UniqueId);
}
[Fact] [Fact]
public async Task CreateAssignmentAsync_ExistingAssignment_IsIgnored() public async Task CreateAssignmentAsync_ExistingAssignment_IsIgnored()
{ {
@@ -297,6 +317,27 @@ public class MailFetchingTests : IAsyncLifetime
insertedCopies.Select(mail => mail.FolderId).Should().BeEquivalentTo([_inboxFolder.Id, archiveFolder.Id]); insertedCopies.Select(mail => mail.FolderId).Should().BeEquivalentTo([_inboxFolder.Id, archiveFolder.Id]);
} }
[Fact]
public async Task UpdateMailAsync_PreservesLocalPinnedState()
{
var existingMail = BuildMail(_inboxFolder.Id, DateTime.UtcNow.AddHours(-1));
existingMail.IsPinned = true;
await _databaseService.Connection.InsertAsync(existingMail, typeof(MailCopy));
var refreshedMail = BuildMail(_inboxFolder.Id, DateTime.UtcNow, id: existingMail.Id);
refreshedMail.UniqueId = existingMail.UniqueId;
refreshedMail.FileId = existingMail.FileId;
refreshedMail.Subject = "Updated subject";
await _mailService.UpdateMailAsync(refreshedMail);
var storedMail = await _databaseService.Connection.FindAsync<MailCopy>(existingMail.UniqueId);
storedMail.Should().NotBeNull();
storedMail!.IsPinned.Should().BeTrue();
storedMail.Subject.Should().Be("Updated subject");
}
// ── Performance: 1 000 mails / ~70 threads ───────────────────────────────── // ── Performance: 1 000 mails / ~70 threads ─────────────────────────────────
/// <summary> /// <summary>
@@ -13,6 +13,8 @@ public sealed class MailRequestStateTests
[Fact] [Fact]
public void MarkReadRequest_RevertUiChanges_RestoresOriginalReadState() public void MarkReadRequest_RevertUiChanges_RestoresOriginalReadState()
{ {
WeakReferenceMessenger.Default.Reset();
var mailCopy = CreateMailCopy(isRead: false, isFlagged: false); var mailCopy = CreateMailCopy(isRead: false, isFlagged: false);
var request = new MarkReadRequest(mailCopy, IsRead: true); var request = new MarkReadRequest(mailCopy, IsRead: true);
var recipient = new MailRequestRecipient(); var recipient = new MailRequestRecipient();
@@ -27,20 +29,23 @@ public sealed class MailRequestStateTests
request.RevertUIChanges(); request.RevertUIChanges();
mailCopy.IsRead.Should().BeFalse(); mailCopy.IsRead.Should().BeFalse();
recipient.Updated.Should().HaveCount(2); recipient.StateUpdates.Should().HaveCount(2);
recipient.Updated[0].Source.Should().Be(EntityUpdateSource.ClientUpdated); recipient.StateUpdates[0].Source.Should().Be(EntityUpdateSource.ClientUpdated);
recipient.Updated[1].Source.Should().Be(EntityUpdateSource.ClientReverted); recipient.StateUpdates[1].Source.Should().Be(EntityUpdateSource.ClientReverted);
recipient.Updated[1].UpdatedMail.IsRead.Should().BeFalse(); recipient.StateUpdates[1].UpdatedState.IsRead.Should().BeFalse();
} }
finally finally
{ {
WeakReferenceMessenger.Default.UnregisterAll(recipient); WeakReferenceMessenger.Default.UnregisterAll(recipient);
WeakReferenceMessenger.Default.Reset();
} }
} }
[Fact] [Fact]
public void ChangeFlagRequest_RevertUiChanges_RestoresOriginalFlagState() public void ChangeFlagRequest_RevertUiChanges_RestoresOriginalFlagState()
{ {
WeakReferenceMessenger.Default.Reset();
var mailCopy = CreateMailCopy(isRead: true, isFlagged: false); var mailCopy = CreateMailCopy(isRead: true, isFlagged: false);
var request = new ChangeFlagRequest(mailCopy, IsFlagged: true); var request = new ChangeFlagRequest(mailCopy, IsFlagged: true);
var recipient = new MailRequestRecipient(); var recipient = new MailRequestRecipient();
@@ -55,14 +60,15 @@ public sealed class MailRequestStateTests
request.RevertUIChanges(); request.RevertUIChanges();
mailCopy.IsFlagged.Should().BeFalse(); mailCopy.IsFlagged.Should().BeFalse();
recipient.Updated.Should().HaveCount(2); recipient.StateUpdates.Should().HaveCount(2);
recipient.Updated[0].Source.Should().Be(EntityUpdateSource.ClientUpdated); recipient.StateUpdates[0].Source.Should().Be(EntityUpdateSource.ClientUpdated);
recipient.Updated[1].Source.Should().Be(EntityUpdateSource.ClientReverted); recipient.StateUpdates[1].Source.Should().Be(EntityUpdateSource.ClientReverted);
recipient.Updated[1].UpdatedMail.IsFlagged.Should().BeFalse(); recipient.StateUpdates[1].UpdatedState.IsFlagged.Should().BeFalse();
} }
finally finally
{ {
WeakReferenceMessenger.Default.UnregisterAll(recipient); WeakReferenceMessenger.Default.UnregisterAll(recipient);
WeakReferenceMessenger.Default.Reset();
} }
} }
@@ -76,10 +82,10 @@ public sealed class MailRequestStateTests
IsFlagged = isFlagged IsFlagged = isFlagged
}; };
internal sealed class MailRequestRecipient : IRecipient<MailUpdatedMessage> internal sealed class MailRequestRecipient : IRecipient<MailStateUpdatedMessage>
{ {
public List<MailUpdatedMessage> Updated { get; } = []; public List<MailStateUpdatedMessage> StateUpdates { get; } = [];
public void Receive(MailUpdatedMessage message) => Updated.Add(message); public void Receive(MailStateUpdatedMessage message) => StateUpdates.Add(message);
} }
} }
@@ -1,3 +1,4 @@
using CommunityToolkit.Mvvm.Messaging;
using FluentAssertions; using FluentAssertions;
using MimeKit; using MimeKit;
using Moq; using Moq;
@@ -8,6 +9,7 @@ using Wino.Core.Domain.Extensions;
using Wino.Core.Domain.Interfaces; using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.MailItem; using Wino.Core.Domain.Models.MailItem;
using Wino.Core.Tests.Helpers; using Wino.Core.Tests.Helpers;
using Wino.Messaging.UI;
using Wino.Services; using Wino.Services;
using Xunit; using Xunit;
@@ -229,6 +231,190 @@ public class MailThreadingTests : IAsyncLifetime
mimeMessage.ReplyTo.Mailboxes.Should().ContainSingle(m => m.Address == "support@test.local"); mimeMessage.ReplyTo.Mailboxes.Should().ContainSingle(m => m.Address == "support@test.local");
} }
[Fact]
public async Task ApplyMailStateUpdatesAsync_ForBatchReadStateChange_SendsBulkMailUpdatedMessage()
{
var mail1 = new MailCopy
{
UniqueId = Guid.NewGuid(),
Id = Guid.NewGuid().ToString(),
FolderId = _draftFolder.Id,
IsRead = true,
Subject = "First"
};
var mail2 = new MailCopy
{
UniqueId = Guid.NewGuid(),
Id = Guid.NewGuid().ToString(),
FolderId = _draftFolder.Id,
IsRead = true,
Subject = "Second"
};
await _databaseService.Connection.InsertAllAsync(new[] { mail1, mail2 }, typeof(MailCopy));
var recipient = new MailUpdateRecipient();
WeakReferenceMessenger.Default.Register<MailUpdatedMessage>(recipient);
WeakReferenceMessenger.Default.Register<BulkMailUpdatedMessage>(recipient);
try
{
await _mailService.ApplyMailStateUpdatesAsync(
[
new MailCopyStateUpdate(mail1.Id, IsRead: false),
new MailCopyStateUpdate(mail2.Id, IsRead: false)
]);
recipient.SingleUpdates.Should().BeEmpty();
recipient.BulkUpdates.Should().ContainSingle();
recipient.BulkUpdates[0].Source.Should().Be(EntityUpdateSource.Server);
recipient.BulkUpdates[0].ChangedProperties.Should().Be(MailCopyChangeFlags.IsRead);
recipient.BulkUpdates[0].UpdatedMails.Should().HaveCount(2);
recipient.BulkUpdates[0].UpdatedMails.Should().OnlyContain(x => !x.IsRead);
(await _databaseService.Connection.FindAsync<MailCopy>(mail1.UniqueId))!.IsRead.Should().BeFalse();
(await _databaseService.Connection.FindAsync<MailCopy>(mail2.UniqueId))!.IsRead.Should().BeFalse();
}
finally
{
WeakReferenceMessenger.Default.Unregister<MailUpdatedMessage>(recipient);
WeakReferenceMessenger.Default.Unregister<BulkMailUpdatedMessage>(recipient);
}
}
[Fact]
public async Task ApplyMailStateUpdatesAsync_ForBatchMarkRead_SendsBulkMailReadStatusChanged()
{
var mail1 = new MailCopy
{
UniqueId = Guid.NewGuid(),
Id = Guid.NewGuid().ToString(),
FolderId = _draftFolder.Id,
IsRead = false,
Subject = "First unread"
};
var mail2 = new MailCopy
{
UniqueId = Guid.NewGuid(),
Id = Guid.NewGuid().ToString(),
FolderId = _draftFolder.Id,
IsRead = false,
Subject = "Second unread"
};
await _databaseService.Connection.InsertAllAsync(new[] { mail1, mail2 }, typeof(MailCopy));
var recipient = new MailReadStatusRecipient();
WeakReferenceMessenger.Default.Register<MailReadStatusChanged>(recipient);
WeakReferenceMessenger.Default.Register<BulkMailReadStatusChanged>(recipient);
try
{
await _mailService.ApplyMailStateUpdatesAsync(
[
new MailCopyStateUpdate(mail1.Id, IsRead: true),
new MailCopyStateUpdate(mail2.Id, IsRead: true)
]);
recipient.SingleUpdates.Should().BeEmpty();
recipient.BulkUpdates.Should().ContainSingle();
recipient.BulkUpdates[0].UniqueIds.Should().BeEquivalentTo([mail1.UniqueId, mail2.UniqueId]);
}
finally
{
WeakReferenceMessenger.Default.Unregister<MailReadStatusChanged>(recipient);
WeakReferenceMessenger.Default.Unregister<BulkMailReadStatusChanged>(recipient);
}
}
[Fact]
public async Task ChangePinnedStatusAsync_SendsHydratedBulkMailUpdatedMessage()
{
var mail = new MailCopy
{
UniqueId = Guid.NewGuid(),
Id = Guid.NewGuid().ToString(),
FolderId = _draftFolder.Id,
IsPinned = false,
Subject = "Pinned draft"
};
await _databaseService.Connection.InsertAsync(mail, typeof(MailCopy));
var recipient = new MailUpdateRecipient();
WeakReferenceMessenger.Default.Register<MailUpdatedMessage>(recipient);
WeakReferenceMessenger.Default.Register<BulkMailUpdatedMessage>(recipient);
try
{
await _mailService.ChangePinnedStatusAsync([mail.UniqueId], true);
recipient.SingleUpdates.Should().BeEmpty();
recipient.BulkUpdates.Should().ContainSingle();
recipient.BulkUpdates[0].ChangedProperties.Should().Be(MailCopyChangeFlags.IsPinned);
recipient.BulkUpdates[0].UpdatedMails.Should().ContainSingle();
var updatedMail = recipient.BulkUpdates[0].UpdatedMails[0];
updatedMail.IsPinned.Should().BeTrue();
updatedMail.AssignedFolder.Should().NotBeNull();
updatedMail.AssignedFolder!.Id.Should().Be(_draftFolder.Id);
updatedMail.AssignedAccount.Should().NotBeNull();
updatedMail.AssignedAccount!.Id.Should().Be(_account.Id);
}
finally
{
WeakReferenceMessenger.Default.Unregister<MailUpdatedMessage>(recipient);
WeakReferenceMessenger.Default.Unregister<BulkMailUpdatedMessage>(recipient);
}
}
[Fact]
public async Task CreateAssignmentAsync_SendsHydratedMailAddedMessage()
{
var archiveFolder = new MailItemFolder
{
Id = Guid.NewGuid(),
MailAccountId = _account.Id,
FolderName = "Archive",
RemoteFolderId = "archive",
SpecialFolderType = SpecialFolderType.Archive,
IsSystemFolder = true,
IsSynchronizationEnabled = true
};
var mail = new MailCopy
{
UniqueId = Guid.NewGuid(),
Id = "assignment-mail",
FolderId = _draftFolder.Id,
Subject = "Assigned copy"
};
await _databaseService.Connection.InsertAsync(archiveFolder, typeof(MailItemFolder));
await _databaseService.Connection.InsertAsync(mail, typeof(MailCopy));
var recipient = new MailAddRecipient();
WeakReferenceMessenger.Default.Register<MailAddedMessage>(recipient);
try
{
await _mailService.CreateAssignmentAsync(_account.Id, mail.Id, archiveFolder.RemoteFolderId);
recipient.Added.Should().ContainSingle();
var addedMail = recipient.Added[0].AddedMail;
addedMail.UniqueId.Should().NotBe(mail.UniqueId);
addedMail.AssignedFolder.Should().NotBeNull();
addedMail.AssignedFolder!.Id.Should().Be(archiveFolder.Id);
addedMail.AssignedAccount.Should().NotBeNull();
addedMail.AssignedAccount!.Id.Should().Be(_account.Id);
}
finally
{
WeakReferenceMessenger.Default.Unregister<MailAddedMessage>(recipient);
}
}
private static MimeMessage CreateReferencedMimeMessage(string subject, string? messageId = null) private static MimeMessage CreateReferencedMimeMessage(string subject, string? messageId = null)
{ {
var message = new MimeMessage(); var message = new MimeMessage();
@@ -243,6 +429,31 @@ public class MailThreadingTests : IAsyncLifetime
return message; return message;
} }
internal sealed class MailUpdateRecipient : IRecipient<MailUpdatedMessage>, IRecipient<BulkMailUpdatedMessage>
{
public List<MailUpdatedMessage> SingleUpdates { get; } = [];
public List<BulkMailUpdatedMessage> BulkUpdates { get; } = [];
public void Receive(MailUpdatedMessage message) => SingleUpdates.Add(message);
public void Receive(BulkMailUpdatedMessage message) => BulkUpdates.Add(message);
}
internal sealed class MailAddRecipient : IRecipient<MailAddedMessage>
{
public List<MailAddedMessage> Added { get; } = [];
public void Receive(MailAddedMessage message) => Added.Add(message);
}
internal sealed class MailReadStatusRecipient : IRecipient<MailReadStatusChanged>, IRecipient<BulkMailReadStatusChanged>
{
public List<MailReadStatusChanged> SingleUpdates { get; } = [];
public List<BulkMailReadStatusChanged> BulkUpdates { get; } = [];
public void Receive(MailReadStatusChanged message) => SingleUpdates.Add(message);
public void Receive(BulkMailReadStatusChanged message) => BulkUpdates.Add(message);
}
private static MailService BuildMailService(InMemoryDatabaseService db) private static MailService BuildMailService(InMemoryDatabaseService db)
{ {
var signatureService = new Mock<ISignatureService>(); var signatureService = new Mock<ISignatureService>();
@@ -0,0 +1,41 @@
using FluentAssertions;
using Wino.Core.Domain.Entities.Shared;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Models.Accounts;
using Wino.Services;
using Xunit;
namespace Wino.Core.Tests.Services;
public class SpecialImapProviderConfigResolverTests
{
[Fact]
public void GetServerInformation_ICloud_UsesMailboxLocalPartForIncomingAndOutgoingUsernames()
{
var sut = new SpecialImapProviderConfigResolver();
var account = new MailAccount
{
Id = Guid.NewGuid(),
Address = "tester@icloud.com"
};
var dialogResult = new AccountCreationDialogResult(
MailProviderType.IMAP4,
"iCloud",
new SpecialImapProviderDetails(
"tester@icloud.com",
"app-password",
"Tester",
SpecialImapProvider.iCloud,
ImapCalendarSupportMode.CalDav),
"#0078D4",
InitialSynchronizationRange.SixMonths,
true,
true);
var serverInformation = sut.GetServerInformation(account, dialogResult);
serverInformation.IncomingServerUsername.Should().Be("tester");
serverInformation.OutgoingServerUsername.Should().Be("tester");
serverInformation.CalDavUsername.Should().Be("tester@icloud.com");
}
}
@@ -0,0 +1,24 @@
using FluentAssertions;
using Wino.Core.Domain.Enums;
using Wino.Services;
using Xunit;
namespace Wino.Core.Tests.Services;
public class TranslationServiceTests
{
[Theory]
[InlineData("pl-PL", AppLanguage.Polish)]
[InlineData("de-AT", AppLanguage.Deutsch)]
[InlineData("pt-PT", AppLanguage.PortugeseBrazil)]
[InlineData("zh-TW", AppLanguage.Chinese)]
[InlineData("tr_TR", AppLanguage.Turkish)]
[InlineData("ko-KR", AppLanguage.Korean)]
[InlineData("nl-NL", AppLanguage.English)]
public void ResolveSupportedLanguage_ReturnsExpectedLanguage(string languageTag, AppLanguage expectedLanguage)
{
var result = TranslationService.ResolveSupportedLanguage([languageTag]);
result.Should().Be(expectedLanguage);
}
}
@@ -0,0 +1,87 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.Messaging;
using FluentAssertions;
using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Entities.Shared;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Requests.Bundles;
using Wino.Core.Requests.Mail;
using Wino.Core.Synchronizers;
using Wino.Messaging.UI;
using Xunit;
namespace Wino.Core.Tests.Synchronizers;
public sealed class BaseSynchronizerUiChangeTests
{
[Fact]
public void ApplyOptimisticUiChanges_UsesBundleUiChangeRequest_ForBatchBundle()
{
WeakReferenceMessenger.Default.Reset();
var folderId = Guid.NewGuid();
var account = new MailAccount { Id = Guid.NewGuid(), Name = "Test account" };
var synchronizer = new TestSynchronizer(account);
var recipient = new UiChangeRecipient();
var request1 = new MarkReadRequest(CreateMailCopy(folderId, isRead: false), IsRead: true);
var request2 = new MarkReadRequest(CreateMailCopy(folderId, isRead: false), IsRead: true);
var batchRequest = new BatchMarkReadRequest([request1, request2]);
var bundle = new HttpRequestBundle<object>(new object(), batchRequest, request1);
WeakReferenceMessenger.Default.Register<MailStateUpdatedMessage>(recipient);
WeakReferenceMessenger.Default.Register<BulkMailStateUpdatedMessage>(recipient);
try
{
synchronizer.ApplyUiChanges([bundle]);
recipient.SingleUpdates.Should().BeEmpty();
recipient.BulkUpdates.Should().ContainSingle();
recipient.BulkUpdates[0].UpdatedStates.Should().HaveCount(2);
request1.Item.IsRead.Should().BeFalse();
request2.Item.IsRead.Should().BeFalse();
}
finally
{
WeakReferenceMessenger.Default.Unregister<MailStateUpdatedMessage>(recipient);
WeakReferenceMessenger.Default.Unregister<BulkMailStateUpdatedMessage>(recipient);
WeakReferenceMessenger.Default.Reset();
}
}
private static MailCopy CreateMailCopy(Guid folderId, bool isRead) =>
new()
{
UniqueId = Guid.NewGuid(),
Id = Guid.NewGuid().ToString(),
FolderId = folderId,
IsRead = isRead
};
private sealed class TestSynchronizer : BaseSynchronizer<object>
{
public TestSynchronizer(MailAccount account)
: base(account, WeakReferenceMessenger.Default)
{
}
public void ApplyUiChanges(List<IRequestBundle<object>> bundles) => ApplyOptimisticUiChanges(bundles);
public override Task ExecuteNativeRequestsAsync(List<IRequestBundle<object>> batchedRequests, CancellationToken cancellationToken = default)
=> Task.CompletedTask;
}
internal sealed class UiChangeRecipient : IRecipient<MailStateUpdatedMessage>, IRecipient<BulkMailStateUpdatedMessage>
{
public List<MailStateUpdatedMessage> SingleUpdates { get; } = [];
public List<BulkMailStateUpdatedMessage> BulkUpdates { get; } = [];
public void Receive(MailStateUpdatedMessage message) => SingleUpdates.Add(message);
public void Receive(BulkMailStateUpdatedMessage message) => BulkUpdates.Add(message);
}
}
@@ -0,0 +1,262 @@
using System.Reflection;
using System.IO;
using System.Xml.Linq;
using FluentAssertions;
using Moq;
using Wino.Core.Domain.Entities.Calendar;
using Wino.Core.Domain.Entities.Shared;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Calendar;
using Wino.Core.Integration.Processors;
using Wino.Core.Misc;
using Wino.Core.Synchronizers.ImapSync;
using Wino.Core.Synchronizers.Mail;
using Wino.Services;
using Xunit;
namespace Wino.Core.Tests.Synchronizers;
public class CalDavCalendarMetadataTests
{
[Fact]
public void ParseCalendarCollection_MapsCollectionMetadataAndSkipsNonEventCalendars()
{
var xml = XDocument.Parse(
"""
<D:multistatus xmlns:D="DAV:" xmlns:C="urn:ietf:params:xml:ns:caldav" xmlns:CS="http://calendarserver.org/ns/" xmlns:ICAL="http://apple.com/ns/ical/">
<D:response>
<D:href>/calendars/work/</D:href>
<D:propstat>
<D:status>HTTP/1.1 200 OK</D:status>
<D:prop>
<D:resourcetype>
<D:collection />
<C:calendar />
</D:resourcetype>
<D:displayname>Work</D:displayname>
<C:calendar-description>Team calendar</C:calendar-description>
<CS:getctag>"ctag-1"</CS:getctag>
<D:sync-token>sync-1</D:sync-token>
<D:current-user-privilege-set>
<D:privilege>
<D:read />
</D:privilege>
</D:current-user-privilege-set>
<C:calendar-timezone><![CDATA[
BEGIN:VCALENDAR
BEGIN:VTIMEZONE
TZID:Europe/Warsaw
END:VTIMEZONE
END:VCALENDAR
]]></C:calendar-timezone>
<C:supported-calendar-component-set>
<C:comp name="VEVENT" />
<C:comp name="VTODO" />
</C:supported-calendar-component-set>
<C:schedule-calendar-transp>
<C:transparent />
</C:schedule-calendar-transp>
<ICAL:calendar-color>#5b617aff</ICAL:calendar-color>
<ICAL:calendar-order>2</ICAL:calendar-order>
</D:prop>
</D:propstat>
</D:response>
<D:response>
<D:href>/calendars/tasks/</D:href>
<D:propstat>
<D:status>HTTP/1.1 200 OK</D:status>
<D:prop>
<D:resourcetype>
<D:collection />
<C:calendar />
</D:resourcetype>
<D:displayname>Tasks</D:displayname>
<C:supported-calendar-component-set>
<C:comp name="VTODO" />
</C:supported-calendar-component-set>
</D:prop>
</D:propstat>
</D:response>
</D:multistatus>
""");
var calendars = ParseCalendars(xml, new Uri("https://calendar.example.com/"));
calendars.Should().ContainSingle();
var calendar = calendars[0];
calendar.RemoteCalendarId.Should().Be("https://calendar.example.com/calendars/work");
calendar.Name.Should().Be("Work");
calendar.Description.Should().Be("Team calendar");
calendar.CTag.Should().Be("\"ctag-1\"");
calendar.SyncToken.Should().Be("sync-1");
calendar.TimeZone.Should().Be("Europe/Warsaw");
calendar.BackgroundColorHex.Should().Be("#5B617A");
calendar.IsReadOnly.Should().BeTrue();
calendar.SupportsEvents.Should().BeTrue();
calendar.DefaultShowAs.Should().Be(CalendarItemShowAs.Free);
calendar.Order.Should().Be(2d);
}
[Fact]
public async Task SynchronizeCalendarMetadataAsync_UpdatesServerBackedSettingsAndPreservesUserColorOverride()
{
var tempDirectory = CreateTempDirectory();
var serverInformation = new CustomServerInformation
{
Id = Guid.NewGuid(),
IncomingServer = "imap.example.com",
IncomingServerPort = "993",
IncomingServerUsername = "user@example.com",
IncomingServerPassword = "password",
OutgoingServer = "smtp.example.com",
OutgoingServerPort = "587",
OutgoingServerUsername = "user@example.com",
OutgoingServerPassword = "password",
MaxConcurrentClients = 5,
CalendarSupportMode = ImapCalendarSupportMode.CalDav
};
var account = new MailAccount
{
Id = Guid.NewGuid(),
Name = "IMAP Test",
Address = "test@example.com",
ProviderType = MailProviderType.IMAP4,
IsCalendarAccessGranted = true,
ServerInformation = serverInformation
};
var localCalendar = new AccountCalendar
{
Id = Guid.NewGuid(),
AccountId = account.Id,
RemoteCalendarId = "https://calendar.example.com/calendars/work",
Name = "Local",
BackgroundColorHex = "#123456",
TextColorHex = "#FFFFFF",
IsBackgroundColorUserOverridden = true,
TimeZone = "UTC",
IsReadOnly = false,
DefaultShowAs = CalendarItemShowAs.Busy
};
var changeProcessor = new Mock<IImapChangeProcessor>();
changeProcessor
.Setup(x => x.GetAccountCalendarsAsync(account.Id))
.ReturnsAsync(new List<AccountCalendar> { localCalendar });
changeProcessor
.Setup(x => x.UpdateAccountCalendarAsync(It.IsAny<AccountCalendar>()))
.Returns(Task.CompletedTask);
changeProcessor
.Setup(x => x.DeleteCalendarIcsForCalendarAsync(It.IsAny<Guid>(), It.IsAny<Guid>()))
.Returns(Task.CompletedTask);
changeProcessor
.Setup(x => x.DeleteAccountCalendarAsync(It.IsAny<AccountCalendar>()))
.Returns(Task.CompletedTask);
changeProcessor
.Setup(x => x.InsertAccountCalendarAsync(It.IsAny<AccountCalendar>()))
.Returns(Task.CompletedTask);
var synchronizer = CreateSynchronizer(tempDirectory, account, changeProcessor.Object);
try
{
await InvokePrivateAsync(
synchronizer,
"SynchronizeCalendarMetadataAsync",
new List<CalDavCalendar>
{
new()
{
RemoteCalendarId = localCalendar.RemoteCalendarId,
Name = "Remote",
TimeZone = "Europe/Warsaw",
BackgroundColorHex = "#ABCDEF",
IsReadOnly = true,
DefaultShowAs = CalendarItemShowAs.Free,
Order = 0
}
});
localCalendar.Name.Should().Be("Remote");
localCalendar.TimeZone.Should().Be("Europe/Warsaw");
localCalendar.IsReadOnly.Should().BeTrue();
localCalendar.DefaultShowAs.Should().Be(CalendarItemShowAs.Free);
localCalendar.IsPrimary.Should().BeTrue();
localCalendar.BackgroundColorHex.Should().Be("#123456");
localCalendar.TextColorHex.Should().Be(ColorHelpers.GetReadableTextColorHex("#123456"));
changeProcessor.Verify(x => x.UpdateAccountCalendarAsync(localCalendar), Times.Once);
changeProcessor.Verify(x => x.InsertAccountCalendarAsync(It.IsAny<AccountCalendar>()), Times.Never);
changeProcessor.Verify(x => x.DeleteAccountCalendarAsync(It.IsAny<AccountCalendar>()), Times.Never);
}
finally
{
await synchronizer.KillSynchronizerAsync();
DeleteDirectory(tempDirectory);
}
}
private static List<CalDavCalendar> ParseCalendars(XDocument xml, Uri baseUri)
{
var parseMethod = typeof(CalDavClient).GetMethod(
"ParseCalendarCollection",
BindingFlags.NonPublic | BindingFlags.Static);
parseMethod.Should().NotBeNull();
var result = parseMethod!.Invoke(null, [xml, baseUri]);
return result.Should().BeOfType<List<CalDavCalendar>>().Subject;
}
private static ImapSynchronizer CreateSynchronizer(string appDataFolder, MailAccount account, IImapChangeProcessor changeProcessor)
{
var applicationConfiguration = new Mock<IApplicationConfiguration>();
applicationConfiguration.SetupProperty(x => x.ApplicationDataFolderPath, appDataFolder);
applicationConfiguration.SetupProperty(x => x.PublisherSharedFolderPath, appDataFolder);
applicationConfiguration.SetupProperty(x => x.ApplicationTempFolderPath, appDataFolder);
applicationConfiguration.SetupGet(x => x.SentryDNS).Returns(string.Empty);
var unifiedSynchronizer = new UnifiedImapSynchronizer(
Mock.Of<IFolderService>(),
Mock.Of<IMailService>(),
Mock.Of<IImapSynchronizerErrorHandlerFactory>());
return new ImapSynchronizer(
account,
changeProcessor,
applicationConfiguration.Object,
unifiedSynchronizer,
Mock.Of<IImapSynchronizerErrorHandlerFactory>(),
Mock.Of<ICalDavClient>(),
Mock.Of<IAutoDiscoveryService>(),
Mock.Of<ICalendarService>());
}
private static string CreateTempDirectory()
{
var path = Path.Combine(Path.GetTempPath(), "wino-caldav-calendar-tests", Guid.NewGuid().ToString("N"));
Directory.CreateDirectory(path);
return path;
}
private static void DeleteDirectory(string path)
{
if (Directory.Exists(path))
{
Directory.Delete(path, recursive: true);
}
}
private static async Task InvokePrivateAsync(object instance, string methodName, params object[] parameters)
{
var method = instance.GetType().GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance)
?? throw new InvalidOperationException($"Method '{methodName}' not found.");
var task = (Task)method.Invoke(instance, parameters)!;
await task.ConfigureAwait(false);
}
}
@@ -19,6 +19,32 @@ namespace Wino.Core.Tests.Synchronizers;
public sealed class GmailSynchronizerRequestSuccessTests public sealed class GmailSynchronizerRequestSuccessTests
{ {
[Fact]
public async Task UpdateAccountSyncIdentifierAsync_EmptyStoredIdentifier_PersistsFirstHistoryCursor()
{
var changeProcessor = new Mock<IGmailChangeProcessor>(MockBehavior.Strict);
changeProcessor
.Setup(x => x.UpdateAccountDeltaSynchronizationIdentifierAsync(It.IsAny<Guid>(), "123"))
.ReturnsAsync("123");
var synchronizer = CreateSynchronizer(changeProcessor.Object, synchronizationDeltaIdentifier: string.Empty);
await InvokeUpdateAccountSyncIdentifierAsync(synchronizer, 123);
changeProcessor.Verify(x => x.UpdateAccountDeltaSynchronizationIdentifierAsync(It.IsAny<Guid>(), "123"), Times.Once);
}
[Fact]
public async Task UpdateAccountSyncIdentifierAsync_OlderHistoryCursor_DoesNotRegressStoredCursor()
{
var changeProcessor = new Mock<IGmailChangeProcessor>(MockBehavior.Strict);
var synchronizer = CreateSynchronizer(changeProcessor.Object, synchronizationDeltaIdentifier: "456");
await InvokeUpdateAccountSyncIdentifierAsync(synchronizer, 123);
changeProcessor.Verify(x => x.UpdateAccountDeltaSynchronizationIdentifierAsync(It.IsAny<Guid>(), It.IsAny<string>()), Times.Never);
}
[Fact] [Fact]
public async Task ProcessSingleNativeRequestResponseAsync_BatchMarkReadRequest_PersistsLocalReadStateForEachMail() public async Task ProcessSingleNativeRequestResponseAsync_BatchMarkReadRequest_PersistsLocalReadStateForEachMail()
{ {
@@ -209,13 +235,15 @@ public sealed class GmailSynchronizerRequestSuccessTests
private static GmailSynchronizer CreateSynchronizer( private static GmailSynchronizer CreateSynchronizer(
IGmailChangeProcessor changeProcessor, IGmailChangeProcessor changeProcessor,
IGmailSynchronizerErrorHandlerFactory? errorFactory = null) IGmailSynchronizerErrorHandlerFactory? errorFactory = null,
string? synchronizationDeltaIdentifier = null)
{ {
var account = new MailAccount var account = new MailAccount
{ {
Id = Guid.NewGuid(), Id = Guid.NewGuid(),
Name = "Gmail", Name = "Gmail",
Address = "user@example.com" Address = "user@example.com",
SynchronizationDeltaIdentifier = synchronizationDeltaIdentifier
}; };
var authenticator = new Mock<IGmailAuthenticator>(MockBehavior.Loose); var authenticator = new Mock<IGmailAuthenticator>(MockBehavior.Loose);
@@ -249,4 +277,17 @@ public sealed class GmailSynchronizerRequestSuccessTests
task.Should().NotBeNull(); task.Should().NotBeNull();
await task!; await task!;
} }
private static async Task InvokeUpdateAccountSyncIdentifierAsync(GmailSynchronizer synchronizer, ulong historyId)
{
var method = typeof(GmailSynchronizer).GetMethod(
"UpdateAccountSyncIdentifierAsync",
BindingFlags.Instance | BindingFlags.NonPublic);
method.Should().NotBeNull();
var task = method!.Invoke(synchronizer, [historyId]) as Task;
task.Should().NotBeNull();
await task!;
}
} }
@@ -2,12 +2,14 @@ using FluentAssertions;
using MailKit; using MailKit;
using MailKit.Net.Imap; using MailKit.Net.Imap;
using Moq; using Moq;
using System.Linq;
using System.Reflection; using System.Reflection;
using Wino.Core.Domain.Entities.Mail; using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Entities.Shared; using Wino.Core.Domain.Entities.Shared;
using Wino.Core.Domain.Interfaces; using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.MailItem; using Wino.Core.Domain.Models.MailItem;
using Wino.Core.Synchronizers.ImapSync; using Wino.Core.Synchronizers.ImapSync;
using Wino.Services.Extensions;
using Xunit; using Xunit;
using IMailService = Wino.Core.Domain.Interfaces.IMailService; using IMailService = Wino.Core.Domain.Interfaces.IMailService;
@@ -223,4 +225,61 @@ public class UnifiedImapSynchronizerTests
capturedPackage.Should().NotBeNull(); capturedPackage.Should().NotBeNull();
capturedPackage!.MimeMessage.Should().BeNull(); capturedPackage!.MimeMessage.Should().BeNull();
} }
[Fact]
public async Task ProcessSummariesAsync_ShouldBatchStateUpdates_ForExistingMailCopies()
{
var localFolder = new MailItemFolder
{
Id = Guid.NewGuid(),
MailAccountId = Guid.NewGuid(),
FolderName = "Inbox",
RemoteFolderId = "INBOX"
};
var summaryMock = new Mock<IMessageSummary>();
summaryMock.SetupGet(x => x.UniqueId).Returns(new UniqueId(42));
summaryMock.SetupGet(x => x.Flags).Returns(MessageFlags.Seen | MessageFlags.Flagged);
var existingMailCopy = new MailCopy
{
Id = MailkitClientExtensions.CreateUid(localFolder.Id, 42),
IsRead = false,
IsFlagged = false
};
var mailServiceMock = new Mock<IMailService>();
mailServiceMock
.Setup(x => x.GetExistingMailsAsync(localFolder.Id, It.IsAny<IEnumerable<UniqueId>>()))
.ReturnsAsync([existingMailCopy]);
mailServiceMock
.Setup(x => x.ApplyMailStateUpdatesAsync(It.IsAny<IEnumerable<MailCopyStateUpdate>>()))
.Returns(Task.CompletedTask);
var sut = new UnifiedImapSynchronizer(
Mock.Of<IFolderService>(),
mailServiceMock.Object,
Mock.Of<IImapSynchronizerErrorHandlerFactory>());
var imapSynchronizerMock = new Mock<IImapSynchronizer>();
var processMethod = typeof(UnifiedImapSynchronizer).GetMethod("ProcessSummariesAsync", BindingFlags.Instance | BindingFlags.NonPublic);
processMethod.Should().NotBeNull();
var task = (Task<List<string>>)processMethod!.Invoke(
sut,
[imapSynchronizerMock.Object, localFolder, new List<IMessageSummary> { summaryMock.Object }, CancellationToken.None])!;
var result = await task;
result.Should().BeEmpty();
mailServiceMock.Verify(
x => x.ApplyMailStateUpdatesAsync(It.Is<IEnumerable<MailCopyStateUpdate>>(updates =>
updates.Count() == 1
&& updates.First().MailCopyId == existingMailCopy.Id
&& updates.First().IsRead == true
&& updates.First().IsFlagged == true)),
Times.Once);
mailServiceMock.Verify(x => x.CreateMailAsync(It.IsAny<Guid>(), It.IsAny<NewMailItemPackage>()), Times.Never);
}
} }
@@ -10,6 +10,7 @@ using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces; using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.MailItem; using Wino.Core.Domain.Models.MailItem;
using Wino.Core.Domain.Models.Synchronization; using Wino.Core.Domain.Models.Synchronization;
using Wino.Core.Requests.Mail;
using Wino.Core.Requests.Folder; using Wino.Core.Requests.Folder;
using Wino.Core.Synchronizers; using Wino.Core.Synchronizers;
using Xunit; using Xunit;
@@ -49,6 +50,38 @@ public sealed class WinoSynchronizerMailRequestTests
synchronizer.ExecuteNativeRequestsInvocationCount.Should().Be(1); synchronizer.ExecuteNativeRequestsInvocationCount.Should().Be(1);
} }
[Fact]
public async Task ExecuteRequests_should_dispatch_grouped_mark_read_requests_with_composite_grouping_key()
{
var synchronizer = new TestMailSynchronizer();
var folderId = Guid.NewGuid();
synchronizer.QueueRequest(new MarkReadRequest(new MailCopy
{
UniqueId = Guid.NewGuid(),
Id = Guid.NewGuid().ToString(),
FolderId = folderId
}, IsRead: true));
synchronizer.QueueRequest(new MarkReadRequest(new MailCopy
{
UniqueId = Guid.NewGuid(),
Id = Guid.NewGuid().ToString(),
FolderId = folderId
}, IsRead: true));
var result = await synchronizer.SynchronizeMailsAsync(new MailSynchronizationOptions
{
AccountId = synchronizer.Account.Id,
Type = MailSynchronizationType.ExecuteRequests
});
result.CompletedState.Should().Be(SynchronizationCompletedState.Success);
synchronizer.MarkReadInvocationCount.Should().Be(1);
synchronizer.LastMarkReadBatchCount.Should().Be(2);
synchronizer.ExecuteNativeRequestsInvocationCount.Should().Be(1);
}
private sealed class TestMailSynchronizer private sealed class TestMailSynchronizer
: WinoSynchronizer<object, object, object> : WinoSynchronizer<object, object, object>
{ {
@@ -60,6 +93,8 @@ public sealed class WinoSynchronizerMailRequestTests
public override uint BatchModificationSize => 1; public override uint BatchModificationSize => 1;
public override uint InitialMessageDownloadCountPerFolder => 0; public override uint InitialMessageDownloadCountPerFolder => 0;
public int CreateRootFolderInvocationCount { get; private set; } public int CreateRootFolderInvocationCount { get; private set; }
public int MarkReadInvocationCount { get; private set; }
public int LastMarkReadBatchCount { get; private set; }
public int ExecuteNativeRequestsInvocationCount { get; private set; } public int ExecuteNativeRequestsInvocationCount { get; private set; }
public override List<IRequestBundle<object>> CreateRootFolder(CreateRootFolderRequest request) public override List<IRequestBundle<object>> CreateRootFolder(CreateRootFolderRequest request)
@@ -68,6 +103,13 @@ public sealed class WinoSynchronizerMailRequestTests
return [new TestRequestBundle(new object(), request)]; return [new TestRequestBundle(new object(), request)];
} }
public override List<IRequestBundle<object>> MarkRead(BatchMarkReadRequest request)
{
MarkReadInvocationCount++;
LastMarkReadBatchCount = request.Count;
return [new TestRequestBundle(new object(), request[0])];
}
public override Task ExecuteNativeRequestsAsync(List<IRequestBundle<object>> batchedRequests, CancellationToken cancellationToken = default) public override Task ExecuteNativeRequestsAsync(List<IRequestBundle<object>> batchedRequests, CancellationToken cancellationToken = default)
{ {
ExecuteNativeRequestsInvocationCount++; ExecuteNativeRequestsInvocationCount++;
@@ -1,6 +1,7 @@
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Collections.Generic;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging; using CommunityToolkit.Mvvm.Messaging;
@@ -9,6 +10,7 @@ using Wino.Core.Domain.Entities.Shared;
using Wino.Core.Domain.Enums; using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces; using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Navigation; using Wino.Core.Domain.Models.Navigation;
using Wino.Core.ViewModels.Data;
using Wino.Mail.ViewModels.Data; using Wino.Mail.ViewModels.Data;
using Wino.Messaging.Client.Navigation; using Wino.Messaging.Client.Navigation;
@@ -17,6 +19,7 @@ namespace Wino.Core.ViewModels;
public abstract partial class AccountManagementPageViewModelBase : CoreBaseViewModel public abstract partial class AccountManagementPageViewModelBase : CoreBaseViewModel
{ {
public ObservableCollection<IAccountProviderDetailViewModel> Accounts { get; set; } = []; public ObservableCollection<IAccountProviderDetailViewModel> Accounts { get; set; } = [];
public IEnumerable<IAccountProviderDetailViewModel> StartupAccounts => Accounts.Where(IsStartupEligible);
public bool IsPurchasePanelVisible => !HasUnlimitedAccountProduct; public bool IsPurchasePanelVisible => !HasUnlimitedAccountProduct;
public bool IsAccountCreationAlmostOnLimit => Accounts != null && Accounts.Count == FREE_ACCOUNT_COUNT - 1; public bool IsAccountCreationAlmostOnLimit => Accounts != null && Accounts.Count == FREE_ACCOUNT_COUNT - 1;
@@ -130,10 +133,21 @@ public abstract partial class AccountManagementPageViewModelBase : CoreBaseViewM
private void AccountsChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) private void AccountsChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{ {
OnPropertyChanged(nameof(HasAccountsDefined)); OnPropertyChanged(nameof(HasAccountsDefined));
OnPropertyChanged(nameof(StartupAccounts));
} }
private static string GetAccountDetailsTitle(MailAccount account) private static string GetAccountDetailsTitle(MailAccount account)
=> !string.IsNullOrWhiteSpace(account?.Address) => !string.IsNullOrWhiteSpace(account?.Address)
? string.Format(Translator.SettingsAccountDetails_NavigationTitle, account.Address) ? string.Format(Translator.SettingsAccountDetails_NavigationTitle, account.Address)
: account?.Name ?? Translator.AccountDetailsPage_Title; : account?.Name ?? Translator.AccountDetailsPage_Title;
private static bool IsStartupEligible(IAccountProviderDetailViewModel account)
{
return account switch
{
AccountProviderDetailViewModel accountViewModel => accountViewModel.Account.IsMailAccessGranted,
MergedAccountProviderDetailViewModel mergedAccountViewModel => mergedAccountViewModel.HoldingAccounts.Any(a => a.Account.IsMailAccessGranted),
_ => true
};
}
} }
@@ -1,5 +1,6 @@
using System; using System;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using Wino.Core.Domain;
using Wino.Core.Domain.Entities.Shared; using Wino.Core.Domain.Entities.Shared;
using Wino.Core.Domain.Interfaces; using Wino.Core.Domain.Interfaces;
@@ -9,6 +10,8 @@ public partial class AccountProviderDetailViewModel : ObservableObject, IAccount
{ {
[ObservableProperty] [ObservableProperty]
[NotifyPropertyChangedFor(nameof(CapabilitySummary))]
[NotifyPropertyChangedFor(nameof(DescriptionText))]
private MailAccount account; private MailAccount account;
public IProviderDetail ProviderDetail { get; set; } public IProviderDetail ProviderDetail { get; set; }
@@ -20,6 +23,10 @@ public partial class AccountProviderDetailViewModel : ObservableObject, IAccount
public int Order => Account.Order; public int Order => Account.Order;
public string StartupEntityAddresses => Account.Address; public string StartupEntityAddresses => Account.Address;
public string CapabilitySummary => BuildCapabilitySummary(Account);
public string DescriptionText => string.IsNullOrWhiteSpace(Account.Address)
? CapabilitySummary
: $"{CapabilitySummary} | {Account.Address}";
public int HoldingAccountCount => 1; public int HoldingAccountCount => 1;
@@ -30,4 +37,15 @@ public partial class AccountProviderDetailViewModel : ObservableObject, IAccount
ProviderDetail = providerDetail; ProviderDetail = providerDetail;
Account = account; Account = account;
} }
private static string BuildCapabilitySummary(MailAccount account)
{
if (account?.IsMailAccessGranted == true && account.IsCalendarAccessGranted)
return Translator.AccountCapability_MailAndCalendar;
if (account?.IsMailAccessGranted == true)
return Translator.AccountCapability_MailOnly;
return Translator.AccountCapability_CalendarOnly;
}
} }
@@ -389,6 +389,24 @@ public partial class PersonalizationPageViewModel : CoreBaseViewModel
public bool HasReadReceiptTracking { get; } = false; public bool HasReadReceiptTracking { get; } = false;
public bool IsReadReceiptAcknowledged { get; } = false; public bool IsReadReceiptAcknowledged { get; } = false;
public string ReadReceiptDisplayText { get; } = string.Empty; public string ReadReceiptDisplayText { get; } = string.Empty;
public IReadOnlyList<MailCategory> Categories { get; } =
[
new()
{
Id = Guid.NewGuid(),
Name = "Follow Up",
BackgroundColorHex = "#DCEBFF",
TextColorHex = "#0B5CAD"
},
new()
{
Id = Guid.NewGuid(),
Name = "Planning",
BackgroundColorHex = "#DDF5D7",
TextColorHex = "#236A1E"
}
];
public bool HasCategories => Categories.Count > 0;
public AccountContact SenderContact { get; } = null; public AccountContact SenderContact { get; } = null;
event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged
{ {
@@ -160,7 +160,10 @@ public partial class SettingOptionsPageViewModel : CoreBaseViewModel
public void NavigateToAddAccount() public void NavigateToAddAccount()
{ {
Messenger.Send(new BreadcrumbNavigationRequested(Translator.SettingsManageAccountSettings_Title, WinoPage.ManageAccountsPage)); Messenger.Send(new BreadcrumbNavigationRequested(Translator.SettingsManageAccountSettings_Title, WinoPage.ManageAccountsPage));
Messenger.Send(new BreadcrumbNavigationRequested(Translator.WelcomeWizard_Step2Title, WinoPage.ProviderSelectionPage)); Messenger.Send(new BreadcrumbNavigationRequested(
Translator.WelcomeWizard_Step2Title,
WinoPage.ProviderSelectionPage,
ProviderSelectionNavigationContext.CreateForSettingsAddAccount()));
} }
public void NavigateToManageAccounts() public void NavigateToManageAccounts()
@@ -571,6 +571,19 @@ public partial class WinoAccountManagementPageViewModel : CoreBaseViewModel,
} }
var aiStatus = aiStatusResponse.Result; var aiStatus = aiStatusResponse.Result;
if (IsExpiredAiEntitlement(aiStatus.EntitlementStatus))
{
await ExecuteUIThread(() =>
{
_aiPackAddOn.IsPurchased = false;
_aiPackAddOn.HasUsageData = false;
_aiPackAddOn.ErrorText = string.Empty;
_aiPackAddOn.RenewalText = string.Empty;
_aiPackAddOn.UsageResetText = string.Empty;
});
return;
}
if (aiStatus.MonthlyLimit is not int usageLimit || usageLimit <= 0 || aiStatus.Used is not int usageCount) if (aiStatus.MonthlyLimit is not int usageLimit || usageLimit <= 0 || aiStatus.Used is not int usageCount)
{ {
await ExecuteUIThread(() => await ExecuteUIThread(() =>
@@ -613,4 +626,7 @@ public partial class WinoAccountManagementPageViewModel : CoreBaseViewModel,
}); });
} }
} }
private static bool IsExpiredAiEntitlement(string? entitlementStatus)
=> string.Equals(entitlementStatus, "Expired", StringComparison.OrdinalIgnoreCase);
} }
+8 -3
View File
@@ -58,6 +58,7 @@ public class ImapClientPool : IDisposable
private readonly int _targetMinimumConnections; private readonly int _targetMinimumConnections;
private DateTime _lastKeepAliveSentUtc = DateTime.MinValue; private DateTime _lastKeepAliveSentUtc = DateTime.MinValue;
private Exception _lastConnectionException;
private WinoImapClient _dedicatedIdleClient; private WinoImapClient _dedicatedIdleClient;
private bool _disposedValue; private bool _disposedValue;
private bool _initialized; private bool _initialized;
@@ -114,7 +115,7 @@ public class ImapClientPool : IDisposable
var initialClient = await CreateAndConnectClientAsync(cancellationToken).ConfigureAwait(false); var initialClient = await CreateAndConnectClientAsync(cancellationToken).ConfigureAwait(false);
if (initialClient == null) if (initialClient == null)
{ {
throw CreatePoolException("Failed to create initial IMAP connection for the pool."); throw CreatePoolException("Failed to create initial IMAP connection for the pool.", _lastConnectionException);
} }
_clientStates[initialClient] = ImapClientState.Available; _clientStates[initialClient] = ImapClientState.Available;
@@ -192,6 +193,7 @@ public class ImapClientPool : IDisposable
} }
catch (Exception ex) catch (Exception ex)
{ {
_lastConnectionException = ex;
_logger.Warning(ex, "Pooled IMAP client was not ready. Marking as failed."); _logger.Warning(ex, "Pooled IMAP client was not ready. Marking as failed.");
MarkClientAsFailed(pooledClient); MarkClientAsFailed(pooledClient);
} }
@@ -215,12 +217,12 @@ public class ImapClientPool : IDisposable
} }
catch (OperationCanceledException) when (!cancellationToken.IsCancellationRequested) catch (OperationCanceledException) when (!cancellationToken.IsCancellationRequested)
{ {
throw CreatePoolException($"Timed out while acquiring an IMAP client after {timeout.TotalSeconds:F1} seconds. Failures: {createFailures}."); throw CreatePoolException($"Timed out while acquiring an IMAP client after {timeout.TotalSeconds:F1} seconds. Failures: {createFailures}.", _lastConnectionException);
} }
throw cancellationToken.IsCancellationRequested throw cancellationToken.IsCancellationRequested
? new OperationCanceledException(cancellationToken) ? new OperationCanceledException(cancellationToken)
: CreatePoolException($"Failed to acquire IMAP client within {timeout.TotalSeconds:F1} seconds. Failures: {createFailures}."); : CreatePoolException($"Failed to acquire IMAP client within {timeout.TotalSeconds:F1} seconds. Failures: {createFailures}.", _lastConnectionException);
} }
/// <summary> /// <summary>
@@ -516,14 +518,17 @@ public class ImapClientPool : IDisposable
private async Task<WinoImapClient> CreateAndConnectClientAsync(CancellationToken cancellationToken) private async Task<WinoImapClient> CreateAndConnectClientAsync(CancellationToken cancellationToken)
{ {
var client = CreateNewClient(); var client = CreateNewClient();
_lastConnectionException = null;
try try
{ {
await EnsureClientReadyAsync(client, cancellationToken).ConfigureAwait(false); await EnsureClientReadyAsync(client, cancellationToken).ConfigureAwait(false);
_lastConnectionException = null;
return client; return client;
} }
catch (Exception ex) catch (Exception ex)
{ {
_lastConnectionException = ex;
_logger.Warning(ex, "Failed to create and connect IMAP client."); _logger.Warning(ex, "Failed to create and connect IMAP client.");
DisposeClient(client); DisposeClient(client);
return null; return null;
@@ -30,7 +30,9 @@ public interface IDefaultChangeProcessor
Task ChangeMailReadStatusAsync(string mailCopyId, bool isRead); Task ChangeMailReadStatusAsync(string mailCopyId, bool isRead);
Task ChangeFlagStatusAsync(string mailCopyId, bool isFlagged); Task ChangeFlagStatusAsync(string mailCopyId, bool isFlagged);
Task<bool> CreateMailAsync(Guid AccountId, NewMailItemPackage package); Task<bool> CreateMailAsync(Guid AccountId, NewMailItemPackage package);
Task CreateMailsAsync(Guid accountId, IReadOnlyList<NewMailItemPackage> packages);
Task DeleteMailAsync(Guid accountId, string mailId); Task DeleteMailAsync(Guid accountId, string mailId);
Task DeleteMailsAsync(Guid accountId, IEnumerable<string> mailIds);
Task<List<MailCopy>> GetDownloadedUnreadMailsAsync(Guid accountId, IEnumerable<string> downloadedMailCopyIds); Task<List<MailCopy>> GetDownloadedUnreadMailsAsync(Guid accountId, IEnumerable<string> downloadedMailCopyIds);
Task SaveMimeFileAsync(Guid fileId, MimeMessage mimeMessage, Guid accountId); Task SaveMimeFileAsync(Guid fileId, MimeMessage mimeMessage, Guid accountId);
Task DeleteFolderAsync(Guid accountId, string remoteFolderId); Task DeleteFolderAsync(Guid accountId, string remoteFolderId);
@@ -56,6 +58,9 @@ public interface IDefaultChangeProcessor
Task UpdateCalendarDeltaSynchronizationToken(Guid calendarId, string deltaToken); Task UpdateCalendarDeltaSynchronizationToken(Guid calendarId, string deltaToken);
Task<List<MailCopy>> GetMailCopiesAsync(IEnumerable<string> mailCopyIds); Task<List<MailCopy>> GetMailCopiesAsync(IEnumerable<string> mailCopyIds);
Task CreateMailRawAsync(MailAccount account, MailItemFolder mailItemFolder, NewMailItemPackage package); Task CreateMailRawAsync(MailAccount account, MailItemFolder mailItemFolder, NewMailItemPackage package);
Task ApplyMailStateUpdatesAsync(IEnumerable<MailCopyStateUpdate> updates);
Task CreateAssignmentsAsync(Guid accountId, IEnumerable<MailFolderAssignmentUpdate> assignments);
Task DeleteAssignmentsAsync(Guid accountId, IEnumerable<MailFolderAssignmentUpdate> assignments);
Task DeleteUserMailCacheAsync(Guid accountId); Task DeleteUserMailCacheAsync(Guid accountId);
Task UpsertMailInvitationCalendarMappingAsync(MailInvitationCalendarMapping mapping); Task UpsertMailInvitationCalendarMappingAsync(MailInvitationCalendarMapping mapping);
Task<MailInvitationCalendarMapping> GetMailInvitationCalendarMappingAsync(Guid accountId, string mailCopyId); Task<MailInvitationCalendarMapping> GetMailInvitationCalendarMappingAsync(Guid accountId, string mailCopyId);
@@ -156,18 +161,33 @@ public class DefaultChangeProcessor(IDatabaseService databaseService,
public Task ChangeMailReadStatusAsync(string mailCopyId, bool isRead) public Task ChangeMailReadStatusAsync(string mailCopyId, bool isRead)
=> MailService.ChangeReadStatusAsync(mailCopyId, isRead); => MailService.ChangeReadStatusAsync(mailCopyId, isRead);
public Task ApplyMailStateUpdatesAsync(IEnumerable<MailCopyStateUpdate> updates)
=> MailService.ApplyMailStateUpdatesAsync(updates);
public Task DeleteAssignmentAsync(Guid accountId, string mailCopyId, string remoteFolderId) public Task DeleteAssignmentAsync(Guid accountId, string mailCopyId, string remoteFolderId)
=> MailService.DeleteAssignmentAsync(accountId, mailCopyId, remoteFolderId); => MailService.DeleteAssignmentAsync(accountId, mailCopyId, remoteFolderId);
public Task DeleteAssignmentsAsync(Guid accountId, IEnumerable<MailFolderAssignmentUpdate> assignments)
=> MailService.DeleteAssignmentsAsync(accountId, assignments);
public Task DeleteMailAsync(Guid accountId, string mailId) public Task DeleteMailAsync(Guid accountId, string mailId)
=> MailService.DeleteMailAsync(accountId, mailId); => MailService.DeleteMailAsync(accountId, mailId);
public Task DeleteMailsAsync(Guid accountId, IEnumerable<string> mailIds)
=> MailService.DeleteMailsAsync(accountId, mailIds);
public Task<bool> CreateMailAsync(Guid accountId, NewMailItemPackage package) public Task<bool> CreateMailAsync(Guid accountId, NewMailItemPackage package)
=> MailService.CreateMailAsync(accountId, package); => MailService.CreateMailAsync(accountId, package);
public Task CreateMailsAsync(Guid accountId, IReadOnlyList<NewMailItemPackage> packages)
=> MailService.CreateMailsAsync(accountId, packages);
public Task CreateMailRawAsync(MailAccount account, MailItemFolder mailItemFolder, NewMailItemPackage package) public Task CreateMailRawAsync(MailAccount account, MailItemFolder mailItemFolder, NewMailItemPackage package)
=> MailService.CreateMailRawAsync(account, mailItemFolder, package); => MailService.CreateMailRawAsync(account, mailItemFolder, package);
public Task CreateAssignmentsAsync(Guid accountId, IEnumerable<MailFolderAssignmentUpdate> assignments)
=> MailService.CreateAssignmentsAsync(accountId, assignments);
public Task<bool> MapLocalDraftAsync(Guid accountId, Guid localDraftCopyUniqueId, string newMailCopyId, string newDraftId, string newThreadId) public Task<bool> MapLocalDraftAsync(Guid accountId, Guid localDraftCopyUniqueId, string newMailCopyId, string newDraftId, string newThreadId)
=> MailService.MapLocalDraftAsync(accountId, localDraftCopyUniqueId, newMailCopyId, newDraftId, newThreadId); => MailService.MapLocalDraftAsync(accountId, localDraftCopyUniqueId, newMailCopyId, newDraftId, newThreadId);
@@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using CommunityToolkit.Mvvm.Messaging; using CommunityToolkit.Mvvm.Messaging;
using Wino.Core.Domain.Entities.Mail; using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Enums; using Wino.Core.Domain.Enums;
@@ -14,18 +15,26 @@ public record EmptyFolderRequest(MailItemFolder Folder, List<MailCopy> MailsToDe
public bool ExcludeMustHaveFolders => false; public bool ExcludeMustHaveFolders => false;
public override void ApplyUIChanges() public override void ApplyUIChanges()
{ {
foreach (var item in MailsToDelete) var removedMails = MailsToDelete?
{ .Where(item => item != null)
WeakReferenceMessenger.Default.Send(new MailRemovedMessage(item, EntityUpdateSource.ClientUpdated)); .ToList();
}
if (removedMails == null || removedMails.Count == 0)
return;
WeakReferenceMessenger.Default.Send(new BulkMailRemovedMessage(removedMails, EntityUpdateSource.ClientUpdated));
} }
public override void RevertUIChanges() public override void RevertUIChanges()
{ {
foreach (var item in MailsToDelete) var addedMails = MailsToDelete?
{ .Where(item => item != null)
WeakReferenceMessenger.Default.Send(new MailAddedMessage(item, EntityUpdateSource.ClientReverted)); .ToList();
}
if (addedMails == null || addedMails.Count == 0)
return;
WeakReferenceMessenger.Default.Send(new BulkMailAddedMessage(addedMails, EntityUpdateSource.ClientReverted));
} }
public List<Guid> SynchronizationFolderIds => [Folder.Id]; public List<Guid> SynchronizationFolderIds => [Folder.Id];
@@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using CommunityToolkit.Mvvm.Messaging; using CommunityToolkit.Mvvm.Messaging;
using Wino.Core.Domain.Entities.Mail; using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Enums; using Wino.Core.Domain.Enums;
@@ -17,31 +18,31 @@ public record MarkFolderAsReadRequest(MailItemFolder Folder, List<MailCopy> Mail
public override void ApplyUIChanges() public override void ApplyUIChanges()
{ {
if (MailsToMarkRead == null || MailsToMarkRead.Count == 0) return; var updatedMails = MailsToMarkRead?
.Where(item => item != null && !item.IsRead)
.Select(item => new MailStateChange(item.UniqueId, IsRead: true))
.ToList();
foreach (var item in MailsToMarkRead) if (updatedMails == null || updatedMails.Count == 0)
{ return;
// Skip if already read
if (item.IsRead) continue;
item.IsRead = true; WeakReferenceMessenger.Default.Send(new BulkMailStateUpdatedMessage(
updatedMails,
WeakReferenceMessenger.Default.Send(new MailUpdatedMessage(item, EntityUpdateSource.ClientUpdated, MailCopyChangeFlags.IsRead)); EntityUpdateSource.ClientUpdated));
}
} }
public override void RevertUIChanges() public override void RevertUIChanges()
{ {
if (MailsToMarkRead == null || MailsToMarkRead.Count == 0) return; var updatedMails = MailsToMarkRead?
.Where(item => item != null && !item.IsRead)
.Select(item => new MailStateChange(item.UniqueId, IsRead: false))
.ToList();
foreach (var item in MailsToMarkRead) if (updatedMails == null || updatedMails.Count == 0)
{ return;
// Skip if already unread (wasn't changed by ApplyUIChanges)
if (!item.IsRead) continue;
item.IsRead = false; WeakReferenceMessenger.Default.Send(new BulkMailStateUpdatedMessage(
updatedMails,
WeakReferenceMessenger.Default.Send(new MailUpdatedMessage(item, EntityUpdateSource.ClientReverted, MailCopyChangeFlags.IsRead)); EntityUpdateSource.ClientReverted));
}
} }
} }
+20
View File
@@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using CommunityToolkit.Mvvm.Messaging; using CommunityToolkit.Mvvm.Messaging;
using Wino.Core.Domain.Entities.Mail; using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Enums; using Wino.Core.Domain.Enums;
@@ -38,6 +39,7 @@ public record ArchiveRequest(bool IsArchiving, MailCopy Item, MailItemFolder Fro
} }
public override MailSynchronizerOperation Operation => MailSynchronizerOperation.Archive; public override MailSynchronizerOperation Operation => MailSynchronizerOperation.Archive;
public override object GroupingKey() => (Operation, IsArchiving, FromFolder.Id, ToFolder?.Id ?? Guid.Empty);
public override void ApplyUIChanges() public override void ApplyUIChanges()
{ {
@@ -55,4 +57,22 @@ public class BatchArchiveRequest : BatchCollection<ArchiveRequest>
public BatchArchiveRequest(IEnumerable<ArchiveRequest> collection) : base(collection) public BatchArchiveRequest(IEnumerable<ArchiveRequest> collection) : base(collection)
{ {
} }
public override void ApplyUIChanges()
{
var removedMails = this.Select(x => x.Item).Where(x => x != null).ToList();
if (removedMails.Count == 0)
return;
WeakReferenceMessenger.Default.Send(new BulkMailRemovedMessage(removedMails, EntityUpdateSource.ClientUpdated));
}
public override void RevertUIChanges()
{
var addedMails = this.Select(x => x.Item).Where(x => x != null).ToList();
if (addedMails.Count == 0)
return;
WeakReferenceMessenger.Default.Send(new BulkMailAddedMessage(addedMails, EntityUpdateSource.ClientReverted));
}
} }
+40 -8
View File
@@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using CommunityToolkit.Mvvm.Messaging; using CommunityToolkit.Mvvm.Messaging;
using Wino.Core.Domain.Entities.Mail; using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Enums; using Wino.Core.Domain.Enums;
@@ -25,25 +26,26 @@ public record ChangeFlagRequest(MailCopy Item, bool IsFlagged) : MailRequestBase
/// If the mail is already in the desired flagged state, no change is needed. /// If the mail is already in the desired flagged state, no change is needed.
/// </summary> /// </summary>
public bool IsNoOp { get; } = Item.IsFlagged == IsFlagged; public bool IsNoOp { get; } = Item.IsFlagged == IsFlagged;
public bool OriginalIsFlagged => _originalIsFlagged;
public override object GroupingKey() => (Operation, Item.FolderId, IsFlagged);
public override void ApplyUIChanges() public override void ApplyUIChanges()
{ {
// Skip UI update if the mail is already in the desired state
if (IsNoOp) return; if (IsNoOp) return;
Item.IsFlagged = IsFlagged; WeakReferenceMessenger.Default.Send(new MailStateUpdatedMessage(
new MailStateChange(Item.UniqueId, IsFlagged: IsFlagged),
WeakReferenceMessenger.Default.Send(new MailUpdatedMessage(Item, EntityUpdateSource.ClientUpdated, MailCopyChangeFlags.IsFlagged)); EntityUpdateSource.ClientUpdated));
} }
public override void RevertUIChanges() public override void RevertUIChanges()
{ {
// Skip UI revert if this was a no-op request
if (IsNoOp) return; if (IsNoOp) return;
Item.IsFlagged = _originalIsFlagged; WeakReferenceMessenger.Default.Send(new MailStateUpdatedMessage(
new MailStateChange(Item.UniqueId, IsFlagged: _originalIsFlagged),
WeakReferenceMessenger.Default.Send(new MailUpdatedMessage(Item, EntityUpdateSource.ClientReverted, MailCopyChangeFlags.IsFlagged)); EntityUpdateSource.ClientReverted));
} }
} }
@@ -52,4 +54,34 @@ public class BatchChangeFlagRequest : BatchCollection<ChangeFlagRequest>
public BatchChangeFlagRequest(IEnumerable<ChangeFlagRequest> collection) : base(collection) public BatchChangeFlagRequest(IEnumerable<ChangeFlagRequest> collection) : base(collection)
{ {
} }
public override void ApplyUIChanges()
{
var updatedMails = this
.Where(x => !x.IsNoOp)
.Select(x => new MailStateChange(x.Item.UniqueId, IsFlagged: x.IsFlagged))
.ToList();
if (updatedMails.Count == 0)
return;
WeakReferenceMessenger.Default.Send(new BulkMailStateUpdatedMessage(
updatedMails,
EntityUpdateSource.ClientUpdated));
}
public override void RevertUIChanges()
{
var updatedMails = this
.Where(x => !x.IsNoOp)
.Select(x => new MailStateChange(x.Item.UniqueId, IsFlagged: x.OriginalIsFlagged))
.ToList();
if (updatedMails.Count == 0)
return;
WeakReferenceMessenger.Default.Send(new BulkMailStateUpdatedMessage(
updatedMails,
EntityUpdateSource.ClientReverted));
}
} }
@@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using CommunityToolkit.Mvvm.Messaging; using CommunityToolkit.Mvvm.Messaging;
using Wino.Core.Domain.Entities.Mail; using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Enums; using Wino.Core.Domain.Enums;
@@ -30,6 +31,7 @@ public record ChangeJunkStateRequest(bool IsJunk, MailCopy Item, MailItemFolder
public bool ExcludeMustHaveFolders => false; public bool ExcludeMustHaveFolders => false;
public override MailSynchronizerOperation Operation => MailSynchronizerOperation.ChangeJunkState; public override MailSynchronizerOperation Operation => MailSynchronizerOperation.ChangeJunkState;
public override object GroupingKey() => (Operation, IsJunk, FromFolder.Id, TargetFolder?.Id ?? Guid.Empty);
public override void ApplyUIChanges() public override void ApplyUIChanges()
{ {
@@ -47,4 +49,22 @@ public class BatchChangeJunkStateRequest : BatchCollection<ChangeJunkStateReques
public BatchChangeJunkStateRequest(IEnumerable<ChangeJunkStateRequest> collection) : base(collection) public BatchChangeJunkStateRequest(IEnumerable<ChangeJunkStateRequest> collection) : base(collection)
{ {
} }
public override void ApplyUIChanges()
{
var removedMails = this.Select(x => x.Item).Where(x => x != null).ToList();
if (removedMails.Count == 0)
return;
WeakReferenceMessenger.Default.Send(new BulkMailRemovedMessage(removedMails, EntityUpdateSource.ClientUpdated));
}
public override void RevertUIChanges()
{
var addedMails = this.Select(x => x.Item).Where(x => x != null).ToList();
if (addedMails.Count == 0)
return;
WeakReferenceMessenger.Default.Send(new BulkMailAddedMessage(addedMails, EntityUpdateSource.ClientReverted));
}
} }
+20
View File
@@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using CommunityToolkit.Mvvm.Messaging; using CommunityToolkit.Mvvm.Messaging;
using Wino.Core.Domain.Entities.Mail; using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Enums; using Wino.Core.Domain.Enums;
@@ -19,6 +20,7 @@ public record DeleteRequest(MailCopy MailItem) : MailRequestBase(MailItem),
public List<Guid> SynchronizationFolderIds => [Item.FolderId]; public List<Guid> SynchronizationFolderIds => [Item.FolderId];
public bool ExcludeMustHaveFolders => false; public bool ExcludeMustHaveFolders => false;
public override MailSynchronizerOperation Operation => MailSynchronizerOperation.Delete; public override MailSynchronizerOperation Operation => MailSynchronizerOperation.Delete;
public override object GroupingKey() => (Operation, Item.FolderId);
public override void ApplyUIChanges() public override void ApplyUIChanges()
{ {
@@ -36,4 +38,22 @@ public class BatchDeleteRequest : BatchCollection<DeleteRequest>
public BatchDeleteRequest(IEnumerable<DeleteRequest> collection) : base(collection) public BatchDeleteRequest(IEnumerable<DeleteRequest> collection) : base(collection)
{ {
} }
public override void ApplyUIChanges()
{
var removedMails = this.Select(x => x.Item).Where(x => x != null).ToList();
if (removedMails.Count == 0)
return;
WeakReferenceMessenger.Default.Send(new BulkMailRemovedMessage(removedMails, EntityUpdateSource.ClientUpdated));
}
public override void RevertUIChanges()
{
var addedMails = this.Select(x => x.Item).Where(x => x != null).ToList();
if (addedMails.Count == 0)
return;
WeakReferenceMessenger.Default.Send(new BulkMailAddedMessage(addedMails, EntityUpdateSource.ClientReverted));
}
} }
+40 -8
View File
@@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using CommunityToolkit.Mvvm.Messaging; using CommunityToolkit.Mvvm.Messaging;
using Wino.Core.Domain.Entities.Mail; using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Enums; using Wino.Core.Domain.Enums;
@@ -24,25 +25,26 @@ public record MarkReadRequest(MailCopy Item, bool IsRead) : MailRequestBase(Item
/// If the mail is already in the desired read state, no change is needed. /// If the mail is already in the desired read state, no change is needed.
/// </summary> /// </summary>
public bool IsNoOp { get; } = Item.IsRead == IsRead; public bool IsNoOp { get; } = Item.IsRead == IsRead;
public bool OriginalIsRead => _originalIsRead;
public override object GroupingKey() => (Operation, Item.FolderId, IsRead);
public override void ApplyUIChanges() public override void ApplyUIChanges()
{ {
// Skip UI update if the mail is already in the desired state
if (IsNoOp) return; if (IsNoOp) return;
Item.IsRead = IsRead; WeakReferenceMessenger.Default.Send(new MailStateUpdatedMessage(
new MailStateChange(Item.UniqueId, IsRead: IsRead),
WeakReferenceMessenger.Default.Send(new MailUpdatedMessage(Item, EntityUpdateSource.ClientUpdated, MailCopyChangeFlags.IsRead)); EntityUpdateSource.ClientUpdated));
} }
public override void RevertUIChanges() public override void RevertUIChanges()
{ {
// Skip UI revert if this was a no-op request
if (IsNoOp) return; if (IsNoOp) return;
Item.IsRead = _originalIsRead; WeakReferenceMessenger.Default.Send(new MailStateUpdatedMessage(
new MailStateChange(Item.UniqueId, IsRead: _originalIsRead),
WeakReferenceMessenger.Default.Send(new MailUpdatedMessage(Item, EntityUpdateSource.ClientReverted, MailCopyChangeFlags.IsRead)); EntityUpdateSource.ClientReverted));
} }
} }
@@ -51,4 +53,34 @@ public class BatchMarkReadRequest : BatchCollection<MarkReadRequest>
public BatchMarkReadRequest(IEnumerable<MarkReadRequest> collection) : base(collection) public BatchMarkReadRequest(IEnumerable<MarkReadRequest> collection) : base(collection)
{ {
} }
public override void ApplyUIChanges()
{
var updatedMails = this
.Where(x => !x.IsNoOp)
.Select(x => new MailStateChange(x.Item.UniqueId, IsRead: x.IsRead))
.ToList();
if (updatedMails.Count == 0)
return;
WeakReferenceMessenger.Default.Send(new BulkMailStateUpdatedMessage(
updatedMails,
EntityUpdateSource.ClientUpdated));
}
public override void RevertUIChanges()
{
var updatedMails = this
.Where(x => !x.IsNoOp)
.Select(x => new MailStateChange(x.Item.UniqueId, IsRead: x.OriginalIsRead))
.ToList();
if (updatedMails.Count == 0)
return;
WeakReferenceMessenger.Default.Send(new BulkMailStateUpdatedMessage(
updatedMails,
EntityUpdateSource.ClientReverted));
}
} }
+20
View File
@@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using CommunityToolkit.Mvvm.Messaging; using CommunityToolkit.Mvvm.Messaging;
using Wino.Core.Domain.Entities.Mail; using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Enums; using Wino.Core.Domain.Enums;
@@ -15,6 +16,7 @@ public record MoveRequest(MailCopy Item, MailItemFolder FromFolder, MailItemFold
public List<Guid> SynchronizationFolderIds => new() { FromFolder.Id, ToFolder.Id }; public List<Guid> SynchronizationFolderIds => new() { FromFolder.Id, ToFolder.Id };
public bool ExcludeMustHaveFolders => false; public bool ExcludeMustHaveFolders => false;
public override MailSynchronizerOperation Operation => MailSynchronizerOperation.Move; public override MailSynchronizerOperation Operation => MailSynchronizerOperation.Move;
public override object GroupingKey() => (Operation, FromFolder.Id, ToFolder?.Id ?? Guid.Empty);
public override void ApplyUIChanges() public override void ApplyUIChanges()
{ {
@@ -32,4 +34,22 @@ public class BatchMoveRequest : BatchCollection<MoveRequest>, IUIChangeRequest
public BatchMoveRequest(IEnumerable<MoveRequest> collection) : base(collection) public BatchMoveRequest(IEnumerable<MoveRequest> collection) : base(collection)
{ {
} }
public override void ApplyUIChanges()
{
var removedMails = this.Select(x => x.Item).Where(x => x != null).ToList();
if (removedMails.Count == 0)
return;
WeakReferenceMessenger.Default.Send(new BulkMailRemovedMessage(removedMails, EntityUpdateSource.ClientUpdated));
}
public override void RevertUIChanges()
{
var addedMails = this.Select(x => x.Item).Where(x => x != null).ToList();
if (addedMails.Count == 0)
return;
WeakReferenceMessenger.Default.Send(new BulkMailAddedMessage(addedMails, EntityUpdateSource.ClientReverted));
}
} }
@@ -11,6 +11,7 @@ using Serilog;
using Wino.Core.Domain.Interfaces; using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models; using Wino.Core.Domain.Models;
using Wino.Core.Domain.Models.AutoDiscovery; using Wino.Core.Domain.Models.AutoDiscovery;
using Wino.Core.Domain.Validation;
namespace Wino.Core.Services; namespace Wino.Core.Services;
@@ -450,6 +451,9 @@ public class AutoDiscoveryService : IAutoDiscoveryService
private async Task<bool> HasAnyDnsAddressRecordAsync(string host, CancellationToken cancellationToken) private async Task<bool> HasAnyDnsAddressRecordAsync(string host, CancellationToken cancellationToken)
{ {
if (MailAccountAddressValidator.IsImplicitlyResolvableHost(host))
return true;
var aRecords = await QueryDnsAsync(host, "A", cancellationToken).ConfigureAwait(false); var aRecords = await QueryDnsAsync(host, "A", cancellationToken).ConfigureAwait(false);
if (aRecords.Count > 0) if (aRecords.Count > 0)
return true; return true;
+29 -6
View File
@@ -123,7 +123,7 @@ public class SynchronizationManager : ISynchronizationManager, IRecipient<Accoun
catch (ImapClientPoolException clientPoolException) catch (ImapClientPoolException clientPoolException)
{ {
_logger.Error(clientPoolException, "IMAP connectivity test failed"); _logger.Error(clientPoolException, "IMAP connectivity test failed");
return ImapConnectivityTestResults.Failure(clientPoolException); return ImapConnectivityTestResults.Failure(clientPoolException.InnerException ?? clientPoolException);
} }
catch (Exception exception) catch (Exception exception)
{ {
@@ -259,25 +259,48 @@ public class SynchronizationManager : ISynchronizationManager, IRecipient<Accoun
/// <param name="accountId">Account ID to queue the request for</param> /// <param name="accountId">Account ID to queue the request for</param>
/// <param name="triggerSynchronization">Whether to automatically trigger synchronization after queuing the request</param> /// <param name="triggerSynchronization">Whether to automatically trigger synchronization after queuing the request</param>
public async Task QueueRequestAsync(IRequestBase request, Guid accountId, bool triggerSynchronization) public async Task QueueRequestAsync(IRequestBase request, Guid accountId, bool triggerSynchronization)
=> await QueueRequestsAsync([request], accountId, triggerSynchronization).ConfigureAwait(false);
public async Task QueueRequestsAsync(IEnumerable<IRequestBase> requests, Guid accountId, bool triggerSynchronization)
{ {
EnsureInitialized(); EnsureInitialized();
var requestList = requests?.Where(request => request != null).ToList() ?? [];
if (requestList.Count == 0)
return;
var synchronizer = await GetOrCreateSynchronizerAsync(accountId); var synchronizer = await GetOrCreateSynchronizerAsync(accountId);
if (synchronizer == null) if (synchronizer == null)
{ {
_logger.Error("Could not find or create synchronizer for account {AccountId} to queue request", accountId); _logger.Error("Could not find or create synchronizer for account {AccountId} to queue {RequestCount} request(s)", accountId, requestList.Count);
return; return;
} }
_logger.Debug("Queuing request {RequestType} for account {AccountId}", if (requestList.Count == 1)
request.GetType().Name, accountId); {
_logger.Debug("Queuing request {RequestType} for account {AccountId}",
requestList[0].GetType().Name, accountId);
}
else
{
var requestSummary = string.Join(", ", requestList
.GroupBy(request => request.GetType().Name)
.OrderBy(group => group.Key)
.Select(group => $"{group.Key} x{group.Count()}"));
synchronizer.QueueRequest(request); _logger.Debug("Queuing {RequestCount} requests for account {AccountId}: {RequestSummary}",
requestList.Count, accountId, requestSummary);
}
foreach (var request in requestList)
{
synchronizer.QueueRequest(request);
}
if (triggerSynchronization) if (triggerSynchronization)
{ {
// Determine if this is a calendar or mail operation // Determine if this is a calendar or mail operation
bool isCalendarOperation = request is ICalendarActionRequest; bool isCalendarOperation = requestList.All(request => request is ICalendarActionRequest);
if (isCalendarOperation) if (isCalendarOperation)
{ {
+10 -10
View File
@@ -93,13 +93,11 @@ public class WinoRequestDelegator : IWinoRequestDelegator
// Queue requests for each account and start synchronization. // Queue requests for each account and start synchronization.
foreach (var accountGroup in accountIds) foreach (var accountGroup in accountIds)
{ {
foreach (var accountRequest in accountGroup) var groupedRequests = accountGroup.Cast<IRequestBase>().ToList();
{ await QueueRequestsAsync(groupedRequests, accountGroup.Key).ConfigureAwait(false);
await QueueRequestAsync(accountRequest, accountGroup.Key);
}
var account = accountGroup.First().Item.AssignedAccount; var account = accountGroup.First().Item.AssignedAccount;
var actionItems = SynchronizationActionHelper.CreateActionItems(accountGroup, accountGroup.Key, account.Name); var actionItems = SynchronizationActionHelper.CreateActionItems(groupedRequests, accountGroup.Key, account.Name);
if (actionItems.Count > 0) if (actionItems.Count > 0)
WeakReferenceMessenger.Default.Send(new SynchronizationActionsAdded(accountGroup.Key, account.Name, actionItems)); WeakReferenceMessenger.Default.Send(new SynchronizationActionsAdded(accountGroup.Key, account.Name, actionItems));
@@ -214,10 +212,7 @@ public class WinoRequestDelegator : IWinoRequestDelegator
if (requestList.Count == 0) if (requestList.Count == 0)
return; return;
foreach (var request in requestList) await QueueRequestsAsync(requestList, accountId).ConfigureAwait(false);
{
await QueueRequestAsync(request, accountId).ConfigureAwait(false);
}
await SendSyncActionsAddedAsync(requestList, accountId).ConfigureAwait(false); await SendSyncActionsAddedAsync(requestList, accountId).ConfigureAwait(false);
await QueueSynchronizationAsync(accountId).ConfigureAwait(false); await QueueSynchronizationAsync(accountId).ConfigureAwait(false);
@@ -274,7 +269,12 @@ public class WinoRequestDelegator : IWinoRequestDelegator
private async Task QueueRequestAsync(IRequestBase request, Guid accountId) private async Task QueueRequestAsync(IRequestBase request, Guid accountId)
{ {
// Don't trigger synchronization for individual requests - we'll trigger it once for all requests // Don't trigger synchronization for individual requests - we'll trigger it once for all requests
await SynchronizationManager.Instance.QueueRequestAsync(request, accountId, triggerSynchronization: false); await SynchronizationManager.Instance.QueueRequestAsync(request, accountId, triggerSynchronization: false).ConfigureAwait(false);
}
private async Task QueueRequestsAsync(IEnumerable<IRequestBase> requests, Guid accountId)
{
await SynchronizationManager.Instance.QueueRequestsAsync(requests, accountId, triggerSynchronization: false).ConfigureAwait(false);
} }
private Task QueueSynchronizationAsync(Guid accountId) private Task QueueSynchronizationAsync(Guid accountId)
+7 -3
View File
@@ -54,6 +54,10 @@ public class WinoRequestProcessor : IWinoRequestProcessor
{ {
var action = preperationRequest.Action; var action = preperationRequest.Action;
var moveTargetStructure = preperationRequest.MoveTargetFolder; var moveTargetStructure = preperationRequest.MoveTargetFolder;
var mailItems = preperationRequest.MailItems?.Where(item => item != null).ToList() ?? [];
if (mailItems.Count == 0)
return [];
// Ask confirmation for permanent delete operation. // Ask confirmation for permanent delete operation.
// Drafts are always hard deleted without any protection. // Drafts are always hard deleted without any protection.
@@ -78,12 +82,12 @@ public class WinoRequestProcessor : IWinoRequestProcessor
// Handle the case when user is trying to move multiple mails that belong to different accounts. // Handle the case when user is trying to move multiple mails that belong to different accounts.
// We can't handle this with only 1 picker dialog. // We can't handle this with only 1 picker dialog.
bool isInvalidMoveTarget = preperationRequest.MailItems.Select(a => a.AssignedAccount.Id).Distinct().Count() > 1; bool isInvalidMoveTarget = mailItems.Select(a => a.AssignedAccount.Id).Distinct().Count() > 1;
if (isInvalidMoveTarget) if (isInvalidMoveTarget)
throw new InvalidMoveTargetException(InvalidMoveTargetReason.MultipleAccounts); throw new InvalidMoveTargetException(InvalidMoveTargetReason.MultipleAccounts);
var accountId = preperationRequest.MailItems.FirstOrDefault().AssignedAccount.Id; var accountId = mailItems[0].AssignedAccount.Id;
moveTargetStructure = await _dialogService.PickFolderAsync(accountId, PickFolderReason.Move, _folderService); moveTargetStructure = await _dialogService.PickFolderAsync(accountId, PickFolderReason.Move, _folderService);
@@ -94,7 +98,7 @@ public class WinoRequestProcessor : IWinoRequestProcessor
var requests = new List<IMailActionRequest>(); var requests = new List<IMailActionRequest>();
// TODO: Fix: Collection was modified; enumeration operation may not execute // TODO: Fix: Collection was modified; enumeration operation may not execute
foreach (var item in preperationRequest.MailItems.ToList()) foreach (var item in mailItems)
{ {
var singleRequest = await GetSingleRequestAsync(item, action, moveTargetStructure, preperationRequest.ToggleExecution); var singleRequest = await GetSingleRequestAsync(item, action, moveTargetStructure, preperationRequest.ToggleExecution);
@@ -12,6 +12,7 @@ using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces; using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Accounts; using Wino.Core.Domain.Models.Accounts;
using Wino.Core.Domain.Models.Synchronization; using Wino.Core.Domain.Models.Synchronization;
using Wino.Core.Requests.Mail;
using Wino.Core.Requests.Bundles; using Wino.Core.Requests.Bundles;
using Wino.Messaging.UI; using Wino.Messaging.UI;
@@ -262,4 +263,75 @@ public abstract partial class BaseSynchronizer<TBaseRequest> : ObservableObject,
return ret; return ret;
} }
protected void ApplyOptimisticUiChanges(IEnumerable<IRequestBundle<TBaseRequest>> bundles, Func<IRequestBase, bool> shouldApply = null)
{
var bundleList = bundles?
.Where(b => b?.Request != null && (shouldApply?.Invoke(b.Request) ?? true))
.ToList() ?? [];
if (bundleList.Count == 0)
return;
var requestList = new List<IRequestBase>(bundleList.Count);
foreach (var bundle in bundleList)
{
if (bundle.UIChangeRequest != null && !ReferenceEquals(bundle.UIChangeRequest, bundle.Request))
{
bundle.UIChangeRequest.ApplyUIChanges();
continue;
}
requestList.Add(bundle.Request);
}
if (requestList.Count == 0)
return;
var appliedBatchRequestKeys = new HashSet<object>();
foreach (var group in requestList.GroupBy(r => r.GroupingKey()))
{
var groupRequests = group.ToList();
if (groupRequests.Count <= 1)
continue;
if (!TryApplyBatchUiChanges(groupRequests))
continue;
appliedBatchRequestKeys.Add(group.Key);
}
foreach (var request in requestList)
{
if (!appliedBatchRequestKeys.Contains(request.GroupingKey()))
{
request.ApplyUIChanges();
}
}
}
private static bool TryApplyBatchUiChanges(IReadOnlyList<IRequestBase> requests)
{
if (requests == null || requests.Count <= 1)
return false;
return requests[0] switch
{
MarkReadRequest => ApplyBatch(new BatchMarkReadRequest(requests.Cast<MarkReadRequest>())),
ChangeFlagRequest => ApplyBatch(new BatchChangeFlagRequest(requests.Cast<ChangeFlagRequest>())),
DeleteRequest => ApplyBatch(new BatchDeleteRequest(requests.Cast<DeleteRequest>())),
MoveRequest => ApplyBatch(new BatchMoveRequest(requests.Cast<MoveRequest>())),
ArchiveRequest => ApplyBatch(new BatchArchiveRequest(requests.Cast<ArchiveRequest>())),
ChangeJunkStateRequest => ApplyBatch(new BatchChangeJunkStateRequest(requests.Cast<ChangeJunkStateRequest>())),
_ => false
};
static bool ApplyBatch(IUIChangeRequest request)
{
request.ApplyUIChanges();
return true;
}
}
} }
+163 -52
View File
@@ -1050,6 +1050,11 @@ public class GmailSynchronizer : WinoSynchronizer<IClientServiceRequest, Message
{ {
_logger.Debug("Processing delta change {HistoryId} for {Name}", listHistoryResponse.HistoryId.GetValueOrDefault(), Account.Name); _logger.Debug("Processing delta change {HistoryId} for {Name}", listHistoryResponse.HistoryId.GetValueOrDefault(), Account.Name);
var pendingStateUpdates = new List<MailCopyStateUpdate>();
var pendingAssignmentCreates = new Dictionary<string, MailFolderAssignmentUpdate>(StringComparer.Ordinal);
var pendingAssignmentDeletes = new Dictionary<string, MailFolderAssignmentUpdate>(StringComparer.Ordinal);
var deletedMessageIds = new HashSet<string>(StringComparer.Ordinal);
foreach (var history in listHistoryResponse.History) foreach (var history in listHistoryResponse.History)
{ {
// Handle label additions. // Handle label additions.
@@ -1057,7 +1062,7 @@ public class GmailSynchronizer : WinoSynchronizer<IClientServiceRequest, Message
{ {
foreach (var addedLabel in history.LabelsAdded) foreach (var addedLabel in history.LabelsAdded)
{ {
await HandleLabelAssignmentAsync(addedLabel); await HandleLabelAssignmentAsync(addedLabel, pendingStateUpdates, pendingAssignmentCreates, pendingAssignmentDeletes).ConfigureAwait(false);
} }
} }
@@ -1066,7 +1071,7 @@ public class GmailSynchronizer : WinoSynchronizer<IClientServiceRequest, Message
{ {
foreach (var removedLabel in history.LabelsRemoved) foreach (var removedLabel in history.LabelsRemoved)
{ {
await HandleLabelRemovalAsync(removedLabel); await HandleLabelRemovalAsync(removedLabel, pendingStateUpdates, pendingAssignmentCreates, pendingAssignmentDeletes).ConfigureAwait(false);
} }
} }
@@ -1079,36 +1084,108 @@ public class GmailSynchronizer : WinoSynchronizer<IClientServiceRequest, Message
_logger.Debug("Processing message deletion for {MessageId}", messageId); _logger.Debug("Processing message deletion for {MessageId}", messageId);
await _gmailChangeProcessor.DeleteMailAsync(Account.Id, messageId).ConfigureAwait(false); deletedMessageIds.Add(messageId);
} }
} }
} }
if (pendingStateUpdates.Count > 0)
{
await _gmailChangeProcessor.ApplyMailStateUpdatesAsync(pendingStateUpdates).ConfigureAwait(false);
}
if (pendingAssignmentCreates.Count > 0)
{
await _gmailChangeProcessor.CreateAssignmentsAsync(Account.Id, pendingAssignmentCreates.Values.ToList()).ConfigureAwait(false);
}
if (pendingAssignmentDeletes.Count > 0)
{
await _gmailChangeProcessor.DeleteAssignmentsAsync(Account.Id, pendingAssignmentDeletes.Values.ToList()).ConfigureAwait(false);
}
if (deletedMessageIds.Count > 0)
{
await _gmailChangeProcessor.DeleteMailsAsync(Account.Id, deletedMessageIds).ConfigureAwait(false);
}
} }
private async Task HandleArchiveAssignmentAsync(string archivedMessageId) private static string GetAssignmentChangeKey(string messageId, string labelId)
=> $"{messageId}\u001f{labelId}";
private static void QueueAssignmentChange(
Dictionary<string, MailFolderAssignmentUpdate> creates,
Dictionary<string, MailFolderAssignmentUpdate> deletes,
MailFolderAssignmentUpdate assignment,
bool shouldCreate)
{ {
if (assignment == null ||
string.IsNullOrWhiteSpace(assignment.MailCopyId) ||
string.IsNullOrWhiteSpace(assignment.RemoteFolderId))
{
return;
}
var key = GetAssignmentChangeKey(assignment.MailCopyId, assignment.RemoteFolderId);
if (shouldCreate)
{
deletes.Remove(key);
creates[key] = assignment;
}
else
{
creates.Remove(key);
deletes[key] = assignment;
}
}
private async Task HandleArchiveAssignmentAsync(
string archivedMessageId,
Dictionary<string, MailFolderAssignmentUpdate> pendingAssignmentCreates,
Dictionary<string, MailFolderAssignmentUpdate> pendingAssignmentDeletes)
{
if (!archiveFolderId.HasValue)
return;
// Ignore if the message is already in the archive. // Ignore if the message is already in the archive.
bool archived = await _gmailChangeProcessor.IsMailExistsInFolderAsync(archivedMessageId, archiveFolderId.Value); bool archived = await _gmailChangeProcessor.IsMailExistsInFolderAsync(archivedMessageId, archiveFolderId.Value).ConfigureAwait(false);
if (archived) return; if (archived) return;
_logger.Debug("Processing archive assignment for message {Id}", archivedMessageId); _logger.Debug("Processing archive assignment for message {Id}", archivedMessageId);
QueueAssignmentChange(
await _gmailChangeProcessor.CreateAssignmentAsync(Account.Id, archivedMessageId, ServiceConstants.ARCHIVE_LABEL_ID).ConfigureAwait(false); pendingAssignmentCreates,
pendingAssignmentDeletes,
new MailFolderAssignmentUpdate(archivedMessageId, ServiceConstants.ARCHIVE_LABEL_ID),
shouldCreate: true);
} }
private async Task HandleUnarchiveAssignmentAsync(string unarchivedMessageId) private async Task HandleUnarchiveAssignmentAsync(
string unarchivedMessageId,
Dictionary<string, MailFolderAssignmentUpdate> pendingAssignmentCreates,
Dictionary<string, MailFolderAssignmentUpdate> pendingAssignmentDeletes)
{ {
if (!archiveFolderId.HasValue)
return;
// Ignore if the message is not in the archive. // Ignore if the message is not in the archive.
bool archived = await _gmailChangeProcessor.IsMailExistsInFolderAsync(unarchivedMessageId, archiveFolderId.Value); bool archived = await _gmailChangeProcessor.IsMailExistsInFolderAsync(unarchivedMessageId, archiveFolderId.Value).ConfigureAwait(false);
if (!archived) return; if (!archived) return;
_logger.Debug("Processing un-archive assignment for message {Id}", unarchivedMessageId); _logger.Debug("Processing un-archive assignment for message {Id}", unarchivedMessageId);
QueueAssignmentChange(
await _gmailChangeProcessor.DeleteAssignmentAsync(Account.Id, unarchivedMessageId, ServiceConstants.ARCHIVE_LABEL_ID).ConfigureAwait(false); pendingAssignmentCreates,
pendingAssignmentDeletes,
new MailFolderAssignmentUpdate(unarchivedMessageId, ServiceConstants.ARCHIVE_LABEL_ID),
shouldCreate: false);
} }
private async Task HandleLabelAssignmentAsync(HistoryLabelAdded addedLabel) private async Task HandleLabelAssignmentAsync(
HistoryLabelAdded addedLabel,
List<MailCopyStateUpdate> pendingStateUpdates,
Dictionary<string, MailFolderAssignmentUpdate> pendingAssignmentCreates,
Dictionary<string, MailFolderAssignmentUpdate> pendingAssignmentDeletes)
{ {
var messageId = addedLabel.Message.Id; var messageId = addedLabel.Message.Id;
@@ -1119,23 +1196,31 @@ public class GmailSynchronizer : WinoSynchronizer<IClientServiceRequest, Message
// ARCHIVE is a virtual folder - handle it separately // ARCHIVE is a virtual folder - handle it separately
if (labelId == ServiceConstants.ARCHIVE_LABEL_ID) if (labelId == ServiceConstants.ARCHIVE_LABEL_ID)
{ {
await HandleArchiveAssignmentAsync(messageId).ConfigureAwait(false); await HandleArchiveAssignmentAsync(messageId, pendingAssignmentCreates, pendingAssignmentDeletes).ConfigureAwait(false);
continue; continue;
} }
// When UNREAD label is added mark the message as un-read. // When UNREAD label is added mark the message as un-read.
if (labelId == ServiceConstants.UNREAD_LABEL_ID) if (labelId == ServiceConstants.UNREAD_LABEL_ID)
await _gmailChangeProcessor.ChangeMailReadStatusAsync(messageId, false).ConfigureAwait(false); pendingStateUpdates.Add(new MailCopyStateUpdate(messageId, IsRead: false));
// When STARRED label is added mark the message as flagged. // When STARRED label is added mark the message as flagged.
if (labelId == ServiceConstants.STARRED_LABEL_ID) if (labelId == ServiceConstants.STARRED_LABEL_ID)
await _gmailChangeProcessor.ChangeFlagStatusAsync(messageId, true).ConfigureAwait(false); pendingStateUpdates.Add(new MailCopyStateUpdate(messageId, IsFlagged: true));
await _gmailChangeProcessor.CreateAssignmentAsync(Account.Id, messageId, labelId).ConfigureAwait(false); QueueAssignmentChange(
pendingAssignmentCreates,
pendingAssignmentDeletes,
new MailFolderAssignmentUpdate(messageId, labelId),
shouldCreate: true);
} }
} }
private async Task HandleLabelRemovalAsync(HistoryLabelRemoved removedLabel) private async Task HandleLabelRemovalAsync(
HistoryLabelRemoved removedLabel,
List<MailCopyStateUpdate> pendingStateUpdates,
Dictionary<string, MailFolderAssignmentUpdate> pendingAssignmentCreates,
Dictionary<string, MailFolderAssignmentUpdate> pendingAssignmentDeletes)
{ {
var messageId = removedLabel.Message.Id; var messageId = removedLabel.Message.Id;
@@ -1146,20 +1231,23 @@ public class GmailSynchronizer : WinoSynchronizer<IClientServiceRequest, Message
// ARCHIVE is a virtual folder - handle it separately // ARCHIVE is a virtual folder - handle it separately
if (labelId == ServiceConstants.ARCHIVE_LABEL_ID) if (labelId == ServiceConstants.ARCHIVE_LABEL_ID)
{ {
await HandleUnarchiveAssignmentAsync(messageId).ConfigureAwait(false); await HandleUnarchiveAssignmentAsync(messageId, pendingAssignmentCreates, pendingAssignmentDeletes).ConfigureAwait(false);
continue; continue;
} }
// When UNREAD label is removed mark the message as read. // When UNREAD label is removed mark the message as read.
if (labelId == ServiceConstants.UNREAD_LABEL_ID) if (labelId == ServiceConstants.UNREAD_LABEL_ID)
await _gmailChangeProcessor.ChangeMailReadStatusAsync(messageId, true).ConfigureAwait(false); pendingStateUpdates.Add(new MailCopyStateUpdate(messageId, IsRead: true));
// When STARRED label is removed mark the message as un-flagged. // When STARRED label is removed mark the message as un-flagged.
if (labelId == ServiceConstants.STARRED_LABEL_ID) if (labelId == ServiceConstants.STARRED_LABEL_ID)
await _gmailChangeProcessor.ChangeFlagStatusAsync(messageId, false).ConfigureAwait(false); pendingStateUpdates.Add(new MailCopyStateUpdate(messageId, IsFlagged: false));
// For other labels remove the mail assignment. QueueAssignmentChange(
await _gmailChangeProcessor.DeleteAssignmentAsync(Account.Id, messageId, labelId).ConfigureAwait(false); pendingAssignmentCreates,
pendingAssignmentDeletes,
new MailFolderAssignmentUpdate(messageId, labelId),
shouldCreate: false);
} }
} }
@@ -1542,6 +1630,8 @@ public class GmailSynchronizer : WinoSynchronizer<IClientServiceRequest, Message
await Task.WhenAll(batchTasks).ConfigureAwait(false); await Task.WhenAll(batchTasks).ConfigureAwait(false);
// Process all downloaded messages // Process all downloaded messages
var pendingPackages = new List<NewMailItemPackage>();
foreach (var gmailMessage in downloadedMessages) foreach (var gmailMessage in downloadedMessages)
{ {
try try
@@ -1552,12 +1642,7 @@ public class GmailSynchronizer : WinoSynchronizer<IClientServiceRequest, Message
var packages = await CreateNewMailPackagesAsync(gmailMessage, null, cancellationToken).ConfigureAwait(false); var packages = await CreateNewMailPackagesAsync(gmailMessage, null, cancellationToken).ConfigureAwait(false);
if (packages != null) if (packages != null)
{ pendingPackages.AddRange(packages);
foreach (var package in packages)
{
await _gmailChangeProcessor.CreateMailAsync(Account.Id, package).ConfigureAwait(false);
}
}
// Update sync identifier if available // Update sync identifier if available
if (gmailMessage.HistoryId.HasValue) if (gmailMessage.HistoryId.HasValue)
@@ -1570,6 +1655,11 @@ public class GmailSynchronizer : WinoSynchronizer<IClientServiceRequest, Message
_logger.Error(ex, "Failed to process downloaded message {MessageId}", gmailMessage.Id); _logger.Error(ex, "Failed to process downloaded message {MessageId}", gmailMessage.Id);
} }
} }
if (pendingPackages.Count > 0)
{
await _gmailChangeProcessor.CreateMailsAsync(Account.Id, pendingPackages).ConfigureAwait(false);
}
} }
} }
@@ -1592,12 +1682,9 @@ public class GmailSynchronizer : WinoSynchronizer<IClientServiceRequest, Message
// Create mail packages from metadata // Create mail packages from metadata
var packages = await CreateNewMailPackagesAsync(gmailMessage, null, cancellationToken).ConfigureAwait(false); var packages = await CreateNewMailPackagesAsync(gmailMessage, null, cancellationToken).ConfigureAwait(false);
if (packages != null) if (packages != null && packages.Count > 0)
{ {
foreach (var package in packages) await _gmailChangeProcessor.CreateMailsAsync(Account.Id, packages).ConfigureAwait(false);
{
await _gmailChangeProcessor.CreateMailAsync(Account.Id, package).ConfigureAwait(false);
}
} }
// Update sync identifier if available // Update sync identifier if available
@@ -1897,9 +1984,19 @@ public class GmailSynchronizer : WinoSynchronizer<IClientServiceRequest, Message
if (historyId == null) return false; if (historyId == null) return false;
var newHistoryId = historyId.Value; var newHistoryId = historyId.Value;
var currentSynchronizationIdentifier = Account.SynchronizationDeltaIdentifier;
return Account.SynchronizationDeltaIdentifier == null || if (string.IsNullOrWhiteSpace(currentSynchronizationIdentifier))
(ulong.TryParse(Account.SynchronizationDeltaIdentifier, out ulong currentIdentifier) && newHistoryId > currentIdentifier); return true;
if (!ulong.TryParse(currentSynchronizationIdentifier, out ulong currentIdentifier))
{
_logger.Warning("Current Gmail history ID '{HistoryId}' is invalid for {Name}. Replacing it with {NewHistoryId}.",
currentSynchronizationIdentifier, Account.Name, newHistoryId);
return true;
}
return newHistoryId > currentIdentifier;
} }
private async Task UpdateAccountSyncIdentifierAsync(ulong? historyId) private async Task UpdateAccountSyncIdentifierAsync(ulong? historyId)
@@ -1932,12 +2029,9 @@ public class GmailSynchronizer : WinoSynchronizer<IClientServiceRequest, Message
// Create mail packages from the downloaded message // Create mail packages from the downloaded message
var packages = await CreateNewMailPackagesAsync(gmailMessage, null, cancellationToken).ConfigureAwait(false); var packages = await CreateNewMailPackagesAsync(gmailMessage, null, cancellationToken).ConfigureAwait(false);
if (packages != null) if (packages != null && packages.Count > 0)
{ {
foreach (var package in packages) await _gmailChangeProcessor.CreateMailsAsync(Account.Id, packages).ConfigureAwait(false);
{
await _gmailChangeProcessor.CreateMailAsync(Account.Id, package).ConfigureAwait(false);
}
} }
await UpdateAccountSyncIdentifierAsync(gmailMessage.HistoryId).ConfigureAwait(false); await UpdateAccountSyncIdentifierAsync(gmailMessage.HistoryId).ConfigureAwait(false);
@@ -1989,25 +2083,27 @@ public class GmailSynchronizer : WinoSynchronizer<IClientServiceRequest, Message
switch (bundle.UIChangeRequest) switch (bundle.UIChangeRequest)
{ {
case BatchMarkReadRequest batchMarkReadRequest: case BatchMarkReadRequest batchMarkReadRequest:
foreach (var request in batchMarkReadRequest) await _gmailChangeProcessor.ApplyMailStateUpdatesAsync(
{ batchMarkReadRequest.Select(request => new MailCopyStateUpdate(request.Item.Id, IsRead: request.IsRead)))
await _gmailChangeProcessor.ChangeMailReadStatusAsync(request.Item.Id, request.IsRead).ConfigureAwait(false); .ConfigureAwait(false);
}
break; break;
case MarkReadRequest markReadRequest: case MarkReadRequest markReadRequest:
await _gmailChangeProcessor.ChangeMailReadStatusAsync(markReadRequest.Item.Id, markReadRequest.IsRead).ConfigureAwait(false); await _gmailChangeProcessor.ApplyMailStateUpdatesAsync(
[new MailCopyStateUpdate(markReadRequest.Item.Id, IsRead: markReadRequest.IsRead)])
.ConfigureAwait(false);
break; break;
case BatchChangeFlagRequest batchChangeFlagRequest: case BatchChangeFlagRequest batchChangeFlagRequest:
foreach (var request in batchChangeFlagRequest) await _gmailChangeProcessor.ApplyMailStateUpdatesAsync(
{ batchChangeFlagRequest.Select(request => new MailCopyStateUpdate(request.Item.Id, IsFlagged: request.IsFlagged)))
await _gmailChangeProcessor.ChangeFlagStatusAsync(request.Item.Id, request.IsFlagged).ConfigureAwait(false); .ConfigureAwait(false);
}
break; break;
case ChangeFlagRequest changeFlagRequest: case ChangeFlagRequest changeFlagRequest:
await _gmailChangeProcessor.ChangeFlagStatusAsync(changeFlagRequest.Item.Id, changeFlagRequest.IsFlagged).ConfigureAwait(false); await _gmailChangeProcessor.ApplyMailStateUpdatesAsync(
[new MailCopyStateUpdate(changeFlagRequest.Item.Id, IsFlagged: changeFlagRequest.IsFlagged)])
.ConfigureAwait(false);
break; break;
} }
} }
@@ -2065,16 +2161,31 @@ public class GmailSynchronizer : WinoSynchronizer<IClientServiceRequest, Message
} }
var existingAfterDownload = await _gmailChangeProcessor.AreMailsExistsAsync(addedArchiveIds).ConfigureAwait(false); var existingAfterDownload = await _gmailChangeProcessor.AreMailsExistsAsync(addedArchiveIds).ConfigureAwait(false);
var pendingArchiveCreates = new Dictionary<string, MailFolderAssignmentUpdate>(StringComparer.Ordinal);
var pendingArchiveDeletes = new Dictionary<string, MailFolderAssignmentUpdate>(StringComparer.Ordinal);
foreach (var archiveAddedItem in existingAfterDownload) foreach (var archiveAddedItem in existingAfterDownload)
{ {
await HandleArchiveAssignmentAsync(archiveAddedItem).ConfigureAwait(false); await HandleArchiveAssignmentAsync(archiveAddedItem, pendingArchiveCreates, pendingArchiveDeletes).ConfigureAwait(false);
}
if (pendingArchiveCreates.Count > 0)
{
await _gmailChangeProcessor.CreateAssignmentsAsync(Account.Id, pendingArchiveCreates.Values.ToList()).ConfigureAwait(false);
} }
} }
var pendingArchiveRemovals = new Dictionary<string, MailFolderAssignmentUpdate>(StringComparer.Ordinal);
var pendingArchiveCreateOverrides = new Dictionary<string, MailFolderAssignmentUpdate>(StringComparer.Ordinal);
foreach (var unAarchivedRemovedItem in removedArchiveIds) foreach (var unAarchivedRemovedItem in removedArchiveIds)
{ {
await HandleUnarchiveAssignmentAsync(unAarchivedRemovedItem).ConfigureAwait(false); await HandleUnarchiveAssignmentAsync(unAarchivedRemovedItem, pendingArchiveCreateOverrides, pendingArchiveRemovals).ConfigureAwait(false);
}
if (pendingArchiveRemovals.Count > 0)
{
await _gmailChangeProcessor.DeleteAssignmentsAsync(Account.Id, pendingArchiveRemovals.Values.ToList()).ConfigureAwait(false);
} }
} }
@@ -29,6 +29,8 @@ namespace Wino.Core.Synchronizers.ImapSync;
public class UnifiedImapSynchronizer public class UnifiedImapSynchronizer
{ {
private static readonly TimeSpan UidReconcileInterval = TimeSpan.FromHours(12); private static readonly TimeSpan UidReconcileInterval = TimeSpan.FromHours(12);
private const int NewMessageFetchBatchSize = 50;
private const int ExistingMessageFlagFetchBatchSize = 250;
private readonly ILogger _logger = Log.ForContext<UnifiedImapSynchronizer>(); private readonly ILogger _logger = Log.ForContext<UnifiedImapSynchronizer>();
private readonly IFolderService _folderService; private readonly IFolderService _folderService;
@@ -47,6 +49,9 @@ public class UnifiedImapSynchronizer
MessageSummaryItems.References | MessageSummaryItems.References |
MessageSummaryItems.ModSeq | MessageSummaryItems.ModSeq |
MessageSummaryItems.BodyStructure; MessageSummaryItems.BodyStructure;
private readonly MessageSummaryItems _existingMailSynchronizationFlags =
MessageSummaryItems.Flags |
MessageSummaryItems.UniqueId;
public UnifiedImapSynchronizer( public UnifiedImapSynchronizer(
IFolderService folderService, IFolderService folderService,
@@ -182,15 +187,35 @@ public class UnifiedImapSynchronizer
var downloadedMessageIds = new List<string>(); var downloadedMessageIds = new List<string>();
foreach (var batch in uids.Distinct().OrderBy(a => a.Id).Batch(50)) foreach (var batch in uids.Distinct().OrderBy(a => a.Id).Batch(ExistingMessageFlagFetchBatchSize))
{ {
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
var summaryBatch = await remoteFolder var batchUids = batch.ToList();
.FetchAsync(new UniqueIdSet(batch.ToList(), SortOrder.Ascending), _mailSynchronizationFlags, cancellationToken) var existingMails = await _mailService.GetExistingMailsAsync(localFolder.Id, batchUids).ConfigureAwait(false);
.ConfigureAwait(false); var existingByUid = CreateExistingMailLookup(existingMails);
var existingUids = batchUids.Where(uid => existingByUid.ContainsKey(uid.Id)).ToList();
var newUids = batchUids.Where(uid => !existingByUid.ContainsKey(uid.Id)).ToList();
downloadedMessageIds.AddRange(await ProcessSummariesAsync(synchronizer, localFolder, summaryBatch, cancellationToken).ConfigureAwait(false)); if (existingUids.Count > 0)
{
var existingSummaryBatch = await remoteFolder
.FetchAsync(new UniqueIdSet(existingUids, SortOrder.Ascending), _existingMailSynchronizationFlags, cancellationToken)
.ConfigureAwait(false);
await ApplySummaryFlagUpdatesAsync(existingByUid, existingSummaryBatch).ConfigureAwait(false);
}
foreach (var newBatch in newUids.Batch(NewMessageFetchBatchSize))
{
cancellationToken.ThrowIfCancellationRequested();
var newSummaryBatch = await remoteFolder
.FetchAsync(new UniqueIdSet(newBatch.ToList(), SortOrder.Ascending), _mailSynchronizationFlags, cancellationToken)
.ConfigureAwait(false);
downloadedMessageIds.AddRange(await ProcessSummariesCoreAsync(synchronizer, localFolder, newSummaryBatch, existingByUid, cancellationToken).ConfigureAwait(false));
}
} }
UpdateHighestKnownUid(localFolder, remoteFolder, uids.Select(a => a.Id)); UpdateHighestKnownUid(localFolder, remoteFolder, uids.Select(a => a.Id));
@@ -268,7 +293,29 @@ public class UnifiedImapSynchronizer
.ConfigureAwait(false); .ConfigureAwait(false);
} }
downloadedMessageIds = await DownloadMessagesByUidsAsync(client, remoteFolder, folder, changedUids, synchronizer, cancellationToken).ConfigureAwait(false); var existingMails = await _mailService.GetExistingMailsAsync(folder.Id, changedUids).ConfigureAwait(false);
var existingByUid = CreateExistingMailLookup(existingMails);
var newOrUnknownUids = changedUids.Where(uid => !existingByUid.ContainsKey(uid.Id)).ToList();
var existingUidsWithoutFlagEvents = changedUids
.Where(uid => existingByUid.ContainsKey(uid.Id) && !changedFlags.ContainsKey(uid.Id))
.ToList();
if (existingUidsWithoutFlagEvents.Count > 0)
{
var missingEventSummaries = await remoteFolder
.FetchAsync(new UniqueIdSet(existingUidsWithoutFlagEvents, SortOrder.Ascending), _existingMailSynchronizationFlags, cancellationToken)
.ConfigureAwait(false);
foreach (var summary in missingEventSummaries)
{
if (summary.UniqueId != UniqueId.Invalid && summary.Flags != null)
{
changedFlags[summary.UniqueId.Id] = summary.Flags.Value;
}
}
}
downloadedMessageIds = await DownloadMessagesByUidsAsync(client, remoteFolder, folder, newOrUnknownUids, synchronizer, cancellationToken).ConfigureAwait(false);
folder.HighestModeSeq = unchecked((long)remoteFolder.HighestModSeq); folder.HighestModeSeq = unchecked((long)remoteFolder.HighestModSeq);
@@ -456,11 +503,19 @@ public class UnifiedImapSynchronizer
folder.UidValidity = remoteFolder.UidValidity; folder.UidValidity = remoteFolder.UidValidity;
} }
private async Task<List<string>> ProcessSummariesAsync( private Task<List<string>> ProcessSummariesAsync(
IImapSynchronizer synchronizer, IImapSynchronizer synchronizer,
MailItemFolder localFolder, MailItemFolder localFolder,
IList<IMessageSummary> summaries, IList<IMessageSummary> summaries,
CancellationToken cancellationToken) CancellationToken cancellationToken)
=> ProcessSummariesCoreAsync(synchronizer, localFolder, summaries, existingByUid: null, cancellationToken);
private async Task<List<string>> ProcessSummariesCoreAsync(
IImapSynchronizer synchronizer,
MailItemFolder localFolder,
IList<IMessageSummary> summaries,
IReadOnlyDictionary<uint, MailCopy> existingByUid,
CancellationToken cancellationToken)
{ {
var downloadedMessageIds = new List<string>(); var downloadedMessageIds = new List<string>();
@@ -475,10 +530,8 @@ public class UnifiedImapSynchronizer
if (uniqueIds.Count == 0) if (uniqueIds.Count == 0)
return downloadedMessageIds; return downloadedMessageIds;
var existingMails = await _mailService.GetExistingMailsAsync(localFolder.Id, uniqueIds).ConfigureAwait(false); existingByUid ??= CreateExistingMailLookup(await _mailService.GetExistingMailsAsync(localFolder.Id, uniqueIds).ConfigureAwait(false));
var existingByUid = existingMails var pendingStateUpdates = new List<MailCopyStateUpdate>();
.Select(m => (Uid: MailkitClientExtensions.ResolveUidStruct(m.Id), Mail: m))
.ToDictionary(a => a.Uid.Id, a => a.Mail);
foreach (var summary in summaries) foreach (var summary in summaries)
{ {
@@ -491,7 +544,11 @@ public class UnifiedImapSynchronizer
{ {
if (summary.Flags != null) if (summary.Flags != null)
{ {
await UpdateMailFlagsAsync(existingMail, summary.Flags.Value).ConfigureAwait(false); var pendingStateUpdate = CreateMailStateUpdate(existingMail, summary.Flags.Value);
if (pendingStateUpdate != null)
{
pendingStateUpdates.Add(pendingStateUpdate);
}
} }
continue; continue;
@@ -516,23 +573,79 @@ public class UnifiedImapSynchronizer
} }
} }
if (pendingStateUpdates.Count > 0)
{
await _mailService.ApplyMailStateUpdatesAsync(pendingStateUpdates).ConfigureAwait(false);
}
return downloadedMessageIds; return downloadedMessageIds;
} }
private async Task UpdateMailFlagsAsync(MailCopy mailCopy, MessageFlags flags) private async Task ApplySummaryFlagUpdatesAsync(
IReadOnlyDictionary<uint, MailCopy> existingByUid,
IList<IMessageSummary> summaries)
{
if (existingByUid == null || existingByUid.Count == 0 || summaries == null || summaries.Count == 0)
return;
var pendingStateUpdates = new List<MailCopyStateUpdate>();
foreach (var summary in summaries)
{
if (summary.UniqueId == UniqueId.Invalid || summary.Flags == null)
continue;
if (!existingByUid.TryGetValue(summary.UniqueId.Id, out var existingMail))
continue;
var pendingStateUpdate = CreateMailStateUpdate(existingMail, summary.Flags.Value);
if (pendingStateUpdate != null)
{
pendingStateUpdates.Add(pendingStateUpdate);
}
}
if (pendingStateUpdates.Count > 0)
{
await _mailService.ApplyMailStateUpdatesAsync(pendingStateUpdates).ConfigureAwait(false);
}
}
private static IReadOnlyDictionary<uint, MailCopy> CreateExistingMailLookup(IEnumerable<MailCopy> existingMails)
{
var lookup = new Dictionary<uint, MailCopy>();
foreach (var mail in existingMails ?? [])
{
if (mail == null || string.IsNullOrEmpty(mail.Id))
continue;
try
{
lookup[MailkitClientExtensions.ResolveUidStruct(mail.Id).Id] = mail;
}
catch (ArgumentOutOfRangeException)
{
}
}
return lookup;
}
private static MailCopyStateUpdate CreateMailStateUpdate(MailCopy mailCopy, MessageFlags flags)
{ {
var isFlagged = MailkitClientExtensions.GetIsFlagged(flags); var isFlagged = MailkitClientExtensions.GetIsFlagged(flags);
var isRead = MailkitClientExtensions.GetIsRead(flags); var isRead = MailkitClientExtensions.GetIsRead(flags);
if (isFlagged != mailCopy.IsFlagged) bool shouldUpdateFlagged = isFlagged != mailCopy.IsFlagged;
{ bool shouldUpdateRead = isRead != mailCopy.IsRead;
await _mailService.ChangeFlagStatusAsync(mailCopy.Id, isFlagged).ConfigureAwait(false);
}
if (isRead != mailCopy.IsRead) return !shouldUpdateFlagged && !shouldUpdateRead
{ ? null
await _mailService.ChangeReadStatusAsync(mailCopy.Id, isRead).ConfigureAwait(false); : new MailCopyStateUpdate(
} mailCopy.Id,
shouldUpdateRead ? isRead : null,
shouldUpdateFlagged ? isFlagged : null);
} }
private async Task ApplyDeletedUidsAsync(MailItemFolder folder, IList<UniqueId> uniqueIds) private async Task ApplyDeletedUidsAsync(MailItemFolder folder, IList<UniqueId> uniqueIds)
@@ -552,15 +665,14 @@ public class UnifiedImapSynchronizer
if (changedFlags == null || changedFlags.Count == 0) if (changedFlags == null || changedFlags.Count == 0)
return; return;
foreach (var changed in changedFlags) var stateUpdates = changedFlags
{ .Select(changed => new MailCopyStateUpdate(
var localMailCopyId = MailkitClientExtensions.CreateUid(folder.Id, changed.Key); MailkitClientExtensions.CreateUid(folder.Id, changed.Key),
var isFlagged = MailkitClientExtensions.GetIsFlagged(changed.Value); MailkitClientExtensions.GetIsRead(changed.Value),
var isRead = MailkitClientExtensions.GetIsRead(changed.Value); MailkitClientExtensions.GetIsFlagged(changed.Value)))
.ToList();
await _mailService.ChangeReadStatusAsync(localMailCopyId, isRead).ConfigureAwait(false); await _mailService.ApplyMailStateUpdatesAsync(stateUpdates).ConfigureAwait(false);
await _mailService.ChangeFlagStatusAsync(localMailCopyId, isFlagged).ConfigureAwait(false);
}
} }
private async Task ReconcileUidBasedFlagChangesAsync(MailItemFolder localFolder, IMailFolder remoteFolder, CancellationToken cancellationToken) private async Task ReconcileUidBasedFlagChangesAsync(MailItemFolder localFolder, IMailFolder remoteFolder, CancellationToken cancellationToken)
@@ -613,13 +725,14 @@ public class UnifiedImapSynchronizer
var existingMarkReadCandidates = await FilterExistingRemoteUidsAsync(remoteFolder, markReadCandidates, cancellationToken).ConfigureAwait(false); var existingMarkReadCandidates = await FilterExistingRemoteUidsAsync(remoteFolder, markReadCandidates, cancellationToken).ConfigureAwait(false);
var existingUnflagCandidates = await FilterExistingRemoteUidsAsync(remoteFolder, unflagCandidates, cancellationToken).ConfigureAwait(false); var existingUnflagCandidates = await FilterExistingRemoteUidsAsync(remoteFolder, unflagCandidates, cancellationToken).ConfigureAwait(false);
var pendingStateUpdates = new List<MailCopyStateUpdate>();
foreach (var uid in existingMarkReadCandidates) foreach (var uid in existingMarkReadCandidates)
{ {
if (!localByUid.TryGetValue(uid, out var localMail) || localMail.IsRead) if (!localByUid.TryGetValue(uid, out var localMail) || localMail.IsRead)
continue; continue;
await _mailService.ChangeReadStatusAsync(localMail.Id, true).ConfigureAwait(false); pendingStateUpdates.Add(new MailCopyStateUpdate(localMail.Id, IsRead: true));
} }
foreach (var uid in remoteUnreadUids) foreach (var uid in remoteUnreadUids)
@@ -627,7 +740,7 @@ public class UnifiedImapSynchronizer
if (!localByUid.TryGetValue(uid, out var localMail) || !localMail.IsRead) if (!localByUid.TryGetValue(uid, out var localMail) || !localMail.IsRead)
continue; continue;
await _mailService.ChangeReadStatusAsync(localMail.Id, false).ConfigureAwait(false); pendingStateUpdates.Add(new MailCopyStateUpdate(localMail.Id, IsRead: false));
} }
foreach (var uid in existingUnflagCandidates) foreach (var uid in existingUnflagCandidates)
@@ -635,7 +748,7 @@ public class UnifiedImapSynchronizer
if (!localByUid.TryGetValue(uid, out var localMail) || !localMail.IsFlagged) if (!localByUid.TryGetValue(uid, out var localMail) || !localMail.IsFlagged)
continue; continue;
await _mailService.ChangeFlagStatusAsync(localMail.Id, false).ConfigureAwait(false); pendingStateUpdates.Add(new MailCopyStateUpdate(localMail.Id, IsFlagged: false));
} }
foreach (var uid in remoteFlaggedUids) foreach (var uid in remoteFlaggedUids)
@@ -643,7 +756,12 @@ public class UnifiedImapSynchronizer
if (!localByUid.TryGetValue(uid, out var localMail) || localMail.IsFlagged) if (!localByUid.TryGetValue(uid, out var localMail) || localMail.IsFlagged)
continue; continue;
await _mailService.ChangeFlagStatusAsync(localMail.Id, true).ConfigureAwait(false); pendingStateUpdates.Add(new MailCopyStateUpdate(localMail.Id, IsFlagged: true));
}
if (pendingStateUpdates.Count > 0)
{
await _mailService.ApplyMailStateUpdatesAsync(pendingStateUpdates).ConfigureAwait(false);
} }
} }
+131 -41
View File
@@ -112,56 +112,104 @@ public class ImapSynchronizer : WinoSynchronizer<ImapRequest, ImapMessageCreatio
public override List<IRequestBundle<ImapRequest>> Move(BatchMoveRequest requests) public override List<IRequestBundle<ImapRequest>> Move(BatchMoveRequest requests)
{ {
return CreateTaskBundle(async (client, item) => if (requests == null || requests.Count == 0)
{ return [];
var sourceFolder = await client.GetFolderAsync(item.FromFolder.RemoteFolderId);
var destinationFolder = await client.GetFolderAsync(item.ToFolder.RemoteFolderId); return CreateSingleTaskBundle(async (client, _) =>
{
var sourceFolder = await client.GetFolderAsync(requests[0].FromFolder.RemoteFolderId).ConfigureAwait(false);
var destinationFolder = await client.GetFolderAsync(requests[0].ToFolder.RemoteFolderId).ConfigureAwait(false);
var uniqueIds = requests.Select(item => GetUniqueId(item.Item.Id)).ToList();
// Only opening source folder is enough.
await sourceFolder.OpenAsync(FolderAccess.ReadWrite).ConfigureAwait(false); await sourceFolder.OpenAsync(FolderAccess.ReadWrite).ConfigureAwait(false);
await sourceFolder.MoveToAsync(GetUniqueId(item.Item.Id), destinationFolder).ConfigureAwait(false); try
await sourceFolder.CloseAsync().ConfigureAwait(false); {
}, requests); await sourceFolder.MoveToAsync(uniqueIds, destinationFolder).ConfigureAwait(false);
}
finally
{
await sourceFolder.CloseAsync().ConfigureAwait(false);
}
}, requests[0], requests);
} }
public override List<IRequestBundle<ImapRequest>> ChangeFlag(BatchChangeFlagRequest requests) public override List<IRequestBundle<ImapRequest>> ChangeFlag(BatchChangeFlagRequest requests)
{ {
return CreateTaskBundle(async (client, item) => if (requests == null || requests.Count == 0)
return [];
return CreateSingleTaskBundle(async (client, _) =>
{ {
var folder = item.Item.AssignedFolder; var folder = requests[0].Item.AssignedFolder;
var remoteFolder = await client.GetFolderAsync(folder.RemoteFolderId); var remoteFolder = await client.GetFolderAsync(folder.RemoteFolderId).ConfigureAwait(false);
var uniqueIds = requests.Select(item => GetUniqueId(item.Item.Id)).ToList();
var request = new StoreFlagsRequest(requests[0].IsFlagged ? StoreAction.Add : StoreAction.Remove, MessageFlags.Flagged)
{
Silent = true
};
await remoteFolder.OpenAsync(FolderAccess.ReadWrite).ConfigureAwait(false); await remoteFolder.OpenAsync(FolderAccess.ReadWrite).ConfigureAwait(false);
await remoteFolder.StoreAsync(GetUniqueId(item.Item.Id), new StoreFlagsRequest(item.IsFlagged ? StoreAction.Add : StoreAction.Remove, MessageFlags.Flagged) { Silent = true }).ConfigureAwait(false); try
await remoteFolder.CloseAsync().ConfigureAwait(false); {
}, requests); await remoteFolder.StoreAsync(uniqueIds, request).ConfigureAwait(false);
}
finally
{
await remoteFolder.CloseAsync().ConfigureAwait(false);
}
}, requests[0], requests);
} }
public override List<IRequestBundle<ImapRequest>> Delete(BatchDeleteRequest requests) public override List<IRequestBundle<ImapRequest>> Delete(BatchDeleteRequest requests)
{ {
return CreateTaskBundle(async (client, request) => if (requests == null || requests.Count == 0)
return [];
return CreateSingleTaskBundle(async (client, _) =>
{ {
var folder = request.Item.AssignedFolder; var folder = requests[0].Item.AssignedFolder;
var remoteFolder = await client.GetFolderAsync(folder.RemoteFolderId).ConfigureAwait(false); var remoteFolder = await client.GetFolderAsync(folder.RemoteFolderId).ConfigureAwait(false);
var uniqueIds = requests.Select(request => GetUniqueId(request.Item.Id)).ToList();
var storeRequest = new StoreFlagsRequest(StoreAction.Add, MessageFlags.Deleted) { Silent = true };
await remoteFolder.OpenAsync(FolderAccess.ReadWrite).ConfigureAwait(false); await remoteFolder.OpenAsync(FolderAccess.ReadWrite).ConfigureAwait(false);
await remoteFolder.AddFlagsAsync(GetUniqueId(request.Item.Id), MessageFlags.Deleted, true); try
await remoteFolder.ExpungeAsync().ConfigureAwait(false); {
await remoteFolder.CloseAsync().ConfigureAwait(false); await remoteFolder.StoreAsync(uniqueIds, storeRequest).ConfigureAwait(false);
}, requests); await remoteFolder.ExpungeAsync(uniqueIds).ConfigureAwait(false);
}
finally
{
await remoteFolder.CloseAsync().ConfigureAwait(false);
}
}, requests[0], requests);
} }
public override List<IRequestBundle<ImapRequest>> MarkRead(BatchMarkReadRequest requests) public override List<IRequestBundle<ImapRequest>> MarkRead(BatchMarkReadRequest requests)
{ {
return CreateTaskBundle(async (client, request) => if (requests == null || requests.Count == 0)
return [];
return CreateSingleTaskBundle(async (client, _) =>
{ {
var folder = request.Item.AssignedFolder; var folder = requests[0].Item.AssignedFolder;
var remoteFolder = await client.GetFolderAsync(folder.RemoteFolderId); var remoteFolder = await client.GetFolderAsync(folder.RemoteFolderId).ConfigureAwait(false);
var uniqueIds = requests.Select(request => GetUniqueId(request.Item.Id)).ToList();
var storeRequest = new StoreFlagsRequest(requests[0].IsRead ? StoreAction.Add : StoreAction.Remove, MessageFlags.Seen)
{
Silent = true
};
await remoteFolder.OpenAsync(FolderAccess.ReadWrite).ConfigureAwait(false); await remoteFolder.OpenAsync(FolderAccess.ReadWrite).ConfigureAwait(false);
await remoteFolder.StoreAsync(GetUniqueId(request.Item.Id), new StoreFlagsRequest(request.IsRead ? StoreAction.Add : StoreAction.Remove, MessageFlags.Seen) { Silent = true }).ConfigureAwait(false); try
await remoteFolder.CloseAsync().ConfigureAwait(false); {
}, requests); await remoteFolder.StoreAsync(uniqueIds, storeRequest).ConfigureAwait(false);
}
finally
{
await remoteFolder.CloseAsync().ConfigureAwait(false);
}
}, requests[0], requests);
} }
public override List<IRequestBundle<ImapRequest>> CreateDraft(CreateDraftRequest request) public override List<IRequestBundle<ImapRequest>> CreateDraft(CreateDraftRequest request)
@@ -718,13 +766,7 @@ public class ImapSynchronizer : WinoSynchronizer<ImapRequest, ImapMessageCreatio
// First apply the UI changes for each bundle. // First apply the UI changes for each bundle.
// This is important to reflect changes to the UI before the network call is done. // This is important to reflect changes to the UI before the network call is done.
foreach (var item in batchedRequests) ApplyOptimisticUiChanges(batchedRequests, ShouldApplyOptimisticUIChanges);
{
if (ShouldApplyOptimisticUIChanges(item.Request))
{
item.Request.ApplyUIChanges();
}
}
// All task bundles will execute on the same client. // All task bundles will execute on the same client.
// Tasks themselves don't pull the client from the pool // Tasks themselves don't pull the client from the pool
@@ -754,7 +796,7 @@ public class ImapSynchronizer : WinoSynchronizer<ImapRequest, ImapMessageCreatio
if (ShouldApplyOptimisticUIChanges(item.Request)) if (ShouldApplyOptimisticUIChanges(item.Request))
{ {
item.Request.RevertUIChanges(); item.UIChangeRequest?.RevertUIChanges();
} }
isCrashed = true; isCrashed = true;
@@ -795,7 +837,7 @@ public class ImapSynchronizer : WinoSynchronizer<ImapRequest, ImapMessageCreatio
if (ShouldApplyOptimisticUIChanges(item.Request)) if (ShouldApplyOptimisticUIChanges(item.Request))
{ {
item.Request.RevertUIChanges(); item.UIChangeRequest?.RevertUIChanges();
} }
throw; throw;
} }
@@ -1480,7 +1522,7 @@ public class ImapSynchronizer : WinoSynchronizer<ImapRequest, ImapMessageCreatio
.ToDictionary(g => g.Key, g => g.First(), StringComparer.OrdinalIgnoreCase); .ToDictionary(g => g.Key, g => g.First(), StringComparer.OrdinalIgnoreCase);
var usedCalendarColors = new HashSet<string>(StringComparer.OrdinalIgnoreCase); var usedCalendarColors = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
var remotePrimaryCalendarId = remoteCalendars.FirstOrDefault()?.RemoteCalendarId; var remotePrimaryCalendarId = GetPrimaryCalDavCalendarId(remoteCalendars);
foreach (var localCalendar in localCalendars.ToList()) foreach (var localCalendar in localCalendars.ToList())
{ {
@@ -1503,6 +1545,7 @@ public class ImapSynchronizer : WinoSynchronizer<ImapRequest, ImapMessageCreatio
if (existingLocal == null) if (existingLocal == null)
{ {
var insertedCalendarColor = ResolveSynchronizedCalendarBackgroundColor(remoteCalendar.BackgroundColorHex, null, usedCalendarColors);
var newCalendar = new AccountCalendar var newCalendar = new AccountCalendar
{ {
Id = Guid.NewGuid(), Id = Guid.NewGuid(),
@@ -1510,10 +1553,12 @@ public class ImapSynchronizer : WinoSynchronizer<ImapRequest, ImapMessageCreatio
RemoteCalendarId = remoteCalendar.RemoteCalendarId, RemoteCalendarId = remoteCalendar.RemoteCalendarId,
Name = remoteCalendar.Name, Name = remoteCalendar.Name,
IsPrimary = isPrimary, IsPrimary = isPrimary,
IsReadOnly = remoteCalendar.IsReadOnly,
IsSynchronizationEnabled = true, IsSynchronizationEnabled = true,
IsExtended = true, IsExtended = true,
BackgroundColorHex = ColorHelpers.GetDistinctFlatColorHex(usedCalendarColors), DefaultShowAs = remoteCalendar.DefaultShowAs,
TimeZone = "UTC", BackgroundColorHex = insertedCalendarColor,
TimeZone = remoteCalendar.TimeZone,
SynchronizationDeltaToken = string.Empty SynchronizationDeltaToken = string.Empty
}; };
@@ -1523,10 +1568,15 @@ public class ImapSynchronizer : WinoSynchronizer<ImapRequest, ImapMessageCreatio
continue; continue;
} }
var resolvedColor = ColorHelpers.GetDistinctFlatColorHex(usedCalendarColors, existingLocal.BackgroundColorHex); var resolvedColor = ResolveSynchronizedCalendarBackgroundColor(remoteCalendar.BackgroundColorHex, existingLocal, usedCalendarColors);
var resolvedTextColor = ColorHelpers.GetReadableTextColorHex(resolvedColor);
var shouldUpdate = !string.Equals(existingLocal.Name, remoteCalendar.Name, StringComparison.Ordinal) var shouldUpdate = !string.Equals(existingLocal.Name, remoteCalendar.Name, StringComparison.Ordinal)
|| !string.Equals(existingLocal.TimeZone, remoteCalendar.TimeZone, StringComparison.OrdinalIgnoreCase)
|| existingLocal.IsReadOnly != remoteCalendar.IsReadOnly
|| existingLocal.DefaultShowAs != remoteCalendar.DefaultShowAs
|| existingLocal.IsPrimary != isPrimary || existingLocal.IsPrimary != isPrimary
|| !string.Equals(existingLocal.BackgroundColorHex, resolvedColor, StringComparison.OrdinalIgnoreCase); || !string.Equals(existingLocal.BackgroundColorHex, resolvedColor, StringComparison.OrdinalIgnoreCase)
|| !string.Equals(existingLocal.TextColorHex, resolvedTextColor, StringComparison.OrdinalIgnoreCase);
if (!shouldUpdate) if (!shouldUpdate)
{ {
@@ -1535,14 +1585,54 @@ public class ImapSynchronizer : WinoSynchronizer<ImapRequest, ImapMessageCreatio
} }
existingLocal.Name = remoteCalendar.Name; existingLocal.Name = remoteCalendar.Name;
existingLocal.TimeZone = remoteCalendar.TimeZone;
existingLocal.IsReadOnly = remoteCalendar.IsReadOnly;
existingLocal.DefaultShowAs = remoteCalendar.DefaultShowAs;
existingLocal.IsPrimary = isPrimary; existingLocal.IsPrimary = isPrimary;
existingLocal.BackgroundColorHex = resolvedColor; existingLocal.BackgroundColorHex = resolvedColor;
existingLocal.TextColorHex = ColorHelpers.GetReadableTextColorHex(existingLocal.BackgroundColorHex); existingLocal.TextColorHex = resolvedTextColor;
usedCalendarColors.Add(existingLocal.BackgroundColorHex); usedCalendarColors.Add(existingLocal.BackgroundColorHex);
await _imapChangeProcessor.UpdateAccountCalendarAsync(existingLocal).ConfigureAwait(false); await _imapChangeProcessor.UpdateAccountCalendarAsync(existingLocal).ConfigureAwait(false);
} }
} }
private static string GetPrimaryCalDavCalendarId(IReadOnlyList<CalDavCalendar> remoteCalendars)
{
if (remoteCalendars == null || remoteCalendars.Count == 0)
return string.Empty;
if (remoteCalendars.Any(calendar => calendar.Order.HasValue))
{
return remoteCalendars
.OrderBy(calendar => calendar.Order ?? double.MaxValue)
.ThenBy(calendar => calendar.Name, StringComparer.OrdinalIgnoreCase)
.Select(calendar => calendar.RemoteCalendarId)
.FirstOrDefault() ?? string.Empty;
}
return remoteCalendars.First().RemoteCalendarId;
}
private static string ResolveSynchronizedCalendarBackgroundColor(
string remoteBackgroundColor,
AccountCalendar accountCalendar,
ISet<string> usedCalendarColors = null)
{
if (accountCalendar?.IsBackgroundColorUserOverridden == true)
return accountCalendar.BackgroundColorHex;
var preferredColor = string.IsNullOrWhiteSpace(remoteBackgroundColor)
? accountCalendar?.BackgroundColorHex
: remoteBackgroundColor;
if (string.IsNullOrWhiteSpace(remoteBackgroundColor) && usedCalendarColors != null)
return ColorHelpers.GetDistinctFlatColorHex(usedCalendarColors, preferredColor);
return string.IsNullOrWhiteSpace(preferredColor)
? ColorHelpers.GenerateFlatColorHex()
: preferredColor;
}
private interface IImapCalendarOperationHandler private interface IImapCalendarOperationHandler
{ {
bool RequiresConnectedClient { get; } bool RequiresConnectedClient { get; }
@@ -2020,10 +2020,7 @@ public class OutlookSynchronizer : WinoSynchronizer<RequestInformation, Message,
{ {
// First apply all UI changes immediately before any batching. // First apply all UI changes immediately before any batching.
// This ensures UI reflects changes right away, regardless of batch processing. // This ensures UI reflects changes right away, regardless of batch processing.
foreach (var bundle in batchedRequests) ApplyOptimisticUiChanges(batchedRequests);
{
bundle.UIChangeRequest?.ApplyUIChanges();
}
// SendDraft requests may include large attachments, which require upload sessions. // SendDraft requests may include large attachments, which require upload sessions.
// Upload these attachments before the batched patch/send sequence. // Upload these attachments before the batched patch/send sequence.
+7 -7
View File
@@ -161,11 +161,11 @@ public abstract class WinoSynchronizer<TBaseRequest, TMessageType, TCalendarEven
foreach (var group in keys) foreach (var group in keys)
{ {
var key = group.Key; var firstRequest = group.FirstOrDefault();
if (key is MailSynchronizerOperation mailSynchronizerOperation) if (firstRequest is IMailActionRequest mailActionRequest)
{ {
switch (mailSynchronizerOperation) switch (mailActionRequest.Operation)
{ {
case MailSynchronizerOperation.MarkRead: case MailSynchronizerOperation.MarkRead:
nativeRequests.AddRange(MarkRead(new BatchMarkReadRequest(group.Cast<MarkReadRequest>()))); nativeRequests.AddRange(MarkRead(new BatchMarkReadRequest(group.Cast<MarkReadRequest>())));
@@ -204,9 +204,9 @@ public abstract class WinoSynchronizer<TBaseRequest, TMessageType, TCalendarEven
break; break;
} }
} }
else if (key is FolderSynchronizerOperation folderSynchronizerOperation) else if (firstRequest is IFolderActionRequest folderActionRequest)
{ {
switch (folderSynchronizerOperation) switch (folderActionRequest.Operation)
{ {
case FolderSynchronizerOperation.RenameFolder: case FolderSynchronizerOperation.RenameFolder:
nativeRequests.AddRange(RenameFolder(group.ElementAt(0) as RenameFolderRequest)); nativeRequests.AddRange(RenameFolder(group.ElementAt(0) as RenameFolderRequest));
@@ -230,9 +230,9 @@ public abstract class WinoSynchronizer<TBaseRequest, TMessageType, TCalendarEven
break; break;
} }
} }
else if (key is CategorySynchronizerOperation categorySynchronizerOperation) else if (firstRequest is ICategoryActionRequest categoryActionRequest)
{ {
switch (categorySynchronizerOperation) switch (categoryActionRequest.Operation)
{ {
case CategorySynchronizerOperation.CreateCategory: case CategorySynchronizerOperation.CreateCategory:
nativeRequests.AddRange(CreateCategory(group.ElementAt(0) as MailCategoryCreateRequest)); nativeRequests.AddRange(CreateCategory(group.ElementAt(0) as MailCategoryCreateRequest));
@@ -6,6 +6,7 @@ using FluentAssertions;
using Wino.Core.Domain.Entities.Mail; using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Enums; using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces; using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.MailItem;
using Wino.Mail.ViewModels.Collections; using Wino.Mail.ViewModels.Collections;
using Wino.Mail.ViewModels.Data; using Wino.Mail.ViewModels.Data;
using Xunit; using Xunit;
@@ -167,7 +168,7 @@ public class WinoMailCollectionTests
groupItems.Add(item); groupItems.Add(item);
} }
groups.Add(((DateTime)group.Key, groupItems)); groups.Add((((MailListGroupKey)group.Key).Value is DateTime keyDate ? keyDate : default, groupItems));
} }
groups.Should().NotBeEmpty(); groups.Should().NotBeEmpty();
@@ -188,6 +189,45 @@ public class WinoMailCollectionTests
} }
} }
[Fact]
public async Task AddRangeAsync_ShouldPlacePinnedItemsBeforeUnpinnedItems()
{
var sut = CreateCollection();
var olderPinned = CreateMailCopy(threadId: "pinned", creationDate: DateTime.UtcNow.AddDays(-3));
olderPinned.IsPinned = true;
var newerUnpinned = CreateMailCopy(threadId: "regular", creationDate: DateTime.UtcNow);
await sut.AddRangeAsync(
[
new MailItemViewModel(newerUnpinned),
new MailItemViewModel(olderPinned)
],
clearIdCache: true);
var firstItem = FlattenItems(sut).First().Should().BeOfType<MailItemViewModel>().Subject;
firstItem.MailCopy.UniqueId.Should().Be(olderPinned.UniqueId);
}
[Fact]
public async Task UpdateMailCopy_ShouldMovePinnedItemToTop()
{
var sut = CreateCollection();
var older = CreateMailCopy(threadId: "older", creationDate: DateTime.UtcNow.AddDays(-2));
var newer = CreateMailCopy(threadId: "newer", creationDate: DateTime.UtcNow);
await sut.AddAsync(older);
await sut.AddAsync(newer);
var updatedOlder = CloneMailCopy(older);
updatedOlder.IsPinned = true;
await sut.UpdateMailCopy(updatedOlder, EntityUpdateSource.Server, MailCopyChangeFlags.IsPinned);
var firstItem = FlattenItems(sut).First().Should().BeOfType<MailItemViewModel>().Subject;
firstItem.MailCopy.UniqueId.Should().Be(older.UniqueId);
}
[Fact] [Fact]
public async Task UpdateMailCopy_ShouldMergeExistingSingles_WhenThreadIdChangesToMatch() public async Task UpdateMailCopy_ShouldMergeExistingSingles_WhenThreadIdChangesToMatch()
{ {
@@ -371,6 +411,7 @@ public class WinoMailCollectionTests
Importance = source.Importance, Importance = source.Importance,
IsRead = source.IsRead, IsRead = source.IsRead,
IsFlagged = source.IsFlagged, IsFlagged = source.IsFlagged,
IsPinned = source.IsPinned,
IsFocused = source.IsFocused, IsFocused = source.IsFocused,
HasAttachments = source.HasAttachments, HasAttachments = source.HasAttachments,
ItemType = source.ItemType, ItemType = source.ItemType,
@@ -59,6 +59,29 @@ public class MailItemViewModelUpdateTests
nameof(MailItemViewModel.SortingName)); nameof(MailItemViewModel.SortingName));
} }
[Fact]
public void UpdateFrom_ShouldNotifyPinnedState_WhenPinnedChanges()
{
var original = CreateMailCopy("thread-1", DateTime.UtcNow);
var updated = CloneMailCopy(original);
updated.IsPinned = true;
var sut = new MailItemViewModel(original);
var raisedProperties = new List<string>();
sut.PropertyChanged += (_, e) =>
{
if (!string.IsNullOrEmpty(e.PropertyName))
{
raisedProperties.Add(e.PropertyName);
}
};
sut.UpdateFrom(updated);
raisedProperties.Should().Contain(nameof(MailItemViewModel.IsPinned));
}
[Fact] [Fact]
public async Task UpdateMailCopy_ShouldNotifyThreadOnlyForReadState_WhenReadStateChanges() public async Task UpdateMailCopy_ShouldNotifyThreadOnlyForReadState_WhenReadStateChanges()
{ {
@@ -125,6 +148,7 @@ public class MailItemViewModelUpdateTests
Importance = MailImportance.Normal, Importance = MailImportance.Normal,
IsRead = false, IsRead = false,
IsFlagged = false, IsFlagged = false,
IsPinned = false,
IsFocused = false, IsFocused = false,
HasAttachments = false, HasAttachments = false,
ItemType = MailItemType.Mail, ItemType = MailItemType.Mail,
@@ -151,6 +175,7 @@ public class MailItemViewModelUpdateTests
Importance = source.Importance, Importance = source.Importance,
IsRead = source.IsRead, IsRead = source.IsRead,
IsFlagged = source.IsFlagged, IsFlagged = source.IsFlagged,
IsPinned = source.IsPinned,
IsFocused = source.IsFocused, IsFocused = source.IsFocused,
HasAttachments = source.HasAttachments, HasAttachments = source.HasAttachments,
ItemType = source.ItemType, ItemType = source.ItemType,
@@ -17,6 +17,7 @@ using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Accounts; using Wino.Core.Domain.Models.Accounts;
using Wino.Core.Domain.Models.Folders; using Wino.Core.Domain.Models.Folders;
using Wino.Core.Domain.Models.Navigation; using Wino.Core.Domain.Models.Navigation;
using Wino.Core.Domain.Models.Synchronization;
using Wino.Core.Misc; using Wino.Core.Misc;
using Wino.Core.Services; using Wino.Core.Services;
using Wino.Core.ViewModels.Data; using Wino.Core.ViewModels.Data;
@@ -96,8 +97,14 @@ public partial class AccountDetailsPageViewModel : MailBaseViewModel
[ObservableProperty] [ObservableProperty]
private bool isTaskbarBadgeEnabled; private bool isTaskbarBadgeEnabled;
[ObservableProperty]
public partial AccountCapabilityOption SelectedCapabilityOption { get; set; }
public bool IsFocusedInboxSupportedForAccount => Account != null && Account.Preferences.IsFocusedInboxEnabled != null; public bool IsFocusedInboxSupportedForAccount => Account != null && Account.Preferences.IsFocusedInboxEnabled != null;
public bool IsImapServer => ServerInformation != null; public bool IsImapServer => ServerInformation != null;
public bool HasMailAccess => Account?.IsMailAccessGranted == true;
public bool HasCalendarAccess => Account?.IsCalendarAccessGranted == true;
public bool IsOAuthCapabilityEditable => Account?.ProviderType is MailProviderType.Outlook or MailProviderType.Gmail;
public string ProviderIconPath => Account?.SpecialImapProvider != SpecialImapProvider.None public string ProviderIconPath => Account?.SpecialImapProvider != SpecialImapProvider.None
? $"ms-appx:///Assets/Providers/{Account.SpecialImapProvider}.png" ? $"ms-appx:///Assets/Providers/{Account.SpecialImapProvider}.png"
: $"ms-appx:///Assets/Providers/{Account?.ProviderType}.png"; : $"ms-appx:///Assets/Providers/{Account?.ProviderType}.png";
@@ -130,6 +137,13 @@ public partial class AccountDetailsPageViewModel : MailBaseViewModel
new ImapConnectionSecurityModel(Core.Domain.Enums.ImapConnectionSecurity.None, Translator.ImapConnectionSecurity_None) new ImapConnectionSecurityModel(Core.Domain.Enums.ImapConnectionSecurity.None, Translator.ImapConnectionSecurity_None)
]; ];
public List<AccountCapabilityOption> CapabilityOptions { get; } =
[
new(true, false, Translator.AccountCapability_MailOnly),
new(false, true, Translator.AccountCapability_CalendarOnly),
new(true, true, Translator.AccountCapability_MailAndCalendar)
];
public AccountDetailsPageViewModel(IMailDialogService dialogService, public AccountDetailsPageViewModel(IMailDialogService dialogService,
IAccountService accountService, IAccountService accountService,
@@ -262,6 +276,7 @@ public partial class AccountDetailsPageViewModel : MailBaseViewModel
AccountName = Account.Name; AccountName = Account.Name;
SenderName = Account.SenderName; SenderName = Account.SenderName;
ServerInformation = Account.ServerInformation; ServerInformation = Account.ServerInformation;
SelectedCapabilityOption = ResolveCapabilityOption(Account.IsMailAccessGranted, Account.IsCalendarAccessGranted);
IsFocusedInboxEnabled = Account.Preferences.IsFocusedInboxEnabled.GetValueOrDefault(); IsFocusedInboxEnabled = Account.Preferences.IsFocusedInboxEnabled.GetValueOrDefault();
AreNotificationsEnabled = Account.Preferences.IsNotificationsEnabled; AreNotificationsEnabled = Account.Preferences.IsNotificationsEnabled;
@@ -288,7 +303,11 @@ public partial class AccountDetailsPageViewModel : MailBaseViewModel
SelectedOutgoingServerConnectionSecurityIndex = AvailableConnectionSecurities.FindIndex(a => a.ImapConnectionSecurity == ServerInformation.OutgoingServerSocketOption); SelectedOutgoingServerConnectionSecurityIndex = AvailableConnectionSecurities.FindIndex(a => a.ImapConnectionSecurity == ServerInformation.OutgoingServerSocketOption);
} }
SelectedTabIndex = _statePersistanceService.ApplicationMode == WinoApplicationMode.Calendar ? 2 : 1; SelectedTabIndex = _statePersistanceService.ApplicationMode == WinoApplicationMode.Calendar && HasCalendarAccess
? 2
: HasMailAccess
? 1
: 0;
var folderStructures = (await _folderService.GetFolderStructureForAccountAsync(Account.Id, true)).Folders; var folderStructures = (await _folderService.GetFolderStructureForAccountAsync(Account.Id, true)).Folders;
@@ -382,11 +401,15 @@ public partial class AccountDetailsPageViewModel : MailBaseViewModel
partial void OnAccountChanged(MailAccount value) partial void OnAccountChanged(MailAccount value)
{ {
SelectedCapabilityOption = ResolveCapabilityOption(value?.IsMailAccessGranted == true, value?.IsCalendarAccessGranted == true);
OnPropertyChanged(nameof(IsFocusedInboxSupportedForAccount)); OnPropertyChanged(nameof(IsFocusedInboxSupportedForAccount));
OnPropertyChanged(nameof(ProviderIconPath)); OnPropertyChanged(nameof(ProviderIconPath));
OnPropertyChanged(nameof(Address)); OnPropertyChanged(nameof(Address));
OnPropertyChanged(nameof(IsInitialSynchronizationSummaryVisible)); OnPropertyChanged(nameof(IsInitialSynchronizationSummaryVisible));
OnPropertyChanged(nameof(InitialSynchronizationSummary)); OnPropertyChanged(nameof(InitialSynchronizationSummary));
OnPropertyChanged(nameof(HasMailAccess));
OnPropertyChanged(nameof(HasCalendarAccess));
OnPropertyChanged(nameof(IsOAuthCapabilityEditable));
} }
protected override async void OnPropertyChanged(PropertyChangedEventArgs e) protected override async void OnPropertyChanged(PropertyChangedEventArgs e)
@@ -417,6 +440,21 @@ public partial class AccountDetailsPageViewModel : MailBaseViewModel
Account.Preferences.IsTaskbarBadgeEnabled = IsTaskbarBadgeEnabled; Account.Preferences.IsTaskbarBadgeEnabled = IsTaskbarBadgeEnabled;
await _accountService.UpdateAccountAsync(Account); await _accountService.UpdateAccountAsync(Account);
break; break;
case nameof(SelectedCapabilityOption) when IsOAuthCapabilityEditable && SelectedCapabilityOption != null:
if (Account.IsMailAccessGranted == SelectedCapabilityOption.IsMailAccessGranted &&
Account.IsCalendarAccessGranted == SelectedCapabilityOption.IsCalendarAccessGranted)
break;
try
{
await UpdateOAuthCapabilityAsync(SelectedCapabilityOption);
}
catch (Exception ex)
{
await ExecuteUIThread(() => SelectedCapabilityOption = ResolveCapabilityOption(Account.IsMailAccessGranted, Account.IsCalendarAccessGranted));
_dialogService.InfoBarMessage(Translator.GeneralTitle_Error, ex.Message, InfoBarMessageType.Error);
}
break;
case nameof(SelectedPrimaryCalendar) when SelectedPrimaryCalendar != null: case nameof(SelectedPrimaryCalendar) when SelectedPrimaryCalendar != null:
foreach (var calendar in AccountCalendars) foreach (var calendar in AccountCalendars)
{ {
@@ -427,6 +465,111 @@ public partial class AccountDetailsPageViewModel : MailBaseViewModel
break; break;
} }
} }
private AccountCapabilityOption ResolveCapabilityOption(bool isMailAccessGranted, bool isCalendarAccessGranted)
=> CapabilityOptions.First(option =>
option.IsMailAccessGranted == isMailAccessGranted &&
option.IsCalendarAccessGranted == isCalendarAccessGranted);
private async Task UpdateOAuthCapabilityAsync(AccountCapabilityOption selectedOption)
{
var previousMailAccess = Account.IsMailAccessGranted;
var previousCalendarAccess = Account.IsCalendarAccessGranted;
var requiresReauthorization = (selectedOption.IsMailAccessGranted && !previousMailAccess) ||
(selectedOption.IsCalendarAccessGranted && !previousCalendarAccess);
try
{
if (requiresReauthorization)
{
Account.IsMailAccessGranted = selectedOption.IsMailAccessGranted;
Account.IsCalendarAccessGranted = selectedOption.IsCalendarAccessGranted;
await SynchronizationManager.Instance.HandleAuthorizationAsync(
Account.ProviderType,
Account,
Account.ProviderType == MailProviderType.Gmail);
}
}
catch
{
Account.IsMailAccessGranted = previousMailAccess;
Account.IsCalendarAccessGranted = previousCalendarAccess;
throw;
}
Account.IsMailAccessGranted = selectedOption.IsMailAccessGranted;
Account.IsCalendarAccessGranted = selectedOption.IsCalendarAccessGranted;
await _accountService.UpdateAccountAsync(Account);
if (selectedOption.IsMailAccessGranted && !previousMailAccess)
{
await SynchronizationManager.Instance.SynchronizeProfileAsync(Account.Id);
await SynchronizationManager.Instance.SynchronizeMailAsync(new MailSynchronizationOptions
{
AccountId = Account.Id,
Type = MailSynchronizationType.FullFolders
});
if (Account.ProviderType == MailProviderType.Outlook)
{
await SynchronizationManager.Instance.SynchronizeMailAsync(new MailSynchronizationOptions
{
AccountId = Account.Id,
Type = MailSynchronizationType.Categories
});
}
if (!string.IsNullOrWhiteSpace(Account.Address))
{
var aliases = await _accountService.GetAccountAliasesAsync(Account.Id);
var hasRootAlias = aliases.Any(alias => alias.IsRootAlias);
if (!hasRootAlias)
{
await _accountService.CreateRootAliasAsync(Account.Id, Account.Address);
}
}
await SynchronizationManager.Instance.SynchronizeMailAsync(new MailSynchronizationOptions
{
AccountId = Account.Id,
Type = MailSynchronizationType.Alias
});
}
if (selectedOption.IsCalendarAccessGranted && !previousCalendarAccess)
{
await SynchronizationManager.Instance.SynchronizeCalendarAsync(new CalendarSynchronizationOptions
{
AccountId = Account.Id,
Type = CalendarSynchronizationType.CalendarMetadata
});
}
var refreshedAccount = await _accountService.GetAccountAsync(Account.Id);
await ExecuteUIThread(() =>
{
Account = refreshedAccount;
AccountName = refreshedAccount.Name;
SenderName = refreshedAccount.SenderName;
EnsureSelectedTabForCapabilities();
});
}
private void EnsureSelectedTabForCapabilities()
{
if (SelectedTabIndex == 1 && !HasMailAccess)
{
SelectedTabIndex = HasCalendarAccess ? 2 : 0;
}
else if (SelectedTabIndex == 2 && !HasCalendarAccess)
{
SelectedTabIndex = HasMailAccess ? 1 : 0;
}
}
} }
public sealed class AccountCalendarShowAsOption public sealed class AccountCalendarShowAsOption
@@ -441,6 +584,20 @@ public sealed class AccountCalendarShowAsOption
} }
} }
public sealed class AccountCapabilityOption
{
public bool IsMailAccessGranted { get; }
public bool IsCalendarAccessGranted { get; }
public string DisplayText { get; }
public AccountCapabilityOption(bool isMailAccessGranted, bool isCalendarAccessGranted, string displayText)
{
IsMailAccessGranted = isMailAccessGranted;
IsCalendarAccessGranted = isCalendarAccessGranted;
DisplayText = displayText;
}
}
public partial class AccountCalendarSettingsItemViewModel : ObservableObject public partial class AccountCalendarSettingsItemViewModel : ObservableObject
{ {
public AccountCalendar Calendar { get; } public AccountCalendar Calendar { get; }
@@ -103,7 +103,10 @@ public partial class AccountManagementViewModel : AccountManagementPageViewModel
return; return;
} }
Messenger.Send(new BreadcrumbNavigationRequested(Translator.WelcomeWizard_Step2Title, WinoPage.ProviderSelectionPage)); Messenger.Send(new BreadcrumbNavigationRequested(
Translator.WelcomeWizard_Step2Title,
WinoPage.ProviderSelectionPage,
ProviderSelectionNavigationContext.CreateForSettingsAddAccount()));
} }
public Task StartAddNewAccountAsync() => AddNewAccountAsync(); public Task StartAddNewAccountAsync() => AddNewAccountAsync();

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