Compare commits

..
Author SHA1 Message Date
Nikolaj c5fe779db0 Bump version 2023-03-23 09:20:38 +01:00
Nikolaj bf82d29e53 Convert path to absolute 2023-03-23 09:20:20 +01:00
517 changed files with 5695 additions and 27751 deletions
+7 -2
View File
@@ -11,10 +11,15 @@ jobs:
issues: write
pull-requests: write
steps:
- name: Install dependencies
run: |
npm install node-fetch@2
- name: Fetch random comment 🗣️ and add it to the PR
uses: actions/github-script@v6
with:
script: |
const fetch = require('node-fetch')
const response = await fetch('https://collaboratorsv2.euwest01.umbraco.io/umbraco/api/comments/PostComment', {
method: 'post',
body: JSON.stringify({
@@ -41,13 +46,13 @@ jobs:
});
} else {
console.log("Returned data not indicate success.");
if(response.status !== 200) {
console.log("Status code:", response.status)
}
console.log("Returned data:", data);
if(data === '') {
console.log("An empty response usually indicates that either no comment was found or the actor user was not eligible for getting an automated response (HQ users are not getting auto-responses).")
}
-1
View File
@@ -49,5 +49,4 @@
<PropertyGroup>
<GitVersionBaseDirectory>$(MSBuildThisFileDirectory)</GitVersionBaseDirectory>
</PropertyGroup>
</Project>
+57 -105
View File
@@ -21,33 +21,9 @@ parameters:
displayName: Upload API docs
type: boolean
default: false
- name: forceReleaseTestFilter
displayName: Force to use the release test filters
type: boolean
default: false
- name: integrationNonReleaseTestFilter
displayName: TestFilter used for non-release type builds
type: string
default: '--filter TestCategory!=LongRunning&TestCategory!=NonCritical'
- name: integrationReleaseTestFilter
displayName: TestFilter used for release type builds
type: string
default: ' '
- name: nonWindowsIntegrationNonReleaseTestFilter
displayName: TestFilter used for non-release type builds on non windows agents
type: string
default: '--filter TestCategory!=LongRunning&TestCategory!=NonCritical'
- name: nonWindowsIntegrationReleaseTestFilter
displayName: TestFilter used for release type builds on non windows agents
type: string
default: ' '
- name: isNightly
displayName: 'Is nightly build (used for MyGet feed)'
type: boolean
default: false
variables:
nodeVersion: 20
nodeVersion: 14.18.1
dotnetVersion: 6.x
dotnetIncludePreviewVersions: false
solution: umbraco.sln
@@ -73,7 +49,6 @@ stages:
steps:
- task: NodeTool@0
displayName: Use Node.js $(nodeVersion)
retryCountOnTaskFailure: 3
inputs:
versionSpec: $(nodeVersion)
- task: Cache@2
@@ -86,9 +61,9 @@ stages:
path: $(npm_config_cache)
- script: npm ci --no-fund --no-audit --prefer-offline
workingDirectory: src/Umbraco.Web.UI.Client
displayName: Run npm ci (Backoffice)
displayName: Run npm ci
- task: gulp@0
displayName: Run gulp build (Backoffice)
displayName: Run gulp build
inputs:
gulpFile: src/Umbraco.Web.UI.Client/gulpfile.js
targets: coreBuild
@@ -105,12 +80,44 @@ stages:
command: restore
projects: $(solution)
- task: DotNetCoreCLI@2
name: build
displayName: Run dotnet build and generate NuGet packages
displayName: Run dotnet build
inputs:
command: build
projects: $(solution)
arguments: '--configuration $(buildConfiguration) --no-restore --property:ContinuousIntegrationBuild=true --property:GeneratePackageOnBuild=true --property:PackageOutputPath=$(Build.ArtifactStagingDirectory)/nupkg'
arguments: '--configuration $(buildConfiguration) --no-restore -p:ContinuousIntegrationBuild=true'
- script: |
version="$(Build.BuildNumber)"
echo "varsion: $version"
major="$(echo $version | cut -d '.' -f 1)"
echo "major version: $major"
echo "##vso[task.setvariable variable=majorVersion;isOutput=true]$major"
displayName: Set major version
name: determineMajorVersion
- task: PowerShell@2
displayName: Prepare nupkg
inputs:
targetType: inline
script: |
$umbracoVersion = "$(Build.BuildNumber)" -replace "\+",".g"
$templatePaths = Get-ChildItem 'templates/**/.template.config/template.json'
foreach ($templatePath in $templatePaths) {
$a = Get-Content $templatePath -Raw | ConvertFrom-Json
if ($a.symbols -and $a.symbols.UmbracoVersion) {
$a.symbols.UmbracoVersion.defaultValue = $umbracoVersion
$a | ConvertTo-Json -Depth 32 | Set-Content $templatePath
}
}
dotnet pack $(solution) --configuration $(buildConfiguration) -p:BuildProjectReferences=false --output $(Build.ArtifactStagingDirectory)/nupkg
- script: |
sha="$(Build.SourceVersion)"
sha=${sha:0:7}
buildnumber="$(Build.BuildNumber)_$(Build.BuildId)_$sha"
echo "##vso[build.updatebuildnumber]$buildnumber"
displayName: Update build number
- task: PublishPipelineArtifact@1
displayName: Publish nupkg
inputs:
@@ -123,11 +130,11 @@ stages:
artifactName: build_output
- stage: Build_Docs
condition: and(succeeded(), or(eq(dependencies.Build.outputs['A.build.NBGV_PublicRelease'], 'True'), ${{parameters.buildApiDocs}}))
condition: and(succeeded(), or(startsWith(variables['Build.SourceBranch'], 'refs/heads/release/'), ${{parameters.buildApiDocs}}))
displayName: Prepare API Documentation
dependsOn: Build
variables:
umbracoMajorVersion: $[ stageDependencies.Build.A.outputs['build.NBGV_VersionMajor'] ]
umbracoMajorVersion: $[ stageDependencies.Build.A.outputs['determineMajorVersion.majorVersion'] ]
jobs:
# C# API Reference
- job:
@@ -140,7 +147,7 @@ stages:
inputs:
targetType: inline
script: |
choco install docfx --version=2.59.4 -y
choco install docfx --version=2.59.2 -y
if ($lastexitcode -ne 0){
throw ("Error installing DocFX")
}
@@ -181,10 +188,9 @@ stages:
vmImage: 'ubuntu-latest'
steps:
- task: NodeTool@0
displayName: Use Node.js 10.15.x
retryCountOnTaskFailure: 3
displayName: Use Node.js 10.15.0
inputs:
versionSpec: 10.15.x # Won't work with higher versions
versionSpec: 10.15.0 # Won't work with higher versions
- script: |
npm ci --no-fund --no-audit --prefer-offline
npx gulp docs
@@ -253,8 +259,6 @@ stages:
- stage: Integration
displayName: Integration Tests
dependsOn: Build
variables:
releaseTestFilter: eq(dependencies.Build.outputs['A.build.NBGV_PublicRelease'], 'True')
jobs:
# Integration Tests (SQLite)
- job:
@@ -282,30 +286,12 @@ stages:
performMultiLevelLookup: true
includePreviewVersions: $(dotnetIncludePreviewVersions)
- task: DotNetCoreCLI@2
displayName: Run dotnet test Windows
condition: eq(variables['Agent.OS'],'Windows_NT')
displayName: Run dotnet test
inputs:
command: test
projects: '**/*.Tests.Integration.csproj'
arguments: '--configuration $(buildConfiguration) --no-build'
testRunTitle: Integration Tests SQLite - $(Agent.OS)
${{ if or(variables.releaseTestFilter, parameters.forceReleaseTestFilter) }}:
arguments: '--configuration $(buildConfiguration) --no-build ${{parameters.integrationReleaseTestFilter}}'
${{ else }}:
arguments: '--configuration $(buildConfiguration) ${{parameters.integrationNonReleaseTestFilter}}'
env:
Tests__Database__DatabaseType: 'Sqlite'
Umbraco__CMS__Global__MainDomLock: 'FileSystemMainDomLock'
- task: DotNetCoreCLI@2
displayName: Run dotnet test Non Windows
condition: ne(variables['Agent.OS'],'Windows_NT')
inputs:
command: test
projects: '**/*.Tests.Integration.csproj'
testRunTitle: Integration Tests SQLite - $(Agent.OS)
${{ if or(variables.releaseTestFilter, parameters.forceReleaseTestFilter) }}:
arguments: '--configuration $(buildConfiguration) --no-build ${{parameters.nonWindowsIntegrationReleaseTestFilter}}'
${{ else }}:
arguments: '--configuration $(buildConfiguration) ${{parameters.nonWindowsIntegrationNonReleaseTestFilter}}'
env:
Tests__Database__DatabaseType: 'Sqlite'
Umbraco__CMS__Global__MainDomLock: 'FileSystemMainDomLock'
@@ -313,7 +299,7 @@ stages:
# Integration Tests (SQL Server)
- job:
timeoutInMinutes: 120
condition: or(eq(stageDependencies.Build.A.outputs['build.NBGV_PublicRelease'], 'True'), ${{parameters.sqlServerIntegrationTests}})
condition: or(startsWith(variables['Build.SourceBranch'], 'refs/heads/release/'), ${{parameters.sqlServerIntegrationTests}})
displayName: Integration Tests (SQL Server)
strategy:
matrix:
@@ -324,7 +310,7 @@ stages:
Linux:
vmImage: 'ubuntu-latest'
testDb: SqlServer
connectionString: 'Server=localhost,1433;User Id=sa;Password=$(SA_PASSWORD);TrustServerCertificate=true'
connectionString: 'Server=localhost,1433;User Id=sa;Password=$(SA_PASSWORD);'
pool:
vmImage: $(vmImage)
variables:
@@ -335,11 +321,6 @@ stages:
inputs:
artifact: build_output
path: $(Build.SourcesDirectory)
- task: UseDotNet@2
displayName: Use .NET $(dotnetVersion)
inputs:
version: $(dotnetVersion)
includePreviewVersions: $(dotnetIncludePreviewVersions)
- powershell: sqllocaldb start mssqllocaldb
displayName: Start localdb (Windows only)
condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT'))
@@ -347,31 +328,12 @@ stages:
displayName: Start SQL Server (Linux only)
condition: and(succeeded(), eq(variables['Agent.OS'], 'Linux'))
- task: DotNetCoreCLI@2
displayName: Run dotnet test Windows
condition: eq(variables['Agent.OS'],'Windows_NT')
displayName: Run dotnet test
inputs:
command: test
projects: '**/*.Tests.Integration.csproj'
arguments: '--configuration $(buildConfiguration) --no-build'
testRunTitle: Integration Tests SQL Server - $(Agent.OS)
${{ if or(variables.releaseTestFilter, parameters.forceReleaseTestFilter) }}:
arguments: '--configuration $(buildConfiguration) --no-build ${{parameters.integrationReleaseTestFilter}}'
${{ else }}:
arguments: '--configuration $(buildConfiguration) --no-build ${{parameters.integrationNonReleaseTestFilter}}'
env:
Tests__Database__DatabaseType: $(testDb)
Tests__Database__SQLServerMasterConnectionString: $(connectionString)
Umbraco__CMS__Global__MainDomLock: 'SqlMainDomLock'
- task: DotNetCoreCLI@2
displayName: Run dotnet test NonWindows
condition: ne(variables['Agent.OS'],'Windows_NT')
inputs:
command: test
projects: '**/*.Tests.Integration.csproj'
testRunTitle: Integration Tests SQL Server - $(Agent.OS)
${{ if or(variables.releaseTestFilter, parameters.forceReleaseTestFilter) }}:
arguments: '--configuration $(buildConfiguration) --no-build ${{parameters.nonWindowsIntegrationReleaseTestFilter}}'
${{ else }}:
arguments: '--configuration $(buildConfiguration) --no-build ${{parameters.nonWindowsIntegrationNonReleaseTestFilter}}'
env:
Tests__Database__DatabaseType: $(testDb)
Tests__Database__SQLServerMasterConnectionString: $(connectionString)
@@ -399,7 +361,6 @@ stages:
dockerImageName: umbraco-linux
Windows:
vmImage: 'windows-latest'
DOTNET_GENERATE_ASPNET_CERTIFICATE: true # Automatically generate HTTPS development certificate on Windows
# Enable console logging in Release mode
Serilog__WriteTo__0__Name: Async
Serilog__WriteTo__0__Args__configure__0__Name: Console
@@ -407,7 +368,7 @@ stages:
Umbraco__CMS__Unattended__InstallUnattended: true
Umbraco__CMS__Global__InstallMissingDatabase: true
UmbracoDatabaseServer: (LocalDB)\MSSQLLocalDB
UmbracoDatabaseName: AcceptanceTestDB
UmbracoDatabaseName: Playwright
ConnectionStrings__umbracoDbDSN: Server=$(UmbracoDatabaseServer);Database=$(UmbracoDatabaseName);Integrated Security=true;
# Custom Umbraco settings
Umbraco__CMS__Global__VersionCheckPeriod: 0
@@ -424,7 +385,6 @@ stages:
path: $(Build.SourcesDirectory)/tests/Umbraco.Tests.AcceptanceTest/misc/nupkg
- task: NodeTool@0
displayName: Use Node.js $(nodeVersion)
retryCountOnTaskFailure: 3
inputs:
versionSpec: $(nodeVersion)
- task: Cache@2
@@ -469,7 +429,7 @@ stages:
workingDirectory: tests/Umbraco.Tests.AcceptanceTest/misc
- pwsh: |
dotnet new --install ./nupkg/Umbraco.Templates.*.nupkg
dotnet new umbraco --name AcceptanceTestProject --no-restore --output .
dotnet new umbraco --name Playwright --no-restore --output .
dotnet restore --configfile ./nuget.config
dotnet build --configuration $(buildConfiguration) --no-restore
dotnet dev-certs https
@@ -490,8 +450,6 @@ stages:
workingDirectory: tests/Umbraco.Tests.AcceptanceTest
env:
CI: true
CommitId: $(Build.SourceVersion)
AgentOs: $(Agent.OS)
- pwsh: |
docker logs $(dockerImageName) > $(Build.ArtifactStagingDirectory)/playwright.log 2>&1
docker stop $(dockerImageName)
@@ -530,11 +488,9 @@ stages:
- Unit
- Integration
# - E2E # TODO: Enable when stable.
condition: and(succeeded(), or(eq(dependencies.Build.outputs['A.build.NBGV_PublicRelease'], 'True'), ${{parameters.myGetDeploy}}))
condition: and(succeeded(), or(startsWith(variables['Build.SourceBranch'], 'refs/heads/release/'), ${{parameters.myGetDeploy}}))
jobs:
- job:
pool:
vmImage: "windows-latest" # NuGetCommand@2 is no longer supported on Ubuntu 24.04 so we'll use windows until an alternative is available.
displayName: Push to pre-release feed
steps:
- checkout: none
@@ -549,20 +505,16 @@ stages:
command: 'push'
packagesToPush: $(Build.ArtifactStagingDirectory)/**/*.nupkg
nuGetFeedType: 'external'
${{ if eq(parameters.isNightly, true) }}:
publishFeedCredentials: 'MyGet - Umbraco Nightly'
${{ else }}:
publishFeedCredentials: 'MyGet - Pre-releases'
publishFeedCredentials: 'MyGet - Pre-releases'
- stage: Deploy_NuGet
displayName: NuGet release
dependsOn:
- Deploy_MyGet
- Build_Docs
condition: and(succeeded(), or(eq(dependencies.Build.outputs['A.build.NBGV_PublicRelease'], 'True'), ${{parameters.nuGetDeploy}}))
condition: and(succeeded(), or(startsWith(variables['Build.SourceBranch'], 'refs/heads/release/'), ${{parameters.nuGetDeploy}}))
jobs:
- job:
pool:
vmImage: "windows-latest" # NuGetCommand@2 is no longer supported on Ubuntu 24.04 so we'll use windows until an alternative is available.
displayName: Push to NuGet
steps:
- checkout: none
@@ -583,12 +535,12 @@ stages:
pool:
vmImage: 'windows-latest' # Apparently AzureFileCopy is windows only :(
variables:
umbracoMajorVersion: $[ stageDependencies.Build.A.outputs['build.NBGV_VersionMajor'] ]
umbracoMajorVersion: $[ stageDependencies.Build.A.outputs['determineMajorVersion.majorVersion'] ]
displayName: Upload API Documention
dependsOn:
- Build
- Deploy_NuGet
condition: and(succeeded(), or(eq(dependencies.Build.outputs['A.build.NBGV_PublicRelease'], 'True'), ${{parameters.uploadApiDocs}}))
condition: and(succeeded(), or(startsWith(variables['Build.SourceBranch'], 'refs/heads/release/'), ${{parameters.uploadApiDocs}}))
jobs:
- job:
displayName: Upload C# Docs
-35
View File
@@ -1,35 +0,0 @@
name: Nightly_$(TeamProject)_$(Build.DefinitionName)_$(SourceBranchName)_$(Date:yyyyMMdd)$(Rev:.r)
pr: none
trigger: none
schedules:
- cron: '0 0 * * *'
displayName: Daily midnight build
branches:
include:
- v10/dev
- v12/dev
- v13/dev
- v14/dev
steps:
- checkout: none
- task: TriggerBuild@4
inputs:
definitionIsInCurrentTeamProject: true
buildDefinition: '301'
queueBuildForUserThatTriggeredBuild: true
ignoreSslCertificateErrors: false
useSameSourceVersion: false
useCustomSourceVersion: false
useSameBranch: true
waitForQueuedBuildsToFinish: false
storeInEnvironmentVariable: false
templateParameters: 'sqlServerIntegrationTests: true, forceReleaseTestFilter: true, myGetDeploy: true, isNightly: true'
authenticationMethod: 'OAuth Token'
enableBuildInQueueCondition: false
dependentOnSuccessfulBuildCondition: false
dependentOnFailedBuildCondition: false
checkbuildsoncurrentbranch: false
failTaskIfConditionsAreNotFulfilled: false
-6
View File
@@ -1,6 +0,0 @@
{
"sdk": {
"version": "6.0.300",
"rollForward": "latestFeature"
}
}
-67
View File
@@ -1,67 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<NoWarn>NU1507</NoWarn>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Dazinator.Extensions.FileProviders" Version="2.0.0" />
<PackageVersion Include="Examine" Version="3.0.1" />
<PackageVersion Include="Examine.Core" Version="3.0.1" />
<PackageVersion Include="HtmlAgilityPack" Version="1.11.54" />
<PackageVersion Include="IPNetwork2" Version="2.6.618" />
<PackageVersion Include="K4os.Compression.LZ4" Version="1.3.6" />
<PackageVersion Include="MailKit" Version="3.2.0" />
<PackageVersion Include="Markdown" Version="2.2.1" />
<PackageVersion Include="MessagePack" Version="2.5.187" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.24" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="6.0.24" />
<PackageVersion Include="Microsoft.Data.Sqlite" Version="6.0.24" />
<PackageVersion Include="Microsoft.CSharp" Version="4.7.0" />
<PackageVersion Include="Microsoft.Extensions.FileProviders.Embedded" Version="6.0.24" />
<PackageVersion Include="Microsoft.Extensions.FileProviders.Physical" Version="6.0.0" />
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="6.0.0" />
<PackageVersion Include="Microsoft.Extensions.Identity.Core" Version="6.0.24" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="6.0.0" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="6.0.0" />
<PackageVersion Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="6.0.0" />
<PackageVersion Include="Microsoft.Extensions.Options.DataAnnotations" Version="6.0.0" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Abstractions" Version="6.0.0" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Json" Version="6.0.0" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="6.0.1" />
<PackageVersion Include="Microsoft.Extensions.Http" Version="6.0.0" />
<PackageVersion Include="Microsoft.Extensions.Identity.Stores" Version="6.0.24" />
<PackageVersion Include="MiniProfiler.AspNetCore.Mvc" Version="4.2.22" />
<PackageVersion Include="MiniProfiler.Shared" Version="4.2.22" />
<PackageVersion Include="ncrontab" Version="3.3.3" />
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
<PackageVersion Include="NPoco.SqlServer" Version="5.3.2" />
<PackageVersion Include="Serilog" Version="2.12.0" />
<PackageVersion Include="Serilog.AspNetCore" Version="5.0.0" />
<PackageVersion Include="Serilog.Enrichers.Process" Version="2.0.2" />
<PackageVersion Include="Serilog.Enrichers.Thread" Version="3.1.0" />
<PackageVersion Include="Serilog.Expressions" Version="3.4.1" />
<PackageVersion Include="Serilog.Extensions.Hosting" Version="4.2.0" />
<PackageVersion Include="Serilog.Formatting.Compact" Version="1.1.0" />
<PackageVersion Include="Serilog.Formatting.Compact.Reader" Version="1.0.5" />
<PackageVersion Include="Serilog.Settings.Configuration" Version="3.4.0" />
<PackageVersion Include="Serilog.Sinks.Async" Version="1.5.0" />
<PackageVersion Include="Serilog.Sinks.File" Version="5.0.0" />
<PackageVersion Include="Serilog.Sinks.Map" Version="1.0.2" />
<PackageVersion Include="SixLabors.ImageSharp" Version="2.1.10" />
<PackageVersion Include="SixLabors.ImageSharp.Web" Version="2.0.2" />
<PackageVersion Include="Smidge.InMemory" Version="4.3.0" />
<PackageVersion Include="Smidge.Nuglify" Version="4.2.1" />
<PackageVersion Include="System.IO.FileSystem.AccessControl" Version="5.0.0" />
<PackageVersion Include="System.Security.Cryptography.Pkcs" Version="6.0.4" />
<PackageVersion Include="System.Threading.Tasks.Dataflow" Version="6.0.0" />
<PackageVersion Include="System.ComponentModel.Annotations" Version="5.0.0" />
<PackageVersion Include="System.Reflection.Emit.Lightweight" Version="4.7.0" />
<PackageVersion Include="System.Runtime.Caching" Version="6.0.0" />
<PackageVersion Include="Umbraco.CSharpTest.Net.Collections" Version="14.906.1403.1085" />
<!-- Add dependencies that we force an update to, even that we do not use them explicitly and they seems to be taken from the framework instead of from Nuget -->
<PackageVersion Include="System.Net.Http" Version="4.3.4" />
<PackageVersion Include="System.Security.Cryptography.Xml" Version="6.0.1" />
<PackageVersion Include="System.Text.RegularExpressions" Version="4.3.1" />
</ItemGroup>
</Project>
+1 -16
View File
@@ -51,7 +51,6 @@ namespace JsonSchema
public ImagingSettings? Imaging { get; set; }
public IndexCreatorSettings? Examine { get; set; }
public IndexingSettings? Indexing { get; set; }
public KeepAliveSettings? KeepAlive { get; set; }
@@ -89,27 +88,13 @@ namespace JsonSchema
public HelpPageSettings? HelpPage { get; set; }
public InstallDefaultData? InstallDefaultData { get; set; }
public InstallDefaultDataSettings? DefaultDataCreation { get; set; }
public DataTypesSettings? DataTypes { get; set; }
public MarketplaceSettings? Marketplace { get; set; }
}
/// <summary>
/// Configurations for the Umbraco CMS InstallDefaultData configuration.
/// </summary>
public class InstallDefaultData
{
public InstallDefaultDataSettings? Languages { get; set; }
public InstallDefaultDataSettings? DataTypes { get; set; }
public InstallDefaultDataSettings? MediaTypes { get; set; }
public InstallDefaultDataSettings? MemberTypes { get; set; }
}
/// <summary>
/// Configurations for the Umbraco Forms package to Umbraco CMS
/// </summary>
+3 -4
View File
@@ -3,17 +3,16 @@
<OutputType>Exe</OutputType>
<IsPackable>false</IsPackable>
<EnablePackageValidation>false</EnablePackageValidation>
<ManagePackageVersionsCentrally>false</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="CommandLineParser" Version="2.9.1" />
<PackageReference Include="NJsonSchema" Version="10.9.0" />
<PackageReference Include="NJsonSchema" Version="10.7.2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Umbraco.Core\Umbraco.Core.csproj" />
<PackageReference Include="Umbraco.Deploy.Core" Version="10.4.0" />
<PackageReference Include="Umbraco.Forms.Core" Version="10.5.4" />
<PackageReference Include="Umbraco.Deploy.Core" Version="10.1.2" />
<PackageReference Include="Umbraco.Forms.Core" Version="10.2.1" />
</ItemGroup>
</Project>
@@ -4,7 +4,6 @@
<Description>Contains the presentation layer for the Umbraco CMS Management API.</Description>
<IsPackable>false</IsPackable>
<EnablePackageValidation>false</EnablePackageValidation>
<ManagePackageVersionsCentrally>false</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
@@ -13,7 +12,7 @@
<PackageReference Include="Microsoft.AspNetCore.Mvc.Versioning.ApiExplorer" Version="5.0.0" />
<PackageReference Include="NSwag.AspNetCore" Version="13.16.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Umbraco.Infrastructure\Umbraco.Infrastructure.csproj" />
<ProjectReference Include="..\Umbraco.New.Cms.Core\Umbraco.New.Cms.Core.csproj" />
@@ -21,7 +20,7 @@
<ProjectReference Include="..\Umbraco.New.Cms.Web.Common\Umbraco.New.Cms.Web.Common.csproj" />
<ProjectReference Include="..\Umbraco.Web.Common\Umbraco.Web.Common.csproj" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="OpenApi.json" />
</ItemGroup>
@@ -1,12 +1,12 @@
namespace Umbraco.Cms.Persistence.SqlServer;
/// <summary>
/// Constants related to SQL Server.
/// Constants related to SQLite.
/// </summary>
public static class Constants
{
/// <summary>
/// SQL Server provider name.
/// SQLite provider name.
/// </summary>
public const string ProviderName = "Microsoft.Data.SqlClient";
}
@@ -1,5 +1,4 @@
using System.Runtime.Serialization;
using Microsoft.Data.SqlClient;
using Umbraco.Cms.Core.Install.Models;
using Umbraco.Cms.Infrastructure.Persistence;
using Umbraco.Extensions;
@@ -51,25 +50,6 @@ public class SqlAzureDatabaseProviderMetadata : IDatabaseProviderMetadata
/// <inheritdoc />
public bool ForceCreateDatabase => false;
/// <inheritdoc />
public bool CanRecognizeConnectionString(string? connectionString)
{
if (connectionString is null)
{
return false;
}
try
{
var builder = new SqlConnectionStringBuilder(connectionString);
return string.IsNullOrEmpty(builder.AttachDBFilename) && builder.DataSource.Contains("database.windows.net");
}
catch (ArgumentException)
{
return false;
}
}
/// <inheritdoc />
public string GenerateConnectionString(DatabaseModel databaseModel)
{
@@ -51,27 +51,6 @@ public class SqlLocalDbDatabaseProviderMetadata : IDatabaseProviderMetadata
/// <inheritdoc />
public bool ForceCreateDatabase => true;
/// <inheritdoc />
public bool CanRecognizeConnectionString(string? connectionString)
{
if (connectionString is null)
{
return false;
}
try
{
var builder = new SqlConnectionStringBuilder(connectionString);
return !string.IsNullOrEmpty(builder.AttachDBFilename);
}
catch (ArgumentException)
{
return false;
}
}
/// <inheritdoc />
public string GenerateConnectionString(DatabaseModel databaseModel)
{
@@ -1,9 +1,6 @@
using System.Data.Common;
using System.Runtime.Serialization;
using Microsoft.Data.SqlClient;
using Umbraco.Cms.Core.Install.Models;
using Umbraco.Cms.Infrastructure.Persistence;
using Umbraco.Extensions;
namespace Umbraco.Cms.Persistence.SqlServer.Services;
@@ -52,26 +49,6 @@ public class SqlServerDatabaseProviderMetadata : IDatabaseProviderMetadata
/// <inheritdoc />
public bool ForceCreateDatabase => false;
/// <inheritdoc />
public bool CanRecognizeConnectionString(string? connectionString)
{
if (connectionString is null)
{
return false;
}
try
{
var builder = new SqlConnectionStringBuilder(connectionString);
return string.IsNullOrEmpty(builder.AttachDBFilename);
}
catch (ArgumentException)
{
return false;
}
}
/// <inheritdoc />
public string GenerateConnectionString(DatabaseModel databaseModel) =>
databaseModel.IntegratedAuth
@@ -134,10 +134,9 @@ public class SqlServerDistributedLockingMechanism : IDistributedLockingMechanism
const string query = "SELECT value FROM umbracoLock WITH (REPEATABLEREAD) WHERE id=@id";
var lockTimeoutQuery = $"SET LOCK_TIMEOUT {_timeout.TotalMilliseconds}";
db.Execute("SET LOCK_TIMEOUT " + _timeout.TotalMilliseconds + ";");
// execute the lock timeout query and the actual query in a single server roundtrip
var i = db.ExecuteScalar<int?>($"{lockTimeoutQuery};{query}", new { id = LockId });
var i = db.ExecuteScalar<int?>(query, new { id = LockId });
if (i == null)
{
@@ -170,10 +169,9 @@ public class SqlServerDistributedLockingMechanism : IDistributedLockingMechanism
const string query =
@"UPDATE umbracoLock WITH (REPEATABLEREAD) SET value = (CASE WHEN (value=1) THEN -1 ELSE 1 END) WHERE id=@id";
var lockTimeoutQuery = $"SET LOCK_TIMEOUT {_timeout.TotalMilliseconds}";
db.Execute("SET LOCK_TIMEOUT " + _timeout.TotalMilliseconds + ";");
// execute the lock timeout query and the actual query in a single server roundtrip
var i = db.Execute($"{lockTimeoutQuery};{query}", new { id = LockId });
var i = db.Execute(query, new { id = LockId });
if (i == 0)
{
@@ -1,11 +0,0 @@
using Umbraco.Cms.Core.Mapping;
using Umbraco.Cms.Infrastructure.Persistence;
namespace Umbraco.Cms.Persistence.SqlServer.Services;
public class SqlServerSpecificMapperFactory : IProviderSpecificMapperFactory
{
public string ProviderName => Constants.ProviderName;
public NPocoMapperCollection Mappers => new(() => new[] { new UmbracoDefaultMapper() });
}
@@ -272,13 +272,6 @@ where tbl.[name]=@0 and col.[name]=@1;",
return !constraintName.IsNullOrWhiteSpace();
}
public override bool DoesPrimaryKeyExist(IDatabase db, string tableName, string primaryKeyName)
{
IEnumerable<SqlPrimaryKey>? keys = db.Fetch<SqlPrimaryKey>($"select * from sysobjects where xtype='pk' and parent_obj in (select id from sysobjects where name='{tableName}')")
.Where(x => x.Name == primaryKeyName);
return keys.FirstOrDefault() is not null;
}
public override bool DoesTableExist(IDatabase db, string tableName)
{
var result =
@@ -460,9 +453,4 @@ _sqlInspector ??= new SqlInspectionUtilities();
}
#endregion
private class SqlPrimaryKey
{
public string Name { get; set; } = null!;
}
}
@@ -22,8 +22,6 @@ public static class UmbracoBuilderExtensions
/// </summary>
public static IUmbracoBuilder AddUmbracoSqlServerSupport(this IUmbracoBuilder builder)
{
builder.Services.TryAddEnumerable(ServiceDescriptor
.Singleton<IProviderSpecificMapperFactory, SqlServerSpecificMapperFactory>());
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<ISqlSyntaxProvider, SqlServerSyntaxProvider>());
builder.Services.TryAddEnumerable(ServiceDescriptor
.Singleton<IBulkSqlInsertProvider, SqlServerBulkSqlInsertProvider>());
@@ -1,4 +1,3 @@
using System.Globalization;
using NPoco;
namespace Umbraco.Cms.Persistence.Sqlite.Mappers;
@@ -29,24 +28,6 @@ public class SqlitePocoGuidMapper : DefaultMapper
};
}
if (destType == typeof(decimal))
{
return value =>
{
var result = Convert.ToDecimal(value, CultureInfo.InvariantCulture);
return result;
};
}
if (destType == typeof(decimal?))
{
return value =>
{
var result = Convert.ToDecimal(value, CultureInfo.InvariantCulture);
return result;
};
}
return base.GetFromDbConverter(destType, sourceType);
}
}
@@ -56,26 +56,6 @@ public class SqliteDatabaseProviderMetadata : IDatabaseProviderMetadata
/// </remarks>
public bool ForceCreateDatabase => true;
/// <inheritdoc />
public bool CanRecognizeConnectionString(string? connectionString)
{
if (connectionString is null)
{
return false;
}
try
{
var builder = new SqliteConnectionStringBuilder(connectionString);
return !string.IsNullOrEmpty(builder.DataSource);
}
catch (ArgumentException)
{
return false;
}
}
/// <inheritdoc />
public string GenerateConnectionString(DatabaseModel databaseModel)
{
@@ -154,7 +154,7 @@ public class SqliteDistributedLockingMechanism : IDistributedLockingMechanism
try
{
var i = db.ExecuteNonQuery(command);
var i = command.ExecuteNonQuery();
if (i == 0)
{
@@ -174,14 +174,6 @@ public class SqliteSyntaxProvider : SqlSyntaxProviderBase<SqliteSyntaxProvider>
return false;
}
public override bool DoesPrimaryKeyExist(IDatabase db, string tableName, string primaryKeyName)
{
IEnumerable<string> items = db.Fetch<string>($"select sql from sqlite_master where type = 'table' and name = '{tableName}'")
.Where(x => x.Contains($"CONSTRAINT {primaryKeyName} PRIMARY KEY"));
return items.Any();
}
public override string GetFieldNameForUpdate<TDto>(Expression<Func<TDto, object?>> fieldSelector, string? tableAlias = null)
{
var field = ExpressionHelper.FindProperty(fieldSelector).Item1 as PropertyInfo;
@@ -5,7 +5,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Data.Sqlite" />
<PackageReference Include="Microsoft.Data.Sqlite" Version="6.0.5" />
</ItemGroup>
<ItemGroup>
-1
View File
@@ -4,7 +4,6 @@
<Description>Installs Umbraco CMS with all default dependencies in your ASP.NET Core project.</Description>
<IncludeBuildOutput>false</IncludeBuildOutput>
<IncludeSymbols>false</IncludeSymbols>
<ManagePackageVersionsCentrally>false</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
@@ -84,8 +84,8 @@ public sealed class ContentCacheRefresher : PayloadCacheRefresherBase<ContentCac
isolatedCache.ClearOfType<IContent>((k, v) => v.Path?.Contains(pathid) ?? false);
}
// if the item is not a blueprint and is being completely removed, we need to refresh the domains cache if any domain was assigned to the content
if (payload.Blueprint is false && payload.ChangeTypes.HasTypesAny(TreeChangeTypes.Remove))
// if the item is being completely removed, we need to refresh the domains cache if any domain was assigned to the content
if (payload.ChangeTypes.HasTypesAny(TreeChangeTypes.Remove))
{
idsRemoved.Add(payload.Id);
}
@@ -120,11 +120,7 @@ public sealed class ContentCacheRefresher : PayloadCacheRefresherBase<ContentCac
// should rename it, and then, this is only for Deploy, and then, ???
// if (Suspendable.PageCacheRefresher.CanUpdateDocumentCache)
// ...
if (payloads.Any(x => x.Blueprint is false))
{
// Only notify if the payload contains actual (non-blueprint) contents
NotifyPublishedSnapshotService(_publishedSnapshotService, AppCaches, payloads);
}
NotifyPublishedSnapshotService(_publishedSnapshotService, AppCaches, payloads);
base.Refresh(payloads);
}
@@ -161,13 +157,8 @@ public sealed class ContentCacheRefresher : PayloadCacheRefresherBase<ContentCac
}
}
// TODO (V14): Change into a record
public class JsonPayload
{
public JsonPayload()
{ }
[Obsolete("Use the default constructor and property initializers.")]
public JsonPayload(int id, Guid? key, TreeChangeTypes changeTypes)
{
Id = id;
@@ -175,13 +166,11 @@ public sealed class ContentCacheRefresher : PayloadCacheRefresherBase<ContentCac
ChangeTypes = changeTypes;
}
public int Id { get; init; }
public int Id { get; }
public Guid? Key { get; init; }
public Guid? Key { get; }
public TreeChangeTypes ChangeTypes { get; init; }
public bool Blueprint { get; init; }
public TreeChangeTypes ChangeTypes { get; }
}
#endregion
@@ -88,6 +88,10 @@ public sealed class DataTypeCacheRefresher : PayloadCacheRefresherBase<DataTypeC
}
}
// TODO: not sure I like these?
TagsValueConverter.ClearCaches();
SliderValueConverter.ClearCaches();
// refresh the models and cache
_publishedModelFactory.WithSafeLiveFactoryReset(() =>
_publishedSnapshotService.Notify(payloads));
@@ -134,14 +134,8 @@ public sealed class LanguageCacheRefresher : PayloadCacheRefresherBase<LanguageC
ContentCacheRefresher.RefreshContentTypes(AppCaches); // we need to evict all IContent items
// now refresh all nucache
ContentCacheRefresher.JsonPayload[] clearContentPayload = new[]
{
new ContentCacheRefresher.JsonPayload()
{
ChangeTypes = TreeChangeTypes.RefreshAll
}
};
ContentCacheRefresher.JsonPayload[] clearContentPayload =
new[] { new ContentCacheRefresher.JsonPayload(0, null, TreeChangeTypes.RefreshAll) };
ContentCacheRefresher.NotifyPublishedSnapshotService(_publishedSnapshotService, AppCaches, clearContentPayload);
}
+8 -31
View File
@@ -9,9 +9,6 @@ namespace Umbraco.Cms.Core.Cache;
/// </summary>
public class ObjectCacheAppCache : IAppPolicyCache, IDisposable
{
private static readonly TimeSpan _readLockTimeout = TimeSpan.FromSeconds(5);
private static readonly TimeSpan _writeLockTimeout = TimeSpan.FromSeconds(5);
private readonly ReaderWriterLockSlim _locker = new(LockRecursionPolicy.SupportsRecursion);
private bool _disposedValue;
@@ -36,10 +33,7 @@ public class ObjectCacheAppCache : IAppPolicyCache, IDisposable
Lazy<object?>? result;
try
{
if (_locker.TryEnterReadLock(_readLockTimeout) is false)
{
throw new TimeoutException("Timeout exceeded to the memory cache when getting item");
}
_locker.EnterReadLock();
result = MemoryCache.Get(key) as Lazy<object?>; // null if key not found
}
finally
@@ -201,10 +195,7 @@ public class ObjectCacheAppCache : IAppPolicyCache, IDisposable
{
try
{
if (_locker.TryEnterWriteLock(_writeLockTimeout) is false)
{
throw new TimeoutException("Timeout exceeded to the memory cache when clearing item");
}
_locker.EnterWriteLock();
if (MemoryCache[key] == null)
{
return;
@@ -232,10 +223,8 @@ public class ObjectCacheAppCache : IAppPolicyCache, IDisposable
var isInterface = type.IsInterface;
try
{
if (_locker.TryEnterWriteLock(_writeLockTimeout) is false)
{
throw new TimeoutException("Timeout exceeded to the memory cache when clearing by type");
}
_locker.EnterWriteLock();
// ToArray required to remove
foreach (var key in MemoryCache
.Where(x =>
@@ -270,10 +259,7 @@ public class ObjectCacheAppCache : IAppPolicyCache, IDisposable
{
try
{
if (_locker.TryEnterWriteLock(_writeLockTimeout) is false)
{
throw new TimeoutException("Timeout exceeded to the memory cache when clearing by generic type");
}
_locker.EnterWriteLock();
Type typeOfT = typeof(T);
var isInterface = typeOfT.IsInterface;
@@ -310,10 +296,7 @@ public class ObjectCacheAppCache : IAppPolicyCache, IDisposable
{
try
{
if (_locker.TryEnterWriteLock(_writeLockTimeout) is false)
{
throw new TimeoutException("Timeout exceeded to the memory cache when clearing generic type with predicate");
}
_locker.EnterWriteLock();
Type typeOfT = typeof(T);
var isInterface = typeOfT.IsInterface;
@@ -355,10 +338,7 @@ public class ObjectCacheAppCache : IAppPolicyCache, IDisposable
{
try
{
if (_locker.TryEnterWriteLock(_writeLockTimeout) is false)
{
throw new TimeoutException("Timeout exceeded to the memory cache when clearing with prefix");
}
_locker.EnterWriteLock();
// ToArray required to remove
foreach (var key in MemoryCache
@@ -385,10 +365,7 @@ public class ObjectCacheAppCache : IAppPolicyCache, IDisposable
try
{
if (_locker.TryEnterWriteLock(_writeLockTimeout) is false)
{
throw new TimeoutException("Timeout exceeded to the memory cach when clearing by regex");
}
_locker.EnterWriteLock();
// ToArray required to remove
foreach (var key in MemoryCache
@@ -3,26 +3,30 @@ using System.Collections;
namespace Umbraco.Cms.Core.Composing;
/// <summary>
/// Provides a base class for builder collections.
/// Provides a base class for builder collections.
/// </summary>
/// <typeparam name="TItem">The type of the items.</typeparam>
public abstract class BuilderCollectionBase<TItem> : IBuilderCollection<TItem>
{
private readonly LazyReadOnlyCollection<TItem> _items;
/// <summary>
/// Initializes a new instance of the <see cref="BuilderCollectionBase{TItem}" /> with items.
/// Initializes a new instance of the
/// <see cref="BuilderCollectionBase{TItem}" />
/// with items.
/// </summary>
/// <param name="items">The items.</param>
public BuilderCollectionBase(Func<IEnumerable<TItem>> items)
=> _items = new LazyReadOnlyCollection<TItem>(items);
public BuilderCollectionBase(Func<IEnumerable<TItem>> items) => _items = new LazyReadOnlyCollection<TItem>(items);
/// <inheritdoc />
public int Count => _items.Count;
/// <inheritdoc />
/// <summary>
/// Gets an enumerator.
/// </summary>
public IEnumerator<TItem> GetEnumerator() => _items.GetEnumerator();
/// <inheritdoc />
/// <summary>
/// Gets an enumerator.
/// </summary>
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
@@ -1,16 +1,13 @@
namespace Umbraco.Cms.Core.Composing;
/// <summary>
/// Represents a builder collection, ie an immutable enumeration of items.
/// Represents a builder collection, ie an immutable enumeration of items.
/// </summary>
/// <typeparam name="TItem">The type of the items.</typeparam>
public interface IBuilderCollection<out TItem> : IEnumerable<TItem>
{
/// <summary>
/// Gets the number of items in the collection.
/// Gets the number of items in the collection.
/// </summary>
/// <value>
/// The count.
/// </value>
int Count { get; }
}
+1 -10
View File
@@ -21,7 +21,7 @@ public class TypeFinder : ITypeFinder
/// its an exact name match
/// NOTE this means that "foo." will NOT exclude "foo.dll" but only "foo.*.dll"
/// </remarks>
internal static string[] KnownAssemblyExclusionFilter =
internal static readonly string[] KnownAssemblyExclusionFilter =
{
"mscorlib,", "netstandard,", "System,", "Antlr3.", "AutoMapper,", "AutoMapper.", "Autofac,", // DI
"Autofac.", "AzureDirectory,", "Castle.", // DI, tests
@@ -49,20 +49,11 @@ public class TypeFinder : ITypeFinder
private string[]? _assembliesAcceptingLoadExceptions;
private volatile HashSet<Assembly>? _localFilteredAssemblyCache;
[Obsolete("Please use the constructor taking all parameters. This constructor will be removed in V14.")]
public TypeFinder(ILogger<TypeFinder> logger, IAssemblyProvider assemblyProvider, ITypeFinderConfig? typeFinderConfig = null)
: this(logger, assemblyProvider, null, typeFinderConfig)
{ }
public TypeFinder(ILogger<TypeFinder> logger, IAssemblyProvider assemblyProvider, string[]? additionalExlusionAssemblies, ITypeFinderConfig? typeFinderConfig = null)
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_assemblyProvider = assemblyProvider;
_typeFinderConfig = typeFinderConfig;
if (additionalExlusionAssemblies is not null)
{
KnownAssemblyExclusionFilter = KnownAssemblyExclusionFilter.Union(additionalExlusionAssemblies).ToArray();
}
}
/// <inheritdoc />
@@ -262,9 +262,4 @@ public class ContentSettings
/// </summary>
[DefaultValue(StaticDisallowedUploadFiles)]
public string[] DisallowedUploadedFileExtensions { get; set; } = StaticDisallowedUploadFiles.Split(',');
/// <summary>
/// Gets or sets the allowed external host for media. If empty only relative paths are allowed.
/// </summary>
public string[] AllowedMediaHosts { get; set; } = Array.Empty<string>();
}
@@ -1,18 +0,0 @@
using System.ComponentModel;
namespace Umbraco.Cms.Core.Configuration.Models;
/// <summary>
/// Typed configuration options for index creator settings.
/// </summary>
[UmbracoOptions(Constants.Configuration.ConfigIndexing)]
public class IndexingSettings
{
private const bool StaticExplicitlyIndexEachNestedProperty = true;
/// <summary>
/// Gets or sets a value for whether each nested property should have it's own indexed value. Requires a rebuild of indexes when changed.
/// </summary>
[DefaultValue(StaticExplicitlyIndexEachNestedProperty)]
public bool ExplicitlyIndexEachNestedProperty { get; set; } = StaticExplicitlyIndexEachNestedProperty;
}
@@ -14,7 +14,6 @@ public class NuCacheSettings
internal const string StaticNuCacheSerializerType = "MessagePack";
internal const int StaticSqlPageSize = 1000;
internal const int StaticKitBatchSize = 1;
internal const bool StaticUsePagedSqlQuery = true;
/// <summary>
/// Gets or sets a value defining the BTree block size.
@@ -41,7 +40,4 @@ public class NuCacheSettings
public int KitBatchSize { get; set; } = StaticKitBatchSize;
public bool UnPublishedContentCompression { get; set; } = false;
[DefaultValue(StaticUsePagedSqlQuery)]
public bool UsePagedSqlQuery { get; set; } = true;
}
@@ -116,18 +116,18 @@ public class RichTextEditorSettings
new Dictionary<string, string> { ["entity_encoding"] = "raw" };
/// <summary>
/// HTML RichText Editor TinyMCE Commands.
/// HTML RichText Editor TinyMCE Commands
/// </summary>
/// WB-TODO Custom Array of objects
public RichTextEditorCommand[] Commands { get; set; } = Default_commands;
/// <summary>
/// HTML RichText Editor TinyMCE Plugins.
/// HTML RichText Editor TinyMCE Plugins
/// </summary>
public string[] Plugins { get; set; } = Default_plugins;
/// <summary>
/// HTML RichText Editor TinyMCE Custom Config.
/// HTML RichText Editor TinyMCE Custom Config
/// </summary>
/// WB-TODO Custom Dictionary
public IDictionary<string, string> CustomConfig { get; set; } = Default_custom_config;
@@ -138,7 +138,7 @@ public class RichTextEditorSettings
public string ValidElements { get; set; } = StaticValidElements;
/// <summary>
/// Invalid HTML elements for RichText Editor.
/// Invalid HTML elements for RichText Editor
/// </summary>
[DefaultValue(StaticInvalidElements)]
public string InvalidElements { get; set; } = StaticInvalidElements;
@@ -2,7 +2,6 @@
// See LICENSE for more details.
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
namespace Umbraco.Cms.Core.Configuration.Models;
@@ -23,11 +22,6 @@ public class SecuritySettings
internal const string StaticAllowedUserNameCharacters =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+\\";
internal const int StaticMemberDefaultLockoutTimeInMinutes = 30 * 24 * 60;
internal const int StaticUserDefaultLockoutTimeInMinutes = 30 * 24 * 60;
private const long StaticUserDefaultFailedLoginDurationInMilliseconds = 1000;
private const long StaticUserMinimumFailedLoginDurationInMilliseconds = 250;
/// <summary>
/// Gets or sets a value indicating whether to keep the user logged in.
/// </summary>
@@ -71,14 +65,12 @@ public class SecuritySettings
/// <summary>
/// Gets or sets a value for the user password settings.
/// </summary>
[Obsolete("This no longer works. You can now inject this by using IOptions<UserPasswordConfigurationSettings> instead, scheduled for removal in v13")]
public UserPasswordConfigurationSettings? UserPassword { get; set; } = new();
public UserPasswordConfigurationSettings? UserPassword { get; set; }
/// <summary>
/// Gets or sets a value for the member password settings.
/// </summary>
[Obsolete("This no longer works. You can now inject this by using IOptions<MemberPasswordConfigurationSettings> instead, scheduled for removal in v13")]
public MemberPasswordConfigurationSettings? MemberPassword { get; set; } = new();
public MemberPasswordConfigurationSettings? MemberPassword { get; set; }
/// <summary>
/// Gets or sets a value indicating whether to bypass the two factor requirement in Umbraco when using external login
@@ -94,44 +86,10 @@ public class SecuritySettings
[DefaultValue(StaticUserBypassTwoFactorForExternalLogins)]
public bool UserBypassTwoFactorForExternalLogins { get; set; } = StaticUserBypassTwoFactorForExternalLogins;
/// <summary>
/// Gets or sets a value for how long (in minutes) a member is locked out when a lockout occurs.
/// </summary>
[DefaultValue(StaticMemberDefaultLockoutTimeInMinutes)]
public int MemberDefaultLockoutTimeInMinutes { get; set; } = StaticMemberDefaultLockoutTimeInMinutes;
/// <summary>
/// Gets or sets a value for how long (in minutes) a user is locked out when a lockout occurs.
/// </summary>
[DefaultValue(StaticUserDefaultLockoutTimeInMinutes)]
public int UserDefaultLockoutTimeInMinutes { get; set; } = StaticUserDefaultLockoutTimeInMinutes;
/// <summary>
/// Gets or sets a value indicating whether to allow editing invariant properties from a non-default language variation.
/// </summary>
[Obsolete("Use ContentSettings.AllowEditFromInvariant instead")]
[DefaultValue(StaticAllowEditInvariantFromNonDefault)]
public bool AllowEditInvariantFromNonDefault { get; set; } = StaticAllowEditInvariantFromNonDefault;
/// <summary>
/// Gets or sets the default duration (in milliseconds) of failed login attempts.
/// </summary>
/// <value>
/// The default duration (in milliseconds) of failed login attempts.
/// </value>
/// <remarks>
/// The user login endpoint ensures that failed login attempts take at least as long as the average successful login.
/// However, if no successful logins have occurred, this value is used as the default duration.
/// </remarks>
[DefaultValue(StaticUserDefaultFailedLoginDurationInMilliseconds)]
public long UserDefaultFailedLoginDurationInMilliseconds { get; set; } = StaticUserDefaultFailedLoginDurationInMilliseconds;
/// <summary>
/// Gets or sets the minimum duration (in milliseconds) of failed login attempts.
/// </summary>
/// <value>
/// The minimum duration (in milliseconds) of failed login attempts.
/// </value>
[DefaultValue(StaticUserMinimumFailedLoginDurationInMilliseconds)]
public long UserMinimumFailedLoginDurationInMilliseconds { get; set; } = StaticUserMinimumFailedLoginDurationInMilliseconds;
}
@@ -22,9 +22,4 @@ public class TypeFinderSettings
/// scanning for plugins based on different root referenced assemblies you can add the assembly name to this list.
/// </summary>
public IEnumerable<string>? AdditionalEntryAssemblies { get; set; }
/// <summary>
/// Gets or sets a value for the assemblies that will be excluded from scanning.
/// </summary>
public string[] AdditionalAssemblyExclusionEntries { get; set; } = Array.Empty<string>();
}
@@ -19,7 +19,7 @@ public class UmbracoPluginSettings
".css", // styles
".js", // scripts
".jpg", ".jpeg", ".gif", ".png", ".svg", // images
".eot", ".ttf", ".woff", ".woff2", // fonts
".eot", ".ttf", ".woff", // fonts
".xml", ".json", ".config", // configurations
".lic", // license
".map", // js map files
@@ -38,7 +38,6 @@ public static partial class Constants
public const string ConfigHosting = ConfigPrefix + "Hosting";
public const string ConfigImaging = ConfigPrefix + "Imaging";
public const string ConfigExamine = ConfigPrefix + "Examine";
public const string ConfigIndexing = ConfigPrefix + "Indexing";
public const string ConfigKeepAlive = ConfigPrefix + "KeepAlive";
public const string ConfigLogging = ConfigPrefix + "Logging";
public const string ConfigMemberPassword = ConfigPrefix + "Security:MemberPassword";
@@ -10,7 +10,6 @@ public static partial class Constants
public const string GetVersion = "Umbraco.Core.VersionableRepository.GetVersion";
public const string GetVersions = "Umbraco.Core.VersionableRepository.GetVersions";
public const string EnsureUniqueNodeName = "Umbraco.Core.VersionableRepository.EnsureUniqueNodeName";
public const string SortOrderExists = "Umbraco.Core.VersionableRepository.SortOrderExists";
public const string GetSortOrder = "Umbraco.Core.VersionableRepository.GetSortOrder";
public const string GetParentNode = "Umbraco.Core.VersionableRepository.GetParentNode";
public const string GetReservedId = "Umbraco.Core.VersionableRepository.GetReservedId";
-1
View File
@@ -28,6 +28,5 @@ public static partial class Constants
public static string IsDebug = "IsDebug";
public static string DatabaseProvider = "DatabaseProvider";
public static string CurrentServerRole = "CurrentServerRole";
public static string BackofficeExternalLoginProviderCount = "BackofficeExternalLoginProviderCount";
}
}
@@ -50,7 +50,6 @@ public static partial class UmbracoBuilderExtensions
builder
.AddUmbracoOptions<ModelsBuilderSettings>()
.AddUmbracoOptions<ActiveDirectorySettings>()
.AddUmbracoOptions<IndexCreatorSettings>()
.AddUmbracoOptions<MarketplaceSettings>()
.AddUmbracoOptions<ContentSettings>()
.AddUmbracoOptions<CoreDebugSettings>()
@@ -65,7 +64,7 @@ public static partial class UmbracoBuilderExtensions
.AddUmbracoOptions<HealthChecksSettings>()
.AddUmbracoOptions<HostingSettings>()
.AddUmbracoOptions<ImagingSettings>()
.AddUmbracoOptions<IndexingSettings>()
.AddUmbracoOptions<IndexCreatorSettings>()
.AddUmbracoOptions<KeepAliveSettings>()
.AddUmbracoOptions<LoggingSettings>()
.AddUmbracoOptions<MemberPasswordConfigurationSettings>()
@@ -318,9 +318,8 @@ namespace Umbraco.Cms.Core.DependencyInjection
Services.AddSingleton<ConflictingPackageData>();
Services.AddSingleton<CompiledPackageXmlParser>();
// Register a noop IHtmlSanitizer & IMarkdownSanitizer to be replaced
// Register a noop IHtmlSanitizer to be replaced
Services.AddUnique<IHtmlSanitizer, NoopHtmlSanitizer>();
Services.AddUnique<IMarkdownSanitizer, NoopMarkdownSanitizer>();
Services.AddUnique<IPropertyTypeUsageService, PropertyTypeUsageService>();
Services.AddUnique<IDataTypeUsageService, DataTypeUsageService>();
@@ -328,9 +327,6 @@ namespace Umbraco.Cms.Core.DependencyInjection
Services.AddUnique<ICultureImpactFactory>(provider => new CultureImpactFactory(provider.GetRequiredService<IOptionsMonitor<ContentSettings>>()));
Services.AddUnique<IDictionaryService, DictionaryService>();
Services.AddUnique<ITemporaryMediaService, TemporaryMediaService>();
// Register filestream security analyzers
Services.AddUnique<IFileStreamSecurityValidator,FileStreamSecurityValidator>();
}
}
}
File diff suppressed because it is too large Load Diff
@@ -1754,8 +1754,9 @@
<key alias="usergroup">Uživatelská skupina</key>
<key alias="userInvited">byl pozván</key>
<key alias="userInvitedSuccessHelp">Novému uživateli byla zaslána pozvánka s informacemi, jak se přihlásit do Umbraco.</key>
<key alias="userinviteWelcomeMessage">Dobrý den, vítejte v Umbraco! Za pouhou 1 minutu budete moci používat Umbraco. Jenom od vás potřebujeme, abyste si nastavili heslo.</key>
<key alias="userinviteWelcomeMessage">Dobrý den, vítejte v Umbraco! Za pouhou 1 minutu budete moci používat Umbraco. Jenom od vás potřebujeme, abyste si nastavili heslo a přidali obrázek pro svůj avatar.</key>
<key alias="userinviteExpiredMessage">Vítejte v Umbraco! Vaše pozvánka bohužel vypršela. Obraťte se na svého správce a požádejte jej, aby jí znovu odeslal.</key>
<key alias="userinviteAvatarMessage">Nahrání vaší fotografie usnadní ostatním uživatelům, aby vás poznali. Kliknutím na kruh výše nahrajte svou fotku.</key>
<key alias="writer">Spisovatel</key>
<key alias="change">Změnit</key>
<key alias="yourProfile" version="7.0">Váš profil</key>
@@ -1868,8 +1869,8 @@
<key alias="stateInactive">Neaktivní</key>
<key alias="sortNameAscending">Jméno (A-Z)</key>
<key alias="sortNameDescending">Jméno (Z-A)</key>
<key alias="sortCreateDateAscending">Nejstarší</key>
<key alias="sortCreateDateDescending">Nejnovější</key>
<key alias="sortCreateDateAscending">Nejnovější</key>
<key alias="sortCreateDateDescending">Nejstarší</key>
<key alias="sortLastLoginDateDescending">Poslední přihlášení</key>
<key alias="noUserGroupsAdded">Nebyly přidány žádné skupiny uživatelů</key>
</area>
@@ -576,7 +576,7 @@
<area alias="dictionary">
<key alias="noItems">Nid oes unrhyw eitemau geiriadur.</key>
<key alias="importDictionaryItemHelp">
I fewnforio eitem geiriadur, dewch o hyd i'r ffeil ".udt" ar eich cyfrifiadur trwy glicio
I fewnforio eitem geiriadur, dewch o hyd i'r ffeil ".udt" ar eich cyfrifiadur trwy glicio
ar y botwm "Mewnforio" (bydd gofyn i chi am gadarnhad ar y sgrin nesaf)
</key>
<key alias="itemDoesNotExists">Nid yw eitem geiriadur yn bodoli.</key>
@@ -2308,8 +2308,9 @@ Er mwyn gweinyddu eich gwefan, agorwch swyddfa gefn Umbraco a dechreuwch ychwang
<key alias="userGroups">Grwpiau defnyddiwr</key>
<key alias="userInvited">wedi'i wahodd</key>
<key alias="userInvitedSuccessHelp">Mae gwahoddiad wedi cael ei anfon at y defnyddiwr newydd gyda manylion ar sut i fewngofnodi i Umbraco.</key>
<key alias="userinviteWelcomeMessage">Helo a chroeso i Umbraco! Mewn 1 munud yn unig, byddech chi'n barod i fynd, rydym dim ond angen gosod cyfrinair.</key>
<key alias="userinviteWelcomeMessage">Helo a chroeso i Umbraco! Mewn 1 munud yn unig, byddech chi'n barod i fynd, rydym dim ond angen gosod cyfrinair a llun ar gyfer eich avatar.</key>
<key alias="userinviteExpiredMessage">Croeso i Umbraco! Yn anffodus, mae eich gwahoddiad wedi terfynu. Cysylltwch â'ch gweinyddwr a gofynnwch iddynt ail-anfon.</key>
<key alias="userinviteAvatarMessage">Lanlwythwch lun i wneud o'n haws i boble eich adnabod chi.</key>
<key alias="writer">Ysgrifennydd</key>
<key alias="translator">Cyfieithydd</key>
<key alias="change">Newid</key>
+15 -15
View File
@@ -54,8 +54,8 @@
<key alias="setPermissions">Sæt rettigheder</key>
<key alias="unlock">Lås op</key>
<key alias="createblueprint">Opret indholdsskabelon</key>
<key alias="resendInvite">Gensend invitation</key>
<key alias="defaultValue">Standardværdi</key>
<key alias="resendInvite">Gensend Invitation</key>
<key alias="defaultValue">Standard værdi</key>
</area>
<area alias="actionCategories">
<key alias="content">Indhold</key>
@@ -342,7 +342,6 @@
<key alias="createNewMember">Opret et nyt medlem</key>
<key alias="allMembers">Alle medlemmer</key>
<key alias="memberGroupNoProperties">Medlemgrupper har ingen yderligere egenskaber til redigering.</key>
<key alias="2fa">Totrinsbekræftelse</key>
</area>
<area alias="contentType">
<key alias="copyFailed">Kopiering af indholdstypen fejlede</key>
@@ -717,7 +716,6 @@
<key alias="by">af</key>
<key alias="cancel">Fortryd</key>
<key alias="cellMargin">Celle margen</key>
<key alias="change">Skift</key>
<key alias="choose">Vælg</key>
<key alias="clear">Ryd</key>
<key alias="close">Luk</key>
@@ -1895,13 +1893,15 @@ Mange hilsner fra Umbraco robotten
logger ind i Umbraco.
</key>
<key alias="userinviteWelcomeMessage">Hej og velkommen til Umbraco! På bare 1 minut vil du være klar til at komme i
gang, vi skal bare have dig til at oprette en adgangskode.
gang, vi skal bare have dig til at oprette en adgangskode og tilføje et billede til din avatar.
</key>
<key alias="userinviteExpiredMessage">Velkommen til Umbraco! Desværre er din invitation udløbet. Kontakt din
administrator og bed om at gensende invitationen.
</key>
<key alias="userinviteAvatarMessage">Hvis du uploader et billede af dig selv, gør du det nemt for andre brugere at
genkende dig. Klik på cirklen ovenfor for at uploade et billede.
</key>
<key alias="writer">Forfatter</key>
<key alias="configureTwoFactor">Konfigurer totrinsbekræftelse</key>
<key alias="change">Skift</key>
<key alias="yourProfile">Din profil</key>
<key alias="yourHistory">Din historik</key>
@@ -1925,15 +1925,15 @@ Mange hilsner fra Umbraco robotten
<key alias="stateInactive">Inaktiv</key>
<key alias="sortNameAscending">Navn (A-Å)</key>
<key alias="sortNameDescending">Navn (Å-A)</key>
<key alias="sortCreateDateAscending">Ældste</key>
<key alias="sortCreateDateDescending">Nyeste</key>
<key alias="sortCreateDateAscending">Nyeste</key>
<key alias="sortCreateDateDescending">Ældste</key>
<key alias="sortLastLoginDateDescending">Sidst logget ind</key>
<key alias="noUserGroupsAdded">Ingen brugere er blevet tilføjet</key>
<key alias="2faDisableText">Hvis du ønsker at slå denne totrinsbekræftelse fra, så skal du nu indtaste koden fra din enhed:</key>
<key alias="2faProviderIsEnabled">Denne totrinsbekræftelse er slået til</key>
<key alias="2faProviderIsDisabledMsg">Den valgte totrinsbekræftelse er nu slået fra</key>
<key alias="2faProviderIsNotDisabledMsg">Der skete en ukendt fejl da denne totrinsbekræftelse skulles slåes fra</key>
<key alias="2faDisableForUser">Er du sikker på, at du vil fjerne denne totrinsbekræftelse for denne bruger?</key>
<key alias="2faDisableText">Hvis du ønsker at slå denne autentificeringsmetode fra, så skal du nu indtaste koden fra dit device:</key>
<key alias="2faProviderIsEnabled">Denne autentificeringsmetode er slået til</key>
<key alias="2faProviderIsDisabledMsg">Den valgte autentificeringsmetode er nu slået fra</key>
<key alias="2faProviderIsNotDisabledMsg">Der skete en ukendt fejl da denne autentificeringsmetode skulles slåes fra</key>
<key alias="2faDisableForUser">Er du sikker på, at du vil fjerne denne autentificeringsmetode for denne bruger?</key>
</area>
<area alias="validation">
<key alias="validation">Validering</key>
@@ -2230,7 +2230,7 @@ Mange hilsner fra Umbraco robotten
<key alias="allowedBlockColumnsHelp">Vælg de forskellige antal kolonner denne blok må optage i layoutet. Dette forhindre ikke blokken i at optræde i et mindre område.</key>
<key alias="allowedBlockRows">TIlgængelige række-størrelser</key>
<key alias="allowedBlockRowsHelp">Vælg hvor mange rækker denne blok på optage i layoutet.</key>
<key alias="allowBlockInRoot">Tillad på rodniveau</key>
<key alias="allowBlockInRoot">Tillad på rodniveay</key>
<key alias="allowBlockInRootHelp">Gør denne blok tilgængelig i layoutets rodniveau. Hvis dette ikke er valgt, kan denne blok kun bruges inden for andre blokkes definerede områder.</key>
<key alias="areas">Blok-områder</key>
<key alias="areasLayoutColumns">Layout-kolonner</key>
@@ -2238,7 +2238,7 @@ Mange hilsner fra Umbraco robotten
<key alias="areasConfigurations">Opsætning af områder</key>
<key alias="areasConfigurationsHelp">Hvis det skal være muligt at indsætte nye blokke indeni denne blok, skal der oprettes ét eller flere områder til at indsætte de nye blokke i.</key>
<key alias="invalidDropPosition">Ikke tilladt placering.</key>
<key alias="defaultLayoutStylesheet">Standardlayout stylesheet</key>
<key alias="defaultLayoutStylesheet">Standart layout stylesheet</key>
<key alias="confirmPasteDisallowedNestedBlockHeadline">Ikke tilladt indhold blev afvist</key>
<key alias="confirmPasteDisallowedNestedBlockMessage">
<![CDATA[Det indsatte indhold bestod af ikke tilladt del-indhold, disse dele er blevet afvist. Vil du beholde det resterene alligevel?]]></key>
+65 -332
View File
@@ -93,7 +93,6 @@
<area alias="assignDomain">
<key alias="permissionDenied">Erlaubnis verweigert.</key>
<key alias="addNew">Neue Domain hinzufügen</key>
<key alias="addCurrent">Aktuelle Domain hinzufügen</key>
<key alias="remove">entfernen</key>
<key alias="invalidNode">Ungültiges Element.</key>
<key alias="invalidDomain">Format der Domain ungültig.</key>
@@ -110,8 +109,7 @@
Außerdem werden Pfade mit erstem URL-Segment unterstützt z. B.: "example.com/en" or "/en".]]></key>
<key alias="inherit">Vererben</key>
<key alias="setLanguage">Kultur</key>
<key alias="setLanguageHelp">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.</key>
<key alias="setLanguageHelp">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.</key>
<key alias="setDomains">Domainen</key>
</area>
<area alias="buttons">
@@ -156,7 +154,6 @@
<key alias="deleteTag">TAG entfernen</key>
<key alias="confirmActionCancel">Abbrechen</key>
<key alias="confirmActionConfirm">Bestätigen</key>
<key alias="morePublishingOptions">Mehr Veröffentlichungs Optionen</key>
<key alias="submitChanges">Senden</key>
</area>
<area alias="auditTrails">
@@ -174,7 +171,6 @@
<key alias="sendtopublish">Veröffentlichung für Inhalt angefordert</key>
<key alias="sendtopublishvariant">Veröffentlichung für Inhalt angefordert in Sprache: %0%</key>
<key alias="sort">Unterknoten wurden sortiert von Benutzer</key>
<key alias="custom">%0%</key>
<key alias="contentversionpreventcleanup">Versionsbereinigung deaktiviert für Version: %0%</key>
<key alias="contentversionenablecleanup">Versionsbereinigung aktiviert für Version: %0%</key>
<key alias="smallCopy">Kopieren</key>
@@ -190,7 +186,6 @@
<key alias="smallSendToPublish">Veröffentlichung anfordern</key>
<key alias="smallSendToPublishVariant">Veröffentlichung anfordern</key>
<key alias="smallSort">Sortieren</key>
<key alias="smallCustom">Benutzerdefiniert</key>
<key alias="smallContentVersionPreventCleanup">Speichern</key>
<key alias="smallContentVersionEnableCleanup">Speichern</key>
<key alias="historyIncludingVariants">Verlauf (alle Variationen)</key>
@@ -232,12 +227,8 @@
<key alias="noMediaLink">Dieses Media-Element hat keinen Link</key>
<key alias="noProperties">Diesem Element kann kein Inhalt zugewiesen werden</key>
<key alias="otherElements">Eigenschaften</key>
<key alias="parentNotPublished">Dieses Dokument ist veröffentlicht aber nicht sichtbar,
da das übergeordnete Dokument '%0%' nicht publiziert ist
</key>
<key alias="parentCultureNotPublished">Diese Kultur wurde veröffentlicht, aber wird nicht angezeigt,
weil sie auf dem Oberknoten '%0%' unveröffentlicht ist
</key>
<key alias="parentNotPublished">Dieses Dokument ist veröffentlicht aber nicht sichtbar, da das übergeordnete Dokument '%0%' nicht publiziert ist</key>
<key alias="parentCultureNotPublished">Diese Kultur wurde veröffentlicht, aber wird nicht angezeigt, weil sie auf dem Oberknoten '%0%' unveröffentlicht ist</key>
<key alias="parentNotPublishedAnomaly">Ups! Dieses Dokument ist veröffentlicht aber nicht im internen Cache aufzufinden: Systemfehler.</key>
<key alias="getUrlException">Der URL wurde nicht gefunden</key>
<key alias="routeError">Dieses Dokument wurde veröffentlicht, aber sein URL würde mit Inhalt %0% kollidieren</key>
@@ -247,21 +238,24 @@
<key alias="publishedPendingChanges">Veröffentlicht (Änderungen bereit)</key>
<key alias="publishStatus">Publikationsstatus</key>
<key alias="publishDescendantsHelp">
<![CDATA[Wähle <em>Veröffentlichen mit Unterknoten</em> zum Veröffentlichen <strong>der gewählten Sprache</strong> samt aller Unterknoten der selben Sprache, um ihren Inhalt öffentlich verfügbar zu machen.]]></key>
<![CDATA[
Wähle <em>Veröffentlichen mit Unterknoten</em> zum Veröffentlichen <strong>der gewählten Sprache</strong>
samt aller Unterknoten der selben Sprache, um ihren Inhalt öffentlich verfügbar zu machen.]]>
</key>
<key alias="publishDescendantsWithVariantsHelp">
<![CDATA[Wähle <em>Veröffentlichen mit Unterknoten</em> zum Veröffentlichen <strong>der gewählten Sprache</strong> samt aller Unterknoten der selben Sprache, um ihren Inhalt öffentlich verfügbar zu machen.]]></key>
<![CDATA[
Wähle <em>Veröffentlichen mit Unterknoten</em> zum Veröffentlichen <strong>der gewählten Sprache</strong>
samt aller Unterknoten der selben Sprache, um ihren Inhalt öffentlich verfügbar zu machen.]]>
</key>
<key alias="releaseDate">Veröffentlichen am</key>
<key alias="unpublishDate">Veröffentlichung widerrufen am</key>
<key alias="removeDate">Datum entfernen</key>
<key alias="setDate">Datum wählen</key>
<key alias="sortDone">Sortierung abgeschlossen</key>
<key alias="sortHelp">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
</key>
<key alias="sortHelp">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</key>
<key alias="statistics">Statistiken</key>
<key alias="titleOptional">Titel (optional)</key>
<key alias="altTextOptional">Alternativtext (optional)</key>
<key alias="captionTextOptional">Beschriftung (optional)</key>
<key alias="type">Typ</key>
<key alias="unpublish">Veröffentlichung widerrufen</key>
<key alias="unpublished">Entwurf</key>
@@ -269,8 +263,6 @@
<key alias="updateDate">Zuletzt bearbeitet am</key>
<key alias="updateDateDesc" version="7.0">Letzter Änderungszeitpunkt des Dokuments</key>
<key alias="uploadClear">Datei entfernen</key>
<key alias="uploadClearImageContext">Klicke hier um das das Bild vom Medienelement zu entfernen.</key>
<key alias="uploadClearFileContext">Klicke hier um das das Bild vom Medienelement zu entfernen.</key>
<key alias="urls">Link zum Dokument</key>
<key alias="memberof">Mitglied der Gruppe(n)</key>
<key alias="notmemberof">Kein Mitglied der Gruppe(n)</key>
@@ -278,55 +270,29 @@
<key alias="target" version="7.0">Ziel</key>
<key alias="scheduledPublishServerTime">Dies führt zur folgenden Zeit auf dem Server:</key>
<key alias="scheduledPublishDocumentation">
<![CDATA[<a href="https://docs.umbraco.com/umbraco-cms/fundamentals/data/scheduled-publishing#timezones" target="_blank" rel="noopener">Was bedeutet dies?</a>]]></key>
<![CDATA[
<a href="https://docs.umbraco.com/umbraco-cms/fundamentals/data/scheduled-publishing#timezones" target="_blank" rel="noopener">Was bedeutet dies?</a>
]]>
</key>
<key alias="nestedContentDeleteItem">Wollen Sie dieses Element wirklich entfernen?</key>
<key alias="nestedContentDeleteAllItems">Sicher das Sie alle Elemente entfernen wollen?</key>
<key alias="nestedContentEditorNotSupported">Eigenschaft %0% verwendet Editor %1%,
welcher nicht von Nested Content unterstützt wird.
</key>
<key alias="nestedContentNoContentTypes">Keine Dokument-Typen für diese Eigenschaft konfiguriert.</key>
<key alias="nestedContentAddElementType">Elementtyp hinzufügen</key>
<key alias="nestedContentSelectElementTypeModalTitle">Elementtype auswählen</key>
<key alias="nestedContentGroupHelpText">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.
</key>
<key alias="nestedContentTemplateHelpTextPart1">Geben Sie eine Angular Anweisung an um den Namen für das jweilige Element
zu bestimmen. Verwende
</key>
<key alias="nestedContentTemplateHelpTextPart2">um den Index des Elements anzuzeigen.</key>
<key alias="nestedContentNoGroups">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.</key>
<key alias="nestedContentEditorNotSupported">Eigenschaft %0% verwendet Editor %1%, welcher nicht von Nested Content unterstützt wird.</key>
<key alias="nestedContentNoContentTypes">Es wurden keine Dokument-(Inhalts-)Typen für diese Eigenschaft definiert.</key>
<key alias="addTextBox">Füge ein weiteres Textfeld hinzu</key>
<key alias="removeTextBox">Entferne dieses Textfeld</key>
<key alias="contentRoot">Inhalt-Basis</key>
<key alias="includeUnpublished">Inklusive Entwürfen: veröffentliche auch unveröffentlichte Elemente.</key>
<key alias="isSensitiveValue">Dieser Wert ist verborgen.
Wenn Sie diesen Wert einsehen müssen, wenden Sie sich bitte an einen Administrator.
</key>
<key alias="isSensitiveValue">Dieser Wert ist verborgen. Wenn Sie diesen Wert einsehen müssen, wenden Sie sich bitte an einen Administrator.</key>
<key alias="isSensitiveValue_short">Dieser Wert ist verborgen.</key>
<key alias="languagesToPublish">Welche Sprache möchten Sie veröffentlichen?</key>
<key alias="languagesToSendForApproval">Welche Sprachen möchten Sie zur Freigabe schicken?</key>
<key alias="languagesToSchedule">Welche Sprachen möchten Sie zu einer bestimmten Zeit veröffentlichen?</key>
<key alias="languagesToUnpublish">Wählen Sie die Sprachen, deren Veröffentlichung zurück genommen werden soll.
Das Zurücknehmen der Veröffentlichung einer Pflichtsprache betrifft alle Sprachen.
</key>
<key alias="variantsWillBeSaved">Alle neuen Variationen werden gespeichert.</key>
<key alias="variantsToPublish">Welche Variationen wollen Sie veröffentlichen?</key>
<key alias="variantsToSave">Wählen Sie welche Variation gespeichert werden soll.</key>
<key alias="publishRequiresVariants">Folgende Variationen werden benötigt um das Element veröffentlichen zu können: </key>
<key alias="notReadyToPublish">Wir sind für Veröffentlichungen bereit</key>
<key alias="languagesToUnpublish">Wählen Sie die Sprachen, deren Veröffentlichung zurück genommen werden soll. Das Zurücknehmen der Veröffentlichung einer Pflichtsprache betrifft alle Sprachen.</key>
<key alias="readyToPublish">Bereit zu Veröffentlichen?</key>
<key alias="readyToSave">Bereit zu Sichern?</key>
<key alias="resetFocalPoint">Fokus zurücksetzten.</key>
<key alias="sendForApproval">Freigabe anfordern</key>
<key alias="schedulePublishHelp">Wählen Sie Datum und Uhrzeit für die Veröffentlichung bzw. deren Rücknahme.</key>
<key alias="createEmpty">Neues Element anlegen</key>
<key alias="createFromClipboard">Aus der Zwischenablage einfügen</key>
<key alias="nodeIsInTrash">Dieses Element befindet sich im Papierkorb.</key>
<key alias="variantSaveNotAllowed">Speichern ist nicht erlaubt.</key>
<key alias="variantPublishNotAllowed">Veröffentlichen ist nicht erlaubt.</key>
<key alias="variantSendForApprovalNotAllowed">Zur Genehmigung senden ist nicht erlaubt.</key>
<key alias="variantScheduleNotAllowed">Plannung ist nicht erlaubt</key>
<key alias="variantUnpublishNotAllowed">Veröffentlichung zurücknehmen ist nicht erlaubt.</key>
</area>
<area alias="blueprints">
<key alias="createBlueprintFrom"><![CDATA[Erzeuge eine neue Inhaltsvorlage von <em>%0%</em>]]></key>
@@ -335,46 +301,22 @@
<key alias="createdBlueprintHeading">Inhaltsvorlage erzeugt</key>
<key alias="createdBlueprintMessage">Inhaltsvorlage von '%0%' wurde erzeugt</key>
<key alias="duplicateBlueprintMessage">Eine gleichnamige Inhaltsvorlage ist bereits vorhanden</key>
<key alias="blueprintDescription">Eine Inhaltsvorlage ist vordefinierter Inhalt,
den ein Redakteur als Basis für neuen Inhalt verwenden kann
</key>
<key alias="blueprintDescription">Eine Inhaltsvorlage ist vordefinierter Inhalt, den ein Redakteur als Basis für neuen Inhalt verwenden kann</key>
</area>
<area alias="media">
<key alias="clickToUpload">Für Upload klicken</key>
<key alias="orClickHereToUpload">oder klicken Sie hier um eine Datei zu wählen</key>
<key alias="disallowedFileType">Dieser Dateityp darf nicht hochgeladen werden</key>
<key alias="invalidFileName">Diese Datei kann nicht hochgeladen werden wil der Dateiname ungültig ist.</key><key alias="disallowedMediaType">Diese Datei kann nicht hochgeladen werden, der Medienttype mit dem Alias '%0%' ist hier nicht erlaubt.</key>
<key alias="maxFileSize">Max. Dateigröße ist</key>
<key alias="mediaRoot">Media-Basis</key>
<key alias="moveToSameFolderFailed">Eltern- und Ziel-Verzeichnis dürfen nicht übereinstimmen</key>
<key alias="createFolderFailed">Unter Element Id %0% konnte kein Verzeichnis angelegt werden</key>
<key alias="renameFolderFailed">Das Verzeichnis mit Id %0% konnte nicht umbenannt werden</key>
<key alias="dragAndDropYourFilesIntoTheArea">Wählen Sie Dateien aus und ziehen Sie diese in diesen Bereich</key>
<key alias="uploadNotAllowed">Hochladen ist in diesem Bereich nicht erlaubt.</key>
</area>
<area alias="member">
<key alias="createNewMember">Neues Mitglied anlegen</key>
<key alias="allMembers">Alle Mitglieder</key>
<key alias="duplicateMemberLogin">Ein Mitglied mit diesem Login existiert bereits.</key>
<key alias="memberGroupNoProperties">Mitgliedsgruppen haben keine weiteren editierbaren Eigenschaften.</key>
<key alias="memberHasGroup">Das Mitglied ist bereits in der Gruppe '%0%'</key>
<key alias="memberHasPassword">Das Mitglied hat bereits ein Passwort</key>
<key alias="memberLockoutNotEnabled">Sperren ist nicht aktiviert für dieses Mitglied.</key>
<key alias="memberNotInGroup">Das Mitglied ist nicht in der Gruppe '%0%'</key>
<key alias="2fa">Zwei-Faktor-Authentifizierung</key>
</area>
<area alias="contentType">
<key alias="copyFailed">Kopieren des Dokumenttyps fehlgeschlagen</key>
<key alias="moveFailed">Bewegen des Dokumenttyps fehlgeschlagen</key>
</area>
<area alias="mediaType">
<key alias="copyFailed">Kopieren des Medienttyps fehlgeschlagen</key>
<key alias="moveFailed">Bewegen des Medienttyps fehlgeschlagen</key>
<key alias="autoPickMediaType">Automatische auswahl.</key>
</area>
<area alias="memberType">
<key alias="copyFailed">Kopieren des Mitgliedtyps fehlgeschlagen</key>
</area>
<area alias="create">
<key alias="chooseNode">An welcher Stellen wollen Sie das Element erstellen</key>
@@ -382,44 +324,13 @@
<key alias="createContentBlueprint">Wählen Sie einen Dokumenttyp für eine Inhaltsvorlage</key>
<key alias="enterFolderName">Geben Sie einen Verzeichnisnamen ein</key>
<key alias="updateData">Wählen Sie einen Namen und einen Typ</key>
<key alias="noDocumentTypes" version="7.0">
<![CDATA[Es stehen keine erlaubten Dokumenttypen zur Verfügung. Sie müssen diese in den Einstellungen (unter "Dokumenttypen") aktivieren.]]></key>
<key alias="noDocumentTypesAtRoot">
<![CDATA[Es stehen keine erlaubten Dokumenttypen zur Verfügung. Sie müssen diese in den Einstellungen (unter "Dokumenttypen") aktivieren.]]></key>
<key alias="noDocumentTypesWithNoSettingsAccess">Die im Inhaltsbaum ausgewählte Seite
erlaubt keine Unterseiten.
</key>
<key alias="noDocumentTypes" version="7.0"><![CDATA[Es stehen keine erlaubten Dokumenttypen zur Verfügung. Sie müssen diese in den Einstellungen (unter "Dokumenttypen") aktivieren.]]></key>
<key alias="noDocumentTypesWithNoSettingsAccess">Die im Inhaltsbaum ausgewählte Seite erlaubt keine Unterseiten.</key>
<key alias="noDocumentTypesEditPermissions">Bearbeitungsrechte für diesen Dokumenttyp</key>
<key alias="noDocumentTypesCreateNew">Neuen Dokumenttypen erstellen</key>
<key alias="noDocumentTypesAllowedAtRoot">
<![CDATA[Keine Dokumenttypen vorhanden welche hier eingefügt werden dürfen. Sie müssen diese in den Einstellungen (unter "Dokumenttypen") aktivieren.]]></key>
<key alias="noMediaTypes" version="7.0"><![CDATA[Es stehen keine erlaubten Medientypen zur Verfügung.
Sie müssen diese in den Einstellungen (unter "Medientypen") aktivieren.]]></key>
<key alias="noMediaTypesWithNoSettingsAccess">Das im Strukturbaum ausgewählte Medienelement
erlaubt keine untergeordneten Elemente.
</key>
<key alias="noMediaTypes" version="7.0"><![CDATA[Es stehen keine erlaubten Medientypen zur Verfügung. Sie müssen diese in den Einstellungen (unter "Medientypen") aktivieren.]]></key>
<key alias="noMediaTypesWithNoSettingsAccess">Das im Strukturbaum ausgewählte Medienelement erlaubt keine untergeordneten Elemente.</key>
<key alias="noMediaTypesEditPermissions">Bearbeitungsrechte für diesen Medientyp</key>
<key alias="documentTypeWithoutTemplate">Dokumenttyp ohne Vorlage</key>
<key alias="documentTypeWithTemplate">Dokumenttyp mit Template</key>
<key alias="documentTypeWithTemplateDescription">Die Definition für eine Inhaltsseite welche von einem
Redakteur im Inhaltsbaum angelgt werden können und direkt über die URL aufgerufen werden kann.
</key>
<key alias="documentType">Dokumenttype</key>
<key alias="documentTypeDescription">Die Definition für eine Inhaltsseite welche von einem
Redakteur im Inhaltsbaum angelgt werden können und direkt über die URL aufgerufen werden kann.
</key>
<key alias="elementType">Elementtyp</key>
<key alias="elementTypeDescription">Definiert die Vorlage für sich wiederholende Eigenschaften, zum Beispiel, in einer 'Block
List' oder im 'Nested Content' Editor.
</key>
<key alias="composition">Komposition</key>
<key alias="compositionDescription">Definiert eine wiederverwendbare Komposition von Eigenschaften welche in anderen
Dokumenttypen wiederverwendet werden können.
</key>
<key alias="folder">Ordner</key>
<key alias="folderDescription">Werden benützt um Dokumenttypen, Komposition und Elementtypen in diesem
Dokumenttypbaums zu organisieren.
</key>
<key alias="newFolder">Neues Verzeichnis</key>
<key alias="newDataType">Neuer Datentyp</key>
<key alias="newJavascriptFile">Neue JavaScript-Datei</key>
@@ -444,17 +355,11 @@
<key alias="stay">Bleiben</key>
<key alias="discardChanges">Änderungen verwerfen</key>
<key alias="unsavedChanges">Es gibt ungesicherte Änderungen</key>
<key alias="unsavedChangesWarning">Wollen Sie diese Seite wirklich verlassen?
- es gibt ungesicherte Änderungen
</key>
<key alias="unsavedChangesWarning">Wollen Sie diese Seite wirklich verlassen? - es gibt ungesicherte Änderungen</key>
<key alias="confirmListViewPublish">Veröffentlichen macht die ausgewählten Elemente auf der Website sichtbar.</key>
<key alias="confirmListViewUnpublish">Aufheben der Veröffentlichung entfernt die ausgewählten Elemente
und ihre Unterknoten von der Website.
</key>
<key alias="confirmListViewUnpublish">Aufheben der Veröffentlichung entfernt die ausgewählten Elemente und ihre Unterknoten von der Website.</key>
<key alias="confirmUnpublish">Aufheben der Veröffentlichung entfernt diese Seite und ihre Unterseiten von der Website.</key>
<key alias="doctypeChangeWarning">Es gibt ungesicherte Änderungen.
Ändern des Dokumenttyps macht diese rückgängig.
</key>
<key alias="doctypeChangeWarning">Es gibt ungesicherte Änderungen. Ändern des Dokumenttyps macht diese rückgängig.</key>
</area>
<area alias="bulk">
<key alias="done">Fertig</key>
@@ -486,16 +391,12 @@
<key alias="anchorInsert">Name</key>
<key alias="closeThisWindow">Fenster schließen</key>
<key alias="confirmdelete">Wollen Sie dies wirklich entfernen</key>
<key alias="confirmdeleteNumberOfItems"><![CDATA[Sicher das Sie <strong>%0%</strong> von <strong>%1%</strong> Elementen löschen wollen?]]></key>
<key alias="confirmdisable">Wollen Sie folgendes wirklich deaktivieren</key>
<key alias="confirmremove">Sicher das Sie es entfernen wollen?</key>
<key alias="confirmremoveusageof"><![CDATA[Sicher das Sie die Verwendung von <strong>%0%</strong> entfernen wollen?]]></key>
<key alias="confirmlogout">Sind Sie sich wirklich abmelden?</key>
<key alias="confirmSure">Sind Sie sicher?</key>
<key alias="cut">Ausschneiden</key>
<key alias="editdictionary">Wörterbucheintrag bearbeiten</key>
<key alias="editlanguage">Sprache bearbeiten</key>
<key alias="editSelectedMedia">Ausgewähltes Medien</key>
<key alias="insertAnchor">Anker einfügen</key>
<key alias="insertCharacter">Zeichen einfügen</key>
<key alias="insertgraphicheadline">Grafische Überschrift einfügen</key>
@@ -505,8 +406,7 @@
<key alias="inserttable">Tabelle einfügen</key>
<key alias="languagedeletewarning">Dies entfernt die Sprache</key>
<key alias="languageChangeWarning">
Die Kultur-Variante einer Sprache zu ändern ist möglicherweise eine aufwendige Operation und führt zum Erneuern von Inhalts-Zwischenspeicher und Such-Index.
</key>
Die Kultur-Variante einer Sprache zu ändern ist möglicherweise eine aufwendige Operation und führt zum Erneuern von Inhalts-Zwischenspeicher und Such-Index.</key>
<key alias="lastEdited">Zuletzt bearbeitet</key>
<key alias="link">Verknüpfung</key>
<key alias="linkinternal">Anker:</key>
@@ -518,25 +418,16 @@
<key alias="permissionsSet">Berechtigungen vergeben für</key>
<key alias="permissionsSetForGroup">Berechtigungen vergeben für %0% für Benutzer-Gruppe %1%</key>
<key alias="permissionsHelp">Wählen Sie die Benutzer-Gruppe, deren Berechtigungen Sie setzen möchten</key>
<key alias="recycleBinDeleting">Der Papierkorb wird geleert.
Bitte warten Sie und schließen Sie das Fenster erst, wenn der Vorgang abgeschlossen ist.
</key>
<key alias="recycleBinDeleting">Der Papierkorb wird geleert. Bitte warten Sie und schließen Sie das Fenster erst, wenn der Vorgang abgeschlossen ist.</key>
<key alias="recycleBinIsEmpty">Der Papierkorb ist leer</key>
<key alias="recycleBinWarning">Wenn Sie den Papierkorb leeren, werden die enthaltenen Elemente endgültig gelöscht. Dieser Vorgang kann nicht rückgängig gemacht werden.</key>
<key alias="regexSearchError">
Der Webservice von &lt;a target='_blank' rel='noopener' href='http://regexlib.com'&gt;regexlib.com&lt;/a&gt; ist zur Zeit nicht erreichbar. Bitte versuchen Sie es später erneut.</key>
<key alias="regexSearchHelp">
Finden Sie einen vorbereiteten regulären Ausdruck zur Validierung der Werte, die in dieses Feld eingegeben werden - zum Beispiel 'email, 'plz', 'URL' oder ähnlich.
</key>
<key alias="regexSearchError">Der Webservice von &lt;a target='_blank' rel='noopener' href='http://regexlib.com'&gt;regexlib.com&lt;/a&gt; ist zur Zeit nicht erreichbar. Bitte versuchen Sie es später erneut.</key>
<key alias="regexSearchHelp">Finden Sie einen vorbereiteten regulären Ausdruck zur Validierung der Werte, die in dieses Feld eingegeben werden - zum Beispiel 'email, 'plz', 'URL' oder ähnlich.</key>
<key alias="removeMacro">Macro entfernen</key>
<key alias="requiredField">Pflichtfeld</key>
<key alias="sitereindexed">Die Website-Index wurd neu erstellt</key>
<key alias="siterepublished">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.
</key>
<key alias="siterepublishHelp">Der Zwischenspeicher der Website wird aktualisiert und der veröffentlichte Inhalt auf den neuesten Stand gebracht.
Unveröffentlichte Inhalte bleiben dabei weiterhin unveröffentlicht.
</key>
<key alias="siterepublished">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.</key>
<key alias="siterepublishHelp">Der Zwischenspeicher der Website wird aktualisiert und der veröffentlichte Inhalt auf den neuesten Stand gebracht. Unveröffentlichte Inhalte bleiben dabei weiterhin unveröffentlicht.</key>
<key alias="tableColumns">Anzahl der Spalten</key>
<key alias="tableRows">Anzahl der Zeilen</key>
<key alias="thumbnailimageclickfororiginal">Für Originalgröße auf die Abbildung klicken</key>
@@ -550,7 +441,6 @@
<key alias="linkToMedia">Medien-Link</key>
<key alias="selectContentStartNode">Inhalts-Startknoten wählen</key>
<key alias="selectMedia">Medienelement wählen</key>
<key alias="selectMediaType">Medientype wählen</key>
<key alias="selectIcon">Bildzeichen wählen</key>
<key alias="selectItem">Element wählen</key>
<key alias="selectLink">Link wählen</key>
@@ -560,11 +450,8 @@
<key alias="selectMediaStartNode">Medien-Startknoten wählen</key>
<key alias="selectMember">Mitglied wählen</key>
<key alias="selectMemberGroup">Mitgliedergruppe wählen</key>
<key alias="selectMemberType">Membertype wählen</key>
<key alias="selectNode">Knoten wählen</key>
<key alias="selectSections">Bereich wählen</key>
<key alias="selectLanguages">Sprachen wählen</key>
<key alias="selectUser">Benutzer wählen</key>
<key alias="selectUsers">Benutzer wählen</key>
<key alias="noIconsFound">Keine Bildzeichen gefunden</key>
<key alias="noMacroParams">Für dieses Makro gibt es keine Parameter</key>
@@ -577,50 +464,42 @@
<key alias="unLinkYour">Trennen Sie Ihr</key>
<key alias="account">Konto</key>
<key alias="selectEditor">Editor wählen</key>
<key alias="selectEditorConfiguration">Konfiguration wählen</key>
<key alias="selectSnippet">Kode-Vorlage wählen</key>
<key alias="variantdeletewarning">Dies wird den Knoten und all seine Sprachen entfernen.
<key alias="variantdeletewarning">
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.
</key>
<key alias="propertyuserpickerremovewarning"><![CDATA[Dies entfernt den User <strong>%0%</strong>.]]></key>
<key alias="userremovewarning"><![CDATA[Dies entfernt den User <strong>%0%</strong> von der <strong>%1%</strong> Gruppe]]></key>
<key alias="yesRemove">Ja, entfernen</key>
<key alias="deleteLayout">Sie löschen das Layout</key>
<key alias="deletingALayout">Bearbeiten des layout resultiert im Verlust der aller Daten für bestehenden Inhalt basierend auf dieser Konfiruation.</key>
</area>
<area alias="dictionary">
<key alias="importDictionaryItemHelp">
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)
</key>
<key alias="itemDoesNotExists">Wörterbuch Eintrag existiert nicht.</key>
<key alias="parentDoesNotExists">Eltern Element existiert nicht.</key>
<key alias="noItems">Es gibt keine Einträge im Wörterbuch.</key>
<key alias="noItemsInFile">Keine Wörterbuch Einträge in dieser Datei gefunden.</key>
<key alias="noItemsFound">Keine Wörterbuch Einträge gefunden.</key>
<key alias="createNew">Eintrag erstellen</key>
</area>
<area alias="dictionaryItem">
<key alias="description"><![CDATA[
<key alias="description">
<![CDATA[
Bearbeiten Sie nachfolgend die verschiedenen Sprachversionen für den Wörterbucheintrag '<em>%0%</em>'.
<br/>Unter dem links angezeigten Menüpunkt 'Sprachen' können Sie weitere hinzufügen.]]></key>
<br/>Unter dem links angezeigten Menüpunkt 'Sprachen' können Sie weitere hinzufügen.
]]>
</key>
<key alias="displayName">Name der Kultur</key>
<key alias="changeKeyError"><![CDATA[
<key alias="changeKeyError">
<![CDATA[
Der Wert '%0%' ist bereits vorhanden.
]]></key>
]]>
</key>
<key alias="overviewTitle">Wörterbuch Übersicht</key>
</area>
<area alias="examineManagement">
<key alias="configuredSearchers"><![CDATA[<em>Sucher</em> einrichten ]]></key>
<key alias="configuredSearchersDescription">
<![CDATA[
Zeigt die Eigenschaften und Werkzeuge für eingerichtete <em>Sucher</em> (z.B.: multi-index searcher)]]></key>
Zeigt die Eigenschaften und Werkzeuge für eingerichtete <em>Sucher</em> (z.B.: multi-index searcher)
]]>
</key>
<key alias="fieldValues">Feldwerte</key>
<key alias="healthStatus">Gesundheitsstatus</key>
<key alias="healthStatusDescription">Der Gesundheitsstatus und Lesbarkeit des Indizes.</key>
<key alias="indexers">Indizierer</key>
<key alias="indexInfo">Indexinformationen</key>
<key alias="contentInIndex">Inhalt des Indexes</key>
<key alias="indexInfoDescription">Zeigt die Eigenschaften des Indizes</key>
<key alias="manageIndexes">Examine Index-Verwaltung</key>
<key alias="manageIndexesDescription">
@@ -632,18 +511,12 @@
Dies erzeugt den Index neu.<br />
Abhängig von der Inhaltsmenge Ihrer <em>Website</em> kann das eingie Zeit dauern.<br />
Es wird davon abgeraten, einen Index einer <em>Website</em> während hoher Auslastung- oder Inhaltbearbeitungszeiten zu erneuern.
]]></key>
]]>
</key>
<key alias="searchers">Sucher</key>
<key alias="searchDescription">Durchsuche den Index und betrachte die Ergebnisse</key>
<key alias="tools">Werkzeuge</key>
<key alias="toolsDescription">Werkzeuge zur Indexverwaltung</key>
<key alias="fields">Felder</key>
<key alias="indexCannotRead">Der Index kann nicht gelesen werden und wird deshalb neu erstellt.</key>
<key alias="processIsTakingLonger">Der Prozess dauert länger als erwartet, checken Sie die Umbraco Logs um zu sehen ob
Fehler passiert sind.
</key>
<key alias="indexCannotRebuild">Der Index kann nicht rebuilded werden weil er nicht zugewissen wurde.</key>
<key alias="iIndexPopulator">IIndexPopulator</key>
</area>
<area alias="placeholders">
<key alias="username">Benutzername eingeben</key>
@@ -664,9 +537,6 @@
<key alias="anchor">#value oder ?key=value</key>
<key alias="enterAlias">Bitte einen Alias eingeben...</key>
<key alias="generatingAlias">Alias erzeugen...</key>
<key alias="a11yCreateItem">Element erstellen</key>
<key alias="a11yEdit">Bearbeiten</key>
<key alias="a11yName">Benennen</key>
</area>
<area alias="editcontenttype">
<key alias="createListView" version="7.2">Angepasste Listenansicht erstellen</key>
@@ -679,7 +549,6 @@
<key alias="folderWasRenamed">%0% wurde umbenannt in %1%</key>
</area>
<area alias="editdatatype">
<key alias="canChangePropertyEditorHelp">Ä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.</key>
<key alias="addPrevalue">Neuer Vorgabewert</key>
<key alias="dataBaseDatatype">Feldtyp in der Datenbank</key>
<key alias="guid">Datentyp-GUID</key>
@@ -694,25 +563,14 @@
<key alias="selectFolder">Wählen Sie das Verzeichnis aus der untenstehenden Baumstruktur, in das</key>
<key alias="inTheTree">verschoben werden soll.</key>
<key alias="wasMoved">wurde verschoben in</key>
<key alias="hasReferencesDeleteConsequence">
<![CDATA[Löschen von <strong>%0%</strong> wird die Eigenschaften und Daten von folgenden Element löschen]]></key>
<key alias="acceptDeleteConsequence">Ich verstehe das diese Aktion Eigenschaften und Daten basierend auf diesem
DataTyps löschen wird.
</key>
</area>
<area alias="errorHandling">
<key alias="errorButDataWasSaved">Ihre Daten wurden gespeichert.
Bevor Sie diese Seite jedoch veröffentlichen können, müssen Sie die folgenden Korrekturen vornehmen:
</key>
<key alias="errorChangingProviderPassword">Der aktuelle Mitgliedschaftsanbieter erlaubt keine Kennwortänderung
(EnablePasswordRetrieval muss auf "true" gesetzt sein)
</key>
<key alias="errorButDataWasSaved">Ihre Daten wurden gespeichert. Bevor Sie diese Seite jedoch veröffentlichen können, müssen Sie die folgenden Korrekturen vornehmen:</key>
<key alias="errorChangingProviderPassword">Der aktuelle Mitgliedschaftsanbieter erlaubt keine Kennwortänderung (EnablePasswordRetrieval muss auf "true" gesetzt sein)</key>
<key alias="errorExistsWithoutTab">'%0%' ist bereits vorhanden</key>
<key alias="errorHeader">Bitte prüfen und korrigieren:</key>
<key alias="errorHeaderWithoutTab">Bitte prüfen und korrigieren:</key>
<key alias="errorInPasswordFormat">Für das Kennwort ist eine Mindestlänge von %0% Zeichen vorgesehen,
wovon mindestens %1% Sonderzeichen (nicht alphanumerisch) sein müssen
</key>
<key alias="errorInPasswordFormat">Für das Kennwort ist eine Mindestlänge von %0% Zeichen vorgesehen, wovon mindestens %1% Sonderzeichen (nicht alphanumerisch) sein müssen</key>
<key alias="errorIntegerWithoutTab">'%0%' muss eine Zahl sein</key>
<key alias="errorMandatory">'%0%' (in Registerkarte '%1%') ist ein Pflichtfeld</key>
<key alias="errorMandatoryWithoutTab">'%0%' ist ein Pflichtfeld</key>
@@ -720,27 +578,20 @@
<key alias="errorRegExpWithoutTab">'%0%' hat ein falsches Format</key>
</area>
<area alias="errors">
<key alias="defaultError">Ein unbekannter Fehler ist passiert.</key>
<key alias="concurrencyError">Optimistic concurrency Fehler, Objekte wurde geändert.</key>
<key alias="receivedErrorFromServer">Der Server hat einen Fehler gemeldet</key>
<key alias="dissallowedMediaType">Dieser Dateityp wird durch die Systemeinstellungen blockiert</key>
<key alias="codemirroriewarning">ACHTUNG! Obwohl CodeMirror in den Einstellungen aktiviert ist,
bleibt das Modul wegen mangelnder Stabilität in Internet Explorer deaktiviert.
</key>
<key alias="codemirroriewarning">ACHTUNG! Obwohl CodeMirror in den Einstellungen aktiviert ist, bleibt das Modul wegen mangelnder Stabilität in Internet Explorer deaktiviert.</key>
<key alias="contentTypeAliasAndNameNotNull">Bitte geben Sie die Bezeichnung und den Alias des neuen Dokumenttyps ein.</key>
<key alias="filePermissionsError">Es besteht ein Problem mit den Lese-/Schreibrechten auf eine Datei oder einen Ordner</key>
<key alias="macroErrorLoadingPartialView">Fehler beim Laden einer "Partial View Kodedatei" (Datei: %0%)</key>
<key alias="missingTitle">Bitte geben Sie einen Titel ein</key>
<key alias="missingType">Bitte wählen Sie einen Typ</key>
<key alias="pictureResizeBiggerThanOrg">Soll die Abbildung wirklich über die
Originalgröße hinaus vergrößert werden?
</key>
<key alias="pictureResizeBiggerThanOrg">Soll die Abbildung wirklich über die Originalgröße hinaus vergrößert werden?</key>
<key alias="startNodeDoesNotExists">Startelement gelöscht, bitte kontaktieren Sie den System-Administrator.</key>
<key alias="stylesMustMarkBeforeSelect">Bitte markieren Sie den gewünschten Text, bevor Sie einen Stil auswählen</key>
<key alias="stylesNoStylesOnPage">Keine aktiven Stile vorhanden</key>
<key alias="tableColMergeLeft">Bitte platzieren Sie den Mauszeiger in die erste der zusammenzuführenden Zellen</key>
<key alias="tableSplitNotSplittable">Sie können keine Zelle trennen, die nicht zuvor aus mehreren zusammengeführt wurde.</key>
<key alias="propertyHasErrors">Die Eigenschaft ist nicht valide</key>
</area>
<area alias="general">
<key alias="options">Optionen</key>
@@ -759,18 +610,16 @@
<key alias="cellMargin">Zellabstand</key>
<key alias="choose">Auswählen</key>
<key alias="close">Schließen</key>
<key alias="clear">Leeren</key>
<key alias="closewindow">Fenster schließen</key>
<key alias="closepane">Fenster Pane</key>
<key alias="comment">Kommentar</key>
<key alias="confirm">bestätigen</key>
<key alias="constrain">Beschneiden</key>
<!--???-->
<key alias="constrainProportions">Seitenverhältnis beibehalten</key>
<key alias="content">Inhalt</key>
<key alias="continue">Weiter</key>
<key alias="copy">Kopieren</key>
<key alias="create">Neu</key>
<key alias="cropSection">Ausschnitte Bereich</key>
<key alias="database">Datenbank</key>
<key alias="date">Datum</key>
<key alias="default">Standard</key>
@@ -780,7 +629,6 @@
<key alias="design">Design</key>
<key alias="dictionary">Wörterbuch</key>
<key alias="dimensions">Abmessungen</key>
<key alias="discard">Verwerfen</key>
<key alias="down">nach unten</key>
<key alias="download">Herunterladen</key>
<key alias="edit">Bearbeiten</key>
@@ -793,8 +641,6 @@
<key alias="first">Erste(s)</key>
<key alias="general">Allgemein</key>
<key alias="groups">Gruppen</key>
<key alias="groups">Gruppe</key>
<key alias="generic">Generisch</key>
<key alias="group">Gruppe</key>
<key alias="height">Höhe</key>
<key alias="help">Hilfe</key>
@@ -803,7 +649,6 @@
<key alias="icon">Bildzeichen</key>
<key alias="id">Id</key>
<key alias="import">Import</key>
<key alias="excludeFromSubFolders">Nur in diesem Ordner suchen</key>
<key alias="info">Info</key>
<key alias="innerMargin">Innerer Abstand</key>
<key alias="insert">Einfügen</key>
@@ -822,19 +667,18 @@
<key alias="logout">Abmelden</key>
<key alias="macro">Makro</key>
<key alias="mandatory">Pflichtfeld</key>
<key alias="media">Medien</key>
<key alias="message">Nachricht</key>
<key alias="move">Verschieben</key>
<key alias="name">Name</key>
<key alias="new">Neu</key>
<key alias="next">Weiter</key>
<key alias="no">Nein</key>
<key alias="nodeName">Knoten Name</key>
<key alias="of">von</key>
<key alias="off">Aus</key>
<key alias="ok">Ok</key>
<key alias="open">Öffnen</key>
<key alias="on">An</key>
<!--???-->
<key alias="or">oder</key>
<key alias="orderBy">Sortieren nach</key>
<key alias="password">Kennwort</key>
@@ -842,7 +686,6 @@
<key alias="pleasewait">Einen Moment bitte...</key>
<key alias="previous">Zurück</key>
<key alias="properties">Eigenschaften</key>
<key alias="readMore">Mehr erfahren</key>
<key alias="rebuild">Erneuern</key>
<key alias="reciept">E-Mail-Empfänger für die Formulardaten</key>
<key alias="recycleBin">Papierkorb</key>
@@ -850,7 +693,6 @@
<key alias="reload">Neu laden</key>
<key alias="remaining">Verbleibend</key>
<key alias="remove">Entfernen</key>
<key alias="revert">Rückgängig</key>
<key alias="rename">Umbenennen</key>
<key alias="renew">Erneuern</key>
<key alias="required" version="7.0">Pflichtangabe</key>
@@ -858,22 +700,18 @@
<key alias="retry">Wiederholen</key>
<key alias="rights">Berechtigungen</key>
<key alias="scheduledPublishing">Geplantes Veröffentlichen</key>
<key alias="umbracoInfo">Umbraco Information</key>
<key alias="search">Suchen</key>
<key alias="searchNoResult">Leider können wir nicht finden, wonach Sie suchen.</key>
<key alias="noItemsInList">Es wurden keine Elemente hinzugefügt</key>
<key alias="server">Server</key>
<key alias="settings">Einstellungen</key>
<key alias="shared">Geteilt</key>
<key alias="show">Anzeigen</key>
<key alias="showPageOnSend">Seite beim Senden anzeigen</key>
<key alias="size">Größe</key>
<key alias="sort">Sortieren</key>
<key alias="status">Status</key>
<key alias="submit">Senden</key>
<key alias="success">Erfolt</key>
<key alias="type">Typ</key>
<key alias="typeName">Typ Name</key>
<key alias="typeToSearch">Durchsuchen ...</key>
<key alias="under">unter</key>
<key alias="up">nach oben</key>
@@ -883,7 +721,6 @@
<key alias="url">URL</key>
<key alias="user">Benutzer</key>
<key alias="username">Benutzername</key>
<key alias="validate">Validieren</key>
<key alias="value">Wert</key>
<key alias="view">Ansicht</key>
<key alias="welcome">Willkommen ...</key>
@@ -896,24 +733,17 @@
<key alias="preview">Vorschau</key>
<key alias="changePassword">Kennwort ändern</key>
<key alias="to">nach</key>
<!--???-->
<key alias="listView">Listenansicht</key>
<key alias="saving">Sichern läuft...</key>
<key alias="current">Aktuelle(s)</key>
<key alias="embed">Eingebettet</key>
<key alias="selected">ausgewählt</key>
<key alias="other">Anderes</key>
<key alias="articles">Artikel</key>
<key alias="videos">Videos</key>
<key alias="avatar">Avatar für</key>
<key alias="header">Kopf</key>
<key alias="systemField">System Feld</key>
<key alias="lastUpdated">Zuletzt geändert</key>
</area>
<area alias="colors">
<key alias="blue">Blau</key>
</area>
<area alias="shortcuts">
<key alias="addTab">Tab hinzufügen</key>
<key alias="addGroup">Neue Gruppe</key>
<key alias="addProperty">Neue Eigenschaft</key>
<key alias="addEditor">Editor hinzufügen</key>
@@ -948,17 +778,14 @@
</area>
<area alias="installer">
<key alias="databaseErrorCannotConnect">Mit dieser Datenbank kann leider keine Verbindung hergestellt werden.</key>
<key alias="databaseErrorWebConfig">Appsettings.json Datei konnte nicht gespeichert werden. Bitte ändern Sie die Datei
manuell.
</key>
<key alias="databaseFound">Die Datenbank ist erreichbar und wurde identifiziert als</key>
<key alias="databaseHeader">Datenbank</key>
<key alias="databaseInstall">
<![CDATA[
Klicken Sie auf <strong>Installieren</strong>, um die Datenbank für Umbraco %0% einzurichten.
]]></key>
<key alias="databaseInstallDone">Die Datenbank wurde für Umbraco %0% konfiguriert.
Klicken Sie auf &lt;strong&gt;weiter&lt;/strong&gt;, um fortzufahren.</key>
]]>
</key>
<key alias="databaseInstallDone">Die Datenbank wurde für Umbraco %0% konfiguriert. Klicken Sie auf &lt;strong&gt;weiter&lt;/strong&gt;, um fortzufahren.</key>
<key alias="databaseText">Um diesen Schritt abzuschließen, müssen Sie die notwendigen Informationen zur Datenbankverbindung angeben.&lt;br /&gt;Bitte kontaktieren Sie Ihren Provider bzw. Server-Administrator für weitere Informationen.</key>
<key alias="databaseUpgrade">
<![CDATA[
@@ -1345,7 +1172,6 @@
Bitte deinstallieren Sie also mit Vorsicht. Falls Sie unsicher sind, kontaktieren Sie den Autor des Pakets.]]>
</key>
<key alias="packageVersion">Paketversion</key>
<key alias="verifiedToWorkOnUmbracoCloud">Bestätigt auf Umbraco Cloud zu funktioneren</key>
</area>
<area alias="paste">
<key alias="doNothing">Einfügen mit Formatierung (Nicht empfohlen)</key>
@@ -1430,22 +1256,6 @@
<key alias="pickedTrashedItem">Sie haben ein entferntes oder im Papierkorb befindliches Medienelement ausgewählt</key>
<key alias="pickedTrashedItems">Sie haben entfernte oder im Papierkorb befindliche medienelemente ausgewählt</key>
<key alias="trashed">Verworfen</key>
<key alias="openMedia">Medien öffnen</key>
<key alias="changeMedia">Medientyp ändern</key>
<key alias="editMediaEntryLabel">Ändere %0% auf %1%</key>
<key alias="confirmCancelMediaEntryCreationHeadline">Erstellen abbrechen?</key>
<key alias="confirmCancelMediaEntryCreationMessage"><![CDATA[Sind Sie sich sicher das Sie das Erstellen abbrechen wollen?]]></key>
<key alias="confirmCancelMediaEntryHasChanges">Sie haben Änderungen an diesem Inhalt vorgenommen. Sind Sie sich sicher das Sie
diese verwerfen wollen?
</key>
<key alias="confirmRemoveAllMediaEntryMessage">Alle Medien löschen?</key>
<key alias="tabClipboard">Clipboard</key>
<key alias="notAllowed">Nicht erlaubt</key>
<key alias="openMediaPicker">Medienpicker öffnen</key>
</area>
<area alias="propertyEditorPicker">
<key alias="title">Wählen Sie einen Editor</key>
<key alias="openPropertyEditorPicker">Editor auswählen</key>
</area>
<area alias="relatedlinks">
<key alias="enterExternal">Externen Link eingeben</key>
@@ -1460,24 +1270,15 @@
<key alias="reset">Zurücksetzen</key>
<key alias="updateEditCrop">Fertig</key>
<key alias="undoEditCrop">Rückgängig machen</key>
<key alias="customCrop">Benutzer definiert</key>
</area>
<area alias="rollback">
<key alias="changes">Änderungen</key>
<key alias="created">Erstellt</key>
<key alias="headline">Wählen Sie eine Version, um diese mit der aktuellen zu vergleichen</key>
<key alias="currentVersion">Aktuelle Version</key>
<key alias="diffHelp">Zeigt die Unterschiede zwischen der aktuellen und der ausgewählten Version an.&lt;br /&gt;Text in &lt;del&gt;rot&lt;/del&gt; fehlen in der ausgewählten Version, &lt;ins&gt;grün&lt;/ins&gt; markierter Text wurde hinzugefügt.</key>
<key alias="noDiff">Keine Unterschiede zwischen den beiden Versionen gefunden.</key>
<key alias="documentRolledBack">Dokument wurde zurückgesetzt</key>
<key alias="htmlHelp">Zeigt die ausgewählte Version als HTML an. Wenn Sie sich die Unterschiede zwischen zwei Versionen anzeigen lassen wollen, benutzen Sie bitte die Vergleichsansicht.</key>
<key alias="rollbackTo">Zurücksetzen auf</key>
<key alias="selectVersion">Version auswählen</key>
<key alias="view">Ansicht</key>
<key alias="pagination"><![CDATA[Zeige Versionen von %0% zu %1% von %2% Versionen]]></key>
<key alias="versions">Versionen</key>
<key alias="currentDraftVersion">Aktulle Bearbeitungs Version</key>
<key alias="currentPublishedVersion">Aktulle veröffentlichte Version</key>
</area>
<area alias="scripts">
<key alias="editscript">Skript bearbeiten</key>
@@ -1493,12 +1294,7 @@
<key alias="users">Benutzer</key>
</area>
<area alias="help">
<key alias="tours">Touren</key>
<key alias="theBestUmbracoVideoTutorials">Die besten Umbraco-Video-Tutorials</key>
<key alias="umbracoForum">Besuche our.umbraco.com</key>
<key alias="umbracoTv">Besuche umbraco.tv</key>
<key alias="umbracoLearningBase">Schaue gratis Tutorials</key>
<key alias="umbracoLearningBaseDescription">von Umbraco Learning Base</key>
</area>
<area alias="settings">
<key alias="defaulttemplate">Standardvorlage</key>
@@ -1843,12 +1639,6 @@
falls die angefragte Sprache nicht verfügbar ist, wählen Sie diese Option hier aus.
</key>
<key alias="fallbackLanguage">Ersatzsprache</key>
<key alias="none">Keine</key>
<key alias="invariantPropertyUnlockHelp"><![CDATA[<strong>%0%</strong> wird zwischen Sprachen und Segmenten geteilt.]]></key>
<key alias="invariantCulturePropertyUnlockHelp"><![CDATA[<strong>%0%</strong> wird zwischen allen Sprachen geteilt.]]></key>
<key alias="invariantSegmentPropertyUnlockHelp"><![CDATA[<strong>%0%</strong> wird zwischen allen Segmenten geteilt.]]></key>
<key alias="invariantLanguageProperty">Geteilt: Sprachen</key>
<key alias="invariantSegmentProperty">Geteilt: Segmente</key>
</area>
<area alias="macro">
<key alias="addParameter">Parameter hinzufügen</key>
@@ -1981,10 +1771,7 @@
<key alias="createDate">Benutzer angelegt</key>
<key alias="changePassword">Kennwort ändern</key>
<key alias="changePhoto">Foto ändern</key>
<key alias="emailRequired">Benötigt - geben Sie eine Email Adresse für diesen User an</key>
<key alias="newPassword">Neues Kennwort</key>
<key alias="newPasswordFormatLengthTip">Noch %0% Zeichen benötigt!</key>
<key alias="newPasswordFormatNonAlphaTip">Es sollten mindestens %0% Sonderzeichen verwendet werden.</key>
<key alias="noLockouts">wurde nicht ausgeschlossen</key>
<key alias="noPasswordChange">Das Kennwort wurde nicht geändert</key>
<key alias="confirmNewPassword">Neues Kennwort (Bestätigung)</key>
@@ -2059,8 +1846,9 @@
<key alias="usergroup">Benutzergruppe</key>
<key alias="userInvited">wurde eingeladen</key>
<key alias="userInvitedSuccessHelp">Eine Einladung mit Anweisungen zur Anmeldung im Umbraco-Back-Office wurde dem neuen Benutzer zugeschickt.</key>
<key alias="userinviteWelcomeMessage">Hallo und Willkommen bei Umbraco! In nur einer Minute sind Sie bereit loszulegen, Sie müssen nur ein Kennwort festlegen.</key>
<key alias="userinviteWelcomeMessage">Hallo und Willkommen bei Umbraco! In nur einer Minute sind Sie bereit loszulegen, Sie müssen nur ein Kennwort festlegen und optinal Ihrem Avatar ein Bild hinzufügen.</key>
<key alias="userinviteExpiredMessage">Willkommen bei Umbraco! Bedauerlicherweise ist Ihre Einladung verfallen. Bitte kontaktieren Sie Ihren Administrator und bitten Sie ihn, diese erneut zu schicken.</key>
<key alias="userinviteAvatarMessage">Laden Sie ein Foto von sich hoch, um es anderen Benutzern zu erleichtern, sie zu erkennen. Klicken Sie auf den Kreis oben, um Ihr Foto hochzuladen.</key>
<key alias="writer">Autor</key>
<key alias="change">Änderung</key>
<!--???-->
@@ -2178,8 +1966,8 @@
<key alias="stateInactive">Nicht aktiv</key>
<key alias="sortNameAscending">Name (A-Z)</key>
<key alias="sortNameDescending">Name (Z-A)</key>
<key alias="sortCreateDateAscending">Oldest</key>
<key alias="sortCreateDateDescending">Newest</key>
<key alias="sortCreateDateAscending">Newest</key>
<key alias="sortCreateDateDescending">Oldest</key>
<key alias="sortLastLoginDateDescending">Last login</key>
</area>
<area alias="validation">
@@ -2330,59 +2118,4 @@
<key alias="selectAllLogLevelFilters">Wählen Sie Alle</key>
<key alias="deselectAllLogLevelFilters">Alle abwählen</key>
</area>
<area alias="formsDashboard">
<key alias="formsHeadline">Umbraco Forms</key>
<key alias="formsDescription">Erstellen Sie Formulare mithilfe einer intuitiven Benutzeroberfläche. Von einfachen Kontaktformularen
die Email verschicken bis hin zu komplexen Fragebögen die mit einem CRM System verbunden sind. Ihre Kunden werden es lieben!
</key>
</area>
<area alias="contentTemplatesDashboard">
<key alias="whatHeadline">Was sind Inhaltsvorlagen?</key>
<key alias="whatDescription">Inhaltsvorlagen sind vordefinierte Inhalte die ausgewählt werden können
wenn Sie einen neuen Inhaltsknoten anlegen wollen.
</key>
<key alias="createHeadline">Wie erstelle ich eine Inhaltsvorlage?</key>
<key alias="createDescription">
<![CDATA[
<p>Es gibt zwei Möglichkeiten eine Inhaltsvorlage zu erstellen:</p>
<ul>
<li>Rechtsklicken Sie einen Inhaltsknoten und wählen Sie "Inhaltsvorlage erstellen" aus.</li>
<li>Rechtsklicken Sie den Inhaltsvorlagen-Baum und wählen Sie den Dokumententypen aus für den Sie eine Vorlage erstellen wollen.</li>
</ul>
<p>Wenn Sie einen Namen vergen haben können Reakteure diese als Vorlage für neue Seiten benutzen.</p>
]]>
</key>
<key alias="manageHeadline">Wie verwalte ich eine Inhaltsvorlage?</key>
<key alias="manageDescription">Sie können Inhaltsvorlagen bearbeiten und löschen in dem Sie im Inhaltsvorlage-Baum die gewünschte
Vorlage auswählen. Außerdem können Sie auch direkt den Dokumenttypen bearbeiten oder löschen auf dem die Vorlage basiert
</key>
</area>
<area alias="preview">
<key alias="endLabel">Beenden</key>
<key alias="endTitle">Vorschau beenden</key>
<key alias="openWebsiteLabel">Website Vorschau</key>
<key alias="openWebsiteTitle">Website in Vorschaumodus öffnen</key>
<key alias="returnToPreviewHeadline">Websitevorschau anzeigen?</key>
<key alias="returnToPreviewDescription">Sie haben den Vorschaumodus beendet, wollen Sie ihn erneut öffnen um
gespeicherte Version der Website anzusehen?
</key>
<key alias="returnToPreviewAcceptButton">Vorschau der letzten Version anzeigen</key>
<key alias="returnToPreviewDeclineButton">Veröffentlichte Version anzeigen</key>
<key alias="viewPublishedContentHeadline">Veröffentlichte Version anzeigen?</key>
<key alias="viewPublishedContentDescription">Sie befinden sich im Vorschaumodus, wollen Sie ihn verlassen um die letzte
veröffentlichte Version ihrer Website zu sehen?
</key>
<key alias="viewPublishedContentAcceptButton">Veröffentlichte Version anzeigen</key>
<key alias="viewPublishedContentDeclineButton">Im Vorschaumodus bleiben</key>
</area>
<area alias="permissions">
<key alias="FolderCreation">Ornder erstellen</key>
<key alias="FileWritingForPackages">Dateien durch Packages erstellen lassen</key>
<key alias="FileWriting">Dateien schreiben</key>
<key alias="MediaFolderCreation">Medien Ordner stellen</key>
</area>
<area alias="treeSearch">
<key alias="searchResult">Element zurückgegeben</key>
<key alias="searchResults">Elemente zurückgegeben</key>
</area>
</language>
+10 -10
View File
@@ -341,7 +341,6 @@
<key alias="createFolderFailed">Failed to create a folder under parent id %0%</key>
<key alias="renameFolderFailed">Failed to rename the folder with id %0%</key>
<key alias="dragAndDropYourFilesIntoTheArea">Drag and drop your file(s) into the area</key>
<key alias="fileSecurityValidationFailure">One or more file security validations have failed</key>
</area>
<area alias="member">
<key alias="createNewMember">Create a new member</key>
@@ -489,7 +488,7 @@
<key alias="insertlink">Insert link</key>
<key alias="insertMacro">Click to add a Macro</key>
<key alias="inserttable">Insert table</key>
<key alias="languagedeletewarning">This will delete the language and all content related to the language</key>
<key alias="languagedeletewarning">This will delete the language</key>
<key alias="languageChangeWarning">Changing the culture for a language may be an expensive operation and will result
in the content cache and indexes being rebuilt
</key>
@@ -879,8 +878,6 @@
<key alias="header">Header</key>
<key alias="systemField">system field</key>
<key alias="lastUpdated">Last Updated</key>
<key alias="skipToMenu">Skip to menu</key>
<key alias="skipToContent">Skip to content</key>
</area>
<area alias="colors">
<key alias="blue">Blue</key>
@@ -1332,7 +1329,7 @@ To manage your website, simply open the Umbraco backoffice and start adding cont
<key alias="packageLikes">Likes</key>
<key alias="packageCompatibility">Compatibility</key>
<key alias="packageCompatibilityDescription">This package is compatible with the following versions of Umbraco, as
reported by community members. Full compatibility cannot be guaranteed for versions reported below 100%
reported by community members. Full compatability cannot be guaranteed for versions reported below 100%
</key>
<key alias="packageExternalSources">External sources</key>
<key alias="packageAuthor">Author</key>
@@ -1541,7 +1538,7 @@ To manage your website, simply open the Umbraco backoffice and start adding cont
<key alias="contentTypeDublicatePropertyType">Property type already exists</key>
<key alias="contentTypePropertyTypeCreated">Property type created</key>
<key alias="contentTypePropertyTypeCreatedText"><![CDATA[Name: %0% <br /> DataType: %1%]]></key>
<key alias="contentTypePropertyTypeDeleted">Property type deleted</key>
<key alias="contentTypePropertyTypeDeleted">Propertytype deleted</key>
<key alias="contentTypeSavedHeader">Document Type saved</key>
<key alias="contentTypeTabCreated">Tab created</key>
<key alias="contentTypeTabDeleted">Tab deleted</key>
@@ -2125,11 +2122,14 @@ To manage your website, simply open the Umbraco backoffice and start adding cont
Umbraco.
</key>
<key alias="userinviteWelcomeMessage">Hello there and welcome to Umbraco! In just 1 minute youll be good to go, we
just need you to setup a password.
just need you to setup a password and add a picture for your avatar.
</key>
<key alias="userinviteExpiredMessage">Welcome to Umbraco! Unfortunately your invite has expired. Please contact your
administrator and ask them to resend it.
</key>
<key alias="userinviteAvatarMessage">Uploading a photo of yourself will make it easy for other users to recognize
you. Click the circle above to upload your photo.
</key>
<key alias="writer">Writer</key>
<key alias="change">Change</key>
<key alias="yourProfile" version="7.0">Your profile</key>
@@ -2243,8 +2243,8 @@ To manage your website, simply open the Umbraco backoffice and start adding cont
<key alias="stateInactive">Inactive</key>
<key alias="sortNameAscending">Name (A-Z)</key>
<key alias="sortNameDescending">Name (Z-A)</key>
<key alias="sortCreateDateAscending">Oldest</key>
<key alias="sortCreateDateDescending">Newest</key>
<key alias="sortCreateDateAscending">Newest</key>
<key alias="sortCreateDateDescending">Oldest</key>
<key alias="sortLastLoginDateDescending">Last login</key>
<key alias="noUserGroupsAdded">No user groups have been added</key>
<key alias="2faDisableText">If you wish to disable this two-factor provider, then you must enter the code shown on your authentication device:</key>
@@ -2773,7 +2773,7 @@ To manage your website, simply open the Umbraco backoffice and start adding cont
<key alias="focusParentBlock">Set focus on the container block</key>
<key alias="areaIdentification">Identification</key>
<key alias="areaValidation">Validation</key>
<key alias="areaValidationEntriesShort"><![CDATA[<strong>%0%</strong> must be present at least <strong>%2%</strong> time(s).]]></key>
<key alias="areaValidationEntriesShort"><![CDATA[<strong>%0%</strong> must be present atleast <strong>%2%</strong> time(s).]]></key>
<key alias="areaValidationEntriesExceed"><![CDATA[<strong>%0%</strong> must maximum be present <strong>%3%</strong> time(s).]]></key>
<key alias="areaNumberOfBlocks">Number of blocks</key>
<key alias="areaDisallowAllBlocks">Only allow specific block types</key>
@@ -352,7 +352,6 @@
<key alias="renameFolderFailed">Failed to rename the folder with id %0%</key>
<key alias="dragAndDropYourFilesIntoTheArea">Drag and drop your file(s) into the area</key>
<key alias="uploadNotAllowed">Upload is not allowed in this location.</key>
<key alias="fileSecurityValidationFailure">One or more file security validations have failed</key>
</area>
<area alias="member">
<key alias="createNewMember">Create a new member</key>
@@ -504,7 +503,7 @@
<key alias="insertlink">Insert link</key>
<key alias="insertMacro">Click to add a Macro</key>
<key alias="inserttable">Insert table</key>
<key alias="languagedeletewarning">This will delete the language and all content related to the language</key>
<key alias="languagedeletewarning">This will delete the language</key>
<key alias="languageChangeWarning">Changing the culture for a language may be an expensive operation and will result
in the content cache and indexes being rebuilt
</key>
@@ -758,7 +757,6 @@
<key alias="by">by</key>
<key alias="cancel">Cancel</key>
<key alias="cellMargin">Cell margin</key>
<key alias="change">Change</key>
<key alias="choose">Choose</key>
<key alias="clear">Clear</key>
<key alias="close">Close</key>
@@ -910,8 +908,6 @@
<key alias="header">Header</key>
<key alias="systemField">system field</key>
<key alias="lastUpdated">Last Updated</key>
<key alias="skipToMenu">Skip to menu</key>
<key alias="skipToContent">Skip to content</key>
</area>
<area alias="colors">
<key alias="blue">Blue</key>
@@ -2220,11 +2216,14 @@ To manage your website, simply open the Umbraco backoffice and start adding cont
Umbraco.
</key>
<key alias="userinviteWelcomeMessage">Hello there and welcome to Umbraco! In just 1 minute youll be good to go, we
just need you to setup a password.
just need you to setup a password and add a picture for your avatar.
</key>
<key alias="userinviteExpiredMessage">Welcome to Umbraco! Unfortunately your invite has expired. Please contact your
administrator and ask them to resend it.
</key>
<key alias="userinviteAvatarMessage">Uploading a photo of yourself will make it easy for other users to recognize
you. Click the circle above to upload your photo.
</key>
<key alias="writer">Writer</key>
<key alias="configureTwoFactor">Configure Two-Factor</key>
<key alias="change">Change</key>
@@ -2339,8 +2338,8 @@ To manage your website, simply open the Umbraco backoffice and start adding cont
<key alias="stateInactive">Inactive</key>
<key alias="sortNameAscending">Name (A-Z)</key>
<key alias="sortNameDescending">Name (Z-A)</key>
<key alias="sortCreateDateAscending">Oldest</key>
<key alias="sortCreateDateDescending">Newest</key>
<key alias="sortCreateDateAscending">Newest</key>
<key alias="sortCreateDateDescending">Oldest</key>
<key alias="sortLastLoginDateDescending">Last login</key>
<key alias="noUserGroupsAdded">No user groups have been added</key>
<key alias="2faDisableText">If you wish to disable this two-factor provider, then you must enter the code shown on your authentication device:</key>
@@ -3004,7 +3003,7 @@ To manage your website, simply open the Umbraco backoffice and start adding cont
We will send:
<ul>
<li>Anonymized site ID, Umbraco version, and packages installed.</li>
<li>Number of: Root nodes, Content nodes, Macros, Media, Document Types, Templates, Languages, Domains, User Group, Users, Members, Backoffice external login providers, and Property Editors in use.</li>
<li>Number of: Root nodes, Content nodes, Macros, Media, Document Types, Templates, Languages, Domains, User Group, Users, Members, and Property Editors in use.</li>
<li>System information: Webserver, server OS, server framework, server OS language, and database provider.</li>
<li>Configuration settings: Modelsbuilder mode, if custom Umbraco path exists, ASP environment, and if you are in debug mode.</li>
</ul>
+2 -13
View File
@@ -347,18 +347,6 @@
<key alias="selectEditor">Selecciona editor</key>
<key alias="selectSnippet">Selecciona snippet</key>
</area>
<area alias="dictionary">
<key alias="importDictionaryItemHelp">
Para importar un elemento del diccionario, busque el archivo ".udt" en su computadora haciendo clic en el
Botón "Importar" (se le pedirá confirmación en la siguiente pantalla)
</key>
<key alias="itemDoesNotExists">El elemento del diccionario no existe.</key>
<key alias="parentDoesNotExists">El elemento principal no existe.</key>
<key alias="noItems">No hay elementos del diccionario.</key>
<key alias="noItemsInFile">No hay elementos de diccionario en este archivo.</key>
<key alias="noItemsFound">No se encontraron elementos del diccionario.</key>
<key alias="createNew">Crear elemento de diccionario</key>
</area>
<area alias="dictionaryItem">
<key alias="description">Editar las diferentes versiones lingüísticas para la entrada en el diccionario '% 0%' debajo</key>
<key alias="displayName"><![CDATA[nombre de la cultura
@@ -1394,7 +1382,8 @@
<key alias="usergroup">Grupo de usuario</key>
<key alias="userInvited">ha sido invitado</key>
<key alias="userInvitedSuccessHelp">Se ha enviado una invitación al nuevo usuario con detalles sobre cómo acceder a Umbraco.</key>
<key alias="userinviteWelcomeMessage">¡Hola y bienvenido a Umbraco!. En un minuto todo estará listo para empezar, sólo necesitamos que configures tu contraseña.</key>
<key alias="userinviteWelcomeMessage">¡Hola y bienvenido a Umbraco!. En un minuto todo estará listo para empezar, sólo necesitamos que configures tu contraseña y una imagen para tu avatar.</key>
<key alias="userinviteAvatarMessage">Sube una foto para que otros usuarios te reconozcan más fácilmente.</key>
<key alias="writer">Redactor</key>
<key alias="change">Cambiar</key>
<key alias="yourProfile" version="7.0">Tu perfil</key>
@@ -1795,8 +1795,9 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à
<key alias="usergroup">Groupe d'utilisateurs</key>
<key alias="userInvited">a été invité</key>
<key alias="userInvitedSuccessHelp">Une invitation a été envoyée au nouvel utilisateur avec les détails concernant la connexion à Umbraco.</key>
<key alias="userinviteWelcomeMessage">Bien le bonjour et bienvenue dans Umbraco! Vous serez prêt.e dans moins d'1 minute, vous devez encore simplement configurer votre mot de passe.</key>
<key alias="userinviteWelcomeMessage">Bien le bonjour et bienvenue dans Umbraco! Vous serez prêt.e dans moins d'1 minute, vous devez encore simplement configurer votre mot de passe et ajouter une photo pour votre avatar.</key>
<key alias="userinviteExpiredMessage">Bienvenue dans Umbraco! Malheureusement, votre invitation a expiré. Veuillez contacter votre administrateur et demandez-lui de vous l'envoyer à nouveau.</key>
<key alias="userinviteAvatarMessage">Chargez une photo afin que les autres utilisateurs puissent vous reconnaître facilement. Cliquez sur le cercle ci-dessus pour charger votre photo.</key>
<key alias="writer">Rédacteur</key>
<key alias="change">Modifier</key>
<key alias="yourProfile" version="7.0">Votre profil</key>
@@ -1909,8 +1910,8 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à
<key alias="stateInactive">Inactif</key>
<key alias="sortNameAscending">Nom (A-Z)</key>
<key alias="sortNameDescending">Nom (Z-A)</key>
<key alias="sortCreateDateAscending">Plus ancien</key>
<key alias="sortCreateDateDescending">Plus récent</key>
<key alias="sortCreateDateAscending">Plus récent</key>
<key alias="sortCreateDateDescending">Plus ancien</key>
<key alias="sortLastLoginDateDescending">Dernière connexion</key>
</area>
<area alias="validation">
File diff suppressed because it is too large Load Diff
@@ -2197,10 +2197,13 @@ Per gestire il tuo sito web, è sufficiente aprire il backoffice di Umbraco e in
<key alias="userInvitedSuccessHelp">
<![CDATA[Un invito è stato invitato al nuovo utente con le istruzioni su come effettuare il login in Umbraco.]]></key>
<key alias="userinviteWelcomeMessage">Ciao e benvenuto su Umbraco! In solo 1 minuto sarai pronto a partire, dovrai
solamente impostare una password.
solamente impostare una password e aggiungere una foto profilo.
</key>
<key alias="userinviteExpiredMessage">
<![CDATA[Benvenuto su Umbraco! Purtroppo il tuo invito è scaduto. Per favore contatta l'amministratore e chiedigli di rispedirlo.]]></key>
<key alias="userinviteAvatarMessage">Caricando una tua foto, gli altri utenti potranno riconoscerti facilmente. Fai
clic sul cerchio sopra per caricare la tua foto.
</key>
<key alias="writer">Autore</key>
<key alias="change">Modifica</key>
<key alias="yourProfile" version="7.0">Il tuo profilo</key>
@@ -2316,8 +2319,8 @@ Per gestire il tuo sito web, è sufficiente aprire il backoffice di Umbraco e in
<key alias="stateInactive">Inattivi</key>
<key alias="sortNameAscending">Nome (A-Z)</key>
<key alias="sortNameDescending">Nome (Z-A)</key>
<key alias="sortCreateDateAscending"><![CDATA[Più vecchi]]></key>
<key alias="sortCreateDateDescending"><![CDATA[Più nuovi]]></key>
<key alias="sortCreateDateAscending"><![CDATA[Più nuovi]]></key>
<key alias="sortCreateDateDescending"><![CDATA[Più vecchi]]></key>
<key alias="sortLastLoginDateDescending">Ultimo login</key>
<key alias="noUserGroupsAdded">Non sono stati aggiunti gruppi di utenti</key>
</area>
@@ -2657,7 +2660,6 @@ Per gestire il tuo sito web, è sufficiente aprire il backoffice di Umbraco e in
<key alias="labelUsedByMemberTypes">Usato nei tipi di membro</key>
<key alias="noMemberTypes">Non ci sono riferimenti a tipi di membro.</key>
<key alias="usedByProperties">Usato da</key>
<key alias="labelUsedByItems">Correlato ai seguenti elementi</key>
<key alias="labelUsedByDocuments">Usato nei documenti</key>
<key alias="labelUsedByMembers">Usato nei membri</key>
<key alias="labelUsedByMedia">Usato nei media</key>
@@ -340,7 +340,6 @@
<key alias="renameFolderFailed">Kan de map met id %0% niet hernoemen</key>
<key alias="dragAndDropYourFilesIntoTheArea">Sleep en zet je bestand(en) neer in dit gebied</key>
<key alias="uploadNotAllowed">Upload is niet toegelaten in deze locatie.</key>
<key alias="fileSecurityValidationFailure">Een of meerdere veiligheid validaties zijn gefaald voor het bestand</key>
</area>
<area alias="member">
<key alias="createNewMember">Maak nieuw lid aan</key>
@@ -1938,11 +1937,12 @@ Echter, Runway biedt een gemakkelijke basis om je snel op weg te helpen. Als je
te loggen in Umbraco
</key>
<key alias="userinviteWelcomeMessage">Hallo en welkom in Umbraco! Binnen ongeveer één minuut kan je aan de slag. Je
moet enkel je wachtwoord instellen.
moet enkel je wachtwoord instellen en een foto toevoegen.
</key>
<key alias="userinviteExpiredMessage">Welkom bij Umbraco! Helaas is je uitnodiging vervallen. Vraag aan je
administrator om de uitnodiging opnieuw te versturen.
</key>
<key alias="userinviteAvatarMessage">Wijzig je foto zodat andere gebruikers je makkelijk kunnen herkennen.</key>
<key alias="writer">Auteur</key>
<key alias="configureTwoFactor">Configureer tweestapsverificatie</key>
<key alias="change">Wijzig</key>
@@ -2056,8 +2056,8 @@ Echter, Runway biedt een gemakkelijke basis om je snel op weg te helpen. Als je
<key alias="stateInactive">Inactief</key>
<key alias="sortNameAscending">Naam (A-Z)</key>
<key alias="sortNameDescending">Naam (Z-A)</key>
<key alias="sortCreateDateAscending">Oudste</key>
<key alias="sortCreateDateDescending">Nieuwste</key>
<key alias="sortCreateDateAscending">Nieuwste</key>
<key alias="sortCreateDateDescending">Oudste</key>
<key alias="sortLastLoginDateDescending">Laatste login</key>
<key alias="noUserGroupsAdded">Er zijn geen gebruikersgroepen toegevoegd</key>
</area>
@@ -822,8 +822,6 @@ Você pode publicar esta página e todas suas sub-páginas ao selecionar <em>pub
<key alias="usertype">Tipo de usuário</key>
<key alias="userTypes">Tipos de usuários</key>
<key alias="writer">Escrevente</key>
<key alias="sortCreateDateAscending">Mais antigo</key>
<key alias="sortCreateDateDescending">Mais recente</key>
</area>
<area alias="logViewer">
<key alias="selectAllLogLevelFilters">Selecionar tudo</key>
@@ -1,18 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<language alias="ro" intName="Romanian (Romania)" localName="romana (Romania)" lcid="" culture="ro-RO">
<creator>
<name>The Umbraco community</name>
<link>https://docs.umbraco.com/umbraco-cms/extending/language-files</link>
</creator>
<area alias="sections">
<key alias="content">Conţinut</key>
<key alias="forms">Formulare</key>
<key alias="media">Media</key>
<key alias="member">Membrii</key>
<key alias="packages">Pachete</key>
<key alias="marketplace">Marketplace</key>
<key alias="settings">Setări</key>
<key alias="translation">Traduceri</key>
<key alias="users">Utilizatori</key>
</area>
</language>
@@ -1703,7 +1703,8 @@
<key alias="usergroup">Группа пользователей</key>
<key alias="userInvited"> был приглашен</key>
<key alias="userInvitedSuccessHelp">Новому пользователю было отправлено приглашение, в котором содержатся инструкции для входа в панель Umbraco.</key>
<key alias="userinviteWelcomeMessage">Здравствуйте и добро пожаловать в Umbraco! Все будет готово в течении пары минут, нам лишь нужно задать Ваш пароль для входа.</key>
<key alias="userinviteWelcomeMessage">Здравствуйте и добро пожаловать в Umbraco! Все будет готово в течении пары минут, нам лишь нужно задать Ваш пароль для входа и добавить аватар.</key>
<key alias="userinviteAvatarMessage">Загрузите изображение, это поможет другим пользователям идентифицировать Вас.</key>
<key alias="userManagement">Управление пользователями</key>
<key alias="userPermissions">Разрешения для пользователя</key>
<key alias="writer">Автор</key>
@@ -134,7 +134,7 @@
<key alias="saveToPublish">Spara och skicka för godkännande</key>
<key alias="schedulePublish">Schemaläggning</key>
<key alias="select">Välj</key>
<key alias="saveAndPreview">Spara och förhandsgranska</key>
<key alias="saveAndPreview">Förhandsgranska</key>
<key alias="showPageDisabled">Förhandsgranskning är avstängt på grund av att det inte finns någon mall tilldelad</key>
<key alias="somethingElse">Gör något annat</key>
<key alias="styleChoose">Välj stil</key>
@@ -1001,8 +1001,8 @@
<key alias="writer">Skribent</key>
<key alias="yourHistory">Din nuvarande historik</key>
<key alias="yourProfile">Din profil</key>
<key alias="sortCreateDateAscending">Äldst</key>
<key alias="sortCreateDateDescending">Nyast</key>
<key alias="sortCreateDateAscending">Nyast</key>
<key alias="sortCreateDateDescending">Äldst</key>
<key alias="sortLastLoginDateDescending">Senaste login</key>
</area>
<area alias="logViewer">
@@ -1879,8 +1879,9 @@ Web sitenizi yönetmek için, Umbraco'nun arka ofisini açın ve içerik eklemey
<key alias="usergroup">Kullanıcı grubu</key>
<key alias="userInvited">davet edildi</key>
<key alias="userInvitedSuccessHelp">Yeni kullanıcıya, Umbraco'da nasıl oturum açılacağına ilişkin ayrıntıları içeren bir davetiye gönderildi.</key>
<key alias="userinviteWelcomeMessage">Merhabalar, Umbraco'ya hoş geldiniz! Sadece 1 dakika içinde hazır olacaksınız, sadece bir şifre belirlemeniz.</key>
<key alias="userinviteWelcomeMessage">Merhabalar, Umbraco'ya hoş geldiniz! Sadece 1 dakika içinde hazır olacaksınız, sadece bir şifre belirlemeniz ve avatarınız için bir resim eklemeniz gerekiyor.</key>
<key alias="userinviteExpiredMessage">Umbraco'ya hoş geldiniz! Maalesef davetinizin süresi doldu. Lütfen yöneticinizle iletişime geçin ve yeniden göndermesini isteyin.</key>
<key alias="userinviteAvatarMessage">Kendi fotoğrafınızı yüklemek, diğer kullanıcıların sizi tanımasını kolaylaştıracaktır. Fotoğrafınızı yüklemek için yukarıdaki daireyi tıklayın.</key>
<key alias="writer">Yazar</key>
<key alias="change">Değiştir</key>
<key alias="yourProfile" version="7.0">Profiliniz</key>
@@ -1995,8 +1996,8 @@ Web sitenizi yönetmek için, Umbraco'nun arka ofisini açın ve içerik eklemey
<key alias="stateInactive">Etkin Değil</key>
<key alias="sortNameAscending">Ad (AZ)</key>
<key alias="sortNameDescending">Ad (ZA)</key>
<key alias="sortCreateDateAscending">En eski</key>
<key alias="sortCreateDateDescending">En yeni</key>
<key alias="sortCreateDateAscending">En yeni</key>
<key alias="sortCreateDateDescending">En eski</key>
<key alias="sortLastLoginDateDescending">Son giriş</key>
<key alias="noUserGroupsAdded">Hiçbir kullanıcı grubu eklenmedi</key>
</area>
File diff suppressed because it is too large Load Diff
@@ -18,9 +18,6 @@
// Set to true if you want the member editable properties shown.
// It will only displays properties marked as "Member can edit" on the "Info" tab of the Member Type.
.WithCustomProperties(false)
// By default the member will be logged in automatically after registration.
// Set this to false if the member should not be logged in automatically.
.WithAutomaticLogIn(true)
.Build();
var success = TempData["FormSuccess"] != null;
@@ -42,8 +39,7 @@ else
new {
MemberTypeAlias = registerModel.MemberTypeAlias,
UsernameIsEmail = registerModel.UsernameIsEmail,
RedirectUrl = registerModel.RedirectUrl,
AutomaticLogIn = registerModel.AutomaticLogIn
RedirectUrl = registerModel.RedirectUrl
}))
{
<h2>Create a new account.</h2>
@@ -137,7 +137,7 @@ internal class NotificationAsyncHandlerWrapperImpl<TNotification> : Notification
/// confusion.
/// </para>
/// </remarks>
public override async Task HandleAsync(
public override Task HandleAsync(
INotification notification,
CancellationToken cancellationToken,
ServiceFactory serviceFactory,
@@ -155,7 +155,7 @@ internal class NotificationAsyncHandlerWrapperImpl<TNotification> : Notification
(theNotification, theToken) =>
x.HandleAsync((TNotification)theNotification, theToken)));
await publish(handlers, notification, cancellationToken);
return publish(handlers, notification, cancellationToken);
}
}
+2 -2
View File
@@ -50,7 +50,7 @@ public partial class EventAggregator : IEventAggregator
=> _serviceFactory = serviceFactory;
/// <inheritdoc />
public async Task PublishAsync<TNotification>(TNotification notification, CancellationToken cancellationToken = default)
public Task PublishAsync<TNotification>(TNotification notification, CancellationToken cancellationToken = default)
where TNotification : INotification
{
// TODO: Introduce codegen efficient Guard classes to reduce noise.
@@ -60,7 +60,7 @@ public partial class EventAggregator : IEventAggregator
}
PublishNotification(notification);
await PublishNotificationAsync(notification, cancellationToken);
return PublishNotificationAsync(notification, cancellationToken);
}
/// <inheritdoc />
@@ -1,19 +0,0 @@
using System.Diagnostics.CodeAnalysis;
using Umbraco.Cms.Core.Strings;
namespace Umbraco.Extensions;
public static class HtmlEncodedStringExtensions
{
/// <summary>
/// Checks if the specified <see cref="IHtmlEncodedString" /> is <c>null</c> or only contains whitespace, optionally after all HTML tags have been stripped/removed.
/// </summary>
/// <param name="htmlEncodedString">The encoded HTML string.</param>
/// <param name="stripHtml">If set to <c>true</c> strips/removes all HTML tags.</param>
/// <returns>
/// Returns <c>true</c> if the HTML string is <c>null</c> or only contains whitespace, optionally after all HTML tags have been stripped/removed.
/// </returns>
public static bool IsNullOrWhiteSpace([NotNullWhen(false)] this IHtmlEncodedString? htmlEncodedString, bool stripHtml = false)
=> (htmlEncodedString?.ToHtmlString() is var htmlString && string.IsNullOrWhiteSpace(htmlString)) ||
(stripHtml && string.IsNullOrWhiteSpace(htmlString.StripHtml()));
}
@@ -30,5 +30,5 @@ public static class PasswordConfigurationExtensions
};
public static int GetMinNonAlphaNumericChars(this IPasswordConfiguration passwordConfiguration) =>
passwordConfiguration.RequireNonLetterOrDigit ? 1 : 0;
passwordConfiguration.RequireNonLetterOrDigit ? 2 : 0;
}
@@ -1040,15 +1040,14 @@ public static class StringExtensions
throw new ArgumentNullException(nameof(text));
}
ReadOnlySpan<char> spanText = text.AsSpan();
var pos = spanText.IndexOf(search, StringComparison.InvariantCulture);
var pos = text.IndexOf(search, StringComparison.InvariantCulture);
if (pos < 0)
{
return text;
}
return string.Concat(spanText[..pos], replace.AsSpan(), spanText[(pos + search.Length)..]);
return text.Substring(0, pos) + replace + text.Substring(pos + search.Length);
}
/// <summary>
+80 -79
View File
@@ -219,52 +219,96 @@ public static class TypeExtensions
/// <returns></returns>
public static PropertyInfo[] GetAllProperties(this Type type)
{
const BindingFlags bindingFlags = BindingFlags.FlattenHierarchy
| BindingFlags.Public
| BindingFlags.NonPublic
| BindingFlags.Instance;
return type.GetAllMemberInfos(t => t.GetProperties(bindingFlags));
if (type.IsInterface)
{
var propertyInfos = new List<PropertyInfo>();
var considered = new List<Type>();
var queue = new Queue<Type>();
considered.Add(type);
queue.Enqueue(type);
while (queue.Count > 0)
{
Type subType = queue.Dequeue();
foreach (Type subInterface in subType.GetInterfaces())
{
if (considered.Contains(subInterface))
{
continue;
}
considered.Add(subInterface);
queue.Enqueue(subInterface);
}
PropertyInfo[] typeProperties = subType.GetProperties(
BindingFlags.FlattenHierarchy
| BindingFlags.Public
| BindingFlags.NonPublic
| BindingFlags.Instance);
IEnumerable<PropertyInfo> newPropertyInfos = typeProperties
.Where(x => !propertyInfos.Contains(x));
propertyInfos.InsertRange(0, newPropertyInfos);
}
return propertyInfos.ToArray();
}
return type.GetProperties(BindingFlags.FlattenHierarchy
| BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
}
/// <summary>
/// Returns public properties including inherited properties even for interfaces
/// Returns all public properties including inherited properties even for interfaces
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
/// <remarks>
/// taken from
/// http://stackoverflow.com/questions/358835/getproperties-to-return-all-properties-for-an-interface-inheritance-hierarchy
/// </remarks>
public static PropertyInfo[] GetPublicProperties(this Type type)
{
const BindingFlags bindingFlags = BindingFlags.FlattenHierarchy
| BindingFlags.Public
| BindingFlags.Instance;
return type.GetAllMemberInfos(t => t.GetProperties(bindingFlags));
}
if (type.IsInterface)
{
var propertyInfos = new List<PropertyInfo>();
/// <summary>
/// Returns public methods including inherited methods even for interfaces
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public static MethodInfo[] GetPublicMethods(this Type type)
{
const BindingFlags bindingFlags = BindingFlags.FlattenHierarchy
| BindingFlags.Public
| BindingFlags.Instance;
return type.GetAllMemberInfos(t => t.GetMethods(bindingFlags));
}
var considered = new List<Type>();
var queue = new Queue<Type>();
considered.Add(type);
queue.Enqueue(type);
while (queue.Count > 0)
{
Type subType = queue.Dequeue();
foreach (Type subInterface in subType.GetInterfaces())
{
if (considered.Contains(subInterface))
{
continue;
}
/// <summary>
/// Returns all methods including inherited methods even for interfaces
/// </summary>
/// <remarks>Includes both Public and Non-Public methods</remarks>
/// <param name="type"></param>
/// <returns></returns>
public static MethodInfo[] GetAllMethods(this Type type)
{
const BindingFlags bindingFlags = BindingFlags.FlattenHierarchy
| BindingFlags.Public
| BindingFlags.NonPublic
| BindingFlags.Instance;
return type.GetAllMemberInfos(t => t.GetMethods(bindingFlags));
considered.Add(subInterface);
queue.Enqueue(subInterface);
}
PropertyInfo[] typeProperties = subType.GetProperties(
BindingFlags.FlattenHierarchy
| BindingFlags.Public
| BindingFlags.Instance);
IEnumerable<PropertyInfo> newPropertyInfos = typeProperties
.Where(x => !propertyInfos.Contains(x));
propertyInfos.InsertRange(0, newPropertyInfos);
}
return propertyInfos.ToArray();
}
return type.GetProperties(BindingFlags.FlattenHierarchy
| BindingFlags.Public | BindingFlags.Instance);
}
/// <summary>
@@ -468,47 +512,4 @@ public static class TypeExtensions
return attempt;
}
/// <remarks>
/// taken from
/// http://stackoverflow.com/questions/358835/getproperties-to-return-all-properties-for-an-interface-inheritance-hierarchy
/// </remarks>
private static T[] GetAllMemberInfos<T>(this Type type, Func<Type, T[]> getMemberInfos)
where T : MemberInfo
{
if (type.IsInterface is false)
{
return getMemberInfos(type);
}
var memberInfos = new List<T>();
var considered = new List<Type>();
var queue = new Queue<Type>();
considered.Add(type);
queue.Enqueue(type);
while (queue.Count > 0)
{
Type subType = queue.Dequeue();
foreach (Type subInterface in subType.GetInterfaces())
{
if (considered.Contains(subInterface))
{
continue;
}
considered.Add(subInterface);
queue.Enqueue(subInterface);
}
T[] typeMethodInfos = getMemberInfos(subType);
IEnumerable<T> newMethodInfos = typeMethodInfos
.Where(x => !memberInfos.Contains(x));
memberInfos.InsertRange(0, newMethodInfos);
}
return memberInfos.ToArray();
}
}
@@ -232,7 +232,9 @@ public static class UdiGetterExtensions
throw new ArgumentNullException("entity");
}
return GetUdiFromPath(Constants.UdiEntityType.Stylesheet, entity.Path);
return new StringUdi(
Constants.UdiEntityType.Stylesheet,
entity.Path.TrimStart(Constants.CharArrays.ForwardSlash)).EnsureClosed();
}
/// <summary>
@@ -247,15 +249,8 @@ public static class UdiGetterExtensions
throw new ArgumentNullException("entity");
}
return GetUdiFromPath(Constants.UdiEntityType.Script, entity.Path);
}
private static StringUdi GetUdiFromPath(string entityType, string path)
{
var id = path
.TrimStart(Constants.CharArrays.ForwardSlash)
.Replace("\\", "/");
return new StringUdi(entityType, id).EnsureClosed();
return new StringUdi(Constants.UdiEntityType.Script, entity.Path.TrimStart(Constants.CharArrays.ForwardSlash))
.EnsureClosed();
}
/// <summary>
@@ -305,7 +300,7 @@ public static class UdiGetterExtensions
? Constants.UdiEntityType.PartialViewMacro
: Constants.UdiEntityType.PartialView;
return GetUdiFromPath(entityType, entity.Path);
return new StringUdi(entityType, entity.Path.TrimStart(Constants.CharArrays.ForwardSlash)).EnsureClosed();
}
/// <summary>
+1 -1
View File
@@ -358,7 +358,7 @@ namespace Umbraco.Cms.Core.IO
// nothing prevents us to reach the file, security-wise, yet it is outside
// this filesystem's root - throw
throw new UnauthorizedAccessException($"Requested path {originalPath} is outside this filesystem's root.");
throw new UnauthorizedAccessException($"File original: [{originalPath}] full: [{path}] is outside this filesystem's root.");
}
/// <summary>
+19 -19
View File
@@ -7,21 +7,19 @@ namespace Umbraco.Cms.Core.IO;
internal class ShadowWrapper : IFileSystem, IFileProviderFactory
{
private const string ShadowFsPath = "ShadowFs";
private readonly IIOHelper _ioHelper;
private static readonly string ShadowFsPath = Constants.SystemDirectories.TempData.EnsureEndsWith('/') + "ShadowFs";
private readonly IHostingEnvironment _hostingEnvironment;
private readonly IIOHelper _ioHelper;
private readonly Func<bool?>? _isScoped;
private readonly ILoggerFactory _loggerFactory;
private readonly string _shadowPath;
private readonly Func<bool?>? _isScoped;
private string? _shadowDir;
private ShadowFileSystem? _shadowFileSystem;
public ShadowWrapper(IFileSystem innerFileSystem, IIOHelper ioHelper, IHostingEnvironment hostingEnvironment, ILoggerFactory loggerFactory, string shadowPath, Func<bool?>? isScoped = null)
{
InnerFileSystem = innerFileSystem;
_ioHelper = ioHelper ?? throw new ArgumentNullException(nameof(ioHelper));
_hostingEnvironment = hostingEnvironment ?? throw new ArgumentNullException(nameof(hostingEnvironment));
_loggerFactory = loggerFactory;
@@ -37,19 +35,18 @@ internal class ShadowWrapper : IFileSystem, IFileProviderFactory
{
get
{
Func<bool?>? isScoped = _isScoped;
if (isScoped is not null && _shadowFileSystem is not null)
if (_isScoped is not null && _shadowFileSystem is not null)
{
bool? scoped = isScoped();
var isScoped = _isScoped!();
// if the filesystem is created *after* shadowing starts, it won't be shadowing
// better not ignore that situation and raise a meaningful (?) exception
if (scoped.HasValue && scoped.Value && _shadowFileSystem == null)
// better not ignore that situation and raised a meaningful (?) exception
if (isScoped.HasValue && isScoped.Value && _shadowFileSystem == null)
{
throw new Exception("The filesystems are shadowing, but this filesystem is not.");
}
return scoped.HasValue && scoped.Value
return isScoped.HasValue && isScoped.Value
? _shadowFileSystem
: InnerFileSystem;
}
@@ -59,7 +56,8 @@ internal class ShadowWrapper : IFileSystem, IFileProviderFactory
}
/// <inheritdoc />
public IFileProvider? Create() => InnerFileSystem.TryCreateFileProvider(out IFileProvider? fileProvider) ? fileProvider : null;
public IFileProvider? Create() =>
InnerFileSystem.TryCreateFileProvider(out IFileProvider? fileProvider) ? fileProvider : null;
public IEnumerable<string> GetDirectories(string path) => FileSystem.GetDirectories(path);
@@ -71,7 +69,8 @@ internal class ShadowWrapper : IFileSystem, IFileProviderFactory
public void AddFile(string path, Stream stream) => FileSystem.AddFile(path, stream);
public void AddFile(string path, Stream stream, bool overrideExisting) => FileSystem.AddFile(path, stream, overrideExisting);
public void AddFile(string path, Stream stream, bool overrideExisting) =>
FileSystem.AddFile(path, stream, overrideExisting);
public IEnumerable<string> GetFiles(string path) => FileSystem.GetFiles(path);
@@ -108,7 +107,8 @@ internal class ShadowWrapper : IFileSystem, IFileProviderFactory
{
var id = GuidUtils.ToBase32String(Guid.NewGuid(), idLength);
var shadowDir = Path.Combine(hostingEnvironment.LocalTempPath, ShadowFsPath, id);
var virt = ShadowFsPath + "/" + id;
var shadowDir = hostingEnvironment.MapPathContentRoot(virt);
if (Directory.Exists(shadowDir))
{
continue;
@@ -129,10 +129,10 @@ internal class ShadowWrapper : IFileSystem, IFileProviderFactory
// note: no thread-safety here, because ShadowFs is thread-safe due to the check
// on ShadowFileSystemsScope.None - and if None is false then we should be running
// in a single thread anyways
var rootUrl = Path.Combine(ShadowFsPath, id, _shadowPath);
_shadowDir = Path.Combine(_hostingEnvironment.LocalTempPath, rootUrl);
var virt = Path.Combine(ShadowFsPath, id, _shadowPath);
_shadowDir = _hostingEnvironment.MapPathContentRoot(virt);
Directory.CreateDirectory(_shadowDir);
var tempfs = new PhysicalFileSystem(_ioHelper, _hostingEnvironment, _loggerFactory.CreateLogger<PhysicalFileSystem>(), _shadowDir, rootUrl);
var tempfs = new PhysicalFileSystem(_ioHelper, _hostingEnvironment, _loggerFactory.CreateLogger<PhysicalFileSystem>(), _shadowDir, _hostingEnvironment.ToAbsolute(virt));
_shadowFileSystem = new ShadowFileSystem(InnerFileSystem, tempfs);
}
@@ -160,7 +160,7 @@ internal class ShadowWrapper : IFileSystem, IFileProviderFactory
// shadowPath make be path/to/dir, remove each
dir = dir!.Replace('/', Path.DirectorySeparatorChar);
var min = Path.Combine(_hostingEnvironment.LocalTempPath, ShadowFsPath).Length;
var min = _hostingEnvironment.MapPathContentRoot(ShadowFsPath).Length;
var pos = dir.LastIndexOf(Path.DirectorySeparatorChar);
while (pos > min)
{
@@ -19,9 +19,6 @@ public class Issuu : EmbedProviderBase
public override Dictionary<string, string> RequestParams => new()
{
// ApiUrl/?iframe=true
{ "iframe", "true" },
// ApiUrl/?format=xml
{ "format", "xml" },
};
@@ -55,12 +55,11 @@ public abstract class OEmbedProviderBase : IEmbedProvider
if (_httpClient == null)
{
_httpClient = new HttpClient();
_httpClient.DefaultRequestHeaders.UserAgent.TryParseAdd("Umbraco-CMS");
}
using (var request = new HttpRequestMessage(HttpMethod.Get, url))
{
HttpResponseMessage response = _httpClient.SendAsync(request).GetAwaiter().GetResult();
HttpResponseMessage response = _httpClient.SendAsync(request).Result;
return response.Content.ReadAsStringAsync().Result;
}
}
@@ -14,7 +14,7 @@ public class YouTube : EmbedProviderBase
public override string ApiEndpoint => "https://www.youtube.com/oembed";
public override string[] UrlSchemeRegex => new[] { @"youtu.be/.*", @"youtube.com/watch.*", @"youtube.com/shorts/.*" };
public override string[] UrlSchemeRegex => new[] { @"youtu.be/.*", @"youtube.com/watch.*" };
public override Dictionary<string, string> RequestParams => new()
{
@@ -1,16 +0,0 @@
using System.Runtime.Serialization;
namespace Umbraco.Cms.Core.Models.ContentEditing;
/// <summary>
/// Used to publish content and variants
/// </summary>
[DataContract(Name = "publish", Namespace = "")]
public class PublishContent
{
[DataMember(Name = "id")]
public int Id { get; set; }
[DataMember(Name = "cultures")]
public string[]? Cultures { get; set; }
}
@@ -1,88 +1,49 @@
namespace Umbraco.Cms.Core.Models.Editors;
/// <summary>
/// Used to track a reference to another entity in a property value.
/// Used to track reference to other entities in a property value
/// </summary>
public struct UmbracoEntityReference : IEquatable<UmbracoEntityReference>
{
private static readonly UmbracoEntityReference _empty = new(UnknownTypeUdi.Instance, string.Empty);
/// <summary>
/// Initializes a new instance of the <see cref="UmbracoEntityReference" /> struct.
/// </summary>
/// <param name="udi">The UDI.</param>
/// <param name="relationTypeAlias">The relation type alias.</param>
public UmbracoEntityReference(Udi udi, string relationTypeAlias)
{
Udi = udi ?? throw new ArgumentNullException(nameof(udi));
RelationTypeAlias = relationTypeAlias ?? throw new ArgumentNullException(nameof(relationTypeAlias));
}
/// <summary>
/// Initializes a new instance of the <see cref="UmbracoEntityReference" /> struct for a document or media item.
/// </summary>
/// <param name="udi">The UDI.</param>
public UmbracoEntityReference(Udi udi)
{
Udi = udi ?? throw new ArgumentNullException(nameof(udi));
switch (udi.EntityType)
{
case Constants.UdiEntityType.Document:
RelationTypeAlias = Constants.Conventions.RelationTypes.RelatedDocumentAlias;
break;
case Constants.UdiEntityType.Media:
RelationTypeAlias = Constants.Conventions.RelationTypes.RelatedMediaAlias;
break;
default:
// No relation type alias convention for this entity type, so leave it empty
RelationTypeAlias = string.Empty;
RelationTypeAlias = Constants.Conventions.RelationTypes.RelatedDocumentAlias;
break;
}
}
/// <summary>
/// Gets the UDI.
/// </summary>
/// <value>
/// The UDI.
/// </value>
public Udi Udi { get; }
/// <summary>
/// Gets the relation type alias.
/// </summary>
/// <value>
/// The relation type alias.
/// </value>
public string RelationTypeAlias { get; }
/// <summary>
/// Gets an empty reference.
/// </summary>
/// <returns>
/// An empty reference.
/// </returns>
public static UmbracoEntityReference Empty() => _empty;
/// <summary>
/// Determines whether the specified reference is empty.
/// </summary>
/// <param name="reference">The reference.</param>
/// <returns>
/// <c>true</c> if the specified reference is empty; otherwise, <c>false</c>.
/// </returns>
public static bool IsEmpty(UmbracoEntityReference reference) => reference == Empty();
/// <inheritdoc />
public string RelationTypeAlias { get; }
public static bool operator ==(UmbracoEntityReference left, UmbracoEntityReference right) => left.Equals(right);
public override bool Equals(object? obj) => obj is UmbracoEntityReference reference && Equals(reference);
/// <inheritdoc />
public bool Equals(UmbracoEntityReference other) =>
EqualityComparer<Udi>.Default.Equals(Udi, other.Udi) &&
RelationTypeAlias == other.RelationTypeAlias;
/// <inheritdoc />
public override int GetHashCode()
{
var hashCode = -487348478;
@@ -91,9 +52,5 @@ public struct UmbracoEntityReference : IEquatable<UmbracoEntityReference>
return hashCode;
}
/// <inheritdoc />
public static bool operator ==(UmbracoEntityReference left, UmbracoEntityReference right) => left.Equals(right);
/// <inheritdoc />
public static bool operator !=(UmbracoEntityReference left, UmbracoEntityReference right) => !(left == right);
}
+1 -2
View File
@@ -2,7 +2,6 @@ using System.Collections.Specialized;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.Serialization;
using Umbraco.Cms.Core.Models.Entities;
namespace Umbraco.Cms.Core.Models;
@@ -133,7 +132,7 @@ public class PropertyGroup : EntityBase, IEquatable<PropertyGroup>
}
public bool Equals(PropertyGroup? other) =>
base.Equals(other) || (other != null && Type == other.Type && Alias == other.Alias && Id == other.Id);
base.Equals(other) || (other != null && Type == other.Type && Alias == other.Alias);
public override int GetHashCode() => (base.GetHashCode(), Type, Alias).GetHashCode();
@@ -30,7 +30,7 @@ public class PropertyTypeCollection : KeyedCollection<string, IPropertyType>, IN
// This baseclass calling is needed, else compiler will complain about nullability
/// <inheritdoc />
public bool IsReadOnly => false;
public bool IsReadOnly => ((ICollection<IPropertyType>)this).IsReadOnly;
// 'new' keyword is required! we can explicitly implement ICollection<IPropertyType>.Add BUT since normally a concrete PropertyType type
// is passed in, the explicit implementation doesn't get called, this ensures it does get called.
@@ -5,12 +5,6 @@ namespace Umbraco.Cms.Core.Models.PublishedContent;
/// </summary>
public interface IPublishedValueFallback
{
[Obsolete("Scheduled for removal in v14")]
/// <summary>
/// VariationContextAccessor that is not required to be implemented, therefore throws NotImplementedException as default.
/// </summary>
IVariationContextAccessor VariationContextAccessor { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } }
/// <summary>
/// Tries to get a fallback value for a property.
/// </summary>
@@ -7,15 +7,7 @@ namespace Umbraco.Cms.Core.Models.PublishedContent;
/// <para>This is for tests etc - does not implement fallback at all.</para>
/// </remarks>
public class NoopPublishedValueFallback : IPublishedValueFallback
{
/// <inheritdoc />
public IVariationContextAccessor VariationContextAccessor
{
get => new ThreadCultureVariationContextAccessor();
set { }
}
/// <inheritdoc />
public bool TryGetValue(IPublishedProperty property, string? culture, string? segment, Fallback fallback, object? defaultValue, out object? value)
{
@@ -1,4 +1,4 @@
using System.Diagnostics;
using System.Diagnostics;
using System.Xml.Linq;
using System.Xml.XPath;
using Umbraco.Cms.Core.PropertyEditors;
@@ -190,7 +190,7 @@ namespace Umbraco.Cms.Core.Models.PublishedContent
}
_cacheLevel = _converter?.GetPropertyCacheLevel(this) ?? PropertyCacheLevel.Snapshot;
_modelClrType = _converter?.GetPropertyValueType(this) ?? typeof(object);
_modelClrType = _converter == null ? typeof (object) : _converter.GetPropertyValueType(this);
}
/// <inheritdoc />
@@ -20,9 +20,6 @@ public class PublishedValueFallback : IPublishedValueFallback
_variationContextAccessor = variationContextAccessor;
}
[Obsolete("Scheduled for removal in v14")]
public IVariationContextAccessor VariationContextAccessor { get { return _variationContextAccessor; } }
/// <inheritdoc />
public bool TryGetValue(IPublishedProperty property, string? culture, string? segment, Fallback fallback, object? defaultValue, out object? value) =>
TryGetValue<object>(property, culture, segment, fallback, defaultValue, out value);
@@ -1,18 +0,0 @@
// Copyright (c) Umbraco.
// See LICENSE for more details.
using Umbraco.Cms.Core.Events;
using Umbraco.Cms.Core.Models;
namespace Umbraco.Cms.Core.Notifications;
/// <summary>
/// Notification that is send out when a Content item has been scaffolded from an original item and basic cleaning has been performed
/// </summary>
public sealed class ContentScaffoldedNotification : ScaffoldedNotification<IContent>
{
public ContentScaffoldedNotification(IContent original, IContent scaffold, int parentId, EventMessages messages)
: base(original, scaffold, parentId, messages)
{
}
}
@@ -1,23 +0,0 @@
// Copyright (c) Umbraco.
// See LICENSE for more details.
using Umbraco.Cms.Core.Events;
namespace Umbraco.Cms.Core.Notifications;
public abstract class ScaffoldedNotification<T> : CancelableObjectNotification<T>
where T : class
{
protected ScaffoldedNotification(T original, T scaffold, int parentId, EventMessages messages)
: base(original, messages)
{
Scaffold = scaffold;
ParentId = parentId;
}
public T Original => Target;
public T Scaffold { get; }
public int ParentId { get; }
}
@@ -4,156 +4,64 @@ using Umbraco.Cms.Core.Models.Editors;
namespace Umbraco.Cms.Core.PropertyEditors;
/// <summary>
/// Provides a builder collection for <see cref="IDataValueReferenceFactory" /> items.
/// </summary>
public class DataValueReferenceFactoryCollection : BuilderCollectionBase<IDataValueReferenceFactory>
{
// TODO: We could further reduce circular dependencies with PropertyEditorCollection by not having IDataValueReference implemented
// by property editors and instead just use the already built in IDataValueReferenceFactory and/or refactor that into a more normal collection
/// <summary>
/// Initializes a new instance of the <see cref="DataValueReferenceFactoryCollection" /> class.
/// </summary>
/// <param name="items">The items.</param>
public DataValueReferenceFactoryCollection(Func<IEnumerable<IDataValueReferenceFactory>> items)
: base(items)
{ }
/// <summary>
/// Gets all unique references from the specified properties.
/// </summary>
/// <param name="properties">The properties.</param>
/// <param name="propertyEditors">The property editors.</param>
/// <returns>
/// The unique references from the specified properties.
/// </returns>
public ISet<UmbracoEntityReference> GetAllReferences(IPropertyCollection properties, PropertyEditorCollection propertyEditors)
{
var references = new HashSet<UmbracoEntityReference>();
}
// Group by property editor alias to avoid duplicate lookups and optimize value parsing
foreach (var propertyValuesByPropertyEditorAlias in properties.GroupBy(x => x.PropertyType.PropertyEditorAlias, x => x.Values))
// TODO: We could further reduce circular dependencies with PropertyEditorCollection by not having IDataValueReference implemented
// by property editors and instead just use the already built in IDataValueReferenceFactory and/or refactor that into a more normal collection
public IEnumerable<UmbracoEntityReference> GetAllReferences(
IPropertyCollection properties,
PropertyEditorCollection propertyEditors)
{
var trackedRelations = new HashSet<UmbracoEntityReference>();
foreach (IProperty p in properties)
{
if (!propertyEditors.TryGet(propertyValuesByPropertyEditorAlias.Key, out IDataEditor? dataEditor))
if (!propertyEditors.TryGet(p.PropertyType.PropertyEditorAlias, out IDataEditor? editor))
{
continue;
}
// Use distinct values to avoid duplicate parsing of the same value
var values = new HashSet<object?>(properties.Count);
foreach (IPropertyValue propertyValue in propertyValuesByPropertyEditorAlias.SelectMany(x => x))
// TODO: We will need to change this once we support tracking via variants/segments
// for now, we are tracking values from ALL variants
foreach (IPropertyValue propertyVal in p.Values)
{
values.Add(propertyValue.EditedValue);
values.Add(propertyValue.PublishedValue);
}
var val = propertyVal.EditedValue;
references.UnionWith(GetReferences(dataEditor, values));
}
return references;
}
/// <summary>
/// Gets the references.
/// </summary>
/// <param name="dataEditor">The data editor.</param>
/// <param name="values">The values.</param>
/// <returns>
/// The references.
/// </returns>
public IEnumerable<UmbracoEntityReference> GetReferences(IDataEditor dataEditor, params object?[] values)
=> GetReferences(dataEditor, (IEnumerable<object?>)values);
/// <summary>
/// Gets the references.
/// </summary>
/// <param name="dataEditor">The data editor.</param>
/// <param name="values">The values.</param>
/// <returns>
/// The references.
/// </returns>
public IEnumerable<UmbracoEntityReference> GetReferences(IDataEditor dataEditor, IEnumerable<object?> values)
{
// TODO: We will need to change this once we support tracking via variants/segments
// for now, we are tracking values from ALL variants
if (dataEditor.GetValueEditor() is IDataValueReference dataValueReference)
{
foreach (UmbracoEntityReference reference in values.SelectMany(dataValueReference.GetReferences))
{
yield return reference;
}
}
// Loop over collection that may be add to existing property editors
// implementation of GetReferences in IDataValueReference.
// Allows developers to add support for references by a
// package /property editor that did not implement IDataValueReference themselves
foreach (IDataValueReferenceFactory dataValueReferenceFactory in this)
{
// Check if this value reference is for this datatype/editor
// Then call it's GetReferences method - to see if the value stored
// in the dataeditor/property has references to media/content items
if (dataValueReferenceFactory.IsForEditor(dataEditor))
{
IDataValueReference factoryDataValueReference = dataValueReferenceFactory.GetDataValueReference();
foreach (UmbracoEntityReference reference in values.SelectMany(factoryDataValueReference.GetReferences))
IDataValueEditor? valueEditor = editor?.GetValueEditor();
if (valueEditor is IDataValueReference reference)
{
yield return reference;
IEnumerable<UmbracoEntityReference> refs = reference.GetReferences(val);
foreach (UmbracoEntityReference r in refs)
{
trackedRelations.Add(r);
}
}
// Loop over collection that may be add to existing property editors
// implementation of GetReferences in IDataValueReference.
// Allows developers to add support for references by a
// package /property editor that did not implement IDataValueReference themselves
foreach (IDataValueReferenceFactory item in this)
{
// Check if this value reference is for this datatype/editor
// Then call it's GetReferences method - to see if the value stored
// in the dataeditor/property has referecnes to media/content items
if (item.IsForEditor(editor))
{
foreach (UmbracoEntityReference r in item.GetDataValueReference().GetReferences(val))
{
trackedRelations.Add(r);
}
}
}
}
}
}
/// <summary>
/// Gets all relation type aliases that are automatically tracked.
/// </summary>
/// <param name="propertyEditors">The property editors.</param>
/// <returns>
/// All relation type aliases that are automatically tracked.
/// </returns>
public ISet<string> GetAllAutomaticRelationTypesAliases(PropertyEditorCollection propertyEditors)
{
// Always add default automatic relation types
var automaticRelationTypeAliases = new HashSet<string>(Constants.Conventions.RelationTypes.AutomaticRelationTypes);
// Add relation types for all property editors
foreach (IDataEditor dataEditor in propertyEditors)
{
automaticRelationTypeAliases.UnionWith(GetAutomaticRelationTypesAliases(dataEditor));
}
return automaticRelationTypeAliases;
}
/// <summary>
/// Gets the automatic relation types aliases.
/// </summary>
/// <param name="dataEditor">The data editor.</param>
/// <returns>
/// The automatic relation types aliases.
/// </returns>
public IEnumerable<string> GetAutomaticRelationTypesAliases(IDataEditor dataEditor)
{
if (dataEditor.GetValueEditor() is IDataValueReference dataValueReference)
{
// Return custom relation types from value editor implementation
foreach (var alias in dataValueReference.GetAutomaticRelationTypesAliases())
{
yield return alias;
}
}
foreach (IDataValueReferenceFactory dataValueReferenceFactory in this)
{
if (dataValueReferenceFactory.IsForEditor(dataEditor))
{
// Return custom relation types from factory
foreach (var alias in dataValueReferenceFactory.GetDataValueReference().GetAutomaticRelationTypesAliases())
{
yield return alias;
}
}
}
return trackedRelations;
}
}
@@ -9,22 +9,11 @@ namespace Umbraco.Cms.Core.PropertyEditors;
/// </summary>
public class DefaultPropertyIndexValueFactory : IPropertyIndexValueFactory
{
public IEnumerable<KeyValuePair<string, IEnumerable<object?>>> GetIndexValues(IProperty property, string? culture, string? segment, bool published,
IEnumerable<string> availableCultures, IDictionary<Guid, IContentType> contentTypeDictionary)
/// <inheritdoc />
public IEnumerable<KeyValuePair<string, IEnumerable<object?>>> GetIndexValues(IProperty property, string? culture, string? segment, bool published)
{
yield return new KeyValuePair<string, IEnumerable<object?>>(
property.Alias,
property.GetValue(culture, segment, published).Yield());
}
/// <inheritdoc />
[Obsolete("Use the non-obsolete overload, scheduled for removal in v14")]
public IEnumerable<KeyValuePair<string, IEnumerable<object?>>> GetIndexValues(IProperty property, string? culture,
string? segment, bool published, IEnumerable<string> availableCultures)
=> GetIndexValues(property, culture, segment, published, availableCultures,
new Dictionary<Guid, IContentType>());
[Obsolete("Use the non-obsolete overload, scheduled for removal in v14")]
public IEnumerable<KeyValuePair<string, IEnumerable<object?>>> GetIndexValues(IProperty property, string? culture, string? segment, bool published)
=> GetIndexValues(property, culture, segment, published, Enumerable.Empty<string>(), new Dictionary<Guid, IContentType>());
}
@@ -16,10 +16,11 @@ public class DefaultPropertyValueConverterAttribute : Attribute
/// a DefaultPropertyValueConverter can be more specific than another one.
/// </summary>
/// <remarks>
/// An example where this is useful is that both the MultiUrlPickerValueConverter and the JsonValueConverter
/// An example where this is useful is that both the RelatedLiksEditorValueConverter and the JsonValueConverter
/// will be returned as value converters for the Related Links Property editor, however the JsonValueConverter
/// is a very generic converter and the MultiUrlPickerValueConverter is more specific than it, so the
/// MultiUrlPickerValueConverter can specify that it 'shadows' the JsonValueConverter.
/// is a very generic converter and the RelatedLiksEditorValueConverter is more specific than it, so the
/// RelatedLiksEditorValueConverter
/// can specify that it 'shadows' the JsonValueConverter.
/// </remarks>
public Type[] DefaultConvertersToShadow { get; }
}
@@ -1,5 +0,0 @@
namespace Umbraco.Cms.Core.PropertyEditors;
public interface IBlockValuePropertyIndexValueFactory : IPropertyIndexValueFactory
{
}
@@ -1,5 +0,0 @@
namespace Umbraco.Cms.Core.PropertyEditors;
public interface INestedContentPropertyIndexValueFactory : IPropertyIndexValueFactory
{
}
@@ -22,14 +22,5 @@ public interface IPropertyIndexValueFactory
/// more than one value for a given field.
/// </para>
/// </remarks>
IEnumerable<KeyValuePair<string, IEnumerable<object?>>> GetIndexValues(IProperty property, string? culture,
string? segment, bool published, IEnumerable<string> availableCultures,
IDictionary<Guid, IContentType> contentTypeDictionary) => GetIndexValues(property, culture, segment, published);
[Obsolete("Use non-obsolete overload, scheduled for removal in v14")]
IEnumerable<KeyValuePair<string, IEnumerable<object?>>> GetIndexValues(IProperty property, string? culture, string? segment, bool published, IEnumerable<string> availableCultures)
=> GetIndexValues(property, culture, segment, published);
[Obsolete("Use non-obsolete overload, scheduled for removal in v14")]
IEnumerable<KeyValuePair<string, IEnumerable<object?>>> GetIndexValues(IProperty property, string? culture, string? segment, bool published);
}
@@ -1,5 +0,0 @@
namespace Umbraco.Cms.Core.PropertyEditors;
public interface ITagPropertyIndexValueFactory : IPropertyIndexValueFactory
{
}
@@ -1,159 +0,0 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Serialization;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Web.Common.DependencyInjection;
using Umbraco.Extensions;
namespace Umbraco.Cms.Core.PropertyEditors;
/// <summary>
/// Abstract base for property index value factories where the value is json.
/// </summary>
/// <typeparam name="TSerialized">The type to deserialize the json to.</typeparam>
public abstract class JsonPropertyIndexValueFactoryBase<TSerialized> : IPropertyIndexValueFactory
{
private readonly IJsonSerializer _jsonSerializer;
private IndexingSettings _indexingSettings;
protected bool ForceExplicitlyIndexEachNestedProperty { get; set; }
/// <summary>
/// Constructor for the JsonPropertyIndexValueFactoryBase.
/// </summary>
protected JsonPropertyIndexValueFactoryBase(IJsonSerializer jsonSerializer, IOptionsMonitor<IndexingSettings> indexingSettings)
{
_jsonSerializer = jsonSerializer;
_indexingSettings = indexingSettings.CurrentValue;
indexingSettings.OnChange(newValue => _indexingSettings = newValue);
}
/// <summary>
/// Constructor for the JsonPropertyIndexValueFactoryBase.
/// </summary>
[Obsolete("Use non-obsolete constructor. This will be removed in Umbraco 14.")]
protected JsonPropertyIndexValueFactoryBase(IJsonSerializer jsonSerializer): this(jsonSerializer, StaticServiceProvider.Instance.GetRequiredService<IOptionsMonitor<IndexingSettings>>())
{
}
public IEnumerable<KeyValuePair<string, IEnumerable<object?>>> GetIndexValues(
IProperty property,
string? culture,
string? segment,
bool published,
IEnumerable<string> availableCultures,
IDictionary<Guid, IContentType> contentTypeDictionary)
{
var result = new List<KeyValuePair<string, IEnumerable<object?>>>();
var propertyValue = property.GetValue(culture, segment, published);
// If there is a value, it's a string and it's detected as json.
if (propertyValue is string rawValue && rawValue.DetectIsJson())
{
try
{
TSerialized? deserializedPropertyValue = _jsonSerializer.Deserialize<TSerialized>(rawValue);
if (deserializedPropertyValue is null)
{
return result;
}
result.AddRange(Handle(deserializedPropertyValue, property, culture, segment, published, availableCultures, contentTypeDictionary));
}
catch (InvalidCastException)
{
// Swallow...on purpose, there's a chance that this isn't the json format we are looking for
// and we don't want that to affect the website.
}
catch (ArgumentException)
{
// Swallow on purpose to prevent this error:
// Can not add Newtonsoft.Json.Linq.JValue to Newtonsoft.Json.Linq.JObject.
}
}
IEnumerable<KeyValuePair<string, IEnumerable<object?>>> summary = HandleResume(result, property, culture, segment, published);
if (_indexingSettings.ExplicitlyIndexEachNestedProperty || ForceExplicitlyIndexEachNestedProperty)
{
result.AddRange(summary);
return result;
}
return summary;
}
/// <inheritdoc />
[Obsolete("Use non-obsolete constructor. This will be removed in Umbraco 14.")]
public IEnumerable<KeyValuePair<string, IEnumerable<object?>>> GetIndexValues(
IProperty property,
string? culture,
string? segment,
bool published,
IEnumerable<string> availableCultures)
=> GetIndexValues(
property,
culture,
segment,
published,
Enumerable.Empty<string>(),
StaticServiceProvider.Instance.GetRequiredService<IContentTypeService>().GetAll().ToDictionary(x=>x.Key));
[Obsolete("Use method overload that has availableCultures, scheduled for removal in v14")]
public IEnumerable<KeyValuePair<string, IEnumerable<object?>>> GetIndexValues(IProperty property, string? culture, string? segment, bool published)
=> GetIndexValues(
property,
culture,
segment,
published,
Enumerable.Empty<string>(),
StaticServiceProvider.Instance.GetRequiredService<IContentTypeService>().GetAll().ToDictionary(x=>x.Key));
/// <summary>
/// Method to return a list of summary of the content. By default this returns an empty list
/// </summary>
protected virtual IEnumerable<KeyValuePair<string, IEnumerable<object?>>> HandleResume(
List<KeyValuePair<string, IEnumerable<object?>>> result,
IProperty property,
string? culture,
string? segment,
bool published) => Array.Empty<KeyValuePair<string, IEnumerable<object?>>>();
/// <summary>
/// Method that handle the deserialized object.
/// </summary>
[Obsolete("Use the non-obsolete overload instead, scheduled for removal in v14")]
protected abstract IEnumerable<KeyValuePair<string, IEnumerable<object?>>> Handle(
TSerialized deserializedPropertyValue,
IProperty property,
string? culture,
string? segment,
bool published);
[Obsolete("Use the non-obsolete overload instead, scheduled for removal in v14")]
protected virtual IEnumerable<KeyValuePair<string, IEnumerable<object?>>> Handle(
TSerialized deserializedPropertyValue,
IProperty property,
string? culture,
string? segment,
bool published,
IEnumerable<string> availableCultures) => Handle(deserializedPropertyValue, property, culture, segment, published);
/// <summary>
/// Method that handle the deserialized object.
/// </summary>
protected virtual IEnumerable<KeyValuePair<string, IEnumerable<object?>>> Handle(
TSerialized deserializedPropertyValue,
IProperty property,
string? culture,
string? segment,
bool published,
IEnumerable<string> availableCultures,
IDictionary<Guid, IContentType> contentTypeDictionary)
=> Handle(deserializedPropertyValue, property, culture, segment, published, availableCultures);
}
@@ -1,39 +0,0 @@
using Umbraco.Cms.Core.IO;
using Umbraco.Cms.Core.Models.Editors;
using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Core.Serialization;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Strings;
using Umbraco.Extensions;
namespace Umbraco.Cms.Core.PropertyEditors;
/// <summary>
/// A custom value editor to ensure that macro syntax is parsed when being persisted and formatted correctly for
/// display in the editor
/// </summary>
internal class MarkDownPropertyValueEditor : DataValueEditor
{
private readonly IMarkdownSanitizer _markdownSanitizer;
public MarkDownPropertyValueEditor(
ILocalizedTextService localizedTextService,
IShortStringHelper shortStringHelper,
IJsonSerializer jsonSerializer,
IIOHelper ioHelper,
DataEditorAttribute attribute,
IMarkdownSanitizer markdownSanitizer)
: base(localizedTextService, shortStringHelper, jsonSerializer, ioHelper, attribute) => _markdownSanitizer = markdownSanitizer;
public override object? FromEditor(ContentPropertyData editorValue, object? currentValue)
{
if (string.IsNullOrWhiteSpace(editorValue.Value?.ToString()))
{
return null;
}
var sanitized = _markdownSanitizer.Sanitize(editorValue.Value.ToString()!);
return sanitized.NullOrWhiteSpaceAsNull();
}
}
@@ -3,7 +3,6 @@
using Microsoft.Extensions.DependencyInjection;
using Umbraco.Cms.Core.IO;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Web.Common.DependencyInjection;
@@ -51,11 +50,4 @@ public class MarkdownPropertyEditor : DataEditor
/// <inheritdoc />
protected override IConfigurationEditor CreateConfigurationEditor() =>
new MarkdownConfigurationEditor(_ioHelper, _editorConfigurationParser);
/// <summary>
/// Create a custom value editor
/// </summary>
/// <returns></returns>
protected override IDataValueEditor CreateValueEditor() =>
DataValueEditorFactory.Create<MarkDownPropertyValueEditor>(Attribute!);
}
@@ -1,22 +0,0 @@
using Umbraco.Cms.Core.Models;
namespace Umbraco.Cms.Core.PropertyEditors;
/// <summary>
/// Property Index Valye Factory that do not index anything.
/// </summary>
public class NoopPropertyIndexValueFactory : IPropertyIndexValueFactory
{
/// <inheritdoc />
public IEnumerable<KeyValuePair<string, IEnumerable<object?>>> GetIndexValues(IProperty property, string? culture, string? segment, bool published,
IEnumerable<string> availableCultures, IDictionary<Guid, IContentType> contentTypeDictionary)
=> Array.Empty<KeyValuePair<string, IEnumerable<object?>>>();
[Obsolete("Use the overload with the availableCultures parameter instead, scheduled for removal in v14")]
public IEnumerable<KeyValuePair<string, IEnumerable<object?>>> GetIndexValues(IProperty property, string? culture, string? segment, bool published, IEnumerable<string> availableCultures) => Array.Empty<KeyValuePair<string, IEnumerable<object?>>>();
[Obsolete("Use the overload with the availableCultures parameter instead, scheduled for removal in v14")]
public IEnumerable<KeyValuePair<string, IEnumerable<object?>>> GetIndexValues(IProperty property, string? culture, string? segment, bool published)
=> GetIndexValues(property, culture, segment, published);
}
@@ -14,12 +14,12 @@ public class SliderConfiguration
[ConfigurationField("initVal2", "Initial value 2", "number", Description = "Used when range is enabled")]
public decimal InitialValue2 { get; set; }
[ConfigurationField("minVal", "Minimum value", "number", Description = "Must be smaller than the Maximum value")]
[ConfigurationField("minVal", "Minimum value", "number")]
public decimal MinimumValue { get; set; }
[ConfigurationField("maxVal", "Maximum value", "number", Description = "Must be larger than the Minimum value")]
[ConfigurationField("maxVal", "Maximum value", "number")]
public decimal MaximumValue { get; set; }
[ConfigurationField("step", "Step increments", "number", Description = "Must be a positive value")]
[ConfigurationField("step", "Step increments", "number")]
public decimal StepIncrements { get; set; }
}
@@ -25,19 +25,4 @@ public class SliderConfigurationEditor : ConfigurationEditor<SliderConfiguration
ioHelper, editorConfigurationParser)
{
}
public override Dictionary<string, object> ToConfigurationEditor(SliderConfiguration? configuration)
{
// negative step increments can be configured in the back-office. they will cause the slider to
// crash the entire back-office. as we can't configure min and max values for the number prevalue
// editor, we have to this instead to limit the damage.
// logically, the step increments should be inverted instead of hardcoding them to 1, but the
// latter might point people in the direction of their misconfiguration.
if (configuration?.StepIncrements <= 0)
{
configuration.StepIncrements = 1;
}
return base.ToConfigurationEditor(configuration);
}
}
@@ -1,48 +0,0 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Serialization;
using Umbraco.Cms.Web.Common.DependencyInjection;
namespace Umbraco.Cms.Core.PropertyEditors;
public class TagPropertyIndexValueFactory : JsonPropertyIndexValueFactoryBase<string[]>, ITagPropertyIndexValueFactory
{
public TagPropertyIndexValueFactory(
IJsonSerializer jsonSerializer,
IOptionsMonitor<IndexingSettings> indexingSettings)
: base(jsonSerializer, indexingSettings)
{
ForceExplicitlyIndexEachNestedProperty = true;
}
[Obsolete("Use non-obsolete constructor. This will be removed in Umbraco 14.")]
public TagPropertyIndexValueFactory(IJsonSerializer jsonSerializer)
: this(jsonSerializer, StaticServiceProvider.Instance.GetRequiredService<IOptionsMonitor<IndexingSettings>>())
{
}
protected override IEnumerable<KeyValuePair<string, IEnumerable<object?>>> Handle(
string[] deserializedPropertyValue,
IProperty property,
string? culture,
string? segment,
bool published,
IEnumerable<string> availableCultures)
{
yield return new KeyValuePair<string, IEnumerable<object?>>(property.Alias, deserializedPropertyValue);
}
[Obsolete("Use the overload that specifies availableCultures, scheduled for removal in v14")]
protected override IEnumerable<KeyValuePair<string, IEnumerable<object?>>> Handle(
string[] deserializedPropertyValue,
IProperty property,
string? culture,
string? segment,
bool published)
{
yield return new KeyValuePair<string, IEnumerable<object?>>(property.Alias, deserializedPropertyValue);
}
}
@@ -5,7 +5,7 @@ using Umbraco.Extensions;
namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters;
public class ContentPickerValueConverter : PropertyValueConverterBase
internal class ContentPickerValueConverter : PropertyValueConverterBase
{
private static readonly List<string> PropertiesToExclude = new()
{
@@ -1,4 +1,4 @@
using System.Globalization;
using System.Collections.Concurrent;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Models.PublishedContent;
using Umbraco.Cms.Core.Services;
@@ -6,123 +6,74 @@ using Umbraco.Extensions;
namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters;
/// <summary>
/// The slider property value converter.
/// </summary>
/// <seealso cref="Umbraco.Cms.Core.PropertyEditors.PropertyValueConverterBase" />
[DefaultPropertyValueConverter]
public class SliderValueConverter : PropertyValueConverterBase
{
/// <summary>
/// Initializes a new instance of the <see cref="SliderValueConverter" /> class.
/// </summary>
public SliderValueConverter()
{ }
private static readonly ConcurrentDictionary<int, bool> Storages = new();
private readonly IDataTypeService _dataTypeService;
/// <summary>
/// Initializes a new instance of the <see cref="SliderValueConverter" /> class.
/// </summary>
/// <param name="dataTypeService">The data type service.</param>
[Obsolete("The IDataTypeService is not used anymore. This constructor will be removed in a future version.")]
public SliderValueConverter(IDataTypeService dataTypeService)
{ }
public SliderValueConverter(IDataTypeService dataTypeService) => _dataTypeService =
dataTypeService ?? throw new ArgumentNullException(nameof(dataTypeService));
/// <summary>
/// Clears the data type configuration caches.
/// </summary>
[Obsolete("Caching of data type configuration is not done anymore. This method will be removed in a future version.")]
public static void ClearCaches()
{ }
public static void ClearCaches() => Storages.Clear();
/// <inheritdoc />
public override bool IsConverter(IPublishedPropertyType propertyType)
=> propertyType.EditorAlias.InvariantEquals(Constants.PropertyEditors.Aliases.Slider);
/// <inheritdoc />
public override Type GetPropertyValueType(IPublishedPropertyType propertyType)
=> IsRange(propertyType) ? typeof(Range<decimal>) : typeof(decimal);
=> IsRangeDataType(propertyType.DataType.Id) ? typeof(Range<decimal>) : typeof(decimal);
/// <inheritdoc />
public override PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType)
=> PropertyCacheLevel.Element;
/// <inheritdoc />
public override object? ConvertIntermediateToObject(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel cacheLevel, object? source, bool preview)
{
bool isRange = IsRange(propertyType);
var sourceString = source?.ToString();
return isRange
? HandleRange(sourceString)
: HandleDecimal(sourceString);
}
private static Range<decimal> HandleRange(string? sourceString)
{
if (sourceString is null)
if (source == null)
{
return new Range<decimal>();
return null;
}
string[] rangeRawValues = sourceString.Split(Constants.CharArrays.Comma);
if (TryParseDecimal(rangeRawValues[0], out var minimum))
if (IsRangeDataType(propertyType.DataType.Id))
{
if (rangeRawValues.Length == 1)
{
// Configuration is probably changed from single to range, return range with same min/max
return new Range<decimal>
{
Minimum = minimum,
Maximum = minimum
};
}
var rangeRawValues = source.ToString()!.Split(Constants.CharArrays.Comma);
Attempt<decimal> minimumAttempt = rangeRawValues[0].TryConvertTo<decimal>();
Attempt<decimal> maximumAttempt = rangeRawValues[1].TryConvertTo<decimal>();
if (rangeRawValues.Length == 2 && TryParseDecimal(rangeRawValues[1], out var maximum))
if (minimumAttempt.Success && maximumAttempt.Success)
{
return new Range<decimal>
{
Minimum = minimum,
Maximum = maximum
};
return new Range<decimal> { Maximum = maximumAttempt.Result, Minimum = minimumAttempt.Result };
}
}
return new Range<decimal>();
}
private static decimal HandleDecimal(string? sourceString)
{
if (string.IsNullOrEmpty(sourceString))
Attempt<decimal> valueAttempt = source.ToString().TryConvertTo<decimal>();
if (valueAttempt.Success)
{
return default;
return valueAttempt.Result;
}
// This used to be a range slider, so we'll assign the minimum value as the new value
if (sourceString.Contains(','))
{
var minimumValueRepresentation = sourceString.Split(Constants.CharArrays.Comma)[0];
if (TryParseDecimal(minimumValueRepresentation, out var minimum))
{
return minimum;
}
}
else if (TryParseDecimal(sourceString, out var value))
{
return value;
}
return default;
// Something failed in the conversion of the strings to decimals
return null;
}
/// <summary>
/// Helper method for parsing a double consistently
/// Discovers if the slider is set to range mode.
/// </summary>
private static bool TryParseDecimal(string? representation, out decimal value)
=> decimal.TryParse(representation, NumberStyles.Number, CultureInfo.InvariantCulture, out value);
/// <param name="dataTypeId">
/// The data type id.
/// </param>
/// <returns>
/// The <see cref="bool" />.
/// </returns>
private bool IsRangeDataType(int dataTypeId) =>
private static bool IsRange(IPublishedPropertyType propertyType)
=> propertyType.DataType.ConfigurationAs<SliderConfiguration>()?.EnableRange == true;
// GetPreValuesCollectionByDataTypeId is cached at repository level;
// still, the collection is deep-cloned so this is kinda expensive,
// better to cache here + trigger refresh in DataTypeCacheRefresher
// TODO: this is cheap now, remove the caching
Storages.GetOrAdd(dataTypeId, id =>
{
IDataType? dataType = _dataTypeService.GetDataType(id);
SliderConfiguration? configuration = dataType?.ConfigurationAs<SliderConfiguration>();
return configuration?.EnableRange ?? false;
});
}
@@ -1,3 +1,4 @@
using System.Collections.Concurrent;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Models.PublishedContent;
using Umbraco.Cms.Core.Serialization;
@@ -6,66 +7,69 @@ using Umbraco.Extensions;
namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters;
/// <summary>
/// The tags property value converter.
/// </summary>
/// <seealso cref="Umbraco.Cms.Core.PropertyEditors.PropertyValueConverterBase" />
[DefaultPropertyValueConverter]
public class TagsValueConverter : PropertyValueConverterBase
{
private static readonly ConcurrentDictionary<int, bool> Storages = new();
private readonly IDataTypeService _dataTypeService;
private readonly IJsonSerializer _jsonSerializer;
/// <summary>
/// Initializes a new instance of the <see cref="TagsValueConverter" /> class.
/// </summary>
/// <param name="jsonSerializer">The JSON serializer.</param>
/// <exception cref="System.ArgumentNullException">jsonSerializer</exception>
public TagsValueConverter(IJsonSerializer jsonSerializer)
=> _jsonSerializer = jsonSerializer ?? throw new ArgumentNullException(nameof(jsonSerializer));
/// <summary>
/// Initializes a new instance of the <see cref="TagsValueConverter" /> class.
/// </summary>
/// <param name="dataTypeService">The data type service.</param>
/// <param name="jsonSerializer">The JSON serializer.</param>
[Obsolete("The IDataTypeService is not used anymore. This constructor will be removed in a future version.")]
public TagsValueConverter(IDataTypeService dataTypeService, IJsonSerializer jsonSerializer)
: this(jsonSerializer)
{ }
{
_dataTypeService = dataTypeService ?? throw new ArgumentNullException(nameof(dataTypeService));
_jsonSerializer = jsonSerializer ?? throw new ArgumentNullException(nameof(jsonSerializer));
}
/// <summary>
/// Clears the data type configuration caches.
/// </summary>
[Obsolete("Caching of data type configuration is not done anymore. This method will be removed in a future version.")]
public static void ClearCaches()
{ }
public static void ClearCaches() => Storages.Clear();
/// <inheritdoc />
public override bool IsConverter(IPublishedPropertyType propertyType)
=> propertyType.EditorAlias.InvariantEquals(Constants.PropertyEditors.Aliases.Tags);
/// <inheritdoc />
public override Type GetPropertyValueType(IPublishedPropertyType propertyType)
=> typeof(IEnumerable<string>);
/// <inheritdoc />
public override PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType)
=> PropertyCacheLevel.Element;
/// <inheritdoc />
public override object? ConvertSourceToIntermediate(IPublishedElement owner, IPublishedPropertyType propertyType, object? source, bool preview)
{
string? sourceString = source?.ToString();
if (string.IsNullOrEmpty(sourceString))
if (source == null)
{
return Array.Empty<string>();
}
return IsJson(propertyType)
? _jsonSerializer.Deserialize<string[]>(sourceString) ?? Array.Empty<string>()
: sourceString.Split(Constants.CharArrays.Comma, StringSplitOptions.RemoveEmptyEntries);
// if Json storage type deserialize and return as string array
if (JsonStorageType(propertyType.DataType.Id))
{
var array = source.ToString() is not null
? _jsonSerializer.Deserialize<string[]>(source.ToString()!)
: null;
return array ?? Array.Empty<string>();
}
// Otherwise assume CSV storage type and return as string array
return source.ToString()?.Split(Constants.CharArrays.Comma, StringSplitOptions.RemoveEmptyEntries);
}
private static bool IsJson(IPublishedPropertyType propertyType)
=> propertyType.DataType.ConfigurationAs<TagConfiguration>()?.StorageType == TagsStorageType.Json;
public override object? ConvertIntermediateToObject(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel cacheLevel, object? source, bool preview) => (string[]?)source;
/// <summary>
/// Discovers if the tags data type is storing its data in a Json format
/// </summary>
/// <param name="dataTypeId">
/// The data type id.
/// </param>
/// <returns>
/// The <see cref="bool" />.
/// </returns>
private bool JsonStorageType(int dataTypeId) =>
// GetDataType(id) is cached at repository level; still, there is some
// deep-cloning involved (expensive) - better cache here + trigger
// refresh in DataTypeCacheRefresher
Storages.GetOrAdd(dataTypeId, id =>
{
TagConfiguration? configuration = _dataTypeService.GetDataType(id)?.ConfigurationAs<TagConfiguration>();
return configuration?.StorageType == TagsStorageType.Json;
});
}

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