diff --git a/src/Umbraco.Cms.Api.Common/DependencyInjection/UmbracoBuilderAuthExtensions.cs b/src/Umbraco.Cms.Api.Common/DependencyInjection/UmbracoBuilderAuthExtensions.cs
index 1558329746..0139bb61ce 100644
--- a/src/Umbraco.Cms.Api.Common/DependencyInjection/UmbracoBuilderAuthExtensions.cs
+++ b/src/Umbraco.Cms.Api.Common/DependencyInjection/UmbracoBuilderAuthExtensions.cs
@@ -46,7 +46,9 @@ public static class UmbracoBuilderAuthExtensions
Paths.BackOfficeApi.LogoutEndpoint.TrimStart(Constants.CharArrays.ForwardSlash))
.SetRevocationEndpointUris(
Paths.MemberApi.RevokeEndpoint.TrimStart(Constants.CharArrays.ForwardSlash),
- Paths.BackOfficeApi.RevokeEndpoint.TrimStart(Constants.CharArrays.ForwardSlash));
+ Paths.BackOfficeApi.RevokeEndpoint.TrimStart(Constants.CharArrays.ForwardSlash))
+ .SetUserInfoEndpointUris(
+ Paths.MemberApi.UserinfoEndpoint.TrimStart(Constants.CharArrays.ForwardSlash));
// Enable authorization code flow with PKCE
options
@@ -62,7 +64,8 @@ public static class UmbracoBuilderAuthExtensions
.UseAspNetCore()
.EnableAuthorizationEndpointPassthrough()
.EnableTokenEndpointPassthrough()
- .EnableEndSessionEndpointPassthrough();
+ .EnableEndSessionEndpointPassthrough()
+ .EnableUserInfoEndpointPassthrough();
// Enable reference tokens
// - see https://documentation.openiddict.com/configuration/token-storage.html
diff --git a/src/Umbraco.Cms.Api.Common/Security/Paths.cs b/src/Umbraco.Cms.Api.Common/Security/Paths.cs
index 61e89ed3a3..916ab228ff 100644
--- a/src/Umbraco.Cms.Api.Common/Security/Paths.cs
+++ b/src/Umbraco.Cms.Api.Common/Security/Paths.cs
@@ -31,6 +31,8 @@ public static class Paths
public static readonly string RevokeEndpoint = EndpointPath($"{EndpointTemplate}/revoke");
+ public static readonly string UserinfoEndpoint = EndpointPath($"{EndpointTemplate}/userinfo");
+
// NOTE: we're NOT using /api/v1.0/ here because it will clash with the Delivery API docs
private static string EndpointPath(string relativePath) => $"/umbraco/delivery/api/v1/{relativePath}";
}
diff --git a/src/Umbraco.Cms.Api.Delivery/Controllers/Content/ContentApiControllerBase.cs b/src/Umbraco.Cms.Api.Delivery/Controllers/Content/ContentApiControllerBase.cs
index 4637055c11..1db4d9d395 100644
--- a/src/Umbraco.Cms.Api.Delivery/Controllers/Content/ContentApiControllerBase.cs
+++ b/src/Umbraco.Cms.Api.Delivery/Controllers/Content/ContentApiControllerBase.cs
@@ -15,6 +15,7 @@ namespace Umbraco.Cms.Api.Delivery.Controllers.Content;
[ApiExplorerSettings(GroupName = "Content")]
[LocalizeFromAcceptLanguageHeader]
[ValidateStartItem]
+[AddVaryHeader]
[OutputCache(PolicyName = Constants.DeliveryApi.OutputCache.ContentCachePolicy)]
public abstract class ContentApiControllerBase : DeliveryApiControllerBase
{
diff --git a/src/Umbraco.Cms.Api.Delivery/Controllers/Security/CurrentMemberController.cs b/src/Umbraco.Cms.Api.Delivery/Controllers/Security/CurrentMemberController.cs
new file mode 100644
index 0000000000..41d1970d06
--- /dev/null
+++ b/src/Umbraco.Cms.Api.Delivery/Controllers/Security/CurrentMemberController.cs
@@ -0,0 +1,28 @@
+using Asp.Versioning;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+using OpenIddict.Server.AspNetCore;
+using Umbraco.Cms.Api.Delivery.Routing;
+using Umbraco.Cms.Core.DeliveryApi;
+
+namespace Umbraco.Cms.Api.Delivery.Controllers.Security;
+
+[ApiVersion("1.0")]
+[ApiController]
+[VersionedDeliveryApiRoute(Common.Security.Paths.MemberApi.EndpointTemplate)]
+[ApiExplorerSettings(IgnoreApi = true)]
+[Authorize(AuthenticationSchemes = OpenIddictServerAspNetCoreDefaults.AuthenticationScheme)]
+public class CurrentMemberController : DeliveryApiControllerBase
+{
+ private readonly ICurrentMemberClaimsProvider _currentMemberClaimsProvider;
+
+ public CurrentMemberController(ICurrentMemberClaimsProvider currentMemberClaimsProvider)
+ => _currentMemberClaimsProvider = currentMemberClaimsProvider;
+
+ [HttpGet("userinfo")]
+ public async Task Userinfo()
+ {
+ Dictionary claims = await _currentMemberClaimsProvider.GetClaimsAsync();
+ return Ok(claims);
+ }
+}
diff --git a/src/Umbraco.Cms.Api.Delivery/DependencyInjection/UmbracoBuilderExtensions.cs b/src/Umbraco.Cms.Api.Delivery/DependencyInjection/UmbracoBuilderExtensions.cs
index 77f2cae93c..89065a5d2e 100644
--- a/src/Umbraco.Cms.Api.Delivery/DependencyInjection/UmbracoBuilderExtensions.cs
+++ b/src/Umbraco.Cms.Api.Delivery/DependencyInjection/UmbracoBuilderExtensions.cs
@@ -61,6 +61,7 @@ public static class UmbracoBuilderExtensions
builder.Services.AddSingleton();
builder.Services.AddTransient();
builder.Services.AddTransient();
+ builder.Services.AddTransient();
builder.Services.AddScoped();
builder.Services.ConfigureOptions();
diff --git a/src/Umbraco.Cms.Api.Delivery/Filters/AddVaryHeaderAttribute.cs b/src/Umbraco.Cms.Api.Delivery/Filters/AddVaryHeaderAttribute.cs
new file mode 100644
index 0000000000..f8905e72d5
--- /dev/null
+++ b/src/Umbraco.Cms.Api.Delivery/Filters/AddVaryHeaderAttribute.cs
@@ -0,0 +1,13 @@
+using Microsoft.AspNetCore.Mvc.Filters;
+
+namespace Umbraco.Cms.Api.Delivery.Filters;
+
+public sealed class AddVaryHeaderAttribute : ActionFilterAttribute
+{
+ private const string Vary = "Accept-Language, Preview, Start-Item";
+
+ public override void OnResultExecuting(ResultExecutingContext context)
+ => context.HttpContext.Response.Headers.Vary = context.HttpContext.Response.Headers.Vary.Count > 0
+ ? $"{context.HttpContext.Response.Headers.Vary}, {Vary}"
+ : Vary;
+}
diff --git a/src/Umbraco.Cms.Api.Delivery/Json/DeliveryApiVersionAwareJsonConverterBase.cs b/src/Umbraco.Cms.Api.Delivery/Json/DeliveryApiVersionAwareJsonConverterBase.cs
new file mode 100644
index 0000000000..93b5b9f49b
--- /dev/null
+++ b/src/Umbraco.Cms.Api.Delivery/Json/DeliveryApiVersionAwareJsonConverterBase.cs
@@ -0,0 +1,88 @@
+using System.Reflection;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+using Asp.Versioning;
+using Microsoft.AspNetCore.Http;
+using Umbraco.Cms.Core.DeliveryApi;
+
+namespace Umbraco.Cms.Api.Delivery.Json;
+
+public abstract class DeliveryApiVersionAwareJsonConverterBase : JsonConverter
+{
+ private readonly IHttpContextAccessor _httpContextAccessor;
+ private readonly JsonConverter _defaultConverter = (JsonConverter)JsonSerializerOptions.Default.GetConverter(typeof(T));
+
+ public DeliveryApiVersionAwareJsonConverterBase(IHttpContextAccessor httpContextAccessor)
+ => _httpContextAccessor = httpContextAccessor;
+
+ ///
+ public override T? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+ => _defaultConverter.Read(ref reader, typeToConvert, options);
+
+ ///
+ public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
+ {
+ Type type = typeof(T);
+ var apiVersion = GetApiVersion();
+
+ // Get the properties in the specified order
+ PropertyInfo[] properties = type.GetProperties().OrderBy(GetPropertyOrder).ToArray();
+
+ writer.WriteStartObject();
+
+ foreach (PropertyInfo property in properties)
+ {
+ // Filter out properties based on the API version
+ var include = apiVersion is null || ShouldIncludeProperty(property, apiVersion.Value);
+
+ if (include is false)
+ {
+ continue;
+ }
+
+ var propertyName = property.Name;
+ writer.WritePropertyName(options.PropertyNamingPolicy?.ConvertName(propertyName) ?? propertyName);
+ JsonSerializer.Serialize(writer, property.GetValue(value), options);
+ }
+
+ writer.WriteEndObject();
+ }
+
+ private int? GetApiVersion()
+ {
+ HttpContext? httpContext = _httpContextAccessor.HttpContext;
+ ApiVersion? apiVersion = httpContext?.GetRequestedApiVersion();
+
+ return apiVersion?.MajorVersion;
+ }
+
+ private int GetPropertyOrder(PropertyInfo prop)
+ {
+ var attribute = prop.GetCustomAttribute();
+ return attribute?.Order ?? 0;
+ }
+
+ ///
+ /// Determines whether a property should be included based on version bounds.
+ ///
+ /// The property info.
+ /// An integer representing an API version.
+ /// true if the property should be included; otherwise, false.
+ private bool ShouldIncludeProperty(PropertyInfo propertyInfo, int version)
+ {
+ var attribute = propertyInfo
+ .GetCustomAttributes(typeof(IncludeInApiVersionAttribute), false)
+ .FirstOrDefault();
+
+ if (attribute is not IncludeInApiVersionAttribute apiVersionAttribute)
+ {
+ return true; // No attribute means include the property
+ }
+
+ // Check if the version is within the specified bounds
+ var isWithinMinVersion = apiVersionAttribute.MinVersion.HasValue is false || version >= apiVersionAttribute.MinVersion.Value;
+ var isWithinMaxVersion = apiVersionAttribute.MaxVersion.HasValue is false || version <= apiVersionAttribute.MaxVersion.Value;
+
+ return isWithinMinVersion && isWithinMaxVersion;
+ }
+}
diff --git a/src/Umbraco.Cms.Api.Delivery/Querying/Filters/ContentTypeFilter.cs b/src/Umbraco.Cms.Api.Delivery/Querying/Filters/ContentTypeFilter.cs
index 13d9dc77ec..50c390c766 100644
--- a/src/Umbraco.Cms.Api.Delivery/Querying/Filters/ContentTypeFilter.cs
+++ b/src/Umbraco.Cms.Api.Delivery/Querying/Filters/ContentTypeFilter.cs
@@ -1,6 +1,5 @@
using Umbraco.Cms.Api.Delivery.Indexing.Filters;
using Umbraco.Cms.Core.DeliveryApi;
-using Umbraco.Extensions;
namespace Umbraco.Cms.Api.Delivery.Querying.Filters;
@@ -15,15 +14,15 @@ public sealed class ContentTypeFilter : IFilterHandler
///
public FilterOption BuildFilterOption(string filter)
{
- var alias = filter.Substring(ContentTypeSpecifier.Length);
+ var filterValue = filter.Substring(ContentTypeSpecifier.Length);
+ var negate = filterValue.StartsWith('!');
+ var aliases = filterValue.TrimStart('!').Split(',', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries);
return new FilterOption
{
FieldName = ContentTypeFilterIndexer.FieldName,
- Values = alias.IsNullOrWhiteSpace() == false
- ? new[] { alias.TrimStart('!') }
- : Array.Empty(),
- Operator = alias.StartsWith('!')
+ Values = aliases,
+ Operator = negate
? FilterOperation.IsNot
: FilterOperation.Is
};
diff --git a/src/Umbraco.Cms.Api.Delivery/Services/CurrentMemberClaimsProvider.cs b/src/Umbraco.Cms.Api.Delivery/Services/CurrentMemberClaimsProvider.cs
new file mode 100644
index 0000000000..8a358f11a8
--- /dev/null
+++ b/src/Umbraco.Cms.Api.Delivery/Services/CurrentMemberClaimsProvider.cs
@@ -0,0 +1,44 @@
+using OpenIddict.Abstractions;
+using Umbraco.Cms.Core.DeliveryApi;
+using Umbraco.Cms.Core.Security;
+
+namespace Umbraco.Cms.Api.Delivery.Services;
+
+// NOTE: this is public and unsealed to allow overriding the default claims with minimal effort.
+public class CurrentMemberClaimsProvider : ICurrentMemberClaimsProvider
+{
+ private readonly IMemberManager _memberManager;
+
+ public CurrentMemberClaimsProvider(IMemberManager memberManager)
+ => _memberManager = memberManager;
+
+ public virtual async Task> GetClaimsAsync()
+ {
+ MemberIdentityUser? memberIdentityUser = await _memberManager.GetCurrentMemberAsync();
+ return memberIdentityUser is not null
+ ? await GetClaimsForMemberIdentityAsync(memberIdentityUser)
+ : throw new InvalidOperationException("Could not retrieve the current member. This method should only ever be invoked when a member has been authorized.");
+ }
+
+ protected virtual async Task> GetClaimsForMemberIdentityAsync(MemberIdentityUser memberIdentityUser)
+ {
+ var claims = new Dictionary
+ {
+ [OpenIddictConstants.Claims.Subject] = memberIdentityUser.Key
+ };
+
+ if (memberIdentityUser.Name is not null)
+ {
+ claims[OpenIddictConstants.Claims.Name] = memberIdentityUser.Name;
+ }
+
+ if (memberIdentityUser.Email is not null)
+ {
+ claims[OpenIddictConstants.Claims.Email] = memberIdentityUser.Email;
+ }
+
+ claims[OpenIddictConstants.Claims.Role] = await _memberManager.GetRolesAsync(memberIdentityUser);
+
+ return claims;
+ }
+}
diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Security/BackOfficeController.cs b/src/Umbraco.Cms.Api.Management/Controllers/Security/BackOfficeController.cs
index 3e71b4cc31..cada1031e3 100644
--- a/src/Umbraco.Cms.Api.Management/Controllers/Security/BackOfficeController.cs
+++ b/src/Umbraco.Cms.Api.Management/Controllers/Security/BackOfficeController.cs
@@ -275,9 +275,12 @@ public class BackOfficeController : SecurityControllerBase
[MapToApiVersion("1.0")]
public async Task Signout(CancellationToken cancellationToken)
{
- var userName = await GetUserNameFromAuthCookie();
+ AuthenticateResult cookieAuthResult = await HttpContext.AuthenticateAsync(Constants.Security.BackOfficeAuthenticationType);
+ var userName = cookieAuthResult.Principal?.Identity?.Name;
+ var userId = cookieAuthResult.Principal?.Identity?.GetUserId();
await _backOfficeSignInManager.SignOutAsync();
+ _backOfficeUserManager.NotifyLogoutSuccess(cookieAuthResult.Principal ?? User, userId);
_logger.LogInformation(
"User {UserName} from IP address {RemoteIpAddress} has logged out",
diff --git a/src/Umbraco.Cms.Api.Management/DependencyInjection/AuditLogBuilderExtensions.cs b/src/Umbraco.Cms.Api.Management/DependencyInjection/AuditLogBuilderExtensions.cs
index a962ba558e..edca89e56b 100644
--- a/src/Umbraco.Cms.Api.Management/DependencyInjection/AuditLogBuilderExtensions.cs
+++ b/src/Umbraco.Cms.Api.Management/DependencyInjection/AuditLogBuilderExtensions.cs
@@ -1,6 +1,8 @@
using Microsoft.Extensions.DependencyInjection;
using Umbraco.Cms.Api.Management.Factories;
+using Umbraco.Cms.Api.Management.Security;
using Umbraco.Cms.Core.DependencyInjection;
+using Umbraco.Cms.Core.Notifications;
namespace Umbraco.Cms.Api.Management.DependencyInjection;
@@ -9,6 +11,13 @@ internal static class AuditLogBuilderExtensions
internal static IUmbracoBuilder AddAuditLogs(this IUmbracoBuilder builder)
{
builder.Services.AddTransient();
+ builder.AddNotificationHandler();
+ builder.AddNotificationHandler();
+ builder.AddNotificationHandler();
+ builder.AddNotificationHandler();
+ builder.AddNotificationHandler();
+ builder.AddNotificationHandler();
+ builder.AddNotificationHandler();
return builder;
}
diff --git a/src/Umbraco.Cms.Api.Management/Security/BackOfficeUserManagerAuditer.cs b/src/Umbraco.Cms.Api.Management/Security/BackOfficeUserManagerAuditer.cs
new file mode 100644
index 0000000000..561e67bd38
--- /dev/null
+++ b/src/Umbraco.Cms.Api.Management/Security/BackOfficeUserManagerAuditer.cs
@@ -0,0 +1,142 @@
+using System.Globalization;
+using Umbraco.Cms.Core.Events;
+using Umbraco.Cms.Core.Models.Membership;
+using Umbraco.Cms.Core.Notifications;
+using Umbraco.Cms.Core.Services;
+using Umbraco.Cms.Web.Common.Security;
+using Umbraco.Extensions;
+
+namespace Umbraco.Cms.Api.Management.Security;
+
+///
+/// Binds to notifications to write audit logs for the
+///
+internal sealed class BackOfficeUserManagerAuditer :
+ INotificationHandler,
+ INotificationHandler,
+ INotificationHandler,
+ INotificationHandler,
+ INotificationHandler,
+ INotificationHandler,
+ INotificationHandler
+{
+ private readonly IAuditService _auditService;
+ private readonly IUserService _userService;
+
+ public BackOfficeUserManagerAuditer(IAuditService auditService, IUserService userService)
+ {
+ _auditService = auditService;
+ _userService = userService;
+ }
+
+ public void Handle(UserForgotPasswordChangedNotification notification) =>
+ WriteAudit(
+ notification.PerformingUserId,
+ notification.AffectedUserId,
+ notification.IpAddress,
+ "umbraco/user/password/forgot/change",
+ "password forgot/change");
+
+ public void Handle(UserForgotPasswordRequestedNotification notification) =>
+ WriteAudit(
+ notification.PerformingUserId,
+ notification.AffectedUserId,
+ notification.IpAddress,
+ "umbraco/user/password/forgot/request",
+ "password forgot/request");
+
+ public void Handle(UserLoginFailedNotification notification) =>
+ WriteAudit(
+ notification.PerformingUserId,
+ null,
+ notification.IpAddress,
+ "umbraco/user/sign-in/failed",
+ "login failed");
+
+ public void Handle(UserLoginSuccessNotification notification)
+ => WriteAudit(
+ notification.PerformingUserId,
+ notification.AffectedUserId,
+ notification.IpAddress,
+ "umbraco/user/sign-in/login",
+ "login success");
+
+ public void Handle(UserLogoutSuccessNotification notification)
+ => WriteAudit(
+ notification.PerformingUserId,
+ notification.AffectedUserId,
+ notification.IpAddress,
+ "umbraco/user/sign-in/logout",
+ "logout success");
+
+ public void Handle(UserPasswordChangedNotification notification) =>
+ WriteAudit(
+ notification.PerformingUserId,
+ notification.AffectedUserId,
+ notification.IpAddress,
+ "umbraco/user/password/change",
+ "password change");
+
+ public void Handle(UserPasswordResetNotification notification) =>
+ WriteAudit(
+ notification.PerformingUserId,
+ notification.AffectedUserId,
+ notification.IpAddress,
+ "umbraco/user/password/reset",
+ "password reset");
+
+ private static string FormatEmail(IMembershipUser? user) =>
+ user is null ? string.Empty : user.Email.IsNullOrWhiteSpace() ? string.Empty : $"<{user.Email}>";
+
+ private void WriteAudit(
+ string performingId,
+ string? affectedId,
+ string ipAddress,
+ string eventType,
+ string eventDetails)
+ {
+ int? performingIdAsInt = ParseUserId(performingId);
+ int? affectedIdAsInt = ParseUserId(affectedId);
+
+ WriteAudit(performingIdAsInt, affectedIdAsInt, ipAddress, eventType, eventDetails);
+ }
+
+ private static int? ParseUserId(string? id)
+ => int.TryParse(id, NumberStyles.Integer, CultureInfo.InvariantCulture, out var isAsInt) ? isAsInt : null;
+
+ private void WriteAudit(
+ int? performingId,
+ int? affectedId,
+ string ipAddress,
+ string eventType,
+ string eventDetails)
+ {
+ var performingDetails = "User UNKNOWN:0";
+ if (performingId.HasValue)
+ {
+ IUser? performingUser = _userService.GetUserById(performingId.Value);
+ performingDetails = performingUser is null
+ ? $"User UNKNOWN:{performingId.Value}"
+ : $"User \"{performingUser.Name}\" {FormatEmail(performingUser)}";
+ }
+
+ var affectedDetails = "User UNKNOWN:0";
+ if (affectedId.HasValue)
+ {
+ IUser? affectedUser = _userService.GetUserById(affectedId.Value);
+ affectedDetails = affectedUser is null
+ ? $"User UNKNOWN:{affectedId.Value}"
+ : $"User \"{affectedUser.Name}\" {FormatEmail(affectedUser)}";
+ }
+
+ _auditService.Write(
+ performingId ?? 0,
+ performingDetails,
+ ipAddress,
+ DateTime.UtcNow,
+ affectedId ?? 0,
+ affectedDetails,
+ eventType,
+ eventDetails);
+ }
+}
diff --git a/src/Umbraco.Core/Cache/DistributedCacheExtensions.cs b/src/Umbraco.Core/Cache/DistributedCacheExtensions.cs
index d46a22ac44..5cbeb6cdbe 100644
--- a/src/Umbraco.Core/Cache/DistributedCacheExtensions.cs
+++ b/src/Umbraco.Core/Cache/DistributedCacheExtensions.cs
@@ -140,7 +140,9 @@ public static class DistributedCacheExtensions
Id = x.Item.Id,
Key = x.Item.Key,
ChangeTypes = x.ChangeTypes,
- Blueprint = x.Item.Blueprint
+ Blueprint = x.Item.Blueprint,
+ PublishedCultures = x.PublishedCultures?.ToArray(),
+ UnpublishedCultures = x.UnpublishedCultures?.ToArray()
});
dc.RefreshByPayload(ContentCacheRefresher.UniqueId, payloads);
diff --git a/src/Umbraco.Core/Cache/Refreshers/Implement/ContentCacheRefresher.cs b/src/Umbraco.Core/Cache/Refreshers/Implement/ContentCacheRefresher.cs
index 3063f0bd26..dda779cd0c 100644
--- a/src/Umbraco.Core/Cache/Refreshers/Implement/ContentCacheRefresher.cs
+++ b/src/Umbraco.Core/Cache/Refreshers/Implement/ContentCacheRefresher.cs
@@ -380,6 +380,10 @@ public sealed class ContentCacheRefresher : PayloadCacheRefresherBase
+ /// Retrieves the claims for the currently logged in member.
+ ///
+ ///
+ /// This is used by the OIDC user info endpoint to supply "current user" info.
+ ///
+ Task> GetClaimsAsync();
+}
diff --git a/src/Umbraco.Core/DeliveryApi/IncludeInApiVersionAttribute.cs b/src/Umbraco.Core/DeliveryApi/IncludeInApiVersionAttribute.cs
new file mode 100644
index 0000000000..f336126b82
--- /dev/null
+++ b/src/Umbraco.Core/DeliveryApi/IncludeInApiVersionAttribute.cs
@@ -0,0 +1,21 @@
+namespace Umbraco.Cms.Core.DeliveryApi;
+
+[AttributeUsage(AttributeTargets.Property)]
+public class IncludeInApiVersionAttribute : Attribute
+{
+ public int? MinVersion { get; }
+
+ public int? MaxVersion { get; }
+
+ ///
+ /// Initializes a new instance of the class.
+ /// Specifies that the property should be included in the API response if the API version falls within the specified bounds.
+ ///
+ /// The minimum API version (inclusive) for which the property should be included.
+ /// The maximum API version (inclusive) for which the property should be included.
+ public IncludeInApiVersionAttribute(int minVersion = -1, int maxVersion = -1)
+ {
+ MinVersion = minVersion >= 0 ? minVersion : null;
+ MaxVersion = maxVersion >= 0 ? maxVersion : null;
+ }
+}
diff --git a/src/Umbraco.Core/DeliveryApi/NoopCurrentMemberClaimsProvider.cs b/src/Umbraco.Core/DeliveryApi/NoopCurrentMemberClaimsProvider.cs
new file mode 100644
index 0000000000..8080c27562
--- /dev/null
+++ b/src/Umbraco.Core/DeliveryApi/NoopCurrentMemberClaimsProvider.cs
@@ -0,0 +1,6 @@
+namespace Umbraco.Cms.Core.DeliveryApi;
+
+public class NoopCurrentMemberClaimsProvider : ICurrentMemberClaimsProvider
+{
+ public Task> GetClaimsAsync() => Task.FromResult(new Dictionary());
+}
diff --git a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs
index b68a1685ac..14878e5639 100644
--- a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs
+++ b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs
@@ -34,6 +34,8 @@ using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Services.ContentTypeEditing;
using Umbraco.Cms.Core.DynamicRoot;
using Umbraco.Cms.Core.Preview;
+using Umbraco.Cms.Core.PublishedCache;
+using Umbraco.Cms.Core.PublishedCache.Internal;
using Umbraco.Cms.Core.Security.Authorization;
using Umbraco.Cms.Core.Serialization;
using Umbraco.Cms.Core.Services.FileSystem;
diff --git a/src/Umbraco.Core/EmbeddedResources/Lang/de_ch.xml b/src/Umbraco.Core/EmbeddedResources/Lang/de_ch.xml
new file mode 100644
index 0000000000..708471fb4a
--- /dev/null
+++ b/src/Umbraco.Core/EmbeddedResources/Lang/de_ch.xml
@@ -0,0 +1,2455 @@
+
+
+
+ The Umbraco community
+ https://docs.umbraco.com/umbraco-cms/extending/language-files
+
+
+ Kulturen und Hostnamen
+ Protokoll
+ Durchsuchen
+ Dokumenttyp ändern
+ Datentyp ändern
+ Kopieren
+ Neu
+ Exportieren
+ Neues Paket
+ Neue Gruppe
+ Entfernen
+ Deaktivieren
+ Inhalt bearbeiten
+ Einstellungen bearbeiten
+ Papierkorb leeren
+ Aktivieren
+ Dokumenttyp exportieren
+ Dokumenttyp importieren
+ Paket importieren
+ 'Canvas'-Modus starten
+ Abmelden
+ Verschieben
+ Benachrichtigungen
+ Öffentlicher Zugriff
+ Veröffentlichen
+ Veröffentlichung zurücknehmen
+ Aktualisieren
+ Erneut veröffentlichen
+ Entfernen
+ Umbenennen
+ Wiederherstellen
+ Wähle worunter kopiert werden soll
+ Wähle worunter verschoben werden soll
+ Wähle wohin importiert werden soll
+ Wähle wohin die ausgewählten Elemente kopiert werden soll
+ Wähle wohin die ausgewählten Elemente verschoben werden soll
+ in der Baumstrukture
+ wurde verschoben nach
+ wurde kopiert nach
+ wurde gelöscht
+ Berechtigungen
+ Zurücksetzen
+ Zur Veröffentlichung einreichen
+ Zur Übersetzung senden
+ Gruppe festlegen
+ Sortieren
+ Übersetzen
+ Aktualisieren
+ Berechtigung festlegen
+ Freigeben
+ Inhaltsvorlage anlegen
+ Einladung erneut versenden
+
+
+ Inhalt
+ Administration
+ Struktur
+ Anderes
+
+
+ Erlaube Zugriff auf "Kultur und Hostname"-Einstellungen
+ Erlaube Zugriff auf Bearbeiten-Verlauf
+ Erlaube das Anzeigen eines Knotens
+ Erlaube Ändern des Dokumenten-Typs
+ Erlaube Kopieren
+ Erlaube Erzeugen
+ Erlaube Entfernen
+ Erlaube Verschieben
+ Erlaube Zugriff auf "Öffentlich zugänglich"-Einstellungen
+ Erlaube Veröffentlichung
+ Erlaube Rücknahme der Veröffentlichung
+ Erlaube Zugriff auf die Berechtigungen
+ Erlaube Zurücksetzen auf eine vorherige Version
+ Erlaube Anforderungen von Veröffentlichungen
+ Erlaube Anfordern von Übersetzungen
+ Erlaube Sortieren
+ Erlaube Übersetzung
+ Erlaube Sichern von Änderungen
+ Erlaube Anlegen von Inhaltsvorlagen
+ Erlaube das Einrichten von Benachrichtungen für Inhalte
+
+
+ Inhalt
+ Info
+
+
+ Erlaubnis verweigert.
+ Neue Domain hinzufügen
+ Aktuelle Domain hinzufügen
+ entfernen
+ Ungültiges Element.
+ Format der Domain ungültig.
+ Domain wurde bereits zugewiesen.
+ Sprache
+ Domain
+ Domain '%0%' hinzugefügt
+ Domain '%0%' entfernt
+ Die Domain '%0%' ist bereits zugeordnet
+ Domain '%0%' aktualisiert
+ Domains bearbeiten
+
+
+
+ Vererben
+ Kultur
+
+ Definiert die Kultureinstellung für untergeordnete Elemente dieses Elements oder vererbt vom übergeordneten Element.
+ Wird auch auf das aktuelle Element angewendet, sofern auf tieferer Ebene keine Domain zugeordnet ist.
+
+ Domainen
+
+
+ Auswahl aufheben
+ Auswählen
+ Etwas anderes machen
+ Fett
+ Ausrücken
+ Formularelement einfügen
+ Graphische Überschrift einfügen
+ HTML bearbeiten
+ Einrücken
+ Kursiv
+ Zentriert
+ Linksbündig
+ Rechtsbündig
+ Link einfügen
+ Anker einfügen
+ Aufzählung
+ Nummerierung
+ Makro einfügen
+ Abbildung einfügen
+ Veröffentlichen und schliessen
+ Veröffentlichen mit Unterknoten
+ Datenbeziehungen bearbeiten
+ Zurück zur Liste
+ Speichern
+ Sichern und schliessen
+ Speichern und veröffentlichen
+ Speichern und zur Abnahme übergeben
+ Listenansicht sichern
+ Veröffentlichung planen
+ Vorschau
+ Die Vorschaufunktion ist deaktiviert, da keine Vorlage zugewiesen ist
+ Stil auswählen
+ Stil anzeigen
+ Tabelle einfügen
+ Erzeuge Daten-Model und schliesse
+ Sichern und Daten-Model erzeugen
+ Zurücknehmen
+ Erneut anwenden
+ TAG entfernen
+ Abbrechen
+ Bestätigen
+ Mehr Veröffentlichungs Optionen
+ Senden
+
+
+ Medie gelöscht
+ Medie verschoben
+ Medie kopiert
+ Medie gesichert
+
+
+ Anzeigen als
+ Inhalt gelöscht
+ Inhalt unveröffentlicht
+ Inhalt unveröffentlicht für Sprache: %0%
+ Inhalt veröffentlicht
+ Inhalt veröffentlicht für Sprache: %0%
+ Inhalt gesichert
+ Inhalt gesichert für Sprache: %0%
+ Inhalt verschoben
+ Inhalt kopiert
+ Inhalt auf vorherige Version geändert
+ Veröffentlichung für Inhalt angefordert
+ Veröffentlichung für Inhalt angefordert in Sprache: %0%
+ Unterknoten wurden sortiert von Benutzer
+ %0%
+ Versionsbereinigung deaktiviert für Version: %0%
+ Versionsbereinigung aktiviert für Version: %0%
+ Kopieren
+ Veröffentlichen
+ Veröffentlichen
+ Verschieben
+ Sichern
+ Sichern
+ Entfernen
+ Veröffentlichung zurücknehmen
+ Veröffentlichung zurücknehmen
+ Vorgängerversion wieder herstellen
+ Veröffentlichung anfordern
+ Veröffentlichung anfordern
+ Sortieren
+ Benutzerdefiniert
+ Speichern
+ Speichern
+ Verlauf (alle Variationen)
+
+
+ Der Verzeichnisname darf keine ungültigen Zeichen enthalten.
+ Folgendes Element konnte nicht entfernt werden: %0%
+
+
+ Ist veröffentlicht
+ Über dieses Dokument
+ Alias
+ (Wie würden Sie das Bild über das Telefon beschreiben?)
+ Alternative Links
+ Klicken, um das Dokument zu bearbeiten
+ Erstellt von
+ Ursprünglicher Autor
+ Aktualisiert von
+ Erstellt am
+ Erstellungszeitpunkt des Dokuments
+ Dokumenttyp
+ In Bearbeitung
+ Veröffentlichung aufheben am
+ Dieses Dokument wurde nach dem Veröffentlichen bearbeitet.
+ Dieses Dokument ist nicht veröffentlicht.
+ Zuletzt veröffentlicht
+ Keine Elemente anzuzeigen
+ Diese Liste enthält keine Einträge.
+ Es wurden keine untergeordneten Elemente hinzugefügt
+ Es wurden keine Mitglieder hinzugefügt
+ Medientyp
+ Verweis auf Medienobjekt(e)
+ Mitgliedergruppe
+ Mitgliederrolle
+ Mitglieder-Typ
+ Es wurden keine Änderungen vorgenommen
+ Kein Datum gewählt
+ Name des Dokument
+ Dieses Media-Element hat keinen Link
+ Diesem Element kann kein Inhalt zugewiesen werden
+ Eigenschaften
+
+ Dieses Dokument ist veröffentlicht aber nicht sichtbar,
+ da das übergeordnete Dokument '%0%' nicht publiziert ist
+
+
+ Diese Kultur wurde veröffentlicht, aber wird nicht angezeigt,
+ weil sie auf dem Oberknoten '%0%' unveröffentlicht ist
+
+ Ups! Dieses Dokument ist veröffentlicht aber nicht im internen Cache aufzufinden: Systemfehler.
+ Der URL wurde nicht gefunden
+ Dieses Dokument wurde veröffentlicht, aber sein URL würde mit Inhalt %0% kollidieren
+ Dieses Dokument wurde veröffentlicht, aber sein URL kann nicht aufgelöst (routed) werden
+ Veröffentlichen
+ Veröffentlicht
+ Veröffentlicht (Änderungen bereit)
+ Publikationsstatus
+
+ Veröffentlichen mit Unterknoten zum Veröffentlichen der gewählten Sprache samt aller Unterknoten der selben Sprache, um ihren Inhalt öffentlich verfügbar zu machen.]]>
+
+
+ Veröffentlichen mit Unterknoten zum Veröffentlichen der gewählten Sprache samt aller Unterknoten der selben Sprache, um ihren Inhalt öffentlich verfügbar zu machen.]]>
+
+ Veröffentlichen am
+ Veröffentlichung widerrufen am
+ Datum entfernen
+ Datum wählen
+ Sortierung abgeschlossen
+
+ Um die Dokumente zu sortieren, ziehen Sie sie einfach an die gewünschte Position.
+ Sie können mehrere Zeilen markieren indem Sie die Umschalttaste ("Shift") oder die Steuerungstaste ("Strg") gedrückt halten
+
+ Statistiken
+ Titel (optional)
+ Alternativtext (optional)
+ Beschriftung (optional)
+ Typ
+ Veröffentlichung widerrufen
+ Entwurf
+ Nicht angelegt
+ Zuletzt bearbeitet am
+ Letzter Änderungszeitpunkt des Dokuments
+ Datei entfernen
+ Klicke hier um das das Bild vom Medienelement zu entfernen.
+ Klicke hier um das das Bild vom Medienelement zu entfernen.
+ Link zum Dokument
+ Mitglied der Gruppe(n)
+ Kein Mitglied der Gruppe(n)
+ Untergeordnete Elemente
+ Ziel
+ Dies führt zur folgenden Zeit auf dem Server:
+
+ Was bedeutet dies?]]>
+
+ Wollen Sie dieses Element wirklich entfernen?
+ Sicher das Sie alle Elemente entfernen wollen?
+
+ Eigenschaft %0% verwendet Editor %1%,
+ welcher nicht von Nested Content unterstützt wird.
+
+ Keine Dokument-Typen für diese Eigenschaft konfiguriert.
+ Elementtyp hinzufügen
+ Elementtype auswählen
+
+ Wählen Sie die Gruppe aus von der die Eigenschaften angezeigt werden soll. Sollte der Wert leer sein
+ wird die erste Gruppe des Elementtypen verwendet.
+
+
+ Geben Sie eine Angular Anweisung an um den Namen für das jweilige Element
+ zu bestimmen. Verwende
+
+ um den Index des Elements anzuzeigen.
+ Das ausgewählte Element verfügt nicht über unterstützte Gruppen. (Tabs werden von diesem Editor nicht unterstützt, entweder Sie ändern diese zu Gruppen oder Sie verwenden den Block List Editor.
+ Füge ein weiteres Textfeld hinzu
+ Entferne dieses Textfeld
+ Inhalt-Basis
+ Inklusive Entwürfen: veröffentliche auch unveröffentlichte Elemente.
+
+ Dieser Wert ist verborgen.
+ Wenn Sie diesen Wert einsehen müssen, wenden Sie sich bitte an einen Administrator.
+
+ Dieser Wert ist verborgen.
+ Welche Sprache möchten Sie veröffentlichen?
+ Welche Sprachen möchten Sie zur Freigabe schicken?
+ Welche Sprachen möchten Sie zu einer bestimmten Zeit veröffentlichen?
+
+ Wählen Sie die Sprachen, deren Veröffentlichung zurück genommen werden soll.
+ Das Zurücknehmen der Veröffentlichung einer Pflichtsprache betrifft alle Sprachen.
+
+ Alle neuen Variationen werden gespeichert.
+ Welche Variationen wollen Sie veröffentlichen?
+ Wählen Sie welche Variation gespeichert werden soll.
+ Folgende Variationen werden benötigt um das Element veröffentlichen zu können:
+ Wir sind für Veröffentlichungen bereit
+ Bereit zu Veröffentlichen?
+ Bereit zu Sichern?
+ Fokus zurücksetzten.
+ Freigabe anfordern
+ Wählen Sie Datum und Uhrzeit für die Veröffentlichung bzw. deren Rücknahme.
+ Neues Element anlegen
+ Aus der Zwischenablage einfügen
+ Dieses Element befindet sich im Papierkorb.
+ Speichern ist nicht erlaubt.
+ Veröffentlichen ist nicht erlaubt.
+ Zur Genehmigung senden ist nicht erlaubt.
+ Plannung ist nicht erlaubt
+ Veröffentlichung zurücknehmen ist nicht erlaubt.
+
+
+ %0%]]>
+ Leer
+ Wählen Sie eine Inhaltsvorlage
+ Inhaltsvorlage erzeugt
+ Inhaltsvorlage von '%0%' wurde erzeugt
+ Eine gleichnamige Inhaltsvorlage ist bereits vorhanden
+
+ Eine Inhaltsvorlage ist vordefinierter Inhalt,
+ den ein Redakteur als Basis für neuen Inhalt verwenden kann
+
+
+
+ Für Upload klicken
+ oder klicken Sie hier um eine Datei zu wählen
+ Dieser Dateityp darf nicht hochgeladen werden
+
+ Diese Datei kann nicht hochgeladen werden wil der Dateiname ungültig ist.
+ Diese Datei kann nicht hochgeladen werden, der Medienttype mit dem Alias '%0%' ist hier nicht erlaubt.
+ Max. Dateigröße ist
+ Media-Basis
+ Eltern- und Ziel-Verzeichnis dürfen nicht übereinstimmen
+ Unter Element Id %0% konnte kein Verzeichnis angelegt werden
+ Das Verzeichnis mit Id %0% konnte nicht umbenannt werden
+ Wählen Sie Dateien aus und ziehen Sie diese in diesen Bereich
+ Hochladen ist in diesem Bereich nicht erlaubt.
+
+
+ Neues Mitglied anlegen
+ Alle Mitglieder
+ Ein Mitglied mit diesem Login existiert bereits.
+ Mitgliedsgruppen haben keine weiteren editierbaren Eigenschaften.
+ Das Mitglied ist bereits in der Gruppe '%0%'
+ Das Mitglied hat bereits ein Passwort
+ Sperren ist nicht aktiviert für dieses Mitglied.
+ Das Mitglied ist nicht in der Gruppe '%0%'
+ Zwei-Faktor-Authentifizierung
+
+
+ Kopieren des Dokumenttyps fehlgeschlagen
+ Bewegen des Dokumenttyps fehlgeschlagen
+
+
+ Kopieren des Medienttyps fehlgeschlagen
+ Bewegen des Medienttyps fehlgeschlagen
+ Automatische auswahl.
+
+
+ Kopieren des Mitgliedtyps fehlgeschlagen
+
+
+ An welcher Stellen wollen Sie das Element erstellen
+ Neues Element unterhalb von
+ Wählen Sie einen Dokumenttyp für eine Inhaltsvorlage
+ Geben Sie einen Verzeichnisnamen ein
+ Wählen Sie einen Namen und einen Typ
+
+
+
+
+
+
+
+ Die im Inhaltsbaum ausgewählte Seite
+ erlaubt keine Unterseiten.
+
+ Bearbeitungsrechte für diesen Dokumenttyp
+ Neuen Dokumenttypen erstellen
+
+
+
+
+
+
+
+ Das im Strukturbaum ausgewählte Medienelement
+ erlaubt keine untergeordneten Elemente.
+
+ Bearbeitungsrechte für diesen Medientyp
+ Dokumenttyp ohne Vorlage
+ Dokumenttyp mit Template
+
+ Die Definition für eine Inhaltsseite welche von einem
+ Redakteur im Inhaltsbaum angelgt werden können und direkt über die URL aufgerufen werden kann.
+
+ Dokumenttype
+
+ Die Definition für eine Inhaltsseite welche von einem
+ Redakteur im Inhaltsbaum angelgt werden können und direkt über die URL aufgerufen werden kann.
+
+ Elementtyp
+
+ Definiert die Vorlage für sich wiederholende Eigenschaften, zum Beispiel, in einer 'Block
+ List' oder im 'Nested Content' Editor.
+
+ Komposition
+
+ Definiert eine wiederverwendbare Komposition von Eigenschaften welche in anderen
+ Dokumenttypen wiederverwendet werden können.
+
+ Ordner
+
+ Werden benützt um Dokumenttypen, Komposition und Elementtypen in diesem
+ Dokumenttypbaums zu organisieren.
+
+ Neues Verzeichnis
+ Neuer Datentyp
+ Neue JavaScript-Datei
+ Neue leere Partial-View
+ Neues Partial-View-Makro
+ Neue Partial-View nach Vorlage
+ Neues Partial-View-Makro nach Vorlage
+ Neues Partial-View-Makro (ohne Makro)
+ Neue Style-Sheet-Datei
+ Neue Rich-Text-Editor Style-Sheet-Datei
+
+
+ Website anzeigen
+ - Verstecken
+ Wenn Umbraco nicht geöffnet wurde, wurde möglicherweise das Pop-Up unterdrückt.
+ wurde in einem neuen Fenster geöffnet
+ Neu öffnen
+ Besuchen
+ Willkommen
+
+
+ Bleiben
+ Änderungen verwerfen
+ Es gibt ungesicherte Änderungen
+
+ Wollen Sie diese Seite wirklich verlassen?
+ - es gibt ungesicherte Änderungen
+
+ Veröffentlichen macht die ausgewählten Elemente auf der Website sichtbar.
+
+ Aufheben der Veröffentlichung entfernt die ausgewählten Elemente
+ und ihre Unterknoten von der Website.
+
+ Aufheben der Veröffentlichung entfernt diese Seite und ihre Unterseiten von der Website.
+
+ Es gibt ungesicherte Änderungen.
+ Ändern des Dokumenttyps macht diese rückgängig.
+
+
+
+ Fertig
+ %0% Element entfernt
+ %0% Elemente entfernt
+ %0% von %1% Element entfernt
+ %0% von %1% Elementen entfernt
+ %0% Element veröffentlicht
+ %0% Elemente veröffentlicht
+ %0% von %1% Element veröffentlicht
+ %0% von %1% Elementen veröffentlicht
+ %0% Veröffentlichung aufgehoben
+ %0% Veröffentlichungen aufgehoben
+ %0% von %1% Veröffentlichung aufgehoben
+ %0% von %1% Veröffentlichungen aufgehoben
+ %0% Element verschoben
+ %0% Elemente verschoben
+ %0% von %1% Element verschoben
+ %0% von %1% Elementen verschoben
+ %0% Element kopiert
+ %0% Elemente kopiert
+ %0% von %1% Element kopiert
+ %0% von %1% Elementen kopiert
+
+
+ Name des Link
+ Link
+ Anker / querystring
+ Name
+ Fenster schließen
+ Wollen Sie dies wirklich entfernen
+ %0% von %1% Elementen löschen wollen?]]>
+ Wollen Sie folgendes wirklich deaktivieren
+ Sicher das Sie es entfernen wollen?
+ %0% entfernen wollen?]]>
+ Sind Sie sich wirklich abmelden?
+ Sind Sie sicher?
+ Ausschneiden
+ Wörterbucheintrag bearbeiten
+ Sprache bearbeiten
+ Ausgewähltes Medien
+ Anker einfügen
+ Zeichen einfügen
+ Grafische Überschrift einfügen
+ Abbildung einfügen
+ Link einfügen
+ klicken um Macro hinzuzufügen
+ Tabelle einfügen
+ Dies entfernt die Sprache
+
+ Die Kultur-Variante einer Sprache zu ändern ist möglicherweise eine aufwendige Operation und führt zum Erneuern von Inhalts-Zwischenspeicher und Such-Index.
+
+ Zuletzt bearbeitet
+ Verknüpfung
+ Anker:
+ Wenn lokale Links verwendet werden, füge ein "#" vor den Link ein
+ In einem neuen Fenster öffnen?
+ Dieses Makro enthält keine einstellbaren Eigenschaften.
+ Einfügen
+ Berechtigungen bearbeiten für
+ Berechtigungen vergeben für
+ Berechtigungen vergeben für %0% für Benutzer-Gruppe %1%
+ Wählen Sie die Benutzer-Gruppe, deren Berechtigungen Sie setzen möchten
+
+ Der Papierkorb wird geleert.
+ Bitte warten Sie und schließen Sie das Fenster erst, wenn der Vorgang abgeschlossen ist.
+
+ Der Papierkorb ist leer
+ Wenn Sie den Papierkorb leeren, werden die enthaltenen Elemente endgültig gelöscht. Dieser Vorgang kann nicht rückgängig gemacht werden.
+
+ Der Webservice von <a target='_blank' rel='noopener' href='http://regexlib.com'>regexlib.com</a> ist zur Zeit nicht erreichbar. Bitte versuchen Sie es später erneut.
+
+
+ Finden Sie einen vorbereiteten regulären Ausdruck zur Validierung der Werte, die in dieses Feld eingegeben werden - zum Beispiel 'email, 'plz', 'URL' oder ähnlich.
+
+ Macro entfernen
+ Pflichtfeld
+ Die Website-Index wurd neu erstellt
+
+ Der Zwischenspeicher der Website wurde aktualisiert und alle veröffentlichten Inhalte sind jetzt auf dem neuesten Stand.
+ Bisher unveröffentliche Inhalte wurden dabei nicht veröffentlicht.
+
+
+ Der Zwischenspeicher der Website wird aktualisiert und der veröffentlichte Inhalt auf den neuesten Stand gebracht.
+ Unveröffentlichte Inhalte bleiben dabei weiterhin unveröffentlicht.
+
+ Anzahl der Spalten
+ Anzahl der Zeilen
+ Für Originalgröße auf die Abbildung klicken
+ Element auswählen
+ Zwischenspeicher-Element anzeigen
+ Verknüpfe mit Original
+ Einschliesslich Unterknoten
+ Die freundlichste Community
+ Seiten-Link
+ In neuem Fenster / Tab öffnen
+ Medien-Link
+ Inhalts-Startknoten wählen
+ Medienelement wählen
+ Medientype wählen
+ Bildzeichen wählen
+ Element wählen
+ Link wählen
+ Makro wählen
+ Inhalt wählen
+ Inhaltstyp wählen
+ Medien-Startknoten wählen
+ Mitglied wählen
+ Mitgliedergruppe wählen
+ Membertype wählen
+ Knoten wählen
+ Bereich wählen
+ Sprachen wählen
+ Benutzer wählen
+ Benutzer wählen
+ Keine Bildzeichen gefunden
+ Für dieses Makro gibt es keine Parameter
+ Es gibt keine Makros zum Einfügen
+ Externe Login-Anbieter
+ Ausnahmedetails
+ Stacktrace
+ Inner Exception
+ Verknüpfen Sie Ihr
+ Trennen Sie Ihr
+ Konto
+ Editor wählen
+ Konfiguration wählen
+ Kode-Vorlage wählen
+
+ Dies wird den Knoten und all seine Sprachen entfernen.
+ Wenn Sie nur eine Sprache entfernen wollen, wählen Sie diese und setzen sie auf unveröffentlicht.
+
+ %0%.]]>
+ %0% von der %1% Gruppe]]>
+ Ja, entfernen
+ Sie löschen das Layout
+ Bearbeiten des layout resultiert im Verlust der aller Daten für bestehenden Inhalt basierend auf dieser Konfiruation.
+
+
+
+ Um einen Eintrag zu importieren, suchen sie die ".udt" Datei auf ihren Computer durch Klicken des
+ "Import" Knopfes. (Sie werden für Ihre Zustimmung im nächsten Schritt gefragt)
+
+ Wörterbuch Eintrag existiert nicht.
+ Eltern Element existiert nicht.
+ Es gibt keine Einträge im Wörterbuch.
+ Keine Wörterbuch Einträge in dieser Datei gefunden.
+ Keine Wörterbuch Einträge gefunden.
+ Eintrag erstellen
+
+
+
+ %0%'.
+ Unter dem links angezeigten Menüpunkt 'Sprachen' können Sie weitere hinzufügen.]]>
+
+ Name der Kultur
+
+
+
+ Wörterbuch Übersicht
+
+
+ Sucher einrichten ]]>
+
+ Sucher (z.B.: multi-index searcher)]]>
+
+ Feldwerte
+ Gesundheitsstatus
+ Der Gesundheitsstatus und Lesbarkeit des Indizes.
+ Indizierer
+ Indexinformationen
+ Inhalt des Indexes
+ Zeigt die Eigenschaften des Indizes
+ Examine Index-Verwaltung
+
+ Index Detailanzeige und Verwaltungswerkzeuge
+
+ Index erneuern
+
+
+ Abhängig von der Inhaltsmenge Ihrer Website kann das eingie Zeit dauern.
+ Es wird davon abgeraten, einen Index einer Website während hoher Auslastung- oder Inhaltbearbeitungszeiten zu erneuern.
+ ]]>
+
+ Sucher
+ Durchsuche den Index und betrachte die Ergebnisse
+ Werkzeuge
+ Werkzeuge zur Indexverwaltung
+ Felder
+ Der Index kann nicht gelesen werden und wird deshalb neu erstellt.
+
+ Der Prozess dauert länger als erwartet, checken Sie die Umbraco Logs um zu sehen ob
+ Fehler passiert sind.
+
+ Der Index kann nicht rebuilded werden weil er nicht zugewissen wurde.
+ IIndexPopulator
+
+
+ Benutzername eingeben
+ Kennwort eingeben
+ Bestätige das Kennwort
+ %0% benennen ...
+ Bitte Name angeben ...
+ Bitte E-Mail eingeben...
+ Bitte Benutzernamen eingeben...
+ Label...
+ Bitte eine Beschreibung eingeben...
+ Durchsuchen ...
+ Filtern ...
+ Tippen, um Tags hinzuzufügen (nach jedem Tag die Eingabetaste drücken) ...
+ Bitte E-Mail eingeben
+ Bitte Nachricht eingeben...
+ Der Benutzername ist normalerweise Ihre E-Mail-Adresse
+ #value oder ?key=value
+ Bitte einen Alias eingeben...
+ Alias erzeugen...
+ Element erstellen
+ Bearbeiten
+ Benennen
+
+
+ Angepasste Listenansicht erstellen
+ Angepasste Listenansicht entfernen
+ Ein Inhalts-, Medien oder Mitgliedstyp mit gleichem Alias ist bereits vorhanden.
+
+
+ Umbenannt
+ Tragen Sie hier einen neuen Verzeichnisnamen ein
+ %0% wurde umbenannt in %1%
+
+
+ Ändern des Editors in einem Datatyps mit gespeicherten Werten ist nicht erlaubt. Um es zu erlauben müssen Sie die Umbraco:CMS:DataTypes:CanBeChanged Einstellung in der appsettings.json ändern.
+ Neuer Vorgabewert
+ Feldtyp in der Datenbank
+ Datentyp-GUID
+ Steuerelement zur Darstellung
+ Schaltflächen
+ Erweiterte Einstellungen aktivieren für
+ Kontextmenü aktivieren
+ Maximale Standardgröße für eingefügte Bilder
+ Verknüpfte Stylesheets
+ Beschriftung anzeigen
+ Breite und Höhe
+ Wählen Sie das Verzeichnis aus der untenstehenden Baumstruktur, in das
+ verschoben werden soll.
+ wurde verschoben in
+
+ %0% wird die Eigenschaften und Daten von folgenden Element löschen]]>
+
+
+ Ich verstehe das diese Aktion Eigenschaften und Daten basierend auf diesem
+ DataTyps löschen wird.
+
+
+
+
+ Ihre Daten wurden gespeichert.
+ Bevor Sie diese Seite jedoch veröffentlichen können, müssen Sie die folgenden Korrekturen vornehmen:
+
+
+ Der aktuelle Mitgliedschaftsanbieter erlaubt keine Kennwortänderung
+ (EnablePasswordRetrieval muss auf "true" gesetzt sein)
+
+ '%0%' ist bereits vorhanden
+ Bitte prüfen und korrigieren:
+ Bitte prüfen und korrigieren:
+
+ Für das Kennwort ist eine Mindestlänge von %0% Zeichen vorgesehen,
+ wovon mindestens %1% Sonderzeichen (nicht alphanumerisch) sein müssen
+
+ '%0%' muss eine Zahl sein
+ '%0%' (in Registerkarte '%1%') ist ein Pflichtfeld
+ '%0%' ist ein Pflichtfeld
+ '%0%' (in Registerkarte '%1%') hat ein falsches Format
+ '%0%' hat ein falsches Format
+
+
+ Ein unbekannter Fehler ist passiert.
+ Optimistic concurrency Fehler, Objekte wurde geändert.
+ Der Server hat einen Fehler gemeldet
+ Dieser Dateityp wird durch die Systemeinstellungen blockiert
+
+ ACHTUNG! Obwohl CodeMirror in den Einstellungen aktiviert ist,
+ bleibt das Modul wegen mangelnder Stabilität in Internet Explorer deaktiviert.
+
+ Bitte geben Sie die Bezeichnung und den Alias des neuen Dokumenttyps ein.
+ Es besteht ein Problem mit den Lese-/Schreibrechten auf eine Datei oder einen Ordner
+ Fehler beim Laden einer "Partial View Kodedatei" (Datei: %0%)
+ Bitte geben Sie einen Titel ein
+ Bitte wählen Sie einen Typ
+
+ Soll die Abbildung wirklich über die
+ Originalgröße hinaus vergrößert werden?
+
+ Startelement gelöscht, bitte kontaktieren Sie den System-Administrator.
+ Bitte markieren Sie den gewünschten Text, bevor Sie einen Stil auswählen
+ Keine aktiven Stile vorhanden
+ Bitte platzieren Sie den Mauszeiger in die erste der zusammenzuführenden Zellen
+ Sie können keine Zelle trennen, die nicht zuvor aus mehreren zusammengeführt wurde.
+ Die Eigenschaft ist nicht valide
+
+
+ Optionen
+ Info
+ Aktion
+ Aktionen
+ Hinzufügen
+ Alias
+ Alles
+ Sind Sie sicher?
+ Zurück
+ Zurück zur Übersicht
+ Rahmen
+ von
+ Abbrechen
+ Zellabstand
+ Auswählen
+ Schließen
+ Leeren
+ Fenster schließen
+ Fenster Pane
+ Kommentar
+ bestätigen
+ Beschneiden
+ Seitenverhältnis beibehalten
+ Inhalt
+ Weiter
+ Kopieren
+ Neu
+ Ausschnitte Bereich
+ Datenbank
+ Datum
+ Standard
+ Löschen
+ Gelöscht
+ Löschen ...
+ Design
+ Wörterbuch
+ Abmessungen
+ Verwerfen
+ nach unten
+ Herunterladen
+ Bearbeiten
+ Bearbeitet
+ Elemente
+ E-Mail
+ Fehler
+ Feld
+ Suche
+ Erste(s)
+ Allgemein
+ Gruppen
+ Gruppe
+ Generisch
+ Gruppe
+ Höhe
+ Hilfe
+ Verbergen
+ Verlauf
+ Bildzeichen
+ Id
+ Import
+ Nur in diesem Ordner suchen
+ Info
+ Innerer Abstand
+ Einfügen
+ Installieren
+ Ungültig
+ Zentrieren
+ Bezeichnung
+ Sprache
+ Letzte(s)
+ Layout
+ Links
+ Laden
+ Gesperrt
+ Anmelden
+ Abmelden
+ Abmelden
+ Makro
+ Pflichtfeld
+ Medien
+ Nachricht
+ Verschieben
+ Name
+ Neu
+ Weiter
+ Nein
+ Knoten Name
+ von
+ Aus
+ Ok
+ Öffnen
+ An
+ oder
+ Sortieren nach
+ Kennwort
+ Pfad
+ Einen Moment bitte...
+ Zurück
+ Eigenschaften
+ Mehr erfahren
+ Erneuern
+ E-Mail-Empfänger für die Formulardaten
+ Papierkorb
+ Ihr Mülleimer ist leer
+ Neu laden
+ Verbleibend
+ Entfernen
+ Rückgängig
+ Umbenennen
+ Erneuern
+ Pflichtangabe
+ Wiederherstellen
+ Wiederholen
+ Berechtigungen
+ Geplantes Veröffentlichen
+ Umbraco Information
+ Suchen
+ Leider können wir nicht finden, wonach Sie suchen.
+ Es wurden keine Elemente hinzugefügt
+ Server
+ Einstellungen
+ Geteilt
+ Anzeigen
+ Seite beim Senden anzeigen
+ Größe
+ Sortieren
+ Status
+ Senden
+ Erfolt
+ Typ
+ Typ Name
+ Durchsuchen ...
+ unter
+ nach oben
+ Aktualisieren
+ Update
+ Hochladen
+ URL
+ Benutzer
+ Benutzername
+ Validieren
+ Wert
+ Ansicht
+ Willkommen ...
+ Breite
+ Ja
+ Ordner
+ Suchergebnisse
+ Sortieren
+ Sortierung abschließen
+ Vorschau
+ Kennwort ändern
+ nach
+ Listenansicht
+ Sichern läuft...
+ Aktuelle(s)
+ Eingebettet
+ ausgewählt
+ Anderes
+ Artikel
+ Videos
+ Avatar für
+ Kopf
+ System Feld
+ Zuletzt geändert
+
+
+ Blau
+
+
+ Tab hinzufügen
+ Neue Gruppe
+ Neue Eigenschaft
+ Editor hinzufügen
+ Vorlage hinzufügen
+ Knoten unterhalb hinzufügen
+ Element unterhalb hinzufügen
+ Datentyp bearbeiten
+ Bereiche wechseln
+ Abkürzungen
+ Abkürzungen anzeigen
+ Listenansicht wechseln
+ Wurzelknotenberechtigung wechseln
+ Zeile ein-/auskommentieren
+ Zeile entfernen
+ Zeilen oberhalb kopieren
+ Zeilen unterhalb kopieren
+ Zeilen nach oben schieben
+ Zeilen nach unten schieben
+ Standard
+ Editor
+ Kulturvariantenberechtigung wechseln
+
+
+ Hintergrundfarbe
+ Fett
+ Textfarbe
+ Schriftart
+ Text
+
+
+ Dokument
+
+
+ Mit dieser Datenbank kann leider keine Verbindung hergestellt werden.
+
+ Appsettings.json Datei konnte nicht gespeichert werden. Bitte ändern Sie die Datei
+ manuell.
+
+ Die Datenbank ist erreichbar und wurde identifiziert als
+ Datenbank
+
+ Installieren, um die Datenbank für Umbraco %0% einzurichten.
+ ]]>
+
+
+ Die Datenbank wurde für Umbraco %0% konfiguriert.
+ Klicken Sie auf <strong>weiter</strong>, um fortzufahren.
+
+ Um diesen Schritt abzuschließen, müssen Sie die notwendigen Informationen zur Datenbankverbindung angeben.<br />Bitte kontaktieren Sie Ihren Provider bzw. Server-Administrator für weitere Informationen.
+
+
+ Bitte bestätigen Sie mit einem Klick auf Update, dass die Datenbank auf Umbraco %0% aktualisiert werden soll.
+
+
+ Keine Sorge - Dabei werden keine Inhalte gelöscht und alles wird weiterhin funktionieren!
+