diff --git a/.circleci/config.yml b/.circleci/config.yml
index d9d60499..f1896f32 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -4,9 +4,15 @@ executors:
php-5_6:
docker:
- image: circleci/php:5.6
+ auth:
+ username: $DOCKERHUB_USERNAME
+ password: $DOCKERHUB_TOKEN
php-7_2:
docker:
- image: circleci/php:7.2
+ auth:
+ username: $DOCKERHUB_USERNAME
+ password: $DOCKERHUB_TOKEN
jobs:
tests-5_6:
executor: php-5_6
@@ -42,10 +48,14 @@ workflows:
ecommerce_module_core:
jobs:
- tests-5_6:
+ context:
+ - packlink-dockerhub
filters:
tags:
only: /.*/
- tests-7_2:
+ context:
+ - packlink-dockerhub
filters:
tags:
only: /.*/
diff --git a/.gitignore b/.gitignore
index fe359f21..14d70a79 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,4 @@
.idea/*
# Custom content
-vendor
\ No newline at end of file
+vendor
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5cae85ce..2921d8e7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,30 +3,71 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
-## Unreleased
+## [3.1.1](https://github.com/packlink-dev/ecommerce_module_core/compare/v3.1.0...v3.1.1) - 2021-03-26
### Added
- Added additional ISO codes to the postal code transformer.
+- Added missing carrier logos for Italy and Spain.
-## [2.3.0](https://github.com/packlink-dev/ecommerce_module_core/compare/v2.2.2...v2.3.0) - 2020-12-17
+### Changed
+- Changed setting the language based on user's platform country instead of current shop language during the registration process.
+
+## [3.1.0](https://github.com/packlink-dev/ecommerce_module_core/compare/v3.0.6...v3.1.0) - 2020-12-11
### Added
- Added postal code transformer service that transforms postal code into supported postal code format for some countries.
+- Added missing carrier logo for DPD Portugal.
### Changed
+- Changed how the default parcel is validated.
- Changed logic in the shipping cost calculator to use postal code transformer for the delivery postal code before retrieving services from the Packlink API.
- Separated country service into two services which deal with registration and warehouse countries separately. Separated country DTO into two DTOs, with base country DTO and registration country DTO, which adds additional information (registration link and platform country).
- Modified user account service, update shipping services task, and warehouse controller to work with warehouse country service instead of country service.
-## [2.2.2](https://github.com/packlink-dev/ecommerce_module_core/compare/v2.2.1...v2.2.2) - 2020-02-28
+## [3.0.6](https://github.com/packlink-dev/ecommerce_module_core/compare/v3.0.5...v3.0.6) - 2020-11-05
+### Added
+- Added missing carrier logos. Integrations should refresh their shipping services after updating to this Core version in order to assign these logos to their respective shipping services.
+- Fixed setting warehouse postal code and city from the module
+
+## [3.0.5](https://github.com/packlink-dev/ecommerce_module_core/compare/v3.0.4...v3.0.5) - 2020-10-21
+### Changed
+- Fix issue with execution starting logic of multiple non-recurring schedules
+
+## [3.0.4](https://github.com/packlink-dev/ecommerce_module_core/compare/v3.0.3...v3.0.4) - 2020-10-09
+### Changed
+- Fix issue with phone validation.
+- Send setup event when first service is activated.
+
+## [3.0.3](https://github.com/packlink-dev/ecommerce_module_core/compare/v3.0.2...v3.0.3) - 2020-09-23
+### Changed
+- Ajax service request headers enhancements
+
+## [3.0.2](https://github.com/packlink-dev/ecommerce_module_core/compare/v3.0.1...v3.0.2) - 2020-09-10
+### Changed
+- Fix get service url.
+- Fix issue with adding backup service.
+- Fix deserialization of Shipping Method Configuration.
+
+## [3.0.1](https://github.com/packlink-dev/ecommerce_module_core/compare/v3.0.0...v3.0.1) - 2020-08-31
+### Changed
+- Fix origin and destination icon size on services page.
+- Fix icons on the settings page.
+- Fix issue with adding a query parameter to url in register controller.
+- Fix translation issue in italian.
+
+## [3.0.0](https://github.com/packlink-dev/ecommerce_module_core/compare/v2.2.2...v3.0.0) - 2020-08-25
+### Changed
+- Module redesign with new pricing policy.
+
+## [2.2.2](https://github.com/packlink-dev/ecommerce_module_core/compare/v2.2.1...v2.2.2) - 2020-08-28
### Changed
- Fix bug in weekly schedule for schedules setup to run on Sundays
-## [2.2.1](https://github.com/packlink-dev/ecommerce_module_core/compare/v2.2.0...v2.2.1) - 2020-02-28
+## [2.2.1](https://github.com/packlink-dev/ecommerce_module_core/compare/v2.2.0...v2.2.1) - 2020-07-28
### Changed
- Prevent schedule check task from being enqueued if not necessary
-## [2.2.0](https://github.com/packlink-dev/ecommerce_module_core/compare/v2.1.3...v2.2.0) - 2020-02-22
+## [2.2.0](https://github.com/packlink-dev/ecommerce_module_core/compare/v2.1.3...v2.2.0) - 2020-07-22
### Changed
-- `UpdateShipmentData` task has been declared as depricated.
+- `UpdateShipmentData` task has been declared as deprecated.
- `UpdateShipmentData` task will not be scheduled anymore in core.
- BREAKING: Methods `isFirstShipmentDraftCreated` and `setFirstShipmentDraftCreated` have been removed from `Configuration`
Integration should check if said methods have been utilized and remove them.
diff --git a/README.md b/README.md
index 46714b93..39718b61 100644
--- a/README.md
+++ b/README.md
@@ -26,3 +26,7 @@ Also, in commit dialog you must choose at least these options:
- Check TODO
This will also run analysis on commit but only on changed files.
+
+### Resource compilation
+To compile resources in the root directory execute the following command:
+`php cssCompile.php`
diff --git a/composer.json b/composer.json
index bf84f479..6142cf94 100755
--- a/composer.json
+++ b/composer.json
@@ -4,7 +4,8 @@
"type": "library",
"license": "proprietary",
"require": {
- "php": ">=5.3.29"
+ "php": ">=5.3.29",
+ "ext-json": "*"
},
"autoload": {
"psr-4": {
@@ -20,8 +21,13 @@
},
"require-dev": {
"phpunit/phpunit": "^4.8",
- "codacy/coverage": "dev-master"
+ "codacy/coverage": "dev-master",
+ "leafo/scssphp": "0.0.12"
},
+ "scripts": {
+ "post-update-cmd": "php cssCompile.php",
+ "post-install-cmd": "php cssCompile.php"
+ },
"config": {
"platform": {
"php": "5.3.29"
diff --git a/composer.lock b/composer.lock
index 29d46076..948e2a82 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "e23c2abc6fc4e33b3c1a1124b452c8e4",
+ "content-hash": "e70fd0300951d4a23480d19750532e6d",
"packages": [],
"packages-dev": [
{
@@ -13,20 +13,21 @@
"source": {
"type": "git",
"url": "https://github.com/codacy/php-codacy-coverage.git",
- "reference": "629d1fd597f91fb072bd822830059fd5145ce49a"
+ "reference": "656913b35e22ae0d1ec352bc00e3ad90616efb7a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/codacy/php-codacy-coverage/zipball/629d1fd597f91fb072bd822830059fd5145ce49a",
- "reference": "629d1fd597f91fb072bd822830059fd5145ce49a",
+ "url": "https://api.github.com/repos/codacy/php-codacy-coverage/zipball/656913b35e22ae0d1ec352bc00e3ad90616efb7a",
+ "reference": "656913b35e22ae0d1ec352bc00e3ad90616efb7a",
"shasum": ""
},
"require": {
"gitonomy/gitlib": ">=1.0",
"php": ">=5.3.3",
- "symfony/console": "~2.5|~3.0|~4.0"
+ "symfony/console": "~2.5|~3.0|~4.0|~5.0"
},
"require-dev": {
+ "clue/phar-composer": "^1.1",
"phpunit/phpunit": "~6.5"
},
"bin": [
@@ -50,7 +51,8 @@
],
"description": "Sends PHP test coverage information to Codacy.",
"homepage": "https://github.com/codacy/php-codacy-coverage",
- "time": "2018-04-30T16:23:12+00:00"
+ "abandoned": true,
+ "time": "2020-02-11T15:55:24+00:00"
},
{
"name": "doctrine/instantiator",
@@ -162,6 +164,53 @@
"homepage": "http://gitonomy.com",
"time": "2019-06-23T09:49:01+00:00"
},
+ {
+ "name": "leafo/scssphp",
+ "version": "v0.0.12",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/leafo/scssphp.git",
+ "reference": "ff76df3e45af45e808f3fcd516a2cb5cbc77f45e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/leafo/scssphp/zipball/ff76df3e45af45e808f3fcd516a2cb5cbc77f45e",
+ "reference": "ff76df3e45af45e808f3fcd516a2cb5cbc77f45e",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.2.0"
+ },
+ "require-dev": {
+ "php": ">=5.3.0",
+ "phpunit/phpunit": "3.7.*"
+ },
+ "bin": [
+ "pscss"
+ ],
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "scss.inc.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT",
+ "GPL-3.0"
+ ],
+ "authors": [
+ {
+ "name": "Leaf Corcoran",
+ "email": "leafot@gmail.com",
+ "homepage": "http://leafo.net"
+ }
+ ],
+ "description": "scssphp is a compiler for SCSS written in PHP.",
+ "homepage": "http://leafo.net/scssphp/",
+ "abandoned": "scssphp/scssphp",
+ "time": "2014-07-07T01:51:39+00:00"
+ },
{
"name": "phpdocumentor/reflection-docblock",
"version": "2.0.5",
@@ -213,33 +262,33 @@
},
{
"name": "phpspec/prophecy",
- "version": "1.8.1",
+ "version": "v1.10.3",
"source": {
"type": "git",
"url": "https://github.com/phpspec/prophecy.git",
- "reference": "1927e75f4ed19131ec9bcc3b002e07fb1173ee76"
+ "reference": "451c3cd1418cf640de218914901e51b064abb093"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpspec/prophecy/zipball/1927e75f4ed19131ec9bcc3b002e07fb1173ee76",
- "reference": "1927e75f4ed19131ec9bcc3b002e07fb1173ee76",
+ "url": "https://api.github.com/repos/phpspec/prophecy/zipball/451c3cd1418cf640de218914901e51b064abb093",
+ "reference": "451c3cd1418cf640de218914901e51b064abb093",
"shasum": ""
},
"require": {
"doctrine/instantiator": "^1.0.2",
"php": "^5.3|^7.0",
- "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0",
- "sebastian/comparator": "^1.1|^2.0|^3.0",
- "sebastian/recursion-context": "^1.0|^2.0|^3.0"
+ "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0|^5.0",
+ "sebastian/comparator": "^1.2.3|^2.0|^3.0|^4.0",
+ "sebastian/recursion-context": "^1.0|^2.0|^3.0|^4.0"
},
"require-dev": {
- "phpspec/phpspec": "^2.5|^3.2",
+ "phpspec/phpspec": "^2.5 || ^3.2",
"phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.8.x-dev"
+ "dev-master": "1.10.x-dev"
}
},
"autoload": {
@@ -272,7 +321,7 @@
"spy",
"stub"
],
- "time": "2019-06-13T12:50:23+00:00"
+ "time": "2020-03-05T15:02:03+00:00"
},
{
"name": "phpunit/php-code-coverage",
@@ -653,16 +702,16 @@
},
{
"name": "psr/log",
- "version": "1.1.0",
+ "version": "1.1.3",
"source": {
"type": "git",
"url": "https://github.com/php-fig/log.git",
- "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd"
+ "reference": "0f73288fd15629204f9d42b7055f72dacbe811fc"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/php-fig/log/zipball/6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd",
- "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd",
+ "url": "https://api.github.com/repos/php-fig/log/zipball/0f73288fd15629204f9d42b7055f72dacbe811fc",
+ "reference": "0f73288fd15629204f9d42b7055f72dacbe811fc",
"shasum": ""
},
"require": {
@@ -671,7 +720,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.0.x-dev"
+ "dev-master": "1.1.x-dev"
}
},
"autoload": {
@@ -696,7 +745,7 @@
"psr",
"psr-3"
],
- "time": "2018-11-20T15:27:04+00:00"
+ "time": "2020-03-23T09:12:05+00:00"
},
{
"name": "sebastian/comparator",
@@ -1072,7 +1121,7 @@
},
{
"name": "symfony/console",
- "version": "v2.8.50",
+ "version": "v2.8.52",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
@@ -1129,11 +1178,11 @@
],
"description": "Symfony Console Component",
"homepage": "https://symfony.com",
- "time": "2019-06-05T11:33:52+00:00"
+ "time": "2018-11-20T15:55:20+00:00"
},
{
"name": "symfony/debug",
- "version": "v2.8.50",
+ "version": "v2.8.52",
"source": {
"type": "git",
"url": "https://github.com/symfony/debug.git",
@@ -1186,20 +1235,20 @@
],
"description": "Symfony Debug Component",
"homepage": "https://symfony.com",
- "time": "2019-06-18T21:26:03+00:00"
+ "time": "2018-11-11T11:18:13+00:00"
},
{
"name": "symfony/polyfill-ctype",
- "version": "v1.11.0",
+ "version": "v1.17.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
- "reference": "82ebae02209c21113908c229e9883c419720738a"
+ "reference": "e94c8b1bbe2bc77507a1056cdb06451c75b427f9"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/82ebae02209c21113908c229e9883c419720738a",
- "reference": "82ebae02209c21113908c229e9883c419720738a",
+ "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/e94c8b1bbe2bc77507a1056cdb06451c75b427f9",
+ "reference": "e94c8b1bbe2bc77507a1056cdb06451c75b427f9",
"shasum": ""
},
"require": {
@@ -1211,7 +1260,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.11-dev"
+ "dev-master": "1.17-dev"
}
},
"autoload": {
@@ -1227,13 +1276,13 @@
"MIT"
],
"authors": [
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
- },
{
"name": "Gert de Pagter",
"email": "BackEndTea@gmail.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for ctype functions",
@@ -1244,20 +1293,20 @@
"polyfill",
"portable"
],
- "time": "2019-02-06T07:57:58+00:00"
+ "time": "2020-05-12T16:14:59+00:00"
},
{
"name": "symfony/polyfill-mbstring",
- "version": "v1.11.0",
+ "version": "v1.17.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
- "reference": "fe5e94c604826c35a32fa832f35bd036b6799609"
+ "reference": "fa79b11539418b02fc5e1897267673ba2c19419c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fe5e94c604826c35a32fa832f35bd036b6799609",
- "reference": "fe5e94c604826c35a32fa832f35bd036b6799609",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fa79b11539418b02fc5e1897267673ba2c19419c",
+ "reference": "fa79b11539418b02fc5e1897267673ba2c19419c",
"shasum": ""
},
"require": {
@@ -1269,7 +1318,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.11-dev"
+ "dev-master": "1.17-dev"
}
},
"autoload": {
@@ -1303,11 +1352,11 @@
"portable",
"shim"
],
- "time": "2019-02-06T07:57:58+00:00"
+ "time": "2020-05-12T16:47:27+00:00"
},
{
"name": "symfony/process",
- "version": "v2.8.50",
+ "version": "v2.8.52",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
@@ -1352,11 +1401,11 @@
],
"description": "Symfony Process Component",
"homepage": "https://symfony.com",
- "time": "2019-05-30T15:47:52+00:00"
+ "time": "2018-11-11T11:18:13+00:00"
},
{
"name": "symfony/yaml",
- "version": "v2.8.50",
+ "version": "v2.8.52",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
@@ -1413,7 +1462,8 @@
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
- "php": ">=5.3"
+ "php": ">=5.3.29",
+ "ext-json": "*"
},
"platform-dev": [],
"platform-overrides": {
diff --git a/cssCompile.php b/cssCompile.php
new file mode 100644
index 00000000..72c60349
--- /dev/null
+++ b/cssCompile.php
@@ -0,0 +1,36 @@
+setImportPaths('src/BusinessLogic/Resources/scss/');
+ $scss->setFormatter('scss_formatter');
+
+ createDir($dst);
+
+ $dstFileName = $dst . '/app.css';
+ file_put_contents($dstFileName, '');
+
+ $compiledCss = $scss->compile(file_get_contents("{$src}/app.scss"));
+ $existingContent = file_get_contents($dstFileName);
+ file_put_contents($dstFileName, $existingContent . $compiledCss);
+}
+
+/**
+ * Creates directory.
+ *
+ * @param string $destination
+ */
+function createDir($destination)
+{
+ if (!file_exists($destination) && !mkdir($destination) && !is_dir($destination)) {
+ throw new RuntimeException(sprintf('Directory "%s" was not created', $destination));
+ }
+}
diff --git a/phpunit.xml b/phpunit.xml
index 0824c83c..e091d15c 100755
--- a/phpunit.xml
+++ b/phpunit.xml
@@ -10,7 +10,11 @@
- ./src
+ ./src/BusinessLogic
+ ./src/Infrastructure
+
+ ./src/DemoUI
+
diff --git a/src/BusinessLogic/BootstrapComponent.php b/src/BusinessLogic/BootstrapComponent.php
index 50798b72..4fb94eaa 100644
--- a/src/BusinessLogic/BootstrapComponent.php
+++ b/src/BusinessLogic/BootstrapComponent.php
@@ -2,6 +2,7 @@
namespace Packlink\BusinessLogic;
+use Logeecom\Infrastructure\AutoTest\AutoTestService;
use Logeecom\Infrastructure\Http\HttpClient;
use Logeecom\Infrastructure\ServiceRegister;
use Logeecom\Infrastructure\TaskExecution\TaskEvents\TickEvent;
@@ -17,6 +18,8 @@
use Packlink\BusinessLogic\DTO\ValidationError;
use Packlink\BusinessLogic\Http\DTO\ParcelInfo;
use Packlink\BusinessLogic\Http\Proxy;
+use Packlink\BusinessLogic\Language\Interfaces\TranslationService as TranslationServiceInterface;
+use Packlink\BusinessLogic\Language\TranslationService;
use Packlink\BusinessLogic\Location\LocationService;
use Packlink\BusinessLogic\Order\OrderService;
use Packlink\BusinessLogic\OrderShipmentDetails\OrderShipmentDetailsService;
@@ -26,6 +29,7 @@
use Packlink\BusinessLogic\Scheduler\ScheduleTickHandler;
use Packlink\BusinessLogic\ShipmentDraft\OrderSendDraftTaskMapService;
use Packlink\BusinessLogic\ShipmentDraft\ShipmentDraftService;
+use Packlink\BusinessLogic\ShippingMethod\Models\ShippingPricePolicy;
use Packlink\BusinessLogic\ShippingMethod\PackageTransformer;
use Packlink\BusinessLogic\ShippingMethod\ShippingMethodService;
use Packlink\BusinessLogic\User\UserAccountService;
@@ -165,6 +169,20 @@ function () {
return RegistrationService::getInstance();
}
);
+
+ ServiceRegister::registerService(
+ TranslationServiceInterface::CLASS_NAME,
+ function () {
+ return new TranslationService();
+ }
+ );
+
+ ServiceRegister::registerService(
+ AutoTestService::CLASS_NAME,
+ function () {
+ return new AutoTestService();
+ }
+ );
}
/**
@@ -202,5 +220,6 @@ protected static function initDtoRegistry()
FrontDtoFactory::register(RegistrationCountry::CLASS_KEY, RegistrationCountry::CLASS_NAME);
FrontDtoFactory::register(RegistrationRequest::CLASS_KEY, RegistrationRequest::CLASS_NAME);
FrontDtoFactory::register(RegistrationLegalPolicy::CLASS_KEY, RegistrationLegalPolicy::CLASS_NAME);
+ FrontDtoFactory::register(ShippingPricePolicy::CLASS_KEY, ShippingPricePolicy::CLASS_NAME);
}
}
diff --git a/src/BusinessLogic/Controllers/AutoTestController.php b/src/BusinessLogic/Controllers/AutoTestController.php
new file mode 100644
index 00000000..e9d8a176
--- /dev/null
+++ b/src/BusinessLogic/Controllers/AutoTestController.php
@@ -0,0 +1,91 @@
+service = ServiceRegister::getService(AutoTestService::CLASS_NAME);
+ }
+
+ /**
+ * Starts autotest.
+ *
+ * @return array
+ */
+ public function start()
+ {
+ try {
+ $status = array('success' => true, 'itemId' => $this->service->startAutoTest());
+ } catch (Exception $e) {
+ $status = array('success' => false, 'error' => $e->getMessage());
+ }
+
+ return $status;
+ }
+
+ /**
+ * Stops autotest mode.
+ *
+ * @param callable $loggerInitializer Method that will be used to re-register proper shop logger service.
+ */
+ public function stop(callable $loggerInitializer)
+ {
+ $this->service->stopAutoTestMode($loggerInitializer);
+ }
+
+ /**
+ * Retrieves autotest status.
+ *
+ * @param int $id Auto test task id.
+ *
+ * @return array
+ *
+ * @throws \Logeecom\Infrastructure\ORM\Exceptions\QueryFilterInvalidParamException
+ * @throws \Logeecom\Infrastructure\ORM\Exceptions\RepositoryClassException
+ * @throws \Logeecom\Infrastructure\ORM\Exceptions\RepositoryNotRegisteredException
+ */
+ public function checkStatus($id)
+ {
+ $status = $this->service->getAutoTestTaskStatus($id);
+
+ return array(
+ 'finished' => $status->finished,
+ 'error' => $status->error,
+ 'logs' => AutoTestLogger::getInstance()->getLogsArray(),
+ );
+ }
+
+ /**
+ * Retrieves auto test logs.
+ *
+ * @return array
+ *
+ * @throws \Logeecom\Infrastructure\ORM\Exceptions\RepositoryNotRegisteredException
+ */
+ public function getLogs()
+ {
+ return AutoTestLogger::getInstance()->getLogsArray();
+ }
+}
\ No newline at end of file
diff --git a/src/BusinessLogic/Controllers/ConfigurationController.php b/src/BusinessLogic/Controllers/ConfigurationController.php
new file mode 100644
index 00000000..97266643
--- /dev/null
+++ b/src/BusinessLogic/Controllers/ConfigurationController.php
@@ -0,0 +1,40 @@
+ 'https://support-pro.packlink.com/hc/en-gb',
+ 'ES' => 'https://support-pro.packlink.com/hc/es-es',
+ 'DE' => 'https://support-pro.packlink.com/hc/de',
+ 'FR' => 'https://support-pro.packlink.com/hc/fr-fr',
+ 'IT' => 'https://support-pro.packlink.com/hc/it',
+ );
+
+ /**
+ * @return mixed|string
+ */
+ public function getHelpLink()
+ {
+ $lang = UrlService::getUrlLocaleKey();
+
+ if (!array_key_exists($lang, static::$helpUrls)) {
+ $lang = 'EN';
+ }
+
+ return static::$helpUrls[$lang];
+ }
+}
diff --git a/src/BusinessLogic/Controllers/DTO/ModuleState.php b/src/BusinessLogic/Controllers/DTO/ModuleState.php
new file mode 100644
index 00000000..32c3f0c6
--- /dev/null
+++ b/src/BusinessLogic/Controllers/DTO/ModuleState.php
@@ -0,0 +1,47 @@
+ $this->id,
'name' => $this->name,
- 'pricePolicy' => $this->pricePolicy,
'showLogo' => $this->showLogo,
'taxClass' => $this->taxClass,
'isShipToAllCountries' => $this->isShipToAllCountries,
'shippingCountries' => $this->shippingCountries,
+ 'usePacklinkPriceIfNotInRange' => $this->usePacklinkPriceIfNotInRange,
+ 'pricingPolicies' => array(),
+ 'activated' => $this->activated,
);
- if ($this->pricePolicy === ShippingMethod::PRICING_POLICY_PERCENT && $this->percentPricePolicy) {
- $result['percentPricePolicy'] = $this->percentPricePolicy->toArray();
- }
-
- if ($this->pricePolicy === ShippingMethod::PRICING_POLICY_FIXED_PRICE_BY_WEIGHT
- && $this->fixedPriceByWeightPolicy
- ) {
- $this->setFixedPricePolicyToArray($result, 'fixedPriceByWeightPolicy');
- }
-
- if ($this->pricePolicy === ShippingMethod::PRICING_POLICY_FIXED_PRICE_BY_VALUE
- && $this->fixedPriceByValuePolicy
- ) {
- $this->setFixedPricePolicyToArray($result, 'fixedPriceByValuePolicy');
+ if ($this->pricingPolicies) {
+ foreach ($this->pricingPolicies as $policy) {
+ $result['pricingPolicies'][] = $policy->toArray();
+ }
}
return $result;
@@ -117,17 +101,18 @@ public function toArray()
* @param array $raw
*
* @return ShippingMethodConfiguration
+ * @throws \Packlink\BusinessLogic\DTO\Exceptions\FrontDtoValidationException
*/
public static function fromArray(array $raw)
{
$result = new static();
$result->id = $raw['id'];
+ $result->activated = (bool)static::getDataValue($raw, 'activated', false);
$result->name = $raw['name'];
$result->showLogo = $raw['showLogo'];
- $result->pricePolicy = $raw['pricePolicy'];
-
$result->taxClass = isset($raw['taxClass']) ? $raw['taxClass'] : null;
+ $result->usePacklinkPriceIfNotInRange = (bool)static::getDataValue($raw, 'usePacklinkPriceIfNotInRange', false);
if (isset($raw['isShipToAllCountries']) && is_bool($raw['isShipToAllCountries'])) {
$result->isShipToAllCountries = $raw['isShipToAllCountries'];
@@ -141,53 +126,14 @@ public static function fromArray(array $raw)
$result->shippingCountries = array();
}
- if ($result->pricePolicy === ShippingMethod::PRICING_POLICY_PERCENT) {
- $value = $raw['percentPricePolicy'];
- $result->percentPricePolicy = PercentPricePolicy::fromArray($value);
- }
-
- if ($result->pricePolicy === ShippingMethod::PRICING_POLICY_FIXED_PRICE_BY_WEIGHT) {
- self::setFixedPricingPolicyFromArray($result, $raw, 'fixedPriceByWeightPolicy');
- }
-
- if ($result->pricePolicy === ShippingMethod::PRICING_POLICY_FIXED_PRICE_BY_VALUE) {
- self::setFixedPricingPolicyFromArray($result, $raw, 'fixedPriceByValuePolicy');
- }
-
- return $result;
- }
-
- /**
- * Transforms fixed price policy to array and sets it to the given array.
- *
- * @param array $result Resulting array
- * @param string $type Type of the pricing policy
- */
- protected function setFixedPricePolicyToArray(array &$result, $type)
- {
- $result[$type] = array();
- /** @var FixedPricePolicy $item */
- foreach ($this->$type as $item) {
- $result[$type][] = $item->toArray();
- }
- }
-
- /**
- * Transforms fixed price policy from array and sets it to the given instance.
- *
- * @param static $result
- * @param array $raw
- * @param string $type
- */
- protected static function setFixedPricingPolicyFromArray($result, array $raw, $type)
- {
- $values = array();
- if (array_key_exists($type, $raw)) {
- foreach ($raw[$type] as $policy) {
- $values[] = FixedPricePolicy::fromArray($policy);
+ if (!empty($raw['pricingPolicies']) && is_array($raw['pricingPolicies'])) {
+ foreach ($raw['pricingPolicies'] as $policy) {
+ $result->pricingPolicies[] = ShippingPricePolicy::fromArray($policy);
}
+ } else {
+ $result->pricingPolicies = array();
}
- $result->$type = $values;
+ return $result;
}
}
diff --git a/src/BusinessLogic/Controllers/DTO/ShippingMethodResponse.php b/src/BusinessLogic/Controllers/DTO/ShippingMethodResponse.php
index b5158dda..3150ca6a 100644
--- a/src/BusinessLogic/Controllers/DTO/ShippingMethodResponse.php
+++ b/src/BusinessLogic/Controllers/DTO/ShippingMethodResponse.php
@@ -10,11 +10,11 @@
class ShippingMethodResponse extends ShippingMethodConfiguration
{
/**
- * Shipping method title.
+ * Shipping method type (national/international).
*
* @var string
*/
- public $title;
+ public $type;
/**
* Shipping carrier name.
*
@@ -51,12 +51,6 @@ class ShippingMethodResponse extends ShippingMethodConfiguration
* @var string
*/
public $parcelDestination;
- /**
- * Selected flag.
- *
- * @var bool
- */
- public $selected = false;
/**
* Transforms DTO to its array format suitable for http client.
@@ -68,14 +62,13 @@ public function toArray()
return array_merge(
parent::toArray(),
array(
- 'title' => $this->title,
+ 'type' => $this->type,
'carrierName' => $this->carrierName,
'deliveryDescription' => $this->deliveryDescription,
'deliveryType' => $this->deliveryType,
'parcelOrigin' => $this->parcelOrigin,
'parcelDestination' => $this->parcelDestination,
'logoUrl' => $this->logoUrl,
- 'selected' => $this->selected,
)
);
}
diff --git a/src/BusinessLogic/Controllers/DebugController.php b/src/BusinessLogic/Controllers/DebugController.php
new file mode 100644
index 00000000..3a171d47
--- /dev/null
+++ b/src/BusinessLogic/Controllers/DebugController.php
@@ -0,0 +1,186 @@
+configService = ServiceRegister::getService(Configuration::CLASS_NAME);
+ }
+
+ /**
+ * Returns debug mode status.
+ *
+ * @return bool
+ */
+ public function getStatus()
+ {
+ return $this->configService->isDebugModeEnabled();
+ }
+
+ /**
+ * Sets debug mode status.
+ *
+ * @param bool $status New debug status.
+ */
+ public function setStatus($status)
+ {
+ $this->configService->setDebugModeEnabled($status);
+ }
+
+ /**
+ * Returns system info file.
+ *
+ * @throws \Exception
+ */
+ public function getSystemInfo()
+ {
+ if (!defined('JSON_PRETTY_PRINT')) {
+ define('JSON_PRETTY_PRINT', 128);
+ }
+
+ if (!defined('JSON_UNESCAPED_SLASHES')) {
+ define('JSON_UNESCAPED_SLASHES', 64);
+ }
+
+ $file = tempnam(sys_get_temp_dir(), 'packlink_system_info');
+
+ $zip = new \ZipArchive();
+ $zip->open($file, \ZipArchive::CREATE);
+
+ $zip->addFromString(static::USER_INFO_FILE_NAME, $this->getUserSettings());
+ $zip->addFromString(static::QUEUE_INFO_FILE_NAME, $this->getQueue());
+ $zip->addFromString(static::SERVICE_INFO_FILE_NAME, $this->getServicesInfo());
+
+ $this->getIntegrationInfo($zip);
+
+ $zip->close();
+
+ return $file;
+ }
+
+ /**
+ * Returns integration specific information.
+ * An extension point for integrations to add more data.
+ *
+ * @param \ZipArchive $zip
+ */
+ protected function getIntegrationInfo(\ZipArchive $zip)
+ {
+ }
+
+ /**
+ * Returns parcel and warehouse information.
+ *
+ * @return string
+ */
+ protected function getUserSettings()
+ {
+ $result = array();
+ /** @noinspection NullPointerExceptionInspection */
+ $result['User'] = $this->configService->getUserInfo()->toArray();
+ $result['User']['API key'] = $this->configService->getAuthorizationToken();
+ $result['Parcel'] = $this->configService->getDefaultParcel() ?: array();
+ $result['Warehouse'] = $this->configService->getDefaultWarehouse() ?: array();
+ $result['Order Status Mappings'] = $this->configService->getOrderStatusMappings() ?: array();
+
+ return $this->jsonEncode($result);
+ }
+
+ /**
+ * Returns service info.
+ *
+ * @return string
+ */
+ protected function getServicesInfo()
+ {
+ $result = array();
+
+ try {
+ $repository = RepositoryRegistry::getRepository(RepositoryInterface::CLASS_NAME);
+ $result = $repository->select();
+ } catch (RepositoryNotRegisteredException $e) {
+ }
+
+ return $this->formatJsonOutput($result);
+ }
+
+ /**
+ * Returns current queue for current tenant.
+ *
+ * @return string
+ */
+ protected function getQueue()
+ {
+ $result = array();
+
+ try {
+ $repository = RepositoryRegistry::getQueueItemRepository();
+
+ $query = new QueryFilter();
+ $query->where('context', Operators::EQUALS, $this->configService->getContext());
+
+ $result = $repository->select($query);
+ } catch (RepositoryNotRegisteredException $e) {
+ } catch (QueryFilterInvalidParamException $e) {
+ } catch (RepositoryClassException $e) {
+ }
+
+ return $this->formatJsonOutput($result);
+ }
+
+ /**
+ * Encodes the given data.
+ *
+ * @param $data
+ *
+ * @return string
+ */
+ protected function jsonEncode($data)
+ {
+ return json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
+ }
+
+ /**
+ * Formats json output.
+ *
+ * @param \Logeecom\Infrastructure\ORM\Entity[] $items Entities.
+ *
+ * @return string
+ */
+ protected function formatJsonOutput(array $items)
+ {
+ $response = array();
+ foreach ($items as $item) {
+ $response[] = $item->toArray();
+ }
+
+ return $this->jsonEncode($response);
+ }
+}
diff --git a/src/BusinessLogic/Controllers/DefaultParcelController.php b/src/BusinessLogic/Controllers/DefaultParcelController.php
new file mode 100644
index 00000000..96963a96
--- /dev/null
+++ b/src/BusinessLogic/Controllers/DefaultParcelController.php
@@ -0,0 +1,71 @@
+getConfigService()->getDefaultParcel();
+ }
+
+ /**
+ * Sets default parcel and enqueues the Update shipping services task if needed.
+ *
+ * @param array $rawData
+ *
+ * @throws \Logeecom\Infrastructure\TaskExecution\Exceptions\QueueStorageUnavailableException
+ * @throws \Packlink\BusinessLogic\DTO\Exceptions\FrontDtoValidationException
+ */
+ public function setDefaultParcel(array $rawData)
+ {
+ $rawData['default'] = true;
+ $oldParcel = $this->getConfigService()->getDefaultParcel();
+
+ $parcelInfo = ParcelInfo::fromArray($rawData);
+ $this->getConfigService()->setDefaultParcel($parcelInfo);
+
+ if ($oldParcel === null || array_diff($oldParcel->toArray(), $parcelInfo->toArray())) {
+ /** @var QueueService $queueService */
+ $queueService = ServiceRegister::getService(QueueService::CLASS_NAME);
+ $defaultQueueName = $this->getConfigService()->getDefaultQueueName();
+
+ $queueService->enqueue(
+ $defaultQueueName,
+ new UpdateShippingServicesTask(),
+ $this->getConfigService()->getContext()
+ );
+ }
+ }
+
+ /**
+ * Returns an instance of configuration service.
+ *
+ * @return ConfigurationService
+ */
+ private function getConfigService()
+ {
+ if ($this->configService === null) {
+ $this->configService = ServiceRegister::getService(Configuration::CLASS_NAME);
+ }
+
+ return $this->configService;
+ }
+}
diff --git a/src/BusinessLogic/Controllers/LocationsController.php b/src/BusinessLogic/Controllers/LocationsController.php
new file mode 100644
index 00000000..4ec5f724
--- /dev/null
+++ b/src/BusinessLogic/Controllers/LocationsController.php
@@ -0,0 +1,55 @@
+service = ServiceRegister::getService(LocationService::CLASS_NAME);
+ }
+
+ /**
+ * Retrieves locations.
+ *
+ * @param array $query Associative array in the following format ['query' => '...', 'country' => '...'].
+ *
+ * @return \Packlink\BusinessLogic\Http\DTO\LocationInfo[]
+ */
+ public function searchLocations(array $query)
+ {
+ if (empty($query['query']) || empty($query['country'])) {
+ return array();
+ }
+
+ try {
+ $result = $this->service->searchLocations($query['country'], $query['query']);
+ } catch (Exception $e) {
+ Logger::logError('Location search failed.', 'Core', $e->getTrace());
+
+ $result = array();
+ }
+
+ return $result;
+ }
+}
\ No newline at end of file
diff --git a/src/BusinessLogic/Controllers/LoginController.php b/src/BusinessLogic/Controllers/LoginController.php
new file mode 100644
index 00000000..1a4649f5
--- /dev/null
+++ b/src/BusinessLogic/Controllers/LoginController.php
@@ -0,0 +1,42 @@
+login($apiKey);
+ } catch (Exception $e) {
+ /** @var ConfigurationService $configService */
+ $configService = ServiceRegister::getService(Configuration::CLASS_NAME);
+ if ($configService->getAuthorizationToken() !== null) {
+ $configService->setAuthorizationToken(null);
+ }
+ }
+
+ return $result;
+ }
+}
\ No newline at end of file
diff --git a/src/BusinessLogic/Controllers/ModuleStateController.php b/src/BusinessLogic/Controllers/ModuleStateController.php
new file mode 100644
index 00000000..4042670c
--- /dev/null
+++ b/src/BusinessLogic/Controllers/ModuleStateController.php
@@ -0,0 +1,51 @@
+getAuthorizationToken();
+
+ /** @var ParcelInfo|null $defaultParcel */
+ $defaultParcel = $configService->getDefaultParcel();
+
+ /** @var Warehouse|null $defaultWarehouse */
+ $defaultWarehouse = $configService->getDefaultWarehouse();
+
+ $result = new ModuleState();
+
+ if (empty($apiToken)) {
+ $result->state = ModuleState::LOGIN_STATE;
+
+ } else if ($defaultParcel === null || $defaultWarehouse === null) {
+ $result->state = ModuleState::ONBOARDING_STATE;
+
+ } else {
+ $result->state = ModuleState::SERVICES_STATE;
+ }
+
+ return $result;
+ }
+}
diff --git a/src/BusinessLogic/Controllers/OnboardingController.php b/src/BusinessLogic/Controllers/OnboardingController.php
new file mode 100644
index 00000000..b0523d4b
--- /dev/null
+++ b/src/BusinessLogic/Controllers/OnboardingController.php
@@ -0,0 +1,35 @@
+getDefaultParcel();
+ $warehouse = $configService->getDefaultWarehouse();
+
+ if ($parcel === null && $warehouse === null) {
+ $result->state = OnboardingState::WELCOME_STATE;
+
+ } else {
+ $result->state = OnboardingState::OVERVIEW_STATE;
+ }
+
+ return $result;
+ }
+}
diff --git a/src/BusinessLogic/Controllers/OrderStatusMappingController.php b/src/BusinessLogic/Controllers/OrderStatusMappingController.php
new file mode 100644
index 00000000..aed08e94
--- /dev/null
+++ b/src/BusinessLogic/Controllers/OrderStatusMappingController.php
@@ -0,0 +1,62 @@
+getOrderStatusMappings();
+
+ if (empty($mappings)) {
+ foreach ($this->getPacklinkStatuses() as $status => $label) {
+ $mappings[$status] = '';
+ }
+ }
+
+ return $mappings;
+ }
+
+ /**
+ * Returns Packlink shipment statuses.
+ *
+ * @return array Packlink shipment statuses
+ */
+ public function getPacklinkStatuses()
+ {
+ $result = array();
+ foreach (ShipmentStatus::getPossibleStatuses() as $status) {
+ $result[$status] = Translator::translate('orderStatusMapping.' . $status);
+ }
+
+ return $result;
+ }
+
+ /**
+ * Saves order status mappings.
+ *
+ * @param array $data
+ */
+ public function setMappings($data)
+ {
+ /** @var \Packlink\BusinessLogic\Configuration $configService */
+ $configService = ServiceRegister::getService(Configuration::CLASS_NAME);
+ $configService->setOrderStatusMappings($data);
+ }
+}
diff --git a/src/BusinessLogic/Controllers/RegistrationController.php b/src/BusinessLogic/Controllers/RegistrationController.php
new file mode 100644
index 00000000..89216b05
--- /dev/null
+++ b/src/BusinessLogic/Controllers/RegistrationController.php
@@ -0,0 +1,179 @@
+ 'https://support-pro.packlink.com/hc/en-gb/articles/360010011480',
+ 'ES' => 'https://pro.packlink.es/terminos-y-condiciones/',
+ 'DE' => 'https://pro.packlink.de/agb/',
+ 'FR' => 'https://pro.packlink.fr/conditions-generales/',
+ 'IT' => 'https://pro.packlink.it/termini-condizioni/',
+ 'AT' => 'https://support-pro.packlink.com/hc/de/articles/360010011480',
+ 'NL' => 'https://support-pro.packlink.com/hc/nl/articles/360010011480',
+ 'BE' => 'https://support-pro.packlink.com/hc/nl/articles/360010011480',
+ 'PT' => 'https://support-pro.packlink.com/hc/pt/articles/360010011480',
+ 'TR' => 'https://support-pro.packlink.com/hc/tr/articles/360010011480',
+ 'IE' => 'https://support-pro.packlink.com/hc/en-gb/articles/360010011480',
+ 'GB' => 'https://support-pro.packlink.com/hc/en-gb/articles/360010011480',
+ 'HU' => 'https://support-pro.packlink.com/hc/hu/articles/360010011480',
+ );
+ /**
+ * List of terms and conditions URLs for different country codes.
+ *
+ * @var array
+ */
+ private static $privacyPolicyUrls = array(
+ 'EN' => 'https://support-pro.packlink.com/hc/en-gb/articles/360010011560',
+ 'ES' => 'https://support-pro.packlink.com/hc/es-es/articles/360010011560-Pol%C3%ADtica-de-Privacidad',
+ 'DE' => 'https://support-pro.packlink.com/hc/de/articles/360010011560-Datenschutzerkl%C3%A4rung-der-Packlink-Shipping-S-L-',
+ 'FR' => 'https://support-pro.packlink.com/hc/fr-fr/articles/360010011560-Politique-de-confidentialit%C3%A9',
+ 'IT' => 'https://support-pro.packlink.com/hc/it/articles/360010011560-Politica-di-Privacy',
+ 'AT' => 'https://support-pro.packlink.com/hc/de/articles/360010011480',
+ 'NL' => 'https://support-pro.packlink.com/hc/nl/articles/360010011560',
+ 'BE' => 'https://support-pro.packlink.com/hc/nl/articles/360010011560',
+ 'PT' => 'https://support-pro.packlink.com/hc/pt/articles/360010011560',
+ 'TR' => 'https://support-pro.packlink.com/hc/tr/articles/360010011560',
+ 'IE' => 'https://support-pro.packlink.com/hc/en-gb/articles/360010011560',
+ 'GB' => 'https://support-pro.packlink.com/hc/en-gb/articles/360010011560',
+ 'HU' => 'https://support-pro.packlink.com/hc/hu/articles/360010011560',
+ );
+
+ /**
+ * Gets the data needed for a registration page.
+ *
+ * @param string $country
+ *
+ * @return array
+ */
+ public function getRegisterData($country)
+ {
+ /** @var RegistrationInfoService $registrationInfoService */
+ $registrationInfoService = ServiceRegister::getService(RegistrationInfoService::CLASS_NAME);
+ $registrationData = $registrationInfoService->getRegistrationInfoData();
+
+ return array(
+ 'context' => $this->getConfigService()->getContext(),
+ 'email' => $registrationData->getEmail(),
+ 'phone' => $registrationData->getPhone(),
+ 'source' => $registrationData->getSource(),
+ 'termsAndConditionsUrl' => !empty(self::$termsAndConditionsUrls[$country]) ?
+ self::$termsAndConditionsUrls[$country] : self::$termsAndConditionsUrls[self::DEFAULT_COUNTRY],
+ 'privacyPolicyUrl' => !empty(self::$privacyPolicyUrls[$country]) ?
+ self::$privacyPolicyUrls[$country] : self::$privacyPolicyUrls[self::DEFAULT_COUNTRY],
+ );
+ }
+
+ /**
+ * Registers the user to the Packlink system.
+ *
+ * @param array $payload
+ *
+ * @return bool A flag indicating whether the registration was successful.
+ *
+ * @throws \Logeecom\Infrastructure\ORM\Exceptions\RepositoryNotRegisteredException
+ * @throws \Logeecom\Infrastructure\TaskExecution\Exceptions\QueueStorageUnavailableException
+ * @throws \Packlink\BusinessLogic\DTO\Exceptions\FrontDtoNotRegisteredException
+ * @throws \Packlink\BusinessLogic\DTO\Exceptions\FrontDtoValidationException
+ * @throws \Packlink\BusinessLogic\Registration\Exceptions\UnableToRegisterAccountException
+ */
+ public function register(array $payload)
+ {
+ $payload['platform'] = 'PRO';
+ $payload['language'] = $this->getLanguage($payload['platform_country']);
+
+ if (isset($payload['source'])) {
+ $payload['source'] = 'https://' . str_replace(array('http://', 'https://'), '', $payload['source']);
+ }
+
+ $acceptedTermsAndConditions = isset($payload['terms_and_conditions']) && $payload['terms_and_conditions'];
+ $acceptedMarketingEmails = isset($payload['marketing_emails']) && $payload['marketing_emails'];
+
+ $payload['policies'] = array(
+ 'terms_and_conditions' => $acceptedTermsAndConditions,
+ 'data_processing' => $acceptedTermsAndConditions,
+ 'marketing_emails' => $acceptedMarketingEmails,
+ 'marketing_calls' => $acceptedMarketingEmails,
+ );
+
+ /** @var RegistrationRequest $request */
+ $registrationRequest = FrontDtoFactory::get(RegistrationRequest::CLASS_KEY, $payload);
+
+ /** @var RegistrationService $registrationService */
+ $registrationService = ServiceRegister::getService(RegistrationService::CLASS_NAME);
+
+ /** @noinspection PhpParamsInspection */
+ $token = $registrationService->register($registrationRequest);
+
+ if (!empty($token)) {
+ /** @var UserAccountService $userAccountService */
+ $userAccountService = ServiceRegister::getService(UserAccountService::CLASS_NAME);
+ if ($userAccountService->login($token)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns an instance of configuration service.
+ *
+ * @return Configuration
+ */
+ protected function getConfigService()
+ {
+ if ($this->configService === null) {
+ $this->configService = ServiceRegister::getService(Configuration::CLASS_NAME);
+ }
+
+ return $this->configService;
+ }
+
+ /**
+ * Returns shop language in format which Packlink expects, based on user's platform country.
+ *
+ * @param string $platformCountry
+ *
+ * @return string
+ */
+ private function getLanguage($platformCountry)
+ {
+ $supportedLanguages = array(
+ 'ES' => 'es_ES',
+ 'DE' => 'de_DE',
+ 'FR' => 'fr_FR',
+ 'IT' => 'it_IT',
+ );
+
+ $language = 'en_GB';
+
+ if (array_key_exists($platformCountry, $supportedLanguages)) {
+ $language = $supportedLanguages[$platformCountry];
+ }
+
+ return $language;
+ }
+}
diff --git a/src/BusinessLogic/Controllers/RegistrationRegionsController.php b/src/BusinessLogic/Controllers/RegistrationRegionsController.php
new file mode 100644
index 00000000..bcda6bec
--- /dev/null
+++ b/src/BusinessLogic/Controllers/RegistrationRegionsController.php
@@ -0,0 +1,34 @@
+service = ServiceRegister::getService(CountryService::CLASS_NAME);
+ }
+
+ public function getRegions()
+ {
+ return $this->service->getSupportedCountries(false);
+ }
+}
\ No newline at end of file
diff --git a/src/BusinessLogic/Controllers/ShippingMethodController.php b/src/BusinessLogic/Controllers/ShippingMethodController.php
index b2fa6765..8219e7ca 100644
--- a/src/BusinessLogic/Controllers/ShippingMethodController.php
+++ b/src/BusinessLogic/Controllers/ShippingMethodController.php
@@ -2,10 +2,13 @@
namespace Packlink\BusinessLogic\Controllers;
+use Exception;
use Logeecom\Infrastructure\Logger\Logger;
use Logeecom\Infrastructure\ServiceRegister;
use Packlink\BusinessLogic\Controllers\DTO\ShippingMethodConfiguration;
use Packlink\BusinessLogic\Controllers\DTO\ShippingMethodResponse;
+use Packlink\BusinessLogic\Language\Translator;
+use Packlink\BusinessLogic\ShippingMethod\Interfaces\ShopShippingMethodService;
use Packlink\BusinessLogic\ShippingMethod\Models\ShippingMethod;
use Packlink\BusinessLogic\ShippingMethod\ShippingMethodService;
@@ -28,10 +31,14 @@ class ShippingMethodController
* Pickup constant
*/
const PICKUP = 'pickup';
+ /**
+ * Collection constant
+ */
+ const COLLECTION = 'collection';
/**
* Home constant
*/
- const HOME = 'home';
+ const DELIVERY = 'delivery';
/**
* Shipping type: national
*/
@@ -48,23 +55,18 @@ class ShippingMethodController
* Shipping delivery type: economic
*/
const ECONOMIC = 'economic';
- /**
- * Allowed policies.
- *
- * @var array
- */
- private static $policies = array(
- ShippingMethod::PRICING_POLICY_PACKLINK,
- ShippingMethod::PRICING_POLICY_PERCENT,
- ShippingMethod::PRICING_POLICY_FIXED_PRICE_BY_WEIGHT,
- ShippingMethod::PRICING_POLICY_FIXED_PRICE_BY_VALUE,
- );
/**
* Shipping method service.
*
* @var ShippingMethodService
*/
private $shippingMethodService;
+ /**
+ * Shop shipping method service.
+ *
+ * @var \Packlink\BusinessLogic\ShippingMethod\Interfaces\ShopShippingMethodService
+ */
+ private $shopShippingService;
/**
* DashboardController constructor.
@@ -72,6 +74,7 @@ class ShippingMethodController
public function __construct()
{
$this->shippingMethodService = ServiceRegister::getService(ShippingMethodService::CLASS_NAME);
+ $this->shopShippingService = ServiceRegister::getService(ShopShippingMethodService::CLASS_NAME);
}
/**
@@ -81,13 +84,46 @@ public function __construct()
*/
public function getAll()
{
- $all = $this->shippingMethodService->getAllMethods();
- $result = array();
- foreach ($all as $item) {
- $result[] = $this->transformShippingMethodModelToDto($item);
+ return $this->getResponse($this->shippingMethodService->getAllMethods());
+ }
+
+ /**
+ * Returns all shipping methods.
+ *
+ * @return ShippingMethodResponse[] Array of shipping methods.
+ */
+ public function getActive()
+ {
+ return $this->getResponse($this->shippingMethodService->getActiveMethods());
+ }
+
+ /**
+ * Returns all shipping methods.
+ *
+ * @return ShippingMethodResponse[] Array of shipping methods.
+ */
+ public function getInactive()
+ {
+ return $this->getResponse($this->shippingMethodService->getInactiveMethods());
+ }
+
+ /**
+ * Returns shipping method with the given ID.
+ *
+ * @param int $id Shipping method ID.
+ *
+ * @return ShippingMethodResponse|null Shipping method.
+ */
+ public function getShippingMethod($id)
+ {
+ $model = $this->shippingMethodService->getShippingMethod($id);
+ if (!$model) {
+ Logger::logWarning("Shipping method with id {$id} not found!");
+
+ return null;
}
- return $result;
+ return $this->transformShippingMethodModelToDto($model);
}
/**
@@ -99,10 +135,6 @@ public function getAll()
*/
public function save(ShippingMethodConfiguration $shippingMethod)
{
- if (!$this->isValid($shippingMethod)) {
- return null;
- }
-
$model = $this->shippingMethodService->getShippingMethod($shippingMethod->id);
if (!$model) {
Logger::logError("Shipping method with id {$shippingMethod->id} not found!");
@@ -111,16 +143,24 @@ public function save(ShippingMethodConfiguration $shippingMethod)
}
try {
+ $isFirstServiceActivated = $shippingMethod->activated && !$this->shippingMethodService->isAnyMethodActive();
+
$this->updateModelData($shippingMethod, $model);
$this->shippingMethodService->save($model);
- return $this->transformShippingMethodModelToDto($model);
- } catch (\Exception $e) {
+ $result = $this->transformShippingMethodModelToDto($model);
+
+ if ($isFirstServiceActivated) {
+ AnalyticsController::sendSetupEvent();
+ $this->shopShippingService->addBackupShippingMethod(ShippingMethod::fromArray($model->toArray()));
+ }
+
+ return $result;
+ } catch (Exception $e) {
Logger::logError($e->getMessage(), 'Core', $shippingMethod->toArray());
- $result = null;
}
- return $result;
+ return null;
}
/**
@@ -153,6 +193,23 @@ public function deactivate($id)
return $this->shippingMethodService->deactivate($id);
}
+ /**
+ * Transforms shipping methods to the response.
+ *
+ * @param ShippingMethod[] $methods Shipping methods to transform.
+ *
+ * @return ShippingMethodResponse[] Array of shipping methods.
+ */
+ protected function getResponse($methods)
+ {
+ $result = array();
+ foreach ($methods as $item) {
+ $result[] = $this->transformShippingMethodModelToDto($item);
+ }
+
+ return $result;
+ }
+
/**
* Transforms ShippingMethod model class to ShippingMethod DTO.
*
@@ -164,49 +221,28 @@ private function transformShippingMethodModelToDto(ShippingMethod $item)
{
$shippingMethod = new ShippingMethodResponse();
$shippingMethod->id = $item->getId();
- $shippingMethod->selected = $item->isActivated();
+ $shippingMethod->activated = $item->isActivated();
+ $shippingMethod->name = $item->getTitle();
$shippingMethod->logoUrl = $item->getLogoUrl();
$shippingMethod->showLogo = $item->isDisplayLogo();
- $shippingMethod->title = $item->isNational() ? static::NATIONAL : static::INTERNATIONAL;
+ $shippingMethod->type = $item->isNational() ? static::NATIONAL : static::INTERNATIONAL;
$shippingMethod->carrierName = $item->getCarrierName();
- $shippingMethod->deliveryDescription = ($item->isExpressDelivery() ? 'Express' : 'Economic') . ' '
- . $item->getDeliveryTime();
+ $shippingMethod->deliveryDescription = mb_strtolower($item->getDeliveryTime()) . ' - '
+ . Translator::translate(
+ 'shippingServices.' . ($item->isExpressDelivery() ? static::EXPRESS : static::ECONOMIC)
+ );
$shippingMethod->deliveryType = $item->isExpressDelivery() ? static::EXPRESS : static::ECONOMIC;
- $shippingMethod->name = $item->getTitle();
- $shippingMethod->parcelDestination = $item->isDestinationDropOff() ? static::DROP_OFF : static::HOME;
- $shippingMethod->parcelOrigin = $item->isDepartureDropOff() ? static::DROP_OFF : static::PICKUP;
+ $shippingMethod->parcelOrigin = $item->isDepartureDropOff() ? static::DROP_OFF : static::COLLECTION;
+ $shippingMethod->parcelDestination = $item->isDestinationDropOff() ? static::PICKUP : static::DELIVERY;
$shippingMethod->taxClass = $item->getTaxClass();
$shippingMethod->shippingCountries = $item->getShippingCountries();
$shippingMethod->isShipToAllCountries = $item->isShipToAllCountries();
-
- $shippingMethod->pricePolicy = $item->getPricingPolicy();
- $shippingMethod->percentPricePolicy = $item->getPercentPricePolicy();
- $shippingMethod->fixedPriceByWeightPolicy = $item->getFixedPriceByWeightPolicy();
- $shippingMethod->fixedPriceByValuePolicy = $item->getFixedPriceByValuePolicy();
-
- $shippingMethod->logoUrl = $item->getLogoUrl();
+ $shippingMethod->pricingPolicies = $item->getPricingPolicies();
+ $shippingMethod->usePacklinkPriceIfNotInRange = $item->isUsePacklinkPriceIfNotInRange();
return $shippingMethod;
}
- /**
- * Validates shipping method data.
- *
- * @param ShippingMethodConfiguration $data Shipping method data object.
- *
- * @return bool Returns true if shipping method data is valid, false otherwise.
- */
- private function isValid(ShippingMethodConfiguration $data)
- {
- return !(!isset($data->id, $data->name, $data->showLogo, $data->pricePolicy)
- || ($data->pricePolicy === ShippingMethod::PRICING_POLICY_PERCENT && !isset($data->percentPricePolicy))
- || ($data->pricePolicy === ShippingMethod::PRICING_POLICY_FIXED_PRICE_BY_WEIGHT
- && empty($data->fixedPriceByWeightPolicy))
- || ($data->pricePolicy === ShippingMethod::PRICING_POLICY_FIXED_PRICE_BY_VALUE
- && empty($data->fixedPriceByValuePolicy))
- || (!is_bool($data->showLogo) || !in_array($data->pricePolicy, static::$policies, false)));
- }
-
/**
* Updates model data from data transfer object.
*
@@ -220,19 +256,11 @@ private function updateModelData(ShippingMethodConfiguration $configuration, Shi
$model->setTaxClass($configuration->taxClass);
$model->setShipToAllCountries($configuration->isShipToAllCountries);
$model->setShippingCountries($configuration->shippingCountries);
- switch ($configuration->pricePolicy) {
- case ShippingMethod::PRICING_POLICY_PACKLINK:
- $model->setPacklinkPricePolicy();
- break;
- case ShippingMethod::PRICING_POLICY_PERCENT:
- $model->setPercentPricePolicy($configuration->percentPricePolicy);
- break;
- case ShippingMethod::PRICING_POLICY_FIXED_PRICE_BY_WEIGHT:
- $model->setFixedPriceByWeightPolicy($configuration->fixedPriceByWeightPolicy);
- break;
- case ShippingMethod::PRICING_POLICY_FIXED_PRICE_BY_VALUE:
- $model->setFixedPriceByValuePolicy($configuration->fixedPriceByValuePolicy);
- break;
+ $model->setActivated($configuration->activated);
+ $model->resetPricingPolicies();
+ $model->setUsePacklinkPriceIfNotInRange($configuration->usePacklinkPriceIfNotInRange);
+ foreach ($configuration->pricingPolicies as $policy) {
+ $model->addPricingPolicy($policy);
}
}
}
diff --git a/src/BusinessLogic/Controllers/WarehouseController.php b/src/BusinessLogic/Controllers/WarehouseController.php
new file mode 100644
index 00000000..115bb4ba
--- /dev/null
+++ b/src/BusinessLogic/Controllers/WarehouseController.php
@@ -0,0 +1,70 @@
+service = ServiceRegister::getService(WarehouseService::CLASS_NAME);
+ }
+
+ /**
+ * Provides warehouse data.
+ *
+ * @return \Packlink\BusinessLogic\Warehouse\Warehouse | null
+ */
+ public function getWarehouse()
+ {
+ return $this->service->getWarehouse();
+ }
+
+ /**
+ * Updates warehouse.
+ *
+ * @param array $data
+ *
+ * @return \Packlink\BusinessLogic\Warehouse\Warehouse
+ *
+ * @throws \Logeecom\Infrastructure\TaskExecution\Exceptions\QueueStorageUnavailableException
+ * @throws \Packlink\BusinessLogic\DTO\Exceptions\FrontDtoNotRegisteredException
+ * @throws \Packlink\BusinessLogic\DTO\Exceptions\FrontDtoValidationException
+ */
+ public function updateWarehouse(array $data)
+ {
+ return $this->service->updateWarehouseData($data);
+ }
+
+ /**
+ * Returns available countries for warehouse location.
+ *
+ * @return Country[]
+ */
+ public function getWarehouseCountries()
+ {
+ /** @var WarehouseCountryService $countryService */
+ $countryService = ServiceRegister::getService(WarehouseCountryService::CLASS_NAME);
+
+ return $countryService->getSupportedCountries(false);
+ }
+}
\ No newline at end of file
diff --git a/src/BusinessLogic/Country/CountryService.php b/src/BusinessLogic/Country/CountryService.php
index 8b960f01..1f7166d2 100644
--- a/src/BusinessLogic/Country/CountryService.php
+++ b/src/BusinessLogic/Country/CountryService.php
@@ -6,6 +6,7 @@
use Packlink\BusinessLogic\BaseService;
use Packlink\BusinessLogic\Configuration;
use Packlink\BusinessLogic\DTO\FrontDtoFactory;
+use Packlink\BusinessLogic\Language\Translator;
/**
* Class CountryProvider
@@ -40,70 +41,70 @@ class CountryService extends BaseService
'name' => 'Spain',
'code' => 'ES',
'postal_code' => '28001',
- 'registration_link' => 'https://auth.packlink.com/es-ES/{integration}/registro?platform_country=ES',
+ 'registration_link' => 'https://auth.packlink.com/es-ES/{integration}/registro',
'platform_country' => 'ES',
),
'DE' => array(
'name' => 'Germany',
'code' => 'DE',
'postal_code' => '10115',
- 'registration_link' => 'https://auth.packlink.com/de-DE/{integration}/registrieren?platform_country=DE',
+ 'registration_link' => 'https://auth.packlink.com/de-DE/{integration}/registrieren',
'platform_country' => 'DE',
),
'FR' => array(
'name' => 'France',
'code' => 'FR',
'postal_code' => '75001',
- 'registration_link' => 'https://auth.packlink.com/fr-FR/{integration}/inscription?platform_country=FR',
+ 'registration_link' => 'https://auth.packlink.com/fr-FR/{integration}/inscription',
'platform_country' => 'FR',
),
'IT' => array(
'name' => 'Italy',
'code' => 'IT',
'postal_code' => '00118',
- 'registration_link' => 'https://auth.packlink.com/it-IT/{integration}/registro?platform_country=IT',
+ 'registration_link' => 'https://auth.packlink.com/it-IT/{integration}/registro',
'platform_country' => 'IT',
),
'AT' => array(
'name' => 'Austria',
'code' => 'AT',
'postal_code' => '1010',
- 'registration_link' => 'https://auth.packlink.com/de-DE/{integration}/registrieren?platform_country=UN',
+ 'registration_link' => 'https://auth.packlink.com/de-DE/{integration}/registrieren',
'platform_country' => 'UN',
),
'NL' => array(
'name' => 'Netherlands',
'code' => 'NL',
'postal_code' => '1011',
- 'registration_link' => 'https://auth.packlink.com/nl-NL/{integration}/registrieren?platform_country=UN',
+ 'registration_link' => 'https://auth.packlink.com/nl-NL/{integration}/registrieren',
'platform_country' => 'UN',
),
'BE' => array(
'name' => 'Belgium',
'code' => 'BE',
'postal_code' => '1000',
- 'registration_link' => 'https://auth.packlink.com/nl-NL/{integration}/registrieren?platform_country=UN',
+ 'registration_link' => 'https://auth.packlink.com/nl-NL/{integration}/registrieren',
'platform_country' => 'UN',
),
'PT' => array(
'name' => 'Portugal',
'code' => 'PT',
'postal_code' => '1000-017',
- 'registration_link' => 'https://auth.packlink.com/pt-PT/{integration}/registo?platform_country=UN',
+ 'registration_link' => 'https://auth.packlink.com/pt-PT/{integration}/registo',
'platform_country' => 'UN',
),
'TR' => array(
'name' => 'Turkey',
'code' => 'TR',
'postal_code' => '06010',
- 'registration_link' => 'https://auth.packlink.com/tr-TR/{integration}/kayıt-yap?platform_country=UN',
+ 'registration_link' => 'https://auth.packlink.com/tr-TR/{integration}/kayıt-yap',
'platform_country' => 'UN',
),
'IE' => array(
'name' => 'Ireland',
'code' => 'IE',
'postal_code' => 'D1',
- 'registration_link' => 'https://auth.packlink.com/en-GB/{integration}/register?platform_country=UN',
+ 'registration_link' => 'https://auth.packlink.com/en-GB/{integration}/register',
'platform_country' => 'UN',
),
'GB' => array(
@@ -137,12 +138,14 @@ public function isBaseCountry($countryCode)
/**
* Returns a list of supported country DTOs.
*
+ * @param bool $associative Indicates whether the result should be an associative array.
+ *
* @return RegistrationCountry[]
*
* @noinspection PhpUnhandledExceptionInspection
* @noinspection PhpDocMissingThrowsInspection
*/
- public function getSupportedCountries()
+ public function getSupportedCountries($associative = true)
{
$countries = array();
$configuration = ServiceRegister::getService(Configuration::CLASS_NAME);
@@ -153,11 +156,12 @@ public function getSupportedCountries()
'{integration}',
$integration,
$country['registration_link']
- ) . '&platform=PRO';
+ ) . '?platform=PRO&platform_country=' . $country['platform_country'];
+ $country['name'] = Translator::translate('countries.' . $country['code']);
$countries[$country['code']] = FrontDtoFactory::get(RegistrationCountry::CLASS_KEY, $country);
}
- return $countries;
+ return $associative ? $countries : array_values($countries);
}
}
diff --git a/src/BusinessLogic/Country/WarehouseCountryService.php b/src/BusinessLogic/Country/WarehouseCountryService.php
index e509e9a1..6cd1435a 100644
--- a/src/BusinessLogic/Country/WarehouseCountryService.php
+++ b/src/BusinessLogic/Country/WarehouseCountryService.php
@@ -3,6 +3,7 @@
namespace Packlink\BusinessLogic\Country;
use Packlink\BusinessLogic\DTO\FrontDtoFactory;
+use Packlink\BusinessLogic\Language\Translator;
/**
* Class WarehouseCountryService
@@ -91,11 +92,12 @@ class WarehouseCountryService extends CountryService
*/
public function getSupportedCountries($associative = true)
{
- /** @var Country[] $countries */
- $countries = FrontDtoFactory::getFromBatch(
- Country::CLASS_KEY,
- array_merge(static::$supportedCountries, static::$additionalWarehouseCountries)
- );
+ $countries = array_merge(static::$supportedCountries, static::$additionalWarehouseCountries);
+
+ foreach ($countries as $country) {
+ $country['name'] = Translator::translate('countries.' . $country['code']);
+ $countries[$country['code']] = FrontDtoFactory::get(Country::CLASS_KEY, $country);
+ }
return $associative ? $countries : array_values($countries);
}
diff --git a/src/BusinessLogic/DTO/FrontDto.php b/src/BusinessLogic/DTO/FrontDto.php
index 9e5f238e..785fea97 100644
--- a/src/BusinessLogic/DTO/FrontDto.php
+++ b/src/BusinessLogic/DTO/FrontDto.php
@@ -4,6 +4,7 @@
use Logeecom\Infrastructure\Data\DataTransferObject;
use Packlink\BusinessLogic\DTO\Exceptions\FrontDtoValidationException;
+use Packlink\BusinessLogic\Language\Translator;
/**
* Class FrontDto.
@@ -72,7 +73,6 @@ public function toArray()
*
* @param array $payload The payload in key-value format.
*
- * @return void
* @throws \Packlink\BusinessLogic\DTO\Exceptions\FrontDtoValidationException
* When fields are not registered for DTO class or payload contains unknown fields.
*/
@@ -92,7 +92,7 @@ protected static function validate(array $payload)
/**
* Validates whether a DTO has a definition of its fields.
*
- * @param array $validationErrors
+ * @param ValidationError[] $validationErrors The array of errors to populate.
*/
protected static function validateDefinition(array &$validationErrors)
{
@@ -114,14 +114,41 @@ protected static function validateDefinition(array &$validationErrors)
protected static function validateRequiredFields(array $payload, array &$validationErrors)
{
foreach (static::$requiredFields as $field) {
- if (empty($payload[$field])) {
- $validationErrors[] = static::getValidationError(
- ValidationError::ERROR_REQUIRED_FIELD,
- $field,
- 'Field is required.'
- );
- }
+ self::validateRequiredField($payload, $field, $validationErrors);
+ }
+ }
+
+ /**
+ * Validates a required field.
+ *
+ * @param array $payload The payload.
+ * @param string $field The field code.
+ * @param ValidationError[] $validationErrors The array of errors to populate.
+ *
+ * @return bool Returns the result of validation.
+ */
+ protected static function validateRequiredField(array $payload, $field, array &$validationErrors)
+ {
+ if (!static::isFieldSet($payload, $field)) {
+ static::setRequiredFieldError($field, $validationErrors);
+
+ return false;
}
+
+ return true;
+ }
+
+ /**
+ * Checks if a required field is set in payload.
+ *
+ * @param array $payload The input payload.
+ * @param string $field Field code.
+ *
+ * @return bool TRUE if field is set; otherwise, false;
+ */
+ protected static function isFieldSet(array $payload, $field)
+ {
+ return isset($payload[$field]);
}
/**
@@ -134,6 +161,37 @@ protected static function doValidate(array $payload, array &$validationErrors)
{
}
+ /**
+ * Sets the required field validation error.
+ *
+ * @param string $code The field code.
+ * @param ValidationError[] $validationErrors The array of errors to populate.
+ */
+ protected static function setRequiredFieldError($code, array &$validationErrors)
+ {
+ $validationErrors[] = static::getValidationError(
+ ValidationError::ERROR_REQUIRED_FIELD,
+ $code,
+ Translator::translate('validation.requiredField')
+ );
+ }
+
+ /**
+ * Sets the invalid field validation error.
+ *
+ * @param string $code The field code.
+ * @param ValidationError[] $validationErrors The array of errors to populate.
+ * @param string $message Optional field message
+ */
+ protected static function setInvalidFieldError($code, array &$validationErrors, $message = '')
+ {
+ $validationErrors[] = static::getValidationError(
+ ValidationError::ERROR_INVALID_FIELD,
+ $code,
+ $message ?: Translator::translate('validation.invalidField')
+ );
+ }
+
/**
* Get the instance of the ValidationError class.
*
diff --git a/src/BusinessLogic/Http/DTO/ParcelInfo.php b/src/BusinessLogic/Http/DTO/ParcelInfo.php
index d73dab16..19e2ec15 100644
--- a/src/BusinessLogic/Http/DTO/ParcelInfo.php
+++ b/src/BusinessLogic/Http/DTO/ParcelInfo.php
@@ -5,6 +5,7 @@
use Packlink\BusinessLogic\DTO\FrontDto;
use Packlink\BusinessLogic\DTO\FrontDtoFactory;
use Packlink\BusinessLogic\DTO\ValidationError;
+use Packlink\BusinessLogic\Language\Translator;
/**
* Class ParcelInfo.
@@ -107,24 +108,36 @@ protected static function doValidate(array $payload, array &$validationErrors)
{
parent::doValidate($payload, $validationErrors);
- $options = array('options' => array('min_range' => 0));
foreach (array('width', 'length', 'height') as $field) {
- if (!empty($payload[$field]) && filter_var($payload[$field], FILTER_VALIDATE_INT, $options) === false) {
- $validationErrors[] = static::getValidationError(
- ValidationError::ERROR_INVALID_FIELD,
- $field,
- ucfirst($field) . ' must be a positive integer.'
- );
- }
+ static::validateNumber($payload, $field, $validationErrors, true);
}
- if (!empty($payload['weight'])
- && (filter_var($payload['weight'], FILTER_VALIDATE_FLOAT) === false || $payload['weight'] <= 0)
- ) {
- $validationErrors[] = static::getValidationError(
- ValidationError::ERROR_INVALID_FIELD,
- 'weight',
- 'Weight must be a positive decimal number.'
+ static::validateNumber($payload, 'weight', $validationErrors, false);
+ }
+
+ /**
+ * Validates if the given value is a number.
+ *
+ * @param array $payload
+ * @param string $field The field key.
+ * @param ValidationError[] $validationErrors The list of validation errors to alter.
+ * @param boolean $isIntValue If true, value must be an integer. If false, value can be integer or float.
+ */
+ private static function validateNumber(array $payload, $field, array &$validationErrors, $isIntValue)
+ {
+ if (!static::isFieldSet($payload, $field)) {
+ // required field validation already happened
+ return;
+ }
+
+ $value = $payload[$field];
+ if ($isIntValue && !is_int($value) || !$isIntValue && !(is_float($value) || is_int($value))) {
+ static::setInvalidFieldError($field, $validationErrors, Translator::translate('validation.integer'));
+ } elseif ($value <= 0) {
+ static::setInvalidFieldError(
+ $field,
+ $validationErrors,
+ Translator::translate('validation.greaterThanZero')
);
}
}
diff --git a/src/BusinessLogic/Language/Interfaces/TranslationService.php b/src/BusinessLogic/Language/Interfaces/TranslationService.php
new file mode 100644
index 00000000..8dcae2ab
--- /dev/null
+++ b/src/BusinessLogic/Language/Interfaces/TranslationService.php
@@ -0,0 +1,32 @@
+String to be translated. If the key is nested it should be sent separated by '.'.
+ * For example:
+ * Translation file has next definition: {"parent": {"child": "childTranslation"}}.
+ * The key for a parent is: "parent", the key for a child is: "parent.child"
+ * @param array $arguments A list of arguments for translation if needed.
+ *
+ * @return string A translated string if translation is found; otherwise, the input key.
+ */
+ public function translate($key, array $arguments = array());
+}
diff --git a/src/BusinessLogic/Language/TranslationService.php b/src/BusinessLogic/Language/TranslationService.php
new file mode 100644
index 00000000..a78efbf4
--- /dev/null
+++ b/src/BusinessLogic/Language/TranslationService.php
@@ -0,0 +1,153 @@
+ ['translationKey' => 'translation']]
+ * @var array
+ */
+ protected static $translations = array();
+
+ /**
+ * @var string $translationsFileBasePath
+ */
+ protected $translationsFileBasePath;
+
+ /**
+ * @var string
+ */
+ private $currentLanguage;
+
+ /**
+ * TranslationService constructor.
+ *
+ * @param string|null $translationsFileBasePath
+ */
+ public function __construct($translationsFileBasePath = null)
+ {
+ $this->translationsFileBasePath = $translationsFileBasePath;
+
+ if (empty($this->translationsFileBasePath)) {
+ $this->translationsFileBasePath = __DIR__ . '/../Resources/lang';
+ }
+ }
+
+ /**
+ * Translates a key to a value defined for that key for a current language.
+ * If the key can not be found for the current language, translation fallback
+ * value will be returned (translation in English).
+ * If the key is not found in fallback passed key will be returned.
+ *
+ * @param string $key
String to be translated. If the key is nested it should be sent separated by '.'.
+ * For example:
+ * Translation file has next definition: {"parent": {"child": "childTranslation"}}.
+ * The key for a parent is: "parent", the key for a child is: "parent.child"
",
+ "marketingEmails": "Ich ermächtige Packlink Shipping S.L., mir kommerzielle Mitteilungen per E-Mail zuzusenden",
+ "submit": "Registrieren",
+ "chooseYourCountry": "Wählen Sie Ihr Land aus",
+ "searchCountry": "Land suchen",
+ "invalidDeliveryVolume": "Das Feld enthält keinen gültigen Lieferumfang."
+ },
+ "onboardingWelcome": {
+ "header": "Richten Sie nun die grundlegenden Informationen ein, damit Sie Versendungen vornehmen können",
+ "steps": "In nur zwei Schritten können wir Ihnen den Spediteur anbieten, der all Ihre Anforderungen erfüllt",
+ "stepOne": "Paketangaben einfügen",
+ "stepTwo": "Absenderadresse eingeben",
+ "startSetUp": "Einrichten beginnen"
+ },
+ "onboardingOverview": {
+ "header": "Fast geschafft! Bitte überprüfen Sie, ob die eingegebenen Informationen richtig sind oder vervollständigen Sie die Angaben, um fortzufahren.",
+ "parcelDetails": "Paketangaben",
+ "senderAddress": "Absenderadresse",
+ "missingInfo": "Fehlende Informationen",
+ "parcelData": "Gewicht %s kg | Höhe %s cm | Breite %s cm | Länge %s cm",
+ "warehouseData": "%s | %s | %s"
+ },
+ "defaultParcel": {
+ "title-onboarding": "1. Paketangaben einfügen",
+ "description-onboarding": "Wir werden diese Standarddaten für Artikel verwenden, die keine festgelegten Abmessungen und kein festgelegtes Gewicht haben. Sie können sie jederzeit über die Registerkarte Einstellungen bearbeiten.",
+ "title-config": "Standardpaket",
+ "description-config": "Wir werden diese Daten für Artikel verwenden, die keine festgelegten Abmessungen und kein festgelegtes Gewicht haben.",
+ "weight": "Gewicht",
+ "height": "Höhe",
+ "width": "Breite",
+ "length": "Länge"
+ },
+ "defaultWarehouse": {
+ "title-onboarding": "2. Absenderadresse eingeben",
+ "description-onboarding": "Wir werden diese Adresse verwenden, um einen Standardabsender für alle Sendungen zu erstellen. Sie können die Adresse jederzeit über die Registerkarte Einstellungen bearbeiten.",
+ "title-config": "Standard-Absenderadresse",
+ "description-config": "Wir werden diese Adresse verwenden, um einen Standardabsender für alle Sendungen zu erstellen. Sie können die Adresse jederzeit bearbeiten.",
+ "alias": "Absendername",
+ "alias-placeholder": "Hauptlager",
+ "name": "Name der Kontaktperson",
+ "name-placeholder": "Name",
+ "surname": "Nachname der Kontaktperson",
+ "surname-placeholder": "Nachname",
+ "company": "Unternehmen",
+ "company-placeholder": "Unternehmen",
+ "country": "Land",
+ "postal_code": "Stadt oder Postleitzahl",
+ "postal_code-placeholder": "-",
+ "address": "Straße und Hausnummer",
+ "address-placeholder": "Anschrift",
+ "phone": "Telefonnummer",
+ "phone-placeholder": "123 456 7777",
+ "email": "E-Mail-Adresse",
+ "email-placeholder": "ihreemail@example.com"
+ },
+ "configuration": {
+ "menu": "Einstellungen",
+ "title": "Einstellungen",
+ "orderStatus": "Bestellstatus",
+ "warehouse": "Standard-Absenderadresse",
+ "parcel": "Standardpaket",
+ "help": "Hilfe",
+ "contactUs": "Kontaktieren Sie uns:",
+ "systemInfo": "Systeminformationen"
+ },
+ "systemInfo": {
+ "title": "Systeminfodatei und debug mode",
+ "debugMode": "Debug mode",
+ "download": "Systeminfodatei herunterladen"
+ },
+ "orderStatusMapping": {
+ "title": "Bestellstatus",
+ "description": "Mit Packlink können Sie Ihren %s Bestellstatus mit Versandinformationen aktualisieren. Sie können die Informationen jederzeit bearbeiten.",
+ "packlinkProShipmentStatus": "VERSANDSTATUS von Packlink PRO",
+ "systemOrderStatus": "BESTELLSTATUS von %s",
+ "none": "Leer",
+ "pending": "Ausstehend",
+ "processing": "In Bearbeitung",
+ "readyForShipping": "Versandfertig",
+ "inTransit": "Unterwegs",
+ "delivered": "Zugestellt",
+ "cancelled": "Storniert"
+ },
+ "shippingServices": {
+ "myServices": "Mein Versandservice",
+ "noServicesTitle": "Sie brauchen nur Ihre Transportdienstleistung hinzuzufügen",
+ "noServicesDescription": "Sie werden Ihrem Kunden zum Zeitpunkt der Kaufabwicklung angezeigt, damit er auswählen kann, welcher Spediteur sein Paket ausliefert. Richten Sie es jetzt ein, damit Sie sich um nichts anderes kümmern müssen. Sie können es jederzeit ändern, um die Versanddienste zu erneuern oder zu aktualisieren.",
+ "addService": "Dienstleistung hinzufügen",
+ "addNewService": "Neue Dienstleistung hinzufügen",
+ "addedSuccessTitle": "Versanddienst erfolgreich hinzugefügt",
+ "addedSuccessDescription": "Sie können die Dienstleistung unter „Meine Dienstleistungen“ bearbeiten.",
+ "deletedSuccessTitle": "Versanddienst erfolgreich gelöscht",
+ "deletedSuccessDescription": "Über die Schaltfläche „Neue Dienstleistung hinzufügen“ können Sie neue Dienstleistungen hinzufügen.",
+ "disableCarriersTitle": "Sie haben Ihre erste Transportdienstleistung erstellt. Möchten Sie die vorherigen Spediteure deaktivieren?",
+ "disableCarriersDescription": "Um Ihnen einen besseren Service anbieten zu können, sollten Sie die vorher genutzten Spediteure deaktivieren.",
+ "successfullyDisabledShippingMethods": "Versanddienste erfolgreich deaktiviert.",
+ "failedToDisableShippingMethods": "Versanddienste konnten nicht deaktiviert werden.",
+ "pickShippingService": "Lieferdienst hinzufügen",
+ "failedGettingServicesTitle": "Beim Abrufen der Versanddienste ist ein Problem aufgetreten",
+ "failedGettingServicesSubtitle": "Möchten Sie es erneut versuchen?",
+ "retry": "Erneut versuchen",
+ "filterModalTitle": "Filter",
+ "applyFilters": "Anwenden",
+ "type": "Typ",
+ "national": "National",
+ "international": "International",
+ "deliveryType": "Versandart",
+ "economic": "Standard",
+ "express": "Express",
+ "parcelOrigin": "Absendeort des Pakets",
+ "collection": "Abholung an Adresse",
+ "dropoff": "Abgabe im Paketshop",
+ "parcelDestination": "Zielort des Pakets",
+ "pickup": "Abholung im Paketshop",
+ "delivery": "Zustellung an Adresse",
+ "carrierLogo": "Logo des Versandunternehmens",
+ "carrier": "Versandpartner",
+ "serviceTitle": "Name des Dienstes",
+ "serviceTitleDescription": "Personalisieren Sie Ihren Versand, indem Sie ihn bearbeiten. Ihre Kunden werden es sehen können.",
+ "transitTime": "Versandlaufzeit",
+ "origin": "Absender",
+ "destination": "Empfänger",
+ "myPrices": "Meine Preise",
+ "packlinkPrices": "Packlink-Preise",
+ "configureService": "Dienst einrichten",
+ "showCarrierLogo": "Meinen Kunden das Logo anzeigen",
+ "pricePolicy": "Preispolitik",
+ "pricePolicyDescription": "Standardmäßig werden die Packlink Basispreise eingestellt sein. Sie können diese jedoch weiter unten genauer konfigurieren.",
+ "configurePricePolicy": "Meine Versandkosten einrichten",
+ "taxClassTitle": "Wählen Sie Ihre gespeicherte Steuerkategorie",
+ "tax": "Steuer",
+ "serviceCountriesTitle": "Verfügbarkeit nach Zielland",
+ "serviceCountriesDescription": "Wählen Sie die Verfügbarkeit der Länder, die von Ihrem Versanddienst unterstützt werden.",
+ "openCountries": "Länder anzeigen",
+ "allCountriesSelected": "Es wurden alle Länder ausgewählt",
+ "oneCountrySelected": "Es wurde ein Land ausgewählt",
+ "selectedCountries": "Es wurden %s Länder ausgewählt",
+ "firstPricePolicyDescription": "Perfekt, nur noch wenige Schritte:
1. Wählen Sie aus, ob Sie diese nach Gewicht und / oder Kaufpreis einstellen möchten.
2. Wählen Sie eine Preispolitik und richten Sie diese ein.",
+ "addFirstPolicy": "Preisregel hinzufügen",
+ "addAnotherPolicy": "Weitere Regel hinzufügen",
+ "from": "Von",
+ "to": "Bis",
+ "price": "Preis",
+ "rangeTypeExplanation": "1. Wählen Sie aus, ob Sie diese nach Gewicht und / oder Kaufpreis einstellen möchten.",
+ "rangeType": "Typenreihe",
+ "priceRange": "Preisklasse",
+ "priceRangeWithData": "Preisklasse: von %s € bis %s €",
+ "weightRange": "Gewichtsklasse",
+ "weightRangeWithData": "Gewichtsklasse: von %s kg bis %s kg",
+ "weightAndPriceRange": "Gewichts- und Preisklasse",
+ "weightAndPriceRangeWithData": "Gewichts- und Preisklasse: von %s kg bis %s kg und von %s € bis %s €",
+ "singlePricePolicy": "Preispolitik %s",
+ "pricePolicyExplanation": "2. Wählen Sie eine Preispolitik und richten Sie diese ein.",
+ "packlinkPrice": "Packlink-Preise",
+ "percentagePacklinkPrices": "% der Packlink-Preise",
+ "percentagePacklinkPricesWithData": "% der Packlink-Preise: %s von %s%",
+ "fixedPrices": "Festpreis",
+ "fixedPricesWithData": "Festpreis: %s €",
+ "increaseExplanation": "Erhöhen: fügen Sie % zum Preis hinzu. Dies wird dann vom Kunden bezahlt.",
+ "reduceExplanation": "Reduzieren: ziehen Sie % vom Preis ab. Dies werden Sie dann selbst zahlen.",
+ "select": "Auswählen",
+ "invalidRange": "Unzulässiger Bereich",
+ "increase": "Erhöhen",
+ "reduce": "Reduzieren",
+ "selectAllCountries": "Alle ausgewählten Länder",
+ "selectCountriesHeader": "Länder, die von Ihrem Versanddienst unterstützt werden",
+ "selectCountriesSubheader": "Wählen Sie die Verfügbarkeit von mindestens einem Land aus und fügen Sie beliebig viele hinzu",
+ "usePacklinkRange": "Für alle anderen Bereiche gelten die Packlink-Preise",
+ "discardChangesQuestion": "Es gibt nicht gespeicherte Änderungen. Sind Sie sicher, dass Sie zurückgehen und sie verwerfen möchten?",
+ "atLeastOneCountry": ""
+ },
+ "orderListAndDetails": {
+ "packlinkOrderDraft": "Packlink Auftragsentwurf",
+ "printed": "Ausgedruckt",
+ "ready": "Bereit",
+ "printLabel": "Versandetikett drucken",
+ "shipmentLabels": "Versandetiketten",
+ "printShipmentLabels": "Packlink PRO Versandetiketten drucken",
+ "shipmentDetails": "Versanddetails",
+ "disablePopUpBlocker": "Bitte deaktivieren Sie den Popup-Blocker auf dieser Seite, um alle Versandetiketten auf einmal zu öffnen.",
+ "date": "Datum",
+ "number": "Nummer",
+ "status": "Status",
+ "print": "Drucken",
+ "carrierTrackingNumbers": "Trackingnummer des Versandunternehmens",
+ "trackIt": "Versand verfolgen",
+ "packlinkReferenceNumber": "Packlink Referenznummer",
+ "packlinkShippingPrice": "Packlink Versandpreis",
+ "viewOnPacklink": "Auf Packlink PRO ansehen",
+ "createDraft": "Entwurf erstellen",
+ "draftIsBeingCreated": "Der Entwurf wird gerade in Packlink PRO erstellt",
+ "createOrderDraft": "Entwurf der Bestellung in Packlink PRO erstellen",
+ "draftCreateFailed": "Der Versuch der Entwurfserstellung ist fehlgeschlagen. Fehler: %s",
+ "packlinkShipping": "Packlink Shipping",
+ "shipmentOrderNotExist": "Die Bestellung mit der Versandreferenznummer %s existiert nicht im Shop",
+ "orderDetailsNotFound": "Bestelldetails nicht gefunden",
+ "orderNotExist": "Die Bestellung mit der ID %s existiert nicht im Shop",
+ "bulkFailCreateFail": "Die Datei der Versandetiketten konnte nicht erstellt werden",
+ "draftOrderDelayed": "Die Erstellung des Entwurfs verzögert sich",
+ "completeServicesSetup": "You need to complete the services setup to create order draft.",
+ "sendWithPacklink": "Send with Packlink"
+ },
+ "checkoutProcess": {
+ "choseDropOffLocation": "Dieser Versanddienst unterstützt die Zustellung an vordefinierte Abgabestellen. Bitte wählen Sie den für Sie günstigsten Ort aus, indem Sie auf \"Abgabestelle auswählen\" klicken.",
+ "selectDropOffLocation": "Abgabestelle auswählen",
+ "changeDropOffLocation": "Abgabestelle ändern",
+ "packageDeliveredTo": "Das Paket wird geliefert an:",
+ "dropOffDeliveryAddress": "Zustelladresse",
+ "changeAddress": "Für Ihre Zustelladresse sind keine Zustellorte verfügbar. Bitte ändern Sie Ihre Adresse.",
+ "shippingServiceNotFound": "Versanddienst nicht gefunden"
+ },
+ "locationPicker": {
+ "monday": "Montag",
+ "tuesday": "Dienstag",
+ "wednesday": "Mittwoch",
+ "thursday": "Donnerstag",
+ "friday": "Freitag",
+ "saturday": "Samstag",
+ "sunday": "Sonntag",
+ "zipCode": "Postleitzahl",
+ "idCode": "ID Code",
+ "selectThisLocation": "Diesen Ort auswählen",
+ "showWorkingHours": "Öffnungszeiten anzeigen",
+ "hideWorkingHours": "Öffnungszeiten ausblenden",
+ "showOnMap": "Auf der Karte anzeigen",
+ "searchBy": "Suche nach Standortname, ID oder Adresse"
+ },
+ "migrationLogMessages": {
+ "removeControllersHooksFailed": "Alte Controller und Hooks konnten nicht entfernt werden auf Grund von: %s",
+ "deleteObsoleteFilesFailed": "Alte Dateien konnten nicht gelöscht werden auf Grund von: %s",
+ "oldAPIKeyDetected.": "Alter API-Schlüssel erkannt.",
+ "successfullyLoggedIn": "Erfolgreich mit bestehendem API-Schlüssel angemeldet.",
+ "removingObsoleteFiles.": "Veraltete Dateien werden entfernt.",
+ "cannotEnqueueUpgradeShopDetailsTask": "UpgradeShopDetailsTask kann aus folgenden Gründen nicht in die Warteschlange gestellt werden: %s",
+ "deletingOldPluginDta.": "Alte Plugin-Daten werden gelöscht.",
+ "cannotRetrieveOrderReferences": "Bestellreferenzen können nicht abgerufen werden auf Grund von: %s",
+ "createOrderReferenceFailed": "Referenz für Auftrag %s konnte nicht erstellt werden.",
+ "setLabelsFailed": "Versandetiketten für Bestellung mit Referenz %s konnten nicht erstellt werden.",
+ "setTrackingInfoFailed": "Fehler beim Festlegen der Tracking-Informationen für die Bestellung mit Referenz %s",
+ "orderNotFound": "Auftrag mit Referenz %s nicht gefunden."
+ },
+ "systemLogMessages": {
+ "errorCreatingDefaultTask": "Fehler beim Erstellen der Standardkonfiguration des Task-Runner-Status.",
+ "webhookReceived": "Webhook von Packlink erhalten",
+ "couldNotDelete": "Element %s mit ID %s konnte nicht gelöscht werden",
+ "entityCannotBeSaved": "Element %s mit ID %s kann nicht gespeichert werden.",
+ "entityCannotBeUpdated": "Element %s mit ID %s kann nicht aktualisiert werden.",
+ "fieldIsNotIndexed": "Feld %s ist nicht indiziert!",
+ "unknownOrNotIndexed": "Unbekannte oder nicht indizierte OrderBy-Spalte %s",
+ "dirNotCreated": "Das Verzeichnis \"%s\" wurde nicht erstellt",
+ "failedCreatingBackup": "Fehler beim Erstellen des Backup-Versanddienstes.",
+ "backupServiceNotFound": "Backup-Versanddienst konnte nicht gefunden werden."
+ },
+ "autoTest": {
+ "dbNotAccessible.": "Zugriff auf Datenbank nicht möglich.",
+ "taskCouldNotBeStarted.": "Die Aufgabe konnte nicht gestartet werden.",
+ "moduleAutoTest": "Automatischer Test PacklinkPRO-Modul",
+ "useThisPageTestConfiguration": "Auf dieser Seite können Sie die Systemkonfiguration und die Dienste des PacklinkPRO-Moduls testen.",
+ "start": "Start",
+ "downloadTestLog": "Testprotokoll herunterladen",
+ "openModule": "PacklinkPRO-Modul öffnen",
+ "autotestPassedSuccessfully": "Der automatische Test wurde erfolgreich abgeschlossen!",
+ "testNotSuccessful": "Der Test wurde nicht erfolgreich abgeschlossen!"
+ }
+}
\ No newline at end of file
diff --git a/src/BusinessLogic/Resources/lang/en.json b/src/BusinessLogic/Resources/lang/en.json
new file mode 100644
index 00000000..5cc5d3bb
--- /dev/null
+++ b/src/BusinessLogic/Resources/lang/en.json
@@ -0,0 +1,355 @@
+{
+ "general": {
+ "packlinkPro": "Packlink PRO Shipping",
+ "saveUp": "Save up to 70% on your shipping costs. No fixed fees, no minimum shipping volume required. Manage all your shipments in a single platform.",
+ "packlinkShipping": "Packlink Shipping S.L.",
+ "noContract": "No contract needed! More than 300 transport services into a single platform. You can connect all your ecommerce and manage all your shipments in Packlink PRO.",
+ "developedAndManaged": "Developed and managed by Packlink",
+ "generalConditions": "General conditions",
+ "basicSettings": "Basic settings",
+ "contactUs": "Contact us",
+ "systemInfo": "System info",
+ "debugMode": "Debug mode",
+ "help": "Help",
+ "downloadSystemInfoFile": "Download system info file",
+ "curlIsNotInstalled": "cURL is not installed or enabled in your PHP installation. This is required for background task to work. Please install it and then refresh this page.",
+ "loading": "Loading...",
+ "save": "Save",
+ "saveChanges": "Save changes",
+ "accept": "Accept",
+ "cancel": "Cancel",
+ "continue": "Continue",
+ "complete": "Complete",
+ "add": "Add",
+ "edit": "Edit",
+ "delete": "Delete",
+ "discard": "Discard"
+ },
+ "validation": {
+ "requiredField": "This field is required.",
+ "invalidField": "This field is invalid.",
+ "invalidEmail": "This field must be valid email.",
+ "shortPassword": "The password must be at least %s characters long.",
+ "invalidPhone": "This field must be valid phone number.",
+ "maxLength": "The field cannot have more than %s characters.",
+ "numeric": "Value must be valid number.",
+ "greaterThanZero": "Value must be greater than 0.",
+ "nonNegative": "Field cannot have a negative value.",
+ "numberOfDecimalPlaces": "Field must have 2 decimal places.",
+ "integer": "Field must be an integer.",
+ "invalidCountryList": "You must select destination countries.",
+ "invalidLanguage": "Field is not a valid language.",
+ "invalidPlatformCountry": "Field is not a valid platform country.",
+ "invalidUrl": "Field must be a valid URL.",
+ "invalidFieldValue": "Field must be set to \"%s\".",
+ "invalidMaxValue": "Maximal allowed value is %s."
+ },
+ "login": {
+ "apiKey": "Api key",
+ "apiKeyIncorrect": "API key was incorrect.",
+ "dontHaveAccount": "Don't have an account?",
+ "welcome": "Welcome to Packlink PRO",
+ "connectYourService": "Connect your service using your key. You'll find it in the \"Packlink Pro API Key\" section of the \"Settings\".",
+ "validateApiKey": "Validate API key",
+ "chooseYourCountry": "Choose your country to start the registration process",
+ "registerMe": "Register me"
+ },
+ "countries": {
+ "ES": "Spain",
+ "DE": "Germany",
+ "FR": "France",
+ "IT": "Italy",
+ "AT": "Austria",
+ "NL": "Netherlands",
+ "BE": "Belgium",
+ "PT": "Portugal",
+ "TR": "Turkey",
+ "IE": "Ireland",
+ "GB": "Great Britain",
+ "HU": "Hungary",
+ "PL": "Poland",
+ "CH": "Switzerland",
+ "LU": "Luxembourg",
+ "AR": "Argentina",
+ "US": "United States",
+ "BO": "Bolivia",
+ "MX": "Mexico",
+ "CL": "Chile",
+ "CZ": "Czech Republic",
+ "SE": "Sweden"
+ },
+ "register": {
+ "logIn": "Log in",
+ "email": "Email",
+ "password": "Password",
+ "haveAccount": "Already have an account?",
+ "startEnjoying": "Start enjoying Packlink PRO!",
+ "registerAccount": "Register your account",
+ "getToKnowYou": "We would like to get to know you better in order to adapt to you and to send you an individual offer",
+ "monthlyShipmentVolume": "What is your monthly shipment volume?",
+ "phone": "Phone number",
+ "termsAndConditions": "
",
+ "marketingEmails": "I authorise Packlink Shipping S.L. to send me commercial communications by e-mail",
+ "submit": "Register",
+ "chooseYourCountry": "Choose your country",
+ "searchCountry": "Search country",
+ "invalidDeliveryVolume": "Field is not a valid delivery volume."
+ },
+ "onboardingWelcome": {
+ "header": "Let's set up basic information so that you can make shipments",
+ "steps": "It's just two steps that we need to go through to offer you the carrier that best suits your needs",
+ "stepOne": "Set parcel details",
+ "stepTwo": "Set sender's address",
+ "startSetUp": "Start set up"
+ },
+ "onboardingOverview": {
+ "header": "Almost there! Please check that the entered information is correct or complete it in order to continue.",
+ "parcelDetails": "Parcel details",
+ "senderAddress": "Sender's Address",
+ "missingInfo": "Missing information",
+ "parcelData": "Weight %s kg | Height %s cm | Width %s cm | Length %s cm",
+ "warehouseData": "%s | %s | %s"
+ },
+ "defaultParcel": {
+ "title-onboarding": "1. Set parcel details",
+ "description-onboarding": "We will use this default data for items that do not have defined dimensions and weight. You can edit them whenever you like via the settings tab.",
+ "title-config": "Default parcel",
+ "description-config": "We will use this data for items that do not have defined dimensions and weight.",
+ "weight": "Weight",
+ "height": "Height",
+ "width": "Width",
+ "length": "Length"
+ },
+ "defaultWarehouse": {
+ "title-onboarding": "2. Set sender’s address",
+ "description-onboarding": "We will use this address to create a default sender for all shipments. You will be able to edit it whenever you wish via the settings tab.",
+ "title-config": "Default sender address",
+ "description-config": "We will use this address to create a default sender for all shipments. You can edit it at any time.",
+ "alias": "Warehouse name",
+ "alias-placeholder": "Main warehouse",
+ "name": "Name of contact person",
+ "name-placeholder": "Name",
+ "surname": "Surname of contact person",
+ "surname-placeholder": "Surname",
+ "company": "Company name",
+ "company-placeholder": "Company",
+ "country": "Country",
+ "postal_code": "City or postcode",
+ "postal_code-placeholder": "-",
+ "address": "Address",
+ "address-placeholder": "Address",
+ "phone": "Phone number",
+ "phone-placeholder": "123 456 7777",
+ "email": "Email",
+ "email-placeholder": "youremail@example.com"
+ },
+ "configuration": {
+ "menu": "Settings",
+ "title": "Settings",
+ "orderStatus": "Order status",
+ "warehouse": "Default sender address",
+ "parcel": "Default parcel",
+ "help": "Help",
+ "contactUs": "Contact us at:",
+ "systemInfo": "System information"
+ },
+ "systemInfo": {
+ "title": "System information file and debug mode",
+ "debugMode": "Debug mode",
+ "download": "Download system information"
+ },
+ "orderStatusMapping": {
+ "title": "Order status",
+ "description": "With Packlink you can update your %s order status with shipping information. You can edit it at any time.",
+ "packlinkProShipmentStatus": "Packlink PRO SHIPMENT STATUS",
+ "systemOrderStatus": "%s ORDER STATUS",
+ "none": "None",
+ "pending": "Pending",
+ "processing": "Processing",
+ "readyForShipping": "Ready for shipping",
+ "inTransit": "In transit",
+ "delivered": "Delivered",
+ "cancelled": "Canceled"
+ },
+ "shippingServices": {
+ "myServices": "My shipping services",
+ "noServicesTitle": "You just need to add your shipment services",
+ "noServicesDescription": "They will be shown to your customer at the time of checkout, so that they can choose which carrier will deliver their parcel. Set it up now so that you don't need to worry about anything else. You can change it whenever you wish, to renew or upgrade shipping services.",
+ "addService": "Add service",
+ "addNewService": "Add new service",
+ "addedSuccessTitle": "Shipping service added successfully",
+ "addedSuccessDescription": "You can edit the service from the \"My services\" section.",
+ "deletedSuccessTitle": "Shipping service deleted successfully",
+ "deletedSuccessDescription": "You can add new services from the \"Add new service\" button.",
+ "disableCarriersTitle": "You have created your first shipment service. Do you want to disable previous carriers?",
+ "disableCarriersDescription": "To provide you with a better service, it is important to disable the carriers you previously used.",
+ "successfullyDisabledShippingMethods": "Successfully disabled shipping methods.",
+ "failedToDisableShippingMethods": "Failed to disable shipping methods.",
+ "pickShippingService": "Add delivery services",
+ "failedGettingServicesTitle": "We are having troubles getting shipping services",
+ "failedGettingServicesSubtitle": "Do you want to retry?",
+ "retry": "Retry",
+ "filterModalTitle": "Filters",
+ "applyFilters": "Apply",
+ "type": "Type",
+ "national": "Domestic",
+ "international": "International",
+ "deliveryType": "Type of shipment",
+ "economic": "Budget",
+ "express": "Express",
+ "parcelOrigin": "Parcel origin",
+ "collection": "Collection",
+ "dropoff": "Drop off",
+ "parcelDestination": "Parcel destination",
+ "pickup": "Pick up",
+ "delivery": "Delivery",
+ "carrierLogo": "Carrier logo",
+ "carrier": "Carrier",
+ "serviceTitle": "Service title",
+ "serviceTitleDescription": "Customise your shipment by editing it. Your customers will be able to see it.",
+ "transitTime": "Transit Time",
+ "origin": "Origin",
+ "destination": "Destination",
+ "myPrices": "My prices",
+ "packlinkPrices": "Packlink prices",
+ "configureService": "Set up service",
+ "showCarrierLogo": "Show carrier logo to my customers",
+ "pricePolicy": "Price policy",
+ "pricePolicyDescription": "The default will be Packlink's basic prices. But you can configure these in a more precise way below.",
+ "configurePricePolicy": "Set up my shipment prices",
+ "taxClassTitle": "Choose your saved tax class",
+ "tax": "Tax",
+ "serviceCountriesTitle": "Availability by destination country",
+ "serviceCountriesDescription": "Select the availability for the countries that are supported for your shipping service.",
+ "openCountries": "See countries",
+ "allCountriesSelected": "All countries selected",
+ "oneCountrySelected": "One country selected",
+ "selectedCountries": "%s countries selected.",
+ "firstPricePolicyDescription": "Perfect, just a couple of steps:
1. Choose whether you want to set them by weight and/or purchase price.
2. Choose a price policy and set it up.",
+ "addFirstPolicy": "Add price rule",
+ "addAnotherPolicy": "Add another rule",
+ "from": "From",
+ "to": "To",
+ "price": "Price",
+ "rangeTypeExplanation": "1. Choose whether you want to set them by weight and/or purchase price.",
+ "rangeType": "Range type",
+ "priceRange": "Price range",
+ "priceRangeWithData": "Price range: from %s€ to %s€",
+ "weightRange": "Weight range",
+ "weightRangeWithData": "Weight range: from %s kg to %s kg",
+ "weightAndPriceRange": "Weight and price range",
+ "weightAndPriceRangeWithData": "Weight and price range: from %s kg to %s kg and from %s€ to %s€",
+ "singlePricePolicy": "Price policy %s",
+ "pricePolicyExplanation": "2. Choose a price policy and set it up.",
+ "packlinkPrice": "Packlink Price",
+ "percentagePacklinkPrices": "% of Packlink prices",
+ "percentagePacklinkPricesWithData": "% of Packlink prices: %s by %s%",
+ "fixedPrices": "Fixed price",
+ "fixedPricesWithData": "Fixed price: %s€",
+ "increaseExplanation": "Increase: add a % to the price, this will be paid by the customer.",
+ "reduceExplanation": "Reduce: deduct a % from the price, you will pay for it yourself.",
+ "select": "Select",
+ "invalidRange": "Invalid range",
+ "increase": "increase",
+ "reduce": "reduce",
+ "selectAllCountries": "All selected countries",
+ "selectCountriesHeader": "Countries supported for your shipping service",
+ "selectCountriesSubheader": "Select availability of at least one country and add as many required",
+ "usePacklinkRange": "For all other ranges, apply Packlink prices",
+ "discardChangesQuestion": "There are unsaved changes. Are you sure you want to go back and discard them?",
+ "atLeastOneCountry": "At least one country must be selected."
+ },
+ "orderListAndDetails": {
+ "packlinkOrderDraft": "Packlink order draft",
+ "printed": "Printed",
+ "ready": "Ready",
+ "printLabel": "Print label",
+ "shipmentLabels": "Shipment Labels",
+ "printShipmentLabels": "Print Packlink PRO Shipment Labels",
+ "shipmentDetails": "Shipment details",
+ "disablePopUpBlocker": "Please disable pop-up blocker on this page in order to bulk open shipment labels",
+ "date": "Date",
+ "number": "Number",
+ "status": "Status",
+ "print": "Print",
+ "carrierTrackingNumbers": "Carrier tracking numbers",
+ "trackIt": "Track it!",
+ "packlinkReferenceNumber": "Packlink reference number",
+ "packlinkShippingPrice": "Packlink shipping price",
+ "viewOnPacklink": "View on Packlink PRO",
+ "createDraft": "Create Draft",
+ "draftIsBeingCreated": "Draft is currently being created in Packlink PRO",
+ "createOrderDraft": "Create order draft in Packlink PRO",
+ "draftCreateFailed": "Previous attempt to create a draft failed. Error: %s",
+ "packlinkShipping": "Packlink Shipping",
+ "shipmentOrderNotExist": "Order with shipment reference %s doesn't exist in the shop",
+ "orderDetailsNotFound": "Order details not found",
+ "orderNotExist": "Order with ID %s doesn't exist in the shop",
+ "bulkFailCreateFail": "Unable to create bulk labels file",
+ "draftOrderDelayed": "Creation of the draft is delayed",
+ "completeServicesSetup": "You need to complete the services setup to create order draft.",
+ "sendWithPacklink": "Send with Packlink"
+ },
+ "checkoutProcess": {
+ "choseDropOffLocation": "This shipping service supports delivery to pre-defined drop-off locations. Please choose location that suits you the most by clicking on the \"Select drop-off location\" button.",
+ "selectDropOffLocation": "Select drop-off location",
+ "changeDropOffLocation": "Change drop-off location",
+ "packageDeliveredTo": "Package will be delivered to:",
+ "dropOffDeliveryAddress": "Drop-Off delivery address",
+ "changeAddress": "There are no delivery locations available for your delivery address. Please change your address.",
+ "shippingServiceNotFound": "Shipping service not found"
+ },
+ "locationPicker": {
+ "monday": "Monday",
+ "tuesday": "Tuesday",
+ "wednesday": "Wednesday",
+ "thursday": "Thursday",
+ "friday": "Friday",
+ "saturday": "Saturday",
+ "sunday": "Sunday",
+ "zipCode": "Zip code",
+ "idCode": "ID code",
+ "selectThisLocation": "Select this location",
+ "showWorkingHours": "Show working hours",
+ "hideWorkingHours": "Hide working hours",
+ "showOnMap": "Show on map",
+ "searchBy": "Search by location name, id or address"
+ },
+ "migrationLogMessages": {
+ "removeControllersHooksFailed": "Failed to remove old controllers and hooks because: %s",
+ "deleteObsoleteFilesFailed": "Could not delete obsolete files because: %s",
+ "oldAPIKeyDetected.": "Old API key detected.",
+ "successfullyLoggedIn": "Successfully logged in with existing api key.",
+ "removingObsoleteFiles.": "Removing obsolete files.",
+ "cannotEnqueueUpgradeShopDetailsTask": "Cannot enqueue UpgradeShopDetailsTask because: %s",
+ "deletingOldPluginDta.": "Deleting old plugin data.",
+ "cannotRetrieveOrderReferences": "Cannot retrieve order references because: %s",
+ "createOrderReferenceFailed": "Failed to create reference for order %s",
+ "setLabelsFailed": "Failed to set labels for order with reference %s",
+ "setTrackingInfoFailed": "Failed to set tracking info for order with reference %s",
+ "orderNotFound": "Order with reference %s not found."
+ },
+ "systemLogMessages": {
+ "errorCreatingDefaultTask": "Error creating default task runner status configuration.",
+ "webhookReceived": "Webhook from Packlink received.",
+ "couldNotDelete": "Could not delete entity %s with ID %s",
+ "entityCannotBeSaved": "Entity %s with ID %s cannot be saved.",
+ "entityCannotBeUpdated": "Entity %s with ID %s cannot be updated.",
+ "fieldIsNotIndexed": "Field %s is not indexed!",
+ "unknownOrNotIndexed": "Unknown or not indexed OrderBy column %s",
+ "dirNotCreated": "Directory \"%s\" was not created",
+ "failedCreatingBackup": "Failed creating backup service.",
+ "backupServiceNotFound": "Backup service not found."
+ },
+ "autoTest": {
+ "dbNotAccessible.": "Database not accessible.",
+ "taskCouldNotBeStarted.": "Task could not be started.",
+ "moduleAutoTest": "PacklinkPRO module auto-test",
+ "useThisPageTestConfiguration": "Use this page to test the system configuration and PacklinkPRO module services.",
+ "start": "Start",
+ "downloadTestLog": "Download test log",
+ "openModule": "Open PacklinkPRO module",
+ "autotestPassedSuccessfully": "Auto-test passed successfully!",
+ "testNotSuccessful": "The test did not complete successfully."
+ }
+}
\ No newline at end of file
diff --git a/src/BusinessLogic/Resources/lang/es.json b/src/BusinessLogic/Resources/lang/es.json
new file mode 100644
index 00000000..d914a7ba
--- /dev/null
+++ b/src/BusinessLogic/Resources/lang/es.json
@@ -0,0 +1,355 @@
+{
+ "general": {
+ "packlinkPro": "Packlink PRO Shipping",
+ "saveUp": "Ahorra hasta un 70% en tus gastos de envío. Sin tarifas fijas, sin volumen de envíos mínimo. Gestiona todos tus envíos en una sola plataforma.",
+ "packlinkShipping": "Packlink Shipping S.L.",
+ "noContract": "Sin contratos, accede inmediatamente a más de 300 servicios de transporte en una única plataforma. No importa cuantos puntos de venta tengas, todo lo podrás gestionar desde Packlink PRO.",
+ "developedAndManaged": "Desarrollado y gestionado por Packlink",
+ "generalConditions": "Condiciones generales",
+ "basicSettings": "Configuración",
+ "contactUs": "Contacta con nosotros",
+ "systemInfo": "Información del sistema",
+ "debugMode": "Debug mode",
+ "help": "Ayuda",
+ "downloadSystemInfoFile": "Descargar el archivo de información del sistema",
+ "curlIsNotInstalled": "cURL no está instalado ni habilitado en tu instalación de PHP. Es necesario para que funcione la tarea en segundo plano. Por favor, instálalo y luego actualiza esta página.",
+ "loading": "Cargando...",
+ "save": "Guardar",
+ "saveChanges": "Guardar cambios",
+ "accept": "Aceptar",
+ "cancel": "Cancelar",
+ "continue": "Continuar",
+ "complete": "Completar",
+ "add": "Añadir",
+ "edit": "Editar",
+ "delete": "Borrar",
+ "discard": "Ignorar"
+ },
+ "validation": {
+ "requiredField": "Esta campo es obligatorio.",
+ "invalidField": "This field is invalid.",
+ "invalidEmail": "El campo debe ser un correo electrónico válido.",
+ "shortPassword": "La contraseña debe contener %s caracteres como mínimo.",
+ "invalidPhone": "Este campo deber ser un número de teléfono válido.",
+ "maxLength": "Este campo no puede tener más de % caracteres.",
+ "numeric": "Debe ser un valor numérico.",
+ "greaterThanZero": "El valor debe ser mayor que 0.",
+ "nonNegative": "Field cannot have a negative value.",
+ "numberOfDecimalPlaces": "El campo debe tener 2 decimales.",
+ "integer": "El campo debe ser un número entero.",
+ "invalidCountryList": "Debes seleccionar los países de destino.",
+ "invalidLanguage": "Field is not a valid language.",
+ "invalidPlatformCountry": "Field is not a valid platform country.",
+ "invalidUrl": "Field must be a valid URL.",
+ "invalidFieldValue": "Field must be set to \"%s\".",
+ "invalidMaxValue": "Maximal allowed value is %s."
+ },
+ "login": {
+ "apiKey": "Api key",
+ "apiKeyIncorrect": "Clave de API incorrecta",
+ "dontHaveAccount": "¿No tienes una cuenta?",
+ "welcome": "Te damos la bienvenida a Packlink PRO",
+ "connectYourService": "Conecta tu servicio mediante tu clave. La encontrarás en la sección \"Configuración\" apartado \"Packlink Pro API Key\"",
+ "validateApiKey": "Validar API key",
+ "chooseYourCountry": "Elige tu país para comenzar el registro",
+ "registerMe": "Registrarme"
+ },
+ "countries": {
+ "ES": "España",
+ "DE": "Alemania",
+ "FR": "Francia",
+ "IT": "Italia",
+ "AT": "Austria",
+ "NL": "Países Bajos",
+ "BE": "Bélgica",
+ "PT": "Portugal",
+ "TR": "Turquía",
+ "IE": "Irlanda",
+ "GB": "Reino Unido",
+ "HU": "Hungría",
+ "PL": "Polonia",
+ "CH": "Suiza",
+ "LU": "Luxemburgo",
+ "AR": "Argentina",
+ "US": "Estados Unidos",
+ "BO": "Bolivia",
+ "MX": "México",
+ "CL": "Chile",
+ "CZ": "Republica checa",
+ "SE": "Suecia"
+ },
+ "register": {
+ "logIn": "Iniciar sesión",
+ "email": "Correo electrónico",
+ "password": "Contraseña",
+ "haveAccount": "¿Ya tienes una cuenta?",
+ "startEnjoying": "¡Empieza a disfrutar de Packlink PRO!",
+ "registerAccount": "Registro",
+ "getToKnowYou": "Queremos conocerte mejor para adaptarnos a ti y hacerte una propuesta personalizada.",
+ "monthlyShipmentVolume": "¿Cuántos envíos sueles hacer al mes?",
+ "phone": "Teléfono",
+ "termsAndConditions": "
",
+ "marketingEmails": "Autorizo a Packlink Shipping S.L. a enviarme información comercial por correo electrónico",
+ "submit": "Regístrate",
+ "chooseYourCountry": "Elige tu país",
+ "searchCountry": "Busca el país",
+ "invalidDeliveryVolume": "El campo no contiene un volumen de entrega válido."
+ },
+ "onboardingWelcome": {
+ "header": "Vamos a configurar tu información básica para poder hacer envíos",
+ "steps": "Son solo dos pasos, los necesitamos para ofrecerte los servicios de transporte que más se adaptan a tus necesidades.",
+ "stepOne": "Configurar los detalles del paquete",
+ "stepTwo": "Configurar la dirección del remitente",
+ "startSetUp": "Comenzar con la configuración"
+ },
+ "onboardingOverview": {
+ "header": "Ya casi estamos. Por favor, comprueba que la información es correcta o complétala para continuar.",
+ "parcelDetails": "Detalle del paquete",
+ "senderAddress": "Dirección del remitente",
+ "missingInfo": "Faltan datos",
+ "parcelData": "Peso %s kg | Alto %s cm | Ancho %s cm | Largo %s cm",
+ "warehouseData": "%s | %s | %s"
+ },
+ "defaultParcel": {
+ "title-onboarding": "1. Configurar los detalles del paquete",
+ "description-onboarding": "Utilizaremos estos datos predeterminados para los artículos que no tengan dimensiones y peso definidos. Podrás editarlos cuando quieras desde la pestaña de configuración.",
+ "title-config": "Paquete predeterminado",
+ "description-config": "Utilizaremos estos datos para los artículos que no tengan dimensiones y peso definidos.",
+ "weight": "Peso",
+ "height": "Alto",
+ "width": "Ancho",
+ "length": "Largo"
+ },
+ "defaultWarehouse": {
+ "title-onboarding": "2. Configurar la dirección del remitente",
+ "description-onboarding": "Utilizaremos esta dirección para crear un remitente por defecto que valga para todos los envíos. Podrás editarla cuando quieras desde la pestaña de configuración.",
+ "title-config": "Dirección del remitente por defecto",
+ "description-config": "Utilizaremos esta dirección para crear un remitente por defecto que valga para todos los envíos.",
+ "alias": "Nombre del almacén",
+ "alias-placeholder": "Almacen principal",
+ "name": "Nombre de la persona de contacto",
+ "name-placeholder": "Nombe de la persona",
+ "surname": "Apellido de la persona de contacto",
+ "surname-placeholder": "Apellido de la persona",
+ "company": "Nombre de la empresa",
+ "company-placeholder": "Empresa S.A.",
+ "country": "País",
+ "postal_code": "Ciudad o código postal",
+ "postal_code-placeholder": "-",
+ "address": "Dirección",
+ "address-placeholder": "Dirección",
+ "phone": "Número de teléfono",
+ "phone-placeholder": "123 456 7777",
+ "email": "Correo electrónico",
+ "email-placeholder": "tucorreo@example.com"
+ },
+ "configuration": {
+ "menu": "Configuración",
+ "title": "Configuración",
+ "orderStatus": "Estado de la orden",
+ "warehouse": "Almacén por defecto",
+ "parcel": "Paquete predeterminado",
+ "help": "Ayuda",
+ "contactUs": "Contáctanos:",
+ "systemInfo": "Información del sistema"
+ },
+ "systemInfo": {
+ "title": "System information file and debug mode",
+ "debugMode": "Debug mode",
+ "download": "Download system information"
+ },
+ "orderStatusMapping": {
+ "title": "Estado de la orden",
+ "description": "Con Packlink puedes actualizar el estado de tu pedido de %s con la información de envío. Puedes editarla en cualquier momento.",
+ "packlinkProShipmentStatus": "ESTADO DEL ENVÍO de Packlink PRO",
+ "systemOrderStatus": "ESTADO DEL PEDIDO de %s",
+ "none": "Ninguno",
+ "pending": "Pendiente",
+ "processing": "Procesando",
+ "readyForShipping": "Listo para enviar",
+ "inTransit": "En tránsito",
+ "delivered": "Entregado",
+ "cancelled": "Cancelado"
+ },
+ "shippingServices": {
+ "myServices": "Mis servicios de envío",
+ "noServicesTitle": "Solo queda añadir tus servicios de envío",
+ "noServicesDescription": "Se mostrarán a tu cliente en el momento del checkout, así podrá elegir qué transportista le llevará su paquete. Lo configuras ahora y no tienes que preocuparte por nada más, puedes cambiarlo siempre que quieras para renovar o ampliar servicios de envío.",
+ "addService": "Añadir servicio",
+ "addNewService": "Añadir nuevo servicio",
+ "addedSuccessTitle": "Servicio de envío añadido correctamente",
+ "addedSuccessDescription": "Podrás editarlo desde la sección \"Mis servicios\".",
+ "deletedSuccessTitle": "Servicio de envío eliminado correctamente",
+ "deletedSuccessDescription": "Puedes añadir nuevos servicios con el botón \"Añadir nuevo servicio\".",
+ "disableCarriersTitle": "Has creado tu primer servicio de envío. ¿Quieres desabilitar los transportistas anteriores?",
+ "disableCarriersDescription": "Para ofrecerte un mejor servicio, es importante desabilitar los transportistas que tenías previamente.",
+ "successfullyDisabledShippingMethods": "Servicios de envío correctamente deseleccionados.",
+ "failedToDisableShippingMethods": "Error al deshabilitar los servicios de envío.",
+ "pickShippingService": "Añadir servicios de envío",
+ "failedGettingServicesTitle": "Tenemos dificultades para obtener servicios de envío",
+ "failedGettingServicesSubtitle": "¿Quieres volverlo a intentar?",
+ "retry": "Volver a intentar",
+ "filterModalTitle": "Filtros",
+ "applyFilters": "Aplicar",
+ "type": "Tipo",
+ "national": "Nacional",
+ "international": "Internacional",
+ "deliveryType": "Servicio",
+ "economic": "Económico",
+ "express": "Express",
+ "parcelOrigin": "Origen",
+ "collection": "Recogida",
+ "dropoff": "Drop off",
+ "parcelDestination": "Destino",
+ "pickup": "Pick up",
+ "delivery": "Entrega",
+ "carrierLogo": "Logo del transportista",
+ "carrier": "Transportista",
+ "serviceTitle": "Nombre del servicio",
+ "serviceTitleDescription": "Personaliza tu envío editándolo. Será visible para tus clientes.",
+ "transitTime": "Tiempo de tránsito",
+ "origin": "Origen",
+ "destination": "Destino",
+ "myPrices": "Mis precios",
+ "packlinkPrices": "Precios de Packlink",
+ "configureService": "Configura el servicio",
+ "showCarrierLogo": "Mostrar logo del transportista a mis clientes.",
+ "pricePolicy": "Política de precios",
+ "pricePolicyDescription": "Por defecto serán los precios base de Packlink. Pero puedes configurarlos de manera más precisa a continuación.",
+ "configurePricePolicy": "Configurar mis precios de envío",
+ "taxClassTitle": "Elige tu tipo de impuesto guardado",
+ "tax": "Impuestos",
+ "serviceCountriesTitle": "Disponibilidad por país de destino",
+ "serviceCountriesDescription": "Selecciona la disponibilidad para los países que hay permitidos para tu servicio de envío.",
+ "openCountries": "Ver países",
+ "allCountriesSelected": "Todos los países seleccionados",
+ "oneCountrySelected": "Un país seleccionado",
+ "selectedCountries": "%s países seleccionados",
+ "firstPricePolicyDescription": "Perfecto, son un par de pasos:
1- Elige si quieres fijarlos por el peso y/o el precio de la compra.
2- Elige una política de precios y configúrala.",
+ "addFirstPolicy": "Añadir regla de precio",
+ "addAnotherPolicy": "Añadir otro precio",
+ "from": "Desde",
+ "to": "Hasta",
+ "price": "Precio",
+ "rangeTypeExplanation": "1- Elige si quieres fijarlos por el peso y/o el precio de la compra.",
+ "rangeType": "Tipo de rango",
+ "priceRange": "Rango de precio",
+ "priceRangeWithData": "Rango de precio: desde %s€ hasta %s€",
+ "weightRange": "Rango de peso",
+ "weightRangeWithData": "Rango de peso: desde %s kg hasta %s kg",
+ "weightAndPriceRange": "Rango de peso y precio",
+ "weightAndPriceRangeWithData": "Rango de peso y precio: desde %s kg hasta %s kg y desde %s€ hasta %s€",
+ "singlePricePolicy": "Política de precio %s",
+ "pricePolicyExplanation": "2- Elige una política de precios y configúrala.",
+ "packlinkPrice": "Precio Packlink",
+ "percentagePacklinkPrices": "% de los precio de Packlink",
+ "percentagePacklinkPricesWithData": "% de los precio de Packlink: %s por %s%",
+ "fixedPrices": "Precio fijo",
+ "fixedPricesWithData": "Precio fijo: %s€",
+ "increaseExplanation": "Incrementar: añade un % al precio, lo pagará el cliente.",
+ "reduceExplanation": "Reducir: descuenta un % al precio, lo pagarás tú.",
+ "select": "Elige",
+ "invalidRange": "Rango no válido",
+ "increase": "incrementar",
+ "reduce": "reducir",
+ "selectAllCountries": "Selecionar todos los países",
+ "selectCountriesHeader": "Países permitidos para tu servicio de envío",
+ "selectCountriesSubheader": "Selecciona la disponibilidad de al menos un país y añade tantos como necesites",
+ "usePacklinkRange": "Para el resto de rangos, aplicar precios Packlink",
+ "discardChangesQuestion": "Algunos cambios no se han guardado. ¿Estás seguro de que quieres volver e ignorar los cambios?",
+ "atLeastOneCountry": ""
+ },
+ "orderListAndDetails": {
+ "packlinkOrderDraft": "Borrador del pedido de Packlink",
+ "printed": "Impreso",
+ "ready": "Listo",
+ "printLabel": "Imprimir etiquetas",
+ "shipmentLabels": "Etiquetas de los envíos",
+ "printShipmentLabels": "Imprimir Packlink PRO etiquetas de los envíos",
+ "shipmentDetails": "Detalles del envío",
+ "disablePopUpBlocker": "Deshabilita el bloqueador de elementos emergentes en esta página para abrir de forma masiva las etiquetas de envío",
+ "date": "Fecha",
+ "number": "Número",
+ "status": "Estado",
+ "print": "Imprimir",
+ "carrierTrackingNumbers": "Número de tracking del transportista",
+ "trackIt": "Seguimiento",
+ "packlinkReferenceNumber": "Número de referencia Packlink",
+ "packlinkShippingPrice": "Precio de envío de Packlink",
+ "viewOnPacklink": "Ver en Packlink PRO",
+ "createDraft": "Crear borrador",
+ "draftIsBeingCreated": "El borrador se está creando actualmente en Packlink PRO",
+ "createOrderDraft": "Crear borrador en Packlink PRO",
+ "draftCreateFailed": "El intento anterior de crear un borrador ha fallado. Error: %s",
+ "packlinkShipping": "Packlink Shipping",
+ "shipmentOrderNotExist": "El pedido con referencia de envío %s no existe en la tienda",
+ "orderDetailsNotFound": "Detalles del pedido no encontrados",
+ "orderNotExist": "El pedido con ID %s no existe en la tienda",
+ "bulkFailCreateFail": "No se puede crear el archivo de etiquetas masivas",
+ "draftOrderDelayed": "La creación del borrador se ha retrasado",
+ "completeServicesSetup": "You need to complete the services setup to create order draft.",
+ "sendWithPacklink": "Send with Packlink"
+ },
+ "checkoutProcess": {
+ "choseDropOffLocation": "Este servicio de envío admite la entrega a ubicaciones de entrega predefinidas. Elige la ubicación que más te convenga haciendo clic en el botón \"Seleccionar ubicación de entrega\"..",
+ "selectDropOffLocation": "Seleccionar lugar de entrega",
+ "changeDropOffLocation": "Cambiar el lugar de entrega",
+ "packageDeliveredTo": "El paquete será entregado a:",
+ "dropOffDeliveryAddress": "Dirección de entrega",
+ "changeAddress": "No hay servicio disponible para la dirección de entrega. Por favor cambia tu direccion.",
+ "shippingServiceNotFound": "Servicio de envío no encontrado"
+ },
+ "locationPicker": {
+ "monday": "Lunes",
+ "tuesday": "Martes",
+ "wednesday": "Miércoles",
+ "thursday": "Jueves",
+ "friday": "Viernes",
+ "saturday": "Sábado",
+ "sunday": "Domingo",
+ "zipCode": "Código postal",
+ "idCode": "Código ID",
+ "selectThisLocation": "Selecciona esta ubicación",
+ "showWorkingHours": "Mostrar horas de apertura",
+ "hideWorkingHours": "Ocultar horario de apertura",
+ "showOnMap": "Mostrar en el mapa",
+ "searchBy": "Buscar por nombre de ubicación, ID o dirección"
+ },
+ "migrationLogMessages": {
+ "removeControllersHooksFailed": "Error al eliminar los controladores y enlaces antiguos porque: %s",
+ "deleteObsoleteFilesFailed": "No se pudieron eliminar los archivos antiguos porque: %s",
+ "oldAPIKeyDetected.": "Se ha detectado una clave de API antigua.",
+ "successfullyLoggedIn": "Has iniciado correctamente la sesión con la clave de API existente.",
+ "removingObsoleteFiles.": "Eliminando archivo antiguos.",
+ "cannotEnqueueUpgradeShopDetailsTask": "No se pueden poner en espera los detalles de la actualización de la tienda porque: %s",
+ "deletingOldPluginDta.": "Eliminando datos antiguos del plugin.",
+ "cannotRetrieveOrderReferences": "No se pueden recuperar referencias de pedidos porque: %s",
+ "createOrderReferenceFailed": "Error al crear la referencia para el pedido %s",
+ "setLabelsFailed": "Error al generar las etiquetas para el pedido con referencia %s",
+ "setTrackingInfoFailed": "Error al generar la información de seguimiento para el pedido con la referencia %s",
+ "orderNotFound": "Pedido con referencia %s no encontrado."
+ },
+ "systemLogMessages": {
+ "errorCreatingDefaultTask": "Error creating default task runner status configuration.",
+ "webhookReceived": "Webhook de Packlink recibido",
+ "couldNotDelete": "No se pudo eliminar la entidad %s con ID %s",
+ "entityCannotBeSaved": "La entidad %s con ID %s no se puede guardar.",
+ "entityCannotBeUpdated": "La entidad %s con ID %s no se puede actualizar.",
+ "fieldIsNotIndexed": "¡El campo %s no está indexado!",
+ "unknownOrNotIndexed": "Desconocido o no indexado OrderBy column %s",
+ "dirNotCreated": "El directorio \"%s\" no fue creado",
+ "failedCreatingBackup": "Error al crear el servicio flexible",
+ "backupServiceNotFound": "Servicio flexible no encontrado"
+ },
+ "autoTest": {
+ "dbNotAccessible.": "DNo se puede acceder a la base de datos.",
+ "taskCouldNotBeStarted.": "No se ha podido iniciar la tarea.",
+ "moduleAutoTest": "Prueba automática del módulo PacklinkPRO",
+ "useThisPageTestConfiguration": "Utiliza esta página para probar la configuración del sistema y los servicios del módulo PacklinkPRO.",
+ "start": "Inicio",
+ "downloadTestLog": "Descargar el registro de pruebas",
+ "openModule": "Abrir el módulo PacklinkPRO",
+ "autotestPassedSuccessfully": "Prueba automática superada con éxito.",
+ "testNotSuccessful": "La prueba no se ha completado correctamente."
+ }
+}
\ No newline at end of file
diff --git a/src/BusinessLogic/Resources/lang/fr.json b/src/BusinessLogic/Resources/lang/fr.json
new file mode 100644
index 00000000..123550f2
--- /dev/null
+++ b/src/BusinessLogic/Resources/lang/fr.json
@@ -0,0 +1,355 @@
+{
+ "general": {
+ "packlinkPro": "Packlink PRO Shipping",
+ "saveUp": "Économisez jusqu'à 70% sur vos coûts de livraison. Sans frais fixes, sans volume minimum requis. Gérez tous vos envois depuis une seule plateforme.",
+ "packlinkShipping": "Packlink Shipping S.L.",
+ "noContract": "Sans engagement, accédez immédiatement à plus de 300 services de transport sur une seule et unique plateforme. Quelque soit le nombre de points de ventes que vous avez, vous pourrez tout gérer depuis Packlink PRO.",
+ "developedAndManaged": "Développé et géré par Packlink",
+ "generalConditions": "Conditions générales",
+ "basicSettings": "Paramètres",
+ "contactUs": "Contactez-nous",
+ "systemInfo": "Informations du système",
+ "debugMode": "Debug mode",
+ "help": "Aide",
+ "downloadSystemInfoFile": "Téléchargez le document d'information système",
+ "curlIsNotInstalled": "cURL non installé ou non activé dans votre installation PHP. Cette démarche est nécessaire pour que la tâche de fond fonctionne. Veuillez l’installer et rafraîchir cette page.",
+ "loading": "Chargement en cours...",
+ "save": "Enregistrer",
+ "saveChanges": "Enregistrer les modifications",
+ "accept": "Accepter",
+ "cancel": "Annuler",
+ "continue": "Continuer",
+ "complete": "Compléter",
+ "add": "Ajouter",
+ "edit": "Modifier",
+ "delete": "Supprimer",
+ "discard": "Ignorer"
+ },
+ "validation": {
+ "requiredField": "Ce champs est obligatoire.",
+ "invalidField": "This field is invalid.",
+ "invalidEmail": "Le champs doit être une adresse email valide",
+ "shortPassword": "Le mot de passe doit comporter au moins %s lettres.",
+ "invalidPhone": "Ce champs doit contenir un numéro de téléphone valide.",
+ "maxLength": "Ce champ ne peut contenir plus de %s caractères.",
+ "numeric": "Cette valeur doit être numérique.",
+ "greaterThanZero": "La valeur doit être spérieure à 0.",
+ "nonNegative": "Le champ ne peut contenir de valeur négative.",
+ "numberOfDecimalPlaces": "Le champs doit contenir deux décimales.",
+ "integer": "Le champs doit être un nombre entier.",
+ "invalidCountryList": "Veuillez sélectionner les pays de destination.",
+ "invalidLanguage": "Le champ ne contient pas de langue valide.",
+ "invalidPlatformCountry": "Le champ ne contient pas de pays valide.",
+ "invalidUrl": "Le champ doit contenir une URL valide.",
+ "invalidFieldValue": "Le champ doit être défini sur « %s ».",
+ "invalidMaxValue": "La valeur maximale autorisée est %s."
+ },
+ "login": {
+ "apiKey": "Clé API",
+ "apiKeyIncorrect": "Clé API incorrecte",
+ "dontHaveAccount": "Vous n’avez pas de compte ?",
+ "welcome": "Bienvenue sur Packlink PRO",
+ "connectYourService": "Connectez votre service en utilisant votre clé. Vous la trouverez dans la section « Clé API Packlink Pro » dans « Paramètres ».",
+ "validateApiKey": "Valider clé API",
+ "chooseYourCountry": "Sélectionnez votre pays pour commencer votre inscription",
+ "registerMe": "S’inscrire"
+ },
+ "countries": {
+ "ES": "Espagne",
+ "DE": "Allemagne",
+ "FR": "France",
+ "IT": "Italie",
+ "AT": "Autriche",
+ "NL": "Pays-Bas",
+ "BE": "Belgique",
+ "PT": "Portugal",
+ "TR": "Turquie",
+ "IE": "Irlande",
+ "GB": "Royaume-Uni",
+ "HU": "Hongrie",
+ "PL": "Pologne",
+ "CH": "Suisse",
+ "LU": "Luxembourg",
+ "AR": "Argentine",
+ "US": "États Unis",
+ "BO": "Bolivie",
+ "MX": "Mexique",
+ "CL": "Chili",
+ "CZ": "République Tchèque",
+ "SE": "Suède"
+ },
+ "register": {
+ "logIn": "Se connecter",
+ "email": "Adresse électronique",
+ "password": "Mot de passe",
+ "haveAccount": "Vous avez déjà un compte ?",
+ "startEnjoying": "Commencez à utiliser Packlink PRO !",
+ "registerAccount": "Enregistrez-vous",
+ "getToKnowYou": "Nous souhaitons mieux vous connaître afin de nous adapter à vous et de vous faire une offre sur mesure",
+ "monthlyShipmentVolume": "Combien d’envois faites-vous généralement par mois?",
+ "phone": "Numéro de téléphone",
+ "termsAndConditions": "
",
+ "marketingEmails": "J’autorise Packlink Shipping S.L. à m’envoyer des communications commerciales par courriel",
+ "submit": "S'inscrire",
+ "chooseYourCountry": "Sélectionnez votre pays",
+ "searchCountry": "Rechercher un pays",
+ "invalidDeliveryVolume": "Le champ ne contient pas de volume de livraison valide."
+ },
+ "onboardingWelcome": {
+ "header": "Configurez vos informations de base afin d’effectuer des envois",
+ "steps": "Il ne vous reste que deux étapes pour savoir quel transporteur répond le mieux à vos besoins",
+ "stepOne": "Configurez les informations sur le colis",
+ "stepTwo": "Configurez l’adresse de l’émetteur",
+ "startSetUp": "Démarrez la configuration"
+ },
+ "onboardingOverview": {
+ "header": "Vous y êtes presque ! Veuillez vérifier que les informations saisies sont correctes ou complétez-les pour continuer.",
+ "parcelDetails": "Informations sur le colis",
+ "senderAddress": "Adresse de l’émetteur",
+ "missingInfo": "Informations manquantes",
+ "parcelData": "Poids %s kg | Hauteur %s cm | Largeur %s cm | Longueur %s cm",
+ "warehouseData": "%s | %s | %s"
+ },
+ "defaultParcel": {
+ "title-onboarding": "1. Configurez les informations sur le colis",
+ "description-onboarding": "Nous utiliserons ces données prédéfinies pour les articles dont les dimensions et le poids n’ont pas été définis. Vous pouvez les modifier à tout moment via l’onglet Paramètres.",
+ "title-config": "Colis prédéfini",
+ "description-config": "Nous utiliserons ces données pour les articles dont les dimensions et le poids n’ont pas été définis.",
+ "weight": "Poids",
+ "height": "Hauteur",
+ "width": "Largeur",
+ "length": "Longueur"
+ },
+ "defaultWarehouse": {
+ "title-onboarding": "2. Configurer l’adresse de l’émetteur",
+ "description-onboarding": "Nous utiliserons cette adresse pour créer un émetteur prédéfini pour toutes les expéditions. Vous pourrez la modifier à tout moment via l’onglet Paramètres.",
+ "title-config": "Adresse de l’émetteur prédéfinie",
+ "description-config": "Nous utiliserons cette adresse pour créer un émetteur prédéfini pour toutes les expéditions. Vous pourrez la modifier à tout moment.",
+ "alias": "Nom de l’émetteur",
+ "alias-placeholder": "Magasin principal",
+ "name": "Prénom de la personne à contacter",
+ "name-placeholder": "Prénom",
+ "surname": "Nom de la personne à contacter",
+ "surname-placeholder": "Nom",
+ "company": "Nom de l'entreprise",
+ "company-placeholder": "Société",
+ "country": "Pays",
+ "postal_code": "Ville ou code postal",
+ "postal_code-placeholder": "-",
+ "address": "Adresse",
+ "address-placeholder": "Adresse",
+ "phone": "Numéro de téléphone",
+ "phone-placeholder": "123 456 7777",
+ "email": "Email",
+ "email-placeholder": "votreemail@exemple.com"
+ },
+ "configuration": {
+ "menu": "Paramètres",
+ "title": "Paramètres",
+ "orderStatus": "Statut de la commande",
+ "warehouse": "Adresse de l’émetteur prédéfinie",
+ "parcel": "Colis par défaut",
+ "help": "Aide",
+ "contactUs": "Contactez-nous:",
+ "systemInfo": "Informations du système"
+ },
+ "systemInfo": {
+ "title": "Fichier d’informations du système et mode débogage",
+ "debugMode": "Debug mode",
+ "download": "Téléchargez le document d'information système"
+ },
+ "orderStatusMapping": {
+ "title": "Statut de la commande",
+ "description": "Avec Packlink, vous pouvez mettre à jour le statut de votre commande %s avec les informations d’expédition. Vous pourrez les modifier à tout moment.",
+ "packlinkProShipmentStatus": "STATUT DE LIVRAISON Packlink PRO",
+ "systemOrderStatus": "STATUT DE LA COMMANDE %s",
+ "none": "Aucun",
+ "pending": "En attente",
+ "processing": "En cours de traitement",
+ "readyForShipping": "Prêt pour la livraison",
+ "inTransit": "En transit",
+ "delivered": "Délivré",
+ "cancelled": "Annulé"
+ },
+ "shippingServices": {
+ "myServices": "Mes services d’expédition",
+ "noServicesTitle": "Vous devez simplement ajouter vos services d’expédition",
+ "noServicesDescription": "Votre client pourra les voir au moment du paiement et choisir le transporteur qui livrera son colis. Configurez-les maintenant pour n’avoir à vous soucier de rien d’autre. Vous pourrez à tout moment modifier, mettre à jour ou améliorer vos services d’expédition.",
+ "addService": "Ajouter un service",
+ "addNewService": "Ajouter un nouveau service",
+ "addedSuccessTitle": "Service d’expédition ajouté avec succès",
+ "addedSuccessDescription": "Vous pouvez modifier le service dans la section « Mes services ».",
+ "deletedSuccessTitle": "Service d’expédition supprimé avec succès",
+ "deletedSuccessDescription": "Vous pouvez ajouter de nouveaux services avec le bouton « Ajouter un nouveau service ».",
+ "disableCarriersTitle": "Vous avez créé votre premier service d’expédition. Souhaitez-vous désactiver les anciens transporteurs ?",
+ "disableCarriersDescription": "Afin de vous offrir un meilleur service, il est important de désactiver le transporteur que vous utilisiez auparavant.",
+ "successfullyDisabledShippingMethods": "Service d'envoi désactivé avec succès.",
+ "failedToDisableShippingMethods": "Échec de la désactivation du service d'envoi.",
+ "pickShippingService": "Ajouter des services de livraison",
+ "failedGettingServicesTitle": "Nous rencontrons des problèmes dans l’importation des services de livraison",
+ "failedGettingServicesSubtitle": "Souhaitez-vous réessayer ?",
+ "retry": "Réessayer",
+ "filterModalTitle": "Filtres",
+ "applyFilters": "Appliquer",
+ "type": "Type",
+ "national": "National",
+ "international": "International",
+ "deliveryType": "Livraison",
+ "economic": "Économique",
+ "express": "Express",
+ "parcelOrigin": "Origine du colis",
+ "collection": "Collecte à domicile",
+ "dropoff": "Dépôt en point relais",
+ "parcelDestination": "Destination du colis",
+ "pickup": "Point de retrait",
+ "delivery": "Livraison à domicile",
+ "carrierLogo": "Logo du transporteur",
+ "carrier": "Transporteur",
+ "serviceTitle": "Titre du service",
+ "serviceTitleDescription": "Personnalisez votre envoi en le modifiant. Vos clients pourront le voir.",
+ "transitTime": "Temps de transit",
+ "origin": "Origine",
+ "destination": "Destination",
+ "myPrices": "Mes prix",
+ "packlinkPrices": "Prix Packlink",
+ "configureService": "Configurer le service",
+ "showCarrierLogo": "Montrer le logo du transporteur à mes clients",
+ "pricePolicy": "Politique tarifaire",
+ "pricePolicyDescription": "Les tarifs de base de Packlink seront configurés par défaut, mais vous pourrez les configurer plus en détail ci-dessous.",
+ "configurePricePolicy": "Configurer mes frais d’expédition",
+ "taxClassTitle": "Sélectionnez votre taux fiscal enregistré",
+ "tax": "Taxe",
+ "serviceCountriesTitle": "Disponibilité par pays de destination",
+ "serviceCountriesDescription": "Sélectionnez la disponibilité des pays pris en charge par votre service d’expédition.",
+ "openCountries": "Voir pays",
+ "allCountriesSelected": "Tous les pays sont sélectionnés",
+ "oneCountrySelected": "Un pays est sélectionné",
+ "selectedCountries": "%s pays sont sélectionnés",
+ "firstPricePolicyDescription": "Parfait, il ne vous reste que quelques étapes :
1. Choisissez si vous souhaitez les configurer par poids et/ou par prix d’achat.
2. Choisissez une politique tarifaire et configurez-la.",
+ "addFirstPolicy": "Ajouter une règle de prix",
+ "addAnotherPolicy": "Ajouter une autre règle",
+ "from": "De",
+ "to": "À",
+ "price": "Prix",
+ "rangeTypeExplanation": "1. Choisissez si vous souhaitez les configurer par poids et/ou par prix d’achat.",
+ "rangeType": "Type de fourchette",
+ "priceRange": "Fourchette de prix",
+ "priceRangeWithData": "Fourchette de prix : de %s € à %s €",
+ "weightRange": "Fourchette de poids",
+ "weightRangeWithData": "Fourchette de poids : de %s kg à %s kg",
+ "weightAndPriceRange": "Fourchette de poids et de prix",
+ "weightAndPriceRangeWithData": "Fourchette de poids et de prix : de %s kg à %s kg et de %s € à %s €",
+ "singlePricePolicy": "Politique tarifaire %s",
+ "pricePolicyExplanation": "2. Choisissez une politique tarifaire et configurez-la.",
+ "packlinkPrice": "Prix Packlink",
+ "percentagePacklinkPrices": "% des prix Packlink",
+ "percentagePacklinkPricesWithData": "% des prix Packlink : %s de %s%",
+ "fixedPrices": "Prix fixe",
+ "fixedPricesWithData": "Prix fixe : %s €",
+ "increaseExplanation": "Augmentation : ajoutez % au prix, c’est le client qui payera.",
+ "reduceExplanation": "Réduction : déduisez % du prix, c’est vous qui payerez.",
+ "select": "Sélectionner",
+ "invalidRange": "Fourchette invalide",
+ "increase": "Augmenter",
+ "reduce": "Réduire",
+ "selectAllCountries": "Tous les pays sélectionnés",
+ "selectCountriesHeader": "Pays pris en charge par votre service d’expédition",
+ "selectCountriesSubheader": "Sélectionnez la disponibilité d’au moins un pays et ajoutez-en autant que nécessaire",
+ "usePacklinkRange": "Pour toutes les autres fourchettes, appliquez les prix Packlink",
+ "discardChangesQuestion": "Certaines modifications n’ont pas été enregistrées. Êtes-vous sûr de vouloir revenir en arrière et de les ignorer ?",
+ "atLeastOneCountry": ""
+ },
+ "orderListAndDetails": {
+ "packlinkOrderDraft": "Brouillon de commande Packlink",
+ "printed": "Imprimé",
+ "ready": "Prêt",
+ "printLabel": "Imprimer étiquette",
+ "shipmentLabels": "Étiquettes de livraison",
+ "printShipmentLabels": "Imprimer les étiquettes de livraison Packlink PRO",
+ "shipmentDetails": "Détails de l'envoi",
+ "disablePopUpBlocker": "Veuillez désactiver l'outil de blocage des fenêtres pop-up sur cette page afin d'ouvrir massivement les étiquettes d'envoi.",
+ "date": "Date",
+ "number": "Numéro",
+ "status": "Statut",
+ "print": "Imprimer",
+ "carrierTrackingNumbers": "Numéro de tracking du transporteur",
+ "trackIt": "Suivez le!",
+ "packlinkReferenceNumber": "Numéro de référence Packlink",
+ "packlinkShippingPrice": "Prix de livraison Packlink",
+ "viewOnPacklink": "Voir sur Packlink PRO",
+ "createDraft": "Créer un brouillon",
+ "draftIsBeingCreated": "Le brouillon est en cours de création sur Packlink PRO",
+ "createOrderDraft": "Créer un brouillon de commande sur Packlink PRO",
+ "draftCreateFailed": "La tentative précédente de création d'un brouillon a échoué. Erreur: %s",
+ "packlinkShipping": "Packlink Shipping",
+ "shipmentOrderNotExist": "La commande de livraison sous le référence %s n'existe pas sur le shop.",
+ "orderDetailsNotFound": "Détails de commande introuvables",
+ "orderNotExist": "La commande sous l'ID %s n'existe pas sur le shop.",
+ "bulkFailCreateFail": "Création d'un dossier d'étiquettes en masse impossible.",
+ "draftOrderDelayed": "La création du brouillon a été retardée",
+ "completeServicesSetup": "You need to complete the services setup to create order draft.",
+ "sendWithPacklink": "Send with Packlink"
+ },
+ "checkoutProcess": {
+ "choseDropOffLocation": "Ce service de transport soutient la livraison vers des lieux de dépôts prédéfinis. Veuillez choisir la localisation qui vous convient le mieux en cliquant sur le bouton \"Sélectionner le lieu de dépôt\"",
+ "selectDropOffLocation": "Sélectionner le lieu de dépôt.",
+ "changeDropOffLocation": "Changer le lieu de depôt.",
+ "packageDeliveredTo": "Le colis sera délivré à:",
+ "dropOffDeliveryAddress": "Adresse de livraison.",
+ "changeAddress": "Il n'y a pas de lieux de livraison disponibles pour votre adresse de livraison. Veuillez changer votre adresse.",
+ "shippingServiceNotFound": "Service de livraison introuvable."
+ },
+ "locationPicker": {
+ "monday": "Lundi",
+ "tuesday": "Mardi",
+ "wednesday": "Mercredi",
+ "thursday": "Jeudi",
+ "friday": "Vendredi",
+ "saturday": "Samedi",
+ "sunday": "Dimanche",
+ "zipCode": "Code postal",
+ "idCode": "Code ID",
+ "selectThisLocation": "Sélectionner ce lieu",
+ "showWorkingHours": "Montrer les heures de travail",
+ "hideWorkingHours": "Cacher les heures d'ouverture",
+ "showOnMap": "Montrer sur la carte",
+ "searchBy": "Chercher par lieu, nom, id ou adresse"
+ },
+ "migrationLogMessages": {
+ "removeControllersHooksFailed": "Echec du retrait des anciens régulateurs et crochets parce que. %s",
+ "deleteObsoleteFilesFailed": "La suppression des dossiers obsolètes n'a pas pu être effectuée car: %s",
+ "oldAPIKeyDetected.": "Ancienne clé API détectée.",
+ "successfullyLoggedIn": "Connecté avec succès avec la clé API existante.",
+ "removingObsoleteFiles.": "Retrait des dossiers osolètes.",
+ "cannotEnqueueUpgradeShopDetailsTask": "Mise en attente de la tâche \"Mise à jour des détails du Shop\" impossible car: %s",
+ "deletingOldPluginDta.": "Suppression des informations relatives à l'ancien plugin.",
+ "cannotRetrieveOrderReferences": "Récupération des références de commande impossible car: %s",
+ "createOrderReferenceFailed": "Échec de création de référence pour la commande %s",
+ "setLabelsFailed": "Échec de la mise en place d'étiquettes pour la commande sous la référence %s",
+ "setTrackingInfoFailed": "Échec de la mise en place des informations de suivi pour la commande sous la référence %s",
+ "orderNotFound": "La commande sous la référence %s introuvable."
+ },
+ "systemLogMessages": {
+ "errorCreatingDefaultTask": "Erreur lors de la création de la configuration du gestionnaire de tâches par défaut.",
+ "webhookReceived": "Webhook de Packlink reçu",
+ "couldNotDelete": "L'entité %s dont l'ID est %s n'a pas pu être supprimée.",
+ "entityCannotBeSaved": "L'entité %s dont l'ID est %s n'a pas pu être enregistrée.",
+ "entityCannotBeUpdated": "L'entité %s dont l'ID est %s n'a pas pu être mise à jour.",
+ "fieldIsNotIndexed": "Le champs %s n'est pas indexé!",
+ "unknownOrNotIndexed": "Inconnu ou non-indexé OrderBy column %s",
+ "dirNotCreated": "Annuaire \"%s\" n'a pas été créé",
+ "failedCreatingBackup": "Impossible de créer le service de flexibilité.",
+ "backupServiceNotFound": "Service de flexibilité introuvable"
+ },
+ "autoTest": {
+ "dbNotAccessible.": "Base de données inaccessible.",
+ "taskCouldNotBeStarted.": "La tâche n’a pu être lancée.",
+ "moduleAutoTest": "Test automatique du module PacklinkPRO",
+ "useThisPageTestConfiguration": "Utilisez cette page pour tester la configuration du système et les services du module PacklinkPRO.",
+ "start": "Démarrer",
+ "downloadTestLog": "Télécharger le registre de tests",
+ "openModule": "Ouvrir le module PacklinkPRO",
+ "autotestPassedSuccessfully": "Test automatique réussi avec succès !",
+ "testNotSuccessful": "Le test a échoué."
+ }
+}
\ No newline at end of file
diff --git a/src/BusinessLogic/Resources/lang/fromCSV.php b/src/BusinessLogic/Resources/lang/fromCSV.php
new file mode 100644
index 00000000..5968a5d9
--- /dev/null
+++ b/src/BusinessLogic/Resources/lang/fromCSV.php
@@ -0,0 +1,47 @@
+\"Chiave API Packlink Pro\" delle \"Impostazioni\".",
+ "validateApiKey": "Convalida la chiave API",
+ "chooseYourCountry": "Per iniziare la registrazione, scegli il tuo paese",
+ "registerMe": "Iscriviti"
+ },
+ "countries": {
+ "ES": "Spagna",
+ "DE": "Germania",
+ "FR": "Francia",
+ "IT": "Italia",
+ "AT": "Austria",
+ "NL": "Paesi Bassi",
+ "BE": "Belgio",
+ "PT": "Portogallo",
+ "TR": "Turchia",
+ "IE": "Irlanda",
+ "GB": "Regno Unito",
+ "HU": "Ungheria",
+ "PL": "Polonia",
+ "CH": "Svizzera",
+ "LU": "Lussemburgo",
+ "AR": "Argentina",
+ "US": "Stati Uniti",
+ "BO": "Bolivia",
+ "MX": "Messico",
+ "CL": "Chile",
+ "CZ": "Repubblica Ceca",
+ "SE": "Svezia"
+ },
+ "register": {
+ "logIn": "Accedi",
+ "email": "Email",
+ "password": "Password",
+ "haveAccount": "Hai già un account?",
+ "startEnjoying": "Inizia a usufruire di Packlink PRO!",
+ "registerAccount": "Registrati",
+ "getToKnowYou": "Vogliamo conoscerti meglio per adattarci a te e preparare una proposta personalizzata per te",
+ "monthlyShipmentVolume": "Quante spedizioni fai solitamente al mese?",
+ "phone": "Numero di telefono",
+ "termsAndConditions": "
",
+ "marketingEmails": "Autorizzo Packlink Shipping S.L. a inviarmi comunicazioni commerciali via email",
+ "submit": "Registrati",
+ "chooseYourCountry": "Scegli il paese",
+ "searchCountry": "Cerca paese",
+ "invalidDeliveryVolume": "Il campo non contiene un volume di consegna valido."
+ },
+ "onboardingWelcome": {
+ "header": "È necessario impostare alcuni dati di base così che potrai effettuare spedizioni",
+ "steps": "Si tratta di due semplici passaggi che dobbiamo completare per offrirti la compagnia di trasporto che più si adatta alle tue esigenze",
+ "stepOne": "Imposta i dettagli del pacco",
+ "stepTwo": "Imposta l’indirizzo del mittente",
+ "startSetUp": "Avvia la configurazione"
+ },
+ "onboardingOverview": {
+ "header": "Ci siamo quasi! Per continuare, verifica che i dati inseriti siano corretti o completali.",
+ "parcelDetails": "Dettagli del pacco",
+ "senderAddress": "Indirizzo del mittente",
+ "missingInfo": "Dati mancanti",
+ "parcelData": "Peso %s kg | Altezza %s cm | Largezza %s cm | Lunghezza %s cm",
+ "warehouseData": "%s | %s | %s"
+ },
+ "defaultParcel": {
+ "title-onboarding": "1. Imposta i dettagli del pacco",
+ "description-onboarding": "Useremo questi dati predefiniti per gli articoli per cui non vengono specificate le dimensioni e il peso. Puoi modificarli quando vuoi dalla scheda delle impostazioni.",
+ "title-config": "Pacco predefinito",
+ "description-config": "Useremo questi dati per articoli privi di dimensioni e peso definiti.",
+ "weight": "Peso",
+ "height": "Altezza",
+ "width": "Largezza",
+ "length": "Lunghezza"
+ },
+ "defaultWarehouse": {
+ "title-onboarding": "2. Imposta l’indirizzo del mittente",
+ "description-onboarding": "Useremo questo indirizzo per creare un mittente predefinito per tutte le spedizioni. Potrai modificarlo ogni volta che vuoi dalla scheda delle impostazioni.",
+ "title-config": "Indirizzo del mittente predefinito",
+ "description-config": "Useremo questo indirizzo per creare un mittente predefinito per tutte le spedizioni. Potrai modificarlo ogni volta che vuoi.",
+ "alias": "Nome del mittente",
+ "alias-placeholder": "Magazzino principale",
+ "name": "Nome della persona di contatto",
+ "name-placeholder": "Nome",
+ "surname": "Cognome della persona di contatto",
+ "surname-placeholder": "cognome",
+ "company": "Nome dell'azienda",
+ "company-placeholder": "Azienda",
+ "country": "Paese",
+ "postal_code": "Città o codice postale",
+ "postal_code-placeholder": "-",
+ "address": "Indirizzo",
+ "address-placeholder": "Indirizzo",
+ "phone": "Numero di telefono",
+ "phone-placeholder": "123 456 7777",
+ "email": "Email",
+ "email-placeholder": "latuaemail@esempio.com"
+ },
+ "configuration": {
+ "menu": "Impostazioni",
+ "title": "Impostazioni",
+ "orderStatus": "Stato dell’ordine",
+ "warehouse": "Indirizzo del mittente predefinito",
+ "parcel": "Pacco predefinito",
+ "help": "Aiuto",
+ "contactUs": "Contattaci:",
+ "systemInfo": "Informazioni del sistema"
+ },
+ "systemInfo": {
+ "title": "File di informazioni del sistema e modalità debug",
+ "debugMode": "Debug mode",
+ "download": "Scarica il file di informazioni del sistema"
+ },
+ "orderStatusMapping": {
+ "title": "Stato dell’ordine",
+ "description": "Con Packlink, puoi aggiornare lo stato dell’ordine %s con i dati della spedizione. Puoi modificarlo ogni volta che vuoi.",
+ "packlinkProShipmentStatus": "STATO DELLA SPEDIZIONE di Packlink PRO",
+ "systemOrderStatus": "STATO DELLA SPEDIZIONE di %s",
+ "none": "Nessuno",
+ "pending": "In attesa",
+ "processing": "Processando",
+ "readyForShipping": "Pronto per la spedizione",
+ "inTransit": "In transito",
+ "delivered": "Consegnato",
+ "cancelled": "Annullato"
+ },
+ "shippingServices": {
+ "myServices": "I miei servizi di spedizione",
+ "noServicesTitle": "Dovrai solo aggiungere i tuoi servizi di spedizione",
+ "noServicesDescription": "Questi saranno mostrati al cliente al momento del pagamento, per consentirgli di scegliere la compagnia di trasporto che effettuerà la consegna del pacco. Configurali adesso e non dovrai più preoccuparti di nulla. Puoi modificarli ogni volta che vuoi, per aggiornare o rinnovare i servizi di spedizione.",
+ "addService": "Aggiungi servizio",
+ "addNewService": "Aggiungi nuovo servizio",
+ "addedSuccessTitle": "Il servizio di spedizione è stato aggiunto",
+ "addedSuccessDescription": "Puoi modificare il servizio dalla sezione \"I miei servizi\".",
+ "deletedSuccessTitle": "Il servizio di spedizione è stato eliminato",
+ "deletedSuccessDescription": "Puoi aggiungere nuovi servizi tramite il pulsante \"Aggiungi nuovo servizio\".",
+ "disableCarriersTitle": "Hai creato il tuo primo servizio di spedizione. Vuoi disattivare le compagnie di trasporto precedenti?",
+ "disableCarriersDescription": "Per garantirti un servizio migliore, è importante disattivare le compagnie di trasporto utilizzati in precedenza.",
+ "successfullyDisabledShippingMethods": "Servizi di spedizione disattivati correttamente.",
+ "failedToDisableShippingMethods": "Impossibile disattivare i servizi di spedizione.",
+ "pickShippingService": "Aggiungi servizi di consegna",
+ "failedGettingServicesTitle": "Si è verificato un problema durante l’acquisizione dei servizi di spedizione",
+ "failedGettingServicesSubtitle": "Vuoi riprovare?",
+ "retry": "Riprova",
+ "filterModalTitle": "Filtri",
+ "applyFilters": "Applica",
+ "type": "Tipo",
+ "national": "Nazionale",
+ "international": "Internazionale",
+ "deliveryType": "Servizio",
+ "economic": "Economico",
+ "express": "Espresso",
+ "parcelOrigin": "Origine del pacco",
+ "collection": "Ritiro a domicilio",
+ "dropoff": "Ritiro in punto corriere",
+ "parcelDestination": "Destinazione pacco",
+ "pickup": "Consegna in punto corriere",
+ "delivery": "Consegna al domicilio",
+ "carrierLogo": "Logo del corriere",
+ "carrier": "Corriere",
+ "serviceTitle": "Titolo del servizio",
+ "serviceTitleDescription": "Modifica le tue spedizioni per personalizzarle. Queste informazioni saranno visualizzate dai tuoi clienti.",
+ "transitTime": "Tempi di transito",
+ "origin": "Origine",
+ "destination": "Destinazione",
+ "myPrices": "I miei prezzi",
+ "packlinkPrices": "Prezzi di Packlink",
+ "configureService": "Configura il servizio",
+ "showCarrierLogo": "Mostra logo del corriere ai miei clienti",
+ "pricePolicy": "Politica dei prezzi",
+ "pricePolicyDescription": "Per impostazione predefinita, saranno i prezzi di base di Packlink, ma puoi configurarli più dettagliatamente qui di seguito.",
+ "configurePricePolicy": "Configura i prezzi di spedizione",
+ "taxClassTitle": "Scegli la tua aliquota fiscale salvata",
+ "tax": "Tassa",
+ "serviceCountriesTitle": "Disponibilità per paese di destinazione",
+ "serviceCountriesDescription": "Seleziona la disponibilità per i paesi supportati per i tuoi servizi di spedizione.",
+ "openCountries": "Vedi i paesi",
+ "allCountriesSelected": "Tutti i paesi selezionati",
+ "oneCountrySelected": "Un paese selezionato",
+ "selectedCountries": "%s paesi selezionati",
+ "firstPricePolicyDescription": "Perfetto, mancano solo due passaggi:
1. Scegli se vuoi importarli per peso e/o prezzo di acquisto.
2. Scegli una politica dei prezzi e configurala.",
+ "addFirstPolicy": "Aggiungi regola di prezzo",
+ "addAnotherPolicy": "Aggiungi un’altra regola",
+ "from": "Da",
+ "to": "A",
+ "price": "Prezzo",
+ "rangeTypeExplanation": "1. Scegli se vuoi importarli per peso e/o prezzo di acquisto.",
+ "rangeType": "Tipo di range",
+ "priceRange": "Range di prezzo",
+ "priceRangeWithData": "Range di prezzo: da %s€ a %s€",
+ "weightRange": "Range di peso",
+ "weightRangeWithData": "Range di peso: da %s kg a %s kg",
+ "weightAndPriceRange": "Range di prezzo e di peso",
+ "weightAndPriceRangeWithData": "Range di prezzo e di peso: da %s kg a %s kg e da %s€ a %s€",
+ "singlePricePolicy": "Politica dei prezzi %s",
+ "pricePolicyExplanation": "2. Scegli una politica dei prezzi e configurala.",
+ "packlinkPrice": "Prezzo di Packlink",
+ "percentagePacklinkPrices": "% dei prezzi di Packlink",
+ "percentagePacklinkPricesWithData": "% dei prezzi di Packlink: %s del %s%",
+ "fixedPrices": "Prezzo fisso",
+ "fixedPricesWithData": "Prezzo fisso: %s€",
+ "increaseExplanation": "Incremento sul prezzo: aggiungi una % al prezzo, che sarà pagata dal cliente.",
+ "reduceExplanation": "Riduzione sul prezzo: deduci una % dal prezzo, che sarà pagata da te.",
+ "select": "Sélectionner",
+ "invalidRange": "Range non valido",
+ "increase": "Aumenta",
+ "reduce": "Diminuisci",
+ "selectAllCountries": "Tutti i paesi selezionati",
+ "selectCountriesHeader": "Paesi supportati per il tuo servizio di spedizione",
+ "selectCountriesSubheader": "Seleziona la disponibilità di almeno un paese e aggiungi tutti quelli richiesti",
+ "usePacklinkRange": "Per tutti gli altri range, applica i prezzi di Packlink",
+ "discardChangesQuestion": "Alcune modifiche non sono state salvate. Sei sicuro di voler tornare indietro e annullarle?",
+ "atLeastOneCountry": ""
+ },
+ "orderListAndDetails": {
+ "packlinkOrderDraft": "Bozza dell'ordine Packlink",
+ "printed": "Stampato",
+ "ready": "Pronto per la spedizione",
+ "printLabel": "Stampa etichette",
+ "shipmentLabels": "Etichette di spedizione",
+ "printShipmentLabels": "Stampa etichette di spedizione Packlink PRO",
+ "shipmentDetails": "Dettagli della spedizione",
+ "disablePopUpBlocker": "Disabilita il blocco pop-up su questa pagina per poter aprire le etichette di spedizione insieme",
+ "date": "Data",
+ "number": "Numero",
+ "status": "Stato",
+ "print": "Stampa",
+ "carrierTrackingNumbers": "Numero di tracking del corriere",
+ "trackIt": "Traccialo!",
+ "packlinkReferenceNumber": "Numero di ordine Packlink",
+ "packlinkShippingPrice": "PPrezzo di spedizione Packlink",
+ "viewOnPacklink": "Vedi su Packlink PRO",
+ "createDraft": "Crea bozza",
+ "draftIsBeingCreated": "La bozza è attualmente in fase di creazione su Packlink PRO",
+ "createOrderDraft": "Crea una bozza di ordine su Packlink PRO",
+ "draftCreateFailed": "Il precedente tentativo di creare una bozza è fallito. Errore: %s",
+ "packlinkShipping": "Packlink Shipping",
+ "shipmentOrderNotExist": "L'ordine con il numero di spedizione %s non esiste nel negozio",
+ "orderDetailsNotFound": "Dettagli dell'ordine non trovati",
+ "orderNotExist": "L'ordine con ID %s non esiste nel negozio",
+ "bulkFailCreateFail": "Impossibile creare il file di etichette in blocco",
+ "draftOrderDelayed": "La creazione della bozza è stata ritardata",
+ "completeServicesSetup": "You need to complete the services setup to create order draft.",
+ "sendWithPacklink": "Send with Packlink"
+ },
+ "checkoutProcess": {
+ "choseDropOffLocation": "Questo servizio di spedizione supporta la consegna a punti corriere predefiniti. Scegli la località più adatta a te, facendo clic sul pulsante \"Seleziona punto corriere\".",
+ "selectDropOffLocation": "Seleziona la località del punto corriere",
+ "changeDropOffLocation": "Cambia località del punto corriere",
+ "packageDeliveredTo": "La spedizione verrà consegnata a:",
+ "dropOffDeliveryAddress": "Indirizzo di consegna del punto corriere",
+ "changeAddress": "Non ci sono località di consegna disponibili per il tuo indirizzo di consegna. Per favore cambia l'indirizzo.",
+ "shippingServiceNotFound": "Servizio di spedizione non trovato"
+ },
+ "locationPicker": {
+ "monday": "Lunedì",
+ "tuesday": "Martedì",
+ "wednesday": "Mercoledì",
+ "thursday": "Giovedì",
+ "friday": "Venerdì",
+ "saturday": "Sabato",
+ "sunday": "Domenica",
+ "zipCode": "Codice postale",
+ "idCode": "Codice ID",
+ "selectThisLocation": "Seleziona la località",
+ "showWorkingHours": "Mostra orari di apertura",
+ "hideWorkingHours": "Nascondi orari di apertura",
+ "showOnMap": "Mostra sulla mappa",
+ "searchBy": "Cerca nome della località per nome, id o indirizzo"
+ },
+ "migrationLogMessages": {
+ "removeControllersHooksFailed": "Impossibile rimuovere vecchi controller e hook perché: %s",
+ "deleteObsoleteFilesFailed": "Impossibile eliminare i file obsoleti perché: %s",
+ "oldAPIKeyDetected.": "Rilevata vecchia API Key.",
+ "successfullyLoggedIn": "Accesso eseguito correttamente con la API Key esistente.",
+ "removingObsoleteFiles.": "Rimozione di file obsoleti.",
+ "cannotEnqueueUpgradeShopDetailsTask": "Impossibile richiamare UpgradeShopDetailsTask perché: %s",
+ "deletingOldPluginDta.": "Eliminando i vecchi dati del plug-in",
+ "cannotRetrieveOrderReferences": "Impossibile recuperare i riferimenti degli ordini perché: %s",
+ "createOrderReferenceFailed": "Impossibile creare il riferimento per l'ordine %s",
+ "setLabelsFailed": "Impossibile impostare le etichette per l'ordine con riferimento %s",
+ "setTrackingInfoFailed": "Impossibile impostare le informazioni di tracciamento per l'ordine con riferimento %s",
+ "orderNotFound": "Ordine con riferimento %s non trovato"
+ },
+ "systemLogMessages": {
+ "errorCreatingDefaultTask": "Error creating default task runner status configuration.",
+ "webhookReceived": "Webhook di Packlink ricevuto",
+ "couldNotDelete": "Impossibile eliminare l'entità %s con ID %s",
+ "entityCannotBeSaved": "L'entità %s con ID %s non può essere salvata.",
+ "entityCannotBeUpdated": "L'entità %s con ID %s non può essere aggiornata.",
+ "fieldIsNotIndexed": "Il campo %s non è indicizzato!",
+ "unknownOrNotIndexed": "Colonna OrderBy %s sconosciuta o non indicizzata",
+ "dirNotCreated": "La directory \"%s\" non è stata creata",
+ "failedCreatingBackup": "Impossibile creare il servizio jolly.",
+ "backupServiceNotFound": "Servizio jolly non trovato."
+ },
+ "autoTest": {
+ "dbNotAccessible.": "Database non accessibile.",
+ "taskCouldNotBeStarted.": "Non è stato possibile avviare l’attività.",
+ "moduleAutoTest": "Auto-test per il modulo di PacklinkPRO",
+ "useThisPageTestConfiguration": "Usa questa pagina per testare la configurazione del sistema e i servizi del modulo di PacklinkPRO.",
+ "start": "Avvia",
+ "downloadTestLog": "Scarica il registro test",
+ "openModule": "Apri il modulo di PacklinkPRO",
+ "autotestPassedSuccessfully": "L’auto-test è stato superato con successo!",
+ "testNotSuccessful": "Il test non è stato completato correttamente."
+ }
+}
\ No newline at end of file
diff --git a/src/BusinessLogic/Resources/lang/toCSV.php b/src/BusinessLogic/Resources/lang/toCSV.php
new file mode 100644
index 00000000..c4630625
--- /dev/null
+++ b/src/BusinessLogic/Resources/lang/toCSV.php
@@ -0,0 +1,38 @@
+ $translations) {
+ foreach ($translations as $key => $value) {
+ $line = array();
+ $line[] = $group;
+ $line[] = $key;
+ $line[] = $value;
+ $line[] = isset($es[$group][$key]) ? $es[$group][$key] : '';
+ $line[] = isset($de[$group][$key]) ? $de[$group][$key] : '';
+ $line[] = isset($fr[$group][$key]) ? $fr[$group][$key] : '';
+ $line[] = isset($it[$group][$key]) ? $it[$group][$key] : '';
+
+ fputcsv($f, $line);
+ }
+ }
+
+ fclose($f);
+}
+
+toCsv();
\ No newline at end of file
diff --git a/src/BusinessLogic/Resources/lang/translations.csv b/src/BusinessLogic/Resources/lang/translations.csv
new file mode 100644
index 00000000..6f613d87
--- /dev/null
+++ b/src/BusinessLogic/Resources/lang/translations.csv
@@ -0,0 +1,315 @@
+Group,key,English,Spanish,German,French,Italian
+general,packlinkPro,Packlink PRO Shipping,Packlink PRO Shipping,Packlink PRO Shipping,Packlink PRO Shipping,Packlink PRO Shipping
+general,saveUp,"Save up to 70% on your shipping costs. No fixed fees, no minimum shipping volume required. Manage all your shipments in a single platform.","Ahorra hasta un 70% en tus gastos de envío. Sin tarifas fijas, sin volumen de envíos mínimo. Gestiona todos tus envíos en una sola plataforma.","Sparen Sie bis zu 70% bei Ihren Versandkosten. Keine festen Gebühren, kein Mindestvolumen beim Versand. Verwalten Sie alle Ihre Sendungen auf einer einzigen Plattform.","Économisez jusqu'à 70% sur vos coûts de livraison. Sans frais fixes, sans volume minimum requis. Gérez tous vos envois depuis une seule plateforme.",Risparmia fino a un 70% sui costi di spedizione. Senza costi fissi né volumi minimi di spedizione richiesti. Gestisci tutte le tue spedizioni da un'unica piattaforma.
+general,packlinkShipping,Packlink Shipping S.L.,Packlink Shipping S.L.,Packlink Shipping S.L.,Packlink Shipping S.L.,Packlink Shipping S.L.
+general,noContract,No contract needed! More than 300 transport services into a single platform. You can connect all your ecommerce and manage all your shipments in Packlink PRO.,"Sin contratos, accede inmediatamente a más de 300 servicios de transporte en una única plataforma. No importa cuantos puntos de venta tengas, todo lo podrás gestionar desde Packlink PRO.",Ohne Vertragsbindung – Sofortiger Zugriff auf über 300 Versanddienste in einer einzigen Plattform. Verbinden Sie Ihren Onlineshop und steuern Sie alle Sendungen über Packlink PRO.,"Sans engagement, accédez immédiatement à plus de 300 services de transport sur une seule et unique plateforme. Quelque soit le nombre de points de ventes que vous avez, vous pourrez tout gérer depuis Packlink PRO.","Senza contratti, accedi suvito a più di 300 servizi di trasporto da un'unica piattaforma. Indipendentemente da quanti punti vendita hai, puoi gestirli tutto da Packlink PRO."
+general,developedAndManaged,Developed and managed by Packlink,Desarrollado y gestionado por Packlink,Entwickelt und verwaltet von Packlink,Développé et géré par Packlink,Sviluppato e gestito da Packlink
+general,generalConditions,General conditions,Condiciones generales,Allgemeine Bedingungen,Conditions générales,Condizioni generali
+general,basicSettings,Basic settings,Configuración,Einstellungen,Paramètres,Configurazione
+general,contactUs,Contact us,Contacta con nosotros,Kontaktieren Sie uns,Contactez-nous,Contattaci
+general,systemInfo,System info,Información del sistema,Systeminformationen,Informations du système,Informazioni del sistema
+general,debugMode,Debug mode,Debug mode,Debug mode,Debug mode,Debug mode
+general,help,Help,Ayuda,Hilfe,Aide,Aiuto
+general,downloadSystemInfoFile,Download system info file,Descargar el archivo de información del sistema,Systeminfodatei herunterladen,Téléchargez le document d'information système,Scarica il file di informazioni del sistema
+general,curlIsNotInstalled,cURL is not installed or enabled in your PHP installation. This is required for background task to work. Please install it and then refresh this page.,"cURL no está instalado ni habilitado en tu instalación de PHP. Es necesario para que funcione la tarea en segundo plano. Por favor, instálalo y luego actualiza esta página.","cURL ist in Ihrer PHP-Installation nicht installiert oder aktiviert. Dies ist jedoch erforderlich, damit die Hintergrundaufgabe funktioniert. Bitte installieren Sie es und aktualisieren Sie diese Seite.",cURL non installé ou non activé dans votre installation PHP. Cette démarche est nécessaire pour que la tâche de fond fonctionne. Veuillez l’installer et rafraîchir cette page.,cURL non installato o abilitato nella tua installazione PHP. È necessario per il corretto funzionamento dell’attività in background. Installalo e aggiorna la pagina.
+general,loading,Loading...,Cargando...,Lädt...,Chargement en cours...,Caricamento in corso...
+general,save,Save,Guardar,Speichern,Enregistrer,Salva
+general,saveChanges,Save changes,Guardar cambios,Speichern,Enregistrer les modifications,Salva le modifiche
+general,accept,Accept,Aceptar,Akzeptieren,Accepter,Accetto
+general,cancel,Cancel,Cancelar,Abbrechen,Annuler,Annulla
+general,continue,Continue,Continuar,Weiter,Continuer,Continua
+general,complete,Complete,Completar,Vollständig,Compléter,Completi
+general,add,Add,Añadir,Hinzufügen,Ajouter,Aggiungi
+general,edit,Edit,Editar,Bearbeiten,Modifier,Modifica
+general,delete,Delete,Borrar,Löschen,Supprimer,Elimina
+general,discard,Discard,Ignorar,Verwerfen,Ignorer,Scarta
+validation,requiredField,This field is required.,Esta campo es obligatorio.,Dies ist ein Pflichtfeld.,Ce champs est obligatoire.,Questo campo è obbligatorio.
+validation,invalidField,This field is invalid.,This field is invalid.,This field is invalid.,This field is invalid.,This field is invalid.
+validation,invalidEmail,This field must be valid email.,El campo debe ser un correo electrónico válido.,Das Feld muss eine gültige E-Mail-Adresse sein.,Le champs doit être une adresse email valide,Il campo deve essere un email valido.
+validation,shortPassword,The password must be at least %s characters long.,La contraseña debe contener %s caracteres como mínimo.,Das Passwort muss mindestens %s Zeichen haben.,Le mot de passe doit comporter au moins %s lettres.,La password deve contenere almeno %s caratteri.
+validation,invalidPhone,This field must be valid phone number.,Este campo deber ser un número de teléfono válido.,Bitte geben Sie eine gültige Telefonnummer ein.,Ce champs doit contenir un numéro de téléphone valide.,Questo campo deve contenere un numero di telefono valido.
+validation,maxLength,The field cannot have more than %s characters.,Este campo no puede tener más de % caracteres.,Dieses Feld darf maximal %s Zeichen enthalten.,Ce champ ne peut contenir plus de %s caractères.,Il campo non può contenere più di %s caratteri.
+validation,numeric,Value must be valid number.,Debe ser un valor numérico.,Bitte geben Sie einen numerischen Wert ein.,Cette valeur doit être numérique.,Questo valore deve essere numerico.
+validation,greaterThanZero,Value must be greater than 0.,El valor debe ser mayor que 0.,Der Wert muss größer als 0 sein.,La valeur doit être spérieure à 0.,Il valore deve essere maggiore di 0.
+validation,nonNegative,Field cannot have a negative value.,Field cannot have a negative value.,Das Feld darf keine negativen Werte enthalten.,Le champ ne peut contenir de valeur négative.,Il campo non può avere un valore negativo.
+validation,numberOfDecimalPlaces,Field must have 2 decimal places.,El campo debe tener 2 decimales.,Das Feld muss 2 Dezimalstellen haben.,Le champs doit contenir deux décimales.,Il campo deve contenere due decimali.
+validation,integer,Field must be an integer.,El campo debe ser un número entero.,Das Feld muss eine ganze Zahl sein.,Le champs doit être un nombre entier.,Il campo deve essere un numero intero.
+validation,invalidCountryList,You must select destination countries.,Debes seleccionar los países de destino.,Bitte wählen Sie die Zielländer aus.,Veuillez sélectionner les pays de destination.,Devi selezionare i paesi di destinazione.
+validation,invalidLanguage,Field is not a valid language.,Field is not a valid language.,Dieses Feld enthält keine gültige Sprache.,Le champ ne contient pas de langue valide.,Il campo non contiene una lingua valida.
+validation,invalidPlatformCountry,Field is not a valid platform country.,Field is not a valid platform country.,Dieses Feld enthält kein gültiges Land.,Le champ ne contient pas de pays valide.,Il campo non contiene un paese della piattaforma valido.
+validation,invalidUrl,Field must be a valid URL.,Field must be a valid URL.,Dieses Feld muss eine gültige URL enthalten.,Le champ doit contenir une URL valide.,Il campo deve contenere un URL valido.
+validation,invalidFieldValue,"Field must be set to ""%s"".","Field must be set to ""%s"".",Dieses Feld muss auf „%s“ gesetzt werden.,Le champ doit être défini sur « %s ».,"Il campo deve essere impostato su ""%s""."
+validation,invalidMaxValue,Maximal allowed value is %s.,Maximal allowed value is %s.,Der maximale Wert beträgt %s.,La valeur maximale autorisée est %s.,Il valore massimo consentito è %s.
+login,apiKey,Api key,Api key,API-Schlüssel,Clé API,API Key
+login,apiKeyIncorrect,API key was incorrect.,Clave de API incorrecta,Falscher API-Schlüssel,Clé API incorrecte,API Key non corretta
+login,dontHaveAccount,Don't have an account?,¿No tienes una cuenta?,Sie haben noch keinen Account?,Vous n’avez pas de compte ?,Non hai un account?
+login,welcome,Welcome to Packlink PRO,Te damos la bienvenida a Packlink PRO,Willkommen zu Packlink PRO,Bienvenue sur Packlink PRO,Benvenuto a Packlink PRO
+login,connectYourService,"Connect your service using your key. You'll find it in the ""Packlink Pro API Key"" section of the ""Settings"".","Conecta tu servicio mediante tu clave. La encontrarás en la sección ""Configuración"" apartado ""Packlink Pro API Key""","Verbinden Sie Ihren Dienst, indem Sie Ihren API-Schlüssel verwenden. Sie finden ihn unter „Packlink Pro API-Schlüssel“ bei den „Einstellungen“.",Connectez votre service en utilisant votre clé. Vous la trouverez dans la section « Clé API Packlink Pro » dans « Paramètres ».,"Usa la chiave per collegare il tuo servizio. La troverai nella sezione ""Chiave API Packlink Pro"" delle ""Impostazioni""."
+login,validateApiKey,Validate API key,Validar API key,API-Schlüssel bestätigen,Valider clé API,Convalida la chiave API
+login,chooseYourCountry,Choose your country to start the registration process,Elige tu país para comenzar el registro,"Wählen Sie Ihr Land aus, um mit der Registrierung beginnen zu können",Sélectionnez votre pays pour commencer votre inscription,"Per iniziare la registrazione, scegli il tuo paese"
+login,registerMe,Register me,Registrarme,Registrieren,S’inscrire,Iscriviti
+register,logIn,Log in,Iniciar sesión,Einloggen,Se connecter,Accedi
+register,email,Email,Correo electrónico,E-Mail,Adresse électronique,Email
+register,password,Password,Contraseña,Passwort,Mot de passe,Password
+register,haveAccount,Already have an account?,¿Ya tienes una cuenta?,Haben Sie bereits einen Account?,Vous avez déjà un compte ?,Hai già un account?
+register,startEnjoying,Start enjoying Packlink PRO!,¡Empieza a disfrutar de Packlink PRO!,Genießen Sie ab jetzt Packlink PRO!,Commencez à utiliser Packlink PRO !,Inizia a usufruire di Packlink PRO!
+register,registerAccount,Register your account,Registro,Jetzt registrieren,Enregistrez-vous,Registrati
+register,getToKnowYou,We would like to get to know you better in order to adapt to you and to send you an individual offer,Queremos conocerte mejor para adaptarnos a ti y hacerte una propuesta personalizada.,"Wir möchten Sie besser kennenlernen, um uns an Sie anzupassen und Ihnen ein individuelles Angebot zukommen zu lassen",Nous souhaitons mieux vous connaître afin de nous adapter à vous et de vous faire une offre sur mesure,Vogliamo conoscerti meglio per adattarci a te e preparare una proposta personalizzata per te
+register,monthlyShipmentVolume,What is your monthly shipment volume?,¿Cuántos envíos sueles hacer al mes?,Wie hoch ist Ihr monatliches Sendungsaufkommen?,Combien d’envois faites-vous généralement par mois?,Quante spedizioni fai solitamente al mese?
+register,phone,Phone number,Teléfono,Telefonnummer,Numéro de téléphone,Numero di telefono
+register,termsAndConditions,"
"
+register,marketingEmails,I authorise Packlink Shipping S.L. to send me commercial communications by e-mail,Autorizo a Packlink Shipping S.L. a enviarme información comercial por correo electrónico,"Ich ermächtige Packlink Shipping S.L., mir kommerzielle Mitteilungen per E-Mail zuzusenden",J’autorise Packlink Shipping S.L. à m’envoyer des communications commerciales par courriel,Autorizzo Packlink Shipping S.L. a inviarmi comunicazioni commerciali via email
+register,submit,Register,Regístrate,Registrieren,S'inscrire,Registrati
+register,chooseYourCountry,Choose your country,Elige tu país,Wählen Sie Ihr Land aus,Sélectionnez votre pays,Scegli il paese
+register,searchCountry,Search country,Busca el país,Land suchen,Rechercher un pays,Cerca paese
+register,invalidDeliveryVolume,Field is not a valid delivery volume.,El campo no contiene un volumen de entrega válido.,Das Feld enthält keinen gültigen Lieferumfang.,Le champ ne contient pas de volume de livraison valide.,Il campo non contiene un volume di consegna valido.
+countries,ES,Spain,España,Spanien,Espagne,Spagna
+countries,DE,Germany,Alemania,Deutschland,Allemagne,Germania
+countries,FR,France,Francia,Frankreich,France,Francia
+countries,IT,Italy,Italia,Italien,Italie,Italia
+countries,AT,Austria,Austria,Österreich,Autriche,Austria
+countries,NL,Netherlands,Países Bajos,Niederlande,Pays-Bas,Paesi Bassi
+countries,BE,Belgium,Bélgica,Belgien,Belgique,Belgio
+countries,PT,Portugal,Portugal,Portugal,Portugal,Portogallo
+countries,TR,Turkey,Turquía,Türkei,Turquie,Turchia
+countries,IE,Ireland,Irlanda,Irland,Irlande,Irlanda
+countries,GB,Great Britain,Reino Unido,Vereinigtes Königreich,Royaume-Uni,Regno Unito
+countries,HU,Hungary,Hungría,Ungarn,Hongrie,Ungheria
+countries,PL,Poland,Polonia,Polen,Pologne,Polonia
+countries,CH,Switzerland,Suiza,Schweiz,Suisse,Svizzera
+countries,LU,Luxembourg,Luxemburgo,Luxemburg,Luxembourg,Lussemburgo
+countries,AR,Argentina,Argentina,Argentinien,Argentine,Argentina
+countries,US,United States,Estados Unidos,Vereinigte Staaten,États Unis,Stati Uniti
+countries,BO,Bolivia,Bolivia,Bolivien,Bolivie,Bolivia
+countries,MX,Mexico,México,Mexiko,Mexique,Messico
+countries,CL,Chile,Chile,Chile,Chili,Chile
+countries,CZ,Czech Republic,Republica checa,Tschechien,République Tchèque,Repubblica Ceca
+countries,SE,Sweden,Suecia,Schweden,Suède,Svezia
+onboardingWelcome,header,Let's set up basic information so that you can make shipments,Vamos a configurar tu información básica para poder hacer envíos,"Richten Sie nun die grundlegenden Informationen ein, damit Sie Versendungen vornehmen können",Configurez vos informations de base afin d’effectuer des envois,È necessario impostare alcuni dati di base così che potrai effettuare spedizioni
+onboardingWelcome,steps,It's just two steps that we need to go through to offer you the carrier that best suits your needs,"Son solo dos pasos, los necesitamos para ofrecerte los servicios de transporte que más se adaptan a tus necesidades.","In nur zwei Schritten können wir Ihnen den Spediteur anbieten, der all Ihre Anforderungen erfüllt",Il ne vous reste que deux étapes pour savoir quel transporteur répond le mieux à vos besoins,Si tratta di due semplici passaggi che dobbiamo completare per offrirti la compagnia di trasporto che più si adatta alle tue esigenze
+onboardingWelcome,stepOne,Set parcel details,Configurar los detalles del paquete,Paketangaben einfügen,Configurez les informations sur le colis,Imposta i dettagli del pacco
+onboardingWelcome,stepTwo,Set sender's address,Configurar la dirección del remitente,Absenderadresse eingeben,Configurez l’adresse de l’émetteur,Imposta l’indirizzo del mittente
+onboardingWelcome,startSetUp,Start set up,Comenzar con la configuración,Einrichten beginnen,Démarrez la configuration,Avvia la configurazione
+onboardingOverview,header,Almost there! Please check that the entered information is correct or complete it in order to continue.,"Ya casi estamos. Por favor, comprueba que la información es correcta o complétala para continuar.","Fast geschafft! Bitte überprüfen Sie, ob die eingegebenen Informationen richtig sind oder vervollständigen Sie die Angaben, um fortzufahren.",Vous y êtes presque ! Veuillez vérifier que les informations saisies sont correctes ou complétez-les pour continuer.,"Ci siamo quasi! Per continuare, verifica che i dati inseriti siano corretti o completali."
+onboardingOverview,parcelDetails,Parcel details,Detalle del paquete,Paketangaben,Informations sur le colis,Dettagli del pacco
+onboardingOverview,senderAddress,Sender's Address,Dirección del remitente,Absenderadresse,Adresse de l’émetteur,Indirizzo del mittente
+onboardingOverview,missingInfo,Missing information,Faltan datos,Fehlende Informationen,Informations manquantes,Dati mancanti
+onboardingOverview,parcelData,Weight %s kg | Height %s cm | Width %s cm | Length %s cm,Peso %s kg | Alto %s cm | Ancho %s cm | Largo %s cm,Gewicht %s kg | Höhe %s cm | Breite %s cm | Länge %s cm,Poids %s kg | Hauteur %s cm | Largeur %s cm | Longueur %s cm,Peso %s kg | Altezza %s cm | Largezza %s cm | Lunghezza %s cm
+onboardingOverview,warehouseData,%s | %s | %s,%s | %s | %s,%s | %s | %s,%s | %s | %s,%s | %s | %s
+defaultParcel,title-onboarding,1. Set parcel details,1. Configurar los detalles del paquete,1. Paketangaben einfügen,1. Configurez les informations sur le colis,1. Imposta i dettagli del pacco
+defaultParcel,description-onboarding,We will use this default data for items that do not have defined dimensions and weight. You can edit them whenever you like via the settings tab.,Utilizaremos estos datos predeterminados para los artículos que no tengan dimensiones y peso definidos. Podrás editarlos cuando quieras desde la pestaña de configuración.,"Wir werden diese Standarddaten für Artikel verwenden, die keine festgelegten Abmessungen und kein festgelegtes Gewicht haben. Sie können sie jederzeit über die Registerkarte Einstellungen bearbeiten.",Nous utiliserons ces données prédéfinies pour les articles dont les dimensions et le poids n’ont pas été définis. Vous pouvez les modifier à tout moment via l’onglet Paramètres.,Useremo questi dati predefiniti per gli articoli per cui non vengono specificate le dimensioni e il peso. Puoi modificarli quando vuoi dalla scheda delle impostazioni.
+defaultParcel,title-config,Default parcel,Paquete predeterminado,Standardpaket,Colis prédéfini,Pacco predefinito
+defaultParcel,description-config,We will use this data for items that do not have defined dimensions and weight.,Utilizaremos estos datos para los artículos que no tengan dimensiones y peso definidos.,"Wir werden diese Daten für Artikel verwenden, die keine festgelegten Abmessungen und kein festgelegtes Gewicht haben.",Nous utiliserons ces données pour les articles dont les dimensions et le poids n’ont pas été définis.,Useremo questi dati per articoli privi di dimensioni e peso definiti.
+defaultParcel,weight,Weight,Peso,Gewicht,Poids,Peso
+defaultParcel,height,Height,Alto,Höhe,Hauteur,Altezza
+defaultParcel,width,Width,Ancho,Breite,Largeur,Largezza
+defaultParcel,length,Length,Largo,Länge,Longueur,Lunghezza
+defaultWarehouse,title-onboarding,2. Set sender’s address,2. Configurar la dirección del remitente,2. Absenderadresse eingeben,2. Configurer l’adresse de l’émetteur,2. Imposta l’indirizzo del mittente
+defaultWarehouse,description-onboarding,We will use this address to create a default sender for all shipments. You will be able to edit it whenever you wish via the settings tab.,Utilizaremos esta dirección para crear un remitente por defecto que valga para todos los envíos. Podrás editarla cuando quieras desde la pestaña de configuración.,"Wir werden diese Adresse verwenden, um einen Standardabsender für alle Sendungen zu erstellen. Sie können die Adresse jederzeit über die Registerkarte Einstellungen bearbeiten.",Nous utiliserons cette adresse pour créer un émetteur prédéfini pour toutes les expéditions. Vous pourrez la modifier à tout moment via l’onglet Paramètres.,Useremo questo indirizzo per creare un mittente predefinito per tutte le spedizioni. Potrai modificarlo ogni volta che vuoi dalla scheda delle impostazioni.
+defaultWarehouse,title-config,Default sender address,Dirección del remitente por defecto,Standard-Absenderadresse,Adresse de l’émetteur prédéfinie,Indirizzo del mittente predefinito
+defaultWarehouse,description-config,We will use this address to create a default sender for all shipments. You can edit it at any time.,Utilizaremos esta dirección para crear un remitente por defecto que valga para todos los envíos.,"Wir werden diese Adresse verwenden, um einen Standardabsender für alle Sendungen zu erstellen. Sie können die Adresse jederzeit bearbeiten.",Nous utiliserons cette adresse pour créer un émetteur prédéfini pour toutes les expéditions. Vous pourrez la modifier à tout moment.,Useremo questo indirizzo per creare un mittente predefinito per tutte le spedizioni. Potrai modificarlo ogni volta che vuoi.
+defaultWarehouse,alias,Sender name,Nombre del almacén,Absendername,Nom de l’émetteur,Nome del mittente
+defaultWarehouse,alias-placeholder,Main warehouse,Almacen principal,Hauptlager,Magasin principal,Magazzino principale
+defaultWarehouse,name,Name of contact person,Nombre de la persona de contacto,Name der Kontaktperson,Prénom de la personne à contacter,Nome della persona di contatto
+defaultWarehouse,name-placeholder,Name,Nombe de la persona,Name,Prénom,Nome
+defaultWarehouse,surname,Surname of contact person,Apellido de la persona de contacto,Nachname der Kontaktperson,Nom de la personne à contacter,Cognome della persona di contatto
+defaultWarehouse,surname-placeholder,Surname,Apellido de la persona,Nachname,Nom,cognome
+defaultWarehouse,company,Company name,Nombre de la empresa,Unternehmen,Nom de l'entreprise,Nome dell'azienda
+defaultWarehouse,company-placeholder,Company,Empresa S.A.,Unternehmen,Société,Azienda
+defaultWarehouse,country,Country,País,Land,Pays,Paese
+defaultWarehouse,postal_code,City or postcode,Ciudad o código postal,Stadt oder Postleitzahl,Ville ou code postal,Città o codice postale
+defaultWarehouse,postal_code-placeholder,-,-,-,-,-
+defaultWarehouse,address,Address,Dirección,Straße und Hausnummer,Adresse,Indirizzo
+defaultWarehouse,address-placeholder,Address,Dirección,Anschrift,Adresse,Indirizzo
+defaultWarehouse,phone,Phone number,Número de teléfono,Telefonnummer,Numéro de téléphone,Numero di telefono
+defaultWarehouse,phone-placeholder,123 456 7777,123 456 7777,123 456 7777,123 456 7777,123 456 7777
+defaultWarehouse,email,Email,Correo electrónico,E-Mail-Adresse,Email,Email
+defaultWarehouse,email-placeholder,youremail@example.com,tucorreo@example.com,ihreemail@example.com,votreemail@exemple.com,latuaemail@esempio.com
+configuration,menu,Settings,Configuración,Einstellungen,Paramètres,Impostazioni
+configuration,title,Settings,Configuración,Einstellungen,Paramètres,Impostazioni
+configuration,orderStatus,Order status,Estado de la orden,Bestellstatus,Statut de la commande,Stato dell’ordine
+configuration,warehouse,Default sender address,Almacén por defecto,Standard-Absenderadresse,Adresse de l’émetteur prédéfinie,Indirizzo del mittente predefinito
+configuration,parcel,Default parcel,Paquete predeterminado,Standardpaket,Colis par défaut,Pacco predefinito
+configuration,help,Help,Ayuda,Hilfe,Aide,Aiuto
+configuration,contactUs,Contact us at:,Contáctanos:,Kontaktieren Sie uns:,Contactez-nous:,Contattaci:
+configuration,systemInfo,System information,Información del sistema,Systeminformationen,Informations du système,Informazioni del sistema
+systemInfo,title,System information file and debug mode,System information file and debug mode,Systeminfodatei und debug mode,Fichier d’informations du système et mode débogage,File di informazioni del sistema e modalità debug
+systemInfo,debugMode,Debug mode,Debug mode,Debug mode,Debug mode,Debug mode
+systemInfo,download,Download system information,Download system information,Systeminfodatei herunterladen,Téléchargez le document d'information système,Scarica il file di informazioni del sistema
+orderStatusMapping,title,Order status,Estado de la orden,Bestellstatus,Statut de la commande,Stato dell’ordine
+orderStatusMapping,description,With Packlink you can update your %s order status with shipping information. You can edit it at any time.,Con Packlink puedes actualizar el estado de tu pedido de %s con la información de envío. Puedes editarla en cualquier momento.,Mit Packlink können Sie Ihren %s Bestellstatus mit Versandinformationen aktualisieren. Sie können die Informationen jederzeit bearbeiten.,"Avec Packlink, vous pouvez mettre à jour le statut de votre commande %s avec les informations d’expédition. Vous pourrez les modifier à tout moment.","Con Packlink, puoi aggiornare lo stato dell’ordine %s con i dati della spedizione. Puoi modificarlo ogni volta che vuoi."
+orderStatusMapping,packlinkProShipmentStatus,Packlink PRO SHIPMENT STATUS,ESTADO DEL ENVÍO de Packlink PRO,VERSANDSTATUS von Packlink PRO,STATUT DE LIVRAISON Packlink PRO,STATO DELLA SPEDIZIONE di Packlink PRO
+orderStatusMapping,systemOrderStatus,%s ORDER STATUS,ESTADO DEL PEDIDO de %s,BESTELLSTATUS von %s,STATUT DE LA COMMANDE %s,STATO DELLA SPEDIZIONE di %s
+orderStatusMapping,none,None,Ninguno,Leer,Aucun,Nessuno
+orderStatusMapping,pending,Pending,Pendiente,Ausstehend,En attente,In attesa
+orderStatusMapping,processing,Processing,Procesando,In Bearbeitung,En cours de traitement,Processando
+orderStatusMapping,readyForShipping,Ready for shipping,Listo para enviar,Versandfertig,Prêt pour la livraison,Pronto per la spedizione
+orderStatusMapping,inTransit,In transit,En tránsito,Unterwegs,En transit,In transito
+orderStatusMapping,delivered,Delivered,Entregado,Zugestellt,Délivré,Consegnato
+orderStatusMapping,cancelled,Canceled,Cancelado,Storniert,Annulé,Annullato
+shippingServices,myServices,My shipping services,Mis servicios de envío,Mein Versandservice,Mes services d’expédition,I miei servizi di spedizione
+shippingServices,noServicesTitle,You just need to add your shipment services,Solo queda añadir tus servicios de envío,Sie brauchen nur Ihre Transportdienstleistung hinzuzufügen,Vous devez simplement ajouter vos services d’expédition,Dovrai solo aggiungere i tuoi servizi di spedizione
+shippingServices,noServicesDescription,"They will be shown to your customer at the time of checkout, so that they can choose which carrier will deliver their parcel. Set it up now so that you don't need to worry about anything else. You can change it whenever you wish, to renew or upgrade shipping services.","Se mostrarán a tu cliente en el momento del checkout, así podrá elegir qué transportista le llevará su paquete. Lo configuras ahora y no tienes que preocuparte por nada más, puedes cambiarlo siempre que quieras para renovar o ampliar servicios de envío.","Sie werden Ihrem Kunden zum Zeitpunkt der Kaufabwicklung angezeigt, damit er auswählen kann, welcher Spediteur sein Paket ausliefert. Richten Sie es jetzt ein, damit Sie sich um nichts anderes kümmern müssen. Sie können es jederzeit ändern, um die Versanddienste zu erneuern oder zu aktualisieren.","Votre client pourra les voir au moment du paiement et choisir le transporteur qui livrera son colis. Configurez-les maintenant pour n’avoir à vous soucier de rien d’autre. Vous pourrez à tout moment modifier, mettre à jour ou améliorer vos services d’expédition.","Questi saranno mostrati al cliente al momento del pagamento, per consentirgli di scegliere la compagnia di trasporto che effettuerà la consegna del pacco. Configurali adesso e non dovrai più preoccuparti di nulla. Puoi modificarli ogni volta che vuoi, per aggiornare o rinnovare i servizi di spedizione."
+shippingServices,addService,Add service,Añadir servicio,Dienstleistung hinzufügen,Ajouter un service,Aggiungi servizio
+shippingServices,addNewService,Add new service,Añadir nuevo servicio,Neue Dienstleistung hinzufügen,Ajouter un nouveau service,Aggiungi nuovo servizio
+shippingServices,addedSuccessTitle,Shipping service added successfully,Servicio de envío añadido correctamente,Versanddienst erfolgreich hinzugefügt,Service d’expédition ajouté avec succès,Il servizio di spedizione è stato aggiunto
+shippingServices,addedSuccessDescription,"You can edit the service from the ""My services"" section.","Podrás editarlo desde la sección ""Mis servicios"".",Sie können die Dienstleistung unter „Meine Dienstleistungen“ bearbeiten.,Vous pouvez modifier le service dans la section « Mes services ».,"Puoi modificare il servizio dalla sezione ""I miei servizi""."
+shippingServices,deletedSuccessTitle,Shipping service deleted successfully,Servicio de envío eliminado correctamente,Versanddienst erfolgreich gelöscht,Service d’expédition supprimé avec succès,Il servizio di spedizione è stato eliminato
+shippingServices,deletedSuccessDescription,"You can add new services from the ""Add new service"" button.","Puedes añadir nuevos servicios con el botón ""Añadir nuevo servicio"".",Über die Schaltfläche „Neue Dienstleistung hinzufügen“ können Sie neue Dienstleistungen hinzufügen.,Vous pouvez ajouter de nouveaux services avec le bouton « Ajouter un nouveau service ».,"Puoi aggiungere nuovi servizi tramite il pulsante ""Aggiungi nuovo servizio""."
+shippingServices,disableCarriersTitle,You have created your first shipment service. Do you want to disable previous carriers?,Has creado tu primer servicio de envío. ¿Quieres desabilitar los transportistas anteriores?,Sie haben Ihre erste Transportdienstleistung erstellt. Möchten Sie die vorherigen Spediteure deaktivieren?,Vous avez créé votre premier service d’expédition. Souhaitez-vous désactiver les anciens transporteurs ?,Hai creato il tuo primo servizio di spedizione. Vuoi disattivare le compagnie di trasporto precedenti?
+shippingServices,disableCarriersDescription,"To provide you with a better service, it is important to disable the carriers you previously used.","Para ofrecerte un mejor servicio, es importante desabilitar los transportistas que tenías previamente.","Um Ihnen einen besseren Service anbieten zu können, sollten Sie die vorher genutzten Spediteure deaktivieren.","Afin de vous offrir un meilleur service, il est important de désactiver le transporteur que vous utilisiez auparavant.","Per garantirti un servizio migliore, è importante disattivare le compagnie di trasporto utilizzati in precedenza."
+shippingServices,successfullyDisabledShippingMethods,Successfully disabled shipping methods.,Servicios de envío correctamente deseleccionados.,Versanddienste erfolgreich deaktiviert.,Service d'envoi désactivé avec succès.,Servizi di spedizione disattivati correttamente.
+shippingServices,failedToDisableShippingMethods,Failed to disable shipping methods.,Error al deshabilitar los servicios de envío.,Versanddienste konnten nicht deaktiviert werden.,Échec de la désactivation du service d'envoi.,Impossibile disattivare i servizi di spedizione.
+shippingServices,pickShippingService,Add delivery services,Añadir servicios de envío,Lieferdienst hinzufügen,Ajouter des services de livraison,Aggiungi servizi di consegna
+shippingServices,failedGettingServicesTitle,We are having troubles getting shipping services,Tenemos dificultades para obtener servicios de envío,Beim Abrufen der Versanddienste ist ein Problem aufgetreten,Nous rencontrons des problèmes dans l’importation des services de livraison,Si è verificato un problema durante l’acquisizione dei servizi di spedizione
+shippingServices,failedGettingServicesSubtitle,Do you want to retry?,¿Quieres volverlo a intentar?,Möchten Sie es erneut versuchen?,Souhaitez-vous réessayer ?,Vuoi riprovare?
+shippingServices,retry,Retry,Volver a intentar,Erneut versuchen,Réessayer,Riprova
+shippingServices,filterModalTitle,Filters,Filtros,Filter,Filtres,Filtri
+shippingServices,applyFilters,Apply filters,Aplicar,Filter anwenden,Appliquer les filtres,Applica i filtri
+shippingServices,type,Type,Tipo,Typ,Type,Tipo
+shippingServices,national,Domestic,Nacional,National,National,Nazionale
+shippingServices,international,International,Internacional,International,International,Internazionale
+shippingServices,deliveryType,Type of shipment,Servicio,Versandart,Livraison,Servizio
+shippingServices,economic,Budget,Económico,Standard,Économique,Economico
+shippingServices,express,Express,Express,Express,Express,Espresso
+shippingServices,parcelOrigin,Parcel origin,Origen,Absendeort des Pakets,Origine du colis,Origine del pacco
+shippingServices,collection,Collection,Recogida,Abholung an Adresse,Collecte à domicile,Ritiro a domicilio
+shippingServices,dropoff,Drop off,Drop off,Abgabe im Paketshop,Dépôt en point relais,Ritiro in punto corriere
+shippingServices,parcelDestination,Parcel destination,Destino,Zielort des Pakets,Destination du colis,Destinazione pacco
+shippingServices,pickup,Pick up,Pick up,Abholung im Paketshop,Point de retrait,Consegna al domicilio
+shippingServices,delivery,Delivery,Entrega,Zustellung an Adresse,Livraison à domicile,Consegna in punto corriere
+shippingServices,carrierLogo,Carrier logo,Logo del transportista,Logo des Versandunternehmens,Logo du transporteur,Logo del corriere
+shippingServices,carrier,Carrier,Transportista,Versandpartner,Transporteur,Corriere
+shippingServices,serviceTitle,Service title,Nombre del servicio,Name des Dienstes,Titre du service,Titolo del servizio
+shippingServices,serviceTitleDescription,Customise your shipment by editing it. Your customers will be able to see it.,Personaliza tu envío editándolo. Será visible para tus clientes.,"Personalisieren Sie Ihren Versand, indem Sie ihn bearbeiten. Ihre Kunden werden es sehen können.",Personnalisez votre envoi en le modifiant. Vos clients pourront le voir.,Modifica le tue spedizioni per personalizzarle. Queste informazioni saranno visualizzate dai tuoi clienti.
+shippingServices,transitTime,Transit Time,Tiempo de tránsito,Versandlaufzeit,Temps de transit,Tempi di transito
+shippingServices,origin,Origin,Origen,Absender,Origine,Origine
+shippingServices,destination,Destination,Destino,Empfänger,Destination,Destinazione
+shippingServices,myPrices,My prices,Mis precios,Meine Preise,Mes prix,I miei prezzi
+shippingServices,packlinkPrices,Packlink prices,Precios de Packlink,Packlink-Preise,Prix Packlink,Prezzi di Packlink
+shippingServices,configureService,Set up service,Configura el servicio,Dienst einrichten,Configurer le service,Configura il servizio
+shippingServices,showCarrierLogo,Show carrier logo to my customers,Mostrar logo del transportista a mis clientes.,Meinen Kunden das Logo anzeigen,Montrer le logo du transporteur à mes clients,Mostra logo del corriere ai miei clienti
+shippingServices,pricePolicy,Price policy,Política de precios,Preispolitik,Politique tarifaire,Politica dei prezzi
+shippingServices,pricePolicyDescription,The default will be Packlink's basic prices. But you can configure these in a more precise way below.,Por defecto serán los precios base de Packlink. Pero puedes configurarlos de manera más precisa a continuación.,Standardmäßig werden die Packlink Basispreise eingestellt sein. Sie können diese jedoch weiter unten genauer konfigurieren.,"Les tarifs de base de Packlink seront configurés par défaut, mais vous pourrez les configurer plus en détail ci-dessous.","Per impostazione predefinita, saranno i prezzi di base di Packlink, ma puoi configurarli più dettagliatamente qui di seguito."
+shippingServices,configurePricePolicy,Set up my shipment prices,Configurar mis precios de envío,Meine Versandkosten einrichten,Configurer mes frais d’expédition,Configura i prezzi di spedizione
+shippingServices,taxClassTitle,Choose your saved tax class,Elige tu tipo de impuesto guardado,Wählen Sie Ihre gespeicherte Steuerkategorie,Sélectionnez votre taux fiscal enregistré,Scegli la tua aliquota fiscale salvata
+shippingServices,tax,Tax,Impuestos,Steuer,Taxe,Tassa
+shippingServices,serviceCountriesTitle,Availability by destination country,Disponibilidad por país de destino,Verfügbarkeit nach Zielland,Disponibilité par pays de destination,Disponibilità per paese di destinazione
+shippingServices,serviceCountriesDescription,Select the availability for the countries that are supported for your shipping service.,Selecciona la disponibilidad para los países que hay permitidos para tu servicio de envío.,"Wählen Sie die Verfügbarkeit der Länder, die von Ihrem Versanddienst unterstützt werden.",Sélectionnez la disponibilité des pays pris en charge par votre service d’expédition.,Seleziona la disponibilità per i paesi supportati per i tuoi servizi di spedizione.
+shippingServices,openCountries,See countries,Ver países,Länder anzeigen,Voir pays,Vedi i paesi
+shippingServices,allCountriesSelected,All countries selected,Todos los países seleccionados,Es wurden alle Länder ausgewählt,Tous les pays sont sélectionnés,Tutti i paesi selezionati
+shippingServices,oneCountrySelected,One country selected,Un país seleccionado,Es wurde ein Land ausgewählt,Un pays est sélectionné,Un paese selezionato
+shippingServices,selectedCountries,%s countries selected.,%s países seleccionados,Es wurden %s Länder ausgewählt,%s pays sont sélectionnés,%s paesi selezionati
+shippingServices,firstPricePolicyDescription,"Perfect, just a couple of steps:
1. Choose whether you want to set them by weight and/or purchase price.
2. Choose a price policy and set it up.","Perfecto, son un par de pasos:
1- Elige si quieres fijarlos por el peso y/o el precio de la compra.
2- Elige una política de precios y configúrala.","Perfekt, nur noch wenige Schritte:
1. Wählen Sie aus, ob Sie diese nach Gewicht und / oder Kaufpreis einstellen möchten.
2. Wählen Sie eine Preispolitik und richten Sie diese ein.","Parfait, il ne vous reste que quelques étapes :
1. Choisissez si vous souhaitez les configurer par poids et/ou par prix d’achat.
2. Choisissez une politique tarifaire et configurez-la.","Perfetto, mancano solo due passaggi:
1. Scegli se vuoi importarli per peso e/o prezzo di acquisto.
2. Scegli una politica dei prezzi e configurala."
+shippingServices,addFirstPolicy,Add price rule,Añadir regla de precio,Preisregel hinzufügen,Ajouter une règle de prix,Aggiungi regola di prezzo
+shippingServices,addAnotherPolicy,Add another rule,Añadir otro precio,Weitere Regel hinzufügen,Ajouter une autre règle,Aggiungi un’altra regola
+shippingServices,from,From,Desde,Von,De,Da
+shippingServices,to,To,Hasta,Bis,À,A
+shippingServices,price,Price,Precio,Preis,Prix,Prezzo
+shippingServices,rangeTypeExplanation,1. Choose whether you want to set them by weight and/or purchase price.,1- Elige si quieres fijarlos por el peso y/o el precio de la compra.,"1. Wählen Sie aus, ob Sie diese nach Gewicht und / oder Kaufpreis einstellen möchten.",1. Choisissez si vous souhaitez les configurer par poids et/ou par prix d’achat.,1. Scegli se vuoi importarli per peso e/o prezzo di acquisto.
+shippingServices,rangeType,Range type,Tipo de rango,Typenreihe,Type de fourchette,Tipo di range
+shippingServices,priceRange,Price range,Rango de precio,Preisklasse,Fourchette de prix,Range di prezzo
+shippingServices,priceRangeWithData,Price range: from %s€ to %s€,Rango de precio: desde %s€ hasta %s€,Preisklasse: von %s € bis %s €,Fourchette de prix : de %s € à %s €,Range di prezzo: da %s€ a %s€
+shippingServices,weightRange,Weight range,Rango de peso,Gewichtsklasse,Fourchette de poids,Range di peso
+shippingServices,weightRangeWithData,Weight range: from %s kg to %s kg,Rango de peso: desde %s kg hasta %s kg,Gewichtsklasse: von %s kg bis %s kg,Fourchette de poids : de %s kg à %s kg,Range di peso: da %s kg a %s kg
+shippingServices,weightAndPriceRange,Weight and price range,Rango de peso y precio,Gewichts- und Preisklasse,Fourchette de poids et de prix,Range di prezzo e di peso
+shippingServices,weightAndPriceRangeWithData,Weight and price range: from %s kg to %s kg and from %s€ to %s€,Rango de peso y precio: desde %s kg hasta %s kg y desde %s€ hasta %s€,Gewichts- und Preisklasse: von %s kg bis %s kg und von %s € bis %s €,Fourchette de poids et de prix : de %s kg à %s kg et de %s € à %s €,Range di prezzo e di peso: da %s kg a %s kg e da %s€ a %s€
+shippingServices,singlePricePolicy,Price policy %s,Política de precio %s,Preispolitik %s,Politique tarifaire %s,Politica dei prezzi %s
+shippingServices,pricePolicyExplanation,2. Choose a price policy and set it up.,2- Elige una política de precios y configúrala.,2. Wählen Sie eine Preispolitik und richten Sie diese ein.,2. Choisissez une politique tarifaire et configurez-la.,2. Scegli una politica dei prezzi e configurala.
+shippingServices,packlinkPrice,Packlink Price,Precio Packlink,Packlink-Preise,Prix Packlink,Prezzo di Packlink
+shippingServices,percentagePacklinkPrices,% of Packlink prices,% de los precio de Packlink,% der Packlink-Preise,% des prix Packlink,% dei prezzi di Packlink
+shippingServices,percentagePacklinkPricesWithData,% of Packlink prices: %s by %s%,% de los precio de Packlink: %s por %s%,% der Packlink-Preise: %s von %s%,% des prix Packlink : %s de %s%,% dei prezzi di Packlink: %s del %s%
+shippingServices,fixedPrices,Fixed price,Precio fijo,Festpreis,Prix fixe,Prezzo fisso
+shippingServices,fixedPricesWithData,Fixed price: %s€,Precio fijo: %s€,Festpreis: %s €,Prix fixe : %s €,Prezzo fisso: %s€
+shippingServices,increaseExplanation,"Increase: add a % to the price, this will be paid by the customer.","Incrementar: añade un % al precio, lo pagará el cliente.",Erhöhen: fügen Sie % zum Preis hinzu. Dies wird dann vom Kunden bezahlt.,"Augmentation : ajoutez % au prix, c’est le client qui payera.","Incremento sul prezzo: aggiungi una % al prezzo, che sarà pagata dal cliente."
+shippingServices,reduceExplanation,"Reduce: deduct a % from the price, you will pay for it yourself.","Reducir: descuenta un % al precio, lo pagarás tú.",Reduzieren: ziehen Sie % vom Preis ab. Dies werden Sie dann selbst zahlen.,"Réduction : déduisez % du prix, c’est vous qui payerez.","Riduzione sul prezzo: deduci una % dal prezzo, che sarà pagata da te."
+shippingServices,select,Select,Elige,Auswählen,Sélectionner,Sélectionner
+shippingServices,invalidRange,Invalid range,Rango no válido,Unzulässiger Bereich,Fourchette invalide,Range non valido
+shippingServices,increase,increase,incrementar,Erhöhen,Augmenter,Aumenta
+shippingServices,reduce,reduce,reducir,Reduzieren,Réduire,Diminuisci
+shippingServices,selectAllCountries,All selected countries,Selecionar todos los países,Alle ausgewählten Länder,Tous les pays sélectionnés,Tutti i paesi selezionati
+shippingServices,selectCountriesHeader,Countries supported for your shipping service,Países permitidos para tu servicio de envío,"Länder, die von Ihrem Versanddienst unterstützt werden",Pays pris en charge par votre service d’expédition,Paesi supportati per il tuo servizio di spedizione
+shippingServices,selectCountriesSubheader,Select availability of at least one country and add as many required,Selecciona la disponibilidad de al menos un país y añade tantos como necesites,Wählen Sie die Verfügbarkeit von mindestens einem Land aus und fügen Sie beliebig viele hinzu,Sélectionnez la disponibilité d’au moins un pays et ajoutez-en autant que nécessaire,Seleziona la disponibilità di almeno un paese e aggiungi tutti quelli richiesti
+shippingServices,usePacklinkRange,"For all other ranges, apply Packlink prices","Para el resto de rangos, aplicar precios Packlink",Für alle anderen Bereiche gelten die Packlink-Preise,"Pour toutes les autres fourchettes, appliquez les prix Packlink","Per tutti gli altri range, applica i prezzi di Packlink"
+shippingServices,discardChangesQuestion,There are unsaved changes. Are you sure you want to go back and discard them?,Algunos cambios no se han guardado. ¿Estás seguro de que quieres volver e ignorar los cambios?,"Es gibt nicht gespeicherte Änderungen. Sind Sie sicher, dass Sie zurückgehen und sie verwerfen möchten?",Certaines modifications n’ont pas été enregistrées. Êtes-vous sûr de vouloir revenir en arrière et de les ignorer ?,Alcune modifiche non sono state salvate. Sei sicuro di voler tornare indietro e annullarle?
+orderListAndDetails,packlinkOrderDraft,Packlink order draft,Borrador del pedido de Packlink,Packlink Auftragsentwurf,Brouillon de commande Packlink,Bozza dell'ordine Packlink
+orderListAndDetails,printed,Printed,Impreso,Ausgedruckt,Imprimé,Stampato
+orderListAndDetails,ready,Ready,Listo,Bereit,Prêt,Pronto per la spedizione
+orderListAndDetails,printLabel,Print label,Imprimir etiquetas,Versandetikett drucken,Imprimer étiquette,Stampa etichette
+orderListAndDetails,shipmentLabels,Shipment Labels,Etiquetas de los envíos,Versandetiketten,Étiquettes de livraison,Etichette di spedizione
+orderListAndDetails,printShipmentLabels,Print Packlink PRO Shipment Labels,Imprimir Packlink PRO etiquetas de los envíos,Packlink PRO Versandetiketten drucken,Imprimer les étiquettes de livraison Packlink PRO,Stampa etichette di spedizione Packlink PRO
+orderListAndDetails,shipmentDetails,Shipment details,Detalles del envío,Versanddetails,Détails de l'envoi,Dettagli della spedizione
+orderListAndDetails,disablePopUpBlocker,Please disable pop-up blocker on this page in order to bulk open shipment labels,Deshabilita el bloqueador de elementos emergentes en esta página para abrir de forma masiva las etiquetas de envío,"Bitte deaktivieren Sie den Popup-Blocker auf dieser Seite, um alle Versandetiketten auf einmal zu öffnen.",Veuillez désactiver l'outil de blocage des fenêtres pop-up sur cette page afin d'ouvrir massivement les étiquettes d'envoi.,Disabilita il blocco pop-up su questa pagina per poter aprire le etichette di spedizione insieme
+orderListAndDetails,date,Date,Fecha,Datum,Date,Data
+orderListAndDetails,number,Number,Número,Nummer,Numéro,Numero
+orderListAndDetails,status,Status,Estado,Status,Statut,Stato
+orderListAndDetails,print,Print,Imprimir,Drucken,Imprimer,Stampa
+orderListAndDetails,carrierTrackingNumbers,Carrier tracking numbers,Número de tracking del transportista,Trackingnummer des Versandunternehmens,Numéro de tracking du transporteur,Numero di tracking del corriere
+orderListAndDetails,trackIt,Track it!,Seguimiento,Versand verfolgen,Suivez le!,Traccialo!
+orderListAndDetails,packlinkReferenceNumber,Packlink reference number,Número de referencia Packlink,Packlink Referenznummer,Numéro de référence Packlink,Numero di ordine Packlink
+orderListAndDetails,packlinkShippingPrice,Packlink shipping price,Precio de envío de Packlink,Packlink Versandpreis,Prix de livraison Packlink,PPrezzo di spedizione Packlink
+orderListAndDetails,viewOnPacklink,View on Packlink PRO,Ver en Packlink PRO,Auf Packlink PRO ansehen,Voir sur Packlink PRO,Vedi su Packlink PRO
+orderListAndDetails,createDraft,Create Draft,Crear borrador,Entwurf erstellen,Créer un brouillon,Crea bozza
+orderListAndDetails,draftIsBeingCreated,Draft is currently being created in Packlink PRO,El borrador se está creando actualmente en Packlink PRO,Der Entwurf wird gerade in Packlink PRO erstellt,Le brouillon est en cours de création sur Packlink PRO,La bozza è attualmente in fase di creazione su Packlink PRO
+orderListAndDetails,createOrderDraft,Create order draft in Packlink PRO,Crear borrador en Packlink PRO,Entwurf der Bestellung in Packlink PRO erstellen,Créer un brouillon de commande sur Packlink PRO,Crea una bozza di ordine su Packlink PRO
+orderListAndDetails,draftCreateFailed,Previous attempt to create a draft failed. Error: %s,El intento anterior de crear un borrador ha fallado. Error: %s,Der Versuch der Entwurfserstellung ist fehlgeschlagen. Fehler: %s,La tentative précédente de création d'un brouillon a échoué. Erreur: %s,Il precedente tentativo di creare una bozza è fallito. Errore: %s
+orderListAndDetails,packlinkShipping,Packlink Shipping,Packlink Shipping,Packlink Shipping,Packlink Shipping,Packlink Shipping
+orderListAndDetails,shipmentOrderNotExist,Order with shipment reference %s doesn't exist in the shop,El pedido con referencia de envío %s no existe en la tienda,Die Bestellung mit der Versandreferenznummer %s existiert nicht im Shop,La commande de livraison sous le référence %s n'existe pas sur le shop.,L'ordine con il numero di spedizione %s non esiste nel negozio
+orderListAndDetails,orderDetailsNotFound,Order details not found,Detalles del pedido no encontrados,Bestelldetails nicht gefunden,Détails de commande introuvables,Dettagli dell'ordine non trovati
+orderListAndDetails,orderNotExist,Order with ID %s doesn't exist in the shop,El pedido con ID %s no existe en la tienda,Die Bestellung mit der ID %s existiert nicht im Shop,La commande sous l'ID %s n'existe pas sur le shop.,L'ordine con ID %s non esiste nel negozio
+orderListAndDetails,bulkFailCreateFail,Unable to create bulk labels file,No se puede crear el archivo de etiquetas masivas,Die Datei der Versandetiketten konnte nicht erstellt werden,Création d'un dossier d'étiquettes en masse impossible.,Impossibile creare il file di etichette in blocco
+orderListAndDetails,draftOrderDelayed,Creation of the draft is delayed,La creación del borrador se ha retrasado,Die Erstellung des Entwurfs verzögert sich,La création du brouillon a été retardée,La creazione della bozza è stata ritardata
+orderListAndDetails,completeServicesSetup,You need to complete the services setup to create order draft.,You need to complete the services setup to create order draft.,You need to complete the services setup to create order draft.,You need to complete the services setup to create order draft.,You need to complete the services setup to create order draft.
+orderListAndDetails,sendWithPacklink,Send with Packlink,Send with Packlink,Send with Packlink,Send with Packlink,Send with Packlink
+checkoutProcess,choseDropOffLocation,"This shipping service supports delivery to pre-defined drop-off locations. Please choose location that suits you the most by clicking on the ""Select drop-off location"" button.","Este servicio de envío admite la entrega a ubicaciones de entrega predefinidas. Elige la ubicación que más te convenga haciendo clic en el botón ""Seleccionar ubicación de entrega""..","Dieser Versanddienst unterstützt die Zustellung an vordefinierte Abgabestellen. Bitte wählen Sie den für Sie günstigsten Ort aus, indem Sie auf ""Abgabestelle auswählen"" klicken.","Ce service de transport soutient la livraison vers des lieux de dépôts prédéfinis. Veuillez choisir la localisation qui vous convient le mieux en cliquant sur le bouton ""Sélectionner le lieu de dépôt""","Questo servizio di spedizione supporta la consegna a punti corriere predefiniti. Scegli la località più adatta a te, facendo clic sul pulsante ""Seleziona punto corriere""."
+checkoutProcess,selectDropOffLocation,Select drop-off location,Seleccionar lugar de entrega,Abgabestelle auswählen,Sélectionner le lieu de dépôt.,Seleziona la località del punto corriere
+checkoutProcess,changeDropOffLocation,Change drop-off location,Cambiar el lugar de entrega,Abgabestelle ändern,Changer le lieu de depôt.,Cambia località del punto corriere
+checkoutProcess,packageDeliveredTo,Package will be delivered to:,El paquete será entregado a:,Das Paket wird geliefert an:,Le colis sera délivré à:,La spedizione verrà consegnata a:
+checkoutProcess,dropOffDeliveryAddress,Drop-Off delivery address,Dirección de entrega,Zustelladresse,Adresse de livraison.,Indirizzo di consegna del punto corriere
+checkoutProcess,changeAddress,There are no delivery locations available for your delivery address. Please change your address.,No hay servicio disponible para la dirección de entrega. Por favor cambia tu direccion.,Für Ihre Zustelladresse sind keine Zustellorte verfügbar. Bitte ändern Sie Ihre Adresse.,Il n'y a pas de lieux de livraison disponibles pour votre adresse de livraison. Veuillez changer votre adresse.,Non ci sono località di consegna disponibili per il tuo indirizzo di consegna. Per favore cambia l'indirizzo.
+checkoutProcess,shippingServiceNotFound,Shipping service not found,Servicio de envío no encontrado,Versanddienst nicht gefunden,Service de livraison introuvable.,Servizio di spedizione non trovato
+locationPicker,monday,Monday,Lunes,Montag,Lundi,Lunedì
+locationPicker,tuesday,Tuesday,Martes,Dienstag,Mardi,Martedì
+locationPicker,wednesday,Wednesday,Miércoles,Mittwoch,Mercredi,Mercoledì
+locationPicker,thursday,Thursday,Jueves,Donnerstag,Jeudi,Giovedì
+locationPicker,friday,Friday,Viernes,Freitag,Vendredi,Venerdì
+locationPicker,saturday,Saturday,Sábado,Samstag,Samedi,Sabato
+locationPicker,sunday,Sunday,Domingo,Sonntag,Dimanche,Domenica
+locationPicker,zipCode,Zip code,Código postal,Postleitzahl,Code postal,Codice postale
+locationPicker,idCode,ID code,Código ID,ID Code,Code ID,Codice ID
+locationPicker,selectThisLocation,Select this location,Selecciona esta ubicación,Diesen Ort auswählen,Sélectionner ce lieu,Seleziona la località
+locationPicker,showWorkingHours,Show working hours,Mostrar horas de apertura,Öffnungszeiten anzeigen,Montrer les heures de travail,Mostra orari di apertura
+locationPicker,hideWorkingHours,Hide working hours,Ocultar horario de apertura,Öffnungszeiten ausblenden,Cacher les heures d'ouverture,Nascondi orari di apertura
+locationPicker,showOnMap,Show on map,Mostrar en el mapa,Auf der Karte anzeigen,Montrer sur la carte,Mostra sulla mappa
+locationPicker,searchBy,"Search by location name, id or address","Buscar por nombre de ubicación, ID o dirección","Suche nach Standortname, ID oder Adresse","Chercher par lieu, nom, id ou adresse","Cerca nome della località per nome, id o indirizzo"
+migrationLogMessages,removeControllersHooksFailed,Failed to remove old controllers and hooks because: %s,Error al eliminar los controladores y enlaces antiguos porque: %s,Alte Controller und Hooks konnten nicht entfernt werden auf Grund von: %s,Echec du retrait des anciens régulateurs et crochets parce que. %s,Impossibile rimuovere vecchi controller e hook perché: %s
+migrationLogMessages,deleteObsoleteFilesFailed,Could not delete obsolete files because: %s,No se pudieron eliminar los archivos antiguos porque: %s,Alte Dateien konnten nicht gelöscht werden auf Grund von: %s,La suppression des dossiers obsolètes n'a pas pu être effectuée car: %s,Impossibile eliminare i file obsoleti perché: %s
+migrationLogMessages,oldAPIKeyDetected.,Old API key detected.,Se ha detectado una clave de API antigua.,Alter API-Schlüssel erkannt.,Ancienne clé API détectée.,Rilevata vecchia API Key.
+migrationLogMessages,successfullyLoggedIn,Successfully logged in with existing api key.,Has iniciado correctamente la sesión con la clave de API existente.,Erfolgreich mit bestehendem API-Schlüssel angemeldet.,Connecté avec succès avec la clé API existante.,Accesso eseguito correttamente con la API Key esistente.
+migrationLogMessages,removingObsoleteFiles.,Removing obsolete files.,Eliminando archivo antiguos.,Veraltete Dateien werden entfernt.,Retrait des dossiers osolètes.,Rimozione di file obsoleti.
+migrationLogMessages,cannotEnqueueUpgradeShopDetailsTask,Cannot enqueue UpgradeShopDetailsTask because: %s,No se pueden poner en espera los detalles de la actualización de la tienda porque: %s,UpgradeShopDetailsTask kann aus folgenden Gründen nicht in die Warteschlange gestellt werden: %s,"Mise en attente de la tâche ""Mise à jour des détails du Shop"" impossible car: %s",Impossibile richiamare UpgradeShopDetailsTask perché: %s
+migrationLogMessages,deletingOldPluginDta.,Deleting old plugin data.,Eliminando datos antiguos del plugin.,Alte Plugin-Daten werden gelöscht.,Suppression des informations relatives à l'ancien plugin.,Eliminando i vecchi dati del plug-in
+migrationLogMessages,cannotRetrieveOrderReferences,Cannot retrieve order references because: %s,No se pueden recuperar referencias de pedidos porque: %s,Bestellreferenzen können nicht abgerufen werden auf Grund von: %s,Récupération des références de commande impossible car: %s,Impossibile recuperare i riferimenti degli ordini perché: %s
+migrationLogMessages,createOrderReferenceFailed,Failed to create reference for order %s,Error al crear la referencia para el pedido %s,Referenz für Auftrag %s konnte nicht erstellt werden.,Échec de création de référence pour la commande %s,Impossibile creare il riferimento per l'ordine %s
+migrationLogMessages,setLabelsFailed,Failed to set labels for order with reference %s,Error al generar las etiquetas para el pedido con referencia %s,Versandetiketten für Bestellung mit Referenz %s konnten nicht erstellt werden.,Échec de la mise en place d'étiquettes pour la commande sous la référence %s,Impossibile impostare le etichette per l'ordine con riferimento %s
+migrationLogMessages,setTrackingInfoFailed,Failed to set tracking info for order with reference %s,Error al generar la información de seguimiento para el pedido con la referencia %s,Fehler beim Festlegen der Tracking-Informationen für die Bestellung mit Referenz %s,Échec de la mise en place des informations de suivi pour la commande sous la référence %s,Impossibile impostare le informazioni di tracciamento per l'ordine con riferimento %s
+migrationLogMessages,orderNotFound,Order with reference %s not found.,Pedido con referencia %s no encontrado.,Auftrag mit Referenz %s nicht gefunden.,La commande sous la référence %s introuvable.,Ordine con riferimento %s non trovato
+systemLogMessages,errorCreatingDefaultTask,Error creating default task runner status configuration.,Error creating default task runner status configuration.,Fehler beim Erstellen der Standardkonfiguration des Task-Runner-Status.,Erreur lors de la création de la configuration du gestionnaire de tâches par défaut.,Error creating default task runner status configuration.
+systemLogMessages,webhookReceived,Webhook from Packlink received.,Webhook de Packlink recibido,Webhook von Packlink erhalten,Webhook de Packlink reçu,Webhook di Packlink ricevuto
+systemLogMessages,couldNotDelete,Could not delete entity %s with ID %s,No se pudo eliminar la entidad %s con ID %s,Element %s mit ID %s konnte nicht gelöscht werden,L'entité %s dont l'ID est %s n'a pas pu être supprimée.,Impossibile eliminare l'entità %s con ID %s
+systemLogMessages,entityCannotBeSaved,Entity %s with ID %s cannot be saved.,La entidad %s con ID %s no se puede guardar.,Element %s mit ID %s kann nicht gespeichert werden.,L'entité %s dont l'ID est %s n'a pas pu être enregistrée.,L'entità %s con ID %s non può essere salvata.
+systemLogMessages,entityCannotBeUpdated,Entity %s with ID %s cannot be updated.,La entidad %s con ID %s no se puede actualizar.,Element %s mit ID %s kann nicht aktualisiert werden.,L'entité %s dont l'ID est %s n'a pas pu être mise à jour.,L'entità %s con ID %s non può essere aggiornata.
+systemLogMessages,fieldIsNotIndexed,Field %s is not indexed!,¡El campo %s no está indexado!,Feld %s ist nicht indiziert!,Le champs %s n'est pas indexé!,Il campo %s non è indicizzato!
+systemLogMessages,unknownOrNotIndexed,Unknown or not indexed OrderBy column %s,Desconocido o no indexado OrderBy column %s,Unbekannte oder nicht indizierte OrderBy-Spalte %s,Inconnu ou non-indexé OrderBy column %s,Colonna OrderBy %s sconosciuta o non indicizzata
+systemLogMessages,dirNotCreated,"Directory ""%s"" was not created","El directorio ""%s"" no fue creado","Das Verzeichnis ""%s"" wurde nicht erstellt","Annuaire ""%s"" n'a pas été créé","La directory ""%s"" non è stata creata"
+systemLogMessages,failedCreatingBackup,Failed creating backup service.,Error al crear el servicio flexible,Fehler beim Erstellen des Backup-Versanddienstes.,Impossible de créer le service de flexibilité.,Impossibile creare il servizio jolly.
+systemLogMessages,backupServiceNotFound,Backup service not found.,Servicio flexible no encontrado,Backup-Versanddienst konnte nicht gefunden werden.,Service de flexibilité introuvable,Servizio jolly non trovato.
+autoTest,dbNotAccessible.,Database not accessible.,DNo se puede acceder a la base de datos.,Zugriff auf Datenbank nicht möglich.,Base de données inaccessible.,Database non accessibile.
+autoTest,taskCouldNotBeStarted.,Task could not be started.,No se ha podido iniciar la tarea.,Die Aufgabe konnte nicht gestartet werden.,La tâche n’a pu être lancée.,Non è stato possibile avviare l’attività.
+autoTest,moduleAutoTest,PacklinkPRO module auto-test,Prueba automática del módulo PacklinkPRO,Automatischer Test PacklinkPRO-Modul,Test automatique du module PacklinkPRO,Auto-test per il modulo di PacklinkPRO
+autoTest,useThisPageTestConfiguration,Use this page to test the system configuration and PacklinkPRO module services.,Utiliza esta página para probar la configuración del sistema y los servicios del módulo PacklinkPRO.,Auf dieser Seite können Sie die Systemkonfiguration und die Dienste des PacklinkPRO-Moduls testen.,Utilisez cette page pour tester la configuration du système et les services du module PacklinkPRO.,Usa questa pagina per testare la configurazione del sistema e i servizi del modulo di PacklinkPRO.
+autoTest,start,Start,Inicio,Start,Démarrer,Avvia
+autoTest,downloadTestLog,Download test log,Descargar el registro de pruebas,Testprotokoll herunterladen,Télécharger le registre de tests,Scarica il registro test
+autoTest,openModule,Open PacklinkPRO module,Abrir el módulo PacklinkPRO,PacklinkPRO-Modul öffnen,Ouvrir le module PacklinkPRO,Apri il modulo di PacklinkPRO
+autoTest,autotestPassedSuccessfully,Auto-test passed successfully!,Prueba automática superada con éxito.,Der automatische Test wurde erfolgreich abgeschlossen!,Test automatique réussi avec succès !,L’auto-test è stato superato con successo!
+autoTest,testNotSuccessful,The test did not complete successfully.,La prueba no se ha completado correctamente.,Der Test wurde nicht erfolgreich abgeschlossen!,Le test a échoué.,Il test non è stato completato correttamente.
\ No newline at end of file
diff --git a/src/BusinessLogic/Resources/scss/animations.scss b/src/BusinessLogic/Resources/scss/animations.scss
new file mode 100644
index 00000000..b6a9ccef
--- /dev/null
+++ b/src/BusinessLogic/Resources/scss/animations.scss
@@ -0,0 +1,6 @@
+// animations
+@keyframes pl-rotate {
+ 100% {
+ transform: rotate(360deg);
+ }
+}
diff --git a/src/BusinessLogic/Resources/scss/app.scss b/src/BusinessLogic/Resources/scss/app.scss
new file mode 100644
index 00000000..b780e9f9
--- /dev/null
+++ b/src/BusinessLogic/Resources/scss/app.scss
@@ -0,0 +1,473 @@
+@import "variables";
+@import "reset";
+@import "animations";
+@import "utility";
+@import "ui-controls";
+@import "icons";
+
+#pl-page {
+ #pl-main-header {
+ height: 90px;
+ }
+
+ .pl-onboarding-list {
+ width: 100%;
+ justify-content: flex-start;
+ }
+
+ .pl-onboarding-overview-list {
+ width: 100%;
+
+ .pl-list-item {
+ flex-direction: row;
+ align-items: center;
+ padding-bottom: 20px;
+
+ i {
+ margin-right: 10px;
+ }
+
+ & + .pl-list-item {
+ border-top: 1px solid $color-light;
+ padding-top: 20px;
+ }
+
+ .pl-item-details {
+ text-align: left;
+ }
+
+ .pl-onboarding-list-title {
+ color: $color-gray;
+ text-align: left;
+ }
+ }
+ }
+
+ .pl-parcel-wrapper {
+ align-items: flex-start;
+ min-width: 100%;
+ }
+
+ .pl-main-logo img {
+ width: 200px;
+ }
+
+ .pl-register-country-list-wrapper {
+ margin: 15px 0 0;
+ min-width: 300px;
+ width: 100%;
+ display: flex;
+ flex-direction: column;
+
+ .pl-country {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ width: 100%;
+ padding: 5px 0;
+ color: $color-blue;
+ font-size: 15px;
+ text-transform: uppercase;
+ cursor: pointer;
+ flex-shrink: 0;
+
+ &:hover {
+ background-color: $color-little-transparent;
+
+ .pl-country-name {
+ color: $color-blue;
+ }
+ }
+
+ .pl-country-logo {
+ width: 60px;
+ }
+
+ .pl-country-name {
+ white-space: nowrap;
+ margin-left: 15px;
+ align-items: flex-start;
+ flex-grow: 1;
+ }
+
+ img {
+ width: 35px;
+ height: 35px;
+ }
+ }
+ }
+
+ .pl-login-footer {
+ padding: 24px 30px 32px;
+ background-color: $color-navy-dark;
+ color: $color-white;
+ flex-shrink: 0;
+
+ * {
+ color: $color-white;
+ }
+ }
+
+ .pl-onboarding-welcome-steps {
+ align-items: flex-start;
+ width: 100%;
+
+ .pl-list-item {
+ padding: 20px 0;
+ width: 100%;
+ border-bottom: 1px solid $color-light;
+
+ &:last-child {
+ border-bottom: none;
+ }
+ }
+ }
+
+ .pl-configuration-menu {
+ padding: 5px 20px;
+ margin-right: -20px;
+ font-weight: bold;
+
+ i {
+ margin-left: 10px;
+ }
+ }
+
+ .pl-configuration-page {
+ justify-content: space-between;
+
+ .pl-config-list {
+ flex-direction: column;
+ width: 300px;
+
+ .pl-config-list-item {
+ border-bottom: 1px solid $border-light;
+ padding: 17px 0 17px 26px;
+ flex-direction: row;
+ align-items: center;
+ width: 100%;
+
+ &:hover {
+ background-color: $border-light;
+ cursor: pointer;
+ }
+
+ a {
+ display: flex;
+ flex-direction: row;
+ flex-grow: 1;
+ align-items: center;
+ }
+ }
+ }
+
+ .pl-footer {
+ flex-direction: row;
+ justify-content: space-between;
+ padding: 20px;
+
+ span {
+ color: $color-light-gray;
+ margin-right: 5px;
+ }
+ }
+ }
+
+ .pl-page-onboarding {
+ .pl-page-buttons {
+ text-align: center;
+ }
+ }
+
+ .pl-page-config {
+ width: 100%;
+ flex-grow: 1;
+
+ header.pl-sub-header h1 {
+ text-align: left;
+ margin-left: 10px;
+ }
+
+ .pl-small-page, .pl-medium-page {
+ margin-left: 0;
+ margin-right: 0;
+ }
+
+ .pl-page-info {
+ text-align: left;
+ }
+ }
+
+ .pl-status-mapping {
+ width: 100%;
+ flex-direction: row;
+ border-top: 1px solid $border-light;
+ border-bottom: 1px solid $border-light;
+
+ &.pl-order-status-mappings-header {
+ border: none;
+ }
+
+ .pl-half-width {
+ flex-direction: row;
+ max-width: 50%;
+ min-width: 50%;
+ align-items: center;
+ margin: 0;
+ padding: 5px 0;
+
+ .pl-separation-indicator {
+ font-size: 32px;
+ margin-right: 36px;
+ }
+ }
+ }
+
+ .pl-services-filter-wrapper {
+ flex-direction: row;
+ width: 100%;
+ justify-content: flex-start;
+ padding: 0 20px;
+ flex: 0 0 auto;
+
+ .pl-filter:not(:last-child) {
+ margin-right: 32px;
+ }
+ }
+
+ .pl-pick-shipping-services-page {
+ #pl-open-filter-button {
+ display: none;
+ }
+ }
+
+ .pl-modal .pl-filters-wrapper {
+ width: 300px;
+ }
+
+ .pl-filter {
+ padding: 20px 0;
+
+ &.pl-filter-selected {
+ display: none;
+ }
+
+ .pl-filter-title {
+ text-transform: uppercase;
+ margin-bottom: 12px;
+ text-align: left;
+ color: $text-heading-color;
+ font-weight: bold;
+ }
+
+ .pl-filter-options {
+ flex-direction: row;
+ justify-content: flex-start;
+
+ .pl-filter-option {
+ padding: 6px 13px;
+ border: 1px solid $border-color;
+ border-radius: 13px;
+ cursor: pointer;
+ color: $input-control-color;
+ margin-right: 12px;
+
+ &.pl-selected {
+ border-color: $color-blue;
+ background-color: $color-blue;
+ color: $color-white;
+ }
+ }
+ }
+ }
+
+ .pl-form-group {
+ &:not(:first-child) {
+ &.pl-change-percent-wrapper {
+ margin-top: 0;
+ }
+ }
+ }
+
+ .pl-my-shipping-services-page {
+ header {
+ background-color: #1A77C2;
+ color: $color-white;
+ font-size: 18px;
+ font-weight: bold;
+ padding: 25px 21px;
+ }
+
+ .pl-page-buttons {
+ display: none;
+ }
+ }
+
+ .pl-no-services {
+ img {
+ height: 176px;
+ }
+
+ .pl-no-services-description {
+ max-width: 420px;
+ margin-left: 60px;
+ text-align: left;
+
+ p {
+ margin: 20px 0;
+ }
+
+ button {
+ padding: 16px;
+ margin: 0;
+ max-width: 200px;
+ }
+ }
+ }
+
+ .pl-country-checkbox-wrapper {
+ padding: 15px;
+ }
+
+ .pl-shipping-country-selection-wrapper {
+ max-height: 320px;
+ overflow: auto;
+
+ > * {
+ border-bottom: 1px solid $border-light;
+ }
+ }
+
+ .pl-shipping-country-selected {
+ background-color: $border-light;
+ }
+
+ #pl-countries-alert-wrapper {
+ position: relative;
+ display: none;
+ &.visible {
+ display: flex;
+ }
+ }
+}
+
+// mobile rules
+@media (max-width: 768px) {
+ #pl-page {
+ .pl-main-logo {
+ width: 100%;
+ }
+
+ .pl-register-country-list-wrapper {
+ min-width: 100%;
+ }
+
+ .pl-login-footer {
+ padding: 16px 20px;
+ }
+
+ .pl-list-item .pl-row-orientation {
+ flex-direction: column;
+ }
+
+ .pl-configuration-page {
+ .pl-config-list {
+ width: 100%;
+
+ .pl-config-list-item {
+ padding-right: 15px;
+ padding-left: 20px;
+ }
+ }
+
+ .pl-footer {
+ flex-direction: column;
+
+ > :first-child {
+ padding-bottom: 20px;
+ }
+ }
+ }
+
+ .pl-my-shipping-services-page {
+ .pl-no-services {
+ flex-direction: column;
+ justify-content: flex-start;
+ padding-bottom: 0;
+
+ img {
+ max-height: 40%;
+ }
+
+ .pl-no-services-description {
+ margin: 20px 0 0;
+
+ h1 {
+ text-align: center;
+ }
+
+ button {
+ display: none;
+ }
+
+ p {
+ margin-bottom: 0;
+ }
+ }
+ }
+
+ .pl-page-buttons {
+ display: flex;
+ }
+ }
+ }
+}
+
+// tablet and mobile rules
+@media (max-width: 1280px) {
+ #pl-page {
+ .pl-services-filter-wrapper {
+ padding: 0 10px;
+
+ .pl-filter:not(.pl-filter-selected) {
+ display: none;
+ }
+
+ .pl-filter-selected {
+ flex-direction: row;
+ display: flex;
+ padding: 0;
+
+ .pl-filter-options {
+ flex-wrap: wrap;
+ }
+
+ .pl-filter-option {
+ flex-direction: row;
+
+ &.pl-selected {
+ margin-top: 10px;
+ }
+
+ &::after {
+ content: 'X';
+ margin-left: 5px;
+ margin-top: 1px;
+ }
+ }
+ }
+ }
+
+ .pl-pick-shipping-services-page {
+ #pl-open-filter-button {
+ display: flex;
+ }
+ }
+ }
+}
+
+// tablet rules
+@media (min-width: 769px) and (max-width: 1280px) {
+ #pl-page {
+ }
+}
\ No newline at end of file
diff --git a/src/BusinessLogic/Resources/scss/icons.scss b/src/BusinessLogic/Resources/scss/icons.scss
new file mode 100644
index 00000000..25e42f64
--- /dev/null
+++ b/src/BusinessLogic/Resources/scss/icons.scss
@@ -0,0 +1,18 @@
+/* Material icons */
+
+//noinspection CssNoGenericFontName
+#pl-page .material-icons {
+ font-family: 'Material Icons Outlined';
+ font-weight: normal;
+ font-style: normal;
+ font-size: 24px;
+ line-height: 1;
+ letter-spacing: normal;
+ text-transform: none;
+ display: inline-block;
+ white-space: nowrap;
+ word-wrap: normal;
+ direction: ltr;
+ -webkit-font-feature-settings: 'liga';
+ -webkit-font-smoothing: antialiased;
+}
\ No newline at end of file
diff --git a/src/BusinessLogic/Resources/scss/reset.scss b/src/BusinessLogic/Resources/scss/reset.scss
new file mode 100644
index 00000000..0edf1c40
--- /dev/null
+++ b/src/BusinessLogic/Resources/scss/reset.scss
@@ -0,0 +1,129 @@
+@font-face {
+ font-weight: 700;
+ font-family: pl-proxima-nova;
+ font-style: normal;
+ src: url("https://cdn.packlink.com/apps/giger/fonts/ProximaNova/ProximaNova-BoldWeb.woff") format("woff")
+}
+
+@font-face {
+ font-weight: 600;
+ font-family: pl-proxima-nova;
+ font-style: normal;
+ src: url("https://cdn.packlink.com/apps/giger/fonts/ProximaNova/ProximaNova-SemiboldWeb.woff") format("woff")
+}
+
+@font-face {
+ font-weight: 400;
+ font-family: pl-proxima-nova;
+ font-style: normal;
+ src: url("https://cdn.packlink.com/apps/giger/fonts/ProximaNova/ProximaNova-RegularWeb.woff") format("woff")
+}
+
+// CSS reset
+// We do not reset the html and body, since we need to reset only for the app's root element
+#pl-page {
+ display: flex;
+ flex-direction: column;
+ background-color: $color-white;
+ flex-grow: 1;
+ position: relative;
+
+ template {
+ display: none;
+ }
+
+ * {
+ position: relative;
+ margin: 0;
+ padding: 0;
+ font-family: pl-proxima-nova, sans-serif;
+ font-size: 14px;
+ line-height: 16px;
+ font-weight: 400;
+ font-style: normal;
+ color: $text-color;
+ box-sizing: border-box;
+
+ scrollbar-color: $color-blue $border-color;
+
+ &::-webkit-scrollbar {
+ height: 10px;
+ width: 10px;
+ }
+
+ &::-webkit-scrollbar-thumb {
+ border-radius: 2px;
+ background-color: $color-blue;
+ }
+
+ &::-webkit-scrollbar-track {
+ background-color: $border-color;
+ }
+
+ &::before, &::after {
+ box-sizing: border-box;
+ }
+ }
+
+ main {
+ background-color: $color-white;
+ }
+
+ br {
+ margin-bottom: 10px;
+ }
+
+ h1, h2, h3, h4, h5, h6 {
+ color: $text-heading-color;
+ font-weight: bold;
+
+ br {
+ margin: 0;
+ }
+ }
+
+ h1 {
+ line-height: 22px;
+ font-size: 18px;
+ }
+
+ ul, ol {
+ list-style: none
+ }
+
+ img {
+ height: auto;
+ max-width: 100%
+ }
+
+ strong {
+ font-weight: 700;
+ font-style: normal;
+ }
+
+ table {
+ border-collapse: collapse;
+ border-spacing: 0;
+ }
+
+ a {
+ color: #1a77c2;
+ }
+
+ a, :link, :visited {
+ text-decoration: none;
+ }
+
+ div {
+ display: flex;
+ flex-direction: column;
+ }
+
+ button, .pl-button, input, select, textarea {
+ outline: none;
+
+ &:focus, &:active {
+ outline: none;
+ }
+ }
+}
diff --git a/src/BusinessLogic/Resources/scss/ui-controls.scss b/src/BusinessLogic/Resources/scss/ui-controls.scss
new file mode 100644
index 00000000..4634edb5
--- /dev/null
+++ b/src/BusinessLogic/Resources/scss/ui-controls.scss
@@ -0,0 +1,747 @@
+#pl-page {
+ header {
+ border-bottom: 1px solid $border-color;
+ padding: 20px;
+ display: flex;
+ align-items: center;
+ flex-shrink: 0;
+
+ .pl-header-holder {
+ justify-content: space-between;
+ flex-direction: row;
+ flex-grow: 1;
+ align-items: center;
+ margin-left: 20px;
+
+ .pl-button {
+ padding: 10px 13px;
+ text-transform: none;
+ margin: 0;
+ }
+ }
+
+ &.pl-sub-header {
+ border-color: $border-light;
+ flex-direction: row;
+
+ button {
+ z-index: 1;
+ }
+
+ h1 {
+ margin: 0 0 0 -$icon-button-size;
+ }
+ }
+ }
+
+ > main {
+ display: flex;
+ flex-grow: 1;
+ overflow: auto;
+ }
+
+ button, .pl-button {
+ overflow: visible;
+ display: inline-flex;
+ padding: 16px;
+ vertical-align: middle;
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ cursor: pointer;
+ color: $color-blue;
+ font-style: normal;
+ font-weight: 600;
+ text-align: center;
+ text-decoration: none;
+ text-shadow: none;
+ text-transform: uppercase;
+ border: 1px solid transparent;
+ border-radius: 4px;
+ box-shadow: none;
+ transition: background .4s, border-color .4s, color .4s;
+ align-items: center;
+ justify-content: center;
+ margin: 10px 0 0;
+ height: auto;
+ min-width: 170px;
+
+ &.pl-button-primary {
+ background-color: $color-blue;
+ color: $color-white;
+ }
+
+ &.pl-button-secondary {
+ border: 1px solid $color-blue;
+ background-color: $color-white;
+
+ &:hover {
+ border: 1px solid $color-blue-darker;
+ }
+ }
+
+ &.pl-button-inverted {
+ background-color: $color-white;
+ color: $color-navy-dark;
+ }
+
+ &:hover {
+ color: $color-white;
+ background: $color-blue-darker;
+ box-shadow: none;
+ }
+
+ &:disabled {
+ color: $color-gray;
+ background-color: $color-light;
+ pointer-events: none;
+ }
+
+ &.pl-small {
+ padding: 5px;
+ width: 100px;
+ min-width: 100px;
+ margin: 5px 0;
+ }
+ }
+
+ .pl-icon-button {
+ border: none;
+ background: transparent;
+ padding: 0;
+ width: $icon-button-size;
+ height: $icon-button-size;
+ min-width: $icon-button-size;
+ margin: 0;
+
+ i {
+ font-size: 20px;
+ width: auto;
+ color: $color-blue;
+ }
+
+ &:focus {
+ outline: none;
+ }
+
+ &:hover {
+ cursor: pointer;
+
+ i {
+ color: $color-white;
+ }
+ }
+ }
+
+ section {
+ border-bottom: 1px solid $border-light;
+ padding: 20px 0;
+
+ &:first-child {
+ padding-top: 0;
+ }
+
+ .pl-section-title {
+ font-weight: 600;
+ text-transform: uppercase;
+ display: block;
+ margin-bottom: 8px;
+ }
+
+ .pl-section-subtitle {
+ display: block;
+ }
+
+ .pl-button {
+ padding: 8px 12px
+ }
+ }
+
+ .pl-form-group-wrapper {
+ display: flex;
+ flex-direction: row;
+ margin-top: 15px;
+
+ .pl-form-group + .pl-form-group {
+ margin-top: 0;
+ margin-left: -1px;
+ }
+ }
+
+ .pl-button-group {
+ flex-direction: row;
+
+ button {
+ border-radius: 0;
+
+ &:first-child {
+ border-radius: 4px 0 0 4px;
+ }
+
+ &:last-child {
+ border-radius: 0 4px 4px 0;
+ }
+ }
+ }
+
+ .pl-form-group {
+ position: relative;
+ border: none;
+ width: 100%;
+ align-items: start;
+ flex-shrink: 0;
+
+ &.pl-half-width, .pl-half-width {
+ width: 50%;
+ min-width: 50%;
+ }
+
+ &:not(:first-child) {
+ margin-top: 12px;
+ }
+
+ label {
+ position: absolute;
+ top: 8px;
+ left: 16px;
+ color: $color-gray;
+ text-transform: uppercase;
+ font-size: 12px;
+ }
+
+ input, select {
+ height: $input-height;
+ background: $color-white;
+ border-radius: 0;
+ border: 1px solid $border-color;
+ color: $input-control-color;
+ line-height: 22px;
+ font-size: 14px;
+ width: 100%;
+ margin: 0;
+ box-shadow: unset;
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+ padding: 21px 15px 13px;
+ max-width: none;
+
+ &.compact {
+ padding-top: 13px;
+ }
+
+ &:focus {
+ border: 1px solid $color-blue;
+ outline: none;
+ }
+
+ &::placeholder, &::-webkit-input-placeholder {
+ color: #CBCBCB;
+ }
+ }
+
+ select {
+ -moz-padding-start: 11px;
+ }
+
+ i {
+ position: absolute;
+ right: 10px;
+ top: $input-height/2;
+ margin-top: (-1 * $icon-button-size / 2);
+ color: $border-color;
+ width: $icon-button-size;
+ height: $icon-button-size;
+ }
+
+ select + i {
+ cursor: default;
+ pointer-events: none;
+ }
+
+ .pl-autocomplete-list {
+ background-color: $color-white;
+ border: 1px solid $border-color;
+ width: 100%;
+ margin-top: $input-height;
+ position: absolute;
+ z-index: 1;
+ max-height: 200px;
+ overflow: auto;
+
+ .pl-autocomplete-list-item {
+ width: 100%;
+ padding: 5px;
+ font-size: 15px;
+ cursor: pointer;
+
+ &:hover, &.pl-focus {
+ background-color: $color-little-transparent;
+ color: $color-blue;
+ }
+ }
+ }
+ }
+
+ input[type=checkbox] {
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+ width: $checkbox-size;
+ min-width: $checkbox-size;
+ height: $checkbox-size;
+ border: 1px solid $border-color;
+ position: relative;
+
+ ~ label {
+ margin-left: 10px;
+ }
+
+ &:hover {
+ border-color: $color-blue;
+ }
+
+ &:checked {
+ background-color: $color-blue;
+ border-color: $color-blue;
+ text-align: center;
+
+ &:before {
+ color: $color-white;
+ content: '\2713';
+ margin: 0;
+ font: bold 20px/24px pl-proxima-nova;
+ width: $checkbox-size;
+ min-width: $checkbox-size;
+ height: $checkbox-size;
+ }
+ }
+ }
+
+ .pl-alert-wrapper {
+ position: absolute;
+ width: 100%;
+ padding: 10px;
+ }
+
+ .pl-alert {
+ position: relative;
+ cursor: pointer;
+ padding: .75rem 1.25rem;
+ margin: auto;
+ border: 1px solid transparent;
+ border-radius: .25rem;
+ flex-direction: row;
+ align-items: center;
+
+ &.pl-alert-danger {
+ color: $color-red;
+ background-color: #f8d7da;
+ border-color: #f5c6cb;
+ }
+
+ &.pl-alert-success {
+ color: #155724;
+ background-color: #d4edda;
+ border-color: #c3e6cb;
+ }
+
+ .pl-alert-text {
+ color: inherit;
+ }
+
+ i {
+ color: inherit;
+ margin-left: 20px;
+ }
+ }
+
+ .pl-checkbox {
+ margin-top: 15px;
+ display: flex;
+ flex-direction: row;
+
+ label {
+ cursor: pointer;
+ text-align: left;
+ align-items: center;
+ display: flex;
+ }
+
+ &.pl-error {
+ .pl-error-message {
+ display: none;
+ }
+ }
+ }
+
+ .pl-switch {
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+ align-items: center;
+
+ .pl-switch-button {
+ cursor: pointer;
+
+ .pl-switch-on, .pl-switch-off {
+ font-size: $input-height;
+ }
+
+ .pl-switch-on {
+ color: $color-blue;
+ display: none;
+ }
+
+ &.pl-selected {
+ .pl-switch-on {
+ display: block;
+ }
+
+ .pl-switch-off {
+ display: none;
+ }
+ }
+ }
+ }
+
+ .pl-spinner {
+ position: absolute;
+ z-index: 500;
+ background-color: $color-semi-transparent;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+
+ div {
+ width: 100px;
+ height: 100px;
+ border: 3px solid transparent;
+ border-right-color: $color-blue;
+ border-left-color: $color-blue;
+ border-radius: 50%;
+ animation: pl-rotate 1s linear 0s infinite;
+ }
+ }
+
+ .pl-modal-mask {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ background-color: $color-little-transparent;
+ z-index: 100;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+
+ .pl-modal {
+ background: $color-white;
+ display: flex;
+ max-height: 90%;
+ max-width: 90%;
+ flex-flow: column;
+ align-items: center;
+ position: relative;
+ margin: 0 auto;
+ box-shadow: 0 4px 4px 0 rgba(0, 0, 0, 0.2);
+
+ .pl-modal-close-button {
+ position: absolute;
+ width: 24px;
+ height: 24px;
+ top: 15px;
+ right: 12px;
+ font-size: 3rem;
+ font-weight: 600;
+ color: $color-blue;
+ cursor: pointer;
+ z-index: 1;
+
+ i {
+ color: $color-blue;
+ font-weight: bold;
+ }
+ }
+
+ .pl-modal-title {
+ color: $text-heading-color;
+ font-size: 21px;
+ font-weight: bold;
+ line-height: 22px;
+ text-align: center;
+ padding: 20px 40px 0;
+ }
+
+ .pl-modal-subtitle {
+ color: $text-heading-light-color;
+ font-size: 16px;
+ line-height: 19px;
+ }
+
+ .pl-modal-body {
+ padding: 20px 40px;
+ align-items: flex-start;
+ justify-content: flex-start;
+ width: 100%;
+ overflow: hidden auto;
+
+ &.pl-full-width {
+ padding: 20px 0;
+ }
+ }
+
+ .pl-modal-footer {
+ padding: 0 40px 20px;
+ display: flex;
+ flex-direction: row;
+ justify-content: center;
+ width: 100%;
+ flex-shrink: 0;
+
+ .pl-button {
+ margin-top: 0;
+
+ & + .pl-button {
+ margin-left: 10px;
+ }
+ }
+ }
+ }
+ }
+
+ .pl-error {
+ input, select {
+ border: 1px solid $color-red !important;
+ }
+
+ label, i {
+ color: $color-red;
+ }
+
+ .pl-error-message {
+ margin: 8px 16px 0;
+ color: $color-red;
+ }
+ }
+
+ .pl-shipping-services-table {
+ width: 100%;
+
+ thead tr {
+ th {
+ background-color: $border-light;
+ z-index: 1;
+
+ .pl-table-resize-handle {
+ width: 20px;
+ cursor: col-resize;
+ position: absolute;
+ right: -11px;
+ top: 50%;
+ transform: rotate(90deg);
+ font-size: 20px;
+ transform-origin: top;
+ color: $color-gray;
+ z-index: 2;
+ }
+ }
+ }
+
+ th {
+ font-size: 12px;
+ font-weight: bold;
+ text-transform: uppercase;
+ position: sticky;
+ top: -1px;
+
+ &.pl-text-center {
+ text-align: center;
+ }
+ }
+
+ td {
+ font-weight: 600;
+
+ .pl-service-name {
+ font-weight: 600;
+ margin-bottom: 10px;
+ }
+ }
+
+ tr {
+ border-top: solid 1px $border-light;
+ border-bottom: solid 1px $border-light;
+ }
+
+ th, td {
+ padding: 15px 20px;
+ text-align: left;
+ }
+ }
+
+ .pl-shipping-services-list {
+ display: none;
+ }
+
+ .pl-shipping-services-list-item {
+ border: 1px solid $border-color;
+ border-radius: 4px;
+ background-color: $color-white;
+ box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.1);
+ flex-direction: column;
+ margin-bottom: 10px;
+ padding: 13px;
+
+ .pl-service-header {
+ border-bottom: 1px dashed $border-color;
+ flex-direction: row;
+ padding-bottom: 13px;
+
+ .pl-service-name {
+ flex-grow: 1;
+ padding-left: 15px;
+ align-items: flex-start;
+ justify-content: center;
+
+ #pl-service-name {
+ font-weight: 600;
+ margin-bottom: 8px;
+ }
+ }
+ }
+
+ .pl-wrap-items {
+ flex-direction: row;
+ justify-content: space-between;
+ padding: 13px 0 0;
+
+ .pl-service-property {
+ min-width: 170px;
+ margin-bottom: 13px;
+
+ .pl-property-title {
+ font-weight: 600;
+ text-transform: uppercase;
+ color: $color-gray;
+ font-size: 12px;
+ letter-spacing: 0;
+ line-height: 16px;
+ }
+
+ .pl-property-value {
+ color: $input-control-color;
+ }
+ }
+ }
+
+ .pl-service-buttons {
+ flex-direction: row;
+
+ .pl-button {
+ padding: 5px 15px;
+ min-width: auto;
+ }
+
+ .pl-button:not(.pl-hidden) + .pl-button {
+ margin-left: 10px;
+ }
+ }
+ }
+
+ .pl-button-group {
+ padding-right: 10px;
+
+ button {
+ height: $input-height;
+ min-width: 110px;
+ }
+ }
+
+ pre {
+ white-space: normal;
+ }
+}
+
+// mobile rules
+@media (max-width: 768px) {
+ #pl-page {
+ button, .pl-button {
+ width: 100%;
+ }
+
+ section {
+ .pl-button {
+ width: auto;
+ }
+ }
+
+ header .pl-header-holder {
+ justify-content: flex-end;
+
+ .pl-button {
+ display: none;
+ }
+ }
+
+ .pl-shipping-services-list-item {
+ .pl-wrap-items .pl-service-property {
+ min-width: 50%;
+ }
+
+ .pl-button {
+ width: 100%;
+
+ &.pl-small {
+ padding: 11px;
+ }
+ }
+ }
+
+ .pl-modal-mask {
+ .pl-modal {
+ .pl-modal-title {
+ padding: 20px 20px 0;
+ max-width: 90%;
+ }
+
+ .pl-modal-body {
+ padding: 20px;
+ }
+
+ .pl-modal-footer {
+ padding: 0 20px 20px;
+
+ .pl-button {
+ min-width: 50%;
+ }
+ }
+ }
+ }
+ }
+}
+
+// mobile and tablet rules
+@media (max-width: 1280px) {
+ #pl-page {
+ .pl-shipping-services-table {
+ display: none;
+ }
+
+ .pl-shipping-services-list {
+ display: flex;
+ flex: 0 0 auto;
+ padding: 10px;
+ }
+ }
+}
+
+// tablet rules
+@media (min-width: 769px) and (max-width: 1280px) {
+ #pl-page {
+ }
+}
diff --git a/src/BusinessLogic/Resources/scss/utility.scss b/src/BusinessLogic/Resources/scss/utility.scss
new file mode 100644
index 00000000..ed0645f1
--- /dev/null
+++ b/src/BusinessLogic/Resources/scss/utility.scss
@@ -0,0 +1,248 @@
+#pl-page {
+ .pl-inline {
+ display: inline;
+ }
+
+ .pl-full-width {
+ width: 100%;
+ }
+
+ .pl-half-width {
+ display: inline-flex;
+ width: 50%;
+ }
+
+ .pl-small-page, .pl-medium-page {
+ margin-left: auto;
+ margin-right: auto;
+ }
+
+ .pl-medium-page {
+ max-width: 540px;
+ }
+
+ .pl-small-page {
+ max-width: 410px;
+ }
+
+ .pl-small-width {
+ max-width: 410px;
+ }
+
+ .pl-hidden {
+ display: none !important;
+ }
+
+ .pl-pull-left {
+ float: left;
+ }
+
+ .pl-text-center {
+ text-align: center;
+ }
+
+ .pl-text-left {
+ text-align: left;
+ }
+
+ .pl-separate-vertically {
+ margin-top: 26px;
+ margin-bottom: 26px;
+ }
+
+ .pl-separate-top-small {
+ margin-top: 2px;
+ }
+
+ .pl-separate-horizontally {
+ margin-left: 26px;
+ margin-right: 26px;
+ }
+
+ .pl-top-separate {
+ margin-top: 20px;
+ }
+
+ .pl-bottom-separate {
+ margin-bottom: 36px;
+ }
+
+ .pl-left-separate {
+ margin-left: 20px;
+ }
+
+ .pl-right-separate {
+ margin-right: 20px;
+ }
+
+ .pl-page-content {
+ overflow: hidden auto;
+ margin-bottom: 10px;
+ }
+
+ .pl-page-padding {
+ padding: 20px;
+ }
+
+ .pl-flex-expand {
+ flex-grow: 1;
+ }
+
+ .pl-no-shrink {
+ flex-shrink: 0;
+ }
+
+ .pl-row-orientation {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ }
+
+ .pl-flex-left {
+ align-items: flex-start;
+ justify-content: flex-start;
+ }
+
+ .pl-justify-f-start {
+ justify-content: flex-start;
+ }
+
+ .pl-separate-content {
+ justify-content: space-between;
+ }
+
+ .pl-no-margin {
+ margin: 0 !important;
+ }
+
+ .pl-no-border {
+ border-color: transparent !important;
+ }
+
+ .pl-center {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ text-align: center;
+ }
+
+ #pl-origin-collection svg {
+ width: 24px;
+ height: 23px;
+ }
+
+ #pl-origin-dropoff svg {
+ width: 25px;
+ height: 23px;
+ }
+
+ #pl-destination-pickup svg {
+ width: 24px;
+ height: 22px;
+ }
+
+ #pl-destination-delivery svg {
+ width: 27px;
+ height: 22px;
+ }
+
+ #pl-navigate-warehouse svg {
+ width: 22px;
+ height: 22px;
+ }
+
+ #pl-navigate-parcel svg {
+ width: 23px;
+ height: 22px;
+ }
+
+ .pl-flex-start {
+ align-items: flex-start;
+ }
+
+ .pl-wrap-items {
+ flex-wrap: wrap;
+ }
+
+ .pl-header-text-wrapper {
+ line-height: 22px;
+ font-size: 22px;
+ }
+
+ .pl-small {
+ padding: 5px;
+ width: 100px;
+ min-width: 100px;
+ margin: 0;
+ }
+
+ .pl-no-wrap {
+ white-space: nowrap;
+ width: auto;
+ }
+
+ .pl-page-buttons {
+ display: block;
+ //text-align: center;
+ padding: 0 20px 20px;
+ }
+
+ .pl-error-text {
+ color: $color-red;
+ }
+
+ .pl-icon-text {
+ color: $color-blue;
+ }
+
+ .pl-clickable {
+ cursor: pointer;
+ }
+
+ .pl-all-caps {
+ text-transform: uppercase;
+ }
+
+ .pl-block {
+ display: block;
+ }
+
+ .pl-split-content {
+ justify-content: space-between;
+ flex-direction: row;
+ }
+
+ &.pl-disable-selection {
+ -moz-user-select: none; /* Firefox */
+ -ms-user-select: none; /* Internet Explorer */
+ -khtml-user-select: none; /* KHTML browsers (e.g. Konqueror) */
+ -webkit-user-select: none; /* Chrome, Safari, and Opera */
+ -webkit-touch-callout: none; /* Disable Android and iOS callouts*/
+ }
+}
+
+// mobile rules
+@media (max-width: 768px) {
+ #pl-page {
+ .pl-desktop-only {
+ display: none !important;
+ }
+
+ .pl-page-content {
+ margin-bottom: 100px;
+ }
+
+ .pl-page-buttons {
+ position: absolute;
+ bottom: 0;
+ width: 100%;
+ padding: 20px;
+ background-color: $color-white;
+ }
+
+ .pl-medium-page, .pl-small-page {
+ width: 100%;
+ max-width: 100%;
+ }
+ }
+}
diff --git a/src/BusinessLogic/Resources/scss/variables.scss b/src/BusinessLogic/Resources/scss/variables.scss
new file mode 100644
index 00000000..eb5a492a
--- /dev/null
+++ b/src/BusinessLogic/Resources/scss/variables.scss
@@ -0,0 +1,23 @@
+$text-color: #3a3d46;
+$input-control-color: #5d5d5d;
+$text-heading-color: #5E6972;
+$text-heading-light-color: #737373;
+
+$border-color: #d7d7d7;
+$border-light: #F5F5F5;
+
+$color-white: #ffffff;
+$color-blue: #2095f2;
+$color-blue-darker: rgba(32, 149, 242, .7);
+$color-navy-dark: #2E4265;
+$color-gray: #9B9B9B;
+$color-light-gray: #717C87;
+$color-light: #E1E1E1;
+$color-red: #e63f3f;
+
+$color-little-transparent: rgba(216, 216, 216, 0.8);
+$color-semi-transparent: rgba(255, 255, 255, 0.5);
+
+$icon-button-size: 24px;
+$input-height: 56px;
+$checkbox-size: 20px;
diff --git a/src/BusinessLogic/Resources/templates/configuration.html b/src/BusinessLogic/Resources/templates/configuration.html
new file mode 100644
index 00000000..0c7ef492
--- /dev/null
+++ b/src/BusinessLogic/Resources/templates/configuration.html
@@ -0,0 +1,59 @@
+
diff --git a/src/BusinessLogic/Resources/templates/countries-selection-modal.html b/src/BusinessLogic/Resources/templates/countries-selection-modal.html
new file mode 100644
index 00000000..a7c267e4
--- /dev/null
+++ b/src/BusinessLogic/Resources/templates/countries-selection-modal.html
@@ -0,0 +1,21 @@
+
+
+
\ No newline at end of file
diff --git a/src/BusinessLogic/Resources/templates/default-parcel.html b/src/BusinessLogic/Resources/templates/default-parcel.html
new file mode 100644
index 00000000..f4ff6852
--- /dev/null
+++ b/src/BusinessLogic/Resources/templates/default-parcel.html
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/BusinessLogic/Resources/templates/default-warehouse.html b/src/BusinessLogic/Resources/templates/default-warehouse.html
new file mode 100644
index 00000000..4899c44d
--- /dev/null
+++ b/src/BusinessLogic/Resources/templates/default-warehouse.html
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/BusinessLogic/Resources/templates/disable-carriers-modal.html b/src/BusinessLogic/Resources/templates/disable-carriers-modal.html
new file mode 100644
index 00000000..d8420625
--- /dev/null
+++ b/src/BusinessLogic/Resources/templates/disable-carriers-modal.html
@@ -0,0 +1,5 @@
+
+
+
{$shippingServices.disableCarriersTitle}
+
{$shippingServices.disableCarriersDescription}
+
diff --git a/src/BusinessLogic/Resources/templates/edit-shipping-service.html b/src/BusinessLogic/Resources/templates/edit-shipping-service.html
new file mode 100644
index 00000000..ef3e0a54
--- /dev/null
+++ b/src/BusinessLogic/Resources/templates/edit-shipping-service.html
@@ -0,0 +1,95 @@
+
+
+
+
{$shippingServices.configureService}
+
+
+
+
+
+
+
+
diff --git a/src/BusinessLogic/Resources/templates/login.html b/src/BusinessLogic/Resources/templates/login.html
new file mode 100644
index 00000000..77866b4b
--- /dev/null
+++ b/src/BusinessLogic/Resources/templates/login.html
@@ -0,0 +1,36 @@
+
+
+
+
+ {$login.welcome}
+
+
+ {$login.connectYourService}
+
+
+
+
+
+
diff --git a/src/BusinessLogic/Resources/templates/my-shipping-services.html b/src/BusinessLogic/Resources/templates/my-shipping-services.html
new file mode 100644
index 00000000..8be90763
--- /dev/null
+++ b/src/BusinessLogic/Resources/templates/my-shipping-services.html
@@ -0,0 +1,25 @@
+
+
+ {$shippingServices.myServices}
+
+
+
+
+
+
{$shippingServices.noServicesTitle}
+
{$shippingServices.noServicesDescription}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/BusinessLogic/Resources/templates/onboarding-overview.html b/src/BusinessLogic/Resources/templates/onboarding-overview.html
new file mode 100644
index 00000000..01c226fe
--- /dev/null
+++ b/src/BusinessLogic/Resources/templates/onboarding-overview.html
@@ -0,0 +1,41 @@
+
+
+
+
+ {$onboardingOverview.header}
+
+
+
+
+ check
+
+
+
{$onboardingOverview.parcelDetails}
+
+
+
+
+
+
+ check
+
+
+
{$onboardingOverview.senderAddress}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/BusinessLogic/Resources/templates/onboarding-welcome.html b/src/BusinessLogic/Resources/templates/onboarding-welcome.html
new file mode 100644
index 00000000..cd18f66c
--- /dev/null
+++ b/src/BusinessLogic/Resources/templates/onboarding-welcome.html
@@ -0,0 +1,26 @@
+
+
+
+ {$onboardingWelcome.header}
+
+
+ {$onboardingWelcome.steps}
+
+
+
+
+ 1. {$onboardingWelcome.stepOne}
+
+
+ 2. {$onboardingWelcome.stepTwo}
+
+
+
+
+
+
+
+
diff --git a/src/BusinessLogic/Resources/templates/order-status-mapping.html b/src/BusinessLogic/Resources/templates/order-status-mapping.html
new file mode 100644
index 00000000..4f46b3e5
--- /dev/null
+++ b/src/BusinessLogic/Resources/templates/order-status-mapping.html
@@ -0,0 +1,42 @@
+
+
+
+
{$orderStatusMapping.title}
+
+
+
+
+
+
+
+
+
+
+
+
+ chevron_right
+
+
+
+ expand_more
+
+
+
\ No newline at end of file
diff --git a/src/BusinessLogic/Resources/templates/pick-shipping-services.html b/src/BusinessLogic/Resources/templates/pick-shipping-services.html
new file mode 100644
index 00000000..98b4ecbc
--- /dev/null
+++ b/src/BusinessLogic/Resources/templates/pick-shipping-services.html
@@ -0,0 +1,76 @@
+
+
+
+
+
{$shippingServices.pickShippingService}
+
+
+
+
+
+
+
+ {$shippingServices.type}
+
+
+
+ {$shippingServices.national}
+
+
+ {$shippingServices.international}
+
+
+
+
+
+ {$shippingServices.deliveryType}
+
+
+
+ {$shippingServices.economic}
+
+
+ {$shippingServices.express}
+
+
+
+
+
+ {$shippingServices.parcelOrigin}
+
+
+
+ {$shippingServices.collection}
+
+
+ {$shippingServices.dropoff}
+
+
+
+
+
+ {$shippingServices.parcelDestination}
+
+
+
+ {$shippingServices.pickup}
+
+
+ {$shippingServices.delivery}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/BusinessLogic/Resources/templates/pricing-policies-list.html b/src/BusinessLogic/Resources/templates/pricing-policies-list.html
new file mode 100644
index 00000000..ec8cf30a
--- /dev/null
+++ b/src/BusinessLogic/Resources/templates/pricing-policies-list.html
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/BusinessLogic/Resources/templates/pricing-policy-modal.html b/src/BusinessLogic/Resources/templates/pricing-policy-modal.html
new file mode 100644
index 00000000..afb17037
--- /dev/null
+++ b/src/BusinessLogic/Resources/templates/pricing-policy-modal.html
@@ -0,0 +1,101 @@
+
+
+
\ No newline at end of file
diff --git a/src/BusinessLogic/Resources/templates/register-modal.html b/src/BusinessLogic/Resources/templates/register-modal.html
new file mode 100644
index 00000000..e0cdf2ac
--- /dev/null
+++ b/src/BusinessLogic/Resources/templates/register-modal.html
@@ -0,0 +1,13 @@
+
+
+ search
+
+
+
+
+
+ country_name
+
+
+
diff --git a/src/BusinessLogic/Resources/templates/register.html b/src/BusinessLogic/Resources/templates/register.html
new file mode 100644
index 00000000..d8b78621
--- /dev/null
+++ b/src/BusinessLogic/Resources/templates/register.html
@@ -0,0 +1,92 @@
+
+
+
+
+ {$register.startEnjoying}
+
+
+ {$register.registerAccount}
+
+
+
+
+
+
diff --git a/src/BusinessLogic/Resources/templates/shipping-services-header.html b/src/BusinessLogic/Resources/templates/shipping-services-header.html
new file mode 100644
index 00000000..e9b67737
--- /dev/null
+++ b/src/BusinessLogic/Resources/templates/shipping-services-header.html
@@ -0,0 +1,4 @@
+
+
+ {$configuration.menu} settings
+
\ No newline at end of file
diff --git a/src/BusinessLogic/Resources/templates/shipping-services-list.html b/src/BusinessLogic/Resources/templates/shipping-services-list.html
new file mode 100644
index 00000000..45246ebf
--- /dev/null
+++ b/src/BusinessLogic/Resources/templates/shipping-services-list.html
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{$shippingServices.transitTime}
+
+
+
+
{$shippingServices.type}
+
+
+
+
{$shippingServices.parcelOrigin}
+
+ {$shippingServices.collection}
+
+
+ {$shippingServices.dropoff}
+
+
+
+
{$shippingServices.parcelDestination}
+
+ {$shippingServices.pickup}
+
+
+ {$shippingServices.delivery}
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/BusinessLogic/Resources/templates/shipping-services-table.html b/src/BusinessLogic/Resources/templates/shipping-services-table.html
new file mode 100644
index 00000000..2aea3fac
--- /dev/null
+++ b/src/BusinessLogic/Resources/templates/shipping-services-table.html
@@ -0,0 +1,108 @@
+
+
+
+
+ {$shippingServices.carrier}
+
+
+ {$shippingServices.serviceTitle}
+
+
+ {$shippingServices.transitTime}
+
+
+ {$shippingServices.type}
+
+
+ {$shippingServices.origin}
+
+
+ {$shippingServices.destination}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {$shippingServices.collection}
+
+
+
+ {$shippingServices.dropoff}
+
+
+
+
+
+ {$shippingServices.pickup}
+
+
+
+ {$shippingServices.delivery}
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/BusinessLogic/Resources/templates/system-info-modal.html b/src/BusinessLogic/Resources/templates/system-info-modal.html
new file mode 100644
index 00000000..d098f03d
--- /dev/null
+++ b/src/BusinessLogic/Resources/templates/system-info-modal.html
@@ -0,0 +1,13 @@
+