Browse Source

Merge branch 'release/4.x'

# Conflicts:
#	backend/src/Squidex.Domain.Apps.Core.Model/Apps/AppPatterns.cs
#	backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/ContentWrapper/ContentFieldObject.cs
#	backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/ScriptOperations.cs
#	backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/JsonValueConverter.cs
#	backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/StatusSerializer.cs
#	backend/src/Squidex.Domain.Apps.Entities.MongoDb/Rules/MongoRuleEventRepository.cs
#	backend/src/Squidex.Domain.Apps.Entities/Apps/AppDomainObject.cs
#	backend/src/Squidex.Domain.Apps.Entities/Apps/Plans/IAppPlanBillingManager.cs
#	backend/src/Squidex.Domain.Apps.Entities/Apps/Plans/NoopAppPlanBillingManager.cs
#	backend/src/Squidex.Domain.Apps.Entities/Assets/AssetDomainObject.cs
#	backend/src/Squidex.Domain.Apps.Entities/Contents/BulkUpdateCommandMiddleware.cs
#	backend/src/Squidex.Domain.Apps.Entities/Contents/ContentDomainObject.cs
#	backend/src/Squidex.Domain.Apps.Entities/Contents/ContentOperationContext.cs
#	backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/ContentEnricher.cs
#	backend/src/Squidex.Domain.Apps.Entities/Contents/Text/Lucene/Storage/AssetIndexStorage.cs
#	backend/src/Squidex.Domain.Apps.Entities/Rules/RuleDomainObject.cs
#	backend/src/Squidex.Domain.Apps.Entities/Schemas/Commands/IUpsertCommand.cs
#	backend/src/Squidex.Domain.Apps.Entities/Schemas/Guards/GuardSchema.cs
#	backend/src/Squidex.Domain.Apps.Entities/Schemas/SchemaDomainObject.cs
#	backend/src/Squidex.Infrastructure.MongoDb/MongoDb/InstantSerializer.cs
#	backend/src/Squidex.Infrastructure.MongoDb/MongoDb/RefTokenSerializer.cs
#	backend/src/Squidex.Infrastructure/Commands/DomainObjectBase.cs
#	backend/src/Squidex.Infrastructure/Commands/DomainObjectGrain.cs
#	backend/src/Squidex/Areas/Api/Controllers/Assets/AssetContentController.cs
#	backend/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/AppPatternJsonTests.cs
#	backend/tests/Squidex.Domain.Apps.Core.Tests/Model/Contents/WorkflowsJsonTests.cs
#	backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/ReferencesFieldTests.cs
#	backend/tests/Squidex.Domain.Apps.Entities.Tests/Apps/AppCommandMiddlewareTests.cs
#	backend/tests/Squidex.Domain.Apps.Entities.Tests/Apps/AppDomainObjectTests.cs
#	backend/tests/Squidex.Domain.Apps.Entities.Tests/Apps/Plans/UsageGateTests.cs
#	backend/tests/Squidex.Domain.Apps.Entities.Tests/Assets/AssetCommandMiddlewareTests.cs
#	backend/tests/Squidex.Domain.Apps.Entities.Tests/Assets/AssetDomainObjectTests.cs
#	backend/tests/Squidex.Domain.Apps.Entities.Tests/Rules/Guards/Triggers/UsageTriggerValidationTests.cs
pull/568/head
Sebastian 5 years ago
parent
commit
8e088beb1c
  1. 853
      backend/i18n/frontend_en.json
  2. 853
      backend/i18n/frontend_nl.json
  3. 472
      backend/i18n/source/backend__ignore.json
  4. 20
      backend/i18n/source/backend__todos.json
  5. 325
      backend/i18n/source/backend_en.json
  6. 325
      backend/i18n/source/backend_nl.json
  7. 217
      backend/i18n/source/frontend__ignore.json
  8. 1
      backend/i18n/source/frontend__todos.json
  9. 853
      backend/i18n/source/frontend_en.json
  10. 848
      backend/i18n/source/frontend_nl.json
  11. 7
      backend/i18n/translate.bat
  12. 10
      backend/i18n/translate.sh
  13. 25
      backend/i18n/translator/Squidex.Translator.sln
  14. 153
      backend/i18n/translator/Squidex.Translator/Commands.cs
  15. 24
      backend/i18n/translator/Squidex.Translator/Extensions.cs
  16. 57
      backend/i18n/translator/Squidex.Translator/Processes/Backend.cs
  17. 57
      backend/i18n/translator/Squidex.Translator/Processes/CheckBackend.cs
  18. 121
      backend/i18n/translator/Squidex.Translator/Processes/CheckFrontend.cs
  19. 46
      backend/i18n/translator/Squidex.Translator/Processes/Frontend.cs
  20. 58
      backend/i18n/translator/Squidex.Translator/Processes/GenerateBackendResources.cs
  21. 44
      backend/i18n/translator/Squidex.Translator/Processes/GenerateFrontendResources.cs
  22. 47
      backend/i18n/translator/Squidex.Translator/Processes/GenerateKeys.cs
  23. 143
      backend/i18n/translator/Squidex.Translator/Processes/Helper.cs
  24. 64
      backend/i18n/translator/Squidex.Translator/Processes/TranslateBackend.cs
  25. 212
      backend/i18n/translator/Squidex.Translator/Processes/TranslateTemplates.cs
  26. 64
      backend/i18n/translator/Squidex.Translator/Processes/TranslateTypescript.cs
  27. 33
      backend/i18n/translator/Squidex.Translator/Program.cs
  28. 27
      backend/i18n/translator/Squidex.Translator/Squidex.Translator.csproj
  29. 18
      backend/i18n/translator/Squidex.Translator/State/Old/OldTranslatedText.cs
  30. 20
      backend/i18n/translator/Squidex.Translator/State/Old/OldTranslationState.cs
  31. 16
      backend/i18n/translator/Squidex.Translator/State/Old/TextOrigin.cs
  32. 23
      backend/i18n/translator/Squidex.Translator/State/TranslatedTexts.cs
  33. 331
      backend/i18n/translator/Squidex.Translator/State/TranslationService.cs
  34. 15
      backend/i18n/translator/Squidex.Translator/State/TranslationTodos.cs
  35. 15
      backend/i18n/translator/Squidex.Translator/State/TranslationsToIgnore.cs
  36. 30
      backend/src/Migrations/OldEvents/AppClientRenamed.cs
  37. 28
      backend/src/Squidex.Domain.Apps.Core.Model/Apps/AppClient.cs
  38. 19
      backend/src/Squidex.Domain.Apps.Core.Model/Apps/AppClients.cs
  39. 4
      backend/src/Squidex.Domain.Apps.Core.Model/Apps/AppPattern.cs
  40. 5
      backend/src/Squidex.Domain.Apps.Core.Model/Apps/AppPatterns.cs
  41. 11
      backend/src/Squidex.Domain.Apps.Core.Model/Apps/Json/AppClientsConverter.cs
  42. 38
      backend/src/Squidex.Domain.Apps.Core.Model/Apps/Json/JsonAppClient.cs
  43. 4
      backend/src/Squidex.Domain.Apps.Core.Model/Comments/Comment.cs
  44. 2
      backend/src/Squidex.Domain.Apps.Core.Model/Contents/Workflow.cs
  45. 2
      backend/src/Squidex.Domain.Apps.Core.Model/Schemas/FieldNames.cs
  46. 43
      backend/src/Squidex.Domain.Apps.Core.Model/Schemas/FieldRule.cs
  47. 16
      backend/src/Squidex.Domain.Apps.Core.Model/Schemas/FieldRuleAction.cs
  48. 30
      backend/src/Squidex.Domain.Apps.Core.Model/Schemas/FieldRules.cs
  49. 8
      backend/src/Squidex.Domain.Apps.Core.Model/Schemas/Json/JsonSchemaModel.cs
  50. 28
      backend/src/Squidex.Domain.Apps.Core.Model/Schemas/Schema.cs
  51. 7
      backend/src/Squidex.Domain.Apps.Core.Model/Schemas/SchemaExtensions.cs
  52. 5
      backend/src/Squidex.Domain.Apps.Core.Operations/EventSynchronization/SchemaSynchronizer.cs
  53. 1
      backend/src/Squidex.Domain.Apps.Core.Operations/GenerateEdmSchema/EdmSchemaExtensions.cs
  54. 2
      backend/src/Squidex.Domain.Apps.Core.Operations/GenerateEdmSchema/EdmTypeVisitor.cs
  55. 3
      backend/src/Squidex.Domain.Apps.Core.Operations/GenerateJsonSchema/ContentSchemaBuilder.cs
  56. 3
      backend/src/Squidex.Domain.Apps.Core.Operations/GenerateJsonSchema/JsonSchemaExtensions.cs
  57. 8
      backend/src/Squidex.Domain.Apps.Core.Operations/GenerateJsonSchema/JsonTypeVisitor.cs
  58. 22
      backend/src/Squidex.Domain.Apps.Core.Operations/GenerateJsonSchema/SchemaBuilder.cs
  59. 1
      backend/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleEventFormatter.cs
  60. 2
      backend/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleRegistry.cs
  61. 35
      backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/ContentWrapper/ContentDataObject.cs
  62. 2
      backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/ContentWrapper/ContentDataProperty.cs
  63. 45
      backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/ContentWrapper/ContentFieldObject.cs
  64. 6
      backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/ContentWrapper/JsonMapper.cs
  65. 2
      backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/ExecutionContext.cs
  66. 9
      backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/Extensions/HttpJintExtension.cs
  67. 2
      backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/Extensions/StringJintExtension.cs
  68. 5
      backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/Extensions/StringWordsJintExtension.cs
  69. 10
      backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/Internal/Parser.cs
  70. 9
      backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/JintScriptEngine.cs
  71. 9
      backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/ScriptOperations.cs
  72. 2
      backend/src/Squidex.Domain.Apps.Core.Operations/Squidex.Domain.Apps.Core.Operations.csproj
  73. 2
      backend/src/Squidex.Domain.Apps.Core.Operations/Templates/Extensions/StringFluidExtension.cs
  74. 5
      backend/src/Squidex.Domain.Apps.Core.Operations/Templates/Extensions/StringWordsFluidExtension.cs
  75. 4
      backend/src/Squidex.Domain.Apps.Core.Operations/Templates/TemplateParseException.cs
  76. 40
      backend/src/Squidex.Domain.Apps.Core.Operations/TextHelpers.cs
  77. 31
      backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/JsonValueConverter.cs
  78. 15
      backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/AllowedValuesValidator.cs
  79. 23
      backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/AssetsValidator.cs
  80. 13
      backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/CollectionValidator.cs
  81. 5
      backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/FieldValidator.cs
  82. 5
      backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/NoValueValidator.cs
  83. 5
      backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/ObjectValidator.cs
  84. 7
      backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/PatternValidator.cs
  85. 21
      backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/RangeValidator.cs
  86. 7
      backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/ReferencesValidator.cs
  87. 5
      backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/RequiredStringValidator.cs
  88. 5
      backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/RequiredValidator.cs
  89. 11
      backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/StringLengthValidator.cs
  90. 5
      backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/UniqueValidator.cs
  91. 9
      backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/UniqueValuesValidator.cs
  92. 5
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetRepository.cs
  93. 2
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/Visitors/FirstPascalPathExtension.cs
  94. 18
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Operations/Adapt.cs
  95. 21
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Operations/QueryContentsByQuery.cs
  96. 9
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/StatusSerializer.cs
  97. 30
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Rules/MongoRuleEventRepository.cs
  98. 5
      backend/src/Squidex.Domain.Apps.Entities/Apps/AppCommandMiddleware.cs
  99. 28
      backend/src/Squidex.Domain.Apps.Entities/Apps/AppDomainObject.cs
  100. 52
      backend/src/Squidex.Domain.Apps.Entities/Apps/AppHistoryEventsCreator.cs

853
backend/i18n/frontend_en.json

@ -0,0 +1,853 @@
{
"api.contentApi": "Content API",
"api.generalApi": "General API",
"api.graphql": "GraphQL",
"api.graphqlPageTitle": "GraphQL",
"api.pageTitle": "API",
"api.title": "API",
"apps.allApps": "All Apps",
"apps.appLoadFailed": "Failed to load app. Please reload.",
"apps.appNameHint": "You can only use letters, numbers and dashes and not more than 40 characters.",
"apps.appNameValidationMessage": "Name can contain lower case letters (a-z), numbers and dashes between.",
"apps.appNameWarning": "The app name cannot be changed later.",
"apps.appsButtonCreate": "Apps Overview",
"apps.appsButtonFallbackTitle": "Apps Overview",
"apps.archieve": "Archive App",
"apps.archieveConfirmText": "Remove pattern",
"apps.archieveConfirmTitle": "Do you really want to archive this app?",
"apps.archieveWarning": "Once you archive an app, there is no going back. Please be certain.",
"apps.archiveFailed": "Failed to archive app. Please reload.",
"apps.create": "Create App",
"apps.createBlankApp": "New App.",
"apps.createBlankAppDescription": "Create a new blank app without content and schemas.",
"apps.createBlogApp": "New Blog Sample",
"apps.createBlogAppDescription": "Start with our ready to use blog.",
"apps.createFailed": "Failed to create app. Please reload.",
"apps.createIdentityApp": "New Identity App",
"apps.createIdentityAppDescription": "Create app for Squidex Identity.",
"apps.createIdentityAppV2": "New Identity App V2",
"apps.createIdentityAppV2Description": "Create app for Squidex Identity V2.",
"apps.createProfileApp": "New Profile Sample",
"apps.createProfileAppDescription": "Create your profile page.",
"apps.createWithTemplate": "Create {template} Sample",
"apps.empty": "You are not collaborating to any app yet",
"apps.generalSettings": "General",
"apps.generalSettingsDangerZone": "General",
"apps.image": "Image",
"apps.imageDrop": "Drop to upload",
"apps.listPageTitle": "Apps",
"apps.loadFailed": "Failed to load apps. Please reload.",
"apps.removeImage": "Remove image",
"apps.removeImageFailed": "Failed to remove app image. Please reload.",
"apps.updateFailed": "Failed to update app. Please reload.",
"apps.upgradeHintCurrent": "You are on the {plan} plan.",
"apps.upgradeHintUpgrade": "Upgrade!",
"apps.uploadImage": "Drop an file to replace the app image. Use a square size.",
"apps.uploadImageButton": "Upload File",
"apps.uploadImageFailed": "Failed to upload image. Please reload.",
"apps.uploadImageTooBig": "App image is too big.",
"apps.welcomeSubtitle": "Welcome to Squidex.",
"apps.welcomeTitle": "Hi {user}",
"assets.createFolder": "Create Folder",
"assets.createFolderFailed": "Failed to create asset folder. Please reload.",
"assets.createFolderTooltip": "Create new folder (CTRL + SHIFT + G)",
"assets.deleteConfirmText": "Do you really want to delete the asset?",
"assets.deleteConfirmTitle": "Delete asset",
"assets.deleteFailed": "Failed to delete asset. Please reload.",
"assets.deleteFolderConfirmText": "Do you really want to delete the folder and all assets?",
"assets.deleteFolderConfirmTitle": "Delete folder",
"assets.deleteMetadataConfirmText": "Do you really want to remove this metadata?",
"assets.deleteMetadataConfirmTitle": "Remove metadata",
"assets.downloadVersion": "Download this Version",
"assets.dropToUpdate": "Drop to update",
"assets.duplicateFile": "Asset has already been uploaded.",
"assets.editor.flipHorizontally": "Flip Horizontally",
"assets.editor.flipVertically": "Flip Vertically",
"assets.editor.focusPointLabel": "Select position of focus point",
"assets.editor.focusPointPreview": "Preview for different sizes",
"assets.editor.rotateLeft": "Rotate Left",
"assets.editor.rotateRight": "Rotate Right",
"assets.fileTooBig": "Asset is too big.",
"assets.folderName": "Folder Name",
"assets.folderNameHint": "The folder name is used as display name and must not be unique.",
"assets.insertAssets": "Insert Assets",
"assets.linkSelected": "Link selected assets ({count})",
"assets.listPageTitle": "Assets",
"assets.loadFailed": "Failed to load assets. Please reload.",
"assets.loadFoldersFailed": "Failed to load asset folders. Please reload.",
"assets.metadata": "Metadata",
"assets.metadataAdd": "Add Metadata",
"assets.moveFailed": "Failed to move asset. Please reload.",
"assets.protected": "Protected",
"assets.refreshTooltip": "Refresh Assets (CTRL + SHIFT + R)",
"assets.reloaded": "Assets reloaded.",
"assets.renameFolder": "Rename Folder",
"assets.replaceConfirmText": "Do you really want to replace the asset with a newer version",
"assets.replaceConfirmTitle": "Replace asset?",
"assets.replaceFailed": "Failed to replace asset. Please reload.",
"assets.searchByName": "Search by name",
"assets.searchByTags": "Search by tags",
"assets.selectMany": "Select assets",
"assets.tabFocusPoint": "Focus Point",
"assets.tabHistory": "History",
"assets.tabImage": "Image",
"assets.tabMetadata": "Metadata",
"assets.updated": "Asset has been updated.",
"assets.updateFailed": "Failed to update asset. Please reload.",
"assets.updateFolderFailed": "Failed to update asset folder. Please reload.",
"assets.uploadByDialog": "Select File(s",
"assets.uploadByDrop": "Drop files here to upload",
"assets.uploaderUploadHere": "No upload in progress, drop files here.",
"assets.uploadFailed": "Failed to upload asset. Please reload.",
"assets.uploadHint": "Drop file on existing item to replace the asset with a newer version.",
"backups.backupCountAssetsLabel": "Assets",
"backups.backupCountAssetsTooltip": "Archived assets",
"backups.backupCountEventsLabel": "Events",
"backups.backupCountEventsTooltip": "Archived events",
"backups.backupDownload": "Download",
"backups.backupDownloadLink": "Ready",
"backups.backupDuration": "Duration",
"backups.deleteConfirmText": "Do you really want to delete the backup?",
"backups.deleteConfirmTitle": "Delete backup",
"backups.deleted": "Backup is about to be deleted.",
"backups.deleteFailed": "Failed to delete backup.",
"backups.empty": "No backups created yet.",
"backups.loadFailed": "Failed to load backups.",
"backups.maximumReached": "Your have reached the maximum number of backups: 10.",
"backups.refreshTooltip": "Refresh backups (CTRL + SHIFT + R)",
"backups.reloaded": "Backups reloaded.",
"backups.restore": "Restore Backup",
"backups.restoreFailed": "Failed to start restore.",
"backups.restoreLastStatus": "Last Restore Operation",
"backups.restoreLastUrl": "Url to backup",
"backups.restoreNewAppName": "Optional app name",
"backups.restorePageTitle": "Restore Backup",
"backups.restoreStarted": "Restore started, it can take several minutes to complete.",
"backups.restoreStartedLabel": "Started",
"backups.restoreStoppedLabel": "Stopped",
"backups.restoreTitle": "Restore Backup",
"backups.start": "Start Backup",
"backups.started": "Backup started, it can take several minutes to complete.",
"backups.startedLabel": "Started",
"backups.startFailed": "Failed to start backup.",
"clients.add": "Add Client",
"clients.addFailed": "Failed to add client. Please reload.",
"clients.allowAnonymous": "Allow anonymous access.",
"clients.allowAnonymousHint": "Allow access to the API without an access token to all resources that are configured via the role of this client. Do not give more than one client anonymous access.",
"clients.apiCallsLimit": "Max API Calls",
"clients.apiCallsLimitHint": "Limit the number of API calls this client can make per month to protect your API contingent for other clients that are more important.",
"clients.clientIdValidationMessage": "Name can only contain letters, numbers, dashes and spaces.",
"clients.clientNamePlaceholder": "Enter client name",
"clients.connect": "Connect",
"clients.connectWizard.cli": "Connect with Squidex CLI",
"clients.connectWizard.cliHint": "Download the CLI and connect to this app to start backups, sync schemas or export content.",
"clients.connectWizard.cliStep1": "Get the latest Squidex CLI",
"clients.connectWizard.cliStep1Download": "[Download the CLI from Github](https://github.com/Squidex/squidex-samples/releases)",
"clients.connectWizard.cliStep1Hint": "The releases contains binaries for all major operation system and a small download if you have .NET Core installed.",
"clients.connectWizard.cliStep2": "Add `<your Squidex CLI download directory>` to your `$PATH` variable",
"clients.connectWizard.cliStep3": "Add your app name the CLI config",
"clients.connectWizard.cliStep3Hint": "You can manage configuration to multiple apps in the CLI and switch to an app.",
"clients.connectWizard.cliStep4": "Switch to your app in the CLI",
"clients.connectWizard.manually": "Connect manually",
"clients.connectWizard.manuallyHint": "Get instructions how to establish a connection with Postman or curl.",
"clients.connectWizard.manuallyStep1": "Get a token using curl",
"clients.connectWizard.manuallyStep2": "Just use the following token",
"clients.connectWizard.manuallyStep3": "Add the token as HTTP header to all requests",
"clients.connectWizard.manuallyTokenHint": "Tokens usally expire after 30days, but you can request multiple tokens.",
"clients.connectWizard.postManDocs": "Start with the Postman tutorial in the [Documentation](https://docs.squidex.io/02-documentation/developer-guides/api-overview/postman).",
"clients.connectWizard.sdk": "Connect to your App with SDK",
"clients.connectWizard.sdkHelp": "You need another SDK?",
"clients.connectWizard.sdkHelpLink": "Contact us in the Support Forum",
"clients.connectWizard.sdkHint": "Download an SDK and establish a connection to this app.",
"clients.connectWizard.sdkStep1": "Install the .NET SDK",
"clients.connectWizard.sdkStep1Download": "The SDK is available on [nuget](https://www.nuget.org/packages/Squidex.ClientLibrary/)",
"clients.connectWizard.sdkStep2": "Create a client manager",
"clients.connectWizard.step0Title": "Setup client",
"clients.connectWizard.step1Title": "Choose connection method",
"clients.connectWizard.step2Title": "Connect",
"clients.deleteConfirmText": "Do you really want to revoke the client?",
"clients.deleteConfirmTitle": "Revoke client",
"clients.empty": "No client created yet.",
"clients.loadFailed": "Failed to load clients. Please reload.",
"clients.refreshTooltip": "Refresh clients (CTRL + SHIFT + R)",
"clients.reloaded": "Clients reloaded.",
"clients.revokeFailed": "Failed to revoke client. Please reload.",
"clients.tokenFailed": "Failed to create token. Please retry.",
"comments.create": "Create a comment",
"comments.createFailed": "Failed to create comment.",
"comments.deleteConfirmText": "Do you really want to delete the comment?",
"comments.deleteConfirmTitle": "Delete comment",
"comments.deleteFailed": "Failed to delete comment.",
"comments.follow": "Follow",
"comments.loadFailed": "Failed to load comments.",
"comments.title": "Comments",
"comments.updateFailed": "Failed to update comment.",
"common.actions": "Actions",
"common.administration": "Administration",
"common.administrationPageTitle": "Administration",
"common.api": "API",
"common.apps": "Apps",
"common.aspectRatio": "AspectRatio",
"common.assets": "Assets",
"common.back": "Back",
"common.backups": "Backups",
"common.bytes": "bytes",
"common.cancel": "Cancel",
"common.clear": "Clear",
"common.clientId": "Client Id",
"common.clients": "Clients",
"common.clientSecret": "Client Secret",
"common.clipboardAdded": "Value has been added to your clipboard.",
"common.clone": "Clone",
"common.cluster": "Cluster",
"common.clusterPageTitle": "Cluster",
"common.comments": "Comments",
"common.confirm": "Confirm",
"common.consumers": "Consumers",
"common.content": "Content",
"common.contents": "Contents",
"common.continue": "Continue",
"common.contributors": "Contributors",
"common.create": "Create",
"common.created": "Created",
"common.date": "Date",
"common.dateTimeEditor.local": "Local",
"common.dateTimeEditor.now": "Now",
"common.dateTimeEditor.nowTooltip": "Use Now (UTC)",
"common.dateTimeEditor.today": "Today",
"common.dateTimeEditor.todayTooltip": "Use Today (UTC)",
"common.dateTimeEditor.utc": "UTC",
"common.delete": "Delete",
"common.description": "Description",
"common.displayName": "Display Name",
"common.edit": "Edit",
"common.email": "Email",
"common.error": "Error",
"common.errorBack": "Back to previous page.",
"common.errorNoPermission": "You do not have the permissions to do this.",
"common.errorNotFound": "Not Found",
"common.event": "Event",
"common.events": "Events",
"common.executed": "Executed",
"common.expertMode": "Expert Mode",
"common.failed": "Failed",
"common.fallback": "Fallback",
"common.field": "Field",
"common.files": "Files",
"common.filters": "Filters",
"common.folders": "Folders",
"common.generalSettings": "Common",
"common.generate": "Generate",
"common.github": "Github",
"common.height": "Height",
"common.help": "Help",
"common.helpTour": "Click the help icon to show a context specific help page. Go to",
"common.hide": "Hide",
"common.hints": "Hints",
"common.history": "History",
"common.httpConflict": "Failed to make the update. Another user has made a change. Please reload.",
"common.httpLimit": "You have exceeded the maximum limit of API calls.",
"common.label": "Label",
"common.languages": "Languages",
"common.latitudeShort": "Lat",
"common.loading": "Loading",
"common.logout": "Logout",
"common.logs": "Logs",
"common.longitudeShort": "Lon",
"common.mapHide": "Hide map",
"common.mapShow": "Show map",
"common.message": "Message",
"common.name": "Name",
"common.no": "No",
"common.nothingChanged": "Nothing has been changed.",
"common.noValue": "- No value -",
"common.or": "or",
"common.pagerInfo": "{itemFirst}-{itemLast} of {numberOfItems}",
"common.password": "Password",
"common.passwordConfirm": "Confirm Password",
"common.pattern": "Pattern",
"common.patterns": "Patterns",
"common.permissions": "Permissions",
"common.preview": "Preview",
"common.product": "Squidex Headless CMS",
"common.project": "Project",
"common.refresh": "Refresh",
"common.rename": "Rename",
"common.requiredHint": "required",
"common.reset": "Reset",
"common.restore": "Restore",
"common.role": "Role",
"common.roles": "Roles",
"common.rules": "Rules",
"common.sampleCodeLabel": "Sample Code at",
"common.save": "Save",
"common.saveShortcut": "CTRL + S",
"common.schemas": "Schemas",
"common.searchGoogleMaps": "Search Google Maps",
"common.searchResults": "Search Results",
"common.separateByLine": "Separate by line",
"common.settings": "Settings",
"common.sidebarTour": "The sidebar navigation contains useful context specific links. Here you can view the history how this schema has changed over time.",
"common.slug": "Slug",
"common.stars.max": "Must not have more more than 15 stars",
"common.status": "Status",
"common.statusChangeTo": "Change to",
"common.submit": "Submit",
"common.subscription": "Subscription",
"common.succeeded": "Succeeded",
"common.tagAdd": ", to add tag",
"common.tagAddReference": ", to add reference",
"common.tagAddSchema": ", to add schema",
"common.tags": "Tags",
"common.tagsAll": "All tags",
"common.time": "Time",
"common.update": "Update",
"common.url": "URL",
"common.users": "Users",
"common.value": "Value",
"common.width": "Width",
"common.workflow": "Workflow",
"common.workflows": "Workflows",
"common.yes": "Yes",
"contents.arrayAddItem": "Add Item",
"contents.arrayCloneItem": "Clone this item",
"contents.arrayCollapseAll": "Collapse all items",
"contents.arrayCollapseItem": "Collapse this item",
"contents.arrayExpandAll": "Expand all items",
"contents.arrayExpandItem": "Expand this item",
"contents.arrayMoveBottom": "Move this item to bottom",
"contents.arrayMoveDown": "Move this item down",
"contents.arrayMoveTop": "Move this item to top",
"contents.arrayMoveUp": "Move this item up",
"contents.arrayNoFields": "Add a nested field first to add items.",
"contents.assetsUpload": "Drop files or click",
"contents.autotranslate": "Autotranslate from master language",
"contents.changeStatusTo": "Change content item(s) to {action}",
"contents.changeStatusToImmediately": "Set to {action} immediately.",
"contents.changeStatusToLater": "Set to {action} at a later point date and time.",
"contents.contentNotValid": "Content element not valid, please check the field with the red bar on the left in all languages (if localizable).",
"contents.create": "New",
"contents.createContentTooltip": "New Content (CTRL + SHIFT + G)",
"contents.created": "Content created successfully.",
"contents.createdByFieldDescription": "The user who created the content item.",
"contents.createFailed": "Failed to create content. Please reload.",
"contents.createFieldDescription": "The date time when the content item was created.",
"contents.createPageTitle": "Create Content",
"contents.createTitle": "New Content",
"contents.currentStatusLabel": "Current Version",
"contents.deleteConfirmText": "Do you really want to delete the content?",
"contents.deleteConfirmTitle": "Delete content",
"contents.deleteFailed": "Failed to delete content. Please reload.",
"contents.deleteManyConfirmText": "Do you really want to delete the selected content items?",
"contents.deleteVersionConfirmText": "Do you really want to delete this version?",
"contents.deleteVersionFailed": "Failed to delete version. Please reload.",
"contents.draftNew": "New Draft",
"contents.draftStatus": "New Version",
"contents.editPageTitle": "Edit Content",
"contents.editTitle": "Edit Content",
"contents.languageModeAll": "All Languages",
"contents.languageModeSingle": "Single Language",
"contents.lastModifiedByFieldDescription": "The user who modified the content item the last time.",
"contents.lastModifiedFieldDescription": "The date time when the content item was modified the last time.",
"contents.lastUpdatedLabel": "Last Updated",
"contents.loadContent": "Load",
"contents.loadContentFailed": "Failed to load content. Please reload.",
"contents.loadDataFailed": "Failed to load data. Please reload.",
"contents.loadFailed": "Failed to load contents. Please reload.",
"contents.loadVersionFailed": "Failed to version a new version. Please reload.",
"contents.newStatusFieldDescription": "The new status of the content item.",
"contents.noReference": "- No Reference -",
"contents.pendingChangesTextToChange": "You have unsaved changes.\n\nWhen you change the status you will loose them.\n\n**Do you want to continue anyway?**",
"contents.pendingChangesTextToClose": "You have unsaved changes.\n\nWhen you close the current content view you will loose them.\n\n**Do you want to continue anyway?**",
"contents.pendingChangesTitle": "Unsaved changes",
"contents.referencesCreateNew": "Add New",
"contents.referencesCreatePublish": "Create and Publish",
"contents.referencesLink": "Link selected contents ({count})",
"contents.referencesSelectExisting": "Select Existing",
"contents.referencesSelectSchema": "Select {schema}",
"contents.refreshTooltip": "Refresh Contents (CTRL + SHIFT + R)",
"contents.reloaded": "Contents reloaded.",
"contents.saveAndPublish": "Save and Publish",
"contents.scheduledAt": "at",
"contents.scheduledAtLabel": "at",
"contents.scheduledTo": "to",
"contents.schemasPageTitle": "Contents",
"contents.searchPlaceholder": "Fulltext search",
"contents.searchSchemasPlaceholder": "Search for schemas...",
"contents.selectionCount": "{count} items selected",
"contents.statusFieldDescription": "The status of the content item.",
"contents.statusQueries": "Status Queries",
"contents.stockPhotoEmpty": "Nothing selected",
"contents.stockPhotoSearch": "Search for Photos by Unsplash",
"contents.unsavedChangesText": "You have unsaved changes. Do you want to load them now?",
"contents.unsavedChangesTitle": "Unsaved changes",
"contents.updated": "Content updated successfully.",
"contents.updateFailed": "Failed to update content. Please reload.",
"contents.validationHint": "Please remember to check all languages when you see validation errors.",
"contents.versionCompare": "Compare",
"contents.versionDelete": "Delete this Version",
"contents.versionFieldDescription": "The version of the content item",
"contents.versionViewing": "Viewing version **{version}**.",
"contents.viewLatest": "View latest",
"contents.viewReset": "Reset Default View",
"contributors.add": "Add Contributor",
"contributors.addFailed": "Failed to add contributors. Please reload.",
"contributors.contributorAssigned": "A new user with the entered email address has been created and assigned as contributor.",
"contributors.contributorAssignedExisting": "User has been assigned",
"contributors.contributorAssignedInvited": "User has been invited and assigned.",
"contributors.contributorAssignedOld": "User has been added as contributor.",
"contributors.deleteConfirmText": "Do you really want to remove the contributor?",
"contributors.deleteConfirmTitle": "Remove contributor",
"contributors.deleteFailed": "Failed to delete contributors. Please reload.",
"contributors.emailPlaceholder": "Find existing user or invite by email",
"contributors.empty": "No contributors found.",
"contributors.import.emailsDetected": "Emails detected: {count}",
"contributors.import.run": "Add Contributors",
"contributors.import.run2": "Import",
"contributors.importButton": "Add many contributors at once",
"contributors.importHintg": "Big team?",
"contributors.importTitle": "Import contributors",
"contributors.loadFailed": "Failed to load contributors. Please reload.",
"contributors.planHint": "Your plan allows up to {maxContributors} contributors.",
"contributors.refreshTooltip": "Refresh contributors (CTRL + SHIFT + R)",
"contributors.reloaded": "Contributors reloaded.",
"contributors.search": "Search",
"contributors.userNotFound": "The user does not exist.",
"dashboard.apiCallsCard": "API Calls",
"dashboard.apiCallsChart": "API Calls Chart",
"dashboard.apiCallsLimitLabel": "Monthly limit",
"dashboard.apiCallsSummaryCard": "API Calls Summary",
"dashboard.apiDocumentationCard": "API Documentation",
"dashboard.apiPerformanceCard": "API Performance (ms): {summary}ms avg",
"dashboard.apiPerformanceChart": "API Performance Chart",
"dashboard.assetSizeCard": "Assets Size (MB",
"dashboard.assetSizeLabel": "Total Size",
"dashboard.assetSizeLimitLabel": "Total limit",
"dashboard.assetTotalSize": "Asset Total Storage Size",
"dashboard.assetUpdloadsCountChart": "Asset Uploads Count Chart",
"dashboard.assetUploadsCard": "Assets Uploads",
"dashboard.assetUploadsSizeChart": "Asset Uploads Size Chart",
"dashboard.configSaved": "Configuration saved.",
"dashboard.contentApi": "Content API",
"dashboard.contentApiDescription": "OpenAPI 3.0 compatible documentation for your app content.",
"dashboard.contentsSummaryCard": "Number of items",
"dashboard.currentMonthLabel": "This month",
"dashboard.downloadLog": "Download Log",
"dashboard.editConfig": "Edit Config",
"dashboard.githubCard": "Github",
"dashboard.githubCardDescription": "Get the source code from Github and report bugs or ask for support.",
"dashboard.historyCard": "History",
"dashboard.pageTitle": "Dashboard",
"dashboard.resetConfigConfirmText": "Do you really want to reset the dashboard to the default?",
"dashboard.resetConfigConfirmTitle": "Reset config",
"dashboard.schemaNewCard": "New Schema",
"dashboard.schemaNewCardDescription": "A schema defines the structure of your content element.",
"dashboard.schemasCard": "Schemas",
"dashboard.schemasCardDescription": "Get an insight to the data model of this app.",
"dashboard.stackedChart": "Stacked",
"dashboard.supportCard": "Feedback & Support",
"dashboard.supportCardDescription": "Provide feedback and request features to help us to improve Squidex.",
"dashboard.trafficChart": "API Traffic Chart",
"dashboard.trafficHeader": "Traffic (MB)",
"dashboard.trafficLimitLabel": "Monthly limit",
"dashboard.trafficSummaryCard": "API Traffic Summary",
"dashboard.welcomeText": "Welcome to **{app}** dashboard.",
"dashboard.welcomeTitle": "Hi {user}",
"eventConsumers.loadFailed": "Failed to load event consumers. Please reload.",
"eventConsumers.pageTitle": "Event Consumers",
"eventConsumers.position": "Position",
"eventConsumers.refreshTooltip": "Refresh event consumers (CTRL + SHIFT + R)",
"eventConsumers.reloaded": "Event Consumers reloaded.",
"eventConsumers.resetFailed": "Failed to reset event consumer. Please reload.",
"eventConsumers.resetTooltip": "Reset Event Consumer",
"eventConsumers.startFailed": "Failed to start event consumer. Please reload.",
"eventConsumers.startTooltip": "Start Event Consumer",
"eventConsumers.stopFailed": "Failed to stop event consumer. Please reload.",
"eventConsumers.stopTooltip": "Stop Event Consumer",
"features.loadFailed": "Failed to load features. Please reload.",
"history.loadFailed": "Failed to load history. Please reload.",
"history.title": "Activity",
"languages.add": "Add Language",
"languages.addFailed": "Failed to add language. Please reload.",
"languages.deleteConfirmText": "Do you really want to remove the language?",
"languages.deleteConfirmTitle": "Remove language",
"languages.deleteFailed": "Failed to delete language. Please reload.",
"languages.loadFailed": "Failed to load languages. Please reload.",
"languages.master": "Is Master",
"languages.masterHint": "Other languages fall back to the master if no fallback is defined.",
"languages.optional": "Is Optional",
"languages.optionalHint": "Values for optional languages must not be entered, even if field is required.",
"languages.refreshTooltip": "Refresh languages (CTRL + SHIFT + R)",
"languages.reloaded": "Languages reloaded.",
"languages.updateFailed": "Failed to change language. Please reload.",
"news.headline": "What's new?",
"news.title": "New Features",
"notifo.subscripeTooltip": "Click this button to subscribe to all changes and to receive push notifications.",
"patterns.deleteConfirmText": "Do you really want to remove this pattern?",
"patterns.deleteConfirmTitle": "Delete pattern",
"patterns.deleteFailed": "Failed to remove pattern. Please reload.",
"patterns.empty": "No pattern created yet.",
"patterns.loadFailed": "Failed to add pattern. Please reload.",
"patterns.nameValidationMessage": "Name can only contain letters, numbers, dashes and spaces.",
"patterns.refreshTooltip": "Refresh patterns (CTRL + SHIFT + R)",
"patterns.reloaded": "Patterns reloaded.",
"patterns.updateFailed": "Failed to update pattern. Please reload.",
"plans.billingPortal": "Billing Portal",
"plans.billingPortalHint": "Go to Billing Portal for payment history and subscription overview.",
"plans.change": "Change",
"plans.changeConfirmTitle": "Change subscription",
"plans.changeFailed": "Failed to change plan. Please reload.",
"plans.includedCalls": "API Calls",
"plans.includedContributors": "Contributors",
"plans.includedStorage": "Storage",
"plans.includedTraffic": "Traffic",
"plans.loadFailed": "Failed to load plans. Please reload.",
"plans.noPlanConfigured": "No plan configured, this app has unlimited usage.",
"plans.notPlanOwner": "You have not created the subscription. Therefore you cannot change the plan.",
"plans.perMonth": "Per Month",
"plans.perYear": "Per Year",
"plans.refreshTooltip": "Refresh Plans (CTRL + SHIFT + R)",
"plans.reloaded": "Plans reloaded.",
"plans.selected": "Selected",
"profile.title": "Profile",
"profile.userEmail": "Signed in with",
"roles.add": "Add role",
"roles.addFailed": "Failed to add role. Please reload.",
"roles.default.owner": "Can do everything, including deleting the app.",
"roles.default.reader": "Can only read assets and contents.",
"roles.defaults.developer": "Can use the API view, edit assets, contents, schemas, rules, workflows and patterns.",
"roles.defaults.editor": "Can edit assets and contents and view workflows.",
"roles.deleteConfirmText": "Delete role",
"roles.deleteConfirmTitle": "Do you really want to delete the role?",
"roles.loadFailed": "Failed to load roles. Please reload.",
"roles.loadPermissionsFailed": "Failed to load permissions. Please reload.",
"roles.refreshTooltip": "Refresh roles (CTRL + SHIFT + R)",
"roles.reloaded": "Roles reloaded.",
"roles.revokeFailed": "Failed to revoke role. Please reload.",
"roles.roleNamePlaceholder": "Enter role name",
"roles.updateFailed": "Failed to update role. Please reload.",
"rules.actionEdit": "Edit Action",
"rules.cancelFailed": "Failed to cancel rule. Please reload.",
"rules.create": "Create new Rule",
"rules.createFailed": "Failed to create rule. Please reload.",
"rules.createTooltip": "New Rule (CTRL + SHIFT + G)",
"rules.deleteConfirmText": "Do you really want to delete the rule?",
"rules.deleteConfirmTitle": "Delete rule",
"rules.deleteFailed": "Failed to delete rule. Please reload.",
"rules.disableFailed": "Failed to disable rule. Please reload.",
"rules.empty": "No rule created yet.",
"rules.emptyAddRule": "Add Rule",
"rules.enableFailed": "Failed to enable rule. Please reload.",
"rules.enqueued": "Rule has been added to the queue.",
"rules.listPageTitle": "Rules",
"rules.loadFailed": "Failed to load Rules. Please reload.",
"rules.readMore": "Read More",
"rules.refreshEventsTooltip": "Refresh Events (CTRL + SHIFT + R)",
"rules.refreshTooltip": "Refresh Rules (CTRL + SHIFT + R)",
"rules.reloaded": "Rules reloaded.",
"rules.restarted": "Rule will start to run in a few seconds.",
"rules.ruleEvents.cancelFailed": "Failed to cancel rule event. Please reload.",
"rules.ruleEvents.enqueue": "Enqueue",
"rules.ruleEvents.enqueued": "Events enqueued. Will be resend in a few seconds.",
"rules.ruleEvents.enqueueFailed": "Failed to enqueue rule event. Please reload.",
"rules.ruleEvents.lastInvokedLabel": "Last Invocation",
"rules.ruleEvents.listPageTitle": "Rule Events",
"rules.ruleEvents.loadFailed": "Failed to load events. Please reload.",
"rules.ruleEvents.nextAttemptLabel": "Next",
"rules.ruleEvents.numAttemptsLabel": "Attempts",
"rules.ruleEvents.reloaded": "RuleEvents reloaded.",
"rules.ruleSyntax.if": "If",
"rules.ruleSyntax.then": "then",
"rules.run": "Run",
"rules.runFailed": "Failed to run rule. Please reload.",
"rules.runningRule": "Rule '{name}' is currently running.",
"rules.runRuleConfirmText": "Do you really want to run the rule for all events?",
"rules.runRuleConfirmTitle": "Run rule",
"rules.stop": "Rule will stop soon.",
"rules.triggerConfirmText": "Do you really want to trigger the rule?",
"rules.triggerConfirmTitle": "Trigger rule",
"rules.triggerEdit": "Edit Trigger",
"rules.triggerFailed": "Failed to trigger rule. Please reload.",
"rules.unnamed": "Unnamed Rule",
"rules.updateFailed": "Failed to update rule. Please reload.",
"rules.wizard.actionHint": "The selection of the action type cannot be changed later.",
"rules.wizard.selectAction": "Select Action",
"rules.wizard.selectTrigger": "Select Trigger",
"rules.wizard.triggerHint": "The selection of the trigger type cannot be changed later.",
"schemas.addField": "Add Field",
"schemas.addFieldAndClose": "Create and close",
"schemas.addFieldAndCreate": "Create and add field",
"schemas.addFieldAndEdit": "Create and edit field",
"schemas.addFieldButton": "Add Field",
"schemas.addFieldFailed": "Failed to add field. Please reload.",
"schemas.addNestedField": "Add Nested Field",
"schemas.changeCategoryFailed": "Failed to change category. Please reload.",
"schemas.clone": "Clone Schema",
"schemas.contextMenuTour": "Open the context menu to delete the schema or to create some scripts for content changes.",
"schemas.create": "Create Schema",
"schemas.createCategory": "Create new category...",
"schemas.createFailed": "Failed to create schema. Please reload.",
"schemas.createSchemaTooltip": "New Schema (CTRL + SHIFT + G)",
"schemas.deleteConfirmText": "Do you really want to delete the schema?",
"schemas.deleteConfirmTitle": "Delete schema",
"schemas.deleteFailed": "Failed to delete schema. Please reload.",
"schemas.deleteFieldFailed": "Failed to delete field. Please reload.",
"schemas.deleteRuleConfirmText": "Do you really want to remove this Field Rule?",
"schemas.deleteRuleConfirmTitle": "Remove Field Rule",
"schemas.deleteUrlConfirmText": "Do you really want to remove this URL?",
"schemas.deleteUrlConfirmTitle": "Remove URL",
"schemas.disableFieldFailed": "Failed to disable field. Please reload.",
"schemas.enableFieldFailed": "Failed to enable field. Please reload.",
"schemas.export.deleteFields": "Delete fields",
"schemas.export.recreateFields": "Recreate fields",
"schemas.export.synchronize": "Synchronize",
"schemas.field.allowedValues": "Allowed Values",
"schemas.field.defaultValue": "Default Value",
"schemas.field.deleteConfirmText": "Do you really want to delete the field?",
"schemas.field.deleteConfirmTitle": "Delete field",
"schemas.field.disable": "Disable in UI",
"schemas.field.disabledMarker": "Disabled",
"schemas.field.editor": "Editor",
"schemas.field.editorUrl": "Editor Url",
"schemas.field.editorUrlHint": "Url to your plugin if you use a custom editor.",
"schemas.field.empty": "No field created yet.",
"schemas.field.enable": "Enable in UI",
"schemas.field.enabledMarker": "Enabled",
"schemas.field.hiddenMarker": "Hidden",
"schemas.field.hide": "Hide in API",
"schemas.field.hintsHint": "Describe this schema for documentation and user interfaces.",
"schemas.field.inlineEditable": "Inline Editable",
"schemas.field.labelHint": "Display name for documentation and user interfaces.",
"schemas.field.localizable": "Localizable",
"schemas.field.localizableHint": "You can mark the field as localizable. It means that is dependent on the language, for example a city name.",
"schemas.field.localizableMarker": "localizable",
"schemas.field.lock": "Lock and prevent changes",
"schemas.field.lockConfirmText": "WARNING: Locking a field cannot be undone! Locked field definitions cannot be unlocked, deleted, or changed anymore. Do you really want to lock this field?",
"schemas.field.lockedMarker": "Locked",
"schemas.field.nameHint": "The name of the field in the API response.",
"schemas.field.namePlaceholder": "Enter field name",
"schemas.field.nameValidationMessage": "Name must be a valid javascript name in camel case.",
"schemas.field.placeholder": "Placeholder",
"schemas.field.placeholderHint": "Define the placeholder for the input control.",
"schemas.field.required": "Required",
"schemas.field.show": "Show in API",
"schemas.field.tabCommon": "Common",
"schemas.field.tabEditing": "Editing",
"schemas.field.tabValidation": "Validation",
"schemas.field.tagsHint": "Tags to annotate your field for automation processes.",
"schemas.field.unique": "Unique",
"schemas.field.visibleMarker": "Visible",
"schemas.fieldTypes.array.count": "Items",
"schemas.fieldTypes.array.countMax": "Max Items",
"schemas.fieldTypes.array.countMin": "Min Items",
"schemas.fieldTypes.array.description": "List of embedded objects.",
"schemas.fieldTypes.assets.allowDuplicates": "Allow duplicate values",
"schemas.fieldTypes.assets.count": "Count",
"schemas.fieldTypes.assets.countMax": "Max Assets",
"schemas.fieldTypes.assets.countMin": "Min Assets",
"schemas.fieldTypes.assets.description": "Images, videos, documents.",
"schemas.fieldTypes.assets.fileExtensions": "File Extensions",
"schemas.fieldTypes.assets.mustBeImage": "Must be Image",
"schemas.fieldTypes.assets.previewMode": "PreviewMode",
"schemas.fieldTypes.assets.previewModeHint": "The preview mode for assets in content lists.",
"schemas.fieldTypes.assets.previewModeName": "Only file name",
"schemas.fieldTypes.assets.previewModeTumbnailName": "Thumbnail and file name",
"schemas.fieldTypes.assets.previewModeTumbnailOrName": "Only thumbnail or file name if not an image",
"schemas.fieldTypes.assets.resolve": "Resolve first asset",
"schemas.fieldTypes.assets.resolveHint": "Show the first referenced asset in the content list.",
"schemas.fieldTypes.assets.size": "Size",
"schemas.fieldTypes.assets.sizeMax": "Min Size",
"schemas.fieldTypes.assets.sizeMin": "Max Size",
"schemas.fieldTypes.boolean.description": "Yes or no, true or false.",
"schemas.fieldTypes.dateTime.defaultMode": "Default Mode",
"schemas.fieldTypes.dateTime.description": "Events date, opening hours.",
"schemas.fieldTypes.dateTime.rangeMax": "Max Value",
"schemas.fieldTypes.dateTime.rangeMin": "Min Value",
"schemas.fieldTypes.geolocation.description": "Coordinates: latitude and longitude.",
"schemas.fieldTypes.json.description": "Data in JSON format, for developers.",
"schemas.fieldTypes.number.description": "ID, order number, rating, quantity.",
"schemas.fieldTypes.number.range": "Range",
"schemas.fieldTypes.number.rangeMax": "Max Value",
"schemas.fieldTypes.number.rangeMin": "Min Value",
"schemas.fieldTypes.references.count": "Items",
"schemas.fieldTypes.references.countMax": "Max Items",
"schemas.fieldTypes.references.countMin": "Min Items",
"schemas.fieldTypes.references.description": "Links to other content items.",
"schemas.fieldTypes.references.resolveHint": "Show the name of the referenced item in content list when MaxItems is set to 1.",
"schemas.fieldTypes.string.description": "Titles, names, paragraphs.",
"schemas.fieldTypes.string.length": "Length",
"schemas.fieldTypes.string.lengthMax": "Max Length",
"schemas.fieldTypes.string.lengthMin": "Min Length",
"schemas.fieldTypes.string.pattern": "Regex Pattern",
"schemas.fieldTypes.string.patternMessage": "Pattern Message",
"schemas.fieldTypes.string.suggestions": "Suggestions",
"schemas.fieldTypes.tags.count": "Items",
"schemas.fieldTypes.tags.countMax": "Max Items",
"schemas.fieldTypes.tags.countMin": "Min Items",
"schemas.fieldTypes.tags.description": "Special format for tags.",
"schemas.fieldTypes.ui.description": "Separator for editing UI.",
"schemas.hideFieldFailed": "Failed to hide field. Please reload.",
"schemas.import": "Import schema",
"schemas.listFields": "List Fields",
"schemas.listFieldsEmpty": "Drop field here or reorder them to show the fields in the content list. When no list field is defined, the first field is used.",
"schemas.loadFailed": "Failed to load schemas. Please reload.",
"schemas.loadSchemaFailed": "Failed to load schema. Please reload.",
"schemas.lockFieldFailed": "Failed to lock field. Please reload.",
"schemas.modeMultiple": "Multiple contents",
"schemas.modeMultipleDescription": "Best for multiple instances like blog posts, pages, authors, products...",
"schemas.modeSingle": "Single content",
"schemas.modeSingleDescription": "Best for single instances like the home page, privacy policies, settings...",
"schemas.nameWarning": "These values cannot be changed later.",
"schemas.previewUrls.empty": "No preview urls configured.",
"schemas.previewUrls.help": "Checkout the integrated help page to learn more about preview URL's.",
"schemas.previewUrls.namePlaceholder": "Web or Mobile",
"schemas.previewUrls.title": "Preview URLs",
"schemas.previewUrls.urlPlaceholder": "URL with variables",
"schemas.published": "Published",
"schemas.publishedTour": "Note, that you have to publish the schema before you can add content to it.",
"schemas.publishFailed": "Failed to publish schema. Please reload.",
"schemas.referenceFields": "Reference Fields",
"schemas.referenceFieldsEmpty": "Drop field here or reorder them to show the fields when referenced by another content. When no reference field is defined, the list fields are used instead.",
"schemas.reloaded": "Schemas reloaded.",
"schemas.reorderFieldsFailed": "Failed to reorder fields. Please reload.",
"schemas.rules.action": "Action",
"schemas.rules.condition": "Condition in Javascript",
"schemas.rules.empty": "No field rules configured.",
"schemas.rules.title": "Field Rules",
"schemas.rules.when": "when",
"schemas.saved": "Schema saved successfully.",
"schemas.saveFieldAndClose": "Save and close",
"schemas.saveFieldAndNew": "Save and add field",
"schemas.schemaHintsHint": "Describe this schema for documentation and user interfaces.",
"schemas.schemaLabelHint": "Display name for documentation and user interfaces.",
"schemas.schemaNameHint": "You can only use letters, numbers and dashes and not more than 40 characters.",
"schemas.schemaNameValidationMessage": "Name can only contain letters, numbers, dashes and spaces.",
"schemas.schemaTagsHint": "Tags to annotate your schema for automation processes.",
"schemas.searchPlaceholder": "Search for schemas...",
"schemas.showFieldFailed": "Failed to show field. Please reload.",
"schemas.synchronized": "Schema synchronized successfully.",
"schemas.synchronizeFailed": "Failed to synchronize schema. Please reload.",
"schemas.tabFields": "Fields",
"schemas.tabJson": "Json",
"schemas.tabMore": "More",
"schemas.tabScripts": "Scripts",
"schemas.tabUI": "UI",
"schemas.ui": "Assigned fields",
"schemas.ui.unassignedFields": "Unassigned fields",
"schemas.unpublished": "Unpublished",
"schemas.unpublishFailed": "Failed to unpublish schema. Please reload.",
"schemas.updateFailed": "Failed to update schema. Please reload.",
"schemas.updateFieldFailed": "Failed to update field. Please reload.",
"schemas.updatePreviewUrlsFailed": "Failed to configure preview urls. Please reload.",
"schemas.updateRulesFailed": "Failed to update schema rules. Please reload.",
"schemas.updateScriptsFailed": "Failed to update schema scripts. Please reload.",
"schemas.updateUIFieldsFailed": "Failed to update UI fields. Please reload.",
"search.addFilter": "Add Filter",
"search.addGroup": "Add Group",
"search.addSorting": "Add Sorting",
"search.advancedTour": "Click this icon to show the advanced search menu!",
"search.customQuery": "Custom Query",
"search.fullTextTour": "Search for content using full text search over all fields and languages!",
"search.help": "Read more about filtering in the [Documentation](https://https://docs.squidex.io/04-guides/02-api.html).",
"search.myQueries": "My queries",
"search.nameQuery": "Name your query",
"search.queriesEmpty": "Search for {types} and use <i class=\"icon-star-empty\"></i> icon in search form to save query for all contributors.",
"search.queryAllNewestFirst": "All (newest first)",
"search.queryAllOldestFirst": "All (oldest first)",
"search.quickNavPlaceholder": "Quick Nav (Press 'q')",
"search.saveQueryMyself": "Save the query only for myself.",
"search.searchFailed": "Failed to make search. Please reload.",
"search.sharedQueries": "Shared queries",
"search.sorting": "Sorting",
"start.login": "Login to Squidex",
"start.loginHint": "The login button will open a new popup. Once you are logged in successful we will redirect you to the Squidex management portal.",
"start.madeBy": "Proudly made by",
"start.madeByCopyright": "Sebastian Stehle and Contributors, 2016-2020",
"tour.joinForum": "Join our Forum",
"tour.joinGithub": "Join us on Github",
"tour.skip": "Skip Tour",
"tour.step0Next": "Let's take a look around",
"tour.step0Text": "You can start managing and distributing your content right away, but we we'd like to walk you through some basics first...\n\nHow'that",
"tour.step1Next": "Continue",
"tour.step1Text": "An App is the repository for your project, e.g. (blog, web shop or mobile app). You can assign contributors to your app to work together.\n\nYou can create an unlimited number of Apps in Squidex to manage multiple projects at the same time.",
"tour.step2Next": "Keep going!",
"tour.step2Text": "Schemas define the structure of your content, the fields and the data types of a content item.\n\nBefore you can add content to your schema, make sure to hit the 'Publish' button at the top to make the schema available to your content editors.",
"tour.step3Next": "Almost there!",
"tour.step3Text": "Content is the actual data in your app which is grouped by the schema.\n\nSelect a published schema first, then add content for this schema.",
"tour.step4Next": "Got It!",
"tour.step4Text": "The assets contains all files that can also be linked to your content. For example images, videos or documents.\n\nYou can upload the assets here and use them later or also upload them directly when you create a new content item with an asset field.",
"tour.step5Text": "But that's not all of the support we can provide.\n\nYou can got to https://docs.squidex.io/> to read more.\n\nDo you want to join our community?",
"tour.step5Title": "Awesome, now you know the basics!",
"tour.tooltipConfirm": "Got It",
"tour.tooltipStop": "Stop Tour",
"tour.welcome": "Welcome to",
"tour.welcomeProduct": "Squidex CMS",
"translate.translateFailed": "Failed to translate text. Please reload.",
"usages.loadCallsFailed": "Failed to load calls usage. Please reload.",
"usages.loadMonthlyCallsFailed": "Failed to load monthly API calls. Please reload.",
"usages.loadStorageFailed": "Failed to load storage usage. Please reload.",
"usages.loadTodayStorageFailed": "Failed to load todays storage size. Please reload.",
"users.create": "New",
"users.createFailed": "Failed to create user. Please reload.",
"users.createPageTitle": "Create User",
"users.createTitle": "New User",
"users.createTooltip": "New User (CTRL + N)",
"users.editPageTitle": "Edit User",
"users.editTitle": "Edit User",
"users.listPageTitle": "User Management",
"users.listTitle": "Users",
"users.loadFailed": "Failed to load users. Please reload.",
"users.loadUserFailed": "Failed to load user. Please reload.",
"users.lockTooltip": "Lock User",
"users.passwordConfirmValidationMessage": "Passwords must be the same.",
"users.refreshTooltip": "Refresh Users (CTRL + SHIFT + R)",
"users.reloaded": "Users reloaded.",
"users.search": "Search for user",
"users.unlockTooltip": "Unlock User",
"users.updateFailed": "Failed to update user. Please reload.",
"validation.between": "{field} must be between '{min}' and '{max}'.",
"validation.betweenlength": "{field|upper} must have between {minlength} and {maxlength} item(s).",
"validation.betweenlengthstring": "{field|upper} must have between {minlength} and {maxlength} character(s).",
"validation.email": "{field|upper} must be an email address.",
"validation.exactly": "{field|upper} must be exactly '{expected}'.",
"validation.exactlylength": "{field|upper} must have exactly {expected} item(s).",
"validation.exactlylengthstring": "{field|upper} must have exactly {expected} character(s).",
"validation.match": "{message}",
"validation.max": "{field|upper} must be less or equal to '{max}'.",
"validation.maxlength": "{field|upper} must not have more than {requiredlength} item(s).",
"validation.maxlengthstring": "{field|upper} must not have more than {requiredlength} character(s).",
"validation.min": "{field|upper} must be greater or equal to '{min}'.",
"validation.minlength": "{field|upper} must have at least {requiredlength} item(s).",
"validation.minlengthstring": "{field|upper} must have at least {requiredlength} character(s).",
"validation.pattern": "{field|upper} does not match to the pattern.",
"validation.patternmessage": "{message}",
"validation.required": "{field|upper} is required.",
"validation.requiredTrue": "{field|upper} is required.",
"validation.uniquestrings": "{field|upper} must not contain duplicate values.",
"validation.validarrayvalues": "{field|upper} contains an invalid value: {invalidvalue}.",
"validation.validdatetime": "{field|upper} is not a valid date time.",
"validation.validvalues": "{field|upper} is not a valid value.",
"workflows.add": "Add Workflow",
"workflows.addStep": "Add Step",
"workflows.createFailed": "Failed to create workflow. Please reload.",
"workflows.deleteConfirmText": "Do you really want to remove the workflow?",
"workflows.deleteConfirmTitle": "Delete workflow",
"workflows.deleteFailed": "Failed to delete Workflow. Please reload.",
"workflows.empty": "No workflows created yet.",
"workflows.loadFailed": "Failed to load workflows. Please reload.",
"workflows.notNamed": "Unnamed Workflow",
"workflows.preventUpdates": "Prevent updates",
"workflows.publishedNotRemovable": "Cannot be removed",
"workflows.refreshTooltip": "Refresh workflows (CTRL + SHIFT + R)",
"workflows.reloaded": "Workflows reloaded.",
"workflows.saved": "Workflow has been saved.",
"workflows.schemasHint": "Restrict this workflow to specific schemas or keep it empty for all schemas.",
"workflows.syntax.expression": "Expression",
"workflows.syntax.for": "for",
"workflows.syntax.when": "when",
"workflows.tabEdit": "Editing",
"workflows.tabVisualize": "Visualize",
"workflows.updateFailed": "Failed to update Workflow. Please reload.",
"workflows.workflowNameHint": "Optional name for the workflow.",
"workflows.workflowNamePlaceholder": "Enter workflow name"
}

853
backend/i18n/frontend_nl.json

@ -0,0 +1,853 @@
{
"api.contentApi": "Content API",
"api.generalApi": "Algemene API",
"api.graphql": "GraphQL",
"api.graphqlPageTitle": "GraphQL",
"api.pageTitle": "API",
"api.title": "API",
"apps.allApps": "Alle apps",
"apps.appLoadFailed": "Kan app niet laden. Laad opnieuw.",
"apps.appNameHint": "Je kunt alleen letters, cijfers en streepjes gebruiken en niet meer dan 40 tekens.",
"apps.appNameValidationMessage": "Naam mag kleine letters (a-z), cijfers en streepjes tussen bevatten.",
"apps.appNameWarning": "De app-naam kan later niet worden gewijzigd.",
"apps.appsButtonCreate": "Apps-overzicht",
"apps.appsButtonFallbackTitle": "Apps-overzicht",
"apps.archieve": "App archiveren",
"apps.archieveConfirmText": "Patroon verwijderen",
"apps.archieveConfirmTitle": "Wil je deze app echt archiveren?",
"apps.archieveWarning": "Zodra je een app archiveert, is er geen weg meer terug. Wees alsjeblieft zeker.",
"apps.archiveFailed": "Kan app niet archiveren. Laad opnieuw.",
"apps.create": "App maken",
"apps.createBlankApp": "Nieuwe app.",
"apps.createBlankAppDescription": "Maak een nieuwe lege app zonder inhoud en schema's.",
"apps.createBlogApp": "Nieuw blogvoorbeeld",
"apps.createBlogAppDescription": "Begin met onze gebruiksklare blog.",
"apps.createFailed": "Maken van app is mislukt. Laad opnieuw.",
"apps.createIdentityApp": "Nieuwe identiteits-app",
"apps.createIdentityAppDescription": "Maak een app voor Squidex Identity.",
"apps.createIdentityAppV2": "Nieuwe identiteits-app V2",
"apps.createIdentityAppV2Description": "Maak een app voor Squidex Identity V2.",
"apps.createProfileApp": "Nieuw profielvoorbeeld",
"apps.createProfileAppDescription": "Maak uw profielpagina.",
"apps.createWithTemplate": "Maak {sjabloon} voorbeeld",
"apps.empty": "Je werkt nog niet samen aan een app",
"apps.generalSettings": "Algemeen",
"apps.generalSettingsDangerZone": "Algemeen",
"apps.image": "Afbeelding",
"apps.imageDrop": "Zet neer om te uploaden",
"apps.listPageTitle": "Apps",
"apps.loadFailed": "Laden van apps is mislukt. Laad opnieuw.",
"apps.removeImage": "Afbeelding verwijderen",
"apps.removeImageFailed": "Verwijderen van app-afbeelding is mislukt. Laad opnieuw.",
"apps.updateFailed": "Update app mislukt. Laad opnieuw.",
"apps.upgradeHintCurrent": "Je zit in het plan {plan}.",
"apps.upgradeHintUpgrade": "Upgrade!",
"apps.uploadImage": "Zet een bestand neer om de app-afbeelding te vervangen. Gebruik een vierkant formaat.",
"apps.uploadImageButton": "Upload bestand",
"apps.uploadImageFailed": "Uploaden van afbeelding is mislukt. Laad opnieuw.",
"apps.uploadImageTooBig": "App-afbeelding is te groot.",
"apps.welcomeSubtitle": "Welkom bij Squidex.",
"apps.welcomeTitle": "Hallo {user}",
"assets.createFolder": "Map maken",
"assets.createFolderFailed": "Maken van een map is mislukt. Laad opnieuw.",
"assets.createFolderTooltip": "Nieuwe map maken (CTRL + SHIFT + G)",
"assets.deleteConfirmText": "Weet je zeker dat je het item wilt verwijderen?",
"assets.deleteConfirmTitle": "Item verwijderen",
"assets.deleteFailed": "Verwijderen van item is mislukt. Laad opnieuw.",
"assets.deleteFolderConfirmText": "Weet je zeker dat je de map en alle bestanden wilt verwijderen?",
"assets.deleteFolderConfirmTitle": "Map verwijderen",
"assets.deleteMetadataConfirmText": "Wil je deze metadata echt verwijderen?",
"assets.deleteMetadataConfirmTitle": "Metadata verwijderen",
"assets.downloadVersion": "Download deze versie",
"assets.dropToUpdate": "Zet neer om te updaten",
"assets.duplicateFile": "Asset is al geüpload.",
"assets.editor.flipHorizontally": "Horizontaal spiegelen",
"assets.editor.flipVertically": "Verticaal spiegelen",
"assets.editor.focusPointLabel": "Selecteer positie van focuspunt",
"assets.editor.focusPointPreview": "Voorbeeld voor verschillende formaten",
"assets.editor.rotateLeft": "Links draaien",
"assets.editor.rotateRight": "Rechts draaien",
"assets.fileTooBig": "Asset is te groot.",
"assets.folderName": "Mapnaam",
"assets.folderNameHint": "De mapnaam wordt gebruikt als weergavenaam en mag niet uniek zijn.",
"assets.insertAssets": "Assets invoegen",
"assets.linkSelected": "Link geselecteerde items ({count})",
"assets.listPageTitle": "Assets",
"assets.loadFailed": "Laden van bestanden is mislukt. Laad opnieuw.",
"assets.loadFoldersFailed": "Laden van mappen is mislukt. Laad opnieuw.",
"assets.metadata": "Metadata",
"assets.metadataAdd": "Metadata toevoegen",
"assets.moveFailed": "Verplaatsen van item is mislukt. Laad opnieuw.",
"assets.protected": "Beschermd",
"assets.refreshTooltip": "Assets vernieuwen (CTRL + SHIFT + R)",
"assets.reloaded": "Bestanden herladen.",
"assets.renameFolder": "Naam map wijzigen",
"assets.replaceConfirmText": "Wilt je de asset echt vervangen door een nieuwere versie",
"assets.replaceConfirmTitle": "Asset vervangen?",
"assets.replaceFailed": "Kan item niet vervangen. Laad opnieuw.",
"assets.searchByName": "Zoeken op naam",
"assets.searchByTags": "Zoeken op tags",
"assets.selectMany": "Selecteer middelen",
"assets.tabFocusPoint": "Focuspunt",
"assets.tabHistory": "Geschiedenis",
"assets.tabImage": "Afbeelding",
"assets.tabMetadata": "Metadata",
"assets.updated": "Asset is bijgewerkt.",
"assets.updateFailed": "Bijwerken van item is mislukt. Laad opnieuw.",
"assets.updateFolderFailed": "Bijwerken van de map is mislukt. Laad opnieuw.",
"assets.uploadByDialog": "Selecteer bestand (en",
"assets.uploadByDrop": "Zet bestanden hier neer om te uploaden",
"assets.uploaderUploadHere": "Geen upload bezig, zet bestanden hier neer.",
"assets.uploadFailed": "Uploaden van item is mislukt. Laad opnieuw.",
"assets.uploadHint": "Zet het bestand neer op bestaand item om het bestand te vervangen door een nieuwere versie.",
"backups.backupCountAssetsLabel": "Bestanden",
"backups.backupCountAssetsTooltip": "Gearchiveerde middelen",
"backups.backupCountEventsLabel": "Evenementen",
"backups.backupCountEventsTooltip": "Gearchiveerde gebeurtenissen",
"backups.backupDownload": "Downloaden",
"backups.backupDownloadLink": "Klaar",
"backups.backupDuration": "Duur",
"backups.deleteConfirmText": "Wilt je de back-up echt verwijderen?",
"backups.deleteConfirmTitle": "Back-up verwijderen",
"backups.deleted": "Back-up wordt binnenkort verwijderd.",
"backups.deleteFailed": "Verwijderen van back-up is mislukt.",
"backups.empty": "Nog geen back-ups gemaakt.",
"backups.loadFailed": "Laden van back-ups is mislukt.",
"backups.maximumReached": "Je hebt het maximale aantal back-ups bereikt: 10",
"backups.refreshTooltip": "Vernieuw back-ups (CTRL + SHIFT + R)",
"backups.reloaded": "Back-ups herladen.",
"backups.restore": "Back-up herstellen",
"backups.restoreFailed": "Starten van herstel is mislukt.",
"backups.restoreLastStatus": "Laatste herstelbewerking",
"backups.restoreLastUrl": "URL voor back-up",
"backups.restoreNewAppName": "Optionele app-naam",
"backups.restorePageTitle": "Back-up herstellen",
"backups.restoreStarted": "Herstel gestart, het kan enkele minuten duren.",
"backups.restoreStartedLabel": "Gestart",
"backups.restoreStoppedLabel": "Gestopt",
"backups.restoreTitle": "Back-up herstellen",
"backups.start": "Start back-up",
"backups.started": "Back-up gestart, het kan enkele minuten duren om te voltooien.",
"backups.startedLabel": "Gestart",
"backups.startFailed": "Starten van back-up is mislukt.",
"clients.add": "Client toevoegen",
"clients.addFailed": "Toevoegen van client is mislukt. Laad opnieuw.",
"clients.allowAnonymous": "Sta anonieme toegang toe.",
"clients.allowAnonymousHint": "Sta toegang tot de API toe zonder toegangstoken voor alle bronnen die zijn geconfigureerd via de rol van deze client. Geef niet meer dan één client anonieme toegang.",
"clients.apiCallsLimit": "Max API Calls",
"clients.apiCallsLimitHint": "Limit the number of API calls this client can make per month to protect your API contingent for other clients that are more important.",
"clients.clientIdValidationMessage": "Naam mag alleen letters, cijfers, streepjes en spaties bevatten.",
"clients.clientNamePlaceholder": "Voer de naam van de klant in",
"clients.connect": "Verbinden",
"clients.connectWizard.cli": "Maak verbinding met Squidex CLI",
"clients.connectWizard.cliHint": "Download de CLI en maak verbinding met deze app om back-ups te starten, schema's te synchroniseren of inhoud te exporteren.",
"clients.connectWizard.cliStep1": "Download de nieuwste Squidex CLI",
"clients.connectWizard.cliStep1Download": "[Download de CLI van Github] (https://github.com/Squidex/squidex-samples/releases)",
"clients.connectWizard.cliStep1Hint": "De releases bevatten binaire bestanden voor alle belangrijke besturingssystemen en een kleine download als .NET Core is geïnstalleerd.",
"clients.connectWizard.cliStep2": "Voeg` <uw Squidex CLI download directory> `toe aan uw` $ PATH` variabele ",
"clients.connectWizard.cliStep3": "Voeg uw app-naam toe aan de CLI-configuratie",
"clients.connectWizard.cliStep3Hint": "Je kunt de configuratie voor meerdere apps in de CLI beheren en overschakelen naar een app.",
"clients.connectWizard.cliStep4": "Schakel over naar uw app in de CLI",
"clients.connectWizard.manually": "Handmatig verbinden",
"clients.connectWizard.manuallyHint": "Krijg instructies om een ​​verbinding tot stand te brengen met Postman of curl.",
"clients.connectWizard.manuallyStep1": "Verkrijg een token met curl",
"clients.connectWizard.manuallyStep2": "Gebruik gewoon het volgende token",
"clients.connectWizard.manuallyStep3": "Voeg het token toe als HTTP-header aan alle verzoeken",
"clients.connectWizard.manuallyTokenHint": "Tokens vervallen gewoonlijk na 30 dagen, maar je kunt meerdere tokens aanvragen.",
"clients.connectWizard.postManDocs": "Begin met de Postman-tutorial in de [Documentatie] (https://docs.squidex.io/02-documentation/developer-guides/api-overview/postman).",
"clients.connectWizard.sdk": "Maak verbinding met uw app met SDK",
"clients.connectWizard.sdkHelp": "Heb je een andere SDK nodig?",
"clients.connectWizard.sdkHelpLink": "Neem contact met ons op in het ondersteuningsforum",
"clients.connectWizard.sdkHint": "Download een SDK en maak verbinding met deze app.",
"clients.connectWizard.sdkStep1": "Installeer de .NET SDK",
"clients.connectWizard.sdkStep1Download": "De SDK is beschikbaar op [nuget] (https://www.nuget.org/packages/Squidex.ClientLibrary/)",
"clients.connectWizard.sdkStep2": "Maak een klantenbeheerder",
"clients.connectWizard.step0Title": "Client instellen",
"clients.connectWizard.step1Title": "Kies verbindingsmethode",
"clients.connectWizard.step2Title": "Verbinden",
"clients.deleteConfirmText": "Wil je de client echt intrekken?",
"clients.deleteConfirmTitle": "Client intrekken",
"clients.empty": "Nog geen client aangemaakt.",
"clients.loadFailed": "Kan clients niet laden. Laad opnieuw.",
"clients.refreshTooltip": "Ververs clients (CTRL + SHIFT + R)",
"clients.reloaded": "Clients herladen.",
"clients.revokeFailed": "Kan client niet intrekken. Laad opnieuw.",
"clients.tokenFailed": "Maken van token is mislukt. Probeer het opnieuw.",
"comments.create": "Maak een opmerking",
"comments.createFailed": "Aanmaken van commentaar mislukt.",
"comments.deleteConfirmText": "Wil je de opmerking echt verwijderen?",
"comments.deleteConfirmTitle": "Verwijder opmerking",
"comments.deleteFailed": "Verwijderen van opmerking is mislukt.",
"comments.follow": "Volgen",
"comments.loadFailed": "Kan commentaar niet laden.",
"comments.title": "Reacties",
"comments.updateFailed": "Update reactie mislukt.",
"common.actions": "Acties",
"common.administration": "Administratie",
"common.administrationPageTitle": "Administratie",
"common.api": "API",
"common.apps": "Apps",
"common.aspectRatio": "AspectRatio",
"common.assets": "Bestanden",
"common.back": "Terug",
"common.backups": "Back-ups",
"common.bytes": "bytes",
"common.cancel": "Annuleren",
"common.clear": "Wissen",
"common.clientId": "Client-ID",
"common.clients": "Clients",
"common.clientSecret": "Clientgeheim",
"common.clipboardAdded": "Waarde is toegevoegd aan uw klembord.",
"common.clone": "Kloon",
"common.cluster": "Cluster",
"common.clusterPageTitle": "Cluster",
"common.comments": "Reacties",
"common.confirm": "Bevestigen",
"common.consumers": "Consumenten",
"common.content": "Inhoud",
"common.contents": "Inhoud",
"common.continue": "Doorgaan",
"common.contributors": "Bijdragers",
"common.create": "Maken",
"common.created": "Gemaakt",
"common.date": "Datum",
"common.dateTimeEditor.local": "Local",
"common.dateTimeEditor.now": "Nu",
"common.dateTimeEditor.nowTooltip": "Nu gebruiken (UTC)",
"common.dateTimeEditor.today": "Vandaag",
"common.dateTimeEditor.todayTooltip": "Gebruik vandaag (UTC)",
"common.dateTimeEditor.utc": "UTC",
"common.delete": "Verwijderen",
"common.description": "Beschrijving",
"common.displayName": "Weergavenaam",
"common.edit": "Bewerken",
"common.email": "E-mail",
"common.error": "Fout",
"common.errorBack": "Terug naar de vorige pagina.",
"common.errorNoPermission": "Je hebt niet de permissies om dit te doen.",
"common.errorNotFound": "Niet gevonden",
"common.event": "Evenement",
"common.events": "Evenementen",
"common.executed": "Uitgevoerd",
"common.expertMode": "Expert-modus",
"common.failed": "Mislukt",
"common.fallback": "Fallback",
"common.field": "Veld",
"common.files": "Bestanden",
"common.filters": "Filters",
"common.folders": "Mappen",
"common.generalSettings": "Algemeen",
"common.generate": "Genereren",
"common.github": "Github",
"common.height": "Hoogte",
"common.help": "Help",
"common.helpTour": "Klik op het helppictogram om een ​​contextspecifieke helppagina weer te geven. Ga naar",
"common.hide": "Verbergen",
"common.hints": "Hints",
"common.history": "Geschiedenis",
"common.httpConflict": "De update is mislukt. Een andere gebruiker heeft een wijziging aangebracht. Laad opnieuw.",
"common.httpLimit": "Je hebt de maximale limiet van API-aanroepen overschreden.",
"common.label": "Label",
"common.languages": "Talen",
"common.latitudeShort": "Lat",
"common.loading": "Laden",
"common.logout": "Uitloggen",
"common.logs": "Logboeken",
"common.longitudeShort": "Lon",
"common.mapHide": "Verberg kaart",
"common.mapShow": "Toon kaart",
"common.message": "Bericht",
"common.name": "Naam",
"common.no": "Nee",
"common.nothingChanged": "Er is niets veranderd.",
"common.noValue": "- Geen waarde -",
"common.or": "of",
"common.pagerInfo": "{itemFirst} - {itemLast} van {numberOfItems}",
"common.password": "Wachtwoord",
"common.passwordConfirm": "Bevestig wachtwoord",
"common.pattern": "Patroon",
"common.patterns": "Patronen",
"common.permissions": "Rechten",
"common.preview": "Preview",
"common.product": "Squidex Headless CMS",
"common.project": "Project",
"common.refresh": "Vernieuwen",
"common.rename": "Hernoemen",
"common.requiredHint": "verplicht",
"common.reset": "Reset",
"common.restore": "Herstellen",
"common.role": "Rol",
"common.roles": "Rollen",
"common.rules": "Regels",
"common.sampleCodeLabel": "Voorbeeldcode bij",
"common.save": "Opslaan",
"common.saveShortcut": "CTRL + S",
"common.schemas": "Schema's",
"common.searchGoogleMaps": "Zoeken in Google Maps",
"common.searchResults": "Zoekresultaten",
"common.separateByLine": "Scheiden op regel",
"common.settings": "Instellingen",
"common.sidebarTour": "De zijbalknavigatie bevat nuttige contextspecifieke links. Hier kun je de geschiedenis bekijken hoe dit schema in de loop van de tijd is veranderd.",
"common.slug": "Slug",
"common.stars.max": "Mag niet meer dan 15 sterren hebben",
"common.status": "Status",
"common.statusChangeTo": "Wijzigen in",
"common.submit": "Verzenden",
"common.subscription": "Abonnement",
"common.succeeded": "Geslaagd",
"common.tagAdd": ", om tag toe te voegen",
"common.tagAddReference": ", om referentie toe te voegen",
"common.tagAddSchema": ", om schema toe te voegen",
"common.tags": "Tags",
"common.tagsAll": "Alle tags",
"common.time": "Tijd",
"common.update": "Update",
"common.url": "URL",
"common.users": "Gebruikers",
"common.value": "Waarde",
"common.width": "Breedte",
"common.workflow": "Workflow",
"common.workflows": "Workflows",
"common.yes": "Ja",
"contents.arrayAddItem": "Item toevoegen",
"contents.arrayCloneItem": "Kloon dit item",
"contents.arrayCollapseAll": "Collapse all items",
"contents.arrayCollapseItem": "Collapse this item",
"contents.arrayExpandAll": "Alle items uitvouwen",
"contents.arrayExpandItem": "Vouw dit item uit",
"contents.arrayMoveBottom": "Verplaats dit item naar beneden",
"contents.arrayMoveDown": "Verplaats dit item naar beneden",
"contents.arrayMoveTop": "Verplaats dit item naar boven",
"contents.arrayMoveUp": "Verplaats dit item omhoog",
"contents.arrayNoFields": "Voeg eerst een genest veld toe om items toe te voegen.",
"contents.assetsUpload": "Zet bestanden neer of klik",
"contents.autotranslate": "Automatisch vertalen vanuit de hoofdtaal",
"contents.changeStatusTo": "Verander inhoud item(s) in {action}",
"contents.changeStatusToImmediately": "Zet onmiddellijk op {action}.",
"contents.changeStatusToLater": "Zet op {action} op een latere datum en tijd.",
"contents.contentNotValid": "Inhoudselement niet geldig, controleer het veld met de rode balk aan de linkerkant in alle talen (indien lokaliseerbaar).",
"contents.create": "Nieuw",
"contents.createContentTooltip": "Nieuwe inhoud (CTRL + SHIFT + G)",
"contents.created": "Inhoud succesvol aangemaakt.",
"contents.createdByFieldDescription": "De gebruiker die het inhoudsitem heeft gemaakt.",
"contents.createFailed": "Maken van inhoud is mislukt. Laad opnieuw.",
"contents.createFieldDescription": "De datum en tijd waarop het inhoudsitem is gemaakt.",
"contents.createPageTitle": "Inhoud maken",
"contents.createTitle": "Nieuwe inhoud",
"contents.currentStatusLabel": "Huidige versie",
"contents.deleteConfirmText": "Wilt je de inhoud echt verwijderen?",
"contents.deleteConfirmTitle": "Inhoud verwijderen",
"contents.deleteFailed": "Verwijderen van inhoud is mislukt. Laad opnieuw.",
"contents.deleteManyConfirmText": "Weet je zeker dat je de geselecteerde inhoudsitems wilt verwijderen?",
"contents.deleteVersionConfirmText": "Wil je deze versie echt verwijderen?",
"contents.deleteVersionFailed": "Verwijderen van versie is mislukt. Laad opnieuw.",
"contents.draftNew": "Nieuw concept",
"contents.draftStatus": "Nieuwe versie",
"contents.editPageTitle": "Inhoud bewerken",
"contents.editTitle": "Inhoud bewerken",
"contents.languageModeAll": "Alle talen",
"contents.languageModeSingle": "Enkele taal",
"contents.lastModifiedByFieldDescription": "De gebruiker die het inhoudsitem de laatste keer heeft gewijzigd.",
"contents.lastModifiedFieldDescription": "De datum en tijd waarop het inhoudsitem de laatste keer is gewijzigd.",
"contents.lastUpdatedLabel": "Laatst bijgewerkt",
"contents.loadContent": "Laden",
"contents.loadContentFailed": "Kan inhoud niet laden. Laad opnieuw.",
"contents.loadDataFailed": "Laden van gegevens is mislukt. Laad opnieuw.",
"contents.loadFailed": "Laden van inhoud is mislukt. Laad opnieuw.",
"contents.loadVersionFailed": "Versie van een nieuwe versie is mislukt. Laad opnieuw.",
"contents.newStatusFieldDescription": "The new status of the content item.",
"contents.noReference": "- Geen referentie -",
"contents.pendingChangesTextToChange": "Je hebt niet-opgeslagen wijzigingen. \n \n Wanneer je de status wijzigt, raak je ze kwijt. \n \n **Wil je toch doorgaan?**",
"contents.pendingChangesTextToClose": "Je hebt niet-opgeslagen wijzigingen. \n \n Wanneer je de huidige inhoudsweergave sluit, raak je ze kwijt. \n n **Wil je toch doorgaan?**",
"contents.pendingChangesTitle": "Niet-opgeslagen wijzigingen",
"contents.referencesCreateNew": "Nieuwe toevoegen",
"contents.referencesCreatePublish": "Maken en publiceren",
"contents.referencesLink": "Link geselecteerde inhoud ({count})",
"contents.referencesSelectExisting": "Selecteer bestaande",
"contents.referencesSelectSchema": "Selecteer {scheme}",
"contents.refreshTooltip": "Ververs inhoud (CTRL + SHIFT + R)",
"contents.reloaded": "Inhoud opnieuw geladen.",
"contents.saveAndPublish": "Opslaan en publiceren",
"contents.scheduledAt": "bij",
"contents.scheduledAtLabel": "bij",
"contents.scheduledTo": "naar",
"contents.schemasPageTitle": "Inhoud",
"contents.searchPlaceholder": "Zoeken in volledige tekst",
"contents.searchSchemasPlaceholder": "Zoek schema's ...",
"contents.selectionCount": "{count} items geselecteerd",
"contents.statusFieldDescription": "De status van het inhoudsitem.",
"contents.statusQueries": "Statusquery's",
"contents.stockPhotoEmpty": "Niets geselecteerd",
"contents.stockPhotoSearch": "Zoeken naar foto's op Unsplash",
"contents.unsavedChangesText": "Je hebt niet-opgeslagen wijzigingen. Wil je ze nu laden?",
"contents.unsavedChangesTitle": "Niet-opgeslagen wijzigingen",
"contents.updated": "Inhoud succesvol bijgewerkt.",
"contents.updateFailed": "Bijwerken van inhoud is mislukt. Laad opnieuw.",
"contents.validationHint": "Denk eraan om alle talen te controleren wanneer je validatiefouten ziet.",
"contents.versionCompare": "Vergelijk",
"contents.versionDelete": "Verwijder deze versie",
"contents.versionFieldDescription": "De versie van het inhoudsitem",
"contents.versionViewing": "Bekijk versie **{version}**.",
"contents.viewLatest": "Bekijk laatste",
"contents.viewReset": "Standaardweergave herstellen",
"contributors.add": "Bijdrager toevoegen",
"contributors.addFailed": "Toevoegen van bijdragers is mislukt. Laad opnieuw.",
"contributors.contributorAssigned": "Een nieuwe gebruiker met het ingevoerde e-mailadres is aangemaakt en toegewezen als bijdrager.",
"contributors.contributorAssignedExisting": "Gebruiker is toegewezen",
"contributors.contributorAssignedInvited": "Gebruiker is uitgenodigd en toegewezen.",
"contributors.contributorAssignedOld": "Gebruiker is toegevoegd als bijdrager.",
"contributors.deleteConfirmText": "Wil je de bijdrager echt verwijderen?",
"contributors.deleteConfirmTitle": "Verwijder bijdrager",
"contributors.deleteFailed": "Verwijderen van bijdragers is mislukt. Laad opnieuw.",
"contributors.emailPlaceholder": "Vind gebruiker of nodig uit via e-mail",
"contributors.empty": "Geen bijdragers gevonden.",
"contributors.import.emailsDetected": "E-mails gedetecteerd: {count}",
"contributors.import.run": "Bijdrager toevoegen",
"contributors.import.run2": "Importeren",
"contributors.importButton": "Voeg veel bijdragers tegelijk toe",
"contributors.importHintg": "Groot team?",
"contributors.importTitle": "Bijdragers importeren",
"contributors.loadFailed": "Laden van bijdragers is mislukt. Laad opnieuw.",
"contributors.planHint": "Uw plan staat maximaal {maxContributors} bijdragers toe.",
"contributors.refreshTooltip": "Bijdragers vernieuwen (CTRL + SHIFT + R)",
"contributors.reloaded": "Contributors reloaded.",
"contributors.search": "Zoeken",
"contributors.userNotFound": "De gebruiker bestaat niet.",
"dashboard.apiCallsCard": "API-oproepen",
"dashboard.apiCallsChart": "Grafiek API-oproepen",
"dashboard.apiCallsLimitLabel": "Maandelijkse limiet",
"dashboard.apiCallsSummaryCard": "Samenvatting API-oproepen",
"dashboard.apiDocumentationCard": "API-documentatie",
"dashboard.apiPerformanceCard": "API-prestaties (ms): {summary} ms gem.",
"dashboard.apiPerformanceChart": "API-prestatiegrafiek",
"dashboard.assetSizeCard": "Grootte van bestand (MB",
"dashboard.assetSizeLabel": "Totale grootte",
"dashboard.assetSizeLimitLabel": "Totale limiet",
"dashboard.assetTotalSize": "Totale opslagruimte",
"dashboard.assetUpdloadsCountChart": "Grafiek aantal itemsuploads",
"dashboard.assetUploadsCard": "Uploads van items",
"dashboard.assetUploadsSizeChart": "Maattabel voor uploads van items",
"dashboard.configSaved": "Configuratie opgeslagen.",
"dashboard.contentApi": "Content API",
"dashboard.contentApiDescription": "OpenAPI 3.0-compatibele documentatie voor uw app-inhoud.",
"dashboard.contentsSummaryCard": "Aantal items",
"dashboard.currentMonthLabel": "Deze maand",
"dashboard.downloadLog": "Downloadlogboek",
"dashboard.editConfig": "Configuratie bewerken",
"dashboard.githubCard": "Github",
"dashboard.githubCardDescription": "Haal de broncode op van Github en meld bugs of vraag om ondersteuning.",
"dashboard.historyCard": "Geschiedenis",
"dashboard.pageTitle": "Dashboard",
"dashboard.resetConfigConfirmText": "Wil je echt het dashboard terugzetten naar de standaardinstellingen?",
"dashboard.resetConfigConfirmTitle": "Reset configuratie",
"dashboard.schemaNewCard": "Nieuw schema",
"dashboard.schemaNewCardDescription": "Een schema definieert de structuur van uw inhoudselement.",
"dashboard.schemasCard": "Schema's",
"dashboard.schemasCardDescription": "Krijg inzicht in het datamodel van deze app.",
"dashboard.stackedChart": "Gestapeld",
"dashboard.supportCard": "Feedback en ondersteuning",
"dashboard.supportCardDescription": "Geef feedback en vraag om functies om ons te helpen Squidex te verbeteren.",
"dashboard.trafficChart": "API-verkeersdiagram",
"dashboard.trafficHeader": "Verkeer (MB)",
"dashboard.trafficLimitLabel": "Maandelijks limiet",
"dashboard.trafficSummaryCard": "API Verkeer Samenvatting",
"dashboard.welcomeText": "Welkom bij **{app}** dashboard.",
"dashboard.welcomeTitle": "Hallo {user}",
"eventConsumers.loadFailed": "Kan gebeurtenisgebruikers niet laden. Laad opnieuw.",
"eventConsumers.pageTitle": "Evenementconsumenten",
"eventConsumers.position": "Positie",
"eventConsumers.refreshTooltip": "Ververs evenementgebruikers (CTRL + SHIFT + R)",
"eventConsumers.reloaded": "Evenementconsumenten herladen.",
"eventConsumers.resetFailed": "Kan gebeurtenisgebruiker niet resetten. Laad opnieuw.",
"eventConsumers.resetTooltip": "Reset Event Consumer",
"eventConsumers.startFailed": "Het starten van een evenementconsument is mislukt. Laad opnieuw.",
"eventConsumers.startTooltip": "Start Event Consumer",
"eventConsumers.stopFailed": "Kan de gebruiker van het evenement niet stoppen. Laad opnieuw.",
"eventConsumers.stopTooltip": "Stop Event Consumer",
"features.loadFailed": "Laden van functies is mislukt. Laad opnieuw.",
"history.loadFailed": "Kan geschiedenis niet laden. Laad opnieuw.",
"history.title": "Activiteit",
"languages.add": "Taal toevoegen",
"languages.addFailed": "Toevoegen van taal is mislukt. Laad opnieuw.",
"languages.deleteConfirmText": "Wil je de taal echt verwijderen?",
"languages.deleteConfirmTitle": "Verwijder taal",
"languages.deleteFailed": "Verwijderen van taal is mislukt. Laad opnieuw.",
"languages.loadFailed": "Laden van talen is mislukt. Laad opnieuw.",
"languages.master": "Is Master",
"languages.masterHint": "Andere talen vallen terug op de master als er geen fallback is gedefinieerd.",
"languages.optional": "Is optioneel",
"languages.optionalHint": "Waarden voor optionele talen mogen niet worden ingevoerd, zelfs niet als dit veld vereist is.",
"languages.refreshTooltip": "Ververs talen (CTRL + SHIFT + R)",
"languages.reloaded": "Talen herladen.",
"languages.updateFailed": "Het wijzigen van de taal is mislukt. Laad opnieuw.",
"news.headline": "Wat is er nieuw?",
"news.title": "Nieuwe functies",
"notifo.subscripeTooltip": "Klik op deze knop om je te abonneren op alle wijzigingen en om pushmeldingen te ontvangen.",
"patterns.deleteConfirmText": "Wil je dit patroon echt verwijderen?",
"patterns.deleteConfirmTitle": "Verwijder patroon",
"patterns.deleteFailed": "Verwijderen van patroon is mislukt. Laad opnieuw.",
"patterns.empty": "Nog geen patroon gemaakt.",
"patterns.loadFailed": "Toevoegen van patroon is mislukt. Laad opnieuw.",
"patterns.nameValidationMessage": "Naam mag alleen letters, cijfers, streepjes en spaties bevatten.",
"patterns.refreshTooltip": "Ververs patronen (CTRL + SHIFT + R)",
"patterns.reloaded": "Patronen herladen.",
"patterns.updateFailed": "Bijwerken van patroon is mislukt. Laad opnieuw.",
"plans.billingPortal": "Factureringsportal",
"plans.billingPortalHint": "Ga naar het factureringsportaal voor betalingsgeschiedenis en abonnementsoverzicht.",
"plans.change": "Wijzigen",
"plans.changeConfirmTitle": "Abonnement wijzigen",
"plans.changeFailed": "Kan plan niet wijzigen. Laad opnieuw.",
"plans.includedCalls": "API-oproepen",
"plans.includedContributors": "Contributors",
"plans.includedStorage": "Opslag",
"plans.includedTraffic": "Verkeer",
"plans.loadFailed": "Laden van plannen is mislukt. Laad opnieuw.",
"plans.noPlanConfigured": "Geen plan geconfigureerd, deze app heeft onbeperkt gebruik.",
"plans.notPlanOwner": "Je hebt geen abonnement aangemaakt. Daarom kun je het plan niet wijzigen.",
"plans.perMonth": "Per maand",
"plans.perYear": "Per jaar",
"plans.refreshTooltip": "Plannen vernieuwen (CTRL + SHIFT + R)",
"plans.reloaded": "Plans reloaded.",
"plans.selected": "Geselecteerd",
"profile.title": "Profiel",
"profile.userEmail": "Aangemeld met",
"roles.add": "Rol toevoegen",
"roles.addFailed": "Toevoegen van rol is mislukt. Laad opnieuw.",
"roles.default.owner": "Kan alles doen, inclusief het verwijderen van de app.",
"roles.default.reader": "Kan alleen items en inhoud lezen.",
"roles.defaults.developer": "Kan de API-weergave gebruiken, middelen, inhoud, schema's, regels, workflows en patronen bewerken.",
"roles.defaults.editor": "Kan middelen en inhoud bewerken en workflows bekijken.",
"roles.deleteConfirmText": "Rol verwijderen",
"roles.deleteConfirmTitle": "Wil je de rol echt verwijderen?",
"roles.loadFailed": "Laden van rollen is mislukt. Laad opnieuw.",
"roles.loadPermissionsFailed": "Kan machtigingen niet laden. Laad opnieuw.",
"roles.refreshTooltip": "Ververs rollen (CTRL + SHIFT + R)",
"roles.reloaded": "Rollen opnieuw geladen.",
"roles.revokeFailed": "Kan rol niet intrekken. Laad opnieuw.",
"roles.roleNamePlaceholder": "Voer de rolnaam in",
"roles.updateFailed": "Update rol mislukt. Laad opnieuw.",
"rules.actionEdit": "Bewerk actie",
"rules.cancelFailed": "Annuleren van regel is mislukt. Laad opnieuw.",
"rules.create": "Maak een nieuwe regel",
"rules.createFailed": "Maken van regel is mislukt. Laad opnieuw.",
"rules.createTooltip": "Nieuwe regel (CTRL + SHIFT + G)",
"rules.deleteConfirmText": "Wil je de regel echt verwijderen?",
"rules.deleteConfirmTitle": "Regel verwijderen",
"rules.deleteFailed": "Verwijderen van regel is mislukt. Laad opnieuw.",
"rules.disableFailed": "Kan regel niet uitschakelen. Laad opnieuw.",
"rules.empty": "Nog geen regel aangemaakt.",
"rules.emptyAddRule": "Regel toevoegen",
"rules.enableFailed": "Kan regel niet inschakelen. Laad opnieuw.",
"rules.enqueued": "Regel is toegevoegd aan de wachtrij.",
"rules.listPageTitle": "Regels",
"rules.loadFailed": "Laden van regels is mislukt. Laad opnieuw.",
"rules.readMore": "Lees meer",
"rules.refreshEventsTooltip": "Ververs evenementen (CTRL + SHIFT + R)",
"rules.refreshTooltip": "Vernieuwingsregels (CTRL + SHIFT + R)",
"rules.reloaded": "Regels herladen.",
"rules.restarted": "Regel begint over een paar seconden te lopen.",
"rules.ruleEvents.cancelFailed": "Annuleren van regelgebeurtenis is mislukt. Laad opnieuw.",
"rules.ruleEvents.enqueue": "Enqueue",
"rules.ruleEvents.enqueued": "Evenementen in de wachtrij geplaatst. Worden over enkele seconden opnieuw verzonden.",
"rules.ruleEvents.enqueueFailed": "Kan regelgebeurtenis niet in wachtrij plaatsen. Laad opnieuw.",
"rules.ruleEvents.lastInvokedLabel": "Laatste aanroep",
"rules.ruleEvents.listPageTitle": "Regelgebeurtenissen",
"rules.ruleEvents.loadFailed": "Kan evenementen niet laden. Laad opnieuw.",
"rules.ruleEvents.nextAttemptLabel": "Volgende",
"rules.ruleEvents.numAttemptsLabel": "Pogingen",
"rules.ruleEvents.reloaded": "RuleEvents herladen.",
"rules.ruleSyntax.if": "If",
"rules.ruleSyntax.then": "then",
"rules.run": "Uitvoeren",
"rules.runFailed": "Uitvoeren van regel mislukt. Laad opnieuw.",
"rules.runningRule": "Regel '{name}' is momenteel actief.",
"rules.runRuleConfirmText": "Wil je de regel echt voor alle evenementen uitvoeren?",
"rules.runRuleConfirmTitle": "Regel uitvoeren",
"rules.stop": "Regel stopt binnenkort.",
"rules.triggerConfirmText": "Wil je echt de regel activeren?",
"rules.triggerConfirmTitle": "Trigger regel",
"rules.triggerEdit": "Trigger bewerken",
"rules.triggerFailed": "Kan regel niet activeren. Laad opnieuw.",
"rules.unnamed": "Naamloos regel",
"rules.updateFailed": "Update regel mislukt. Laad opnieuw.",
"rules.wizard.actionHint": "De selectie van het actietype kan later niet worden gewijzigd.",
"rules.wizard.selectAction": "Selecteer actie",
"rules.wizard.selectTrigger": "Selecteer Trigger",
"rules.wizard.triggerHint": "De selectie van het triggertype kan later niet worden gewijzigd.",
"schemas.addField": "Veld toevoegen",
"schemas.addFieldAndClose": "Maken en sluiten",
"schemas.addFieldAndCreate": "Maak en voeg veld toe",
"schemas.addFieldAndEdit": "Maak en bewerk veld",
"schemas.addFieldButton": "Veld",
"schemas.addFieldFailed": "Toevoegen van veld is mislukt. Laad opnieuw.",
"schemas.addNestedField": "Voeg genest veld toe",
"schemas.changeCategoryFailed": "Kan categorie niet wijzigen. Laad opnieuw.",
"schemas.clone": "Clone Schema",
"schemas.contextMenuTour": "Open het contextmenu om het schema te verwijderen of om scripts te maken voor wijzigingen in de inhoud.",
"schemas.create": "Schema maken",
"schemas.createCategory": "Nieuwe categorie maken ...",
"schemas.createFailed": "Kan schema niet maken. Laad opnieuw.",
"schemas.createSchemaTooltip": "Nieuw schema (CTRL + SHIFT + G)",
"schemas.deleteConfirmText": "Weet je zeker dat je het schema wilt verwijderen?",
"schemas.deleteConfirmTitle": "Schema verwijderen",
"schemas.deleteFailed": "Kan schema niet verwijderen. Laad opnieuw.",
"schemas.deleteFieldFailed": "Verwijderen van veld is mislukt. Laad opnieuw.",
"schemas.deleteRuleConfirmText": "Wil je deze veldregel echt verwijderen?",
"schemas.deleteRuleConfirmTitle": "Veldregel verwijderen",
"schemas.deleteUrlConfirmText": "Wil je deze URL echt verwijderen?",
"schemas.deleteUrlConfirmTitle": "URL verwijderen",
"schemas.disableFieldFailed": "Uitschakelen van veld is mislukt. Laad opnieuw.",
"schemas.enableFieldFailed": "Kan veld niet inschakelen. Laad opnieuw.",
"schemas.export.deleteFields": "Velden verwijderen",
"schemas.export.recreateFields": "Velden opnieuw maken",
"schemas.export.synchronize": "Synchroniseren",
"schemas.field.allowedValues": "Toegestane waarden",
"schemas.field.defaultValue": "Standaardwaarde",
"schemas.field.deleteConfirmText": "Weet je zeker dat je het veld wilt verwijderen?",
"schemas.field.deleteConfirmTitle": "Verwijder veld",
"schemas.field.disable": "Uitschakelen in gebruikersinterface",
"schemas.field.disabledMarker": "Uitgeschakeld",
"schemas.field.editor": "Editor",
"schemas.field.editorUrl": "Editor-URL",
"schemas.field.editorUrlHint": "Url naar uw plug-in als je een aangepaste editor gebruikt.",
"schemas.field.empty": "Nog geen veld aangemaakt.",
"schemas.field.enable": "Inschakelen in gebruikersinterface",
"schemas.field.enabledMarker": "Ingeschakeld",
"schemas.field.hiddenMarker": "Verborgen",
"schemas.field.hide": "Verbergen in API",
"schemas.field.hintsHint": "Beschrijf dit schema voor documentatie en gebruikersinterfaces.",
"schemas.field.inlineEditable": "Inline bewerkbaar",
"schemas.field.labelHint": "Weergavenaam voor documentatie en gebruikersinterfaces.",
"schemas.field.localizable": "Localizable",
"schemas.field.localizableHint": "Je kunt het veld markeren als lokaliseerbaar. Dit betekent dat het afhankelijk is van de taal, bijvoorbeeld de naam van een stad.",
"schemas.field.localizableMarker": "localizable",
"schemas.field.lock": "Vergrendel en voorkom wijzigingen",
"schemas.field.lockConfirmText": "WAARSCHUWING: het vergrendelen van een veld kan niet ongedaan worden gemaakt! Vergrendelde velddefinities kunnen niet meer worden ontgrendeld, verwijderd of gewijzigd. Wil je dit veld echt vergrendelen?",
"schemas.field.lockedMarker": "Vergrendeld",
"schemas.field.nameHint": "De naam van het veld in het API-antwoord.",
"schemas.field.namePlaceholder": "Voer veldnaam in",
"schemas.field.nameValidationMessage": "Naam moet een geldige javascript-naam zijn in het geval van een camel.",
"schemas.field.placeholder": "Placeholder",
"schemas.field.placeholderHint": "Definieer de tijdelijke aanduiding voor het invoerbesturingselement.",
"schemas.field.required": "Vereist",
"schemas.field.show": "Weergeven in API",
"schemas.field.tabCommon": "Algemeen",
"schemas.field.tabEditing": "Bewerken",
"schemas.field.tabValidation": "Validatie",
"schemas.field.tagsHint": "Tags om uw veld te annoteren voor automatiseringsprocessen.",
"schemas.field.unique": "Uniek",
"schemas.field.visibleMarker": "Zichtbaar",
"schemas.fieldTypes.array.count": "Items",
"schemas.fieldTypes.array.countMax": "Max. aantal items",
"schemas.fieldTypes.array.countMin": "Min. items",
"schemas.fieldTypes.array.description": "Lijst met ingesloten objecten.",
"schemas.fieldTypes.assets.allowDuplicates": "Dubbele waarden toestaan",
"schemas.fieldTypes.assets.count": "Tellen",
"schemas.fieldTypes.assets.countMax": "Max. bestanden",
"schemas.fieldTypes.assets.countMin": "Min. bestanden",
"schemas.fieldTypes.assets.description": "Afbeeldingen, video's, documenten.",
"schemas.fieldTypes.assets.fileExtensions": "Bestandsextensies",
"schemas.fieldTypes.assets.mustBeImage": "Moet afbeelding zijn",
"schemas.fieldTypes.assets.previewMode": "PreviewMode",
"schemas.fieldTypes.assets.previewModeHint": "De voorbeeldmodus voor items in inhoudslijsten.",
"schemas.fieldTypes.assets.previewModeName": "Alleen bestandsnaam",
"schemas.fieldTypes.assets.previewModeTumbnailName": "Miniatuur- en bestandsnaam",
"schemas.fieldTypes.assets.previewModeTumbnailOrName": "Alleen miniatuur- of bestandsnaam indien geen afbeelding",
"schemas.fieldTypes.assets.resolve": "Eerste item oplossen",
"schemas.fieldTypes.assets.resolveHint": "Toon het eerste item waarnaar wordt verwezen in de inhoudslijst.",
"schemas.fieldTypes.assets.size": "Grootte",
"schemas.fieldTypes.assets.sizeMax": "Min. grootte",
"schemas.fieldTypes.assets.sizeMin": "Max. grootte",
"schemas.fieldTypes.boolean.description": "Ja of nee, waar of niet waar.",
"schemas.fieldTypes.dateTime.defaultMode": "Standaardmodus",
"schemas.fieldTypes.dateTime.description": "Datum van evenementen, openingstijden.",
"schemas.fieldTypes.dateTime.rangeMax": "Max. waarde",
"schemas.fieldTypes.dateTime.rangeMin": "Min. waarde",
"schemas.fieldTypes.geolocation.description": "Coördinaten: lengte- en breedtegraad.",
"schemas.fieldTypes.json.description": "Gegevens in JSON-indeling, voor ontwikkelaars.",
"schemas.fieldTypes.number.description": "ID, bestelnummer, beoordeling, aantal.",
"schemas.fieldTypes.number.range": "Bereik",
"schemas.fieldTypes.number.rangeMax": "Max. waarde",
"schemas.fieldTypes.number.rangeMin": "Min. waarde",
"schemas.fieldTypes.references.count": "Artikelen",
"schemas.fieldTypes.references.countMax": "Max. aantal items",
"schemas.fieldTypes.references.countMin": "Min. items",
"schemas.fieldTypes.references.description": "Links naar andere inhoudsitems.",
"schemas.fieldTypes.references.resolveHint": "Toon de naam van het item waarnaar wordt verwezen in de inhoudslijst wanneer MaxItems is ingesteld op 1.",
"schemas.fieldTypes.string.description": "Titels, namen, alinea's.",
"schemas.fieldTypes.string.length": "Lengte",
"schemas.fieldTypes.string.lengthMax": "Max. lengte",
"schemas.fieldTypes.string.lengthMin": "Min. lengte",
"schemas.fieldTypes.string.pattern": "Regex-patroon",
"schemas.fieldTypes.string.patternMessage": "Patroonbericht",
"schemas.fieldTypes.string.suggestions": "Suggesties",
"schemas.fieldTypes.tags.count": "Artikelen",
"schemas.fieldTypes.tags.countMax": "Max. aantal items",
"schemas.fieldTypes.tags.countMin": "Min. items",
"schemas.fieldTypes.tags.description": "Speciaal formaat voor tags.",
"schemas.fieldTypes.ui.description": "Scheidingsteken voor het bewerken van gebruikersinterface.",
"schemas.hideFieldFailed": "Kan veld niet verbergen. Laad opnieuw.",
"schemas.import": "Importeer schema",
"schemas.listFields": "Lijstvelden",
"schemas.listFieldsEmpty": "Zet het veld hier neer of rangschik ze opnieuw om de velden in de inhoudslijst weer te geven. Als er geen lijstveld is gedefinieerd, wordt het eerste veld gebruikt.",
"schemas.loadFailed": "Kan schema's niet laden. Laad opnieuw.",
"schemas.loadSchemaFailed": "Kan schema niet laden. Laad opnieuw.",
"schemas.lockFieldFailed": "Kan veld niet vergrendelen. Laad opnieuw.",
"schemas.modeMultiple": "Meerdere inhoud",
"schemas.modeMultipleDescription": "Beste voor meerdere instanties, zoals blogposts, pagina's, auteurs, producten ...",
"schemas.modeSingle": "Enkele inhoud",
"schemas.modeSingleDescription": "Beste voor afzonderlijke instanties zoals de startpagina, privacybeleid, instellingen ...",
"schemas.nameWarning": "Deze waarden kunnen later niet worden gewijzigd.",
"schemas.previewUrls.empty": "Geen voorbeeld-URL's geconfigureerd.",
"schemas.previewUrls.help": "Bekijk de geïntegreerde helppagina voor meer informatie over voorbeeld-URL's.",
"schemas.previewUrls.namePlaceholder": "Web of mobiel",
"schemas.previewUrls.title": "Voorbeeld-URL's",
"schemas.previewUrls.urlPlaceholder": "URL met variabelen",
"schemas.published": "Gepubliceerd",
"schemas.publishedTour": "Merk op dat je het schema moet publiceren voordat je er inhoud aan kunt toevoegen.",
"schemas.publishFailed": "Kan schema niet publiceren. Laad opnieuw.",
"schemas.referenceFields": "Referentievelden",
"schemas.referenceFieldsEmpty": "Zet het veld hier neer of rangschik ze opnieuw om de velden weer te geven wanneer ernaar wordt verwezen door een andere inhoud. Als er geen referentieveld is gedefinieerd, worden de lijstvelden gebruikt.",
"schemas.reloaded": "Schema's herladen.",
"schemas.reorderFieldsFailed": "De volgorde van velden is mislukt. Laad opnieuw.",
"schemas.rules.action": "Actie",
"schemas.rules.condition": "Conditie in Javascript",
"schemas.rules.empty": "Geen veldregels geconfigureerd.",
"schemas.rules.title": "Veldregels",
"schemas.rules.when": "Wanneer",
"schemas.saved": "Schema succesvol opgeslagen.",
"schemas.saveFieldAndClose": "Opslaan en sluiten",
"schemas.saveFieldAndNew": "Opslaan en veld toevoegen",
"schemas.schemaHintsHint": "Beschrijf dit schema voor documentatie en gebruikersinterfaces.",
"schemas.schemaLabelHint": "Weergavenaam voor documentatie en gebruikersinterfaces.",
"schemas.schemaNameHint": "Je mag alleen letters, cijfers en streepjes gebruiken en niet meer dan 40 tekens.",
"schemas.schemaNameValidationMessage": "Naam mag alleen letters, cijfers, streepjes en spaties bevatten.",
"schemas.schemaTagsHint": "Tags om uw schema voor automatiseringsprocessen te annoteren.",
"schemas.searchPlaceholder": "Zoek schema's ...",
"schemas.showFieldFailed": "Kan veld niet weergeven. Laad opnieuw.",
"schemas.synchronized": "Schema is succesvol gesynchroniseerd.",
"schemas.synchronizeFailed": "Synchroniseren van schema is mislukt. Laad opnieuw.",
"schemas.tabFields": "Velden",
"schemas.tabJson": "Json",
"schemas.tabMore": "Meer",
"schemas.tabScripts": "Scripts",
"schemas.tabUI": "UI",
"schemas.ui": "Toegewezen velden",
"schemas.ui.unassignedFields": "Niet-toegewezen velden",
"schemas.unpublished": "Niet gepubliceerd",
"schemas.unpublishFailed": "Kan de publicatie van het schema niet ongedaan maken. Laad het opnieuw.",
"schemas.updateFailed": "Kan schema niet updaten. Laad opnieuw.",
"schemas.updateFieldFailed": "Kan veld niet bijwerken. Laad opnieuw.",
"schemas.updatePreviewUrlsFailed": "Configureren van voorbeeld-URL's is mislukt. Laad opnieuw.",
"schemas.updateRulesFailed": "Updaten van schemaregels is mislukt. Laad opnieuw.",
"schemas.updateScriptsFailed": "Updaten van schemascripts is mislukt. Laad opnieuw.",
"schemas.updateUIFieldsFailed": "Bijwerken van UI-velden is mislukt. Laad opnieuw.",
"search.addFilter": "Filter toevoegen",
"search.addGroup": "Groep toevoegen",
"search.addSorting": "Sortering toevoegen",
"search.advancedTour": "Klik op dit pictogram om het geavanceerde zoekmenu weer te geven!",
"search.customQuery": "Aangepaste zoekopdracht",
"search.fullTextTour": "Zoek naar inhoud met volledige tekstzoekopdracht in alle velden en talen!",
"search.help": "Lees meer over filteren in de [Documentation] (https: // https: //docs.squidex.io/04-guides/02-api.html).",
"search.myQueries": "Mijn zoekopdrachten",
"search.nameQuery": "Geef uw zoekopdracht een naam",
"search.queriesEmpty": "Zoek naar {types} en gebruik <i class = \" icon-star-empty \"> </i> icon in het zoekformulier om de zoekopdracht op te slaan voor alle bijdragers.",
"search.queryAllNewestFirst": "Alle (nieuwste eerst)",
"search.queryAllOldestFirst": "Alle (oudste eerst)",
"search.quickNavPlaceholder": "Snelle navigatie (druk op 'q')",
"search.saveQueryMyself": "Bewaar de zoekopdracht alleen voor mezelf.",
"search.searchFailed": "Zoeken mislukt. Laad opnieuw.",
"search.sharedQueries": "Gedeelde zoekopdrachten",
"search.sorting": "Sorteren",
"start.login": "Log in op Squidex",
"start.loginHint": "De login-knop opent een nieuwe pop-up. Zodra je succesvol bent ingelogd, zullen we je doorverwijzen naar het Squidex beheerportaal.",
"start.madeBy": "Met trots gemaakt door",
"start.madeByCopyright": "Sebastian Stehle en medewerkers, 2016-2020",
"tour.joinForum": "Word lid van ons forum",
"tour.joinGithub": "Bezoek ons ​​op Github",
"tour.skip": "Tour overslaan",
"tour.step0Next": "Laten we eens rondkijken",
"tour.step0Text": "Je kunt direct beginnen met het beheren en distribueren van uw inhoud, maar we willen je graag eerst wat basisbeginselen laten zien ... \n \n Hoe dat",
"tour.step1Next": "Doorgaan",
"tour.step1Text": "Een app is de opslagplaats voor uw project, bijvoorbeeld (blog, webshop of mobiele app). Je kunt bijdragers aan uw app toewijzen om samen te werken. \n \n Je kunt een onbeperkt aantal apps maken in Squidex om meerdere projecten tegelijkertijd te beheren. ",
"tour.step2Next": "Ga door!",
"tour.step2Text": "Schema's bepalen de structuur van uw inhoud, de velden en de gegevenstypen van een inhoudsitem. \n \n Voordat je inhoud aan uw schema kunt toevoegen, moet je op de knop 'Publiceren' bovenaan klikken om het schema beschikbaar te maken voor uw inhoudeditors. ",
"tour.step3Next": "Bijna klaar!",
"tour.step3Text": "Inhoud zijn de feitelijke gegevens in uw app die zijn gegroepeerd op basis van het schema. \n \n Selecteer eerst een gepubliceerd schema en voeg vervolgens inhoud toe voor dit schema.",
"tour.step4Next": "Begrepen!",
"tour.step4Text": "De mappen bevatten alle bestanden die ook aan uw inhoud kunnen worden gekoppeld. Bijvoorbeeld afbeeldingen, video's of documenten. \n \n Je kunt de bestanden hier uploaden en later gebruiken of ze direct uploaden wanneer je een nieuw contentitem met een bestandveld maakt. ",
"tour.step5Text": "Maar dat is niet alle ondersteuning die we kunnen bieden. \n \n Je kunt naar https://docs.squidex.io/> gaan om meer te lezen. \n \n Wil je lid worden van onze community ? ",
"tour.step5Title": "Geweldig, nu ken je de basis!",
"tour.tooltipConfirm": "Begrepen",
"tour.tooltipStop": "Tour stoppen",
"tour.welcome": "Welkom bij",
"tour.welcomeProduct": "Squidex CMS",
"translate.translateFailed": "Kan tekst niet vertalen. Laad opnieuw.",
"usages.loadCallsFailed": "Kan gebruik van oproepen niet laden. Laad opnieuw.",
"usages.loadMonthlyCallsFailed": "Laden van maandelijkse API-aanroepen is mislukt. Laad opnieuw.",
"usages.loadStorageFailed": "Laden van opslaggebruik is mislukt. Laad opnieuw.",
"usages.loadTodayStorageFailed": "Kan de huidige opslaggrootte niet laden. Laad opnieuw.",
"users.create": "Nieuw",
"users.createFailed": "Aanmaken van gebruiker mislukt. Laad opnieuw.",
"users.createPageTitle": "Gebruiker aanmaken",
"users.createTitle": "Nieuwe gebruiker",
"users.createTooltip": "Nieuwe gebruiker (CTRL + N)",
"users.editPageTitle": "Gebruiker bewerken",
"users.editTitle": "Gebruiker bewerken",
"users.listPageTitle": "Gebruikersbeheer",
"users.listTitle": "Gebruikers",
"users.loadFailed": "Laden van gebruikers mislukt. Laad opnieuw.",
"users.loadUserFailed": "Kan gebruiker niet laden. Laad opnieuw.",
"users.lockTooltip": "Gebruiker vergrendelen",
"users.passwordConfirmValidationMessage": "Wachtwoorden moeten hetzelfde zijn.",
"users.refreshTooltip": "Ververs gebruikers (CTRL + SHIFT + R)",
"users.reloaded": "Gebruikers herladen.",
"users.search": "Zoeken naar gebruiker",
"users.unlockTooltip": "Gebruiker ontgrendelen",
"users.updateFailed": "Update gebruiker mislukt. Laad opnieuw.",
"validation.between": "{field} moet tussen '{min}' en '{max}' liggen.",
"validation.betweenlength": "{field|upper} moet tussen {minlength} en {maxlength} item (s) bevatten.",
"validation.betweenlengthstring": "{field|upper} moet tussen {minlength} en {maxlength} teken (s) bevatten.",
"validation.email": "{field|upper} moet een e-mailadres zijn.",
"validation.exactly": "{field|upper} moet exact '{expected}' zijn.",
"validation.exactlylength": "{field|upper} moet exact {expected} item (s) bevatten.",
"validation.exactlylengthstring": "{field|upper} moet exact {expected} teken (s) bevatten.",
"validation.match": "{message}",
"validation.max": "{field|upper} moet kleiner zijn dan of gelijk zijn aan '{max}'.",
"validation.maxlength": "{field|upper} mag niet meer dan {requiredlength} item (s) bevatten.",
"validation.maxlengthstring": "{field|upper} mag niet meer dan {requiredlength} teken (s) bevatten.",
"validation.min": "{field|upper} moet groter zijn dan of gelijk zijn aan '{min}'.",
"validation.minlength": "{field|upper} moet minimaal {requiredlength} item (s) bevatten.",
"validation.minlengthstring": "{field|upper} moet minimaal {requiredlength} teken (s) bevatten.",
"validation.pattern": "{field|upper} komt niet overeen met het patroon.",
"validation.patternmessage": "{message}",
"validation.required": "{field|upper} is vereist.",
"validation.requiredTrue": "{field|upper} is vereist.",
"validation.uniquestrings": "{field|upper} mag geen dubbele waarden bevatten.",
"validation.validarrayvalues": "{field|upper} bevat een ongeldige waarde: {invalidvalue}.",
"validation.validdatetime": "{field|upper} is geen geldige datum en tijd.",
"validation.validvalues": "{field|upper} is geen geldige waarde.",
"workflows.add": "Workflow toevoegen",
"workflows.addStep": "Stap toevoegen",
"workflows.createFailed": "Maken van workflow mislukt. Laad opnieuw.",
"workflows.deleteConfirmText": "Wil je de workflow echt verwijderen?",
"workflows.deleteConfirmTitle": "Workflow verwijderen",
"workflows.deleteFailed": "Verwijderen van workflow is mislukt. Laad opnieuw.",
"workflows.empty": "Nog geen workflows gemaakt.",
"workflows.loadFailed": "Kan workflows niet laden. Laad opnieuw.",
"workflows.notNamed": "Naamloze workflow",
"workflows.preventUpdates": "Updates voorkomen",
"workflows.publishedNotRemovable": "Kan niet worden verwijderd",
"workflows.refreshTooltip": "Werkstromen vernieuwen (CTRL + SHIFT + R)",
"workflows.reloaded": "Workflows opnieuw geladen.",
"workflows.saved": "Workflow is opgeslagen.",
"workflows.schemasHint": "Beperk deze workflow tot specifieke schema's of laat het leeg voor alle schema's.",
"workflows.syntax.expression": "Expressie",
"workflows.syntax.for": "for",
"workflows.syntax.when": "when",
"workflows.tabEdit": "Bewerken",
"workflows.tabVisualize": "Visualiseren",
"workflows.updateFailed": "Update van workflow is mislukt. Laad opnieuw.",
"workflows.workflowNameHint": "Optionele naam voor de workflow.",
"workflows.workflowNamePlaceholder": "Voer de werkstroomnaam in"
}

472
backend/i18n/source/backend__ignore.json

@ -0,0 +1,472 @@
{
"/Migrations/OldTriggers/AssetChangedTrigger.cs": [
"*"
],
"/Migrations/OldTriggers/ContentChangedTriggerSchema.cs": [
"*"
],
"/Squidex.Domain.Apps.Core.Model/Apps/AppClients.cs": [
"*"
],
"/Squidex.Domain.Apps.Core.Model/Contents/Json/ContentFieldDataConverter.cs": [
"*"
],
"/Squidex.Domain.Apps.Core.Model/Freezable.cs": [
"*"
],
"/Squidex.Domain.Apps.Core.Model/InvariantPartitioning.cs": [
"*"
],
"/Squidex.Domain.Apps.Core.Model/Rules/Rule.cs": [
"*"
],
"/Squidex.Domain.Apps.Core.Model/Schemas/FieldCollection.cs": [
"*"
],
"/Squidex.Domain.Apps.Core.Model/Schemas/NestedField{T}.cs": [
"*"
],
"/Squidex.Domain.Apps.Core.Model/Schemas/RootField{T}.cs": [
"*"
],
"/Squidex.Domain.Apps.Core.Operations/ConvertContent/StringFormatter.cs": [
"{array.Count} {pluralName}",
"{lat}, {lon}",
"<Json />",
"0 {pluralName}",
"1 {singularName}"
],
"/Squidex.Domain.Apps.Core.Operations/DefaultValues/DefaultValueFactory.cs": [
", CultureInfo.InvariantCulture)}T00:00:00Z"
],
"/Squidex.Domain.Apps.Core.Operations/GenerateJsonSchema/ContentSchemaBuilder.cs": [
"*"
],
"/Squidex.Domain.Apps.Core.Operations/GenerateJsonSchema/JsonSchemaExtensions.cs": [
"{field.Name} ({field.RawProperties.Hints})"
],
"/Squidex.Domain.Apps.Core.Operations/HandleRules/Result.cs": [
"*"
],
"/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleService.cs": [
"*"
],
"/Squidex.Domain.Apps.Core.Operations/Scripting/ContentWrapper/ContentDataProperty.cs": [
"*"
],
"/Squidex.Domain.Apps.Core.Operations/Scripting/ContentWrapper/JsonMapper.cs": [
"*"
],
"/Squidex.Domain.Apps.Core.Operations/Scripting/Extensions/HttpJintExtension.cs": [
"*"
],
"/Squidex.Domain.Apps.Core.Operations/Scripting/ScriptOptions.cs": [
"CanReject={CanReject}, CanDisallow={CanDisallow}, AsContext={AsContext}"
],
"/Squidex.Domain.Apps.Core.Operations/Templates/TemplateParseException.cs": [
"*"
],
"/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/CollectionValidator.cs": [
"Min length must be greater than max length."
],
"/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/RangeValidator.cs": [
"Min value must be greater than max value."
],
"/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/StringLengthValidator.cs": [
"Min length must be greater than max length."
],
"/Squidex.Domain.Apps.Entities/Apps/AppUISettingsGrain.cs": [
"Path does not lead to an object."
],
"/Squidex.Domain.Apps.Entities/Apps/BackupApps.cs": [
"The app id or name is not available."
],
"/Squidex.Domain.Apps.Entities/Apps/Diagnostics/OrleansAppsHealthCheck.cs": [
"*"
],
"/Squidex.Domain.Apps.Entities/Apps/Invitation/InvitationEventConsumer.cs": [
"*"
],
"/Squidex.Domain.Apps.Entities/Apps/Templates/CreateBlogCommandMiddleware.cs": [
"*"
],
"/Squidex.Domain.Apps.Entities/Apps/Templates/CreateIdentityCommandMiddleware.cs": [
"*"
],
"/Squidex.Domain.Apps.Entities/Apps/Templates/CreateProfileCommandMiddleware.cs": [
"*"
],
"/Squidex.Domain.Apps.Entities/Apps/Templates/DefaultScripts.cs": [
"*"
],
"/Squidex.Domain.Apps.Entities/Backup/BackupReader.cs": [
"Cannot find attachment."
],
"/Squidex.Domain.Apps.Entities/Backup/RestoreGrain.cs": [
"*"
],
"/Squidex.Domain.Apps.Entities/Backup/TempFolderBackupArchiveLocation.cs": [
"*"
],
"/Squidex.Domain.Apps.Entities/Contents/ContentOperationContext.cs": [
"Cannot resolve app with id {appId}.",
"Cannot resolve schema with id id {schemaId}."
],
"/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/AllTypes.cs": [
"*"
],
"/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/AppQueriesGraphType.cs": [
"*"
],
"/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/AssetGraphType.cs": [
"*"
],
"/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/AssetsResultGraphType.cs": [
"*"
],
"/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/ContentDataFlatGraphType.cs": [
"*"
],
"/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/ContentDataGraphType.cs": [
"*"
],
"/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/ContentGraphType.cs": [
"*"
],
"/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/ContentInterfaceGraphType.cs": [
"*"
],
"/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/ContentsResultGraphType.cs": [
"*"
],
"/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/NestedGraphType.cs": [
"*"
],
"/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Utils/GuidGraphType2.cs": [
"*"
],
"/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Utils/JsonGraphType.cs": [
"*"
],
"/Squidex.Domain.Apps.Entities/Contents/Text/Elastic/ElasticSearchTextIndex.cs": [
"*"
],
"/Squidex.Domain.Apps.Entities/Contents/Text/Lucene/IndexManager.cs": [
"*"
],
"/Squidex.Domain.Apps.Entities/Contents/Text/Lucene/IndexManager_Impl.cs": [
"*"
],
"/Squidex.Domain.Apps.Entities/Notifications/NotificationEmailSender.cs": [
"*"
],
"/Squidex.Domain.Apps.Entities/Rules/Runner/RuleRunnerGrain.cs": [
"Cannot find rule."
],
"/Squidex.Domain.Apps.Entities/Rules/UsageTracking/UsageTriggerHandler.cs": [
"Usage exceeded"
],
"/Squidex.Domain.Users.MongoDb/MongoKeyStore.cs": [
"*"
],
"/Squidex.Infrastructure.Amazon/Assets/AmazonS3AssetStore.cs": [
"*"
],
"/Squidex.Infrastructure.Amazon/Assets/SeekFakerStream.cs": [
"*"
],
"/Squidex.Infrastructure.Azure/Assets/AzureBlobAssetStore.cs": [
"*"
],
"/Squidex.Infrastructure.Azure/Diagnostics/CosmosDbHealthCheck.cs": [
"*"
],
"/Squidex.Infrastructure.Azure/EventSourcing/CosmosDbEventStore_Writer.cs": [
"*"
],
"/Squidex.Infrastructure.Azure/EventSourcing/CosmosDbSubscription.cs": [
"*"
],
"/Squidex.Infrastructure.Azure/EventSourcing/FilterBuilder.cs": [
"*"
],
"/Squidex.Infrastructure.GetEventStore/Diagnostics/GetEventStoreHealthCheck.cs": [
"*"
],
"/Squidex.Infrastructure.GetEventStore/EventSourcing/GetEventStore.cs": [
"*"
],
"/Squidex.Infrastructure.GetEventStore/EventSourcing/GetEventStoreSubscription.cs": [
"*"
],
"/Squidex.Infrastructure.GetEventStore/EventSourcing/ProjectionClient.cs": [
"*"
],
"/Squidex.Infrastructure.GoogleCloud/Assets/GoogleCloudAssetStore.cs": [
"*"
],
"/Squidex.Infrastructure.MongoDb/Assets/MongoGridFsAssetStore.cs": [
"*"
],
"/Squidex.Infrastructure.MongoDb/Diagnostics/MongoDBHealthCheck.cs": [
"*"
],
"/Squidex.Infrastructure.MongoDb/EventSourcing/MongoEventStore_Writer.cs": [
"*"
],
"/Squidex.Infrastructure.MongoDb/MongoDb/MongoRepositoryBase.cs": [
"*"
],
"/Squidex.Infrastructure.RabbitMq/CQRS/Events/RabbitMqEventConsumer.cs": [
"*"
],
"/Squidex.Infrastructure.Redis/RedisPubSub.cs": [
"*"
],
"/Squidex.Infrastructure/Assets/AssetAlreadyExistsException.cs": [
"*"
],
"/Squidex.Infrastructure/Assets/AssetNotFoundException.cs": [
"*"
],
"/Squidex.Infrastructure/Assets/FolderAssetStore.cs": [
"*"
],
"/Squidex.Infrastructure/Assets/HasherStream.cs": [
"*"
],
"/Squidex.Infrastructure/Configuration/ConfigurationExtensions.cs": [
"*"
],
"/Squidex.Infrastructure/Diagnostics/GCHealthCheck.cs": [
"*"
],
"/Squidex.Infrastructure/Diagnostics/OrleansHealthCheck.cs": [
"*"
],
"/Squidex.Infrastructure/Email/SmtpEmailSender.cs": [
"*"
],
"/Squidex.Infrastructure/EventSourcing/DefaultEventDataFormatter.cs": [
"*"
],
"/Squidex.Infrastructure/EventSourcing/EventConsumersHealthCheck.cs": [
"*"
],
"/Squidex.Infrastructure/EventSourcing/WrongEventVersionException.cs": [
"*"
],
"/Squidex.Infrastructure/FileExtensions.cs": [
"*"
],
"/Squidex.Infrastructure/Guard.cs": [
"*"
],
"/Squidex.Infrastructure/Http/DumpFormatter.cs": [
"*"
],
"/Squidex.Infrastructure/Json/Newtonsoft/InstantConverter.cs": [
"Not a valid date time, expected String or Date, but got {reader.TokenType}."
],
"/Squidex.Infrastructure/Json/Newtonsoft/JsonValueConverter.cs": [
"Unexpected end when reading Object."
],
"/Squidex.Infrastructure/Json/Newtonsoft/NamedGuidIdConverter.cs": [
"*"
],
"/Squidex.Infrastructure/Json/Newtonsoft/NamedLongIdConverter.cs": [
"*"
],
"/Squidex.Infrastructure/Json/Newtonsoft/NamedStringIdConverter.cs": [
"*"
],
"/Squidex.Infrastructure/Json/Newtonsoft/RefTokenConverter.cs": [
"*"
],
"/Squidex.Infrastructure/Json/Objects/JsonArray.cs": [
"*"
],
"/Squidex.Infrastructure/Json/Objects/JsonObject.cs": [
"*"
],
"/Squidex.Infrastructure/Json/Objects/JsonValue.cs": [
"*"
],
"/Squidex.Infrastructure/Language.cs": [
"*"
],
"/Squidex.Infrastructure/Languages.cs": [
"*"
],
"/Squidex.Infrastructure/Log/Internal/ConsoleLogProcessor.cs": [
"*"
],
"/Squidex.Infrastructure/Log/Internal/FileLogProcessor.cs": [
"*"
],
"/Squidex.Infrastructure/Log/SemanticLog.cs": [
"*"
],
"/Squidex.Infrastructure/Migrations/MigrationFailedException.cs": [
"*"
],
"/Squidex.Infrastructure/Migrations/Migrator.cs": [
"*"
],
"/Squidex.Infrastructure/NamedId{T}.cs": [
"*"
],
"/Squidex.Infrastructure/Orleans/OrleansWrapperException.cs": [
"*"
],
"/Squidex.Infrastructure/Plugins/PluginManager.cs": [
"*"
],
"/Squidex.Infrastructure/Queries/ClrValue.cs": [
"*"
],
"/Squidex.Infrastructure/Queries/CompareFilter.cs": [
"*"
],
"/Squidex.Infrastructure/Queries/Json/FilterConverter.cs": [
"*"
],
"/Squidex.Infrastructure/Queries/Json/JsonFilterVisitor.cs": [
"*"
],
"/Squidex.Infrastructure/Queries/Json/PropertyPathValidator.cs": [
"*"
],
"/Squidex.Infrastructure/Queries/Json/ValueConverter.cs": [
"*"
],
"/Squidex.Infrastructure/Queries/LogicalFilter.cs": [
"*"
],
"/Squidex.Infrastructure/Queries/OData/ConstantWithTypeVisitor.cs": [
"*"
],
"/Squidex.Infrastructure/Queries/PropertyPath.cs": [
"*"
],
"/Squidex.Infrastructure/Queries/Query.cs": [
"*"
],
"/Squidex.Infrastructure/Queries/SortNode.cs": [
"*"
],
"/Squidex.Infrastructure/Reflection/TypeNameRegistry.cs": [
"*"
],
"/Squidex.Infrastructure/RefToken.cs": [
"*"
],
"/Squidex.Infrastructure/States/DefaultStreamNameResolver.cs": [
"*"
],
"/Squidex.Infrastructure/States/InconsistentStateException.cs": [
"*"
],
"/Squidex.Infrastructure/States/Persistence{TSnapshot,TKey}.cs": [
"*"
],
"/Squidex.Infrastructure/StringExtensions.cs": [
"*"
],
"/Squidex.Web/ApiController.cs": [
"*"
],
"/Squidex.Web/ApiExceptionConverter.cs": [
", e.PropertyNames.Select(FixPropertyName))}: {e.Message}"
],
"/Squidex.Web/ApiExceptionFilterAttribute.cs": [
"An unexpected exception has occurred."
],
"/Squidex.Web/CommandMiddlewares/EnrichWithActorCommandMiddleware.cs": [
"*"
],
"/Squidex.Web/CommandMiddlewares/EnrichWithAppIdCommandMiddleware.cs": [
"*"
],
"/Squidex.Web/CommandMiddlewares/EnrichWithSchemaIdCommandMiddleware.cs": [
"*"
],
"/Squidex.Web/EntityCreatedDto.cs": [
"*"
],
"/Squidex.Web/ErrorDto.cs": [
"*"
],
"/Squidex.Web/Json/TypedJsonInheritanceConverter.cs": [
"*"
],
"/Squidex.Web/Pipeline/FileCallbackResultExecutor.cs": [
"*"
],
"/Squidex.Web/Pipeline/RequestExceptionMiddleware.cs": [
"An unexpected exception has occurred."
],
"/Squidex.Web/Pipeline/SameSiteCookiesServiceCollectionExtensions.cs": [
"*"
],
"/Squidex.Web/Resource.cs": [
"*"
],
"/Squidex.Web/ResourceLink.cs": [
"*"
],
"/Squidex.Web/UrlsOptions.cs": [
"*"
],
"/Squidex/Areas/Api/Config/OpenApi/ErrorDtoProcessor.cs": [
"*"
],
"/Squidex/Areas/Api/Config/OpenApi/ODataExtensions.cs": [
"*"
],
"/Squidex/Areas/Api/Config/OpenApi/OpenApiServices.cs": [
"*"
],
"/Squidex/Areas/Api/Config/OpenApi/SecurityProcessor.cs": [
"*"
],
"/Squidex/Areas/Api/Config/OpenApi/XmlResponseTypesProcessor.cs": [
"*"
],
"/Squidex/Areas/Api/Controllers/Contents/Generator/SchemaOpenApiGenerator.cs": [
"*"
],
"/Squidex/Areas/Api/Controllers/News/Service/FeaturesService.cs": [
"data/version/iv ge {FeatureVersion}"
],
"/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/AssetsFieldPropertiesDto.cs": [
"Use ResolveFirst now"
],
"/Squidex/Areas/Frontend/Middlewares/IndexExtensions.cs": [
"*"
],
"/Squidex/Areas/IdentityServer/Config/LazyClientStore.cs": [
"*"
],
"/Squidex/Areas/IdentityServer/Controllers/Extensions.cs": [
"*"
],
"/Squidex/Areas/IdentityServer/Controllers/Profile/RemoveLoginModel.cs": [
"Provider key."
],
"/Squidex/Config/Domain/EventPublishersServices.cs": [
"*"
],
"/Squidex/Config/Orleans/Helper.cs": [
"*"
],
"/Squidex/Config/Startup/LogConfigurationHost.cs": [
"*"
],
"/Squidex/Pipeline/OpenApi/NSwagHelper.cs": [
"*"
],
"/Squidex/Pipeline/Squid/SquidMiddleware.cs": [
"*"
]
}

20
backend/i18n/source/backend__todos.json

@ -0,0 +1,20 @@
{
"/Squidex.Domain.Apps.Core.Model/Freezable.cs": [
"*"
],
"/Squidex.Domain.Apps.Core.Model/InvariantPartitioning.cs": [
"*"
],
"/Squidex.Domain.Users.MongoDb/MongoKeyStore.cs": [
"*"
],
"/Squidex.Domain.Users/PwnedPasswordValidator.cs": [
"This password has previously appeared in a data breach and should never be used. If you've ever used it anywhere before, change it!"
],
"/Squidex.Infrastructure/FileExtensions.cs": [
"*"
],
"/Squidex.Infrastructure/Guard.cs": [
"*"
]
}

325
backend/i18n/source/backend_en.json

@ -0,0 +1,325 @@
{
"annotations_AbsoluteUrl": "The field {name|lower} must be an absolute URL.",
"annotations_Compare": "The field {name|lower} must be the same as {other|lower}.",
"annotations_Required": "The field {name|lower} is required.",
"apps.alreadyArchieved": "App has already been archived.",
"apps.clients.idAlreadyExists": "A client with the same id already exists.",
"apps.contributors.cannotChangeYourself": "You cannot change your own role.",
"apps.contributors.maxReached": "You have reached the maximum number of contributors for your plan.",
"apps.contributors.onlyOneOwner": "Cannot remove the only owner.",
"apps.languages.fallbackNotFound": "App does not have fallback language '{fallback}'.",
"apps.languages.languageAlreadyAdded": "Language has already been added.",
"apps.languages.masterLanguageNoFallbacks": "Master language cannot have fallback languages.",
"apps.languages.masterLanguageNotOptional": "Master language cannot be made optional.",
"apps.languages.masterLanguageNotRemovable": "Master language cannot be removed.",
"apps.nameAlreadyExists": "An app with the same name already exists.",
"apps.notImage": "File is not an image",
"apps.patterns.nameAlreadyExists": "A pattern with the same name already exists.",
"apps.patterns.patternAlreadyExists": "This pattern already exists but with another name.",
"apps.plans.notFound": "A plan with this id does not exist.",
"apps.plans.notPlanOwner": "Plan can only changed from the user who configured the plan initially.",
"apps.roles.defaultRoleNotRemovable": "Cannot delete a default role.",
"apps.roles.defaultRoleNotUpdateable": "Cannot update a default role.",
"apps.roles.nameAlreadyExists": "A role with the same name already exists.",
"apps.roles.usedRoleByClientsNotRemovable": "Cannot remove a role when a client is assigned.",
"apps.roles.usedRoleByContributorsNotRemovable": "Cannot remove a role when a contributor is assigned.",
"aspnet_annotations_AbsoluteUrl": "The field {0} must be an absolute URL.",
"aspnet_annotations_Compare": "The field {0} must be the same as {other|lower}.",
"aspnet_annotations_Required": "The field {0} is required.",
"assets.assetAlreadyDeleted": "Asset has already been deleted",
"assets.assetFolderAlreadyDeleted": "Asset folder has already been deleted",
"assets.folderNotFound": "Asset folder does not exist.",
"assets.folderRecursion": "Cannot add folder to its own child.",
"assets.maxSizeReached": "You have reached your max asset size.",
"backups.alreadyRunning": "Another backup process is already running.",
"backups.maxReached": "You cannot have more than {max} backups.",
"backups.restoreRunning": "A restore operation is already running.",
"comments.noPermissions": "You can only access your notifications.",
"comments.notUserComment": "Comment is created by another user.",
"common.action": "Action",
"common.aspectHeight": "Aspect height",
"common.aspectWidth": "Aspect width",
"common.calculatedDefaultValue": "Calculated default value",
"common.clientd": "Client ID",
"common.clientId": "Client ID",
"common.clientSecret": "Client Secret",
"common.contributorId": "Contributor ID or email",
"common.data": "Data",
"common.defaultValue": "Default value",
"common.displayName": "Display name",
"common.editor": "Editor",
"common.email": "Email",
"common.field": "Field",
"common.fieldIds": "Field IDs",
"common.fieldName": "Field name",
"common.file": "File",
"common.folderName": "Folder name",
"common.fullTextNotSupported": "Query search clause not supported.",
"common.httpContentTypeNotDefined": "File content-type is not defined.",
"common.httpFileNameNotDefined": "File name is not defined.",
"common.httpInvalidRequest": "The model is not valid.",
"common.httpInvalidRequestFormat": "Request body has an invalid format.",
"common.httpOnlyAsUser": "Not allowed for clients.",
"common.httpValidationError": "Validation error",
"common.initialStep": "Initial step",
"common.jsError": "Failed to execute script with Javascript error: {message}",
"common.jsNotAlloweed": "Script has forbidden the operation.",
"common.jsParseError": "Failed to execute script with Javascript syntax error: {message}",
"common.jsRejected": "Script rejected the operation.",
"common.language": "Language code",
"common.login": "Login",
"common.logout": "Logout",
"common.maxHeight": "Max height",
"common.maxItems": "Max items",
"common.maxLength": "Max length",
"common.maxSize": "Max size",
"common.maxValue": "Max value",
"common.maxWidth": "Max width",
"common.minHeight": "Min height",
"common.minItems": "Min items",
"common.minLength": "Min length",
"common.minSize": "Min size",
"common.minValue": "Min value",
"common.minWidth": "Min width",
"common.name": "Name",
"common.notFoundValue": "- not found -",
"common.numDays": "Num days",
"common.odataFailure": "Failed to parse query: {message}",
"common.odataFilterNotValid": "OData $filter clause not valid: {ex.Message}",
"common.odataNotSupported": "OData operation is not supported.",
"common.odataSearchNotValid": "OData $search clause not valid: {ex.Message}",
"common.oldPassword": "Old password",
"common.other": "Other",
"common.partitioning": "Partitioning",
"common.password": "Password",
"common.passwordConfirm": "Confirm",
"common.pattern": "Pattern",
"common.permissions": "Permissions",
"common.planId": "Plan ID",
"common.previewUrls": "Preview URLs",
"common.product": "Squidex Headless CMS",
"common.properties": "Properties",
"common.property": "Property",
"common.readonlyMode": "Application is in readonly mode at the moment.",
"common.referenceNotFound": "Contains invalid reference '{id}'.",
"common.referenceToInvalidSchema": "Contains reference '{id}' to invalid schema.",
"common.remove": "Remove",
"common.resultTooLarge": "Result set is too large to be retrieved. Use $take parameter to reduce the number of items.",
"common.role": "Role",
"common.save": "Save",
"common.schemaId": "Schema ID",
"common.signup": "Signup",
"common.text": "Text",
"common.trigger": "Trigger",
"common.workflow": "Workflow",
"common.workflowStep": "Step",
"common.workflowTransition": "Transition",
"contents.alreadyDeleted": "Content has already been deleted.",
"contents.bulkInsertQueryNotUnique": "More than one content matches to the query.",
"contents.draftNotCreateForUnpublished": "You can only create a new version when the content is published.",
"contents.draftToDeleteNotFound": "There is nothing to delete.",
"contents.invalidArrayOfIds": "Invalid json type, expected array of guid strings.",
"contents.invalidArrayOfObjects": "Invalid json type, expected array of objects.",
"contents.invalidArrayOfStrings": "Invalid json type, expected array of strings.",
"contents.invalidBoolean": "Invalid json type, expected boolean.",
"contents.invalidGeolocation": "Invalid json type, expected latitude/longitude object.",
"contents.invalidGeolocationLatitude": "Latitude must be between -90 and 90.",
"contents.invalidGeolocationLongitude": "Longitude must be between -180 and 180.",
"contents.invalidGeolocationMoreProperties": "Geolocation can only have latitude and longitude property.",
"contents.invalidNumber": "Invalid json type, expected number.",
"contents.invalidString": "Invalid json type, expected string.",
"contents.listReferences": "{count} Reference(s)",
"contents.singletonNotChangeable": "Singleton content cannot be updated.",
"contents.singletonNotCreatable": "Singleton content cannot be created.",
"contents.singletonNotDeletable": "Singleton content cannot be deleted.",
"contents.statusSchedulingNotInFuture": "Due time must be in the future.",
"contents.statusTransitionNotAllowed": "Cannot change status from {oldStatus} to {newStatus}.",
"contents.validation.aspectRatio": "Must have aspect ratio {width}:{height}.",
"contents.validation.assetNotFound": "Id {id} not found.",
"contents.validation.between": "Must be between {min} and {max}.",
"contents.validation.characterCount": "Must have exactly {count} character(s).",
"contents.validation.charactersBetween": "Must have between {min} and {max} character(s).",
"contents.validation.duplicates": "Must not contain duplicate values.",
"contents.validation.exactValue": "Must be exactly {value}.",
"contents.validation.extension": "Must be an allowed extension.",
"contents.validation.image": "Not an image.",
"contents.validation.invalid": "Not a valid value.",
"contents.validation.itemCount": "Must have exactly {count} item(s).",
"contents.validation.itemCountBetween": "Must have between {min} and {max} item(s).",
"contents.validation.max": "Must be less or equal to {max}.",
"contents.validation.maximumHeight": "Height {height}px must be less than {max}px.",
"contents.validation.maximumSize": "Size of {size} must be less than {max}.",
"contents.validation.maximumWidth": "Width {width}px must be less than {max}px.",
"contents.validation.maxItems": "Must not have more than {max} item(s).",
"contents.validation.maxLength": "Must not have more than {max} character(s).",
"contents.validation.min": "Must be greater or equal to {min}.",
"contents.validation.minimumHeight": "Height {height}px must be greater than {min}px.",
"contents.validation.minimumSize": "Size of {size} must be greater than {min}.",
"contents.validation.minimumWidth": "Width {width}px must be greater than {min}px.",
"contents.validation.minItems": "Must have at least {min} item(s).",
"contents.validation.minLength": "Must have at least {min} character(s).",
"contents.validation.mustBeEmpty": "Value must not be defined.",
"contents.validation.notAllowed": "Not an allowed value.",
"contents.validation.pattern": "Must follow the pattern.",
"contents.validation.regexTooSlow": "Regex is too slow.",
"contents.validation.required": "Field is required.",
"contents.validation.unique": "Another content with the same value exists.",
"contents.validation.unknownField": "Not a known {fieldType}.",
"contents.workflowErorPublishing": "Content workflow prevents publishing.",
"contents.workflowErrorUpdate": "The workflow does not allow updates at status {status}",
"exception.invalidJsonQuery": "Json query not valid: {message}",
"exception.invalidJsonQueryJson": "Json query not valid json: {message}",
"exceptions.domainObjectDeleted": "Entity ({id}) has been deleted.",
"exceptions.domainObjectNotFound": "Entity ({id}) does not exist.",
"exceptions.domainObjectVersion": "Entity ({id}) requested version {expectedVersion}, but found {currentVersion}.",
"history.apps.clientAdded": "added client {[Id]} to app",
"history.apps.clientRevoked": "revoked client {[Id]}",
"history.apps.clientUpdated": "updated client {[Id]}",
"history.apps.contributoreAssigned": "assigned {user:[Contributor]} as {[Role]}",
"history.apps.contributoreRemoved": "removed {user:[Contributor]} from app",
"history.apps.languagedAdded": "added language {[Language]}",
"history.apps.languagedRemoved": "removed language {[Language]}",
"history.apps.languagedSetToMaster": "changed master language to {[Language]}",
"history.apps.languagedUpdated": "updated language {[Language]}",
"history.apps.patternAdded": "added pattern {[Name]}",
"history.apps.patternDeleted": "deleted pattern {[PatternId]}",
"history.apps.patternUpdated": "updated pattern {[Name]}",
"history.apps.planChanged": "changed plan to {[Plan]}",
"history.apps.planReset": "resetted plan",
"history.apps.roleAdded": "added role {[Name]}",
"history.apps.roleDeleted": "deleted role {[Name]}",
"history.apps.roleUpdated": "updated role {[Name]}",
"history.assets.replaced": "replaced asset.",
"history.assets.updated": "updated asset.",
"history.assets.uploaded": "uploaded asset.",
"history.contents.created": "created {[Schema]} content.",
"history.contents.deleted": "deleted {[Schema]} content.",
"history.contents.draftCreated": "created new draft.",
"history.contents.draftDeleted": "deleted draft.",
"history.contents.scheduleCompleted": "scheduled to change status of {[Schema]} content to {[Status]}.",
"history.contents.scheduleFailed": "failed to schedule status change for {[Schema]} content.",
"history.contents.updated": "updated {[Schema]} content.",
"history.schemas.created": "created schema {[Name]}.",
"history.schemas.deleted": "deleted schema {[Name]}.",
"history.schemas.fieldAdded": "added field {[Field]} to schema {[Name]}.",
"history.schemas.fieldDeleted": "deleted field {[Field]} from schema {[Name]}.",
"history.schemas.fieldDisabled": "disabled field {[Field]} of schema {[Name]}.",
"history.schemas.fieldHidden": "has hidden field {[Field]} of schema {[Name]}.",
"history.schemas.fieldLocked": "has locked field {[Field]} of schema {[Name]}.",
"history.schemas.fieldShown": "has shown field {[Field]} of schema {[Name]}.",
"history.schemas.fieldsReordered": "reordered fields of schema {[Name]}.",
"history.schemas.fieldUpdated": "has updated field {[Field]} of schema {[Name]}.",
"history.schemas.published": "published schema {[Name]}.",
"history.schemas.scriptsConfigured": "configured script of schema {[Name]}.",
"history.schemas.unpublished": "unpublished schema {[Name]}.",
"history.schemas.updated": "updated schema {[Name]}.",
"history.statusChanged": "changed status of {[Schema]} content to {[Status]}.",
"login.githubPrivateEmail": "Your email address is set to private in Github. Please set it to public to use Github login.",
"rules.alreadyDeleted": "Rule has already been deleted.",
"rules.ruleAlreadyRunning": "Another rule is already running.",
"schemas.alreadyDeleted": "Schema has already been deleted.",
"schemas.dateTimeCalculatedDefaultAndDefaultError": "Calculated default value and default value cannot be used together.",
"schemas.duplicateFieldName": "Field '{field}' has been added twice.",
"schemas.fieldCannotBeUIField": "Field cannot be an UI field.",
"schemas.fieldIsLocked": "Schema field is locked.",
"schemas.fieldNameAlreadyExists": "A field with the same name already exists.",
"schemas.fieldNotInSchema": "Field is not part of the schema.",
"schemas.fieldsNotCovered": "Field ids do not cover all fields.",
"schemas.nameAlreadyExists": "A schema with the same name already exists.",
"schemas.noPermission": "You do not have permission for this schema.",
"schemas.notFoundId": "Schema {id} does not exist.",
"schemas.number.eitherMinMaxOrAllowedValuesError": "Either allowed values or min and max length can be defined.",
"schemas.number.inlineEditorError": "Inline editing is not allowed for Radio editor.",
"schemas.onlyArraysHaveNested": "Only array fields can have nested fields.",
"schemas.onylArraysInRoot": "Nested field cannot be array fields.",
"schemas.references.resolveError": "Can only resolve references when MaxItems is 1.",
"schemas.string.eitherMinMaxOrAllowedValuesError": "Either allowed values or min and max value can be defined.",
"schemas.string.inlineEditorError": "Inline editing is only allowed for dropdowns, slugs and input fields.",
"schemas.stringEditorsNeedAllowedValuesError": "Radio buttons or dropdown list need allowed values.",
"schemas.tags.editorNeedsAllowedValues": "Checkboxes or dropdown list need allowed values.",
"schemas.uiFieldCannotBeDisabled": "UI field cannot be disabled.",
"schemas.uiFieldCannotBeEnabled": "UI field cannot be enabled.",
"schemas.uiFieldCannotBeHidden": "UI field cannot be hidden.",
"schemas.uiFieldCannotBeShown": "UI field cannot be shown.",
"search.contentResult": "{name} Content",
"search.contentsResult": "{name} Contents",
"search.schemaResult": "{name} Schema",
"security.passwordStolen": "This password has previously appeared in a data breach and should never be used. If you have ever used it anywhere before, change it!",
"users.accessDenied.text": "This operation is not allowed, your account might be locked.",
"users.accessDenied.title": "Access denied",
"users.consent.agree": "I agree!",
"users.consent.cookiesHeadline": "Cookies & Analytics",
"users.consent.cookiesText": "<p> I understand and agree that Squidex uses cookies to ensure you get the best experience on our platform and to store your login status. </p><p> I understand and agree that Squidex has integrated Google Analytics (with the anonymizer function). Google Analytics is a web analytics service to gather and analyse data about the behavior of users. </p><p> I accept the <a href=\"{privacyUrl}\" target=\"_blank\" rel=\"noopener\">privacy policies</a>.</p>",
"users.consent.emailHeadline": "Automated E-Mails (Optional)",
"users.consent.emailText": "I understand and agree that Squidex sends Emails to inform me about new features, breaking changes and down times.",
"users.consent.headline": "We need your consent",
"users.consent.needed": "You have to give consent.",
"users.consent.piiHeadline": "Personal Information",
"users.consent.piiText": "I understand and agree that Squidex collects the following private information that are retrieved from external authentication providers such as Google, Microsoft or Github. <ul class=\"personal-information\"> <li> Basic personal information (first name, last name and picture) are provided to all other users so that they can add you to their working space. </li><li> At anytime you have the option to change these information to anonymize your account. </li><li> Your user account has an unique identifier and for all your changes we track, that you made these changes and provide this information to other users. </li></ul>",
"users.consent.title": "Consent",
"users.error.headline": "Operation failed",
"users.error.text": "We are really sorry that something went wrong.",
"users.error.title": "Error",
"users.errorHappened": "An unexpected exception occurred.",
"users.lockedOutText": "Your account is locked, please contact the administrator.",
"users.lockedOutTitle": "Account locked",
"users.lockYourselfError": "You cannot lock yourself.",
"users.login.askAdmin": "",
"users.login.emailPlaceholder": "Enter Email",
"users.login.error": "Email or password not correct",
"users.login.loginWith": "{action} with <strong>{provider}</strong>",
"users.login.noAccountLoginAction": "Click here to login",
"users.login.noAccountLoginQuestion": "Already registered?",
"users.login.noAccountSignupAction": "Click here to signup",
"users.login.noAccountSignupQuestion": "No account yet?",
"users.login.passwordPlaceholder": "Enter Password",
"users.login.separator": "OR",
"users.logout.headline": "Logged out!",
"users.logout.text": "!Please close this popup.",
"users.logout.title": "Logout",
"users.profile.addLoginDone": "Login added successfully.",
"users.profile.changePassword": "Change Password",
"users.profile.changePasswordDone": "Password changed successfully.",
"users.profile.clientHint": "Use the client credentials to access the API with your profile information and permissions",
"users.profile.clientTitle": "Client",
"users.profile.confirmPassword": "Confirm",
"users.profile.generateClient": "Generate",
"users.profile.generateClientDone": "Client secret generated successfully.",
"users.profile.headline": "Edit Profile",
"users.profile.hideProfile": "Do not show my profile to other users",
"users.profile.loginsTitle": "Logins",
"users.profile.passwordTitle": "Password",
"users.profile.pii": "Personal Information",
"users.profile.propertiesHint": "Use custom properties for rules and scripts.",
"users.profile.propertiesTitle": "Properties",
"users.profile.propertyAdd": "Add Property",
"users.profile.removeLoginDone": "Login provider removed successfully.",
"users.profile.setPassword": "Set Password",
"users.profile.setPasswordDone": "Password set successfully.",
"users.profile.title": "Profile",
"users.profile.updateProfileDone": "Account updated successfully.",
"users.profile.updatePropertiesDone": "Account updated successfully.",
"users.profile.uploadPicture": "Upload Picture",
"users.profile.uploadPictureDone": "Picture uploaded successfully.",
"users.unlockYourselfError": "You cannot unlock yourself.",
"users.userLocked": "User is not allowed to login.",
"users.userNotFound": "Cannot find user.",
"validation.between": "{property|upper} must be between {min} and {max}.",
"validation.greaterEqualsThan": "{property|upper} must be greater or equal to {other|lower}.",
"validation.greaterThan": "{property|upper} must be greater than {other|lower}.",
"validation.javascriptProperty": "{property|upper} is not a Javascript property name.",
"validation.lessEqualsThan": "{property|upper} must be less or equal to {other|lower}.",
"validation.lessThan": "{property|upper} must be less than {other|lower}.",
"validation.notAnImage": "Picture is not a valid image.",
"validation.onlyOneFile": "Can only upload one file.",
"validation.required": "{property|upper} is required.",
"validation.requiredBoth": "If {property1|lower} or {property2|lower} is used both must be defined.",
"validation.requiredValue": "Value must be defined.",
"validation.slug": "{property|upper} is not a valid slug.",
"validation.valid": "{property|upper} is not a valid value.",
"workflows.overlap": "Multiple workflows cover all schemas.",
"workflows.publishedIsInitial": "Initial step cannot be published step.",
"workflows.publishedNotDefined": "Workflow must have a published step.",
"workflows.publishedStepNotFound": "Transition has an invalid target.",
"workflows.schemaOverlap": "The schema '{schema}' is covered by multiple workflows."
}

325
backend/i18n/source/backend_nl.json

@ -0,0 +1,325 @@
{
"annotations_AbsoluteUrl": "Het veld {name|lower} moet een absolute URL zijn.",
"annotations_Compare": "Het veld {name|lower} moet hetzelfde zijn als {other|lower}.",
"annotations_Required": "Het veld {name|lower} is verplicht.",
"apps.alreadyArchieved": "App is al gearchiveerd.",
"apps.clients.idAlreadyExists": "Er bestaat al een client met dezelfde id.",
"apps.contributors.cannotChangeYourself": "Je kunt jouw eigen rol niet wijzigen.",
"apps.contributors.maxReached": "Je heeft het maximale aantal bijdragers voor jouw plan bereikt.",
"apps.contributors.onlyOneOwner": "Kan de enige eigenaar niet verwijderen.",
"apps.languages.fallbackNotFound": "App heeft geen terugvaltaal '{fallback}'.",
"apps.languages.languageAlreadyAdded": "Taal is al toegevoegd.",
"apps.languages.masterLanguageNoFallbacks": "Hoofdtaal kan geen terugval talen hebben.",
"apps.languages.masterLanguageNotOptional": "Hoofdtaal kan niet optioneel worden gemaakt.",
"apps.languages.masterLanguageNotRemovable": "Hoofdtaal kan niet worden verwijderd.",
"apps.nameAlreadyExists": "Er bestaat al een app met dezelfde naam.",
"apps.notImage": "Bestand is geen afbeelding",
"apps.patterns.nameAlreadyExists": "Er bestaat al een patroon met dezelfde naam.",
"apps.patterns.patternAlreadyExists": "Dit patroon bestaat al maar met een andere naam.",
"apps.plans.notFound": "Een plan met deze id bestaat niet.",
"apps.plans.notPlanOwner": "Plan kan alleen worden gewijzigd van de gebruiker die het plan aanvankelijk heeft geconfigureerd.",
"apps.roles.defaultRoleNotRemovable": "Kan een standaardrol niet verwijderen.",
"apps.roles.defaultRoleNotUpdateable": "Kan een standaardrol niet bijwerken.",
"apps.roles.nameAlreadyExists": "Er bestaat al een rol met dezelfde naam.",
"apps.roles.usedRoleByClientsNotRemovable": "Kan een rol niet verwijderen wanneer een client is toegewezen.",
"apps.roles.usedRoleByContributorsNotRemovable": "Kan een rol niet verwijderen wanneer een bijdrager is toegewezen.",
"aspnet_annotations_AbsoluteUrl": "Het veld {0} moet een absolute URL zijn.",
"aspnet_annotations_Compare": "Het veld {0} moet hetzelfde zijn als {other|lower}.",
"aspnet_annotations_Required": "Het veld {0} is verplicht.",
"assets.assetAlreadyDeleted": "Asset is al verwijderd",
"assets.assetFolderAlreadyDeleted": "Assetmap is al verwijderd",
"assets.folderNotFound": "Assetmap bestaat niet.",
"assets.folderRecursion": "Kan map niet toevoegen aan zijn eigen kind.",
"assets.maxSizeReached": "Je hebt jouw maximale assetgrootte bereikt.",
"backups.alreadyRunning": "Er wordt al een ander back-upproces uitgevoerd.",
"backups.maxReached": "Je kunt niet meer dan {max} backups hebben.",
"backups.restoreRunning": "Er wordt al een herstelbewerking uitgevoerd.",
"comments.noPermissions": "Je hebt alleen toegang tot jouw notificaties.",
"comments.notUserComment": "Reactie is gemaakt door een andere gebruiker.",
"common.action": "Actie",
"common.aspectHeight": "Hoogte aspect",
"common.aspectWidth": "Aspect breedte",
"common.calculatedDefaultValue": "Berekende standaardwaarde",
"common.clientd": "Client-ID",
"common.clientId": "Client-ID",
"common.clientSecret": "Clientgeheim",
"common.contributorId": "Bijdrager-ID of e-mailadres",
"common.data": "Gegevens",
"common.defaultValue": "Standaardwaarde",
"common.displayName": "Weergavenaam",
"common.editor": "Editor",
"common.email": "E-mail",
"common.field": "Veld",
"common.fieldIds": "Veld-ID's",
"common.fieldName": "Veldnaam",
"common.file": "Bestand",
"common.folderName": "Mapnaam",
"common.fullTextNotSupported": "Query-zoekclausule niet ondersteund.",
"common.httpContentTypeNotDefined": "Bestandstype inhoud is niet gedefinieerd.",
"common.httpFileNameNotDefined": "Bestandsnaam is niet gedefinieerd.",
"common.httpInvalidRequest": "Het model is niet geldig.",
"common.httpInvalidRequestFormat": "Verzoektekst heeft een ongeldige indeling.",
"common.httpOnlyAsUser": "Niet toegestaan ​​voor klanten.",
"common.httpValidationError": "Validatiefout",
"common.initialStep": "Eerste stap",
"common.jsError": "Kan script niet uitvoeren met Javascript-fout: {message}",
"common.jsNotAlloweed": "Script heeft de bewerking verboden.",
"common.jsParseError": "Kan script niet uitvoeren met Javascript-syntaxisfout: {message}",
"common.jsRejected": "Script heeft de bewerking afgewezen.",
"common.language": "Taalcode",
"common.login": "Inloggen",
"common.logout": "Uitloggen",
"common.maxHeight": "Max. hoogte",
"common.maxItems": "Max. aantal items",
"common.maxLength": "Max. lengte",
"common.maxSize": "Max. grootte",
"common.maxValue": "Max. waarde",
"common.maxWidth": "Max. breedte",
"common.minHeight": "Min. hoogte",
"common.minItems": "Min items",
"common.minLength": "Min. lengte",
"common.minSize": "Min. grootte",
"common.minValue": "Min. waarde",
"common.minWidth": "Min. breedte",
"common.name": "Naam",
"common.notFoundValue": "- niet gevonden -",
"common.numDays": "Aantal dagen",
"common.odataFailure": "Ontleden zoekopdracht: {message}",
"common.odataFilterNotValid": "OData $ filterclausule niet geldig: {ex.Message}",
"common.odataNotSupported": "OData-bewerking wordt niet ondersteund.",
"common.odataSearchNotValid": "OData $ zoekclausule niet geldig: {ex.Message}",
"common.oldPassword": "Oud wachtwoord",
"common.other": "Anders",
"common.partitioning": "Partitioneren",
"common.password": "Wachtwoord",
"common.passwordConfirm": "Bevestigen",
"common.pattern": "Patroon",
"common.permissions": "Rechten",
"common.planId": "Plan-ID",
"common.previewUrls": "Voorbeeld-URL's",
"common.product": "Squidex Headless CMS",
"common.properties": "Eigenschappen",
"common.property": "Eigenschap",
"common.readonlyMode": "Applicatie is momenteel in de alleen-lezen modus.",
"common.referenceNotFound": "Bevat ongeldige referentie '{id}'.",
"common.referenceToInvalidSchema": "Bevat verwijzing '{id}' naar ongeldig schema.",
"common.remove": "Verwijderen",
"common.resultTooLarge": "Resultaatset is te groot om opgehaald te worden. Gebruik $ take parameter om het aantal items te verminderen.",
"common.role": "Rol",
"common.save": "Opslaan",
"common.schemaId": "Schema-ID",
"common.signup": "Aanmelden",
"common.text": "Tekst",
"common.trigger": "Trigger",
"common.workflow": "Workflow",
"common.workflowStep": "Stap",
"common.workflowTransition": "Overgang",
"contents.alreadyDeleted": "Content is al verwijderd.",
"contents.bulkInsertQueryNotUnique": "Meer dan één inhoud komt overeen met de zoekopdracht.",
"contents.draftNotCreateForUnpublished": "Je kunt alleen een nieuwe versie maken wanneer de inhoud is gepubliceerd.",
"contents.draftToDeleteNotFound": "Er is niets te verwijderen.",
"contents.invalidArrayOfIds": "Ongeldig json-type, verwachte array van guid-strings.",
"contents.invalidArrayOfObjects": "Ongeldig json-type, verwachte reeks objecten.",
"contents.invalidArrayOfStrings": "Ongeldig json-type, verwachte reeks strings.",
"contents.invalidBoolean": "Ongeldig json-type, verwachte boolean.",
"contents.invalidGeolocation": "Ongeldig json-type, verwacht object voor lengte- / breedtegraad.",
"contents.invalidGeolocationLatitude": "Breedtegraad moet tussen -90 en 90 zijn.",
"contents.invalidGeolocationLongitude": "Lengtegraad moet tussen -180 en 180 liggen.",
"contents.invalidGeolocationMoreProperties": "Geolocatie kan alleen de eigenschap lengte- en breedtegraad hebben.",
"contents.invalidNumber": "Ongeldig json-type, verwacht aantal.",
"contents.invalidString": "Ongeldig json-type, verwachte string.",
"contents.listReferences": "{count} referentie (s)",
"contents.singletonNotChangeable": "Singleton-inhoud kan niet worden bijgewerkt.",
"contents.singletonNotCreatable": "Singleton-inhoud kan niet worden gemaakt.",
"contents.singletonNotDeletable": "Singleton-inhoud kan niet worden verwijderd.",
"contents.statusSchedulingNotInFuture": "De tijd moet in de toekomst liggen.",
"contents.statusTransitionNotAllowed": "Kan status niet wijzigen van {oldStatus} in {newStatus}.",
"contents.validation.aspectRatio": "Moet aspectverhouding {breedte}: {hoogte} hebben.",
"contents.validation.assetNotFound": "Id {id} niet gevonden.",
"contents.validation.between": "Moet tussen {min} en {max} liggen.",
"contents.validation.characterCount": "Moet exact {count} teken (s) bevatten.",
"contents.validation.charactersBetween": "Moet tussen {min} en {max} teken (s) bevatten.",
"contents.validation.duplicates": "Mag geen dubbele waarden bevatten.",
"contents.validation.exactValue": "Moet exact {waarde} zijn.",
"contents.validation.extension": "Moet een toegestane extensie zijn.",
"contents.validation.image": "Geen afbeelding.",
"contents.validation.invalid": "Geen geldige waarde.",
"contents.validation.itemCount": "Moet exact {count} item (s) bevatten.",
"contents.validation.itemCountBetween": "Moet tussen {min} en {max} item (s) bevatten.",
"contents.validation.max": "Moet kleiner zijn dan of gelijk zijn aan {max}.",
"contents.validation.maximumHeight": "Hoogte {hoogte} px moet kleiner zijn dan {max} px.",
"contents.validation.maximumSize": "Grootte van {size} moet kleiner zijn dan {max}.",
"contents.validation.maximumWidth": "Breedte {breedte} px moet kleiner zijn dan {max} px.",
"contents.validation.maxItems": "Mag niet meer dan {max} item (s) bevatten.",
"contents.validation.maxLength": "Mag niet meer dan {max} teken (s) bevatten.",
"contents.validation.min": "Moet groter zijn dan of gelijk zijn aan {min}.",
"contents.validation.minimumHeight": "Hoogte {hoogte} px moet groter zijn dan {min} px.",
"contents.validation.minimumSize": "Grootte van {size} moet groter zijn dan {min}.",
"contents.validation.minimumWidth": "Breedte {breedte} px moet groter zijn dan {min} px.",
"contents.validation.minItems": "Moet minstens {min} item (s) bevatten.",
"contents.validation.minLength": "Moet minstens {min} teken (s) bevatten.",
"contents.validation.mustBeEmpty": "Waarde mag niet worden gedefinieerd.",
"contents.validation.notAllowed": "Geen toegestane waarde.",
"contents.validation.pattern": "Moet het patroon volgen.",
"contents.validation.regexTooSlow": "Regex is te traag.",
"contents.validation.required": "Veld is verplicht.",
"contents.validation.unique": "Er bestaat een andere inhoud met dezelfde waarde.",
"contents.validation.unknownField": "Onbekend {fieldType}.",
"contents.workflowErorPublishing": "Contentworkflow verhindert publiceren.",
"contents.workflowErrorUpdate": "De werkstroom staat geen updates toe met status {status}",
"exception.invalidJsonQuery": "Json-query niet geldig: {message}",
"exception.invalidJsonQueryJson": "Json-query is niet geldig json: {message}",
"exceptions.domainObjectDeleted": "Entiteit ({id}) is verwijderd.",
"exceptions.domainObjectNotFound": "Entiteit ({id}) bestaat niet.",
"exceptions.domainObjectVersion": "Entiteit ({id}) heeft versie {verwachteVersion} aangevraagd, maar heeft {currentVersion} gevonden.",
"history.apps.clientAdded": "client {[Id]} toegevoegd aan app",
"history.apps.clientRevoked": "ingetrokken klant {[Id]}",
"history.apps.clientUpdated": "bijgewerkte client {[Id]}",
"history.apps.contributoreAssigned": "heeft {user:[Contributor]} toegewezen als {[Role]}",
"history.apps.contributoreRemoved": "heeft {user:[Contributor]} verwijderd uit app",
"history.apps.languagedAdded": "taal toegevoegd {[Language]}",
"history.apps.languagedRemoved": "verwijderde taal {[Language]}",
"history.apps.languagedSetToMaster": "hoofdtaal gewijzigd in {[Language]}",
"history.apps.languagedUpdated": "bijgewerkte taal {[Language]}",
"history.apps.patternAdded": "toegevoegd patroon {[Name]}",
"history.apps.patternDeleted": "verwijderd patroon {[PatternId]}",
"history.apps.patternUpdated": "bijgewerkt patroon {[Name]}",
"history.apps.planChanged": "plan gewijzigd in {[Plan]}",
"history.apps.planReset": "gereset plan",
"history.apps.roleAdded": "toegevoegde rol {[Name]}",
"history.apps.roleDeleted": "verwijderde rol {[Name]}",
"history.apps.roleUpdated": "bijgewerkte rol {[Name]}",
"history.assets.replaced": "item vervangen.",
"history.assets.updated": "bijgewerkt item.",
"history.assets.uploaded": "geüpload item.",
"history.contents.created": "heeft {[Schema]} inhoud gemaakt.",
"history.contents.deleted": "heeft {[Schema]} inhoud verwijderd.",
"history.contents.draftCreated": "nieuw concept gemaakt.",
"history.contents.draftDeleted": "concept verwijderd.",
"history.contents.scheduleCompleted": "gepland om de status van {[Schema]} inhoud te wijzigen in {[Status]}.",
"history.contents.scheduleFailed": "kon statuswijziging voor {[Schema]} - inhoud niet plannen.",
"history.contents.updated": "heeft {[Schema]} inhoud bijgewerkt.",
"history.schemas.created": "heeft schema {[Name]} gemaakt.",
"history.schemas.deleted": "verwijderde schema {[Name]}.",
"history.schemas.fieldAdded": "veld {[Field]} toegevoegd aan schema {[Name]}.",
"history.schemas.fieldDeleted": "heeft veld {[Field]} verwijderd uit schema {[Name]}.",
"history.schemas.fieldDisabled": "uitgeschakeld veld {[Field]} van schema {[Name]}.",
"history.schemas.fieldHidden": "heeft veld {[Field]} van schema {[Name]} verborgen.",
"history.schemas.fieldLocked": "heeft veld {[Field]} van schema {[Name]} vergrendeld.",
"history.schemas.fieldShown": "heeft veld {[Field]} van schema {[Name]} getoond.",
"history.schemas.fieldsReordered": "opnieuw geordende velden van schema {[Name]}.",
"history.schemas.fieldUpdated": "heeft veld {[Field]} van schema {[Name]} bijgewerkt.",
"history.schemas.published": "gepubliceerd schema {[Name]}.",
"history.schemas.scriptsConfigured": "geconfigureerd script van schema {[Name]}.",
"history.schemas.unpublished": "niet-gepubliceerd schema {[Name]}.",
"history.schemas.updated": "bijgewerkt schema {[Name]}.",
"history.statusChanged": "veranderde status van {[Schema]} inhoud in {[Status]}.",
"login.githubPrivateEmail": "Jouw e-mailadres is ingesteld op privé in Github. Stel het in op openbaar om Github-login te gebruiken.",
"rules.alreadyDeleted": "Regel is al verwijderd.",
"rules.ruleAlreadyRunning": "Er wordt al een andere regel uitgevoerd.",
"schemas.alreadyDeleted": "Schema is al verwijderd.",
"schemas.dateTimeCalculatedDefaultAndDefaultError": "Berekende standaardwaarde en standaardwaarde kunnen niet samen worden gebruikt.",
"schemas.duplicateFieldName": "Veld '{field}' is twee keer toegevoegd.",
"schemas.fieldCannotBeUIField": "Veld mag geen UI-veld zijn.",
"schemas.fieldIsLocked": "Schemaveld is vergrendeld.",
"schemas.fieldNameAlreadyExists": "Er bestaat al een veld met dezelfde naam.",
"schemas.fieldNotInSchema": "Veld maakt geen deel uit van het schema.",
"schemas.fieldsNotCovered": "Veld-id's dekken niet alle velden.",
"schemas.nameAlreadyExists": "Er bestaat al een schema met dezelfde naam.",
"schemas.noPermission": "Je hebt geen toestemming voor dit schema.",
"schemas.notFoundId": "Schema {id} bestaat niet.",
"schemas.number.eitherMinMaxOrAllowedValuesError": "Ofwel toegestane waarden of min en max lengte kunnen worden gedefinieerd.",
"schemas.number.inlineEditorError": "Inline bewerken is niet toegestaan ​​voor Radio-editor.",
"schemas.onlyArraysHaveNested": "Alleen matrixvelden kunnen geneste velden bevatten.",
"schemas.onylArraysInRoot": "Genest veld mag geen matrixvelden zijn.",
"schemas.references.resolveError": "Kan alleen verwijzingen omzetten als MaxItems 1 is.",
"schemas.string.eitherMinMaxOrAllowedValuesError": "Ofwel toegestane waarden of min en max waarde kunnen worden gedefinieerd.",
"schemas.string.inlineEditorError": "Inline bewerken is alleen toegestaan ​​voor dropdowns, slugs en invoervelden.",
"schemas.stringEditorsNeedAllowedValuesError": "Radioknoppen of vervolgkeuzelijsten hebben toegestane waarden nodig.",
"schemas.tags.editorNeedsAllowedValues": "Selectievakjes of vervolgkeuzelijsten hebben toegestane waarden nodig.",
"schemas.uiFieldCannotBeDisabled": "UI-veld kan niet worden uitgeschakeld.",
"schemas.uiFieldCannotBeEnabled": "UI-veld kan niet worden ingeschakeld.",
"schemas.uiFieldCannotBeHidden": "UI-veld kan niet worden verborgen.",
"schemas.uiFieldCannotBeShown": "UI-veld kan niet worden weergegeven.",
"search.contentResult": "{name} Inhoud",
"search.contentsResult": "{name} Inhoud",
"search.schemaResult": "{name} Schema",
"security.passwordStolen": "Dit wachtwoord is eerder verschenen bij een datalek en mag nooit worden gebruikt. Als je het ooit eerder hebt gebruikt, verander het dan!",
"users.accessDenied.text": "Deze bewerking is niet toegestaan, je account is mogelijk vergrendeld.",
"users.accessDenied.title": "Toegang geweigerd",
"users.consent.agree": "Akkoord!",
"users.consent.cookiesHeadline": "Cookies en analyse",
"users.consent.cookiesText": "<p> Ik begrijp en ga ermee akkoord dat Squidex cookies gebruikt om ervoor te zorgen dat je de beste ervaring op ons platform krijgt en om jouw inlogstatus op te slaan. </p> <p> Ik begrijp en ga ermee akkoord dat Squidex heeft Google Analytics geïntegreerd (met de anonimiseringsfunctie). Google Analytics is een webanalysedienst om gegevens over het gedrag van gebruikers te verzamelen en te analyseren. </p> <p> Ik accepteer de <a href = \"{privacyUrl} \" target = \"_blank \" rel = \"noopener \"> privacybeleid </a>. </p> ",
"users.consent.emailHeadline": "Geautomatiseerde e-mailberichten (optioneel)",
"users.consent.emailText": "Ik begrijp en ga ermee akkoord dat Squidex e-mails verzendt om mij te informeren over nieuwe functies, verbroken veranderingen en downtime.",
"users.consent.headline": "We hebben je toestemming nodig",
"users.consent.needed": "Je moet toestemming geven.",
"users.consent.piiHeadline": "Persoonlijke informatie",
"users.consent.piiText": "Ik begrijp en ga ermee akkoord dat Squidex de volgende privégegevens verzamelt die worden opgehaald van externe authenticatieleveranciers zoals Google, Microsoft of Github. <ul class = \" personal-information \"> <li> Persoonlijke basisinformatie (voornaam, achternaam en foto) wordt aan alle andere gebruikers verstrekt, zodat ze je aan hun werkruimte kunnen toevoegen. </li> <li> Je hebt op elk moment de mogelijkheid om deze informatie te wijzigen om jouw account te anonimiseren . </li> <li> Jouw gebruikersaccount heeft een unieke identificatie en voor al jouw wijzigingen volgen we, dat je deze wijzigingen hebt aangebracht en deze informatie aan andere gebruikers verstrekt. </li> </ul> ",
"users.consent.title": "Toestemming",
"users.error.headline": "Bewerking mislukt",
"users.error.text": "Het spijt ons echt dat er iets mis is gegaan.",
"users.error.title": "Fout",
"users.errorHappened": "Er is een onverwachte uitzondering opgetreden.",
"users.lockedOutText": "Jouw account is vergrendeld, neem contact op met de beheerder.",
"users.lockedOutTitle": "Account vergrendeld",
"users.lockYourselfError": "Je kunt jezelf niet vergrendelen.",
"users.login.askAdmin": "",
"users.login.emailPlaceholder": "E-mailadres invoeren",
"users.login.error": "E-mailadres of wachtwoord niet correct",
"users.login.loginWith": "{action} met <strong> {provider} </strong>",
"users.login.noAccountLoginAction": "Klik hier om in te loggen",
"users.login.noAccountLoginQuestion": "Al geregistreerd?",
"users.login.noAccountSignupAction": "Klik hier om in te schrijven",
"users.login.noAccountSignupQuestion": "Nog geen account?",
"users.login.passwordPlaceholder": "Voer wachtwoord in",
"users.login.separator": "OF",
"users.logout.headline": "Uitgelogd!",
"users.logout.text": "! Sluit deze pop-up.",
"users.logout.title": "Uitloggen",
"users.profile.addLoginDone": "Login succesvol toegevoegd.",
"users.profile.changePassword": "Wachtwoord wijzigen",
"users.profile.changePasswordDone": "Wachtwoord succesvol gewijzigd.",
"users.profile.clientHint": "Gebruik de clientreferenties om toegang te krijgen tot de API met jouw profielinformatie en machtigingen",
"users.profile.clientTitle": "Client",
"users.profile.confirmPassword": "Bevestigen",
"users.profile.generateClient": "Genereer",
"users.profile.generateClientDone": "Clientgeheim succesvol gegenereerd.",
"users.profile.headline": "Profiel bewerken",
"users.profile.hideProfile": "Mijn profiel niet aan andere gebruikers tonen",
"users.profile.loginsTitle": "Logins",
"users.profile.passwordTitle": "Wachtwoord",
"users.profile.pii": "Persoonlijke informatie",
"users.profile.propertiesHint": "Gebruik aangepaste eigenschappen voor regels en scripts.",
"users.profile.propertiesTitle": "Eigenschappen",
"users.profile.propertyAdd": "Eigenschap toevoegen",
"users.profile.removeLoginDone": "Login provider succesvol verwijderd.",
"users.profile.setPassword": "Wachtwoord instellen",
"users.profile.setPasswordDone": "Wachtwoord succesvol ingesteld.",
"users.profile.title": "Profiel",
"users.profile.updateProfileDone": "Account succesvol bijgewerkt.",
"users.profile.updatePropertiesDone": "Account succesvol bijgewerkt.",
"users.profile.uploadPicture": "Afbeelding uploaden",
"users.profile.uploadPictureDone": "Foto succesvol geüpload.",
"users.unlockYourselfError": "Je kunt jezelf niet ontgrendelen.",
"users.userLocked": "Gebruiker mag niet inloggen.",
"users.userNotFound": "Kan gebruiker niet vinden.",
"validation.between": "{property|upper} moet tussen {min} en {max} liggen.",
"validation.greaterEqualsThan": "{property|upper} moet groter zijn dan of gelijk zijn aan {other|lower}.",
"validation.greaterThan": "{property|upper} moet groter zijn dan {other|lower}.",
"validation.javascriptProperty": "{property|upper} is geen Javascript-eigenschapsnaam.",
"validation.lessEqualsThan": "{property|upper} moet kleiner zijn dan of gelijk zijn aan {other|lower}.",
"validation.lessThan": "{property|upper} moet kleiner zijn dan {other|lower}.",
"validation.notAnImage": "Afbeelding is geen geldige afbeelding.",
"validation.onlyOneFile": "Kan slechts één bestand uploaden.",
"validation.required": "{property|upper} is vereist.",
"validation.requiredBoth": "Als {property1|lower} of {property2|lower} wordt gebruikt, moeten beide worden gedefinieerd.",
"validation.requiredValue": "Waarde moet worden gedefinieerd.",
"validation.slug": "{property|upper} is geen geldige slug.",
"validation.valid": "{property|upper} is geen geldige waarde.",
"workflows.overlap": "Meerdere workflows omvatten alle schema's.",
"workflows.publishedIsInitial": "Eerste stap kan niet worden gepubliceerd stap.",
"workflows.publishedNotDefined": "Workflow moet een gepubliceerde stap hebben.",
"workflows.publishedStepNotFound": "Overgang heeft een ongeldig doel.",
"workflows.schemaOverlap": "Het schema '{schema}' wordt gedekt door meerdere workflows."
}

217
backend/i18n/source/frontend__ignore.json

@ -0,0 +1,217 @@
{
"/_theme.html": [
"*"
],
"/app.module.ts": [
"Application element not found"
],
"/features/apps/pages/apps-page.component.html": [
"&middot;",
"|"
],
"/features/content/pages/content/content-event.component.html": [
"&middot;"
],
"/features/content/pages/content/content-page.component.html": [
"."
],
"/features/content/shared/forms/array-item.component.html": [
"#{{index + 1}}"
],
"/features/content/shared/forms/field-editor.component.html": [
"*",
"{{field.displayName}} {{displaySuffix}}"
],
"/features/content/shared/references/references-editor.component.html": [
"&middot;"
],
"/features/rules/pages/rules/actions/generic-action.component.html": [
"*"
],
"/features/rules/pages/rules/triggers/asset-changed-trigger.component.html": [
"*"
],
"/features/rules/pages/rules/triggers/comment-trigger.component.html": [
"*"
],
"/features/rules/pages/rules/triggers/content-changed-trigger.component.html": [
"*"
],
"/features/rules/pages/rules/triggers/schema-changed-trigger.component.html": [
"*"
],
"/features/rules/pages/rules/triggers/usage-trigger.component.html": [
"*"
],
"/features/schemas/pages/schema/fields/types/array-validation.component.html": [
"-"
],
"/features/schemas/pages/schema/fields/types/assets-validation.component.html": [
"-",
"3",
"4",
"px"
],
"/features/schemas/pages/schema/fields/types/boolean-ui.component.html": [
"Checkbox",
"Toggle"
],
"/features/schemas/pages/schema/fields/types/date-time-ui.component.html": [
"DateTime"
],
"/features/schemas/pages/schema/fields/types/geolocation-ui.component.html": [
"Map"
],
"/features/schemas/pages/schema/fields/types/number-ui.component.html": [
"Dropdown",
"Input",
"Radio",
"Stars"
],
"/features/schemas/pages/schema/fields/types/number-validation.component.html": [
"-"
],
"/features/schemas/pages/schema/fields/types/references-ui.component.html": [
"Checkboxes",
"Dropdown",
"List",
"Resolve reference"
],
"/features/schemas/pages/schema/fields/types/references-validation.component.html": [
"-"
],
"/features/schemas/pages/schema/fields/types/string-ui.component.html": [
"Color",
"Dropdown",
"HTML",
"Input",
"Markdown",
"Radio",
"RichText",
"StockPhoto",
"TextArea"
],
"/features/schemas/pages/schema/fields/types/string-validation.component.html": [
"-"
],
"/features/schemas/pages/schema/fields/types/tags-ui.component.html": [
"Checkboxes",
"Dropdown"
],
"/features/schemas/pages/schema/fields/types/tags-validation.component.html": [
"-"
],
"/features/settings/pages/backups/backup.component.html": [
","
],
"/features/settings/pages/clients/client-connect-form.component.html": [
"1",
"2",
"3",
"4",
"nuget"
],
"/features/settings/pages/clients/client-connect-form.component.ts": [
"Content-Type: application/x-www-form-urlencoded",
"grant_type=client_credentials&\r\n client_id=${app}:${client.id}&\r\n client_secret=${client.secret}&\r\n scope=squidex-api"
],
"/features/settings/pages/contributors/import-contributors-dialog.component.html": [
"user1@squidex.io;user2@squidex.io"
],
"/framework/angular/forms/validators.ts": [
"matchValidator(): other control is not found in parent group"
],
"/framework/angular/modals/dialog-renderer.component.html": [
"&times;"
],
"/framework/angular/pager.component.html": [
"10",
"20",
"30",
"50"
],
"/framework/angular/pipes/date-time.pipes.ts": [
"dd. LLL yyyy",
"dd. MMM"
],
"/framework/angular/pipes/money.pipe.ts": [
"<span class=\"decimal\">"
],
"/framework/angular/pipes/numbers.pipes.ts": [
" kMGTPEZY"
],
"/index.html": [
"*"
],
"/shared/components/app-form.component.html": [
"appName"
],
"/shared/components/forms/geolocation-editor.component.ts": [
"&copy; <a href=\"http://osm.org/copyright\">OpenStreetMap</a> contributors"
],
"/shared/components/forms/markdown-editor.component.ts": [
"*",
"fa fa-bold",
"fa fa-header",
"fa fa-italic",
"fa fa-list-ul",
"fa fa-quote-left",
"Generic List"
],
"/shared/components/forms/rich-editor.component.ts": [
"code image media link lists advlist paste",
"undo redo | styleselect | bold italic | alignleft aligncenter | bullist numlist outdent indent | link image media | assets"
],
"/shared/components/search/queries/filter-logical.component.html": [
"AND",
"OR"
],
"/shared/components/search/queries/sorting.component.html": [
"ascending",
"descending"
],
"/shared/components/search/search-form.component.ts": [
"form-inline search-form"
],
"/shared/services/auth.service.ts": [
"*"
],
"/shared/services/rules.service.ts": [
"Asset changed",
"Content changed",
"For asset changes like uploaded, updated (reuploaded), renamed, deleted...",
"For content changes like created, updated, published, unpublished...",
"Manually triggered",
"Schema changed",
"To invoke processes manually, for example to update your static site...",
"Usage exceeded",
"User mentioned",
"When a schema definition has been created, updated, published or deleted...",
"When a user is mentioned in any comment...",
"When monthly API calls exceed a specified limit for one time a month..."
],
"/shared/services/schemas.types.ts": [
"Invalid properties type"
],
"/shared/state/contents.forms.visitors.ts": [
"<Json />",
"yyyy-MM-dd HH:mm:ss"
],
"/shared/state/patterns.forms.ts": [
"[A-z0-9]+[A-z0-9\\- ]*[A-z0-9]"
],
"/shared/state/query.ts": [
"ends with",
"is empty",
"is equals to",
"is greater than",
"is greater than or equals to",
"is less than",
"is less than or equals to",
"is not equals to",
"starts with"
],
"/theme/icomoon/demo.html": [
"*"
]
}

1
backend/i18n/source/frontend__todos.json

@ -0,0 +1 @@
{}

853
backend/i18n/source/frontend_en.json

@ -0,0 +1,853 @@
{
"api.contentApi": "Content API",
"api.generalApi": "General API",
"api.graphql": "GraphQL",
"api.graphqlPageTitle": "GraphQL",
"api.pageTitle": "API",
"api.title": "API",
"apps.allApps": "All Apps",
"apps.appLoadFailed": "Failed to load app. Please reload.",
"apps.appNameHint": "You can only use letters, numbers and dashes and not more than 40 characters.",
"apps.appNameValidationMessage": "Name can contain lower case letters (a-z), numbers and dashes between.",
"apps.appNameWarning": "The app name cannot be changed later.",
"apps.appsButtonCreate": "Apps Overview",
"apps.appsButtonFallbackTitle": "Apps Overview",
"apps.archieve": "Archive App",
"apps.archieveConfirmText": "Remove pattern",
"apps.archieveConfirmTitle": "Do you really want to archive this app?",
"apps.archieveWarning": "Once you archive an app, there is no going back. Please be certain.",
"apps.archiveFailed": "Failed to archive app. Please reload.",
"apps.create": "Create App",
"apps.createBlankApp": "New App.",
"apps.createBlankAppDescription": "Create a new blank app without content and schemas.",
"apps.createBlogApp": "New Blog Sample",
"apps.createBlogAppDescription": "Start with our ready to use blog.",
"apps.createFailed": "Failed to create app. Please reload.",
"apps.createIdentityApp": "New Identity App",
"apps.createIdentityAppDescription": "Create app for Squidex Identity.",
"apps.createIdentityAppV2": "New Identity App V2",
"apps.createIdentityAppV2Description": "Create app for Squidex Identity V2.",
"apps.createProfileApp": "New Profile Sample",
"apps.createProfileAppDescription": "Create your profile page.",
"apps.createWithTemplate": "Create {template} Sample",
"apps.empty": "You are not collaborating to any app yet",
"apps.generalSettings": "General",
"apps.generalSettingsDangerZone": "General",
"apps.image": "Image",
"apps.imageDrop": "Drop to upload",
"apps.listPageTitle": "Apps",
"apps.loadFailed": "Failed to load apps. Please reload.",
"apps.removeImage": "Remove image",
"apps.removeImageFailed": "Failed to remove app image. Please reload.",
"apps.updateFailed": "Failed to update app. Please reload.",
"apps.upgradeHintCurrent": "You are on the {plan} plan.",
"apps.upgradeHintUpgrade": "Upgrade!",
"apps.uploadImage": "Drop an file to replace the app image. Use a square size.",
"apps.uploadImageButton": "Upload File",
"apps.uploadImageFailed": "Failed to upload image. Please reload.",
"apps.uploadImageTooBig": "App image is too big.",
"apps.welcomeSubtitle": "Welcome to Squidex.",
"apps.welcomeTitle": "Hi {user}",
"assets.createFolder": "Create Folder",
"assets.createFolderFailed": "Failed to create asset folder. Please reload.",
"assets.createFolderTooltip": "Create new folder (CTRL + SHIFT + G)",
"assets.deleteConfirmText": "Do you really want to delete the asset?",
"assets.deleteConfirmTitle": "Delete asset",
"assets.deleteFailed": "Failed to delete asset. Please reload.",
"assets.deleteFolderConfirmText": "Do you really want to delete the folder and all assets?",
"assets.deleteFolderConfirmTitle": "Delete folder",
"assets.deleteMetadataConfirmText": "Do you really want to remove this metadata?",
"assets.deleteMetadataConfirmTitle": "Remove metadata",
"assets.downloadVersion": "Download this Version",
"assets.dropToUpdate": "Drop to update",
"assets.duplicateFile": "Asset has already been uploaded.",
"assets.editor.flipHorizontally": "Flip Horizontally",
"assets.editor.flipVertically": "Flip Vertically",
"assets.editor.focusPointLabel": "Select position of focus point",
"assets.editor.focusPointPreview": "Preview for different sizes",
"assets.editor.rotateLeft": "Rotate Left",
"assets.editor.rotateRight": "Rotate Right",
"assets.fileTooBig": "Asset is too big.",
"assets.folderName": "Folder Name",
"assets.folderNameHint": "The folder name is used as display name and must not be unique.",
"assets.insertAssets": "Insert Assets",
"assets.linkSelected": "Link selected assets ({count})",
"assets.listPageTitle": "Assets",
"assets.loadFailed": "Failed to load assets. Please reload.",
"assets.loadFoldersFailed": "Failed to load asset folders. Please reload.",
"assets.metadata": "Metadata",
"assets.metadataAdd": "Add Metadata",
"assets.moveFailed": "Failed to move asset. Please reload.",
"assets.protected": "Protected",
"assets.refreshTooltip": "Refresh Assets (CTRL + SHIFT + R)",
"assets.reloaded": "Assets reloaded.",
"assets.renameFolder": "Rename Folder",
"assets.replaceConfirmText": "Do you really want to replace the asset with a newer version",
"assets.replaceConfirmTitle": "Replace asset?",
"assets.replaceFailed": "Failed to replace asset. Please reload.",
"assets.searchByName": "Search by name",
"assets.searchByTags": "Search by tags",
"assets.selectMany": "Select assets",
"assets.tabFocusPoint": "Focus Point",
"assets.tabHistory": "History",
"assets.tabImage": "Image",
"assets.tabMetadata": "Metadata",
"assets.updated": "Asset has been updated.",
"assets.updateFailed": "Failed to update asset. Please reload.",
"assets.updateFolderFailed": "Failed to update asset folder. Please reload.",
"assets.uploadByDialog": "Select File(s",
"assets.uploadByDrop": "Drop files here to upload",
"assets.uploaderUploadHere": "No upload in progress, drop files here.",
"assets.uploadFailed": "Failed to upload asset. Please reload.",
"assets.uploadHint": "Drop file on existing item to replace the asset with a newer version.",
"backups.backupCountAssetsLabel": "Assets",
"backups.backupCountAssetsTooltip": "Archived assets",
"backups.backupCountEventsLabel": "Events",
"backups.backupCountEventsTooltip": "Archived events",
"backups.backupDownload": "Download",
"backups.backupDownloadLink": "Ready",
"backups.backupDuration": "Duration",
"backups.deleteConfirmText": "Do you really want to delete the backup?",
"backups.deleteConfirmTitle": "Delete backup",
"backups.deleted": "Backup is about to be deleted.",
"backups.deleteFailed": "Failed to delete backup.",
"backups.empty": "No backups created yet.",
"backups.loadFailed": "Failed to load backups.",
"backups.maximumReached": "Your have reached the maximum number of backups: 10.",
"backups.refreshTooltip": "Refresh backups (CTRL + SHIFT + R)",
"backups.reloaded": "Backups reloaded.",
"backups.restore": "Restore Backup",
"backups.restoreFailed": "Failed to start restore.",
"backups.restoreLastStatus": "Last Restore Operation",
"backups.restoreLastUrl": "Url to backup",
"backups.restoreNewAppName": "Optional app name",
"backups.restorePageTitle": "Restore Backup",
"backups.restoreStarted": "Restore started, it can take several minutes to complete.",
"backups.restoreStartedLabel": "Started",
"backups.restoreStoppedLabel": "Stopped",
"backups.restoreTitle": "Restore Backup",
"backups.start": "Start Backup",
"backups.started": "Backup started, it can take several minutes to complete.",
"backups.startedLabel": "Started",
"backups.startFailed": "Failed to start backup.",
"clients.add": "Add Client",
"clients.addFailed": "Failed to add client. Please reload.",
"clients.allowAnonymous": "Allow anonymous access.",
"clients.allowAnonymousHint": "Allow access to the API without an access token to all resources that are configured via the role of this client. Do not give more than one client anonymous access.",
"clients.apiCallsLimit": "Max API Calls",
"clients.apiCallsLimitHint": "Limit the number of API calls this client can make per month to protect your API contingent for other clients that are more important.",
"clients.clientIdValidationMessage": "Name can only contain letters, numbers, dashes and spaces.",
"clients.clientNamePlaceholder": "Enter client name",
"clients.connect": "Connect",
"clients.connectWizard.cli": "Connect with Squidex CLI",
"clients.connectWizard.cliHint": "Download the CLI and connect to this app to start backups, sync schemas or export content.",
"clients.connectWizard.cliStep1": "Get the latest Squidex CLI",
"clients.connectWizard.cliStep1Download": "[Download the CLI from Github](https://github.com/Squidex/squidex-samples/releases)",
"clients.connectWizard.cliStep1Hint": "The releases contains binaries for all major operation system and a small download if you have .NET Core installed.",
"clients.connectWizard.cliStep2": "Add `<your Squidex CLI download directory>` to your `$PATH` variable",
"clients.connectWizard.cliStep3": "Add your app name the CLI config",
"clients.connectWizard.cliStep3Hint": "You can manage configuration to multiple apps in the CLI and switch to an app.",
"clients.connectWizard.cliStep4": "Switch to your app in the CLI",
"clients.connectWizard.manually": "Connect manually",
"clients.connectWizard.manuallyHint": "Get instructions how to establish a connection with Postman or curl.",
"clients.connectWizard.manuallyStep1": "Get a token using curl",
"clients.connectWizard.manuallyStep2": "Just use the following token",
"clients.connectWizard.manuallyStep3": "Add the token as HTTP header to all requests",
"clients.connectWizard.manuallyTokenHint": "Tokens usally expire after 30days, but you can request multiple tokens.",
"clients.connectWizard.postManDocs": "Start with the Postman tutorial in the [Documentation](https://docs.squidex.io/02-documentation/developer-guides/api-overview/postman).",
"clients.connectWizard.sdk": "Connect to your App with SDK",
"clients.connectWizard.sdkHelp": "You need another SDK?",
"clients.connectWizard.sdkHelpLink": "Contact us in the Support Forum",
"clients.connectWizard.sdkHint": "Download an SDK and establish a connection to this app.",
"clients.connectWizard.sdkStep1": "Install the .NET SDK",
"clients.connectWizard.sdkStep1Download": "The SDK is available on [nuget](https://www.nuget.org/packages/Squidex.ClientLibrary/)",
"clients.connectWizard.sdkStep2": "Create a client manager",
"clients.connectWizard.step0Title": "Setup client",
"clients.connectWizard.step1Title": "Choose connection method",
"clients.connectWizard.step2Title": "Connect",
"clients.deleteConfirmText": "Do you really want to revoke the client?",
"clients.deleteConfirmTitle": "Revoke client",
"clients.empty": "No client created yet.",
"clients.loadFailed": "Failed to load clients. Please reload.",
"clients.refreshTooltip": "Refresh clients (CTRL + SHIFT + R)",
"clients.reloaded": "Clients reloaded.",
"clients.revokeFailed": "Failed to revoke client. Please reload.",
"clients.tokenFailed": "Failed to create token. Please retry.",
"comments.create": "Create a comment",
"comments.createFailed": "Failed to create comment.",
"comments.deleteConfirmText": "Do you really want to delete the comment?",
"comments.deleteConfirmTitle": "Delete comment",
"comments.deleteFailed": "Failed to delete comment.",
"comments.follow": "Follow",
"comments.loadFailed": "Failed to load comments.",
"comments.title": "Comments",
"comments.updateFailed": "Failed to update comment.",
"common.actions": "Actions",
"common.administration": "Administration",
"common.administrationPageTitle": "Administration",
"common.api": "API",
"common.apps": "Apps",
"common.aspectRatio": "AspectRatio",
"common.assets": "Assets",
"common.back": "Back",
"common.backups": "Backups",
"common.bytes": "bytes",
"common.cancel": "Cancel",
"common.clear": "Clear",
"common.clientId": "Client Id",
"common.clients": "Clients",
"common.clientSecret": "Client Secret",
"common.clipboardAdded": "Value has been added to your clipboard.",
"common.clone": "Clone",
"common.cluster": "Cluster",
"common.clusterPageTitle": "Cluster",
"common.comments": "Comments",
"common.confirm": "Confirm",
"common.consumers": "Consumers",
"common.content": "Content",
"common.contents": "Contents",
"common.continue": "Continue",
"common.contributors": "Contributors",
"common.create": "Create",
"common.created": "Created",
"common.date": "Date",
"common.dateTimeEditor.local": "Local",
"common.dateTimeEditor.now": "Now",
"common.dateTimeEditor.nowTooltip": "Use Now (UTC)",
"common.dateTimeEditor.today": "Today",
"common.dateTimeEditor.todayTooltip": "Use Today (UTC)",
"common.dateTimeEditor.utc": "UTC",
"common.delete": "Delete",
"common.description": "Description",
"common.displayName": "Display Name",
"common.edit": "Edit",
"common.email": "Email",
"common.error": "Error",
"common.errorBack": "Back to previous page.",
"common.errorNoPermission": "You do not have the permissions to do this.",
"common.errorNotFound": "Not Found",
"common.event": "Event",
"common.events": "Events",
"common.executed": "Executed",
"common.expertMode": "Expert Mode",
"common.failed": "Failed",
"common.fallback": "Fallback",
"common.field": "Field",
"common.files": "Files",
"common.filters": "Filters",
"common.folders": "Folders",
"common.generalSettings": "Common",
"common.generate": "Generate",
"common.github": "Github",
"common.height": "Height",
"common.help": "Help",
"common.helpTour": "Click the help icon to show a context specific help page. Go to",
"common.hide": "Hide",
"common.hints": "Hints",
"common.history": "History",
"common.httpConflict": "Failed to make the update. Another user has made a change. Please reload.",
"common.httpLimit": "You have exceeded the maximum limit of API calls.",
"common.label": "Label",
"common.languages": "Languages",
"common.latitudeShort": "Lat",
"common.loading": "Loading",
"common.logout": "Logout",
"common.logs": "Logs",
"common.longitudeShort": "Lon",
"common.mapHide": "Hide map",
"common.mapShow": "Show map",
"common.message": "Message",
"common.name": "Name",
"common.no": "No",
"common.nothingChanged": "Nothing has been changed.",
"common.noValue": "- No value -",
"common.or": "or",
"common.pagerInfo": "{itemFirst}-{itemLast} of {numberOfItems}",
"common.password": "Password",
"common.passwordConfirm": "Confirm Password",
"common.pattern": "Pattern",
"common.patterns": "Patterns",
"common.permissions": "Permissions",
"common.preview": "Preview",
"common.product": "Squidex Headless CMS",
"common.project": "Project",
"common.refresh": "Refresh",
"common.rename": "Rename",
"common.requiredHint": "required",
"common.reset": "Reset",
"common.restore": "Restore",
"common.role": "Role",
"common.roles": "Roles",
"common.rules": "Rules",
"common.sampleCodeLabel": "Sample Code at",
"common.save": "Save",
"common.saveShortcut": "CTRL + S",
"common.schemas": "Schemas",
"common.searchGoogleMaps": "Search Google Maps",
"common.searchResults": "Search Results",
"common.separateByLine": "Separate by line",
"common.settings": "Settings",
"common.sidebarTour": "The sidebar navigation contains useful context specific links. Here you can view the history how this schema has changed over time.",
"common.slug": "Slug",
"common.stars.max": "Must not have more more than 15 stars",
"common.status": "Status",
"common.statusChangeTo": "Change to",
"common.submit": "Submit",
"common.subscription": "Subscription",
"common.succeeded": "Succeeded",
"common.tagAdd": ", to add tag",
"common.tagAddReference": ", to add reference",
"common.tagAddSchema": ", to add schema",
"common.tags": "Tags",
"common.tagsAll": "All tags",
"common.time": "Time",
"common.update": "Update",
"common.url": "URL",
"common.users": "Users",
"common.value": "Value",
"common.width": "Width",
"common.workflow": "Workflow",
"common.workflows": "Workflows",
"common.yes": "Yes",
"contents.arrayAddItem": "Add Item",
"contents.arrayCloneItem": "Clone this item",
"contents.arrayCollapseAll": "Collapse all items",
"contents.arrayCollapseItem": "Collapse this item",
"contents.arrayExpandAll": "Expand all items",
"contents.arrayExpandItem": "Expand this item",
"contents.arrayMoveBottom": "Move this item to bottom",
"contents.arrayMoveDown": "Move this item down",
"contents.arrayMoveTop": "Move this item to top",
"contents.arrayMoveUp": "Move this item up",
"contents.arrayNoFields": "Add a nested field first to add items.",
"contents.assetsUpload": "Drop files or click",
"contents.autotranslate": "Autotranslate from master language",
"contents.changeStatusTo": "Change content item(s) to {action}",
"contents.changeStatusToImmediately": "Set to {action} immediately.",
"contents.changeStatusToLater": "Set to {action} at a later point date and time.",
"contents.contentNotValid": "Content element not valid, please check the field with the red bar on the left in all languages (if localizable).",
"contents.create": "New",
"contents.createContentTooltip": "New Content (CTRL + SHIFT + G)",
"contents.created": "Content created successfully.",
"contents.createdByFieldDescription": "The user who created the content item.",
"contents.createFailed": "Failed to create content. Please reload.",
"contents.createFieldDescription": "The date time when the content item was created.",
"contents.createPageTitle": "Create Content",
"contents.createTitle": "New Content",
"contents.currentStatusLabel": "Current Version",
"contents.deleteConfirmText": "Do you really want to delete the content?",
"contents.deleteConfirmTitle": "Delete content",
"contents.deleteFailed": "Failed to delete content. Please reload.",
"contents.deleteManyConfirmText": "Do you really want to delete the selected content items?",
"contents.deleteVersionConfirmText": "Do you really want to delete this version?",
"contents.deleteVersionFailed": "Failed to delete version. Please reload.",
"contents.draftNew": "New Draft",
"contents.draftStatus": "New Version",
"contents.editPageTitle": "Edit Content",
"contents.editTitle": "Edit Content",
"contents.languageModeAll": "All Languages",
"contents.languageModeSingle": "Single Language",
"contents.lastModifiedByFieldDescription": "The user who modified the content item the last time.",
"contents.lastModifiedFieldDescription": "The date time when the content item was modified the last time.",
"contents.lastUpdatedLabel": "Last Updated",
"contents.loadContent": "Load",
"contents.loadContentFailed": "Failed to load content. Please reload.",
"contents.loadDataFailed": "Failed to load data. Please reload.",
"contents.loadFailed": "Failed to load contents. Please reload.",
"contents.loadVersionFailed": "Failed to version a new version. Please reload.",
"contents.newStatusFieldDescription": "The new status of the content item.",
"contents.noReference": "- No Reference -",
"contents.pendingChangesTextToChange": "You have unsaved changes.\n\nWhen you change the status you will loose them.\n\n**Do you want to continue anyway?**",
"contents.pendingChangesTextToClose": "You have unsaved changes.\n\nWhen you close the current content view you will loose them.\n\n**Do you want to continue anyway?**",
"contents.pendingChangesTitle": "Unsaved changes",
"contents.referencesCreateNew": "Add New",
"contents.referencesCreatePublish": "Create and Publish",
"contents.referencesLink": "Link selected contents ({count})",
"contents.referencesSelectExisting": "Select Existing",
"contents.referencesSelectSchema": "Select {schema}",
"contents.refreshTooltip": "Refresh Contents (CTRL + SHIFT + R)",
"contents.reloaded": "Contents reloaded.",
"contents.saveAndPublish": "Save and Publish",
"contents.scheduledAt": "at",
"contents.scheduledAtLabel": "at",
"contents.scheduledTo": "to",
"contents.schemasPageTitle": "Contents",
"contents.searchPlaceholder": "Fulltext search",
"contents.searchSchemasPlaceholder": "Search for schemas...",
"contents.selectionCount": "{count} items selected",
"contents.statusFieldDescription": "The status of the content item.",
"contents.statusQueries": "Status Queries",
"contents.stockPhotoEmpty": "Nothing selected",
"contents.stockPhotoSearch": "Search for Photos by Unsplash",
"contents.unsavedChangesText": "You have unsaved changes. Do you want to load them now?",
"contents.unsavedChangesTitle": "Unsaved changes",
"contents.updated": "Content updated successfully.",
"contents.updateFailed": "Failed to update content. Please reload.",
"contents.validationHint": "Please remember to check all languages when you see validation errors.",
"contents.versionCompare": "Compare",
"contents.versionDelete": "Delete this Version",
"contents.versionFieldDescription": "The version of the content item",
"contents.versionViewing": "Viewing version **{version}**.",
"contents.viewLatest": "View latest",
"contents.viewReset": "Reset Default View",
"contributors.add": "Add Contributor",
"contributors.addFailed": "Failed to add contributors. Please reload.",
"contributors.contributorAssigned": "A new user with the entered email address has been created and assigned as contributor.",
"contributors.contributorAssignedExisting": "User has been assigned",
"contributors.contributorAssignedInvited": "User has been invited and assigned.",
"contributors.contributorAssignedOld": "User has been added as contributor.",
"contributors.deleteConfirmText": "Do you really want to remove the contributor?",
"contributors.deleteConfirmTitle": "Remove contributor",
"contributors.deleteFailed": "Failed to delete contributors. Please reload.",
"contributors.emailPlaceholder": "Find existing user or invite by email",
"contributors.empty": "No contributors found.",
"contributors.import.emailsDetected": "Emails detected: {count}",
"contributors.import.run": "Add Contributors",
"contributors.import.run2": "Import",
"contributors.importButton": "Add many contributors at once",
"contributors.importHintg": "Big team?",
"contributors.importTitle": "Import contributors",
"contributors.loadFailed": "Failed to load contributors. Please reload.",
"contributors.planHint": "Your plan allows up to {maxContributors} contributors.",
"contributors.refreshTooltip": "Refresh contributors (CTRL + SHIFT + R)",
"contributors.reloaded": "Contributors reloaded.",
"contributors.search": "Search",
"contributors.userNotFound": "The user does not exist.",
"dashboard.apiCallsCard": "API Calls",
"dashboard.apiCallsChart": "API Calls Chart",
"dashboard.apiCallsLimitLabel": "Monthly limit",
"dashboard.apiCallsSummaryCard": "API Calls Summary",
"dashboard.apiDocumentationCard": "API Documentation",
"dashboard.apiPerformanceCard": "API Performance (ms): {summary}ms avg",
"dashboard.apiPerformanceChart": "API Performance Chart",
"dashboard.assetSizeCard": "Assets Size (MB",
"dashboard.assetSizeLabel": "Total Size",
"dashboard.assetSizeLimitLabel": "Total limit",
"dashboard.assetTotalSize": "Asset Total Storage Size",
"dashboard.assetUpdloadsCountChart": "Asset Uploads Count Chart",
"dashboard.assetUploadsCard": "Assets Uploads",
"dashboard.assetUploadsSizeChart": "Asset Uploads Size Chart",
"dashboard.configSaved": "Configuration saved.",
"dashboard.contentApi": "Content API",
"dashboard.contentApiDescription": "OpenAPI 3.0 compatible documentation for your app content.",
"dashboard.contentsSummaryCard": "Number of items",
"dashboard.currentMonthLabel": "This month",
"dashboard.downloadLog": "Download Log",
"dashboard.editConfig": "Edit Config",
"dashboard.githubCard": "Github",
"dashboard.githubCardDescription": "Get the source code from Github and report bugs or ask for support.",
"dashboard.historyCard": "History",
"dashboard.pageTitle": "Dashboard",
"dashboard.resetConfigConfirmText": "Do you really want to reset the dashboard to the default?",
"dashboard.resetConfigConfirmTitle": "Reset config",
"dashboard.schemaNewCard": "New Schema",
"dashboard.schemaNewCardDescription": "A schema defines the structure of your content element.",
"dashboard.schemasCard": "Schemas",
"dashboard.schemasCardDescription": "Get an insight to the data model of this app.",
"dashboard.stackedChart": "Stacked",
"dashboard.supportCard": "Feedback & Support",
"dashboard.supportCardDescription": "Provide feedback and request features to help us to improve Squidex.",
"dashboard.trafficChart": "API Traffic Chart",
"dashboard.trafficHeader": "Traffic (MB)",
"dashboard.trafficLimitLabel": "Monthly limit",
"dashboard.trafficSummaryCard": "API Traffic Summary",
"dashboard.welcomeText": "Welcome to **{app}** dashboard.",
"dashboard.welcomeTitle": "Hi {user}",
"eventConsumers.loadFailed": "Failed to load event consumers. Please reload.",
"eventConsumers.pageTitle": "Event Consumers",
"eventConsumers.position": "Position",
"eventConsumers.refreshTooltip": "Refresh event consumers (CTRL + SHIFT + R)",
"eventConsumers.reloaded": "Event Consumers reloaded.",
"eventConsumers.resetFailed": "Failed to reset event consumer. Please reload.",
"eventConsumers.resetTooltip": "Reset Event Consumer",
"eventConsumers.startFailed": "Failed to start event consumer. Please reload.",
"eventConsumers.startTooltip": "Start Event Consumer",
"eventConsumers.stopFailed": "Failed to stop event consumer. Please reload.",
"eventConsumers.stopTooltip": "Stop Event Consumer",
"features.loadFailed": "Failed to load features. Please reload.",
"history.loadFailed": "Failed to load history. Please reload.",
"history.title": "Activity",
"languages.add": "Add Language",
"languages.addFailed": "Failed to add language. Please reload.",
"languages.deleteConfirmText": "Do you really want to remove the language?",
"languages.deleteConfirmTitle": "Remove language",
"languages.deleteFailed": "Failed to delete language. Please reload.",
"languages.loadFailed": "Failed to load languages. Please reload.",
"languages.master": "Is Master",
"languages.masterHint": "Other languages fall back to the master if no fallback is defined.",
"languages.optional": "Is Optional",
"languages.optionalHint": "Values for optional languages must not be entered, even if field is required.",
"languages.refreshTooltip": "Refresh languages (CTRL + SHIFT + R)",
"languages.reloaded": "Languages reloaded.",
"languages.updateFailed": "Failed to change language. Please reload.",
"news.headline": "What's new?",
"news.title": "New Features",
"notifo.subscripeTooltip": "Click this button to subscribe to all changes and to receive push notifications.",
"patterns.deleteConfirmText": "Do you really want to remove this pattern?",
"patterns.deleteConfirmTitle": "Delete pattern",
"patterns.deleteFailed": "Failed to remove pattern. Please reload.",
"patterns.empty": "No pattern created yet.",
"patterns.loadFailed": "Failed to add pattern. Please reload.",
"patterns.nameValidationMessage": "Name can only contain letters, numbers, dashes and spaces.",
"patterns.refreshTooltip": "Refresh patterns (CTRL + SHIFT + R)",
"patterns.reloaded": "Patterns reloaded.",
"patterns.updateFailed": "Failed to update pattern. Please reload.",
"plans.billingPortal": "Billing Portal",
"plans.billingPortalHint": "Go to Billing Portal for payment history and subscription overview.",
"plans.change": "Change",
"plans.changeConfirmTitle": "Change subscription",
"plans.changeFailed": "Failed to change plan. Please reload.",
"plans.includedCalls": "API Calls",
"plans.includedContributors": "Contributors",
"plans.includedStorage": "Storage",
"plans.includedTraffic": "Traffic",
"plans.loadFailed": "Failed to load plans. Please reload.",
"plans.noPlanConfigured": "No plan configured, this app has unlimited usage.",
"plans.notPlanOwner": "You have not created the subscription. Therefore you cannot change the plan.",
"plans.perMonth": "Per Month",
"plans.perYear": "Per Year",
"plans.refreshTooltip": "Refresh Plans (CTRL + SHIFT + R)",
"plans.reloaded": "Plans reloaded.",
"plans.selected": "Selected",
"profile.title": "Profile",
"profile.userEmail": "Signed in with",
"roles.add": "Add role",
"roles.addFailed": "Failed to add role. Please reload.",
"roles.default.owner": "Can do everything, including deleting the app.",
"roles.default.reader": "Can only read assets and contents.",
"roles.defaults.developer": "Can use the API view, edit assets, contents, schemas, rules, workflows and patterns.",
"roles.defaults.editor": "Can edit assets and contents and view workflows.",
"roles.deleteConfirmText": "Delete role",
"roles.deleteConfirmTitle": "Do you really want to delete the role?",
"roles.loadFailed": "Failed to load roles. Please reload.",
"roles.loadPermissionsFailed": "Failed to load permissions. Please reload.",
"roles.refreshTooltip": "Refresh roles (CTRL + SHIFT + R)",
"roles.reloaded": "Roles reloaded.",
"roles.revokeFailed": "Failed to revoke role. Please reload.",
"roles.roleNamePlaceholder": "Enter role name",
"roles.updateFailed": "Failed to update role. Please reload.",
"rules.actionEdit": "Edit Action",
"rules.cancelFailed": "Failed to cancel rule. Please reload.",
"rules.create": "Create new Rule",
"rules.createFailed": "Failed to create rule. Please reload.",
"rules.createTooltip": "New Rule (CTRL + SHIFT + G)",
"rules.deleteConfirmText": "Do you really want to delete the rule?",
"rules.deleteConfirmTitle": "Delete rule",
"rules.deleteFailed": "Failed to delete rule. Please reload.",
"rules.disableFailed": "Failed to disable rule. Please reload.",
"rules.empty": "No rule created yet.",
"rules.emptyAddRule": "Add Rule",
"rules.enableFailed": "Failed to enable rule. Please reload.",
"rules.enqueued": "Rule has been added to the queue.",
"rules.listPageTitle": "Rules",
"rules.loadFailed": "Failed to load Rules. Please reload.",
"rules.readMore": "Read More",
"rules.refreshEventsTooltip": "Refresh Events (CTRL + SHIFT + R)",
"rules.refreshTooltip": "Refresh Rules (CTRL + SHIFT + R)",
"rules.reloaded": "Rules reloaded.",
"rules.restarted": "Rule will start to run in a few seconds.",
"rules.ruleEvents.cancelFailed": "Failed to cancel rule event. Please reload.",
"rules.ruleEvents.enqueue": "Enqueue",
"rules.ruleEvents.enqueued": "Events enqueued. Will be resend in a few seconds.",
"rules.ruleEvents.enqueueFailed": "Failed to enqueue rule event. Please reload.",
"rules.ruleEvents.lastInvokedLabel": "Last Invocation",
"rules.ruleEvents.listPageTitle": "Rule Events",
"rules.ruleEvents.loadFailed": "Failed to load events. Please reload.",
"rules.ruleEvents.nextAttemptLabel": "Next",
"rules.ruleEvents.numAttemptsLabel": "Attempts",
"rules.ruleEvents.reloaded": "RuleEvents reloaded.",
"rules.ruleSyntax.if": "If",
"rules.ruleSyntax.then": "then",
"rules.run": "Run",
"rules.runFailed": "Failed to run rule. Please reload.",
"rules.runningRule": "Rule '{name}' is currently running.",
"rules.runRuleConfirmText": "Do you really want to run the rule for all events?",
"rules.runRuleConfirmTitle": "Run rule",
"rules.stop": "Rule will stop soon.",
"rules.triggerConfirmText": "Do you really want to trigger the rule?",
"rules.triggerConfirmTitle": "Trigger rule",
"rules.triggerEdit": "Edit Trigger",
"rules.triggerFailed": "Failed to trigger rule. Please reload.",
"rules.unnamed": "Unnamed Rule",
"rules.updateFailed": "Failed to update rule. Please reload.",
"rules.wizard.actionHint": "The selection of the action type cannot be changed later.",
"rules.wizard.selectAction": "Select Action",
"rules.wizard.selectTrigger": "Select Trigger",
"rules.wizard.triggerHint": "The selection of the trigger type cannot be changed later.",
"schemas.addField": "Add Field",
"schemas.addFieldAndClose": "Create and close",
"schemas.addFieldAndCreate": "Create and add field",
"schemas.addFieldAndEdit": "Create and edit field",
"schemas.addFieldButton": "Add Field",
"schemas.addFieldFailed": "Failed to add field. Please reload.",
"schemas.addNestedField": "Add Nested Field",
"schemas.changeCategoryFailed": "Failed to change category. Please reload.",
"schemas.clone": "Clone Schema",
"schemas.contextMenuTour": "Open the context menu to delete the schema or to create some scripts for content changes.",
"schemas.create": "Create Schema",
"schemas.createCategory": "Create new category...",
"schemas.createFailed": "Failed to create schema. Please reload.",
"schemas.createSchemaTooltip": "New Schema (CTRL + SHIFT + G)",
"schemas.deleteConfirmText": "Do you really want to delete the schema?",
"schemas.deleteConfirmTitle": "Delete schema",
"schemas.deleteFailed": "Failed to delete schema. Please reload.",
"schemas.deleteFieldFailed": "Failed to delete field. Please reload.",
"schemas.deleteRuleConfirmText": "Do you really want to remove this Field Rule?",
"schemas.deleteRuleConfirmTitle": "Remove Field Rule",
"schemas.deleteUrlConfirmText": "Do you really want to remove this URL?",
"schemas.deleteUrlConfirmTitle": "Remove URL",
"schemas.disableFieldFailed": "Failed to disable field. Please reload.",
"schemas.enableFieldFailed": "Failed to enable field. Please reload.",
"schemas.export.deleteFields": "Delete fields",
"schemas.export.recreateFields": "Recreate fields",
"schemas.export.synchronize": "Synchronize",
"schemas.field.allowedValues": "Allowed Values",
"schemas.field.defaultValue": "Default Value",
"schemas.field.deleteConfirmText": "Do you really want to delete the field?",
"schemas.field.deleteConfirmTitle": "Delete field",
"schemas.field.disable": "Disable in UI",
"schemas.field.disabledMarker": "Disabled",
"schemas.field.editor": "Editor",
"schemas.field.editorUrl": "Editor Url",
"schemas.field.editorUrlHint": "Url to your plugin if you use a custom editor.",
"schemas.field.empty": "No field created yet.",
"schemas.field.enable": "Enable in UI",
"schemas.field.enabledMarker": "Enabled",
"schemas.field.hiddenMarker": "Hidden",
"schemas.field.hide": "Hide in API",
"schemas.field.hintsHint": "Describe this schema for documentation and user interfaces.",
"schemas.field.inlineEditable": "Inline Editable",
"schemas.field.labelHint": "Display name for documentation and user interfaces.",
"schemas.field.localizable": "Localizable",
"schemas.field.localizableHint": "You can mark the field as localizable. It means that is dependent on the language, for example a city name.",
"schemas.field.localizableMarker": "localizable",
"schemas.field.lock": "Lock and prevent changes",
"schemas.field.lockConfirmText": "WARNING: Locking a field cannot be undone! Locked field definitions cannot be unlocked, deleted, or changed anymore. Do you really want to lock this field?",
"schemas.field.lockedMarker": "Locked",
"schemas.field.nameHint": "The name of the field in the API response.",
"schemas.field.namePlaceholder": "Enter field name",
"schemas.field.nameValidationMessage": "Name must be a valid javascript name in camel case.",
"schemas.field.placeholder": "Placeholder",
"schemas.field.placeholderHint": "Define the placeholder for the input control.",
"schemas.field.required": "Required",
"schemas.field.show": "Show in API",
"schemas.field.tabCommon": "Common",
"schemas.field.tabEditing": "Editing",
"schemas.field.tabValidation": "Validation",
"schemas.field.tagsHint": "Tags to annotate your field for automation processes.",
"schemas.field.unique": "Unique",
"schemas.field.visibleMarker": "Visible",
"schemas.fieldTypes.array.count": "Items",
"schemas.fieldTypes.array.countMax": "Max Items",
"schemas.fieldTypes.array.countMin": "Min Items",
"schemas.fieldTypes.array.description": "List of embedded objects.",
"schemas.fieldTypes.assets.allowDuplicates": "Allow duplicate values",
"schemas.fieldTypes.assets.count": "Count",
"schemas.fieldTypes.assets.countMax": "Max Assets",
"schemas.fieldTypes.assets.countMin": "Min Assets",
"schemas.fieldTypes.assets.description": "Images, videos, documents.",
"schemas.fieldTypes.assets.fileExtensions": "File Extensions",
"schemas.fieldTypes.assets.mustBeImage": "Must be Image",
"schemas.fieldTypes.assets.previewMode": "PreviewMode",
"schemas.fieldTypes.assets.previewModeHint": "The preview mode for assets in content lists.",
"schemas.fieldTypes.assets.previewModeName": "Only file name",
"schemas.fieldTypes.assets.previewModeTumbnailName": "Thumbnail and file name",
"schemas.fieldTypes.assets.previewModeTumbnailOrName": "Only thumbnail or file name if not an image",
"schemas.fieldTypes.assets.resolve": "Resolve first asset",
"schemas.fieldTypes.assets.resolveHint": "Show the first referenced asset in the content list.",
"schemas.fieldTypes.assets.size": "Size",
"schemas.fieldTypes.assets.sizeMax": "Min Size",
"schemas.fieldTypes.assets.sizeMin": "Max Size",
"schemas.fieldTypes.boolean.description": "Yes or no, true or false.",
"schemas.fieldTypes.dateTime.defaultMode": "Default Mode",
"schemas.fieldTypes.dateTime.description": "Events date, opening hours.",
"schemas.fieldTypes.dateTime.rangeMax": "Max Value",
"schemas.fieldTypes.dateTime.rangeMin": "Min Value",
"schemas.fieldTypes.geolocation.description": "Coordinates: latitude and longitude.",
"schemas.fieldTypes.json.description": "Data in JSON format, for developers.",
"schemas.fieldTypes.number.description": "ID, order number, rating, quantity.",
"schemas.fieldTypes.number.range": "Range",
"schemas.fieldTypes.number.rangeMax": "Max Value",
"schemas.fieldTypes.number.rangeMin": "Min Value",
"schemas.fieldTypes.references.count": "Items",
"schemas.fieldTypes.references.countMax": "Max Items",
"schemas.fieldTypes.references.countMin": "Min Items",
"schemas.fieldTypes.references.description": "Links to other content items.",
"schemas.fieldTypes.references.resolveHint": "Show the name of the referenced item in content list when MaxItems is set to 1.",
"schemas.fieldTypes.string.description": "Titles, names, paragraphs.",
"schemas.fieldTypes.string.length": "Length",
"schemas.fieldTypes.string.lengthMax": "Max Length",
"schemas.fieldTypes.string.lengthMin": "Min Length",
"schemas.fieldTypes.string.pattern": "Regex Pattern",
"schemas.fieldTypes.string.patternMessage": "Pattern Message",
"schemas.fieldTypes.string.suggestions": "Suggestions",
"schemas.fieldTypes.tags.count": "Items",
"schemas.fieldTypes.tags.countMax": "Max Items",
"schemas.fieldTypes.tags.countMin": "Min Items",
"schemas.fieldTypes.tags.description": "Special format for tags.",
"schemas.fieldTypes.ui.description": "Separator for editing UI.",
"schemas.hideFieldFailed": "Failed to hide field. Please reload.",
"schemas.import": "Import schema",
"schemas.listFields": "List Fields",
"schemas.listFieldsEmpty": "Drop field here or reorder them to show the fields in the content list. When no list field is defined, the first field is used.",
"schemas.loadFailed": "Failed to load schemas. Please reload.",
"schemas.loadSchemaFailed": "Failed to load schema. Please reload.",
"schemas.lockFieldFailed": "Failed to lock field. Please reload.",
"schemas.modeMultiple": "Multiple contents",
"schemas.modeMultipleDescription": "Best for multiple instances like blog posts, pages, authors, products...",
"schemas.modeSingle": "Single content",
"schemas.modeSingleDescription": "Best for single instances like the home page, privacy policies, settings...",
"schemas.nameWarning": "These values cannot be changed later.",
"schemas.previewUrls.empty": "No preview urls configured.",
"schemas.previewUrls.help": "Checkout the integrated help page to learn more about preview URL's.",
"schemas.previewUrls.namePlaceholder": "Web or Mobile",
"schemas.previewUrls.title": "Preview URLs",
"schemas.previewUrls.urlPlaceholder": "URL with variables",
"schemas.published": "Published",
"schemas.publishedTour": "Note, that you have to publish the schema before you can add content to it.",
"schemas.publishFailed": "Failed to publish schema. Please reload.",
"schemas.referenceFields": "Reference Fields",
"schemas.referenceFieldsEmpty": "Drop field here or reorder them to show the fields when referenced by another content. When no reference field is defined, the list fields are used instead.",
"schemas.reloaded": "Schemas reloaded.",
"schemas.reorderFieldsFailed": "Failed to reorder fields. Please reload.",
"schemas.rules.action": "Action",
"schemas.rules.condition": "Condition in Javascript",
"schemas.rules.empty": "No field rules configured.",
"schemas.rules.title": "Field Rules",
"schemas.rules.when": "when",
"schemas.saved": "Schema saved successfully.",
"schemas.saveFieldAndClose": "Save and close",
"schemas.saveFieldAndNew": "Save and add field",
"schemas.schemaHintsHint": "Describe this schema for documentation and user interfaces.",
"schemas.schemaLabelHint": "Display name for documentation and user interfaces.",
"schemas.schemaNameHint": "You can only use letters, numbers and dashes and not more than 40 characters.",
"schemas.schemaNameValidationMessage": "Name can only contain letters, numbers, dashes and spaces.",
"schemas.schemaTagsHint": "Tags to annotate your schema for automation processes.",
"schemas.searchPlaceholder": "Search for schemas...",
"schemas.showFieldFailed": "Failed to show field. Please reload.",
"schemas.synchronized": "Schema synchronized successfully.",
"schemas.synchronizeFailed": "Failed to synchronize schema. Please reload.",
"schemas.tabFields": "Fields",
"schemas.tabJson": "Json",
"schemas.tabMore": "More",
"schemas.tabScripts": "Scripts",
"schemas.tabUI": "UI",
"schemas.ui": "Assigned fields",
"schemas.ui.unassignedFields": "Unassigned fields",
"schemas.unpublished": "Unpublished",
"schemas.unpublishFailed": "Failed to unpublish schema. Please reload.",
"schemas.updateFailed": "Failed to update schema. Please reload.",
"schemas.updateFieldFailed": "Failed to update field. Please reload.",
"schemas.updatePreviewUrlsFailed": "Failed to configure preview urls. Please reload.",
"schemas.updateRulesFailed": "Failed to update schema rules. Please reload.",
"schemas.updateScriptsFailed": "Failed to update schema scripts. Please reload.",
"schemas.updateUIFieldsFailed": "Failed to update UI fields. Please reload.",
"search.addFilter": "Add Filter",
"search.addGroup": "Add Group",
"search.addSorting": "Add Sorting",
"search.advancedTour": "Click this icon to show the advanced search menu!",
"search.customQuery": "Custom Query",
"search.fullTextTour": "Search for content using full text search over all fields and languages!",
"search.help": "Read more about filtering in the [Documentation](https://https://docs.squidex.io/04-guides/02-api.html).",
"search.myQueries": "My queries",
"search.nameQuery": "Name your query",
"search.queriesEmpty": "Search for {types} and use <i class=\"icon-star-empty\"></i> icon in search form to save query for all contributors.",
"search.queryAllNewestFirst": "All (newest first)",
"search.queryAllOldestFirst": "All (oldest first)",
"search.quickNavPlaceholder": "Quick Nav (Press 'q')",
"search.saveQueryMyself": "Save the query only for myself.",
"search.searchFailed": "Failed to make search. Please reload.",
"search.sharedQueries": "Shared queries",
"search.sorting": "Sorting",
"start.login": "Login to Squidex",
"start.loginHint": "The login button will open a new popup. Once you are logged in successful we will redirect you to the Squidex management portal.",
"start.madeBy": "Proudly made by",
"start.madeByCopyright": "Sebastian Stehle and Contributors, 2016-2020",
"tour.joinForum": "Join our Forum",
"tour.joinGithub": "Join us on Github",
"tour.skip": "Skip Tour",
"tour.step0Next": "Let's take a look around",
"tour.step0Text": "You can start managing and distributing your content right away, but we we'd like to walk you through some basics first...\n\nHow'that",
"tour.step1Next": "Continue",
"tour.step1Text": "An App is the repository for your project, e.g. (blog, web shop or mobile app). You can assign contributors to your app to work together.\n\nYou can create an unlimited number of Apps in Squidex to manage multiple projects at the same time.",
"tour.step2Next": "Keep going!",
"tour.step2Text": "Schemas define the structure of your content, the fields and the data types of a content item.\n\nBefore you can add content to your schema, make sure to hit the 'Publish' button at the top to make the schema available to your content editors.",
"tour.step3Next": "Almost there!",
"tour.step3Text": "Content is the actual data in your app which is grouped by the schema.\n\nSelect a published schema first, then add content for this schema.",
"tour.step4Next": "Got It!",
"tour.step4Text": "The assets contains all files that can also be linked to your content. For example images, videos or documents.\n\nYou can upload the assets here and use them later or also upload them directly when you create a new content item with an asset field.",
"tour.step5Text": "But that's not all of the support we can provide.\n\nYou can got to https://docs.squidex.io/> to read more.\n\nDo you want to join our community?",
"tour.step5Title": "Awesome, now you know the basics!",
"tour.tooltipConfirm": "Got It",
"tour.tooltipStop": "Stop Tour",
"tour.welcome": "Welcome to",
"tour.welcomeProduct": "Squidex CMS",
"translate.translateFailed": "Failed to translate text. Please reload.",
"usages.loadCallsFailed": "Failed to load calls usage. Please reload.",
"usages.loadMonthlyCallsFailed": "Failed to load monthly API calls. Please reload.",
"usages.loadStorageFailed": "Failed to load storage usage. Please reload.",
"usages.loadTodayStorageFailed": "Failed to load todays storage size. Please reload.",
"users.create": "New",
"users.createFailed": "Failed to create user. Please reload.",
"users.createPageTitle": "Create User",
"users.createTitle": "New User",
"users.createTooltip": "New User (CTRL + N)",
"users.editPageTitle": "Edit User",
"users.editTitle": "Edit User",
"users.listPageTitle": "User Management",
"users.listTitle": "Users",
"users.loadFailed": "Failed to load users. Please reload.",
"users.loadUserFailed": "Failed to load user. Please reload.",
"users.lockTooltip": "Lock User",
"users.passwordConfirmValidationMessage": "Passwords must be the same.",
"users.refreshTooltip": "Refresh Users (CTRL + SHIFT + R)",
"users.reloaded": "Users reloaded.",
"users.search": "Search for user",
"users.unlockTooltip": "Unlock User",
"users.updateFailed": "Failed to update user. Please reload.",
"validation.between": "{field} must be between '{min}' and '{max}'.",
"validation.betweenlength": "{field|upper} must have between {minlength} and {maxlength} item(s).",
"validation.betweenlengthstring": "{field|upper} must have between {minlength} and {maxlength} character(s).",
"validation.email": "{field|upper} must be an email address.",
"validation.exactly": "{field|upper} must be exactly '{expected}'.",
"validation.exactlylength": "{field|upper} must have exactly {expected} item(s).",
"validation.exactlylengthstring": "{field|upper} must have exactly {expected} character(s).",
"validation.match": "{message}",
"validation.max": "{field|upper} must be less or equal to '{max}'.",
"validation.maxlength": "{field|upper} must not have more than {requiredlength} item(s).",
"validation.maxlengthstring": "{field|upper} must not have more than {requiredlength} character(s).",
"validation.min": "{field|upper} must be greater or equal to '{min}'.",
"validation.minlength": "{field|upper} must have at least {requiredlength} item(s).",
"validation.minlengthstring": "{field|upper} must have at least {requiredlength} character(s).",
"validation.pattern": "{field|upper} does not match to the pattern.",
"validation.patternmessage": "{message}",
"validation.required": "{field|upper} is required.",
"validation.requiredTrue": "{field|upper} is required.",
"validation.uniquestrings": "{field|upper} must not contain duplicate values.",
"validation.validarrayvalues": "{field|upper} contains an invalid value: {invalidvalue}.",
"validation.validdatetime": "{field|upper} is not a valid date time.",
"validation.validvalues": "{field|upper} is not a valid value.",
"workflows.add": "Add Workflow",
"workflows.addStep": "Add Step",
"workflows.createFailed": "Failed to create workflow. Please reload.",
"workflows.deleteConfirmText": "Do you really want to remove the workflow?",
"workflows.deleteConfirmTitle": "Delete workflow",
"workflows.deleteFailed": "Failed to delete Workflow. Please reload.",
"workflows.empty": "No workflows created yet.",
"workflows.loadFailed": "Failed to load workflows. Please reload.",
"workflows.notNamed": "Unnamed Workflow",
"workflows.preventUpdates": "Prevent updates",
"workflows.publishedNotRemovable": "Cannot be removed",
"workflows.refreshTooltip": "Refresh workflows (CTRL + SHIFT + R)",
"workflows.reloaded": "Workflows reloaded.",
"workflows.saved": "Workflow has been saved.",
"workflows.schemasHint": "Restrict this workflow to specific schemas or keep it empty for all schemas.",
"workflows.syntax.expression": "Expression",
"workflows.syntax.for": "for",
"workflows.syntax.when": "when",
"workflows.tabEdit": "Editing",
"workflows.tabVisualize": "Visualize",
"workflows.updateFailed": "Failed to update Workflow. Please reload.",
"workflows.workflowNameHint": "Optional name for the workflow.",
"workflows.workflowNamePlaceholder": "Enter workflow name"
}

848
backend/i18n/source/frontend_nl.json

@ -0,0 +1,848 @@
{
"api.contentApi": "Content API",
"api.generalApi": "Algemene API",
"api.graphql": "GraphQL",
"api.graphqlPageTitle": "GraphQL",
"api.pageTitle": "API",
"api.title": "API",
"apps.allApps": "Alle apps",
"apps.appLoadFailed": "Kan app niet laden. Laad opnieuw.",
"apps.appNameHint": "Je kunt alleen letters, cijfers en streepjes gebruiken en niet meer dan 40 tekens.",
"apps.appNameValidationMessage": "Naam mag kleine letters (a-z), cijfers en streepjes tussen bevatten.",
"apps.appNameWarning": "De app-naam kan later niet worden gewijzigd.",
"apps.appsButtonCreate": "Apps-overzicht",
"apps.appsButtonFallbackTitle": "Apps-overzicht",
"apps.archieve": "App archiveren",
"apps.archieveConfirmText": "Patroon verwijderen",
"apps.archieveConfirmTitle": "Wil je deze app echt archiveren?",
"apps.archieveWarning": "Zodra je een app archiveert, is er geen weg meer terug. Wees alsjeblieft zeker.",
"apps.archiveFailed": "Kan app niet archiveren. Laad opnieuw.",
"apps.create": "App maken",
"apps.createBlankApp": "Nieuwe app.",
"apps.createBlankAppDescription": "Maak een nieuwe lege app zonder inhoud en schema's.",
"apps.createBlogApp": "Nieuw blogvoorbeeld",
"apps.createBlogAppDescription": "Begin met onze gebruiksklare blog.",
"apps.createFailed": "Maken van app is mislukt. Laad opnieuw.",
"apps.createIdentityApp": "Nieuwe identiteits-app",
"apps.createIdentityAppDescription": "Maak een app voor Squidex Identity.",
"apps.createIdentityAppV2": "Nieuwe identiteits-app V2",
"apps.createIdentityAppV2Description": "Maak een app voor Squidex Identity V2.",
"apps.createProfileApp": "Nieuw profielvoorbeeld",
"apps.createProfileAppDescription": "Maak uw profielpagina.",
"apps.createWithTemplate": "Maak {sjabloon} voorbeeld",
"apps.empty": "Je werkt nog niet samen aan een app",
"apps.generalSettings": "Algemeen",
"apps.generalSettingsDangerZone": "Algemeen",
"apps.image": "Afbeelding",
"apps.imageDrop": "Zet neer om te uploaden",
"apps.listPageTitle": "Apps",
"apps.loadFailed": "Laden van apps is mislukt. Laad opnieuw.",
"apps.removeImage": "Afbeelding verwijderen",
"apps.removeImageFailed": "Verwijderen van app-afbeelding is mislukt. Laad opnieuw.",
"apps.updateFailed": "Update app mislukt. Laad opnieuw.",
"apps.upgradeHintCurrent": "Je zit in het plan {plan}.",
"apps.upgradeHintUpgrade": "Upgrade!",
"apps.uploadImage": "Zet een bestand neer om de app-afbeelding te vervangen. Gebruik een vierkant formaat.",
"apps.uploadImageButton": "Upload bestand",
"apps.uploadImageFailed": "Uploaden van afbeelding is mislukt. Laad opnieuw.",
"apps.uploadImageTooBig": "App-afbeelding is te groot.",
"apps.welcomeSubtitle": "Welkom bij Squidex.",
"apps.welcomeTitle": "Hallo {user}",
"assets.createFolder": "Map maken",
"assets.createFolderFailed": "Maken van een map is mislukt. Laad opnieuw.",
"assets.createFolderTooltip": "Nieuwe map maken (CTRL + SHIFT + G)",
"assets.deleteConfirmText": "Weet je zeker dat je het item wilt verwijderen?",
"assets.deleteConfirmTitle": "Item verwijderen",
"assets.deleteFailed": "Verwijderen van item is mislukt. Laad opnieuw.",
"assets.deleteFolderConfirmText": "Weet je zeker dat je de map en alle bestanden wilt verwijderen?",
"assets.deleteFolderConfirmTitle": "Map verwijderen",
"assets.deleteMetadataConfirmText": "Wil je deze metadata echt verwijderen?",
"assets.deleteMetadataConfirmTitle": "Metadata verwijderen",
"assets.downloadVersion": "Download deze versie",
"assets.dropToUpdate": "Zet neer om te updaten",
"assets.duplicateFile": "Asset is al geüpload.",
"assets.editor.flipHorizontally": "Horizontaal spiegelen",
"assets.editor.flipVertically": "Verticaal spiegelen",
"assets.editor.focusPointLabel": "Selecteer positie van focuspunt",
"assets.editor.focusPointPreview": "Voorbeeld voor verschillende formaten",
"assets.editor.rotateLeft": "Links draaien",
"assets.editor.rotateRight": "Rechts draaien",
"assets.fileTooBig": "Asset is te groot.",
"assets.folderName": "Mapnaam",
"assets.folderNameHint": "De mapnaam wordt gebruikt als weergavenaam en mag niet uniek zijn.",
"assets.insertAssets": "Assets invoegen",
"assets.linkSelected": "Link geselecteerde items ({count})",
"assets.listPageTitle": "Assets",
"assets.loadFailed": "Laden van bestanden is mislukt. Laad opnieuw.",
"assets.loadFoldersFailed": "Laden van mappen is mislukt. Laad opnieuw.",
"assets.metadata": "Metadata",
"assets.metadataAdd": "Metadata toevoegen",
"assets.moveFailed": "Verplaatsen van item is mislukt. Laad opnieuw.",
"assets.protected": "Beschermd",
"assets.refreshTooltip": "Assets vernieuwen (CTRL + SHIFT + R)",
"assets.reloaded": "Bestanden herladen.",
"assets.renameFolder": "Naam map wijzigen",
"assets.replaceConfirmText": "Wilt je de asset echt vervangen door een nieuwere versie",
"assets.replaceConfirmTitle": "Asset vervangen?",
"assets.replaceFailed": "Kan item niet vervangen. Laad opnieuw.",
"assets.searchByName": "Zoeken op naam",
"assets.searchByTags": "Zoeken op tags",
"assets.selectMany": "Selecteer middelen",
"assets.tabFocusPoint": "Focuspunt",
"assets.tabHistory": "Geschiedenis",
"assets.tabImage": "Afbeelding",
"assets.tabMetadata": "Metadata",
"assets.updated": "Asset is bijgewerkt.",
"assets.updateFailed": "Bijwerken van item is mislukt. Laad opnieuw.",
"assets.updateFolderFailed": "Bijwerken van de map is mislukt. Laad opnieuw.",
"assets.uploadByDialog": "Selecteer bestand (en",
"assets.uploadByDrop": "Zet bestanden hier neer om te uploaden",
"assets.uploaderUploadHere": "Geen upload bezig, zet bestanden hier neer.",
"assets.uploadFailed": "Uploaden van item is mislukt. Laad opnieuw.",
"assets.uploadHint": "Zet het bestand neer op bestaand item om het bestand te vervangen door een nieuwere versie.",
"backups.backupCountAssetsLabel": "Bestanden",
"backups.backupCountAssetsTooltip": "Gearchiveerde middelen",
"backups.backupCountEventsLabel": "Evenementen",
"backups.backupCountEventsTooltip": "Gearchiveerde gebeurtenissen",
"backups.backupDownload": "Downloaden",
"backups.backupDownloadLink": "Klaar",
"backups.backupDuration": "Duur",
"backups.deleteConfirmText": "Wilt je de back-up echt verwijderen?",
"backups.deleteConfirmTitle": "Back-up verwijderen",
"backups.deleted": "Back-up wordt binnenkort verwijderd.",
"backups.deleteFailed": "Verwijderen van back-up is mislukt.",
"backups.empty": "Nog geen back-ups gemaakt.",
"backups.loadFailed": "Laden van back-ups is mislukt.",
"backups.maximumReached": "Je hebt het maximale aantal back-ups bereikt: 10",
"backups.refreshTooltip": "Vernieuw back-ups (CTRL + SHIFT + R)",
"backups.reloaded": "Back-ups herladen.",
"backups.restore": "Back-up herstellen",
"backups.restoreFailed": "Starten van herstel is mislukt.",
"backups.restoreLastStatus": "Laatste herstelbewerking",
"backups.restoreLastUrl": "URL voor back-up",
"backups.restoreNewAppName": "Optionele app-naam",
"backups.restorePageTitle": "Back-up herstellen",
"backups.restoreStarted": "Herstel gestart, het kan enkele minuten duren.",
"backups.restoreStartedLabel": "Gestart",
"backups.restoreStoppedLabel": "Gestopt",
"backups.restoreTitle": "Back-up herstellen",
"backups.start": "Start back-up",
"backups.started": "Back-up gestart, het kan enkele minuten duren om te voltooien.",
"backups.startedLabel": "Gestart",
"backups.startFailed": "Starten van back-up is mislukt.",
"clients.add": "Client toevoegen",
"clients.addFailed": "Toevoegen van client is mislukt. Laad opnieuw.",
"clients.allowAnonymous": "Sta anonieme toegang toe.",
"clients.allowAnonymousHint": "Sta toegang tot de API toe zonder toegangstoken voor alle bronnen die zijn geconfigureerd via de rol van deze client. Geef niet meer dan één client anonieme toegang.",
"clients.clientIdValidationMessage": "Naam mag alleen letters, cijfers, streepjes en spaties bevatten.",
"clients.clientNamePlaceholder": "Voer de naam van de klant in",
"clients.connect": "Verbinden",
"clients.connectWizard.cli": "Maak verbinding met Squidex CLI",
"clients.connectWizard.cliHint": "Download de CLI en maak verbinding met deze app om back-ups te starten, schema's te synchroniseren of inhoud te exporteren.",
"clients.connectWizard.cliStep1": "Download de nieuwste Squidex CLI",
"clients.connectWizard.cliStep1Download": "[Download de CLI van Github] (https://github.com/Squidex/squidex-samples/releases)",
"clients.connectWizard.cliStep1Hint": "De releases bevatten binaire bestanden voor alle belangrijke besturingssystemen en een kleine download als .NET Core is geïnstalleerd.",
"clients.connectWizard.cliStep2": "Voeg` <uw Squidex CLI download directory> `toe aan uw` $ PATH` variabele ",
"clients.connectWizard.cliStep3": "Voeg uw app-naam toe aan de CLI-configuratie",
"clients.connectWizard.cliStep3Hint": "Je kunt de configuratie voor meerdere apps in de CLI beheren en overschakelen naar een app.",
"clients.connectWizard.cliStep4": "Schakel over naar uw app in de CLI",
"clients.connectWizard.manually": "Handmatig verbinden",
"clients.connectWizard.manuallyHint": "Krijg instructies om een ​​verbinding tot stand te brengen met Postman of curl.",
"clients.connectWizard.manuallyStep1": "Verkrijg een token met curl",
"clients.connectWizard.manuallyStep2": "Gebruik gewoon het volgende token",
"clients.connectWizard.manuallyStep3": "Voeg het token toe als HTTP-header aan alle verzoeken",
"clients.connectWizard.manuallyTokenHint": "Tokens vervallen gewoonlijk na 30 dagen, maar je kunt meerdere tokens aanvragen.",
"clients.connectWizard.postManDocs": "Begin met de Postman-tutorial in de [Documentatie] (https://docs.squidex.io/02-documentation/developer-guides/api-overview/postman).",
"clients.connectWizard.sdk": "Maak verbinding met uw app met SDK",
"clients.connectWizard.sdkHelp": "Heb je een andere SDK nodig?",
"clients.connectWizard.sdkHelpLink": "Neem contact met ons op in het ondersteuningsforum",
"clients.connectWizard.sdkHint": "Download een SDK en maak verbinding met deze app.",
"clients.connectWizard.sdkStep1": "Installeer de .NET SDK",
"clients.connectWizard.sdkStep1Download": "De SDK is beschikbaar op [nuget] (https://www.nuget.org/packages/Squidex.ClientLibrary/)",
"clients.connectWizard.sdkStep2": "Maak een klantenbeheerder",
"clients.connectWizard.step0Title": "Client instellen",
"clients.connectWizard.step1Title": "Kies verbindingsmethode",
"clients.connectWizard.step2Title": "Verbinden",
"clients.deleteConfirmText": "Wil je de client echt intrekken?",
"clients.deleteConfirmTitle": "Client intrekken",
"clients.empty": "Nog geen client aangemaakt.",
"clients.loadFailed": "Kan clients niet laden. Laad opnieuw.",
"clients.refreshTooltip": "Ververs clients (CTRL + SHIFT + R)",
"clients.reloaded": "Clients herladen.",
"clients.revokeFailed": "Kan client niet intrekken. Laad opnieuw.",
"clients.tokenFailed": "Maken van token is mislukt. Probeer het opnieuw.",
"comments.create": "Maak een opmerking",
"comments.createFailed": "Aanmaken van commentaar mislukt.",
"comments.deleteConfirmText": "Wil je de opmerking echt verwijderen?",
"comments.deleteConfirmTitle": "Verwijder opmerking",
"comments.deleteFailed": "Verwijderen van opmerking is mislukt.",
"comments.follow": "Volgen",
"comments.loadFailed": "Kan commentaar niet laden.",
"comments.title": "Reacties",
"comments.updateFailed": "Update reactie mislukt.",
"common.actions": "Acties",
"common.administration": "Administratie",
"common.administrationPageTitle": "Administratie",
"common.api": "API",
"common.apps": "Apps",
"common.aspectRatio": "AspectRatio",
"common.assets": "Bestanden",
"common.back": "Terug",
"common.backups": "Back-ups",
"common.bytes": "bytes",
"common.cancel": "Annuleren",
"common.clear": "Wissen",
"common.clientId": "Client-ID",
"common.clients": "Clients",
"common.clientSecret": "Clientgeheim",
"common.clipboardAdded": "Waarde is toegevoegd aan uw klembord.",
"common.clone": "Kloon",
"common.cluster": "Cluster",
"common.clusterPageTitle": "Cluster",
"common.comments": "Reacties",
"common.confirm": "Bevestigen",
"common.consumers": "Consumenten",
"common.content": "Inhoud",
"common.contents": "Inhoud",
"common.continue": "Doorgaan",
"common.contributors": "Bijdragers",
"common.create": "Maken",
"common.created": "Gemaakt",
"common.date": "Datum",
"common.dateTimeEditor.now": "Nu",
"common.dateTimeEditor.nowTooltip": "Nu gebruiken (UTC)",
"common.dateTimeEditor.today": "Vandaag",
"common.dateTimeEditor.todayTooltip": "Gebruik vandaag (UTC)",
"common.delete": "Verwijderen",
"common.description": "Beschrijving",
"common.displayName": "Weergavenaam",
"common.edit": "Bewerken",
"common.email": "E-mail",
"common.error": "Fout",
"common.errorBack": "Terug naar de vorige pagina.",
"common.errorNoPermission": "Je hebt niet de permissies om dit te doen.",
"common.errorNotFound": "Niet gevonden",
"common.event": "Evenement",
"common.events": "Evenementen",
"common.executed": "Uitgevoerd",
"common.expertMode": "Expert-modus",
"common.failed": "Mislukt",
"common.fallback": "Fallback",
"common.field": "Veld",
"common.files": "Bestanden",
"common.filters": "Filters",
"common.folders": "Mappen",
"common.generalSettings": "Algemeen",
"common.generate": "Genereren",
"common.github": "Github",
"common.height": "Hoogte",
"common.help": "Help",
"common.helpTour": "Klik op het helppictogram om een ​​contextspecifieke helppagina weer te geven. Ga naar",
"common.hide": "Verbergen",
"common.hints": "Hints",
"common.history": "Geschiedenis",
"common.httpConflict": "De update is mislukt. Een andere gebruiker heeft een wijziging aangebracht. Laad opnieuw.",
"common.httpLimit": "Je hebt de maximale limiet van API-aanroepen overschreden.",
"common.label": "Label",
"common.languages": "Talen",
"common.latitudeShort": "Lat",
"common.loading": "Laden",
"common.logout": "Uitloggen",
"common.logs": "Logboeken",
"common.longitudeShort": "Lon",
"common.mapHide": "Verberg kaart",
"common.mapShow": "Toon kaart",
"common.message": "Bericht",
"common.name": "Naam",
"common.no": "Nee",
"common.nothingChanged": "Er is niets veranderd.",
"common.noValue": "- Geen waarde -",
"common.or": "of",
"common.pagerInfo": "{itemFirst} - {itemLast} van {numberOfItems}",
"common.password": "Wachtwoord",
"common.passwordConfirm": "Bevestig wachtwoord",
"common.pattern": "Patroon",
"common.patterns": "Patronen",
"common.permissions": "Rechten",
"common.preview": "Preview",
"common.product": "Squidex Headless CMS",
"common.project": "Project",
"common.refresh": "Vernieuwen",
"common.rename": "Hernoemen",
"common.requiredHint": "verplicht",
"common.reset": "Reset",
"common.restore": "Herstellen",
"common.role": "Rol",
"common.roles": "Rollen",
"common.rules": "Regels",
"common.sampleCodeLabel": "Voorbeeldcode bij",
"common.save": "Opslaan",
"common.saveShortcut": "CTRL + S",
"common.schemas": "Schema's",
"common.searchGoogleMaps": "Zoeken in Google Maps",
"common.searchResults": "Zoekresultaten",
"common.separateByLine": "Scheiden op regel",
"common.settings": "Instellingen",
"common.sidebarTour": "De zijbalknavigatie bevat nuttige contextspecifieke links. Hier kun je de geschiedenis bekijken hoe dit schema in de loop van de tijd is veranderd.",
"common.slug": "Slug",
"common.stars.max": "Mag niet meer dan 15 sterren hebben",
"common.status": "Status",
"common.statusChangeTo": "Wijzigen in",
"common.submit": "Verzenden",
"common.subscription": "Abonnement",
"common.succeeded": "Geslaagd",
"common.tagAdd": ", om tag toe te voegen",
"common.tagAddReference": ", om referentie toe te voegen",
"common.tagAddSchema": ", om schema toe te voegen",
"common.tags": "Tags",
"common.tagsAll": "Alle tags",
"common.time": "Tijd",
"common.update": "Update",
"common.url": "URL",
"common.users": "Gebruikers",
"common.value": "Waarde",
"common.width": "Breedte",
"common.workflow": "Workflow",
"common.workflows": "Workflows",
"common.yes": "Ja",
"contents.arrayAddItem": "Item toevoegen",
"contents.arrayCloneItem": "Kloon dit item",
"contents.arrayCollapseAll": "Collapse all items",
"contents.arrayCollapseItem": "Collapse this item",
"contents.arrayExpandAll": "Alle items uitvouwen",
"contents.arrayExpandItem": "Vouw dit item uit",
"contents.arrayMoveBottom": "Verplaats dit item naar beneden",
"contents.arrayMoveDown": "Verplaats dit item naar beneden",
"contents.arrayMoveTop": "Verplaats dit item naar boven",
"contents.arrayMoveUp": "Verplaats dit item omhoog",
"contents.arrayNoFields": "Voeg eerst een genest veld toe om items toe te voegen.",
"contents.assetsUpload": "Zet bestanden neer of klik",
"contents.autotranslate": "Automatisch vertalen vanuit de hoofdtaal",
"contents.changeStatusTo": "Verander inhoud item(s) in {action}",
"contents.changeStatusToImmediately": "Zet onmiddellijk op {action}.",
"contents.changeStatusToLater": "Zet op {action} op een latere datum en tijd.",
"contents.contentNotValid": "Inhoudselement niet geldig, controleer het veld met de rode balk aan de linkerkant in alle talen (indien lokaliseerbaar).",
"contents.create": "Nieuw",
"contents.createContentTooltip": "Nieuwe inhoud (CTRL + SHIFT + G)",
"contents.created": "Inhoud succesvol aangemaakt.",
"contents.createdByFieldDescription": "De gebruiker die het inhoudsitem heeft gemaakt.",
"contents.createFailed": "Maken van inhoud is mislukt. Laad opnieuw.",
"contents.createFieldDescription": "De datum en tijd waarop het inhoudsitem is gemaakt.",
"contents.createPageTitle": "Inhoud maken",
"contents.createTitle": "Nieuwe inhoud",
"contents.currentStatusLabel": "Huidige versie",
"contents.deleteConfirmText": "Wilt je de inhoud echt verwijderen?",
"contents.deleteConfirmTitle": "Inhoud verwijderen",
"contents.deleteFailed": "Verwijderen van inhoud is mislukt. Laad opnieuw.",
"contents.deleteManyConfirmText": "Weet je zeker dat je de geselecteerde inhoudsitems wilt verwijderen?",
"contents.deleteVersionConfirmText": "Wil je deze versie echt verwijderen?",
"contents.deleteVersionFailed": "Verwijderen van versie is mislukt. Laad opnieuw.",
"contents.draftNew": "Nieuw concept",
"contents.draftStatus": "Nieuwe versie",
"contents.editPageTitle": "Inhoud bewerken",
"contents.editTitle": "Inhoud bewerken",
"contents.languageModeAll": "Alle talen",
"contents.languageModeSingle": "Enkele taal",
"contents.lastModifiedByFieldDescription": "De gebruiker die het inhoudsitem de laatste keer heeft gewijzigd.",
"contents.lastModifiedFieldDescription": "De datum en tijd waarop het inhoudsitem de laatste keer is gewijzigd.",
"contents.lastUpdatedLabel": "Laatst bijgewerkt",
"contents.loadContent": "Laden",
"contents.loadContentFailed": "Kan inhoud niet laden. Laad opnieuw.",
"contents.loadDataFailed": "Laden van gegevens is mislukt. Laad opnieuw.",
"contents.loadFailed": "Laden van inhoud is mislukt. Laad opnieuw.",
"contents.loadVersionFailed": "Versie van een nieuwe versie is mislukt. Laad opnieuw.",
"contents.noReference": "- Geen referentie -",
"contents.pendingChangesTextToChange": "Je hebt niet-opgeslagen wijzigingen. \n \n Wanneer je de status wijzigt, raak je ze kwijt. \n \n **Wil je toch doorgaan?**",
"contents.pendingChangesTextToClose": "Je hebt niet-opgeslagen wijzigingen. \n \n Wanneer je de huidige inhoudsweergave sluit, raak je ze kwijt. \n n **Wil je toch doorgaan?**",
"contents.pendingChangesTitle": "Niet-opgeslagen wijzigingen",
"contents.referencesCreateNew": "Nieuwe toevoegen",
"contents.referencesCreatePublish": "Maken en publiceren",
"contents.referencesLink": "Link geselecteerde inhoud ({count})",
"contents.referencesSelectExisting": "Selecteer bestaande",
"contents.referencesSelectSchema": "Selecteer {scheme}",
"contents.refreshTooltip": "Ververs inhoud (CTRL + SHIFT + R)",
"contents.reloaded": "Inhoud opnieuw geladen.",
"contents.saveAndPublish": "Opslaan en publiceren",
"contents.scheduledAt": "bij",
"contents.scheduledAtLabel": "bij",
"contents.scheduledTo": "naar",
"contents.schemasPageTitle": "Inhoud",
"contents.searchPlaceholder": "Zoeken in volledige tekst",
"contents.searchSchemasPlaceholder": "Zoek schema's ...",
"contents.selectionCount": "{count} items geselecteerd",
"contents.statusFieldDescription": "De status van het inhoudsitem.",
"contents.statusQueries": "Statusquery's",
"contents.stockPhotoEmpty": "Niets geselecteerd",
"contents.stockPhotoSearch": "Zoeken naar foto's op Unsplash",
"contents.unsavedChangesText": "Je hebt niet-opgeslagen wijzigingen. Wil je ze nu laden?",
"contents.unsavedChangesTitle": "Niet-opgeslagen wijzigingen",
"contents.updated": "Inhoud succesvol bijgewerkt.",
"contents.updateFailed": "Bijwerken van inhoud is mislukt. Laad opnieuw.",
"contents.validationHint": "Denk eraan om alle talen te controleren wanneer je validatiefouten ziet.",
"contents.versionCompare": "Vergelijk",
"contents.versionDelete": "Verwijder deze versie",
"contents.versionFieldDescription": "De versie van het inhoudsitem",
"contents.versionViewing": "Bekijk versie **{version}**.",
"contents.viewLatest": "Bekijk laatste",
"contents.viewReset": "Standaardweergave herstellen",
"contributors.add": "Bijdrager toevoegen",
"contributors.addFailed": "Toevoegen van bijdragers is mislukt. Laad opnieuw.",
"contributors.contributorAssigned": "Een nieuwe gebruiker met het ingevoerde e-mailadres is aangemaakt en toegewezen als bijdrager.",
"contributors.contributorAssignedExisting": "Gebruiker is toegewezen",
"contributors.contributorAssignedInvited": "Gebruiker is uitgenodigd en toegewezen.",
"contributors.contributorAssignedOld": "Gebruiker is toegevoegd als bijdrager.",
"contributors.deleteConfirmText": "Wil je de bijdrager echt verwijderen?",
"contributors.deleteConfirmTitle": "Verwijder bijdrager",
"contributors.deleteFailed": "Verwijderen van bijdragers is mislukt. Laad opnieuw.",
"contributors.emailPlaceholder": "Vind gebruiker of nodig uit via e-mail",
"contributors.empty": "Geen bijdragers gevonden.",
"contributors.import.emailsDetected": "E-mails gedetecteerd: {count}",
"contributors.import.run": "Bijdrager toevoegen",
"contributors.import.run2": "Importeren",
"contributors.importButton": "Voeg veel bijdragers tegelijk toe",
"contributors.importHintg": "Groot team?",
"contributors.importTitle": "Bijdragers importeren",
"contributors.loadFailed": "Laden van bijdragers is mislukt. Laad opnieuw.",
"contributors.planHint": "Uw plan staat maximaal {maxContributors} bijdragers toe.",
"contributors.refreshTooltip": "Bijdragers vernieuwen (CTRL + SHIFT + R)",
"contributors.reloaded": "Contributors reloaded.",
"contributors.search": "Zoeken",
"contributors.userNotFound": "De gebruiker bestaat niet.",
"dashboard.apiCallsCard": "API-oproepen",
"dashboard.apiCallsChart": "Grafiek API-oproepen",
"dashboard.apiCallsLimitLabel": "Maandelijkse limiet",
"dashboard.apiCallsSummaryCard": "Samenvatting API-oproepen",
"dashboard.apiDocumentationCard": "API-documentatie",
"dashboard.apiPerformanceCard": "API-prestaties (ms): {summary} ms gem.",
"dashboard.apiPerformanceChart": "API-prestatiegrafiek",
"dashboard.assetSizeCard": "Grootte van bestand (MB",
"dashboard.assetSizeLabel": "Totale grootte",
"dashboard.assetSizeLimitLabel": "Totale limiet",
"dashboard.assetTotalSize": "Totale opslagruimte",
"dashboard.assetUpdloadsCountChart": "Grafiek aantal itemsuploads",
"dashboard.assetUploadsCard": "Uploads van items",
"dashboard.assetUploadsSizeChart": "Maattabel voor uploads van items",
"dashboard.configSaved": "Configuratie opgeslagen.",
"dashboard.contentApi": "Content API",
"dashboard.contentApiDescription": "OpenAPI 3.0-compatibele documentatie voor uw app-inhoud.",
"dashboard.contentsSummaryCard": "Aantal items",
"dashboard.currentMonthLabel": "Deze maand",
"dashboard.downloadLog": "Downloadlogboek",
"dashboard.editConfig": "Configuratie bewerken",
"dashboard.githubCard": "Github",
"dashboard.githubCardDescription": "Haal de broncode op van Github en meld bugs of vraag om ondersteuning.",
"dashboard.historyCard": "Geschiedenis",
"dashboard.pageTitle": "Dashboard",
"dashboard.resetConfigConfirmText": "Wil je echt het dashboard terugzetten naar de standaardinstellingen?",
"dashboard.resetConfigConfirmTitle": "Reset configuratie",
"dashboard.schemaNewCard": "Nieuw schema",
"dashboard.schemaNewCardDescription": "Een schema definieert de structuur van uw inhoudselement.",
"dashboard.schemasCard": "Schema's",
"dashboard.schemasCardDescription": "Krijg inzicht in het datamodel van deze app.",
"dashboard.stackedChart": "Gestapeld",
"dashboard.supportCard": "Feedback en ondersteuning",
"dashboard.supportCardDescription": "Geef feedback en vraag om functies om ons te helpen Squidex te verbeteren.",
"dashboard.trafficChart": "API-verkeersdiagram",
"dashboard.trafficHeader": "Verkeer (MB)",
"dashboard.trafficLimitLabel": "Maandelijks limiet",
"dashboard.trafficSummaryCard": "API Verkeer Samenvatting",
"dashboard.welcomeText": "Welkom bij **{app}** dashboard.",
"dashboard.welcomeTitle": "Hallo {user}",
"eventConsumers.loadFailed": "Kan gebeurtenisgebruikers niet laden. Laad opnieuw.",
"eventConsumers.pageTitle": "Evenementconsumenten",
"eventConsumers.position": "Positie",
"eventConsumers.refreshTooltip": "Ververs evenementgebruikers (CTRL + SHIFT + R)",
"eventConsumers.reloaded": "Evenementconsumenten herladen.",
"eventConsumers.resetFailed": "Kan gebeurtenisgebruiker niet resetten. Laad opnieuw.",
"eventConsumers.resetTooltip": "Reset Event Consumer",
"eventConsumers.startFailed": "Het starten van een evenementconsument is mislukt. Laad opnieuw.",
"eventConsumers.startTooltip": "Start Event Consumer",
"eventConsumers.stopFailed": "Kan de gebruiker van het evenement niet stoppen. Laad opnieuw.",
"eventConsumers.stopTooltip": "Stop Event Consumer",
"features.loadFailed": "Laden van functies is mislukt. Laad opnieuw.",
"history.loadFailed": "Kan geschiedenis niet laden. Laad opnieuw.",
"history.title": "Activiteit",
"languages.add": "Taal toevoegen",
"languages.addFailed": "Toevoegen van taal is mislukt. Laad opnieuw.",
"languages.deleteConfirmText": "Wil je de taal echt verwijderen?",
"languages.deleteConfirmTitle": "Verwijder taal",
"languages.deleteFailed": "Verwijderen van taal is mislukt. Laad opnieuw.",
"languages.loadFailed": "Laden van talen is mislukt. Laad opnieuw.",
"languages.master": "Is Master",
"languages.masterHint": "Andere talen vallen terug op de master als er geen fallback is gedefinieerd.",
"languages.optional": "Is optioneel",
"languages.optionalHint": "Waarden voor optionele talen mogen niet worden ingevoerd, zelfs niet als dit veld vereist is.",
"languages.refreshTooltip": "Ververs talen (CTRL + SHIFT + R)",
"languages.reloaded": "Talen herladen.",
"languages.updateFailed": "Het wijzigen van de taal is mislukt. Laad opnieuw.",
"news.headline": "Wat is er nieuw?",
"news.title": "Nieuwe functies",
"notifo.subscripeTooltip": "Klik op deze knop om je te abonneren op alle wijzigingen en om pushmeldingen te ontvangen.",
"patterns.deleteConfirmText": "Wil je dit patroon echt verwijderen?",
"patterns.deleteConfirmTitle": "Verwijder patroon",
"patterns.deleteFailed": "Verwijderen van patroon is mislukt. Laad opnieuw.",
"patterns.empty": "Nog geen patroon gemaakt.",
"patterns.loadFailed": "Toevoegen van patroon is mislukt. Laad opnieuw.",
"patterns.nameValidationMessage": "Naam mag alleen letters, cijfers, streepjes en spaties bevatten.",
"patterns.refreshTooltip": "Ververs patronen (CTRL + SHIFT + R)",
"patterns.reloaded": "Patronen herladen.",
"patterns.updateFailed": "Bijwerken van patroon is mislukt. Laad opnieuw.",
"plans.billingPortal": "Factureringsportal",
"plans.billingPortalHint": "Ga naar het factureringsportaal voor betalingsgeschiedenis en abonnementsoverzicht.",
"plans.change": "Wijzigen",
"plans.changeConfirmTitle": "Abonnement wijzigen",
"plans.changeFailed": "Kan plan niet wijzigen. Laad opnieuw.",
"plans.includedCalls": "API-oproepen",
"plans.includedContributors": "Contributors",
"plans.includedStorage": "Opslag",
"plans.includedTraffic": "Verkeer",
"plans.loadFailed": "Laden van plannen is mislukt. Laad opnieuw.",
"plans.noPlanConfigured": "Geen plan geconfigureerd, deze app heeft onbeperkt gebruik.",
"plans.notPlanOwner": "Je hebt geen abonnement aangemaakt. Daarom kun je het plan niet wijzigen.",
"plans.perMonth": "Per maand",
"plans.perYear": "Per jaar",
"plans.refreshTooltip": "Plannen vernieuwen (CTRL + SHIFT + R)",
"plans.reloaded": "Plans reloaded.",
"plans.selected": "Geselecteerd",
"profile.title": "Profiel",
"profile.userEmail": "Aangemeld met",
"roles.add": "Rol toevoegen",
"roles.addFailed": "Toevoegen van rol is mislukt. Laad opnieuw.",
"roles.default.owner": "Kan alles doen, inclusief het verwijderen van de app.",
"roles.default.reader": "Kan alleen items en inhoud lezen.",
"roles.defaults.developer": "Kan de API-weergave gebruiken, middelen, inhoud, schema's, regels, workflows en patronen bewerken.",
"roles.defaults.editor": "Kan middelen en inhoud bewerken en workflows bekijken.",
"roles.deleteConfirmText": "Rol verwijderen",
"roles.deleteConfirmTitle": "Wil je de rol echt verwijderen?",
"roles.loadFailed": "Laden van rollen is mislukt. Laad opnieuw.",
"roles.loadPermissionsFailed": "Kan machtigingen niet laden. Laad opnieuw.",
"roles.refreshTooltip": "Ververs rollen (CTRL + SHIFT + R)",
"roles.reloaded": "Rollen opnieuw geladen.",
"roles.revokeFailed": "Kan rol niet intrekken. Laad opnieuw.",
"roles.roleNamePlaceholder": "Voer de rolnaam in",
"roles.updateFailed": "Update rol mislukt. Laad opnieuw.",
"rules.actionEdit": "Bewerk actie",
"rules.cancelFailed": "Annuleren van regel is mislukt. Laad opnieuw.",
"rules.create": "Maak een nieuwe regel",
"rules.createFailed": "Maken van regel is mislukt. Laad opnieuw.",
"rules.createTooltip": "Nieuwe regel (CTRL + SHIFT + G)",
"rules.deleteConfirmText": "Wil je de regel echt verwijderen?",
"rules.deleteConfirmTitle": "Regel verwijderen",
"rules.deleteFailed": "Verwijderen van regel is mislukt. Laad opnieuw.",
"rules.disableFailed": "Kan regel niet uitschakelen. Laad opnieuw.",
"rules.empty": "Nog geen regel aangemaakt.",
"rules.emptyAddRule": "Regel toevoegen",
"rules.enableFailed": "Kan regel niet inschakelen. Laad opnieuw.",
"rules.enqueued": "Regel is toegevoegd aan de wachtrij.",
"rules.listPageTitle": "Regels",
"rules.loadFailed": "Laden van regels is mislukt. Laad opnieuw.",
"rules.readMore": "Lees meer",
"rules.refreshEventsTooltip": "Ververs evenementen (CTRL + SHIFT + R)",
"rules.refreshTooltip": "Vernieuwingsregels (CTRL + SHIFT + R)",
"rules.reloaded": "Regels herladen.",
"rules.restarted": "Regel begint over een paar seconden te lopen.",
"rules.ruleEvents.cancelFailed": "Annuleren van regelgebeurtenis is mislukt. Laad opnieuw.",
"rules.ruleEvents.enqueue": "Enqueue",
"rules.ruleEvents.enqueued": "Evenementen in de wachtrij geplaatst. Worden over enkele seconden opnieuw verzonden.",
"rules.ruleEvents.enqueueFailed": "Kan regelgebeurtenis niet in wachtrij plaatsen. Laad opnieuw.",
"rules.ruleEvents.lastInvokedLabel": "Laatste aanroep",
"rules.ruleEvents.listPageTitle": "Regelgebeurtenissen",
"rules.ruleEvents.loadFailed": "Kan evenementen niet laden. Laad opnieuw.",
"rules.ruleEvents.nextAttemptLabel": "Volgende",
"rules.ruleEvents.numAttemptsLabel": "Pogingen",
"rules.ruleEvents.reloaded": "RuleEvents herladen.",
"rules.ruleSyntax.if": "If",
"rules.ruleSyntax.then": "then",
"rules.run": "Uitvoeren",
"rules.runFailed": "Uitvoeren van regel mislukt. Laad opnieuw.",
"rules.runningRule": "Regel '{name}' is momenteel actief.",
"rules.runRuleConfirmText": "Wil je de regel echt voor alle evenementen uitvoeren?",
"rules.runRuleConfirmTitle": "Regel uitvoeren",
"rules.stop": "Regel stopt binnenkort.",
"rules.triggerConfirmText": "Wil je echt de regel activeren?",
"rules.triggerConfirmTitle": "Trigger regel",
"rules.triggerEdit": "Trigger bewerken",
"rules.triggerFailed": "Kan regel niet activeren. Laad opnieuw.",
"rules.unnamed": "Naamloos regel",
"rules.updateFailed": "Update regel mislukt. Laad opnieuw.",
"rules.wizard.actionHint": "De selectie van het actietype kan later niet worden gewijzigd.",
"rules.wizard.selectAction": "Selecteer actie",
"rules.wizard.selectTrigger": "Selecteer Trigger",
"rules.wizard.triggerHint": "De selectie van het triggertype kan later niet worden gewijzigd.",
"schemas.addField": "Veld toevoegen",
"schemas.addFieldAndClose": "Maken en sluiten",
"schemas.addFieldAndCreate": "Maak en voeg veld toe",
"schemas.addFieldAndEdit": "Maak en bewerk veld",
"schemas.addFieldButton": "Veld",
"schemas.addFieldFailed": "Toevoegen van veld is mislukt. Laad opnieuw.",
"schemas.addNestedField": "Voeg genest veld toe",
"schemas.changeCategoryFailed": "Kan categorie niet wijzigen. Laad opnieuw.",
"schemas.clone": "Clone Schema",
"schemas.contextMenuTour": "Open het contextmenu om het schema te verwijderen of om scripts te maken voor wijzigingen in de inhoud.",
"schemas.create": "Schema maken",
"schemas.createCategory": "Nieuwe categorie maken ...",
"schemas.createFailed": "Kan schema niet maken. Laad opnieuw.",
"schemas.createSchemaTooltip": "Nieuw schema (CTRL + SHIFT + G)",
"schemas.deleteConfirmText": "Weet je zeker dat je het schema wilt verwijderen?",
"schemas.deleteConfirmTitle": "Schema verwijderen",
"schemas.deleteFailed": "Kan schema niet verwijderen. Laad opnieuw.",
"schemas.deleteFieldFailed": "Verwijderen van veld is mislukt. Laad opnieuw.",
"schemas.deleteRuleConfirmText": "Wil je deze veldregel echt verwijderen?",
"schemas.deleteRuleConfirmTitle": "Veldregel verwijderen",
"schemas.deleteUrlConfirmText": "Wil je deze URL echt verwijderen?",
"schemas.deleteUrlConfirmTitle": "URL verwijderen",
"schemas.disableFieldFailed": "Uitschakelen van veld is mislukt. Laad opnieuw.",
"schemas.enableFieldFailed": "Kan veld niet inschakelen. Laad opnieuw.",
"schemas.export.deleteFields": "Velden verwijderen",
"schemas.export.recreateFields": "Velden opnieuw maken",
"schemas.export.synchronize": "Synchroniseren",
"schemas.field.allowedValues": "Toegestane waarden",
"schemas.field.defaultValue": "Standaardwaarde",
"schemas.field.deleteConfirmText": "Weet je zeker dat je het veld wilt verwijderen?",
"schemas.field.deleteConfirmTitle": "Verwijder veld",
"schemas.field.disable": "Uitschakelen in gebruikersinterface",
"schemas.field.disabledMarker": "Uitgeschakeld",
"schemas.field.editor": "Editor",
"schemas.field.editorUrl": "Editor-URL",
"schemas.field.editorUrlHint": "Url naar uw plug-in als je een aangepaste editor gebruikt.",
"schemas.field.empty": "Nog geen veld aangemaakt.",
"schemas.field.enable": "Inschakelen in gebruikersinterface",
"schemas.field.enabledMarker": "Ingeschakeld",
"schemas.field.hiddenMarker": "Verborgen",
"schemas.field.hide": "Verbergen in API",
"schemas.field.hintsHint": "Beschrijf dit schema voor documentatie en gebruikersinterfaces.",
"schemas.field.inlineEditable": "Inline bewerkbaar",
"schemas.field.labelHint": "Weergavenaam voor documentatie en gebruikersinterfaces.",
"schemas.field.localizable": "Localizable",
"schemas.field.localizableHint": "Je kunt het veld markeren als lokaliseerbaar. Dit betekent dat het afhankelijk is van de taal, bijvoorbeeld de naam van een stad.",
"schemas.field.localizableMarker": "localizable",
"schemas.field.lock": "Vergrendel en voorkom wijzigingen",
"schemas.field.lockConfirmText": "WAARSCHUWING: het vergrendelen van een veld kan niet ongedaan worden gemaakt! Vergrendelde velddefinities kunnen niet meer worden ontgrendeld, verwijderd of gewijzigd. Wil je dit veld echt vergrendelen?",
"schemas.field.lockedMarker": "Vergrendeld",
"schemas.field.nameHint": "De naam van het veld in het API-antwoord.",
"schemas.field.namePlaceholder": "Voer veldnaam in",
"schemas.field.nameValidationMessage": "Naam moet een geldige javascript-naam zijn in het geval van een camel.",
"schemas.field.placeholder": "Placeholder",
"schemas.field.placeholderHint": "Definieer de tijdelijke aanduiding voor het invoerbesturingselement.",
"schemas.field.required": "Vereist",
"schemas.field.show": "Weergeven in API",
"schemas.field.tabCommon": "Algemeen",
"schemas.field.tabEditing": "Bewerken",
"schemas.field.tabValidation": "Validatie",
"schemas.field.tagsHint": "Tags om uw veld te annoteren voor automatiseringsprocessen.",
"schemas.field.unique": "Uniek",
"schemas.field.visibleMarker": "Zichtbaar",
"schemas.fieldTypes.array.count": "Items",
"schemas.fieldTypes.array.countMax": "Max. aantal items",
"schemas.fieldTypes.array.countMin": "Min. items",
"schemas.fieldTypes.array.description": "Lijst met ingesloten objecten.",
"schemas.fieldTypes.assets.allowDuplicates": "Dubbele waarden toestaan",
"schemas.fieldTypes.assets.count": "Tellen",
"schemas.fieldTypes.assets.countMax": "Max. bestanden",
"schemas.fieldTypes.assets.countMin": "Min. bestanden",
"schemas.fieldTypes.assets.description": "Afbeeldingen, video's, documenten.",
"schemas.fieldTypes.assets.fileExtensions": "Bestandsextensies",
"schemas.fieldTypes.assets.mustBeImage": "Moet afbeelding zijn",
"schemas.fieldTypes.assets.previewMode": "PreviewMode",
"schemas.fieldTypes.assets.previewModeHint": "De voorbeeldmodus voor items in inhoudslijsten.",
"schemas.fieldTypes.assets.previewModeName": "Alleen bestandsnaam",
"schemas.fieldTypes.assets.previewModeTumbnailName": "Miniatuur- en bestandsnaam",
"schemas.fieldTypes.assets.previewModeTumbnailOrName": "Alleen miniatuur- of bestandsnaam indien geen afbeelding",
"schemas.fieldTypes.assets.resolve": "Eerste item oplossen",
"schemas.fieldTypes.assets.resolveHint": "Toon het eerste item waarnaar wordt verwezen in de inhoudslijst.",
"schemas.fieldTypes.assets.size": "Grootte",
"schemas.fieldTypes.assets.sizeMax": "Min. grootte",
"schemas.fieldTypes.assets.sizeMin": "Max. grootte",
"schemas.fieldTypes.boolean.description": "Ja of nee, waar of niet waar.",
"schemas.fieldTypes.dateTime.defaultMode": "Standaardmodus",
"schemas.fieldTypes.dateTime.description": "Datum van evenementen, openingstijden.",
"schemas.fieldTypes.dateTime.rangeMax": "Max. waarde",
"schemas.fieldTypes.dateTime.rangeMin": "Min. waarde",
"schemas.fieldTypes.geolocation.description": "Coördinaten: lengte- en breedtegraad.",
"schemas.fieldTypes.json.description": "Gegevens in JSON-indeling, voor ontwikkelaars.",
"schemas.fieldTypes.number.description": "ID, bestelnummer, beoordeling, aantal.",
"schemas.fieldTypes.number.range": "Bereik",
"schemas.fieldTypes.number.rangeMax": "Max. waarde",
"schemas.fieldTypes.number.rangeMin": "Min. waarde",
"schemas.fieldTypes.references.count": "Artikelen",
"schemas.fieldTypes.references.countMax": "Max. aantal items",
"schemas.fieldTypes.references.countMin": "Min. items",
"schemas.fieldTypes.references.description": "Links naar andere inhoudsitems.",
"schemas.fieldTypes.references.resolveHint": "Toon de naam van het item waarnaar wordt verwezen in de inhoudslijst wanneer MaxItems is ingesteld op 1.",
"schemas.fieldTypes.string.description": "Titels, namen, alinea's.",
"schemas.fieldTypes.string.length": "Lengte",
"schemas.fieldTypes.string.lengthMax": "Max. lengte",
"schemas.fieldTypes.string.lengthMin": "Min. lengte",
"schemas.fieldTypes.string.pattern": "Regex-patroon",
"schemas.fieldTypes.string.patternMessage": "Patroonbericht",
"schemas.fieldTypes.string.suggestions": "Suggesties",
"schemas.fieldTypes.tags.count": "Artikelen",
"schemas.fieldTypes.tags.countMax": "Max. aantal items",
"schemas.fieldTypes.tags.countMin": "Min. items",
"schemas.fieldTypes.tags.description": "Speciaal formaat voor tags.",
"schemas.fieldTypes.ui.description": "Scheidingsteken voor het bewerken van gebruikersinterface.",
"schemas.hideFieldFailed": "Kan veld niet verbergen. Laad opnieuw.",
"schemas.import": "Importeer schema",
"schemas.listFields": "Lijstvelden",
"schemas.listFieldsEmpty": "Zet het veld hier neer of rangschik ze opnieuw om de velden in de inhoudslijst weer te geven. Als er geen lijstveld is gedefinieerd, wordt het eerste veld gebruikt.",
"schemas.loadFailed": "Kan schema's niet laden. Laad opnieuw.",
"schemas.loadSchemaFailed": "Kan schema niet laden. Laad opnieuw.",
"schemas.lockFieldFailed": "Kan veld niet vergrendelen. Laad opnieuw.",
"schemas.modeMultiple": "Meerdere inhoud",
"schemas.modeMultipleDescription": "Beste voor meerdere instanties, zoals blogposts, pagina's, auteurs, producten ...",
"schemas.modeSingle": "Enkele inhoud",
"schemas.modeSingleDescription": "Beste voor afzonderlijke instanties zoals de startpagina, privacybeleid, instellingen ...",
"schemas.nameWarning": "Deze waarden kunnen later niet worden gewijzigd.",
"schemas.previewUrls.empty": "Geen voorbeeld-URL's geconfigureerd.",
"schemas.previewUrls.help": "Bekijk de geïntegreerde helppagina voor meer informatie over voorbeeld-URL's.",
"schemas.previewUrls.namePlaceholder": "Web of mobiel",
"schemas.previewUrls.title": "Voorbeeld-URL's",
"schemas.previewUrls.urlPlaceholder": "URL met variabelen",
"schemas.published": "Gepubliceerd",
"schemas.publishedTour": "Merk op dat je het schema moet publiceren voordat je er inhoud aan kunt toevoegen.",
"schemas.publishFailed": "Kan schema niet publiceren. Laad opnieuw.",
"schemas.referenceFields": "Referentievelden",
"schemas.referenceFieldsEmpty": "Zet het veld hier neer of rangschik ze opnieuw om de velden weer te geven wanneer ernaar wordt verwezen door een andere inhoud. Als er geen referentieveld is gedefinieerd, worden de lijstvelden gebruikt.",
"schemas.reloaded": "Schema's herladen.",
"schemas.reorderFieldsFailed": "De volgorde van velden is mislukt. Laad opnieuw.",
"schemas.rules.action": "Actie",
"schemas.rules.condition": "Conditie in Javascript",
"schemas.rules.empty": "Geen veldregels geconfigureerd.",
"schemas.rules.title": "Veldregels",
"schemas.rules.when": "Wanneer",
"schemas.saved": "Schema succesvol opgeslagen.",
"schemas.saveFieldAndClose": "Opslaan en sluiten",
"schemas.saveFieldAndNew": "Opslaan en veld toevoegen",
"schemas.schemaHintsHint": "Beschrijf dit schema voor documentatie en gebruikersinterfaces.",
"schemas.schemaLabelHint": "Weergavenaam voor documentatie en gebruikersinterfaces.",
"schemas.schemaNameHint": "Je mag alleen letters, cijfers en streepjes gebruiken en niet meer dan 40 tekens.",
"schemas.schemaNameValidationMessage": "Naam mag alleen letters, cijfers, streepjes en spaties bevatten.",
"schemas.schemaTagsHint": "Tags om uw schema voor automatiseringsprocessen te annoteren.",
"schemas.searchPlaceholder": "Zoek schema's ...",
"schemas.showFieldFailed": "Kan veld niet weergeven. Laad opnieuw.",
"schemas.synchronized": "Schema is succesvol gesynchroniseerd.",
"schemas.synchronizeFailed": "Synchroniseren van schema is mislukt. Laad opnieuw.",
"schemas.tabFields": "Velden",
"schemas.tabJson": "Json",
"schemas.tabMore": "Meer",
"schemas.tabScripts": "Scripts",
"schemas.tabUI": "UI",
"schemas.ui": "Toegewezen velden",
"schemas.ui.unassignedFields": "Niet-toegewezen velden",
"schemas.unpublished": "Niet gepubliceerd",
"schemas.unpublishFailed": "Kan de publicatie van het schema niet ongedaan maken. Laad het opnieuw.",
"schemas.updateFailed": "Kan schema niet updaten. Laad opnieuw.",
"schemas.updateFieldFailed": "Kan veld niet bijwerken. Laad opnieuw.",
"schemas.updatePreviewUrlsFailed": "Configureren van voorbeeld-URL's is mislukt. Laad opnieuw.",
"schemas.updateRulesFailed": "Updaten van schemaregels is mislukt. Laad opnieuw.",
"schemas.updateScriptsFailed": "Updaten van schemascripts is mislukt. Laad opnieuw.",
"schemas.updateUIFieldsFailed": "Bijwerken van UI-velden is mislukt. Laad opnieuw.",
"search.addFilter": "Filter toevoegen",
"search.addGroup": "Groep toevoegen",
"search.addSorting": "Sortering toevoegen",
"search.advancedTour": "Klik op dit pictogram om het geavanceerde zoekmenu weer te geven!",
"search.customQuery": "Aangepaste zoekopdracht",
"search.fullTextTour": "Zoek naar inhoud met volledige tekstzoekopdracht in alle velden en talen!",
"search.help": "Lees meer over filteren in de [Documentation] (https: // https: //docs.squidex.io/04-guides/02-api.html).",
"search.myQueries": "Mijn zoekopdrachten",
"search.nameQuery": "Geef uw zoekopdracht een naam",
"search.queriesEmpty": "Zoek naar {types} en gebruik <i class = \" icon-star-empty \"> </i> icon in het zoekformulier om de zoekopdracht op te slaan voor alle bijdragers.",
"search.queryAllNewestFirst": "Alle (nieuwste eerst)",
"search.queryAllOldestFirst": "Alle (oudste eerst)",
"search.quickNavPlaceholder": "Snelle navigatie (druk op 'q')",
"search.saveQueryMyself": "Bewaar de zoekopdracht alleen voor mezelf.",
"search.searchFailed": "Zoeken mislukt. Laad opnieuw.",
"search.sharedQueries": "Gedeelde zoekopdrachten",
"search.sorting": "Sorteren",
"start.login": "Log in op Squidex",
"start.loginHint": "De login-knop opent een nieuwe pop-up. Zodra je succesvol bent ingelogd, zullen we je doorverwijzen naar het Squidex beheerportaal.",
"start.madeBy": "Met trots gemaakt door",
"start.madeByCopyright": "Sebastian Stehle en medewerkers, 2016-2020",
"tour.joinForum": "Word lid van ons forum",
"tour.joinGithub": "Bezoek ons ​​op Github",
"tour.skip": "Tour overslaan",
"tour.step0Next": "Laten we eens rondkijken",
"tour.step0Text": "Je kunt direct beginnen met het beheren en distribueren van uw inhoud, maar we willen je graag eerst wat basisbeginselen laten zien ... \n \n Hoe dat",
"tour.step1Next": "Doorgaan",
"tour.step1Text": "Een app is de opslagplaats voor uw project, bijvoorbeeld (blog, webshop of mobiele app). Je kunt bijdragers aan uw app toewijzen om samen te werken. \n \n Je kunt een onbeperkt aantal apps maken in Squidex om meerdere projecten tegelijkertijd te beheren. ",
"tour.step2Next": "Ga door!",
"tour.step2Text": "Schema's bepalen de structuur van uw inhoud, de velden en de gegevenstypen van een inhoudsitem. \n \n Voordat je inhoud aan uw schema kunt toevoegen, moet je op de knop 'Publiceren' bovenaan klikken om het schema beschikbaar te maken voor uw inhoudeditors. ",
"tour.step3Next": "Bijna klaar!",
"tour.step3Text": "Inhoud zijn de feitelijke gegevens in uw app die zijn gegroepeerd op basis van het schema. \n \n Selecteer eerst een gepubliceerd schema en voeg vervolgens inhoud toe voor dit schema.",
"tour.step4Next": "Begrepen!",
"tour.step4Text": "De mappen bevatten alle bestanden die ook aan uw inhoud kunnen worden gekoppeld. Bijvoorbeeld afbeeldingen, video's of documenten. \n \n Je kunt de bestanden hier uploaden en later gebruiken of ze direct uploaden wanneer je een nieuw contentitem met een bestandveld maakt. ",
"tour.step5Text": "Maar dat is niet alle ondersteuning die we kunnen bieden. \n \n Je kunt naar https://docs.squidex.io/> gaan om meer te lezen. \n \n Wil je lid worden van onze community ? ",
"tour.step5Title": "Geweldig, nu ken je de basis!",
"tour.tooltipConfirm": "Begrepen",
"tour.tooltipStop": "Tour stoppen",
"tour.welcome": "Welkom bij",
"tour.welcomeProduct": "Squidex CMS",
"translate.translateFailed": "Kan tekst niet vertalen. Laad opnieuw.",
"usages.loadCallsFailed": "Kan gebruik van oproepen niet laden. Laad opnieuw.",
"usages.loadMonthlyCallsFailed": "Laden van maandelijkse API-aanroepen is mislukt. Laad opnieuw.",
"usages.loadStorageFailed": "Laden van opslaggebruik is mislukt. Laad opnieuw.",
"usages.loadTodayStorageFailed": "Kan de huidige opslaggrootte niet laden. Laad opnieuw.",
"users.create": "Nieuw",
"users.createFailed": "Aanmaken van gebruiker mislukt. Laad opnieuw.",
"users.createPageTitle": "Gebruiker aanmaken",
"users.createTitle": "Nieuwe gebruiker",
"users.createTooltip": "Nieuwe gebruiker (CTRL + N)",
"users.editPageTitle": "Gebruiker bewerken",
"users.editTitle": "Gebruiker bewerken",
"users.listPageTitle": "Gebruikersbeheer",
"users.listTitle": "Gebruikers",
"users.loadFailed": "Laden van gebruikers mislukt. Laad opnieuw.",
"users.loadUserFailed": "Kan gebruiker niet laden. Laad opnieuw.",
"users.lockTooltip": "Gebruiker vergrendelen",
"users.passwordConfirmValidationMessage": "Wachtwoorden moeten hetzelfde zijn.",
"users.refreshTooltip": "Ververs gebruikers (CTRL + SHIFT + R)",
"users.reloaded": "Gebruikers herladen.",
"users.search": "Zoeken naar gebruiker",
"users.unlockTooltip": "Gebruiker ontgrendelen",
"users.updateFailed": "Update gebruiker mislukt. Laad opnieuw.",
"validation.between": "{field} moet tussen '{min}' en '{max}' liggen.",
"validation.betweenlength": "{field|upper} moet tussen {minlength} en {maxlength} item (s) bevatten.",
"validation.betweenlengthstring": "{field|upper} moet tussen {minlength} en {maxlength} teken (s) bevatten.",
"validation.email": "{field|upper} moet een e-mailadres zijn.",
"validation.exactly": "{field|upper} moet exact '{expected}' zijn.",
"validation.exactlylength": "{field|upper} moet exact {expected} item (s) bevatten.",
"validation.exactlylengthstring": "{field|upper} moet exact {expected} teken (s) bevatten.",
"validation.match": "{message}",
"validation.max": "{field|upper} moet kleiner zijn dan of gelijk zijn aan '{max}'.",
"validation.maxlength": "{field|upper} mag niet meer dan {requiredlength} item (s) bevatten.",
"validation.maxlengthstring": "{field|upper} mag niet meer dan {requiredlength} teken (s) bevatten.",
"validation.min": "{field|upper} moet groter zijn dan of gelijk zijn aan '{min}'.",
"validation.minlength": "{field|upper} moet minimaal {requiredlength} item (s) bevatten.",
"validation.minlengthstring": "{field|upper} moet minimaal {requiredlength} teken (s) bevatten.",
"validation.pattern": "{field|upper} komt niet overeen met het patroon.",
"validation.patternmessage": "{message}",
"validation.required": "{field|upper} is vereist.",
"validation.requiredTrue": "{field|upper} is vereist.",
"validation.uniquestrings": "{field|upper} mag geen dubbele waarden bevatten.",
"validation.validarrayvalues": "{field|upper} bevat een ongeldige waarde: {invalidvalue}.",
"validation.validdatetime": "{field|upper} is geen geldige datum en tijd.",
"validation.validvalues": "{field|upper} is geen geldige waarde.",
"workflows.add": "Workflow toevoegen",
"workflows.addStep": "Stap toevoegen",
"workflows.createFailed": "Maken van workflow mislukt. Laad opnieuw.",
"workflows.deleteConfirmText": "Wil je de workflow echt verwijderen?",
"workflows.deleteConfirmTitle": "Workflow verwijderen",
"workflows.deleteFailed": "Verwijderen van workflow is mislukt. Laad opnieuw.",
"workflows.empty": "Nog geen workflows gemaakt.",
"workflows.loadFailed": "Kan workflows niet laden. Laad opnieuw.",
"workflows.notNamed": "Naamloze workflow",
"workflows.preventUpdates": "Updates voorkomen",
"workflows.publishedNotRemovable": "Kan niet worden verwijderd",
"workflows.refreshTooltip": "Werkstromen vernieuwen (CTRL + SHIFT + R)",
"workflows.reloaded": "Workflows opnieuw geladen.",
"workflows.saved": "Workflow is opgeslagen.",
"workflows.schemasHint": "Beperk deze workflow tot specifieke schema's of laat het leeg voor alle schema's.",
"workflows.syntax.expression": "Expressie",
"workflows.syntax.for": "for",
"workflows.syntax.when": "when",
"workflows.tabEdit": "Bewerken",
"workflows.tabVisualize": "Visualiseren",
"workflows.updateFailed": "Update van workflow is mislukt. Laad opnieuw.",
"workflows.workflowNameHint": "Optionele naam voor de workflow.",
"workflows.workflowNamePlaceholder": "Voer de werkstroomnaam in"
}

7
backend/i18n/translate.bat

@ -0,0 +1,7 @@
cd translator\Squidex.Translator
dotnet run translate check-backend D:\Squidex
dotnet run translate check-frontend D:\Squidex
dotnet run translate gen-frontend D:\Squidex
dotnet run translate gen-backend D:\Squidex

10
backend/i18n/translate.sh

@ -0,0 +1,10 @@
#!/bin/bash
PATH=${1:-/Squidex}
cd translator/Squidex.Translator
/usr/local/share/dotnet/dotnet run translate check-backend $1
/usr/local/share/dotnet/dotnet run translate check-frontend $1
/usr/local/share/dotnet/dotnet run translate gen-frontend $1
/usr/local/share/dotnet/dotnet run translate gen-backend $1

25
backend/i18n/translator/Squidex.Translator.sln

@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30128.74
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Squidex.Translator", "Squidex.Translator\Squidex.Translator.csproj", "{AB1B327F-B64A-4CD7-AF2D-47EEFFE5855F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{AB1B327F-B64A-4CD7-AF2D-47EEFFE5855F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AB1B327F-B64A-4CD7-AF2D-47EEFFE5855F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AB1B327F-B64A-4CD7-AF2D-47EEFFE5855F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AB1B327F-B64A-4CD7-AF2D-47EEFFE5855F}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {1A53C732-1705-4578-A007-BA9536B3957E}
EndGlobalSection
EndGlobal

153
backend/i18n/translator/Squidex.Translator/Commands.cs

@ -0,0 +1,153 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System;
using System.IO;
using CommandDotNet;
using FluentValidation;
using FluentValidation.Attributes;
using Squidex.Translator.Processes;
using Squidex.Translator.State;
namespace Squidex.Translator
{
public class Commands
{
[Command(Name = "info", Description = "Shows information about the translator.")]
public void Info()
{
var version = typeof(Commands).Assembly.GetName().Version;
Console.WriteLine($"Squidex Translator Version v{version}");
}
[Command(Name = "translate", Description = "Translates different parts.")]
[SubCommand]
public class Translate
{
[Command(Name = "check-backend", Description = "Check backend files.")]
public void CheckBackend(TranslateArguments arguments)
{
var (folder, service) = Setup(arguments, "backend");
new CheckBackend(folder, service).Run();
}
[Command(Name = "check-frontend", Description = "Check frontend files.")]
public void CheckFrontend(TranslateArguments arguments)
{
var (folder, service) = Setup(arguments, "frontend");
new CheckFrontend(folder, service).Run();
}
[Command(Name = "backend", Description = "Translate backend files.")]
public void Backend(TranslateArguments arguments)
{
var (folder, service) = Setup(arguments, "backend");
new TranslateBackend(folder, service).Run();
}
[Command(Name = "templates", Description = "Translate angular templates.")]
public void Templates(TranslateArguments arguments)
{
var (folder, service) = Setup(arguments, "frontend");
new TranslateTemplates(folder, service).Run(arguments.Report);
}
[Command(Name = "typescript", Description = "Translate typescript files.")]
public void Typescript(TranslateArguments arguments)
{
var (folder, service) = Setup(arguments, "frontend");
new TranslateTypescript(folder, service).Run();
}
[Command(Name = "gen-backend", Description = "Generate the backend translations.")]
public void GenerateBackend(TranslateArguments arguments)
{
var (folder, service) = Setup(arguments, "backend");
new GenerateBackendResources(folder, service).Run();
}
[Command(Name = "gen-frontend", Description = "Generate the frontend translations.")]
public void GenerateFrontend(TranslateArguments arguments)
{
var (folder, service) = Setup(arguments, "frontend");
new GenerateFrontendResources(folder, service).Run();
}
[Command(Name = "gen-keys", Description = "Generate the keys for translations.")]
public void GenerateBackendKeys(TranslateArguments arguments)
{
var (backendFolder, serviceBackend) = Setup(arguments, "backend");
new GenerateKeys(backendFolder, serviceBackend, "backend_keys.json").Run();
var (frontendFolder, frontendService) = Setup(arguments, "frontend");
new GenerateKeys(frontendFolder, frontendService, "frontend_keys.json").Run();
}
[Command(Name = "migrate-backend", Description = "Migrate the backend files.")]
public void MigrateBackend(TranslateArguments arguments)
{
var (_, service) = Setup(arguments, "backend");
service.Migrate();
}
[Command(Name = "migrate-frontend", Description = "Migrate the frontend files.")]
public void MigrateFrontend(TranslateArguments arguments)
{
var (_, service) = Setup(arguments, "frontend");
service.Migrate();
}
private static (DirectoryInfo, TranslationService) Setup(TranslateArguments arguments, string fileName)
{
if (!Directory.Exists(arguments.Folder))
{
throw new ArgumentException("Folder does not exist.");
}
var locales = new string[] { "en", "nl" };
var translationsDirectory = new DirectoryInfo(Path.Combine(arguments.Folder, "backend", "i18n"));
var translationsService = new TranslationService(translationsDirectory, fileName, locales, arguments.SingleWords);
return (new DirectoryInfo(arguments.Folder), translationsService);
}
}
[Validator(typeof(Validator))]
public sealed class TranslateArguments : IArgumentModel
{
[Operand(Name = "folder", Description = "The squidex folder.")]
public string Folder { get; set; }
[Option(LongName = "single", ShortName = "s", Description = "Single words only.")]
public bool SingleWords { get; set; }
[Option(LongName = "report", ShortName = "r")]
public bool Report { get; set; }
public sealed class Validator : AbstractValidator<TranslateArguments>
{
public Validator()
{
RuleFor(x => x.Folder).NotEmpty();
}
}
}
}
}

24
backend/i18n/translator/Squidex.Translator/Extensions.cs

@ -0,0 +1,24 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System.Linq;
namespace Squidex.Translator
{
public static class Extensions
{
public static bool IsPotentialText(this string text)
{
return !string.IsNullOrWhiteSpace(text) && text.Any(c => char.IsLetter(c));
}
public static bool IsPotentialMultiWordText(this string text)
{
return text.Contains(' ') && text.IsPotentialText();
}
}
}

57
backend/i18n/translator/Squidex.Translator/Processes/Backend.cs

@ -0,0 +1,57 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace Squidex.Translator.Processes
{
public static class Backend
{
public static DirectoryInfo GetFolder(DirectoryInfo folder)
{
return new DirectoryInfo(Path.Combine(folder.FullName, "backend", "src"));
}
public static IEnumerable<(FileInfo, string)> GetFiles(DirectoryInfo folder)
{
var files =
folder.GetFiles(@"*.cs", SearchOption.AllDirectories).Union(
folder.GetFiles(@"*.cshtml", SearchOption.AllDirectories));
foreach (var file in files)
{
var relativeName = Helper.RelativeName(file, folder);
if (relativeName.Contains("/obj/") || relativeName.Contains("/bin/"))
{
continue;
}
yield return (file, relativeName);
}
}
public static IEnumerable<(FileInfo, string)> GetFilesCS(DirectoryInfo folder)
{
var files = folder.GetFiles(@"*AssetsController.cs", SearchOption.AllDirectories);
foreach (var file in files)
{
var relativeName = Helper.RelativeName(file, folder);
if (relativeName.Contains("/obj/") || relativeName.Contains("/bin/"))
{
continue;
}
yield return (file, relativeName);
}
}
}
}

57
backend/i18n/translator/Squidex.Translator/Processes/CheckBackend.cs

@ -0,0 +1,57 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using Squidex.Translator.State;
namespace Squidex.Translator.Processes
{
public class CheckBackend
{
private readonly TranslationService service;
private readonly DirectoryInfo folder;
public CheckBackend(DirectoryInfo folder, TranslationService service)
{
this.folder = Backend.GetFolder(folder);
this.service = service;
}
public void Run()
{
var all = new HashSet<string>();
foreach (var (file, relativeName) in Backend.GetFiles(folder))
{
var content = File.ReadAllText(file.FullName);
var matches = Regex.Matches(content, "T\\.Get\\(\"(?<Key>[^\"]*)\"");
var translations = new HashSet<string>();
foreach (Match match in matches)
{
var key = match.Groups["Key"].Value;
translations.Add(key);
all.Add(key);
}
Helper.CheckForFile(service, relativeName, translations);
}
Helper.CheckUnused(service, all);
Helper.CheckOtherLocales(service);
service.Save();
}
}
}

121
backend/i18n/translator/Squidex.Translator/Processes/CheckFrontend.cs

@ -0,0 +1,121 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using Squidex.Translator.State;
namespace Squidex.Translator.Processes
{
public class CheckFrontend
{
private readonly TranslationService service;
private readonly DirectoryInfo folder;
public CheckFrontend(DirectoryInfo folder, TranslationService service)
{
this.folder = Frontend.GetFolder(folder);
this.service = service;
}
public void Run()
{
var all = new HashSet<string>();
foreach (var (file, relativeName) in Frontend.GetTemplateFiles(folder))
{
var translations = GetTranslationsInTemplate(file);
foreach (var translation in translations)
{
all.Add(translation);
}
Helper.CheckForFile(service, relativeName, translations);
}
foreach (var (file, relativeName) in Frontend.GetTypescriptFiles(folder))
{
var translations = GetTranslationsInTypescript(file);
foreach (var translation in translations)
{
all.Add(translation);
}
Helper.CheckForFile(service, relativeName, translations);
}
Helper.CheckUnused(service, all);
Helper.CheckOtherLocales(service);
service.Save();
}
private HashSet<string> GetTranslationsInTemplate(FileInfo file)
{
var content = File.ReadAllText(file.FullName);
var translations = new HashSet<string>();
var matches0 = Regex.Matches(content, "\"i18n\\:(?<Key>[^\"]+)\"", RegexOptions.Singleline);
foreach (Match match in matches0)
{
translations.Add(match.Groups["Key"].Value);
}
var matches1 = Regex.Matches(content, "'i18n\\:(?<Key>[^\']+)'", RegexOptions.Singleline);
foreach (Match match in matches1)
{
translations.Add(match.Groups["Key"].Value);
}
var matches2 = Regex.Matches(content, "'(?<Key>[^\']+)' \\| sqxTranslate", RegexOptions.Singleline);
foreach (Match match in matches2)
{
translations.Add(match.Groups["Key"].Value);
}
return translations;
}
private HashSet<string> GetTranslationsInTypescript(FileInfo file)
{
var content = File.ReadAllText(file.FullName);
var translations = new HashSet<string>();
var matches1 = Regex.Matches(content, "'i18n\\:(?<Key>[^\']+)'", RegexOptions.Singleline);
foreach (Match match in matches1)
{
translations.Add(match.Groups["Key"].Value);
}
var matches2 = Regex.Matches(content, "localizer.get\\('(?<Key>[^\']+)'\\)", RegexOptions.Singleline);
foreach (Match match in matches2)
{
translations.Add(match.Groups["Key"].Value);
}
var matches3 = Regex.Matches(content, "localizer.getOrKey\\('(?<Key>[^\']+)'\\)", RegexOptions.Singleline);
foreach (Match match in matches3)
{
translations.Add(match.Groups["Key"].Value);
}
return translations;
}
}
}

46
backend/i18n/translator/Squidex.Translator/Processes/Frontend.cs

@ -0,0 +1,46 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System;
using System.Collections.Generic;
using System.IO;
namespace Squidex.Translator.Processes
{
public static class Frontend
{
public static DirectoryInfo GetFolder(DirectoryInfo folder)
{
return new DirectoryInfo(Path.Combine(folder.FullName, "frontend", "app"));
}
public static IEnumerable<(FileInfo, string)> GetTypescriptFiles(DirectoryInfo folder)
{
var files = folder.GetFiles(@"*.ts", SearchOption.AllDirectories);
foreach (var file in files)
{
if (file.Name.EndsWith(".spec.ts", StringComparison.OrdinalIgnoreCase))
{
continue;
}
yield return (file, Helper.RelativeName(file, folder));
}
}
public static IEnumerable<(FileInfo, string)> GetTemplateFiles(DirectoryInfo folder)
{
var files = folder.GetFiles(@"*.html", SearchOption.AllDirectories);
foreach (var file in files)
{
yield return (file, Helper.RelativeName(file, folder));
}
}
}
}

58
backend/i18n/translator/Squidex.Translator/Processes/GenerateBackendResources.cs

@ -0,0 +1,58 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System.IO;
using System.Resources.NetStandard;
using Squidex.Translator.State;
namespace Squidex.Translator.Processes
{
public sealed class GenerateBackendResources
{
private readonly TranslationService service;
private readonly DirectoryInfo folder;
public GenerateBackendResources(DirectoryInfo folder, TranslationService service)
{
this.folder = new DirectoryInfo(Path.Combine(folder.FullName, "backend", "src", "Squidex.Shared"));
this.service = service;
}
public void Run()
{
foreach (var locale in service.SupportedLocales)
{
var name = locale ==
service.MainLocale ?
$"Texts.resx" :
$"Texts.{locale}.resx";
var fullName = Path.Combine(folder.FullName, name);
using (var writer = new ResXResourceWriter(fullName))
{
var texts = service.GetTextsWithFallback(locale);
foreach (var (key, value) in texts)
{
writer.AddResource(key, value);
}
}
var text = File.ReadAllText(fullName);
text = text.Replace("System.Resources.NetStandard.ResXResourceReader, System.Resources.NetStandard, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", "System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");
text = text.Replace("System.Resources.NetStandard.ResXResourceWriter, System.Resources.NetStandard, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", "System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");
File.WriteAllText(fullName, text);
}
service.Save();
}
}
}

44
backend/i18n/translator/Squidex.Translator/Processes/GenerateFrontendResources.cs

@ -0,0 +1,44 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System.IO;
using Squidex.Translator.State;
namespace Squidex.Translator.Processes
{
public sealed class GenerateFrontendResources
{
private readonly TranslationService service;
private readonly DirectoryInfo folder;
public GenerateFrontendResources(DirectoryInfo folder, TranslationService service)
{
this.folder = new DirectoryInfo(Path.Combine(folder.FullName, "backend", "i18n"));
this.service = service;
}
public void Run()
{
foreach (var locale in service.SupportedLocales)
{
var fullName = Path.Combine(folder.FullName, $"frontend_{locale}.json");
if (!folder.Exists)
{
Directory.CreateDirectory(folder.FullName);
}
var texts = service.GetTextsWithFallback(locale);
service.WriteTo(texts, fullName);
}
service.Save();
}
}
}

47
backend/i18n/translator/Squidex.Translator/Processes/GenerateKeys.cs

@ -0,0 +1,47 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System.IO;
using Squidex.Translator.State;
namespace Squidex.Translator.Processes
{
public sealed class GenerateKeys
{
private readonly TranslationService service;
private readonly string fileName;
private readonly DirectoryInfo folder;
public GenerateKeys(DirectoryInfo folder, TranslationService service, string fileName)
{
this.folder = folder;
this.service = service;
this.fileName = fileName;
}
public void Run()
{
var keys = new TranslatedTexts();
foreach (var text in service.MainTranslations)
{
keys.Add(text.Key, string.Empty);
}
var fullName = Path.Combine(folder.FullName, fileName);
if (!folder.Exists)
{
Directory.CreateDirectory(folder.FullName);
}
service.WriteTo(keys, fullName);
service.Save();
}
}
}

143
backend/i18n/translator/Squidex.Translator/Processes/Helper.cs

@ -0,0 +1,143 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Squidex.Translator.State;
namespace Squidex.Translator.Processes
{
public static class Helper
{
public static string RelativeName(FileInfo file, DirectoryInfo folder)
{
return file.FullName.Substring(folder.FullName.Length).Replace("\\", "/");
}
public static void CheckOtherLocales(TranslationService service)
{
var mainTranslations = service.MainTranslations;
foreach (var (locale, texts) in service.Translations.Where(x => x.Key != service.MainLocale))
{
Console.WriteLine();
Console.WriteLine("Checking {0}", locale);
var notTranslated = mainTranslations.Keys.Except(texts.Keys).ToList();
var notUsed = texts.Keys.Except(mainTranslations.Keys).ToList();
if (notTranslated.Count > 0 || notUsed.Count > 0)
{
if (notTranslated.Count > 0)
{
Console.WriteLine();
Console.WriteLine("Translations missing:");
foreach (var key in notTranslated.OrderBy(x => x))
{
Console.Write(" * ");
Console.WriteLine(key);
}
}
if (notUsed.Count > 0)
{
Console.WriteLine();
Console.WriteLine("Translations not used:");
foreach (var key in notUsed.OrderBy(x => x))
{
Console.Write(" * ");
Console.WriteLine(key);
}
}
}
else
{
Console.WriteLine("> No errors found");
}
}
}
public static void CheckUnused(TranslationService service, HashSet<string> translations)
{
var notUsed = new SortedSet<string>();
foreach (var key in service.MainTranslations.Keys)
{
if (!translations.Contains(key) &&
!key.StartsWith("validation.", StringComparison.OrdinalIgnoreCase) &&
!key.StartsWith("aspnet_", StringComparison.OrdinalIgnoreCase))
{
notUsed.Add(key);
}
}
if (notUsed.Count > 0)
{
Console.WriteLine("Translations not used:");
foreach (var key in notUsed)
{
Console.Write(" * ");
Console.WriteLine(key);
}
}
}
public static void CheckForFile(TranslationService service, string relativeName, HashSet<string> translations)
{
if (translations.Count > 0)
{
var prefixes = new HashSet<string>();
foreach (var key in translations.ToList())
{
if (service.MainTranslations.ContainsKey(key))
{
translations.Remove(key);
}
var parts = key.Split(".");
if (parts[0] != "common" && parts[0] != "validation")
{
prefixes.Add(parts[0]);
}
}
if (HasInvalidPrefixes(prefixes) || translations.Count > 0)
{
Console.WriteLine("Errors in file {0}.", relativeName);
if (HasInvalidPrefixes(prefixes))
{
Console.WriteLine(" > Multiple prefixes found: {0}", string.Join(",", prefixes));
}
if (translations.Count > 0)
{
foreach (var key in translations)
{
Console.Write(" * ");
Console.WriteLine(key);
}
}
Console.WriteLine();
}
}
}
private static bool HasInvalidPrefixes(HashSet<string> prefixes)
{
return prefixes.Count > 1;
}
}
}

64
backend/i18n/translator/Squidex.Translator/Processes/TranslateBackend.cs

@ -0,0 +1,64 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System;
using System.IO;
using System.Text.RegularExpressions;
using Squidex.Translator.State;
namespace Squidex.Translator.Processes
{
public class TranslateBackend
{
private readonly TranslationService service;
private readonly DirectoryInfo folder;
public TranslateBackend(DirectoryInfo folder, TranslationService service)
{
this.folder = Backend.GetFolder(folder);
this.service = service;
}
public void Run()
{
foreach (var (file, relativeName) in Backend.GetFilesCS(folder))
{
var content = File.ReadAllText(file.FullName);
var isReplaced = false;
content = Regex.Replace(content, "\"[^\"]*\"", match =>
{
var value = match.Value[1..^1];
string result = null;
if (value.IsPotentialMultiWordText())
{
service.Translate(relativeName, value, "Code", key =>
{
result = $"T.Get(\"{key}\")";
isReplaced = true;
});
}
return result ?? $"\"{value}\"";
});
if (isReplaced)
{
Console.WriteLine("-----------------------------");
Console.WriteLine("FILE {0} done", relativeName);
File.WriteAllText(file.FullName, content);
}
}
}
}
}

212
backend/i18n/translator/Squidex.Translator/Processes/TranslateTemplates.cs

@ -0,0 +1,212 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using HtmlAgilityPack;
using Squidex.Translator.State;
#pragma warning disable SA1025 // Code should not contain multiple whitespace in a row
namespace Squidex.Translator.Processes
{
public class TranslateTemplates
{
private static readonly HashSet<string> TagsToIgnore = new HashSet<string>
{
"code",
"script",
"sqx-code",
"style"
};
private static readonly HashSet<string> AttributesToTranslate = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{
"title", // Tooltip
"placeholder", // Input placeholder
"confirmTitle", // Confirm Click
"confirmText", // Confirm Click
"message", // Title Component
};
private readonly TranslationService service;
private readonly DirectoryInfo folder;
private bool isReplaced;
private bool isSilent;
private int total;
public TranslateTemplates(DirectoryInfo folder, TranslationService service)
{
this.folder = Frontend.GetFolder(folder);
this.service = service;
}
public void Run(bool reportMissing)
{
isSilent = reportMissing;
foreach (var (file, relativeName) in Frontend.GetTemplateFiles(folder))
{
isReplaced = false;
// Keep the original casing, otherwise *ngIf is translated to ngif
var html = new HtmlDocument
{
OptionOutputOriginalCase = true
};
html.LoadHtml(File.ReadAllText(file.FullName));
Traverse(relativeName, html.DocumentNode);
if (isReplaced && !reportMissing)
{
Console.WriteLine("-----------------------------");
Console.WriteLine("FILE {0} done", relativeName);
SaveHtml(file, html);
}
}
if (reportMissing)
{
Console.WriteLine("TODO: {0}", total);
}
}
private void Traverse(string fileName, HtmlNode node)
{
if (TagsToIgnore.Contains(node.Name))
{
return;
}
if (node is HtmlTextNode textNode)
{
var text = textNode.Text;
// For strings like Next: <div></div>
var trimmed = text.Trim().Trim(':', '(', ')');
const string whitespace = "&nbsp;";
while (trimmed.StartsWith(whitespace, StringComparison.OrdinalIgnoreCase))
{
trimmed = trimmed.Substring(whitespace.Length);
}
while (trimmed.EndsWith(whitespace, StringComparison.OrdinalIgnoreCase))
{
trimmed = trimmed.Substring(0, trimmed.Length - whitespace.Length);
}
if (!string.IsNullOrWhiteSpace(trimmed) && !IsTranslated(trimmed) && !IsVariable(trimmed))
{
if (!string.IsNullOrWhiteSpace(trimmed))
{
// Extract prefix and suffix to keep our original indentation.
var originalIndex = text.IndexOf(trimmed, StringComparison.Ordinal);
var originalPrefix = text.Substring(0, originalIndex);
var originalSuffix = text.Substring(originalIndex + trimmed.Length);
var originText = $"text in {textNode.ParentNode.Name}";
service.Translate(fileName, trimmed, originText, key =>
{
if (isSilent)
{
total++;
}
else
{
// Keep our original indentation.
textNode.Text = originalPrefix + $"{{{{ '{key}' | sqxTranslate }}}}" + originalSuffix;
isReplaced = true;
}
}, isSilent);
}
}
}
else
{
foreach (var attribute in node.Attributes.ToList())
{
if (AttributesToTranslate.Contains(attribute.Name) && !string.IsNullOrWhiteSpace(attribute.Value) && !IsPipe(attribute) && !IsTranslatedAttribute(attribute.Value))
{
var originText = $"{attribute.Name} attribute";
service.Translate(fileName, attribute.Value, originText, key =>
{
if (isSilent)
{
total++;
}
else
{
if (attribute.Name.Contains("["))
{
node.SetAttributeValue(attribute.Name, $"{{{{ '{key}' | sqxTranslate }}}}");
}
else
{
node.SetAttributeValue(attribute.Name, $"i18n:{key}");
}
isReplaced = true;
}
}, isSilent);
}
}
}
foreach (var child in node.ChildNodes)
{
Traverse(fileName, child);
}
}
private static bool IsPipe(HtmlAttribute attribute)
{
return attribute.Value.Contains("{");
}
private bool IsTranslatedAttribute(string text)
{
return text.Contains("i18n:");
}
private bool IsTranslated(string text)
{
return text.Contains("| sqxTranslate");
}
private bool IsVariable(string text)
{
return text.StartsWith("{{", StringComparison.Ordinal) && Regex.Matches(text, "\\}\\}").Count == 1;
}
private static void SaveHtml(FileInfo file, HtmlDocument html)
{
html.Save(file.FullName);
var text = File.ReadAllText(file.FullName);
// Fix the attributes, because html agility packs converts attributes without value to attributes with empty string.
// For example
// <ng-container content> becomes <ng-container content="">
text = Regex.Replace(text, " (?<Name>[^\\s]*)=\"\"", x => " " + x.Groups["Name"].Value);
File.WriteAllText(file.FullName, text);
}
}
}

64
backend/i18n/translator/Squidex.Translator/Processes/TranslateTypescript.cs

@ -0,0 +1,64 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System;
using System.IO;
using System.Text.RegularExpressions;
using Squidex.Translator.State;
namespace Squidex.Translator.Processes
{
public class TranslateTypescript
{
private readonly TranslationService service;
private readonly DirectoryInfo folder;
public TranslateTypescript(DirectoryInfo folder, TranslationService service)
{
this.folder = Frontend.GetFolder(folder);
this.service = service;
}
public void Run()
{
foreach (var (file, relativeName) in Frontend.GetTypescriptFiles(folder))
{
var content = File.ReadAllText(file.FullName);
var isReplaced = false;
content = Regex.Replace(content, "'[^']*'", match =>
{
var value = match.Value[1..^1];
string result = null;
if (value.IsPotentialMultiWordText())
{
service.Translate(relativeName, value, "Code", key =>
{
result = $"\'i18n:{key}\'";
isReplaced = true;
});
}
return result ?? $"'{value}'";
});
if (isReplaced)
{
Console.WriteLine("-----------------------------");
Console.WriteLine("FILE {0} done", relativeName);
File.WriteAllText(file.FullName, content);
}
}
}
}
}

33
backend/i18n/translator/Squidex.Translator/Program.cs

@ -0,0 +1,33 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System;
using CommandDotNet;
using CommandDotNet.FluentValidation;
namespace Squidex.Translator
{
public static class Program
{
public static int Main(string[] args)
{
try
{
var appRunner =
new AppRunner<Commands>()
.UseFluentValidation(true);
return appRunner.Run(args);
}
catch (Exception ex)
{
Console.WriteLine("ERROR: {0}", ex);
return -1;
}
}
}
}

27
backend/i18n/translator/Squidex.Translator/Squidex.Translator.csproj

@ -0,0 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="HtmlAgilityPack" Version="1.11.24" />
<PackageReference Include="CommandDotNet" Version="3.6.0" />
<PackageReference Include="CommandDotNet.FluentValidation" Version="2.0.2" />
<PackageReference Include="CommandDotNet.IoC.MicrosoftDependencyInjection" Version="2.0.1" />
<PackageReference Include="ConsoleTables" Version="2.4.1" />
<PackageReference Include="CoreTweet" Version="1.0.0.483" />
<PackageReference Include="RefactoringEssentials" Version="5.6.0" PrivateAssets="all" />
<PackageReference Include="ResXResourceReader.NetStandard" Version="1.0.1" />
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="all" />
</ItemGroup>
<PropertyGroup>
<CodeAnalysisRuleSet>..\..\..\Squidex.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<AdditionalFiles Include="..\..\..\stylecop.json" Link="stylecop.json" />
</ItemGroup>
</Project>

18
backend/i18n/translator/Squidex.Translator/State/Old/OldTranslatedText.cs

@ -0,0 +1,18 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System.Collections.Generic;
namespace Squidex.Translator.State.Old
{
public class OldTranslatedText
{
public SortedDictionary<string, string> Texts { get; set; } = new SortedDictionary<string, string>();
public SortedSet<TextOrigin> Origins { get; set; } = new SortedSet<TextOrigin>();
}
}

20
backend/i18n/translator/Squidex.Translator/State/Old/OldTranslationState.cs

@ -0,0 +1,20 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System.Collections.Generic;
namespace Squidex.Translator.State.Old
{
public class OldTranslationState
{
public SortedDictionary<string, OldTranslatedText> Texts { get; set; } = new SortedDictionary<string, OldTranslatedText>();
public HashSet<string> Ignores { get; set; } = new HashSet<string>();
public SortedDictionary<string, SortedSet<string>> Todos { get; set; } = new SortedDictionary<string, SortedSet<string>>();
}
}

16
backend/i18n/translator/Squidex.Translator/State/Old/TextOrigin.cs

@ -0,0 +1,16 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
namespace Squidex.Translator.State
{
public enum TextOrigin
{
Frontend,
BackendInfrastructure,
BackendShared
}
}

23
backend/i18n/translator/Squidex.Translator/State/TranslatedTexts.cs

@ -0,0 +1,23 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System.Collections.Generic;
namespace Squidex.Translator.State
{
public sealed class TranslatedTexts : SortedDictionary<string, string>
{
public TranslatedTexts()
{
}
public TranslatedTexts(TranslatedTexts source)
: base(source)
{
}
}
}

331
backend/i18n/translator/Squidex.Translator/State/TranslationService.cs

@ -0,0 +1,331 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Json.Serialization;
using Squidex.Translator.State.Old;
namespace Squidex.Translator.State
{
public sealed class TranslationService
{
private static readonly JsonSerializerOptions SerializerOptions = new JsonSerializerOptions
{
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
AllowTrailingCommas = true,
PropertyNameCaseInsensitive = true,
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
WriteIndented = true
};
private readonly Dictionary<string, TranslatedTexts> translations = new Dictionary<string, TranslatedTexts>();
private readonly TranslationTodos translationsTodo;
private readonly TranslationsToIgnore translationToIgnore;
private readonly DirectoryInfo sourceDirectory;
private readonly string sourceFileName;
private readonly string[] supportedLocales;
private readonly bool onlySingleWords;
private string previousPrefix;
public TranslatedTexts MainTranslations
{
get { return translations[MainLocale]; }
}
public string MainLocale
{
get { return supportedLocales[0]; }
}
public IEnumerable<string> SupportedLocales
{
get { return supportedLocales; }
}
public IEnumerable<string> NonMainSupportedLocales
{
get { return supportedLocales.Skip(1); }
}
public IReadOnlyDictionary<string, TranslatedTexts> Translations
{
get { return translations; }
}
static TranslationService()
{
SerializerOptions.Converters.Add(new JsonStringEnumConverter());
}
public TranslationService(DirectoryInfo sourceDirectory, string sourceFileName, string[] supportedLocales, bool onlySingleWords)
{
this.onlySingleWords = onlySingleWords;
this.sourceDirectory = sourceDirectory;
this.sourceFileName = sourceFileName;
this.supportedLocales = supportedLocales;
foreach (var locale in supportedLocales)
{
translations[locale] = Load<TranslatedTexts>($"_{locale}.json");
}
translationsTodo = Load<TranslationTodos>("__todos.json");
translationToIgnore = Load<TranslationsToIgnore>("__ignore.json");
}
public TranslatedTexts GetTextsWithFallback(string locale)
{
var result = new TranslatedTexts(MainTranslations);
if (translations.TryGetValue(locale, out var translated))
{
foreach (var key in result.Keys.ToList())
{
if (translated.TryGetValue(key, out var value) && !string.IsNullOrWhiteSpace(value))
{
result[key] = value;
}
}
}
return result;
}
private T Load<T>(string name) where T : new()
{
var fullName = GetFullName(name);
if (File.Exists(fullName))
{
var json = File.ReadAllText(fullName);
return JsonSerializer.Deserialize<T>(json, SerializerOptions);
}
else
{
return new T();
}
}
private void Save<T>(string name, T value) where T : new()
{
var fullName = GetFullName(name);
WriteTo(value, fullName);
}
private string GetFullName(string name)
{
return Path.Combine(sourceDirectory.FullName, "source", $"{sourceFileName}{name}");
}
public void WriteTo<T>(T value, string path) where T : new()
{
var json = JsonSerializer.Serialize(value, SerializerOptions);
if (!sourceDirectory.Exists)
{
Directory.CreateDirectory(sourceDirectory.FullName);
}
File.WriteAllText(path, json);
}
public void Migrate()
{
var oldState = Load<OldTranslationState>(".json");
foreach (var (key, value) in oldState.Texts)
{
if (value.Texts.TryGetValue("en", out var text))
{
MainTranslations[key] = text;
}
}
foreach (var (key, value) in oldState.Todos)
{
translationsTodo[key] = value;
}
Save();
}
public void Save()
{
foreach (var (locale, texts) in translations)
{
Save($"_{locale}.json", texts);
}
Save("__todos.json", translationsTodo);
Save("__ignore.json", translationToIgnore);
}
public void Translate(string fileName, string text, string originText, Action<string> handler, bool silent = false)
{
if (onlySingleWords && text.Contains(' '))
{
return;
}
if (!IsIgnored(fileName, text))
{
var (key, keyState) = MainTranslations.FirstOrDefault(x => x.Value == text);
if (string.IsNullOrWhiteSpace(key))
{
if (silent)
{
handler("DUMMY");
}
else
{
Console.WriteLine();
Console.WriteLine(">>> {0}", text);
Console.WriteLine("{1} in {0}", fileName, originText);
Console.WriteLine();
while (true)
{
Console.WriteLine("Enter key or <Enter> (USE with previous prefix), <t> (TODO), <s> (SKIP), <i> (IGNORE), <f> (IGNORE FILE)");
key = Console.ReadLine();
if (string.IsNullOrWhiteSpace(key))
{
key = $"common.{text.ToLower()}";
if (translations.TryGetValue(key, out var existing))
{
Console.WriteLine("Key is already in use with {0}", existing);
continue;
}
else
{
AddText(key, text);
handler(key);
}
break;
}
else if (key.Equals("s", StringComparison.OrdinalIgnoreCase) == true)
{
Console.WriteLine("Skipped");
}
else if (key.Equals("i", StringComparison.OrdinalIgnoreCase) == true)
{
Console.WriteLine("Ignored");
AddIgnore(fileName, text);
}
else if (key.Equals("f", StringComparison.OrdinalIgnoreCase) == true)
{
Console.WriteLine("Ignored File");
AddIgnore(fileName, "*");
}
else if (key.Equals("t", StringComparison.OrdinalIgnoreCase) == true)
{
Console.WriteLine("ToDo");
AddTodo(fileName, text);
AddIgnore(fileName, text);
}
else
{
if (!key.Contains("."))
{
if (previousPrefix != null)
{
key = $"{previousPrefix}.{key}";
}
else
{
key = $"common.{key}";
}
}
else
{
previousPrefix = string.Join('.', key.Split('.', StringSplitOptions.RemoveEmptyEntries).Skip(1));
}
var useOlder = key.EndsWith("?", StringComparison.OrdinalIgnoreCase);
var useNewer = key.EndsWith("!", StringComparison.OrdinalIgnoreCase);
if (translations.TryGetValue(key, out var existing) && !useOlder && !useNewer)
{
Console.WriteLine("Key is already in use with '{0}'", existing);
continue;
}
else
{
key = key.TrimEnd('!', '?');
if (!useOlder)
{
AddText(key, text);
}
handler(key);
}
}
break;
}
}
}
else
{
handler(key);
}
Save();
}
}
private bool IsIgnored(string name, string text)
{
return translationToIgnore.TryGetValue(name, out var ignores) && (ignores.Contains(text) || ignores.Contains("*"));
}
private void AddText(string key, string text)
{
MainTranslations[key] = text;
}
private void AddIgnore(string name, string text)
{
if (!translationToIgnore.TryGetValue(name, out var ignores))
{
ignores = new SortedSet<string>();
translationToIgnore[name] = ignores;
}
ignores.Add(text);
}
private void AddTodo(string name, string text)
{
if (!translationsTodo.TryGetValue(name, out var todos))
{
todos = new SortedSet<string>();
translationsTodo[name] = todos;
}
todos.Add(text);
}
}
}

15
backend/i18n/translator/Squidex.Translator/State/TranslationTodos.cs

@ -0,0 +1,15 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System.Collections.Generic;
namespace Squidex.Translator.State
{
public sealed class TranslationTodos : SortedDictionary<string, SortedSet<string>>
{
}
}

15
backend/i18n/translator/Squidex.Translator/State/TranslationsToIgnore.cs

@ -0,0 +1,15 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System.Collections.Generic;
namespace Squidex.Translator.State
{
public sealed class TranslationsToIgnore : SortedDictionary<string, SortedSet<string>>
{
}
}

30
backend/src/Migrations/OldEvents/AppClientRenamed.cs

@ -0,0 +1,30 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschränkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using Squidex.Domain.Apps.Events;
using Squidex.Infrastructure.EventSourcing;
using Squidex.Infrastructure.Migrations;
using Squidex.Infrastructure.Reflection;
using AppClientUpdatedV2 = Squidex.Domain.Apps.Events.Apps.AppClientUpdated;
namespace Migrations.OldEvents
{
[EventType(nameof(AppClientRenamed))]
public sealed class AppClientRenamed : AppEvent, IMigrated<IEvent>
{
public string Id { get; set; }
public string Name { get; set; }
public IEvent Migrate()
{
var result = SimpleMapper.Map(this, new AppClientUpdatedV2());
return result;
}
}
}

28
backend/src/Squidex.Domain.Apps.Core.Model/Apps/AppClient.cs

@ -17,31 +17,35 @@ namespace Squidex.Domain.Apps.Core.Apps
public string Secret { get; }
public AppClient(string name, string secret, string role)
public long ApiCallsLimit { get; }
public long ApiTrafficLimit { get; }
public bool AllowAnonymous { get; }
public AppClient(string name, string secret, string role, long apiCallsLimit = 0, long apiTrafficLimit = 0, bool allowAnonymous = false)
: base(name)
{
Guard.NotNullOrEmpty(secret, nameof(secret));
Guard.NotNullOrEmpty(role, nameof(role));
Guard.GreaterEquals(apiCallsLimit, 0, nameof(apiCallsLimit));
Guard.GreaterEquals(apiTrafficLimit, 0, nameof(apiTrafficLimit));
Secret = secret;
Role = role;
Secret = secret;
}
ApiCallsLimit = apiCallsLimit;
[Pure]
public AppClient Update(string newRole)
{
Guard.NotNullOrEmpty(newRole, nameof(newRole));
ApiTrafficLimit = apiTrafficLimit;
return new AppClient(Name, Secret, newRole);
AllowAnonymous = allowAnonymous;
}
[Pure]
public AppClient Rename(string newName)
public AppClient Update(string? name, string? role, long? apiCallsLimit, long? apiTrafficLimit, bool? allowAnonymous)
{
Guard.NotNullOrEmpty(newName, nameof(newName));
return new AppClient(newName, Secret, Role);
return new AppClient(name.Or(Name), Secret, role.Or(Role), apiCallsLimit ?? ApiCallsLimit, apiTrafficLimit ?? ApiTrafficLimit, allowAnonymous ?? AllowAnonymous);
}
}
}

19
backend/src/Squidex.Domain.Apps.Core.Model/Apps/AppClients.cs

@ -53,11 +53,11 @@ namespace Squidex.Domain.Apps.Core.Apps
throw new ArgumentException("Id already exists.", nameof(id));
}
return With<AppClients>(id, new AppClient(id, secret, Role.Editor));
return Add(id, new AppClient(id, secret, Role.Editor));
}
[Pure]
public AppClients Rename(string id, string newName)
public AppClients Update(string id, string? name = null, string? role = null, long? apiCallsLimit = null, long? apiTrafficLimit = null, bool? allowAnonymous = false)
{
Guard.NotNullOrEmpty(id, nameof(id));
@ -66,20 +66,7 @@ namespace Squidex.Domain.Apps.Core.Apps
return this;
}
return With<AppClients>(id, client.Rename(newName));
}
[Pure]
public AppClients Update(string id, string role)
{
Guard.NotNullOrEmpty(id, nameof(id));
if (!TryGetValue(id, out var client))
{
return this;
}
return With<AppClients>(id, client.Update(role));
return With<AppClients>(id, client.Update(name, role, apiCallsLimit, apiTrafficLimit, allowAnonymous));
}
}
}

4
backend/src/Squidex.Domain.Apps.Core.Model/Apps/AppPattern.cs

@ -28,9 +28,9 @@ namespace Squidex.Domain.Apps.Core.Apps
}
[Pure]
public AppPattern Update(string newName, string newPattern, string? newMessage)
public AppPattern Update(string? name, string? pattern, string? message)
{
return new AppPattern(newName, newPattern, newMessage);
return new AppPattern(name.Or(Name), pattern.Or(Pattern), message);
}
}
}

5
backend/src/Squidex.Domain.Apps.Core.Model/Apps/AppPatterns.cs

@ -40,11 +40,8 @@ namespace Squidex.Domain.Apps.Core.Apps
}
[Pure]
public AppPatterns Update(DomainId id, string name, string pattern, string? message = null)
public AppPatterns Update(DomainId id, string? name = null, string? pattern = null, string? message = null)
{
Guard.NotNullOrEmpty(name, nameof(name));
Guard.NotNullOrEmpty(pattern, nameof(pattern));
if (!TryGetValue(id, out var appPattern))
{
return this;

11
backend/src/Squidex.Domain.Apps.Core.Model/Apps/Json/AppClientsConverter.cs

@ -7,7 +7,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Squidex.Infrastructure.Json.Newtonsoft;
@ -17,11 +16,11 @@ namespace Squidex.Domain.Apps.Core.Apps.Json
{
protected override void WriteValue(JsonWriter writer, AppClients value, JsonSerializer serializer)
{
var json = new Dictionary<string, JsonAppClient>(value.Count);
var json = new Dictionary<string, AppClient>(value.Count);
foreach (var (key, appClient) in value)
foreach (var (key, client) in value)
{
json.Add(key, new JsonAppClient(appClient));
json.Add(key, client);
}
serializer.Serialize(writer, json);
@ -29,9 +28,9 @@ namespace Squidex.Domain.Apps.Core.Apps.Json
protected override AppClients ReadValue(JsonReader reader, Type objectType, JsonSerializer serializer)
{
var json = serializer.Deserialize<Dictionary<string, JsonAppClient>>(reader)!;
var json = serializer.Deserialize<Dictionary<string, AppClient>>(reader)!;
return new AppClients(json.ToDictionary(x => x.Key, x => x.Value.ToClient()));
return new AppClients(json);
}
}
}

38
backend/src/Squidex.Domain.Apps.Core.Model/Apps/Json/JsonAppClient.cs

@ -1,38 +0,0 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschränkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using Newtonsoft.Json;
using Squidex.Infrastructure.Reflection;
namespace Squidex.Domain.Apps.Core.Apps.Json
{
public class JsonAppClient
{
[JsonProperty]
public string Name { get; set; }
[JsonProperty]
public string Secret { get; set; }
[JsonProperty]
public string Role { get; set; }
public JsonAppClient()
{
}
public JsonAppClient(AppClient client)
{
SimpleMapper.Map(client, this);
}
public AppClient ToClient()
{
return new AppClient(Name, Secret, Role);
}
}
}

4
backend/src/Squidex.Domain.Apps.Core.Model/Comments/Comment.cs

@ -30,13 +30,9 @@ namespace Squidex.Domain.Apps.Core.Comments
Guard.NotNull(text, nameof(text));
Id = id;
Text = text;
Time = time;
User = user;
Url = url;
}
}

2
backend/src/Squidex.Domain.Apps.Core.Model/Contents/Workflow.cs

@ -35,7 +35,7 @@ namespace Squidex.Domain.Apps.Core.Contents
IReadOnlyDictionary<Status, WorkflowStep>? steps,
IReadOnlyList<DomainId>? schemaIds = null,
string? name = null)
: base(name ?? DefaultName)
: base(name.Or(DefaultName))
{
Initial = initial;

2
backend/src/Squidex.Domain.Apps.Core.Model/Schemas/FieldNames.cs

@ -15,7 +15,7 @@ namespace Squidex.Domain.Apps.Core.Schemas
{
private static readonly List<string> EmptyNames = new List<string>();
public static readonly FieldNames Empty = new FieldNames(new List<string>());
public static readonly FieldNames Empty = new FieldNames(EmptyNames);
public FieldNames(params string[] fields)
: base(fields?.ToList() ?? EmptyNames)

43
backend/src/Squidex.Domain.Apps.Core.Model/Schemas/FieldRule.cs

@ -0,0 +1,43 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Core.Schemas
{
[Equals(DoNotAddEqualityOperators = true)]
public sealed class FieldRule
{
public FieldRuleAction Action { get; }
public string Field { get; }
public string? Condition { get; }
public FieldRule(FieldRuleAction action, string field, string? condition)
{
Guard.Enum(action, nameof(action));
Guard.NotNullOrEmpty(field, nameof(field));
Action = action;
Field = field;
Condition = condition;
}
public static FieldRule Disable(string field, string? condition = null)
{
return new FieldRule(FieldRuleAction.Disable, field, condition);
}
public static FieldRule Hide(string field, string? condition = null)
{
return new FieldRule(FieldRuleAction.Hide, field, condition);
}
}
}

16
backend/src/Squidex.Domain.Apps.Core.Model/Schemas/FieldRuleAction.cs

@ -0,0 +1,16 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
namespace Squidex.Domain.Apps.Core.Schemas
{
public enum FieldRuleAction
{
Disable,
Hide,
Require
}
}

30
backend/src/Squidex.Domain.Apps.Core.Model/Schemas/FieldRules.cs

@ -0,0 +1,30 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
namespace Squidex.Domain.Apps.Core.Schemas
{
public sealed class FieldRules : ReadOnlyCollection<FieldRule>
{
private static readonly List<FieldRule> EmptyRules = new List<FieldRule>();
public static readonly FieldRules Empty = new FieldRules(EmptyRules);
public FieldRules(params FieldRule[] fields)
: base(fields?.ToList() ?? EmptyRules)
{
}
public FieldRules(IList<FieldRule> list)
: base(list ?? EmptyRules)
{
}
}
}

8
backend/src/Squidex.Domain.Apps.Core.Model/Schemas/Json/JsonSchemaModel.cs

@ -42,6 +42,9 @@ namespace Squidex.Domain.Apps.Core.Schemas.Json
[JsonProperty]
public FieldNames? FieldsInReferences { get; set; }
[JsonProperty]
public FieldRules? FieldRules { get; set; }
[JsonProperty]
public JsonFieldModel[] Fields { get; set; }
@ -118,6 +121,11 @@ namespace Squidex.Domain.Apps.Core.Schemas.Json
schema = schema.SetFieldsInReferences(FieldsInReferences);
}
if (FieldRules?.Count > 0)
{
schema = schema.SetFieldRules(FieldRules);
}
if (PreviewUrls?.Count > 0)
{
schema = schema.SetPreviewUrls(PreviewUrls);

28
backend/src/Squidex.Domain.Apps.Core.Model/Schemas/Schema.cs

@ -21,6 +21,7 @@ namespace Squidex.Domain.Apps.Core.Schemas
private string category;
private FieldNames fieldsInLists = FieldNames.Empty;
private FieldNames fieldsInReferences = FieldNames.Empty;
private FieldRules fieldRules = FieldRules.Empty;
private FieldCollection<RootField> fields = FieldCollection<RootField>.Empty;
private IReadOnlyDictionary<string, string> previewUrls = EmptyPreviewUrls;
private SchemaScripts scripts = SchemaScripts.Empty;
@ -72,6 +73,11 @@ namespace Squidex.Domain.Apps.Core.Schemas
get { return fields; }
}
public FieldRules FieldRules
{
get { return fieldRules; }
}
public FieldNames FieldsInLists
{
get { return fieldsInLists; }
@ -192,6 +198,28 @@ namespace Squidex.Domain.Apps.Core.Schemas
return SetFieldsInReferences(new FieldNames(names));
}
[Pure]
public Schema SetFieldRules(FieldRules rules)
{
rules ??= FieldRules.Empty;
if (fieldRules.SetEquals(rules))
{
return this;
}
return Clone(clone =>
{
clone.fieldRules = rules;
});
}
[Pure]
public Schema SetFieldRules(params FieldRule[] rules)
{
return SetFieldRules(new FieldRules(rules));
}
[Pure]
public Schema Publish()
{

7
backend/src/Squidex.Domain.Apps.Core.Model/Schemas/SchemaExtensions.cs

@ -9,6 +9,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using Squidex.Infrastructure;
using Squidex.Text;
namespace Squidex.Domain.Apps.Core.Schemas
{
@ -41,7 +42,7 @@ namespace Squidex.Domain.Apps.Core.Schemas
public static string DisplayName(this IField field)
{
return field.RawProperties.Label.WithFallback(field.TypeName());
return field.RawProperties.Label.Or(field.TypeName());
}
public static string TypeName(this Schema schema)
@ -51,12 +52,12 @@ namespace Squidex.Domain.Apps.Core.Schemas
public static string DisplayName(this Schema schema)
{
return schema.Properties.Label.WithFallback(schema.TypeName());
return schema.Properties.Label.Or(schema.TypeName());
}
public static string DisplayNameUnchanged(this Schema schema)
{
return schema.Properties.Label.WithFallback(schema.Name);
return schema.Properties.Label.Or(schema.Name);
}
public static DomainId SingleId(this ReferencesFieldProperties properties)

5
backend/src/Squidex.Domain.Apps.Core.Operations/EventSynchronization/SchemaSynchronizer.cs

@ -80,6 +80,11 @@ namespace Squidex.Domain.Apps.Core.EventSynchronization
{
yield return E(new SchemaUIFieldsConfigured { FieldsInReferences = target.FieldsInReferences });
}
if (!source.FieldRules.SetEquals(target.FieldRules))
{
yield return E(new SchemaFieldRulesConfigured { FieldRules = target.FieldRules });
}
}
}

1
backend/src/Squidex.Domain.Apps.Core.Operations/GenerateEdmSchema/EdmSchemaExtensions.cs

@ -8,6 +8,7 @@
using Microsoft.OData.Edm;
using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Infrastructure;
using Squidex.Text;
namespace Squidex.Domain.Apps.Core.GenerateEdmSchema
{

2
backend/src/Squidex.Domain.Apps.Core.Operations/GenerateEdmSchema/EdmTypeVisitor.cs

@ -7,7 +7,7 @@
using Microsoft.OData.Edm;
using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Infrastructure;
using Squidex.Text;
namespace Squidex.Domain.Apps.Core.GenerateEdmSchema
{

3
backend/src/Squidex.Domain.Apps.Core.Operations/GenerateJsonSchema/ContentSchemaBuilder.cs

@ -18,7 +18,7 @@ namespace Squidex.Domain.Apps.Core.GenerateJsonSchema
Guard.NotNull(schema, nameof(schema));
Guard.NotNull(dataSchema, nameof(dataSchema));
var schemaName = schema.Properties.Label.WithFallback(schema.Name);
var schemaName = schema.Properties.Label.Or(schema.Name);
var contentSchema = new JsonSchema
{
@ -32,6 +32,7 @@ namespace Squidex.Domain.Apps.Core.GenerateJsonSchema
["createdBy"] = SchemaBuilder.StringProperty($"The user that has created the {schemaName} content.", true),
["lastModified"] = SchemaBuilder.DateTimeProperty($"The date and time when the {schemaName} content has been modified last.", true),
["lastModifiedBy"] = SchemaBuilder.StringProperty($"The user that has updated the {schemaName} content last.", true),
["newStatus"] = SchemaBuilder.StringProperty($"The new status of the content.", true),
["status"] = SchemaBuilder.StringProperty($"The status of the content.", true)
},
Type = JsonObjectType.Object

3
backend/src/Squidex.Domain.Apps.Core.Operations/GenerateJsonSchema/JsonSchemaExtensions.cs

@ -8,6 +8,7 @@
using NJsonSchema;
using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Infrastructure;
using Squidex.Text;
namespace Squidex.Domain.Apps.Core.GenerateJsonSchema
{
@ -69,7 +70,7 @@ namespace Squidex.Domain.Apps.Core.GenerateJsonSchema
jsonProperty.Description = field.Name;
}
jsonProperty.IsRequired = field.RawProperties.IsRequired;
jsonProperty.SetRequired(field.RawProperties.IsRequired);
return jsonProperty;
}

8
backend/src/Squidex.Domain.Apps.Core.Operations/GenerateJsonSchema/JsonTypeVisitor.cs

@ -69,20 +69,16 @@ namespace Squidex.Domain.Apps.Core.GenerateJsonSchema
geolocationSchema.Properties.Add("latitude", new JsonSchemaProperty
{
Type = JsonObjectType.Number,
IsNullableRaw = false,
IsRequired = true,
Maximum = 90,
Minimum = -90
});
}.SetRequired(true));
geolocationSchema.Properties.Add("longitude", new JsonSchemaProperty
{
Type = JsonObjectType.Number,
IsNullableRaw = false,
IsRequired = true,
Maximum = 180,
Minimum = -180
});
}.SetRequired(true));
var reference = schemaResolver("GeolocationDto", geolocationSchema);

22
backend/src/Squidex.Domain.Apps.Core.Operations/GenerateJsonSchema/SchemaBuilder.cs

@ -41,14 +41,14 @@ namespace Squidex.Domain.Apps.Core.GenerateJsonSchema
return Enrich(new JsonSchemaProperty { Type = JsonObjectType.Number }, description, isRequired);
}
public static JsonSchemaProperty ObjectProperty(JsonSchema item, string? description = null, bool isRequired = false)
public static JsonSchemaProperty StringProperty(string? description = null, bool isRequired = false)
{
return Enrich(new JsonSchemaProperty { Type = JsonObjectType.Object, Reference = item }, description, isRequired);
return Enrich(new JsonSchemaProperty { Type = JsonObjectType.String }, description, isRequired);
}
public static JsonSchemaProperty StringProperty(string? description = null, bool isRequired = false)
public static JsonSchemaProperty ObjectProperty(JsonSchema reference, string? description = null, bool isRequired = false)
{
return Enrich(new JsonSchemaProperty { Type = JsonObjectType.String }, description, isRequired);
return Enrich(new JsonSchemaProperty { Reference = reference }, description, isRequired);
}
public static JsonSchemaProperty JsonProperty(string? description = null, bool isRequired = false)
@ -64,16 +64,12 @@ namespace Squidex.Domain.Apps.Core.GenerateJsonSchema
return property;
}
public static void SetRequired(this JsonSchemaProperty property, bool isRequired)
public static JsonSchemaProperty SetRequired(this JsonSchemaProperty property, bool isRequired)
{
if (isRequired)
{
property.IsRequired = true;
}
else
{
property.IsNullableRaw = true;
}
property.IsRequired = isRequired;
property.IsNullableRaw = !isRequired;
return property;
}
}
}

1
backend/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleEventFormatter.cs

@ -18,6 +18,7 @@ using Squidex.Domain.Apps.Core.Scripting;
using Squidex.Domain.Apps.Core.Templates;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Json;
using Squidex.Text;
using ValueTaskSupplement;
namespace Squidex.Domain.Apps.Core.HandleRules

2
backend/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleRegistry.cs

@ -12,8 +12,8 @@ using System.Linq;
using System.Reflection;
using Squidex.Domain.Apps.Core.Rules;
using Squidex.Domain.Apps.Core.Rules.EnrichedEvents;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Reflection;
using Squidex.Text;
#pragma warning disable RECS0033 // Convert 'if' to '||' expression

35
backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/ContentWrapper/ContentDataObject.cs

@ -6,9 +6,11 @@
// ==========================================================================
using System.Collections.Generic;
using System.Linq;
using Jint;
using Jint.Native;
using Jint.Native.Object;
using Jint.Runtime;
using Jint.Runtime.Descriptors;
using Squidex.Domain.Apps.Core.Contents;
using Squidex.Infrastructure;
@ -24,11 +26,11 @@ namespace Squidex.Domain.Apps.Core.Scripting.ContentWrapper
private Dictionary<string, PropertyDescriptor> fieldProperties;
private bool isChanged;
public override bool Extensible => true;
public ContentDataObject(Engine engine, NamedContentData contentData)
: base(engine)
{
Extensible = true;
this.contentData = contentData;
}
@ -68,23 +70,27 @@ namespace Squidex.Domain.Apps.Core.Scripting.ContentWrapper
return isChanged;
}
public override void RemoveOwnProperty(string propertyName)
public override void RemoveOwnProperty(JsValue property)
{
if (fieldsToDelete == null)
{
fieldsToDelete = new HashSet<string>();
}
var propertyName = property.AsString();
fieldsToDelete.Add(propertyName);
fieldProperties?.Remove(propertyName);
MarkChanged();
}
public override bool DefineOwnProperty(string propertyName, PropertyDescriptor desc, bool throwOnError)
public override bool DefineOwnProperty(JsValue property, PropertyDescriptor desc)
{
EnsurePropertiesInitialized();
var propertyName = property.AsString();
if (!fieldProperties.ContainsKey(propertyName))
{
fieldProperties[propertyName] = new ContentDataProperty(this) { Value = desc.Value };
@ -93,25 +99,38 @@ namespace Squidex.Domain.Apps.Core.Scripting.ContentWrapper
return true;
}
public override void Put(string propertyName, JsValue value, bool throwOnError)
public override bool Set(JsValue property, JsValue value, JsValue receiver)
{
EnsurePropertiesInitialized();
var propertyName = property.AsString();
fieldProperties.GetOrAdd(propertyName, this, (k, c) => new ContentDataProperty(c)).Value = value;
return true;
}
public override PropertyDescriptor GetOwnProperty(string propertyName)
public override PropertyDescriptor GetOwnProperty(JsValue property)
{
EnsurePropertiesInitialized();
var propertyName = property.AsString();
return fieldProperties.GetOrAdd(propertyName, this, (k, c) => new ContentDataProperty(c, new ContentFieldObject(c, new ContentFieldData(), false)));
}
public override IEnumerable<KeyValuePair<string, PropertyDescriptor>> GetOwnProperties()
public override IEnumerable<KeyValuePair<JsValue, PropertyDescriptor>> GetOwnProperties()
{
EnsurePropertiesInitialized();
return fieldProperties.Select(x => new KeyValuePair<JsValue, PropertyDescriptor>(x.Key, x.Value));
}
public override List<JsValue> GetOwnPropertyKeys(Types types = Types.String | Types.Symbol)
{
EnsurePropertiesInitialized();
return fieldProperties;
return fieldProperties.Keys.Select(x => (JsValue)x).ToList();
}
private void EnsurePropertiesInitialized()

2
backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/ContentWrapper/ContentDataProperty.cs

@ -38,7 +38,7 @@ namespace Squidex.Domain.Apps.Core.Scripting.ContentWrapper
foreach (var (key, propertyDescriptor) in obj.GetOwnProperties())
{
contentField.Put(key, propertyDescriptor.Value, true);
contentField.Set(key, propertyDescriptor.Value);
}
this.value = contentField;

45
backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/ContentWrapper/ContentFieldObject.cs

@ -6,7 +6,11 @@
// ==========================================================================
using System.Collections.Generic;
using System.Linq;
using Jint;
using Jint.Native;
using Jint.Native.Object;
using Jint.Runtime;
using Jint.Runtime.Descriptors;
using Squidex.Domain.Apps.Core.Contents;
using Squidex.Infrastructure;
@ -19,7 +23,7 @@ namespace Squidex.Domain.Apps.Core.Scripting.ContentWrapper
{
private readonly ContentDataObject contentData;
private readonly ContentFieldData? fieldData;
private HashSet<string> valuesToDelete;
private HashSet<string>? valuesToDelete;
private Dictionary<string, PropertyDescriptor> valueProperties;
private bool isChanged;
@ -28,12 +32,13 @@ namespace Squidex.Domain.Apps.Core.Scripting.ContentWrapper
get { return fieldData; }
}
public override bool Extensible => true;
public ContentFieldObject(ContentDataObject contentData, ContentFieldData? fieldData, bool isNew)
: base(contentData.Engine)
{
Extensible = true;
this.contentData = contentData;
this.fieldData = fieldData;
if (isNew)
@ -80,8 +85,10 @@ namespace Squidex.Domain.Apps.Core.Scripting.ContentWrapper
return isChanged;
}
public override void RemoveOwnProperty(string propertyName)
public override void RemoveOwnProperty(JsValue property)
{
var propertyName = property.AsString();
valuesToDelete ??= new HashSet<string>();
valuesToDelete.Add(propertyName);
@ -90,10 +97,23 @@ namespace Squidex.Domain.Apps.Core.Scripting.ContentWrapper
MarkChanged();
}
public override bool DefineOwnProperty(string propertyName, PropertyDescriptor desc, bool throwOnError)
public override bool Set(JsValue property, JsValue value, JsValue receiver)
{
EnsurePropertiesInitialized();
var propertyName = property.AsString();
valueProperties.GetOrAdd(propertyName, k => new ContentFieldProperty(this)).Value = value;
return true;
}
public override bool DefineOwnProperty(JsValue property, PropertyDescriptor desc)
{
EnsurePropertiesInitialized();
var propertyName = property.AsString();
if (!valueProperties.ContainsKey(propertyName))
{
valueProperties[propertyName] = new ContentFieldProperty(this) { Value = desc.Value };
@ -102,18 +122,27 @@ namespace Squidex.Domain.Apps.Core.Scripting.ContentWrapper
return true;
}
public override PropertyDescriptor GetOwnProperty(string propertyName)
public override PropertyDescriptor GetOwnProperty(JsValue property)
{
EnsurePropertiesInitialized();
var propertyName = property.AsString();
return valueProperties?.GetOrDefault(propertyName) ?? PropertyDescriptor.Undefined;
}
public override IEnumerable<KeyValuePair<string, PropertyDescriptor>> GetOwnProperties()
public override IEnumerable<KeyValuePair<JsValue, PropertyDescriptor>> GetOwnProperties()
{
EnsurePropertiesInitialized();
return valueProperties.Select(x => new KeyValuePair<JsValue, PropertyDescriptor>(x.Key, x.Value));
}
public override List<JsValue> GetOwnPropertyKeys(Types types = Types.String | Types.Symbol)
{
EnsurePropertiesInitialized();
return valueProperties;
return valueProperties.Keys.Select(x => (JsValue)x).ToList();
}
private void EnsurePropertiesInitialized()

6
backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/ContentWrapper/JsonMapper.cs

@ -62,6 +62,8 @@ namespace Squidex.Domain.Apps.Core.Scripting.ContentWrapper
target.FastAddProperty(key, Map(value, engine), false, true, true);
}
target.PreventExtensions();
return target;
}
@ -103,7 +105,7 @@ namespace Squidex.Domain.Apps.Core.Scripting.ContentWrapper
var result = JsonValue.Array();
for (var i = 0; i < arr.GetLength(); i++)
for (var i = 0; i < arr.Length; i++)
{
result.Add(Map(arr.Get(i.ToString())));
}
@ -119,7 +121,7 @@ namespace Squidex.Domain.Apps.Core.Scripting.ContentWrapper
foreach (var (key, propertyDescriptor) in obj.GetOwnProperties())
{
result[key] = Map(propertyDescriptor.Value);
result[key.AsString()] = Map(propertyDescriptor.Value);
}
return result;

2
backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/ExecutionContext.cs

@ -11,7 +11,7 @@ using System.Threading;
using Jint;
using Jint.Native;
using Jint.Native.Object;
using Squidex.Infrastructure;
using Squidex.Text;
namespace Squidex.Domain.Apps.Core.Scripting
{

9
backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/Extensions/HttpJintExtension.cs

@ -8,6 +8,7 @@
using System;
using System.Net.Http;
using System.Threading.Tasks;
using Jint;
using Jint.Native;
using Jint.Native.Json;
using Jint.Runtime;
@ -58,7 +59,7 @@ namespace Squidex.Domain.Apps.Core.Scripting.Extensions
var responseObject = await ParseResponse(context, response);
context.Engine.ResetTimeoutTicks();
context.Engine.ResetConstraints();
callback(responseObject);
}
@ -86,9 +87,11 @@ namespace Squidex.Domain.Apps.Core.Scripting.Extensions
{
var value = TypeConverter.ToString(property.Value);
if (!string.IsNullOrWhiteSpace(key))
var keyString = key.AsString();
if (!string.IsNullOrWhiteSpace(keyString))
{
request.Headers.TryAddWithoutValidation(key, value ?? string.Empty);
request.Headers.TryAddWithoutValidation(keyString, value ?? string.Empty);
}
}
}

2
backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/Extensions/StringJintExtension.cs

@ -8,7 +8,7 @@
using System;
using Jint;
using Jint.Native;
using Squidex.Infrastructure;
using Squidex.Text;
namespace Squidex.Domain.Apps.Core.Scripting.Extensions
{

5
backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/Extensions/StringWordsJintExtension.cs

@ -8,6 +8,7 @@
using System;
using Jint;
using Jint.Native;
using Squidex.Text;
namespace Squidex.Domain.Apps.Core.Scripting.Extensions
{
@ -17,7 +18,7 @@ namespace Squidex.Domain.Apps.Core.Scripting.Extensions
{
try
{
return TextHelpers.WordCount(text);
return text.WordCount();
}
catch
{
@ -29,7 +30,7 @@ namespace Squidex.Domain.Apps.Core.Scripting.Extensions
{
try
{
return TextHelpers.CharacterCount(text);
return text.CharacterCount();
}
catch
{

10
backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/Internal/Parser.cs

@ -30,20 +30,20 @@ namespace Squidex.Domain.Apps.Core.Scripting.Internal
this.memoryCache = memoryCache;
}
public Program Parse(string script)
public Script Parse(string script)
{
var key = Key(script);
if (!memoryCache.TryGetValue<Program>(key, out var program))
if (!memoryCache.TryGetValue<Script>(key, out var compiledScript))
{
var parser = new JavaScriptParser(script, DefaultParserOptions);
program = parser.ParseProgram();
compiledScript = parser.ParseScript();
memoryCache.Set(key, program, Expiration);
memoryCache.Set(key, compiledScript, Expiration);
}
return program;
return compiledScript;
}
private static string Key(string script)

9
backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/JintScriptEngine.cs

@ -1,4 +1,4 @@
// ==========================================================================
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschränkt)
@ -20,6 +20,7 @@ using Squidex.Domain.Apps.Core.Scripting.ContentWrapper;
using Squidex.Domain.Apps.Core.Scripting.Internal;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Json.Objects;
using Squidex.Infrastructure.Translations;
using Squidex.Infrastructure.Validation;
namespace Squidex.Domain.Apps.Core.Scripting
@ -179,15 +180,15 @@ namespace Squidex.Domain.Apps.Core.Scripting
}
catch (ArgumentException ex)
{
throw new ValidationException($"Failed to execute script with javascript syntax error: {ex.Message}", new ValidationError(ex.Message));
throw new ValidationException(T.Get("common.jsParseError", new { error = ex.Message }));
}
catch (JavaScriptException ex)
{
throw new ValidationException($"Failed to execute script with javascript error: {ex.Message}", new ValidationError(ex.Message));
throw new ValidationException(T.Get("common.jsError", new { error = ex.Message }));
}
catch (ParserException ex)
{
throw new ValidationException($"Failed to execute script with javascript error: {ex.Message}", new ValidationError(ex.Message));
throw new ValidationException(T.Get("common.jsError", new { error = ex.Message }));
}
}
}

9
backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/ScriptOperations.cs

@ -1,4 +1,4 @@
// ==========================================================================
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
@ -7,6 +7,7 @@
using Jint;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Translations;
using Squidex.Infrastructure.Validation;
namespace Squidex.Domain.Apps.Core.Scripting
@ -17,16 +18,16 @@ namespace Squidex.Domain.Apps.Core.Scripting
private static readonly MessageDelegate Disallow = message =>
{
message = !string.IsNullOrWhiteSpace(message) ? message : "Not allowed";
message = !string.IsNullOrWhiteSpace(message) ? message : T.Get("common.jsNotAlloweed");
throw new DomainForbiddenException(message);
};
private static readonly MessageDelegate Reject = message =>
{
var errors = !string.IsNullOrWhiteSpace(message) ? new[] { new ValidationError(message) } : null;
message = !string.IsNullOrWhiteSpace(message) ? message : T.Get("common.jsRejected");
throw new ValidationException("Script rejected the operation.", errors);
throw new ValidationException(message);
};
public static Engine AddDisallow(this Engine engine)

2
backend/src/Squidex.Domain.Apps.Core.Operations/Squidex.Domain.Apps.Core.Operations.csproj

@ -18,7 +18,7 @@
<ItemGroup>
<PackageReference Include="Fluid.Core.Squidex" Version="1.0.0-beta" />
<PackageReference Include="HtmlAgilityPack" Version="1.11.24" />
<PackageReference Include="Jint" Version="3.0.0-beta-1580" />
<PackageReference Include="Jint" Version="3.0.0-beta-1828" />
<PackageReference Include="Markdig" Version="0.20.0" />
<PackageReference Include="Microsoft.Extensions.Http" Version="3.1.4" />
<PackageReference Include="Microsoft.OData.Core" Version="7.6.4" />

2
backend/src/Squidex.Domain.Apps.Core.Operations/Templates/Extensions/StringFluidExtension.cs

@ -8,7 +8,7 @@
using Fluid;
using Fluid.Values;
using Newtonsoft.Json;
using Squidex.Infrastructure;
using Squidex.Text;
namespace Squidex.Domain.Apps.Core.Templates.Extensions
{

5
backend/src/Squidex.Domain.Apps.Core.Operations/Templates/Extensions/StringWordsFluidExtension.cs

@ -7,6 +7,7 @@
using Fluid;
using Fluid.Values;
using Squidex.Text;
namespace Squidex.Domain.Apps.Core.Templates.Extensions
{
@ -14,12 +15,12 @@ namespace Squidex.Domain.Apps.Core.Templates.Extensions
{
private static readonly FilterDelegate WordCount = (input, arguments, context) =>
{
return FluidValue.Create(TextHelpers.WordCount(input.ToStringValue()));
return FluidValue.Create(input.ToStringValue().WordCount());
};
private static readonly FilterDelegate CharacterCount = (input, arguments, context) =>
{
return FluidValue.Create(TextHelpers.CharacterCount(input.ToStringValue()));
return FluidValue.Create(input.ToStringValue().CharacterCount());
};
public void RegisterGlobalTypes(IMemberAccessStrategy memberAccessStrategy)

4
backend/src/Squidex.Domain.Apps.Core.Operations/Templates/TemplateParseException.cs

@ -18,8 +18,8 @@ namespace Squidex.Domain.Apps.Core.Templates
{
public IReadOnlyList<string> Errors { get; }
public TemplateParseException(string template, IEnumerable<string> errors)
: base(BuildErrorMessage(errors, template))
public TemplateParseException(string template, IEnumerable<string> errors, Exception? inner = null)
: base(BuildErrorMessage(errors, template), inner)
{
Errors = errors.ToList();
}

40
backend/src/Squidex.Domain.Apps.Core.Operations/TextHelpers.cs

@ -93,45 +93,5 @@ namespace Squidex.Domain.Apps.Core
WriteTextTo(child, sb);
}
}
public static int CharacterCount(string text)
{
var characterCount = 0;
for (int i = 0; i < text.Length; i++)
{
if (char.IsLetter(text[i]))
{
characterCount++;
}
}
return characterCount;
}
public static int WordCount(string text)
{
var numWords = 0;
for (int i = 1; i < text.Length; i++)
{
if (char.IsWhiteSpace(text[i - 1]))
{
var character = text[i];
if (char.IsLetterOrDigit(character) || char.IsPunctuation(character))
{
numWords++;
}
}
}
if (text.Length > 2)
{
numWords++;
}
return numWords;
}
}
}

31
backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/JsonValueConverter.cs

@ -1,4 +1,4 @@
// ==========================================================================
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschränkt)
@ -10,6 +10,7 @@ using System.Collections.Generic;
using NodaTime.Text;
using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Infrastructure.Json.Objects;
using Squidex.Infrastructure.Translations;
using Squidex.Infrastructure.Validation;
namespace Squidex.Domain.Apps.Core.ValidateContent
@ -55,7 +56,7 @@ namespace Squidex.Domain.Apps.Core.ValidateContent
return (b.Value, null);
}
return (null, new JsonError("Invalid json type, expected boolean."));
return (null, new JsonError(T.Get("contents.invalidBoolean")));
}
public (object? Result, JsonError? Error) Visit(IField<NumberFieldProperties> field)
@ -65,7 +66,7 @@ namespace Squidex.Domain.Apps.Core.ValidateContent
return (n.Value, null);
}
return (null, new JsonError("Invalid json type, expected number."));
return (null, new JsonError(T.Get("contents.invalidNumber")));
}
public (object? Result, JsonError? Error) Visit(IField<StringFieldProperties> field)
@ -75,7 +76,7 @@ namespace Squidex.Domain.Apps.Core.ValidateContent
return (s.Value, null);
}
return (null, new JsonError("Invalid json type, expected string."));
return (null, new JsonError(T.Get("contents.invalidString")));
}
public (object? Result, JsonError? Error) Visit(IField<UIFieldProperties> field)
@ -97,7 +98,7 @@ namespace Squidex.Domain.Apps.Core.ValidateContent
return (parseResult.Value, null);
}
return (null, new JsonError("Invalid json type, expected string."));
return (null, new JsonError(T.Get("contents.invalidString")));
}
public (object? Result, JsonError? Error) Visit(IField<GeolocationFieldProperties> field)
@ -109,7 +110,7 @@ namespace Squidex.Domain.Apps.Core.ValidateContent
if (!string.Equals(propertyName, "latitude", StringComparison.OrdinalIgnoreCase) &&
!string.Equals(propertyName, "longitude", StringComparison.OrdinalIgnoreCase))
{
return (null, new JsonError("Geolocation can only have latitude and longitude property."));
return (null, new JsonError(T.Get("contents.invalidGeolocationMoreProperties")));
}
}
@ -119,12 +120,12 @@ namespace Squidex.Domain.Apps.Core.ValidateContent
if (!lat.IsBetween(-90, 90))
{
return (null, new JsonError("Latitude must be between -90 and 90."));
return (null, new JsonError(T.Get("contents.invalidGeolocationLatitude")));
}
}
else
{
return (null, new JsonError("Invalid json type, expected latitude/longitude object."));
return (null, new JsonError(T.Get("contents.invalidGeolocation")));
}
if (geolocation.TryGetValue("longitude", out var lonValue) && lonValue is JsonNumber lonNumber)
@ -133,18 +134,18 @@ namespace Squidex.Domain.Apps.Core.ValidateContent
if (!lon.IsBetween(-180, 180))
{
return (null, new JsonError("Longitude must be between -180 and 180."));
return (null, new JsonError(T.Get("contents.invalidGeolocationLongitude")));
}
}
else
{
return (null, new JsonError("Invalid json type, expected latitude/longitude object."));
return (null, new JsonError(T.Get("contents.invalidGeolocation")));
}
return (value, null);
}
return (null, new JsonError("Invalid json type, expected latitude/longitude object."));
return (null, new JsonError(T.Get("contents.invalidGeolocation")));
}
public (object? Result, JsonError? Error) Visit(IField<JsonFieldProperties> field)
@ -170,14 +171,14 @@ namespace Squidex.Domain.Apps.Core.ValidateContent
}
else
{
return (null, new JsonError("Invalid json type, expected array of strings."));
return (null, new JsonError(T.Get("contents.invalidArrayOfStrings")));
}
}
return (result, null);
}
return (null, new JsonError("Invalid json type, expected array of strings."));
return (null, new JsonError(T.Get("contents.invalidArrayOfStrings")));
}
private (object? Result, JsonError? Error) ConvertToObjectList()
@ -194,14 +195,14 @@ namespace Squidex.Domain.Apps.Core.ValidateContent
}
else
{
return (null, new JsonError("Invalid json type, expected array of objects."));
return (null, new JsonError(T.Get("contents.invalidArrayOfObjects")));
}
}
return (result, null);
}
return (null, new JsonError("Invalid json type, expected array of objects."));
return (null, new JsonError(T.Get("contents.invalidArrayOfObjects")));
}
}
}

15
backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/AllowedValuesValidator.cs

@ -9,19 +9,20 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Translations;
namespace Squidex.Domain.Apps.Core.ValidateContent.Validators
{
public sealed class AllowedValuesValidator<T> : IValidator
public sealed class AllowedValuesValidator<TValue> : IValidator
{
private readonly IEnumerable<T> allowedValues;
private readonly IEnumerable<TValue> allowedValues;
public AllowedValuesValidator(params T[] allowedValues)
: this((IEnumerable<T>)allowedValues)
public AllowedValuesValidator(params TValue[] allowedValues)
: this((IEnumerable<TValue>)allowedValues)
{
}
public AllowedValuesValidator(IEnumerable<T> allowedValues)
public AllowedValuesValidator(IEnumerable<TValue> allowedValues)
{
Guard.NotNull(allowedValues, nameof(allowedValues));
@ -30,9 +31,9 @@ namespace Squidex.Domain.Apps.Core.ValidateContent.Validators
public Task ValidateAsync(object? value, ValidationContext context, AddError addError)
{
if (value != null && value is T typedValue && !allowedValues.Contains(typedValue))
if (value != null && value is TValue typedValue && !allowedValues.Contains(typedValue))
{
addError(context.Path, "Not an allowed value.");
addError(context.Path, T.Get("contents.validation.notAllowed"));
}
return Task.CompletedTask;

23
backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/AssetsValidator.cs

@ -1,4 +1,4 @@
// ==========================================================================
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschränkt)
@ -12,6 +12,7 @@ using System.Threading.Tasks;
using Squidex.Domain.Apps.Core.Assets;
using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Translations;
namespace Squidex.Domain.Apps.Core.ValidateContent.Validators
{
@ -54,32 +55,32 @@ namespace Squidex.Domain.Apps.Core.ValidateContent.Validators
if (asset == null)
{
addError(path, $"Id '{assetId}' not found.");
addError(path, T.Get("contents.validation.assetNotFound", new { id = assetId }));
continue;
}
if (properties.MinSize.HasValue && asset.FileSize < properties.MinSize)
{
addError(path, $"'{asset.FileSize.ToReadableSize()}' less than minimum of '{properties.MinSize.Value.ToReadableSize()}'.");
addError(path, T.Get("contents.validation.minimumSize", new { size = asset.FileSize.ToReadableSize(), min = properties.MinSize.Value.ToReadableSize() }));
}
if (properties.MaxSize.HasValue && asset.FileSize > properties.MaxSize)
{
addError(path, $"'{asset.FileSize.ToReadableSize()}' greater than maximum of '{properties.MaxSize.Value.ToReadableSize()}'.");
addError(path, T.Get("contents.validation.maximumSize", new { size = asset.FileSize.ToReadableSize(), max = properties.MaxSize.Value.ToReadableSize() }));
}
if (properties.AllowedExtensions != null &&
properties.AllowedExtensions.Count > 0 &&
!properties.AllowedExtensions.Any(x => asset.FileName.EndsWith("." + x, StringComparison.OrdinalIgnoreCase)))
{
addError(path, "Invalid file extension.");
addError(path, T.Get("contents.validation.extension"));
}
if (asset.Type != AssetType.Image)
{
if (properties.MustBeImage)
{
addError(path, "Not an image.");
addError(path, T.Get("contents.validation.image"));
}
continue;
@ -97,22 +98,22 @@ namespace Squidex.Domain.Apps.Core.ValidateContent.Validators
if (properties.MinWidth.HasValue && w < properties.MinWidth)
{
addError(path, $"Width '{w}px' less than minimum of '{properties.MinWidth}px'.");
addError(path, T.Get("contents.validation.minimumWidth", new { width = w, min = properties.MinWidth }));
}
if (properties.MaxWidth.HasValue && w > properties.MaxWidth)
{
addError(path, $"Width '{w}px' greater than maximum of '{properties.MaxWidth}px'.");
addError(path, T.Get("contents.validation.maximumWidth", new { width = w, max = properties.MaxWidth }));
}
if (properties.MinHeight.HasValue && h < properties.MinHeight)
{
addError(path, $"Height '{h}px' less than minimum of '{properties.MinHeight}px'.");
addError(path, T.Get("contents.validation.minimumHeight", new { height = h, min = properties.MinHeight }));
}
if (properties.MaxHeight.HasValue && h > properties.MaxHeight)
{
addError(path, $"Height '{h}px' greater than maximum of '{properties.MaxHeight}px'.");
addError(path, T.Get("contents.validation.maximumHeight", new { height = h, max = properties.MaxHeight }));
}
if (properties.AspectHeight.HasValue && properties.AspectWidth.HasValue)
@ -121,7 +122,7 @@ namespace Squidex.Domain.Apps.Core.ValidateContent.Validators
if (Math.Abs(expectedRatio - actualRatio) > double.Epsilon)
{
addError(path, $"Aspect ratio not '{properties.AspectWidth}:{properties.AspectHeight}'.");
addError(path, T.Get("contents.validation.aspectRatio", new { width = properties.AspectWidth, height = properties.AspectHeight }));
}
}
}

13
backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/CollectionValidator.cs

@ -1,4 +1,4 @@
// ==========================================================================
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschränkt)
@ -8,6 +8,7 @@
using System;
using System.Collections;
using System.Threading.Tasks;
using Squidex.Infrastructure.Translations;
namespace Squidex.Domain.Apps.Core.ValidateContent.Validators
{
@ -35,7 +36,7 @@ namespace Squidex.Domain.Apps.Core.ValidateContent.Validators
{
if (isRequired && !context.IsOptional)
{
addError(context.Path, "Field is required.");
addError(context.Path, T.Get("contents.validation.required"));
}
return Task.CompletedTask;
@ -45,23 +46,23 @@ namespace Squidex.Domain.Apps.Core.ValidateContent.Validators
{
if (minItems == maxItems && minItems != items.Count)
{
addError(context.Path, $"Must have exactly {maxItems} item(s).");
addError(context.Path, T.Get("contents.validation.itemCount", new { count = minItems }));
}
else if (items.Count < minItems || items.Count > maxItems)
{
addError(context.Path, $"Must have between {minItems} and {maxItems} item(s).");
addError(context.Path, T.Get("contents.validation.itemCountBetween", new { min = minItems, max = maxItems }));
}
}
else
{
if (minItems.HasValue && items.Count < minItems.Value)
{
addError(context.Path, $"Must have at least {minItems} item(s).");
addError(context.Path, T.Get("contents.validation.minItems", new { min = minItems }));
}
if (maxItems.HasValue && items.Count > maxItems.Value)
{
addError(context.Path, $"Must not have more than {maxItems} item(s).");
addError(context.Path, T.Get("contents.validation.maxItems", new { max = maxItems }));
}
}

5
backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/FieldValidator.cs

@ -1,4 +1,4 @@
// ==========================================================================
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
@ -11,6 +11,7 @@ using System.Threading.Tasks;
using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Json.Objects;
using Squidex.Infrastructure.Translations;
namespace Squidex.Domain.Apps.Core.ValidateContent.Validators
{
@ -69,7 +70,7 @@ namespace Squidex.Domain.Apps.Core.ValidateContent.Validators
}
catch
{
addError(context.Path, "Not a valid value.");
addError(context.Path, T.Get("contents.validation.invalid"));
}
}
}

5
backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/NoValueValidator.cs

@ -1,4 +1,4 @@
// ==========================================================================
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
@ -6,6 +6,7 @@
// ==========================================================================
using System.Threading.Tasks;
using Squidex.Infrastructure.Translations;
namespace Squidex.Domain.Apps.Core.ValidateContent.Validators
{
@ -21,7 +22,7 @@ namespace Squidex.Domain.Apps.Core.ValidateContent.Validators
{
if (!value.IsUndefined())
{
addError(context.Path, "Value must not be defined.");
addError(context.Path, T.Get("contents.validation.mustBeEmpty"));
}
return Task.CompletedTask;

5
backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/ObjectValidator.cs

@ -1,4 +1,4 @@
// ==========================================================================
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
@ -7,6 +7,7 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Squidex.Infrastructure.Translations;
namespace Squidex.Domain.Apps.Core.ValidateContent.Validators
{
@ -39,7 +40,7 @@ namespace Squidex.Domain.Apps.Core.ValidateContent.Validators
if (!schema.ContainsKey(name))
{
addError(context.Path.Enqueue(name), $"Not a known {fieldType}.");
addError(context.Path.Enqueue(name), T.Get("contents.validation.unknownField", new { fieldType }));
}
}

7
backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/PatternValidator.cs

@ -1,4 +1,4 @@
// ==========================================================================
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschränkt)
@ -9,6 +9,7 @@ using System;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Translations;
namespace Squidex.Domain.Apps.Core.ValidateContent.Validators
{
@ -39,7 +40,7 @@ namespace Squidex.Domain.Apps.Core.ValidateContent.Validators
{
if (string.IsNullOrWhiteSpace(errorMessage))
{
addError(context.Path, "Does not match to the pattern.");
addError(context.Path, T.Get("contents.validation.pattern"));
}
else
{
@ -49,7 +50,7 @@ namespace Squidex.Domain.Apps.Core.ValidateContent.Validators
}
catch
{
addError(context.Path, "Regex is too slow.");
addError(context.Path, T.Get("contents.validation.regexTooSlow"));
}
}
}

21
backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/RangeValidator.cs

@ -1,4 +1,4 @@
// ==========================================================================
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschränkt)
@ -7,15 +7,16 @@
using System;
using System.Threading.Tasks;
using Squidex.Infrastructure.Translations;
namespace Squidex.Domain.Apps.Core.ValidateContent.Validators
{
public sealed class RangeValidator<T> : IValidator where T : struct, IComparable<T>
public sealed class RangeValidator<TValue> : IValidator where TValue : struct, IComparable<TValue>
{
private readonly T? min;
private readonly T? max;
private readonly TValue? min;
private readonly TValue? max;
public RangeValidator(T? min, T? max)
public RangeValidator(TValue? min, TValue? max)
{
if (min.HasValue && max.HasValue && min.Value.CompareTo(max.Value) > 0)
{
@ -28,29 +29,29 @@ namespace Squidex.Domain.Apps.Core.ValidateContent.Validators
public Task ValidateAsync(object? value, ValidationContext context, AddError addError)
{
if (value != null && value is T typedValue)
if (value != null && value is TValue typedValue)
{
if (min.HasValue && max.HasValue)
{
if (Equals(min, max) && Equals(min.Value, max.Value))
{
addError(context.Path, $"Must be exactly '{max}'.");
addError(context.Path, T.Get("contents.validation.exactValue", new { value = max.Value }));
}
else if (typedValue.CompareTo(min.Value) < 0 || typedValue.CompareTo(max.Value) > 0)
{
addError(context.Path, $"Must be between '{min}' and '{max}'.");
addError(context.Path, T.Get("contents.validation.between", new { min, max }));
}
}
else
{
if (min.HasValue && typedValue.CompareTo(min.Value) < 0)
{
addError(context.Path, $"Must be greater or equal to '{min}'.");
addError(context.Path, T.Get("contents.validation.min", new { min }));
}
if (max.HasValue && typedValue.CompareTo(max.Value) > 0)
{
addError(context.Path, $"Must be less or equal to '{max}'.");
addError(context.Path, T.Get("contents.validation.max", new { max }));
}
}
}

7
backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/ReferencesValidator.cs

@ -1,4 +1,4 @@
// ==========================================================================
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschränkt)
@ -9,6 +9,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Translations;
namespace Squidex.Domain.Apps.Core.ValidateContent.Validators
{
@ -45,11 +46,11 @@ namespace Squidex.Domain.Apps.Core.ValidateContent.Validators
if (schemaId == DomainId.Empty)
{
addError(context.Path, $"Contains invalid reference '{id}'.");
addError(context.Path, T.Get("common.referenceNotFound", new { id }));
}
else if (schemaIds?.Any() == true && !schemaIds.Contains(schemaId))
{
addError(context.Path, $"Contains reference '{id}' to invalid schema.");
addError(context.Path, T.Get("common.referenceToInvalidSchema", new { id }));
}
}
}

5
backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/RequiredStringValidator.cs

@ -1,4 +1,4 @@
// ==========================================================================
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschränkt)
@ -6,6 +6,7 @@
// ==========================================================================
using System.Threading.Tasks;
using Squidex.Infrastructure.Translations;
namespace Squidex.Domain.Apps.Core.ValidateContent.Validators
{
@ -27,7 +28,7 @@ namespace Squidex.Domain.Apps.Core.ValidateContent.Validators
if (value.IsNullOrUndefined() || IsEmptyString(value))
{
addError(context.Path, "Field is required.");
addError(context.Path, T.Get("contents.validation.required"));
}
return Task.CompletedTask;

5
backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/RequiredValidator.cs

@ -1,4 +1,4 @@
// ==========================================================================
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschränkt)
@ -6,6 +6,7 @@
// ==========================================================================
using System.Threading.Tasks;
using Squidex.Infrastructure.Translations;
namespace Squidex.Domain.Apps.Core.ValidateContent.Validators
{
@ -15,7 +16,7 @@ namespace Squidex.Domain.Apps.Core.ValidateContent.Validators
{
if (value.IsNullOrUndefined() && !context.IsOptional)
{
addError(context.Path, "Field is required.");
addError(context.Path, T.Get("contents.validation.required"));
}
return Task.CompletedTask;

11
backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/StringLengthValidator.cs

@ -1,4 +1,4 @@
// ==========================================================================
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschränkt)
@ -7,6 +7,7 @@
using System;
using System.Threading.Tasks;
using Squidex.Infrastructure.Translations;
namespace Squidex.Domain.Apps.Core.ValidateContent.Validators
{
@ -34,23 +35,23 @@ namespace Squidex.Domain.Apps.Core.ValidateContent.Validators
{
if (minLength == maxLength && minLength != stringValue.Length)
{
addError(context.Path, $"Must have exactly {maxLength} character(s).");
addError(context.Path, T.Get("contents.validation.characterCount", new { count = minLength }));
}
else if (stringValue.Length < minLength || stringValue.Length > maxLength)
{
addError(context.Path, $"Must have between {minLength} and {maxLength} character(s).");
addError(context.Path, T.Get("contents.validation.charactersBetween", new { min = minLength, max = maxLength }));
}
}
else
{
if (minLength.HasValue && stringValue.Length < minLength.Value)
{
addError(context.Path, $"Must have at least {minLength} character(s).");
addError(context.Path, T.Get("contents.validation.minLength", new { min = minLength }));
}
if (maxLength.HasValue && stringValue.Length > maxLength.Value)
{
addError(context.Path, $"Must not have more than {maxLength} character(s).");
addError(context.Path, T.Get("contents.validation.maxLength", new { max = maxLength }));
}
}
}

5
backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/UniqueValidator.cs

@ -1,4 +1,4 @@
// ==========================================================================
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
@ -10,6 +10,7 @@ using System.Linq;
using System.Threading.Tasks;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Queries;
using Squidex.Infrastructure.Translations;
namespace Squidex.Domain.Apps.Core.ValidateContent.Validators
{
@ -52,7 +53,7 @@ namespace Squidex.Domain.Apps.Core.ValidateContent.Validators
if (found.Any(x => x.Id != context.ContentId))
{
addError(context.Path, "Another content with the same value exists.");
addError(context.Path, T.Get("contents.validation.unique"));
}
}
}

9
backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/UniqueValuesValidator.cs

@ -1,4 +1,4 @@
// ==========================================================================
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
@ -8,20 +8,21 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Squidex.Infrastructure.Translations;
namespace Squidex.Domain.Apps.Core.ValidateContent.Validators
{
public sealed class UniqueValuesValidator<T> : IValidator
public sealed class UniqueValuesValidator<TValue> : IValidator
{
public Task ValidateAsync(object? value, ValidationContext context, AddError addError)
{
if (value is IEnumerable<T> items && items.Any())
if (value is IEnumerable<TValue> items && items.Any())
{
var itemsArray = items.ToArray();
if (itemsArray.Length != itemsArray.Distinct().Count())
{
addError(context.Path, "Must not contain duplicate values.");
addError(context.Path, T.Get("contents.validation.duplicates"));
}
}

5
backend/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetRepository.cs

@ -1,4 +1,4 @@
// ==========================================================================
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschränkt)
@ -21,6 +21,7 @@ using Squidex.Infrastructure.MongoDb;
using Squidex.Infrastructure.MongoDb.Queries;
using Squidex.Infrastructure.Queries;
using Squidex.Infrastructure.Tasks;
using Squidex.Infrastructure.Translations;
namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
{
@ -91,7 +92,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
}
catch (MongoQueryException ex) when (ex.Message.Contains("17406"))
{
throw new DomainException("Result set is too large to be retrieved. Use $take parameter to reduce the number of items.");
throw new DomainException(T.Get("common.resultTooLarge"));
}
}
}

2
backend/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/Visitors/FirstPascalPathExtension.cs

@ -6,8 +6,8 @@
// ==========================================================================
using System.Linq;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Queries;
using Squidex.Text;
namespace Squidex.Domain.Apps.Entities.MongoDb.Assets.Visitors
{

18
backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Operations/Adapt.cs

@ -43,23 +43,15 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations
if (result.Count > 1)
{
var edmName = result[1].UnescapeEdmField();
var rootEdmName = result[1].UnescapeEdmField();
var rootField = schema.FieldsByName[rootEdmName];
if (!schema.FieldsByName.TryGetValue(edmName, out var field))
{
throw new NotSupportedException();
}
result[1] = rootField.Id.ToString();
result[1] = field.Id.ToString();
if (field is IArrayField arrayField && result.Count > 3)
if (rootField is IArrayField arrayField && result.Count > 3)
{
var nestedEdmName = result[3].UnescapeEdmField();
if (!arrayField.FieldsByName.TryGetValue(nestedEdmName, out var nestedField))
{
throw new NotSupportedException();
}
var nestedField = arrayField.FieldsByName[nestedEdmName];
result[3] = nestedField.Id.ToString();
}

21
backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Operations/QueryContentsByQuery.cs

@ -1,4 +1,4 @@
// ==========================================================================
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
@ -20,6 +20,7 @@ using Squidex.Infrastructure;
using Squidex.Infrastructure.MongoDb.Queries;
using Squidex.Infrastructure.Queries;
using Squidex.Infrastructure.Tasks;
using Squidex.Infrastructure.Translations;
namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations
{
@ -45,9 +46,9 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations
this.indexer = indexer;
}
protected override Task PrepareAsync(CancellationToken ct = default)
protected override async Task PrepareAsync(CancellationToken ct = default)
{
var index =
var indexBySchemaWithRefs =
new CreateIndexModel<MongoContentEntity>(Index
.Ascending(x => x.IndexedAppId)
.Ascending(x => x.IndexedSchemaId)
@ -55,7 +56,15 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations
.Ascending(x => x.ReferencedIds)
.Descending(x => x.LastModified));
return Collection.Indexes.CreateOneAsync(index, cancellationToken: ct);
await Collection.Indexes.CreateOneAsync(indexBySchemaWithRefs, cancellationToken: ct);
var indexBySchema =
new CreateIndexModel<MongoContentEntity>(Index
.Ascending(x => x.IndexedSchemaId)
.Ascending(x => x.IsDeleted)
.Descending(x => x.LastModified));
await Collection.Indexes.CreateOneAsync(indexBySchema, cancellationToken: ct);
}
public async Task<IResultList<IContentEntity>> DoAsync(IAppEntity app, ISchemaEntity schema, ClrQuery query, SearchScope scope)
@ -98,11 +107,11 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations
}
catch (MongoCommandException ex) when (ex.Code == 96)
{
throw new DomainException("Result set is too large to be retrieved. Use $take parameter to reduce the number of items.");
throw new DomainException(T.Get("common.resultTooLarge"));
}
catch (MongoQueryException ex) when (ex.Message.Contains("17406"))
{
throw new DomainException("Result set is too large to be retrieved. Use $take parameter to reduce the number of items.");
throw new DomainException(T.Get("common.resultTooLarge"));
}
}

9
backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/StatusSerializer.cs

@ -5,7 +5,6 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System.Threading;
using MongoDB.Bson;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Serializers;
@ -15,11 +14,9 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
{
public sealed class StatusSerializer : SerializerBase<Status>
{
private static int isRegistered;
public static void Register()
{
if (Interlocked.Increment(ref isRegistered) == 1)
try
{
try
{
@ -30,6 +27,10 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
return;
}
}
catch (BsonSerializationException)
{
return;
}
}
public override Status Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)

30
backend/src/Squidex.Domain.Apps.Entities.MongoDb/Rules/MongoRuleEventRepository.cs

@ -110,11 +110,29 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Rules
.Set(x => x.JobResult, RuleJobResult.Cancelled));
}
public async Task UpdateAsync(RuleJob job, RuleJobUpdate update)
public Task UpdateAsync(RuleJob job, RuleJobUpdate update)
{
Guard.NotNull(job, nameof(job));
Guard.NotNull(update, nameof(update));
return Task.WhenAll(
UpdateStatisticsAsync(job, update),
UpdateEventAsync(job, update));
}
private Task UpdateEventAsync(RuleJob job, RuleJobUpdate update)
{
return Collection.UpdateOneAsync(x => x.DocumentId == job.Id,
Update
.Set(x => x.Result, update.ExecutionResult)
.Set(x => x.LastDump, update.ExecutionDump)
.Set(x => x.JobResult, update.JobResult)
.Set(x => x.NextAttempt, update.JobNext)
.Inc(x => x.NumCalls, 1));
}
private async Task UpdateStatisticsAsync(RuleJob job, RuleJobUpdate update)
{
if (update.ExecutionResult == RuleResult.Success)
{
await statisticsCollection.IncrementSuccess(job.AppId, job.RuleId, update.Finished);
@ -123,16 +141,6 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Rules
{
await statisticsCollection.IncrementFailed(job.AppId, job.RuleId, update.Finished);
}
var documentId = job.Id.ToString();
await Collection.UpdateOneAsync(x => x.DocumentId == documentId,
Update
.Set(x => x.Result, update.ExecutionResult)
.Set(x => x.LastDump, update.ExecutionDump)
.Set(x => x.JobResult, update.JobResult)
.Set(x => x.NextAttempt, update.JobNext)
.Inc(x => x.NumCalls, 1));
}
public Task<IReadOnlyList<RuleStatistics>> QueryStatisticsByAppAsync(DomainId appId)

5
backend/src/Squidex.Domain.Apps.Entities/Apps/AppCommandMiddleware.cs

@ -1,4 +1,4 @@
// ==========================================================================
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschränkt)
@ -11,6 +11,7 @@ using Squidex.Domain.Apps.Entities.Apps.Commands;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Assets;
using Squidex.Infrastructure.Commands;
using Squidex.Infrastructure.Translations;
using Squidex.Infrastructure.Validation;
namespace Squidex.Domain.Apps.Entities.Apps
@ -64,7 +65,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
if (image == null)
{
throw new ValidationException("File is not an image.");
throw new ValidationException(T.Get("apps.notImage"));
}
}

28
backend/src/Squidex.Domain.Apps.Entities/Apps/AppDomainObject.cs

@ -1,4 +1,4 @@
// ==========================================================================
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschränkt)
@ -21,6 +21,7 @@ using Squidex.Infrastructure.EventSourcing;
using Squidex.Infrastructure.Log;
using Squidex.Infrastructure.Reflection;
using Squidex.Infrastructure.States;
using Squidex.Infrastructure.Translations;
using Squidex.Shared.Users;
namespace Squidex.Domain.Apps.Entities.Apps
@ -64,8 +65,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
protected override bool CanAccept(ICommand command)
{
return command is AppUpdateCommand update &&
Equals(update?.AppId?.Id, Snapshot.Id);
return command is AppUpdateCommand update && Equals(update?.AppId?.Id, Snapshot.Id);
}
public override Task<object?> ExecuteAsync(IAggregateCommand command)
@ -295,7 +295,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
}
else
{
var result = await appPlansBillingManager.ChangePlanAsync(c.Actor.Identifier, Snapshot.NamedId(), c.PlanId);
var result = await appPlansBillingManager.ChangePlanAsync(c.Actor.Identifier, Snapshot.NamedId(), c.PlanId, c.Referer);
switch (result)
{
@ -311,7 +311,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
case ArchiveApp archiveApp:
return UpdateAsync(archiveApp, async c =>
{
await appPlansBillingManager.ChangePlanAsync(c.Actor.Identifier, Snapshot.NamedId(), null);
await appPlansBillingManager.ChangePlanAsync(c.Actor.Identifier, Snapshot.NamedId(), null, null);
ArchiveApp(c);
});
@ -355,19 +355,6 @@ namespace Squidex.Domain.Apps.Entities.Apps
}
}
public void UpdateClient(UpdateClient command)
{
if (!string.IsNullOrWhiteSpace(command.Name))
{
RaiseEvent(SimpleMapper.Map(command, new AppClientRenamed()));
}
if (command.Role != null)
{
RaiseEvent(SimpleMapper.Map(command, new AppClientUpdated { Role = command.Role }));
}
}
public void ChangePlan(ChangePlan command)
{
if (string.Equals(appPlansProvider.GetFreePlan()?.Id, command.PlanId))
@ -385,6 +372,11 @@ namespace Squidex.Domain.Apps.Entities.Apps
RaiseEvent(SimpleMapper.Map(command, new AppUpdated()));
}
public void UpdateClient(UpdateClient command)
{
RaiseEvent(SimpleMapper.Map(command, new AppClientUpdated()));
}
public void UploadImage(UploadAppImage command)
{
RaiseEvent(SimpleMapper.Map(command, new AppImageUploaded { Image = new AppImage(command.File.MimeType) }));

52
backend/src/Squidex.Domain.Apps.Entities/Apps/AppHistoryEventsCreator.cs

@ -1,4 +1,4 @@
// ==========================================================================
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschränkt)
@ -20,58 +20,55 @@ namespace Squidex.Domain.Apps.Entities.Apps
: base(typeNameRegistry)
{
AddEventMessage<AppContributorAssigned>(
"assigned {user:[Contributor]} as {[Role]}");
"history.apps.contributoreAssigned");
AddEventMessage<AppContributorRemoved>(
"removed {user:[Contributor]} from app");
"history.apps.contributoreRemoved");
AddEventMessage<AppClientAttached>(
"added client {[Id]} to app");
"history.apps.clientAdded");
AddEventMessage<AppClientRevoked>(
"revoked client {[Id]}");
"history.apps.clientRevoked");
AddEventMessage<AppClientUpdated>(
"updated client {[Id]}");
AddEventMessage<AppClientRenamed>(
"renamed client {[Id]} to {[Name]}");
"history.apps.clientUpdated");
AddEventMessage<AppPlanChanged>(
"changed plan to {[Plan]}");
"history.apps.planChanged");
AddEventMessage<AppPlanReset>(
"resetted plan");
"history.apps.planReset");
AddEventMessage<AppLanguageAdded>(
"added language {[Language]}");
"history.apps.languagedAdded");
AddEventMessage<AppLanguageRemoved>(
"removed language {[Language]}");
"history.apps.languagedRemoved");
AddEventMessage<AppLanguageUpdated>(
"updated language {[Language]}");
"history.apps.languagedUpdated");
AddEventMessage<AppMasterLanguageSet>(
"changed master language to {[Language]}");
"history.apps.languagedSetToMaster");
AddEventMessage<AppPatternAdded>(
"added pattern {[Name]}");
"history.apps.patternAdded");
AddEventMessage<AppPatternDeleted>(
"deleted pattern {[PatternId]}");
"history.apps.patternDeleted");
AddEventMessage<AppPatternUpdated>(
"updated pattern {[Name]}");
"history.apps.patternUpdated");
AddEventMessage<AppRoleAdded>(
"added role {[Name]}");
"history.apps.roleAdded");
AddEventMessage<AppRoleDeleted>(
"deleted role {[Name]}");
"history.apps.roleDeleted");
AddEventMessage<AppRoleUpdated>(
"updated role {[Name]}");
"history.apps.roleUpdated");
}
private HistoryEvent? CreateEvent(IEvent @event)
@ -84,8 +81,8 @@ namespace Squidex.Domain.Apps.Entities.Apps
return CreateContributorsEvent(e, e.ContributorId);
case AppClientAttached e:
return CreateClientsEvent(e, e.Id);
case AppClientRenamed e:
return CreateClientsEvent(e, e.Id, ClientName(e));
case AppClientUpdated e:
return CreateClientsEvent(e, e.Id);
case AppClientRevoked e:
return CreateClientsEvent(e, e.Id);
case AppLanguageAdded e:
@ -137,9 +134,9 @@ namespace Squidex.Domain.Apps.Entities.Apps
return ForEvent(e, "settings.patterns").Param("PatternId", id).Param("Name", name);
}
private HistoryEvent CreateClientsEvent(IEvent e, string id, string? name = null)
private HistoryEvent CreateClientsEvent(IEvent e, string id)
{
return ForEvent(e, "settings.clients").Param("Id", id).Param("Name", name);
return ForEvent(e, "settings.clients").Param("Id", id);
}
private HistoryEvent CreatePlansEvent(IEvent e, string? plan = null)
@ -151,10 +148,5 @@ namespace Squidex.Domain.Apps.Entities.Apps
{
return Task.FromResult(CreateEvent(@event.Payload));
}
private static string ClientName(AppClientRenamed e)
{
return !string.IsNullOrWhiteSpace(e.Name) ? e.Name : e.Id;
}
}
}

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

Loading…
Cancel
Save