Quellcode durchsuchen

Merge branch 'master' into next

Michael Bromley vor 5 Jahren
Ursprung
Commit
8479e43a94
27 geänderte Dateien mit 800 neuen und 77 gelöschten Zeilen
  1. 14 0
      CHANGELOG.md
  2. 1 1
      e2e-common/test-config.ts
  3. 1 1
      lerna.json
  4. 2 2
      packages/admin-ui-plugin/package.json
  5. 8 1
      packages/admin-ui-plugin/src/constants.ts
  6. 1 1
      packages/admin-ui/package.json
  7. 16 5
      packages/admin-ui/src/lib/catalog/src/components/apply-facet-dialog/apply-facet-dialog.component.ts
  8. 1 1
      packages/admin-ui/src/lib/catalog/src/components/collection-detail/collection-detail.component.ts
  9. 3 1
      packages/admin-ui/src/lib/catalog/src/components/facet-detail/facet-detail.component.ts
  10. 1 0
      packages/admin-ui/src/lib/catalog/src/components/product-detail/product-detail.component.ts
  11. 17 32
      packages/admin-ui/src/lib/catalog/src/providers/product-detail.service.ts
  12. 1 1
      packages/admin-ui/src/lib/core/src/common/version.ts
  13. 8 0
      packages/admin-ui/src/lib/core/src/data/providers/facet-data.service.ts
  14. 21 6
      packages/admin-ui/src/lib/core/src/shared/components/facet-value-selector/facet-value-selector.component.ts
  15. 1 1
      packages/admin-ui/src/lib/marketing/src/components/promotion-detail/promotion-detail.component.ts
  16. 1 1
      packages/admin-ui/src/lib/settings/src/components/payment-method-detail/payment-method-detail.component.html
  17. 9 0
      packages/admin-ui/src/lib/settings/src/components/payment-method-detail/payment-method-detail.component.ts
  18. 671 0
      packages/admin-ui/src/lib/static/i18n-messages/de.json
  19. 1 1
      packages/admin-ui/src/lib/static/vendure-ui-config.json
  20. 2 2
      packages/asset-server-plugin/package.json
  21. 1 1
      packages/core/package.json
  22. 2 2
      packages/create/package.json
  23. 8 8
      packages/dev-server/package.json
  24. 2 2
      packages/elasticsearch-plugin/package.json
  25. 2 2
      packages/email-plugin/package.json
  26. 2 2
      packages/testing/package.json
  27. 3 3
      packages/ui-devkit/package.json

+ 14 - 0
CHANGELOG.md

@@ -1,3 +1,17 @@
+## <small>0.12.5 (2020-05-28)</small>
+
+
+#### Features
+
+* **admin-ui** Add German translations ([00bf630](https://github.com/vendure-ecommerce/vendure/commit/00bf630))
+* **admin-ui** Focus facet selector when opening "add facets" dialog ([42c1a48](https://github.com/vendure-ecommerce/vendure/commit/42c1a48))
+
+#### Fixes
+
+* **admin-ui** Fix error updating PaymentMethod config parameters ([b4061a5](https://github.com/vendure-ecommerce/vendure/commit/b4061a5)), closes [#345](https://github.com/vendure-ecommerce/vendure/issues/345)
+* **admin-ui** Update available facets when creating new values ([05864c6](https://github.com/vendure-ecommerce/vendure/commit/05864c6)), closes [#347](https://github.com/vendure-ecommerce/vendure/issues/347)
+* **asset-server-plugin** Fix mime type detection ([7613f74](https://github.com/vendure-ecommerce/vendure/commit/7613f74)), closes [#341](https://github.com/vendure-ecommerce/vendure/issues/341)
+
 ## <small>0.12.4 (2020-05-20)</small>
 Fixes broken publish of admin-ui-plugin
 

+ 1 - 1
e2e-common/test-config.ts

@@ -67,7 +67,7 @@ function getDbConfig(): ConnectionOptions {
             return {
                 synchronize: true,
                 type: 'mysql',
-                host: process.env.CI ? '127.0.0.1' : '192.168.99.100',
+                host: '127.0.0.1',
                 port: process.env.CI ? +(process.env.E2E_MYSQL_PORT || 3306) : 3306,
                 username: 'root',
                 password: '',

+ 1 - 1
lerna.json

@@ -2,7 +2,7 @@
   "packages": [
     "packages/*"
   ],
-  "version": "0.12.4",
+  "version": "0.12.5",
   "npmClient": "yarn",
   "useWorkspaces": true,
   "command": {

+ 2 - 2
packages/admin-ui-plugin/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@vendure/admin-ui-plugin",
-  "version": "0.12.4",
+  "version": "0.12.5",
   "main": "lib/index.js",
   "types": "lib/index.d.ts",
   "files": [
@@ -20,7 +20,7 @@
     "@types/express": "^4.0.39",
     "@types/fs-extra": "^8.0.1",
     "@vendure/common": "^0.12.3",
-    "@vendure/core": "^0.12.3",
+    "@vendure/core": "^0.12.5",
     "express": "^4.16.4",
     "rimraf": "^3.0.0",
     "typescript": "3.8.3"

+ 8 - 1
packages/admin-ui-plugin/src/constants.ts

@@ -4,4 +4,11 @@ import path from 'path';
 export const DEFAULT_APP_PATH = path.join(__dirname, '../admin-ui');
 export const loggerCtx = 'AdminUiPlugin';
 export const defaultLanguage = LanguageCode.en;
-export const defaultAvailableLanguages = [LanguageCode.en, LanguageCode.es, LanguageCode.zh, LanguageCode.pl];
+
+export const defaultAvailableLanguages = [
+    LanguageCode.de,
+    LanguageCode.en,
+    LanguageCode.es,
+    LanguageCode.pl,
+    LanguageCode.zh,
+];

+ 1 - 1
packages/admin-ui/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@vendure/admin-ui",
-  "version": "0.12.4",
+  "version": "0.12.5",
   "license": "MIT",
   "scripts": {
     "ng": "ng",

+ 16 - 5
packages/admin-ui/src/lib/catalog/src/components/apply-facet-dialog/apply-facet-dialog.component.ts

@@ -1,7 +1,11 @@
-import { ChangeDetectionStrategy, Component } from '@angular/core';
-
-import { FacetValue, FacetWithValues } from '@vendure/admin-ui/core';
-import { Dialog } from '@vendure/admin-ui/core';
+import {
+    AfterViewInit,
+    ChangeDetectionStrategy,
+    ChangeDetectorRef,
+    Component,
+    ViewChild,
+} from '@angular/core';
+import { Dialog, FacetValue, FacetValueSelectorComponent, FacetWithValues } from '@vendure/admin-ui/core';
 
 @Component({
     selector: 'vdr-apply-facet-dialog',
@@ -9,12 +13,19 @@ import { Dialog } from '@vendure/admin-ui/core';
     styleUrls: ['./apply-facet-dialog.component.scss'],
     changeDetection: ChangeDetectionStrategy.OnPush,
 })
-export class ApplyFacetDialogComponent implements Dialog<FacetValue[]> {
+export class ApplyFacetDialogComponent implements Dialog<FacetValue[]>, AfterViewInit {
+    @ViewChild(FacetValueSelectorComponent) private selector: FacetValueSelectorComponent;
     resolveWith: (result?: FacetValue[]) => void;
     selectedValues: FacetValue[] = [];
     // Provided by caller
     facets: FacetWithValues.Fragment[];
 
+    constructor(private changeDetector: ChangeDetectorRef) {}
+
+    ngAfterViewInit() {
+        setTimeout(() => this.selector.focus(), 0);
+    }
+
     selectValues() {
         this.resolveWith(this.selectedValues);
     }

+ 1 - 1
packages/admin-ui/src/lib/catalog/src/components/collection-detail/collection-detail.component.ts

@@ -75,7 +75,7 @@ export class CollectionDetailComponent extends BaseDetailComponent<Collection.Fr
     ngOnInit() {
         this.init();
         this.facets$ = this.dataService.facet
-            .getFacets(9999999, 0)
+            .getAllFacets()
             .mapSingle((data) => data.facets.items)
             .pipe(shareReplay(1));
 

+ 3 - 1
packages/admin-ui/src/lib/catalog/src/components/facet-detail/facet-detail.component.ts

@@ -21,7 +21,7 @@ import {
 import { normalizeString } from '@vendure/common/lib/normalize-string';
 import { notNullOrUndefined } from '@vendure/common/lib/shared-utils';
 import { combineLatest, EMPTY, forkJoin, Observable } from 'rxjs';
-import { map, mergeMap, switchMap, take } from 'rxjs/operators';
+import { map, mapTo, mergeMap, switchMap, take } from 'rxjs/operators';
 
 @Component({
     selector: 'vdr-facet-detail',
@@ -130,6 +130,7 @@ export class FacetDetailComponent extends BaseDetailComponent<FacetWithValues.Fr
                     ) as CreateFacetInput;
                     return this.dataService.facet.createFacet(newFacet);
                 }),
+                switchMap((data) => this.dataService.facet.getAllFacets(true).single$.pipe(mapTo(data))),
             )
             .subscribe(
                 (data) => {
@@ -192,6 +193,7 @@ export class FacetDetailComponent extends BaseDetailComponent<FacetWithValues.Fr
 
                     return forkJoin(updateOperations);
                 }),
+                switchMap(() => this.dataService.facet.getAllFacets(true).single$),
             )
             .subscribe(
                 () => {

+ 1 - 0
packages/admin-ui/src/lib/catalog/src/components/product-detail/product-detail.component.ts

@@ -314,6 +314,7 @@ export class ProductDetailComponent extends BaseDetailComponent<ProductWithVaria
             mergeMap((facets) =>
                 this.modalService.fromComponent(ApplyFacetDialogComponent, {
                     size: 'md',
+                    closable: true,
                     locals: { facets },
                 }),
             ),

+ 17 - 32
packages/admin-ui/src/lib/catalog/src/providers/product-detail.service.ts

@@ -2,21 +2,20 @@ import { Injectable } from '@angular/core';
 import {
     CreateProductInput,
     CreateProductVariantInput,
+    DataService,
     DeletionResult,
     FacetWithValues,
     LanguageCode,
-    ProductOptionGroup,
     UpdateProductInput,
     UpdateProductMutation,
     UpdateProductOptionInput,
     UpdateProductVariantInput,
     UpdateProductVariantsMutation,
 } from '@vendure/admin-ui/core';
-import { DataService } from '@vendure/admin-ui/core';
 import { normalizeString } from '@vendure/common/lib/normalize-string';
 import { notNullOrUndefined } from '@vendure/common/lib/shared-utils';
-import { BehaviorSubject, forkJoin, Observable, of, throwError } from 'rxjs';
-import { map, mergeMap, shareReplay, skip, switchMap } from 'rxjs/operators';
+import { forkJoin, Observable, of, throwError } from 'rxjs';
+import { map, mergeMap, shareReplay, switchMap } from 'rxjs/operators';
 
 import { CreateProductVariantsConfig } from '../components/generate-product-variants/generate-product-variants.component';
 
@@ -28,30 +27,16 @@ import { CreateProductVariantsConfig } from '../components/generate-product-vari
     providedIn: 'root',
 })
 export class ProductDetailService {
-    private facetsSubject = new BehaviorSubject<FacetWithValues.Fragment[]>([]);
-
     constructor(private dataService: DataService) {}
 
     getFacets(): Observable<FacetWithValues.Fragment[]> {
-        let skipValue = 0;
-        if (this.facetsSubject.value.length === 0) {
-            this.dataService.facet
-                .getFacets(9999999, 0)
-                .mapSingle(data => data.facets.items)
-                .subscribe(items => this.facetsSubject.next(items));
-            skipValue = 1;
-        }
-
-        return this.facetsSubject.pipe(
-            skip(skipValue),
-            shareReplay(1),
-        );
+        return this.dataService.facet.getAllFacets().mapSingle((data) => data.facets.items);
     }
 
     getTaxCategories() {
         return this.dataService.settings
             .getTaxCategories()
-            .mapSingle(data => data.taxCategories)
+            .mapSingle((data) => data.taxCategories)
             .pipe(shareReplay(1));
     }
 
@@ -61,14 +46,14 @@ export class ProductDetailService {
         languageCode: LanguageCode,
     ) {
         const createProduct$ = this.dataService.product.createProduct(input);
-        const nonEmptyOptionGroups = createVariantsConfig.groups.filter(g => 0 < g.values.length);
+        const nonEmptyOptionGroups = createVariantsConfig.groups.filter((g) => 0 < g.values.length);
         const createOptionGroups$ = this.createProductOptionGroups(nonEmptyOptionGroups, languageCode);
 
         return forkJoin(createProduct$, createOptionGroups$).pipe(
             mergeMap(([{ createProduct }, optionGroups]) => {
                 const addOptionsToProduct$ = optionGroups.length
                     ? forkJoin(
-                          optionGroups.map(optionGroup => {
+                          optionGroups.map((optionGroup) => {
                               return this.dataService.product.addOptionGroupToProduct({
                                   productId: createProduct.id,
                                   optionGroupId: optionGroup.id,
@@ -83,10 +68,10 @@ export class ProductDetailService {
                 );
             }),
             mergeMap(({ createProduct, optionGroups }) => {
-                const variants = createVariantsConfig.variants.map(v => {
+                const variants = createVariantsConfig.variants.map((v) => {
                     const optionIds = optionGroups.length
                         ? v.optionValues.map((optionName, index) => {
-                              const option = optionGroups[index].options.find(o => o.name === optionName);
+                              const option = optionGroups[index].options.find((o) => o.name === optionName);
                               if (!option) {
                                   throw new Error(
                                       `Could not find a matching ProductOption "${optionName}" when creating variant`,
@@ -100,7 +85,7 @@ export class ProductDetailService {
                         optionIds,
                     };
                 });
-                const options = optionGroups.map(og => og.options).reduce((flat, o) => [...flat, ...o], []);
+                const options = optionGroups.map((og) => og.options).reduce((flat, o) => [...flat, ...o], []);
                 return this.createProductVariants(createProduct, variants, options, languageCode);
             }),
         );
@@ -109,17 +94,17 @@ export class ProductDetailService {
     createProductOptionGroups(groups: Array<{ name: string; values: string[] }>, languageCode: LanguageCode) {
         return groups.length
             ? forkJoin(
-                  groups.map(c => {
+                  groups.map((c) => {
                       return this.dataService.product
                           .createProductOptionGroups({
                               code: normalizeString(c.name, '-'),
                               translations: [{ languageCode, name: c.name }],
-                              options: c.values.map(v => ({
+                              options: c.values.map((v) => ({
                                   code: normalizeString(v, '-'),
                                   translations: [{ languageCode, name: v }],
                               })),
                           })
-                          .pipe(map(data => data.createProductOptionGroup));
+                          .pipe(map((data) => data.createProductOptionGroup));
                   }),
               )
             : of([]);
@@ -131,12 +116,12 @@ export class ProductDetailService {
         options: Array<{ id: string; name: string }>,
         languageCode: LanguageCode,
     ) {
-        const variants: CreateProductVariantInput[] = variantData.map(v => {
+        const variants: CreateProductVariantInput[] = variantData.map((v) => {
             const name = options.length
                 ? `${product.name} ${v.optionIds
-                      .map(id => options.find(o => o.id === id))
+                      .map((id) => options.find((o) => o.id === id))
                       .filter(notNullOrUndefined)
-                      .map(o => o.name)
+                      .map((o) => o.name)
                       .join(' ')}`
                 : product.name;
             return {
@@ -178,7 +163,7 @@ export class ProductDetailService {
 
     deleteProductVariant(id: string, productId: string) {
         return this.dataService.product.deleteProductVariant(id).pipe(
-            switchMap(result => {
+            switchMap((result) => {
                 if (result.deleteProductVariant.result === DeletionResult.DELETED) {
                     return this.dataService.product.getProduct(productId).single$;
                 } else {

+ 1 - 1
packages/admin-ui/src/lib/core/src/common/version.ts

@@ -1,2 +1,2 @@
 // Auto-generated by the set-version.js script.
-export const ADMIN_UI_VERSION = '0.12.4';
+export const ADMIN_UI_VERSION = '0.12.5';

+ 8 - 0
packages/admin-ui/src/lib/core/src/data/providers/facet-data.service.ts

@@ -39,6 +39,14 @@ export class FacetDataService {
         });
     }
 
+    getAllFacets(refresh: boolean = false) {
+        return this.baseDataService.query<GetFacetList.Query, GetFacetList.Variables>(
+            GET_FACET_LIST,
+            {},
+            refresh ? 'network-only' : 'cache-first',
+        );
+    }
+
     getFacet(id: string) {
         return this.baseDataService.query<GetFacetWithValues.Query, GetFacetWithValues.Variables>(
             GET_FACET_WITH_VALUES,

+ 21 - 6
packages/admin-ui/src/lib/core/src/shared/components/facet-value-selector/facet-value-selector.component.ts

@@ -1,9 +1,18 @@
-import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
+import {
+    ChangeDetectionStrategy,
+    Component,
+    EventEmitter,
+    Input,
+    OnInit,
+    Output,
+    ViewChild,
+} from '@angular/core';
 import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
-import { DataService } from '../../../data/providers/data.service';
+import { NgSelectComponent } from '@ng-select/ng-select';
 
 import { FacetValue, FacetWithValues } from '../../../common/generated-types';
 import { flattenFacetValues } from '../../../common/utilities/flatten-facet-values';
+import { DataService } from '../../../data/providers/data.service';
 
 export type FacetValueSeletorItem = {
     name: string;
@@ -30,6 +39,8 @@ export class FacetValueSelectorComponent implements OnInit, ControlValueAccessor
     @Input() facets: FacetWithValues.Fragment[];
     @Input() readonly = false;
 
+    @ViewChild(NgSelectComponent) private ngSelect: NgSelectComponent;
+
     facetValues: FacetValueSeletorItem[] = [];
     onChangeFn: (val: any) => void;
     onTouchFn: () => void;
@@ -45,9 +56,9 @@ export class FacetValueSelectorComponent implements OnInit, ControlValueAccessor
         if (this.readonly) {
             return;
         }
-        this.selectedValuesChange.emit(selected.map(s => s.value));
+        this.selectedValuesChange.emit(selected.map((s) => s.value));
         if (this.onChangeFn) {
-            this.onChangeFn(JSON.stringify(selected.map(s => s.id)));
+            this.onChangeFn(JSON.stringify(selected.map((s) => s.id)));
         }
     }
 
@@ -63,6 +74,10 @@ export class FacetValueSelectorComponent implements OnInit, ControlValueAccessor
         this.disabled = isDisabled;
     }
 
+    focus() {
+        this.ngSelect.focus();
+    }
+
     writeValue(obj: string | FacetValue.Fragment[] | null): void {
         if (typeof obj === 'string') {
             try {
@@ -73,7 +88,7 @@ export class FacetValueSelectorComponent implements OnInit, ControlValueAccessor
                 throw err;
             }
         } else if (obj) {
-            this.value = obj.map(fv => fv.id);
+            this.value = obj.map((fv) => fv.id);
         }
     }
 
@@ -84,5 +99,5 @@ export class FacetValueSelectorComponent implements OnInit, ControlValueAccessor
             id: facetValue.id,
             value: facetValue,
         };
-    }
+    };
 }

+ 1 - 1
packages/admin-ui/src/lib/marketing/src/components/promotion-detail/promotion-detail.component.ts

@@ -64,7 +64,7 @@ export class PromotionDetailComponent extends BaseDetailComponent<Promotion.Frag
     ngOnInit() {
         this.init();
         this.facets$ = this.dataService.facet
-            .getFacets(9999999, 0)
+            .getAllFacets()
             .mapSingle((data) => data.facets.items)
             .pipe(shareReplay(1));
 

+ 1 - 1
packages/admin-ui/src/lib/settings/src/components/payment-method-detail/payment-method-detail.component.html

@@ -46,7 +46,7 @@
         </clr-toggle-wrapper>
     </vdr-form-field>
 
-    <div class="clr-row" formGroupName="configArgs" *ngIf="(entity$ | async)?.configArgs?.length">
+    <div class="clr-row" formGroupName="configArgs" *ngIf="(entity$ | async)?.configArgs?.length && configArgsIsPopulated()">
         <div class="clr-col">
             <label>{{ 'settings.payment-method-config-options' | translate }}</label>
             <section class="form-block" *ngFor="let arg of (entity$ | async)?.configArgs">

+ 9 - 0
packages/admin-ui/src/lib/settings/src/components/payment-method-detail/payment-method-detail.component.ts

@@ -49,6 +49,14 @@ export class PaymentMethodDetailComponent extends BaseDetailComponent<PaymentMet
         return arg.type as any;
     }
 
+    configArgsIsPopulated(): boolean {
+        const configArgsGroup = this.detailForm.get('configArgs') as FormGroup | undefined;
+        if (!configArgsGroup) {
+            return false;
+        }
+        return 0 < Object.keys(configArgsGroup.controls).length;
+    }
+
     save() {
         this.entity$
             .pipe(
@@ -100,6 +108,7 @@ export class PaymentMethodDetailComponent extends BaseDetailComponent<PaymentMet
                 }
             }
         }
+        this.changeDetector.markForCheck();
     }
 
     private parseArgValue(arg: ConfigArg): string | number | boolean {

+ 671 - 0
packages/admin-ui/src/lib/static/i18n-messages/de.json

@@ -0,0 +1,671 @@
+{
+  "admin": {
+    "create-new-administrator": "Neuen Administrator anlegen"
+  },
+  "asset": {
+    "add-asset": "Asset hinzufügen",
+    "add-asset-with-count": "{count, plural, 0 {Assets} one {1 Asset} other {{count} Assets}} hinzufügen",
+    "assets-selected-count": "{count, plural, 0 {Kein Asset} one {1 Asset} other {{count} Assets}} ausgewählt",
+    "dimensions": "Abmessungen",
+    "focal-point": "Fokuspunkt",
+    "notify-create-assets-success": "{count, plural, one {Neues Asset} other {{count} neue Assets}} erstellt",
+    "original-asset-size": "Dateigröße",
+    "preview": "Vorschau",
+    "remove-asset": "Asset entfernen",
+    "search-asset-name": "Assets nach Namen durchsuchen",
+    "select-assets": "Assets auswählen",
+    "set-as-featured-asset": "Als \"Featured Asset\" festlegen",
+    "set-focal-point": "Fokuspunkt setzen",
+    "source-file": "Quelldatei",
+    "unset-focal-point": "Zurücksetzen",
+    "update-focal-point": "Punkt aktualisieren",
+    "update-focal-point-error": "Der Fokuspunkt konnte nicht aktualisiert werden",
+    "update-focal-point-success": "Fokuspunkt aktualisiert",
+    "upload-assets": "Assets hochladen",
+    "uploading": "Hochladen..."
+  },
+  "breadcrumb": {
+    "administrators": "Administratoren",
+    "assets": "Assets",
+    "channels": "Kanäle",
+    "collections": "Sammlungen",
+    "countries": "Länder",
+    "customers": "Kunden",
+    "dashboard": "Dashboard",
+    "facets": "Facetten",
+    "global-settings": "Globale Einstellungen",
+    "job-queue": "Job-Warteschlange",
+    "manage-variants": "Varianten verwalten",
+    "orders": "Bestellungen",
+    "payment-methods": "Zahlungsarten",
+    "products": "Produkte",
+    "promotions": "Promotionen",
+    "roles": "Rollen",
+    "shipping-methods": "Versandarten",
+    "system-status": "Systemstatus",
+    "tax-categories": "Steuerkategorien",
+    "tax-rates": "Steuersätze",
+    "zones": "Zonen"
+  },
+  "catalog": {
+    "add-facet-value": "Facettenwert hinzufügen",
+    "add-facets": "Facetten hinzufügen",
+    "add-option": "Option hinzufügen",
+    "assign-product-to-channel-success": "Produkt erfolgreich an \"{ channel }\" zugewiesen",
+    "assign-products-to-channel": "Produkte dem Kanal zuweisen",
+    "assign-to-channel": "Zuweisung an Kanal",
+    "assign-to-named-channel": "Zuweisen an { channelCode }",
+    "channel-price-preview": "Kanal-Preisvorschau",
+    "collection-contents": "Inhalt der Sammlung",
+    "confirm-adding-options-delete-default-body": "Das Hinzufügen von Optionen zu diesem Produkt führt dazu, dass die vorhandene Standardvariante gelöscht wird. Möchten Sie fortfahren?",
+    "confirm-adding-options-delete-default-title": "Standardvariante löschen?",
+    "confirm-delete-asset": "Asset löschen?",
+    "confirm-delete-channel": "Kanal löschen?",
+    "confirm-delete-collection": "Sammlung löschen?",
+    "confirm-delete-collection-and-children-body": "Wenn Sie diese Sammlung löschen, werden auch alle untergeordneten Sammlungen gelöscht.",
+    "confirm-delete-country": "Land löschen?",
+    "confirm-delete-facet": "Facette löschen?",
+    "confirm-delete-facet-value": "Facettenwert löschen?",
+    "confirm-delete-product": "Produkt löschen?",
+    "confirm-delete-product-variant": "Produktvariante löschen?",
+    "confirm-delete-promotion": "Werbeaktion löschen?",
+    "confirm-delete-shipping-method": "Versandart löschen?",
+    "confirm-delete-zone": "Zone löschen?",
+    "create-new-collection": "Neue Kollektion anlegen",
+    "create-new-facet": "Neue Facette erstellen",
+    "create-new-product": "Neues Produkt",
+    "created-new-variants-success": "{count, plural, one {1 neue Variante} other {{count} neue Varianten}} erfolgreich erstellt",
+    "default-variant": "Standardvariante",
+    "delete-default-variant": "Standardvariante löschen",
+    "display-variant-cards": "Details anzeigen",
+    "display-variant-table": "Tabellenansicht",
+    "drop-files-to-upload": "Dateien zum Hochladen ablegen",
+    "expand-all-collections": "Alle Sammlungen erweitern",
+    "facet-values": "Facettenwerte",
+    "filter-by-name": "Nach Name filtern",
+    "filters": "Filter",
+    "group-by-product": "Nach Produkt gruppieren",
+    "manage-variants": "Varianten verwalten",
+    "move-down": "Nach unten bewegen",
+    "move-to": "Verschieben nach",
+    "move-up": "Nach oben bewegen",
+    "no-channel-selected": "Kein Kanal ausgewählt",
+    "no-featured-asset": "Kein \"Featured Asset\"",
+    "no-selection": "Keine Auswahl",
+    "notify-remove-product-from-channel-error": "Das Produkt konnte nicht aus dem Kanal entfernt werden",
+    "notify-remove-product-from-channel-success": "Das Produkt erfolgreich aus dem Kanal entfernt",
+    "option": "Option",
+    "option-name": "Optionsname",
+    "option-values": "Optionswerte",
+    "price": "Preis",
+    "price-conversion-factor": "Preisumwandlungsfaktor",
+    "price-in-channel": "Preis in { channel }",
+    "price-includes-tax-at": "Einschließlich Steuer von { rate }%",
+    "price-with-tax-in-default-zone": "Inkl. { rate }% Steuer: { price }",
+    "private": "Privat",
+    "product-details": "Produktdetails",
+    "product-name": "Produktname",
+    "product-variants": "Produktvarianten",
+    "public": "Öffentlich",
+    "rebuild-search-index": "Suchindex neu aufbauen",
+    "reindex-error": "Beim Neuaufbau des Suchindex ist ein Fehler aufgetreten",
+    "reindex-successful": "{count, plural, one {Produktvariante} other {{count} Produktvarianten}} indiziert in {time}ms",
+    "reindexing": "Suchindex wird neu aufgebaut",
+    "remove-from-channel": "Aus dem Kanal entfernen",
+    "remove-option": "Option entfernen",
+    "remove-product-from-channel": "Produkt aus dem Kanal entfernen",
+    "search-for-term": "Suche nach Begriff",
+    "search-product-name-or-code": "Suche nach Produktname oder -code",
+    "sku": "Artikelnummer",
+    "slug": "Slug",
+    "stock-on-hand": "Bestand",
+    "tax-category": "Steuerkategorie",
+    "taxes": "Steuern",
+    "track-inventory": "Bestand verfolgen",
+    "update-product-option": "Produktoption aktualisieren",
+    "values": "Werte",
+    "variant": "Variante",
+    "view-contents": "Inhalt anzeigen",
+    "visibility": "Sichtbarkeit"
+  },
+  "common": {
+    "ID": "ID",
+    "actions": "Aktionen",
+    "add-new-variants": "{count, plural, one {1 Variante} other {{count} Varianten}} hinzufügen",
+    "available-languages": "Verfügbare Sprachen",
+    "cancel": "Abbrechen",
+    "cancel-navigation": "Navigation abbrechen",
+    "channel": "Kanal",
+    "channels": "Kanäle",
+    "code": "Code",
+    "confirm-navigation": "Navigation bestätigen",
+    "create": "Erstellen",
+    "created-at": "Erstellt am",
+    "custom-fields": "Benutzerdefinierte Felder",
+    "default-channel": "Standardkanal",
+    "default-language": "Standardsprache",
+    "delete": "Löschen",
+    "description": "Beschreibung",
+    "disabled": "Deaktiviert",
+    "discard-changes": "Änderungen verwerfen",
+    "display-custom-fields": "Benutzerdefinierte Felder anzeigen",
+    "done": "Fertig",
+    "edit": "Bearbeiten",
+    "edit-field": "Feld bearbeiten",
+    "enabled": "Aktiviert",
+    "extension-running-in-separate-window": "Die Erweiterung läuft in einem separaten Fenster",
+    "guest": "Gast",
+    "hide-custom-fields": "Benutzerdefinierte Felder ausblenden",
+    "items-per-page-option": "{ count } pro Seite",
+    "language": "Sprache",
+    "launch-extension": "Erweiterung starten",
+    "live-update": "Live-Aktualisierung",
+    "log-out": "Abmelden",
+    "login": "Anmelden",
+    "more": "Mehr...",
+    "name": "Name",
+    "no-results": "Keine Ergebnisse",
+    "not-set": "Nicht festgelegt",
+    "notify-create-error": "Ein Fehler ist aufgetreten, { entity } konnte nicht erstellt werden",
+    "notify-create-success": "{ entity } erstellt",
+    "notify-delete-error": "Ein Fehler ist aufgetreten, { entity } konnte nicht gelöscht werden",
+    "notify-delete-success": "{ entity } gelöscht",
+    "notify-save-changes-error": "Ein Fehler ist aufgetreten, Änderungen konnten nicht gespeichert werden",
+    "notify-saved-changes": "Änderungen gespeichert",
+    "notify-update-error": "Ein Fehler ist aufgetreten, { entity } konnte nicht aktualisiert werden",
+    "notify-update-success": "{ entity } aktualisiert",
+    "open": "Öffnen",
+    "password": "Passwort",
+    "price": "Preis",
+    "price-with-tax": "Preis mit Steuer",
+    "private": "Privat",
+    "public": "Öffentlich",
+    "remember-me": "Logindaten merken",
+    "remove": "Entfernen",
+    "results-count": "{ count } {count, plural, one {Ergebnis} other {Ergebnisse}}",
+    "select": "Auswählen...",
+    "select-display-language": "Anzeigesprache wählen",
+    "select-today": "Heute auswählen",
+    "there-are-unsaved-changes": "Es gibt ungespeicherte Änderungen. Wenn Sie wechseln, gehen diese Änderungen verloren.",
+    "update": "Aktualisieren",
+    "updated-at": "Aktualisiert am",
+    "username": "Benutzername",
+    "view-next-month": "Nächsten Monat anzeigen",
+    "view-previous-month": "Vorherigen Monat anzeigen",
+    "with-selected": "Auswahl..."
+  },
+  "customer": {
+    "addresses": "Adressen",
+    "city": "Stadt",
+    "country": "Land",
+    "create-new-address": "Neue Adresse anlegen",
+    "create-new-customer": "Neuen Kunden anlegen",
+    "customer-type": "Kundentyp",
+    "default-billing-address": "Standard-Abrechnung",
+    "default-shipping-address": "Standardversand",
+    "email-address": "E-Mail-Adresse",
+    "email-verification-sent": "Eine Verifizierungs-E-Mail wurde gesendet an { emailAddress }",
+    "first-name": "Vorname",
+    "full-name": "Vollständiger Name",
+    "guest": "Gast",
+    "last-name": "Nachname",
+    "name": "Name",
+    "no-orders-placed": "Keine Bestellungen aufgegeben",
+    "orders": "Bestellungen",
+    "password": "Passwort",
+    "phone-number": "Telefonnummer",
+    "postal-code": "Postleitzahl",
+    "province": "Gebiet",
+    "registered": "Registriert",
+    "search-customers-by-email": "Suche nach E-Mail-Adresse",
+    "set-as-default-billing-address": "Als Standard-Rechnungsadresse festlegen",
+    "set-as-default-shipping-address": "Als Standard-Versandadresse festlegen",
+    "street-line-1": "Straße Zeile 1",
+    "street-line-2": "Straße Zeile 2",
+    "title": "Titel",
+    "verified": "Bestätigt"
+  },
+  "datetime": {
+    "ago-days": "{count, plural, one {Vor einem Tag} other {Vor {count} Tagen}}",
+    "ago-hours": "{count, plural, one {Vor einer Stunde} other {Vor {count} Stunden}}",
+    "ago-minutes": "{count, plural, one {Vor einer Minute} other {Vor {count} Minuten}}",
+    "ago-seconds": "{count, plural, =0 {Gerade eben} one {Vor einer Sekunde} other {Vor {count} Sekunden}}",
+    "duration-milliseconds": "{ms}ms",
+    "duration-minutes:seconds": "{m}:{s}m",
+    "duration-seconds": "{s}s",
+    "month-apr": "April",
+    "month-aug": "August",
+    "month-dec": "Dezember",
+    "month-feb": "Februar",
+    "month-jan": "Januar",
+    "month-jul": "Juli",
+    "month-jun": "Juni",
+    "month-mar": "März",
+    "month-may": "Mai",
+    "month-nov": "November",
+    "month-oct": "Oktober",
+    "month-sep": "September",
+    "time": "Zeit",
+    "weekday-fr": "Fr",
+    "weekday-mo": "Mo",
+    "weekday-sa": "Sa",
+    "weekday-su": "So",
+    "weekday-th": "Do",
+    "weekday-tu": "Di",
+    "weekday-we": "Mi"
+  },
+  "editor": {
+    "image-alt": "Beschreibung ('alt')",
+    "image-src": "Quelle",
+    "image-title": "Titel",
+    "insert-image": "Bild einfügen",
+    "link-href": "Link 'href'",
+    "link-title": "Link 'title'",
+    "remove-link": "Entfernen",
+    "set-link": "Link setzen"
+  },
+  "error": {
+    "403-forbidden": "Sie sind derzeit nicht berechtigt, auf \"{ path }\" zuzugreifen. Entweder fehlen Ihnen die Berechtigungen, oder Ihre Sitzung ist abgelaufen.",
+    "could-not-connect-to-server": "Es konnte keine Verbindung zum Vendure-Server auf { url } hergestellt werden.",
+    "facet-value-form-values-do-not-match": "Die Anzahl der Werte im Facetten-Formular stimmt nicht mit der tatsächlichen Anzahl der Werte überein",
+    "health-check-failed": "Systemzustandsprüfung fehlgeschlagen",
+    "no-default-shipping-zone-set": "Dieser Kanal hat keine Standard-Versandzone. Dies kann zu Fehlern bei der Berechnung der Auftragsversandkosten führen.",
+    "no-default-tax-zone-set": "Dieser Kanal verfügt nicht über ein Standard-Steuerzone, was zu Fehlern bei der Preisberechnung führen kann. Bitte erstellen oder wählen Sie eine Zone.",
+    "product-variant-form-values-do-not-match": "Die Anzahl der Varianten im Produktformular stimmt nicht mit der tatsächlichen Anzahl der Varianten überein."
+  },
+  "lang": {
+    "aa": "Afar",
+    "ab": "Abchasisch",
+    "ae": "Avestan",
+    "af": "Afrikaans",
+    "ak": "Akan",
+    "am": "Amharisch",
+    "an": "Aragonisch",
+    "ar": "Arabisch",
+    "as": "Assamesisch",
+    "av": "Avarisch",
+    "ay": "Aymara",
+    "az": "Aserbaidschanisch",
+    "ba": "Baschkirisch",
+    "be": "Belarussisch",
+    "bg": "Bulgarisch",
+    "bh": "Bihari-Sprachen",
+    "bi": "Bislama",
+    "bm": "Bambara",
+    "bn": "Bengalisch",
+    "bo": "Tibetisch",
+    "br": "Bretonisch",
+    "bs": "Bosnisch",
+    "ca": "Katalanisch; Valencianisch",
+    "ce": "Tschetschenisch",
+    "ch": "Chamorro",
+    "co": "Korsisch",
+    "cr": "Cree",
+    "cs": "Tschechisch",
+    "cu": "Kirchenslawisch",
+    "cv": "Tschuwaschisch",
+    "cy": "Walisisch",
+    "da": "Dänisch",
+    "de": "Deutsch",
+    "dv": "Divehi; Divehi; Maledivisch",
+    "dz": "Dzongkha",
+    "ee": "Ewe",
+    "el": "Griechisch, Modern (1453-)",
+    "en": "Englisch",
+    "eo": "Esperanto",
+    "es": "Spanisch; Kastilisch",
+    "et": "Estnisch",
+    "eu": "Baskisch",
+    "fa": "Persisch",
+    "ff": "Fulah",
+    "fi": "Finnisch",
+    "fj": "Fidschianisch",
+    "fo": "Färöisch",
+    "fr": "Französisch",
+    "fy": "Westfriesisch",
+    "ga": "Irisch",
+    "gd": "Gälisch; Schottisch-Gälisch",
+    "gl": "Galizisch",
+    "gn": "Guarani",
+    "gu": "Gujarati",
+    "gv": "Manx",
+    "ha": "Hausa",
+    "he": "Hebräisch",
+    "hi": "Hindi",
+    "ho": "Hiri Motu",
+    "hr": "Kroatisch",
+    "ht": "Haitianisch; Haitianisch-Kreolisch",
+    "hu": "Ungarisch",
+    "hy": "Armenisch",
+    "hz": "Herero",
+    "ia": "Interlingua",
+    "id": "Indonesisch",
+    "ie": "Interlingue; Occidental",
+    "ig": "Igbo",
+    "ii": "Sichuan Yi; Nuosu",
+    "ik": "Inupiaq",
+    "io": "Ido",
+    "is": "Isländisch",
+    "it": "Italienisch",
+    "iu": "Inuktitut",
+    "ja": "Japanisch",
+    "jv": "Javanisch",
+    "ka": "Georgisch",
+    "kg": "Kongo",
+    "ki": "Kikuyu; Gikuyu",
+    "kj": "Kuanyama; Kwanyama",
+    "kk": "Kasachisch",
+    "kl": "Kalaallisut; Grönländisch",
+    "km": "Zentral-Khmer",
+    "kn": "Kannada",
+    "ko": "Koreanisch",
+    "kr": "Kanuri",
+    "ks": "Kaschmirisch",
+    "ku": "Kurdisch",
+    "kv": "Komi",
+    "kw": "Kornisch",
+    "ky": "Kirgisisch",
+    "la": "Lateinisch",
+    "lb": "Luxemburgisch; Letzeburgesch",
+    "lg": "Ganda",
+    "li": "Limburgisch",
+    "ln": "Lingala",
+    "lo": "Laotisch",
+    "lt": "Litauisch",
+    "lu": "Luba-Katanga",
+    "lv": "Lettisch",
+    "mg": "Madagassisch",
+    "mh": "Marshallisch",
+    "mi": "Maori",
+    "mk": "Mazedonisch",
+    "ml": "Malayalam",
+    "mn": "Mongolisch",
+    "mr": "Marathi",
+    "ms": "Malaysisch",
+    "mt": "Maltesisch",
+    "my": "Birmanisch",
+    "na": "Nauru",
+    "nb": "Bokmål, Norwegisch; Norwegisch-Bokmål",
+    "nd": "Ndebele, Norden; Nord-Ndebele",
+    "ne": "Nepalisch",
+    "ng": "Ndonga",
+    "nl": "Niederländisch; Flämisch",
+    "nn": "Norwegisch Nynorsk; Nynorsk, Norwegisch",
+    "no": "Norwegisch",
+    "nr": "Ndebele, Süden; Süd-Ndebele",
+    "nv": "Navajo; Navaho",
+    "ny": "Chichewa; Chewa; Nyanja",
+    "oc": "Okzitanisch (nach 1500); Provenzalisch",
+    "oj": "Ojibwa",
+    "om": "Oromo",
+    "or": "Oriya",
+    "os": "Ossetisch",
+    "pa": "Panjabi; Punjabi",
+    "pi": "Pali",
+    "pl": "Polnisch",
+    "ps": "Paschtu",
+    "pt": "Portugiesisch",
+    "qu": "Quechua",
+    "rm": "Rätoromanisch",
+    "rn": "Rundi",
+    "ro": "Rumänisch; Moldawisch; Moldauisch",
+    "ru": "Russisch",
+    "rw": "Kinyarwanda",
+    "sa": "Sanskrit",
+    "sc": "Sardisch",
+    "sd": "Sindhi",
+    "se": "Nordsamisch",
+    "sg": "Sango",
+    "si": "Singhalesisch",
+    "sk": "Slowakisch",
+    "sl": "Slowenisch",
+    "sm": "Samoanisch",
+    "sn": "Shona",
+    "so": "Somalisch",
+    "sq": "Albanisch",
+    "sr": "Serbisch",
+    "ss": "Swati",
+    "st": "Sotho, Süden",
+    "su": "Sundanesisch",
+    "sv": "Schwedisch",
+    "sw": "Suaheli",
+    "ta": "Tamilisch",
+    "te": "Telugu",
+    "tg": "Tadschikisch",
+    "th": "Thailändisch",
+    "ti": "Tigrinya",
+    "tk": "Turkmenisch",
+    "tl": "Tagalog",
+    "tn": "Tswana",
+    "to": "Tonga (Tonga-Inseln)",
+    "tr": "Türkisch",
+    "ts": "Tsonga",
+    "tt": "Tatarisch",
+    "tw": "Twi",
+    "ty": "Tahitianisch",
+    "ug": "Uigurisch",
+    "uk": "Ukrainisch",
+    "ur": "Urdu",
+    "uz": "Usbekisch",
+    "ve": "Venda",
+    "vi": "Vietnamesisch",
+    "vo": "Volapük",
+    "wa": "Wallonisch",
+    "wo": "Wolof",
+    "xh": "Xhosa",
+    "yi": "Jiddisch",
+    "yo": "Yoruba",
+    "za": "Zhuang; Chuang",
+    "zh": "Chinesisch",
+    "zu": "Zulu"
+  },
+  "marketing": {
+    "actions": "Aktionen",
+    "add-action": "Aktion hinzufügen",
+    "add-condition": "Bedingung hinzufügen",
+    "conditions": "Bedingungen",
+    "coupon-code": "Gutscheincode",
+    "create-new-promotion": "Neue Werbeaktion erstellen",
+    "ends-at": "Endet am",
+    "per-customer-limit": "Begrenzung pro Kunde",
+    "starts-at": "Beginnt am"
+  },
+  "nav": {
+    "administrators": "Administratoren",
+    "assets": "Assets",
+    "catalog": "Katalog",
+    "channels": "Kanäle",
+    "collections": "Sammlungen",
+    "countries": "Länder",
+    "customers": "Kunden",
+    "facets": "Facetten",
+    "global-settings": "Globale Einstellungen",
+    "job-queue": "Job-Warteschlange",
+    "marketing": "Marketing",
+    "orders": "Bestellungen",
+    "payment-methods": "Zahlungsarten",
+    "products": "Produkte",
+    "promotions": "Werbeaktionen",
+    "roles": "Rollen",
+    "sales": "Verkäufe",
+    "settings": "Einstellungen",
+    "shipping-methods": "Versandarten",
+    "system": "System",
+    "system-status": "Systemstatus",
+    "tax-categories": "Steuerkategorien",
+    "tax-rates": "Steuersätze",
+    "zones": "Zonen"
+  },
+  "order": {
+    "add-note": "Notiz hinzufügen",
+    "add-note-success": "Notiz erfolgreich hinzugefügt",
+    "amount": "Betrag",
+    "cancel": "Abbrechen",
+    "cancel-order": "Bestellung stornieren",
+    "cancel-reason-customer-request": "Kundenanfrage",
+    "cancel-reason-not-available": "Nicht verfügbar",
+    "cancel-selected-items": "Auswahl aufheben",
+    "cancellation-reason": "Stornierungsgrund",
+    "cancelled-order-success": "Bestellung erfolgreich storniert",
+    "contents": "Inhalt",
+    "create-fulfillment": "Auftrag ausführen",
+    "create-fulfillment-success": "Auftrag ausgeführt",
+    "customer": "Kunde",
+    "details": "Details",
+    "fulfill": "Ausführen",
+    "fulfill-order": "Auftragsausführung",
+    "fulfillment": "Ausführung",
+    "fulfillment-method": "Ausführungsart",
+    "history-coupon-code-applied": "Gutscheincode aktiviert",
+    "history-coupon-code-removed": "Gutscheincode entfernt",
+    "history-fulfillment-created": "Auftrag ausgeführt",
+    "history-items-cancelled": "{count} {count, plural, one {Artikel} other {Artikel}} gestrichen",
+    "history-order-cancelled": "Bestellung storniert",
+    "history-order-fulfilled": "Auftrag ausgeführt",
+    "history-order-transition": "Auftragsstatus von {from} nach {to}",
+    "history-payment-settled": "Bezahlt",
+    "history-payment-transition": "Zahlungsstatus (#{id}) von {from} nach {to}",
+    "history-refund-transition": "Rückzahlungsstatus (#{id}) von {from} nach {to}",
+    "item-count": "{count} {count, plural, one {Artikel} other {Artikel}}",
+    "line-fulfillment-all": "Alle Positionen ausgeführt",
+    "line-fulfillment-none": "Keine Positionen ausgeführt",
+    "line-fulfillment-partial": "{ count } von { total } Positionen ausgeführt",
+    "net-price": "Nettopreis",
+    "note-is-private": "Notiz ist privat",
+    "note-only-visible-to-administrators": "Nur für Administratoren sichtbar",
+    "note-visible-to-customer": "Sichtbar für Administratoren und Kunden",
+    "order-history": "Bestellhistorie",
+    "payment": "Zahlung",
+    "payment-amount": "Zahlungsbetrag",
+    "payment-metadata": "Metadaten zur Bezahlung",
+    "payment-method": "Zahlungsart",
+    "payment-state": "Status",
+    "payment-to-refund": "Zu erstattende Zahlung",
+    "product-name": "Produktname",
+    "product-sku": "Artikelnummer",
+    "promotions-applied": "Aktivierte Werbeaktionen",
+    "quantity": "Anzahl",
+    "refund": "Rückzahlung",
+    "refund-adjustment": "Anpassung",
+    "refund-and-cancel-order": "Rückzahlung & Stornierung der Bestellung",
+    "refund-metadata": "Metadaten zur Rückzahlung",
+    "refund-order": "Bestellung zurückzahlen",
+    "refund-order-success": "Bestellung erfolgreich zurückgezahlt",
+    "refund-reason": "Rückzahlungsgrund",
+    "refund-reason-customer-request": "Kundenanfrage",
+    "refund-reason-not-available": "Nicht verfügbar",
+    "refund-reason-required": "Rückzahlungsgrund ist erforderlich",
+    "refund-shipping": "Versandkosten erstatten",
+    "refund-total": "Rückzahlung gesamt",
+    "refund-total-error": "Die Erstattungssumme muss zwischen {min} und {max} liegen",
+    "refund-with-amount": "Rückzahlung {amount}",
+    "refunded-count": "{count} {count, plural, one {Artikel} other {Artikel}} erstattet",
+    "return-to-stock": "Zum Lagerbestand hinzufügen",
+    "search-by-order-code": "Suche nach Bestellcode",
+    "settle-payment": "Zahlung durchführen",
+    "settle-payment-error": "Die Zahlung konnte nicht durchgeführt werden",
+    "settle-payment-success": "Zahlung erfolgreich durchgeführt",
+    "settle-refund": "Rückzahlung durchführen",
+    "settle-refund-manual-instructions": "Geben Sie hier nach der manuellen Rückzahlung über Ihren Zahlungsanbieter ({method}) die Transaktions-ID ein.",
+    "settle-refund-success": "Rückzahlung erfolgreich durchgeführt",
+    "shipping": "Versand",
+    "shipping-address": "Lieferadresse",
+    "shipping-method": "Versandart",
+    "state": "Status",
+    "state-adding-items": "Artikel hinzufügen",
+    "state-all-orders": "Alle Bestellungen",
+    "state-arranging-payment": "Zahlung einrichten",
+    "state-cancelled": "Storniert",
+    "state-fulfilled": "Ausgeführt",
+    "state-partially-fulfilled": "Teilweise ausgeführt",
+    "state-payment-authorized": "Zahlung autorisiert",
+    "state-payment-settled": "Bezahlt",
+    "sub-total": "Zwischensumme",
+    "total": "Gesamtsumme",
+    "tracking-code": "Sendungsverfolgungscode",
+    "transaction-id": "Transaktions-ID",
+    "unfulfilled": "Nicht ausgeführt",
+    "unit-price": "Einzelpreis"
+  },
+  "settings": {
+    "add-countries-to-zone": "Länder hinzufügen zu { zoneName }",
+    "add-countries-to-zone-success": "{ countryCount } {countryCount, plural, one {Land} other {Länder}} hinzugefügt zu \"{ zoneName }\"",
+    "add-products-to-test-order": "Produkte zur Testbestellung hinzufügen",
+    "administrator": "Administrator",
+    "catalog": "Katalog",
+    "channel": "Kanal",
+    "channel-token": "Kanal-Token",
+    "confirm-delete-role": "Rolle löschen?",
+    "confirm-delete-tax-category": "Steuerkategorie löschen?",
+    "confirm-delete-tax-rate": "Steuersatz löschen?",
+    "create": "Erstellen",
+    "create-new-channel": "Neuen Kanal erstellen",
+    "create-new-country": "Neues Land erstellen",
+    "create-new-role": "Neue Rolle erstellen",
+    "create-new-shipping-method": "Neue Versandart erstellen",
+    "create-new-tax-category": "Neue Steuerkategorie erstellen",
+    "create-new-tax-rate": "Neuen Steuersatz erstellen",
+    "create-new-zone": "Neue Zone erstellen",
+    "create-zone": "Zone erstellen",
+    "currency": "Währung",
+    "customer": "Kunde",
+    "default-role-label": "Dies ist eine Standardrolle und kann nicht geändert werden.",
+    "default-shipping-zone": "Standard-Versandzone",
+    "default-tax-zone": "Standard-Steuerzone",
+    "delete": "Löschen",
+    "eligible": "Verfügbar",
+    "email-address": "E-Mail-Adresse",
+    "filter-by-member-name": "Nach Land filtern",
+    "first-name": "Vorname",
+    "last-name": "Nachname",
+    "no-eligible-shipping-methods": "Keine verfügbaren Versandarten",
+    "order": "Bestellung",
+    "password": "Passwort",
+    "payment-method-config-options": "Konfiguration der Zahlungsart",
+    "permissions": "Berechtigungen",
+    "prices-include-tax": "Preise enthalten die Steuer für die Standardzone",
+    "promotion": "Werbeaktion",
+    "rate": "Steuersatz",
+    "read": "Lesen",
+    "remove-countries-from-zone-success": "{ countryCount } {countryCount, plural, one {Land} other {Länder}} entfernt aus \"{ zoneName }\"",
+    "remove-from-zone": "Aus Zone entfernen",
+    "roles": "Rollen",
+    "search-by-product-name-or-sku": "Suche nach Produktname oder Artikelnummer",
+    "search-country-by-name": "Länder nach Namen suchen",
+    "section": "Bereich",
+    "settings": "Einstellungen",
+    "shipping-calculator": "Versandkostenrechner",
+    "shipping-eligibility-checker": "Verfügbarkeit der Versandart prüfen",
+    "shipping-method": "Versandart",
+    "tax-category": "Steuerkategorie",
+    "tax-rate": "Steuersatz",
+    "test-address": "Test-Adresse",
+    "test-order": "Test-Bestellung",
+    "test-result": "Test-Ergebnis",
+    "test-shipping-method": "Test-Versandart",
+    "test-shipping-methods": "Test-Versandarten",
+    "track-inventory-default": "Bestand standardmäßig verfolgen",
+    "update": "Aktualisieren",
+    "update-zone": "Zone aktualisieren",
+    "view-zone-members": "Mitglieder anzeigen",
+    "zone": "Zone"
+  },
+  "system": {
+    "all-job-queues": "Alle Job-Warteschlangen",
+    "health-all-systems-up": "Alle Systeme betriesbereit",
+    "health-error": "Fehler: Ein oder mehrere Systeme sind ausgefallen!",
+    "health-last-checked": "Zuletzt überprüft",
+    "health-message": "Nachricht",
+    "health-refresh": "Aktualisieren",
+    "health-status": "Status",
+    "health-status-down": "Ausgefallen",
+    "health-status-up": "Betriesbereit",
+    "hide-settled-jobs": "Abgeschlossene Jobs ausblenden",
+    "job-data": "Job-Daten",
+    "job-duration": "Job-Dauer",
+    "job-error": "Job-Fehler",
+    "job-queue-name": "Name der Warteschlange",
+    "job-result": "Job-Ergebnis",
+    "job-state": "Job-Status"
+  }
+}

+ 1 - 1
packages/admin-ui/src/lib/static/vendure-ui-config.json

@@ -5,5 +5,5 @@
   "tokenMethod": "cookie",
   "authTokenHeaderKey": "vendure-auth-token",
   "defaultLanguage": "en",
-  "availableLanguages": ["en", "es", "zh", "pl"]
+  "availableLanguages": ["en", "es", "zh", "pl", "de"]
 }

+ 2 - 2
packages/asset-server-plugin/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@vendure/asset-server-plugin",
-  "version": "0.12.3",
+  "version": "0.12.5",
   "main": "lib/index.js",
   "types": "lib/index.d.ts",
   "files": [
@@ -23,7 +23,7 @@
     "@types/node-fetch": "^2.5.4",
     "@types/sharp": "^0.24.0",
     "@vendure/common": "^0.12.3",
-    "@vendure/core": "^0.12.3",
+    "@vendure/core": "^0.12.5",
     "aws-sdk": "^2.670.0",
     "express": "^4.16.4",
     "node-fetch": "^2.6.0",

+ 1 - 1
packages/core/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@vendure/core",
-  "version": "0.12.3",
+  "version": "0.12.5",
   "description": "A modern, headless ecommerce framework",
   "repository": {
     "type": "git",

+ 2 - 2
packages/create/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@vendure/create",
-  "version": "0.12.3",
+  "version": "0.12.5",
   "license": "MIT",
   "bin": {
     "create": "./index.js"
@@ -27,7 +27,7 @@
     "@types/listr": "^0.14.0",
     "@types/semver": "^6.0.0",
     "@vendure/common": "^0.12.3",
-    "@vendure/core": "^0.12.3",
+    "@vendure/core": "^0.12.5",
     "rimraf": "^3.0.0",
     "ts-node": "^8.4.1",
     "typescript": "3.8.3"

+ 8 - 8
packages/dev-server/package.json

@@ -1,6 +1,6 @@
 {
   "name": "dev-server",
-  "version": "0.12.4",
+  "version": "0.12.5",
   "main": "index.js",
   "license": "MIT",
   "private": true,
@@ -14,18 +14,18 @@
     "load-test:100k": "node -r ts-node/register load-testing/run-load-test.ts 100000"
   },
   "dependencies": {
-    "@vendure/admin-ui-plugin": "^0.12.4",
-    "@vendure/asset-server-plugin": "^0.12.3",
+    "@vendure/admin-ui-plugin": "^0.12.5",
+    "@vendure/asset-server-plugin": "^0.12.5",
     "@vendure/common": "^0.12.3",
-    "@vendure/core": "^0.12.3",
-    "@vendure/elasticsearch-plugin": "^0.12.3",
-    "@vendure/email-plugin": "^0.12.3",
+    "@vendure/core": "^0.12.5",
+    "@vendure/elasticsearch-plugin": "^0.12.5",
+    "@vendure/email-plugin": "^0.12.5",
     "typescript": "3.8.3"
   },
   "devDependencies": {
     "@types/csv-stringify": "^3.1.0",
-    "@vendure/testing": "^0.12.3",
-    "@vendure/ui-devkit": "^0.12.4",
+    "@vendure/testing": "^0.12.5",
+    "@vendure/ui-devkit": "^0.12.5",
     "concurrently": "^5.0.0",
     "csv-stringify": "^5.3.3"
   }

+ 2 - 2
packages/elasticsearch-plugin/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@vendure/elasticsearch-plugin",
-  "version": "0.12.3",
+  "version": "0.12.5",
   "license": "MIT",
   "main": "lib/index.js",
   "types": "lib/index.d.ts",
@@ -23,7 +23,7 @@
   },
   "devDependencies": {
     "@vendure/common": "^0.12.3",
-    "@vendure/core": "^0.12.3",
+    "@vendure/core": "^0.12.5",
     "rimraf": "^3.0.0",
     "typescript": "3.8.3"
   }

+ 2 - 2
packages/email-plugin/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@vendure/email-plugin",
-  "version": "0.12.3",
+  "version": "0.12.5",
   "license": "MIT",
   "main": "lib/index.js",
   "types": "lib/index.d.ts",
@@ -34,7 +34,7 @@
     "@types/mjml": "^4.0.2",
     "@types/nodemailer": "^6.4.0",
     "@vendure/common": "^0.12.3",
-    "@vendure/core": "^0.12.3",
+    "@vendure/core": "^0.12.5",
     "rimraf": "^3.0.0",
     "typescript": "3.8.3"
   }

+ 2 - 2
packages/testing/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@vendure/testing",
-  "version": "0.12.3",
+  "version": "0.12.5",
   "description": "End-to-end testing tools for Vendure projects",
   "keywords": [
     "vendure",
@@ -44,7 +44,7 @@
   "devDependencies": {
     "@types/mysql": "^2.15.8",
     "@types/pg": "^7.14.1",
-    "@vendure/core": "^0.12.3",
+    "@vendure/core": "^0.12.5",
     "mysql": "^2.17.1",
     "pg": "^7.17.1",
     "rimraf": "^3.0.0",

+ 3 - 3
packages/ui-devkit/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@vendure/ui-devkit",
-  "version": "0.12.4",
+  "version": "0.12.5",
   "description": "A library for authoring Vendure Admin UI extensions",
   "keywords": [
     "vendure",
@@ -39,7 +39,7 @@
     "@angular/cli": "^9.0.5",
     "@angular/compiler": "^9.0.6",
     "@angular/compiler-cli": "^9.0.6",
-    "@vendure/admin-ui": "^0.12.4",
+    "@vendure/admin-ui": "^0.12.5",
     "@vendure/common": "^0.12.3",
     "chalk": "^3.0.0",
     "chokidar": "^3.3.1",
@@ -51,7 +51,7 @@
     "@rollup/plugin-node-resolve": "^7.1.1",
     "@types/fs-extra": "^8.1.0",
     "@types/glob": "^7.1.1",
-    "@vendure/core": "^0.12.3",
+    "@vendure/core": "^0.12.5",
     "rimraf": "^3.0.0",
     "rollup": "^2.2.0",
     "rollup-plugin-terser": "^5.3.0",