diff --git a/.env b/.env index 7a0f6d6..c9be662 100644 --- a/.env +++ b/.env @@ -68,6 +68,11 @@ OAUTH_TOKEN_URL= OAUTH_USERINFO_URL= OAUTH_SCOPE= +# Typically your IP address, this envvar is required for +# some connectors that need to be provided with your host's +# outgoing IP address. +OUTGOING_IP= + LIMITED_FEATURES=false LIMIT_MAX_WATCHLIST=0 LIMIT_MAX_WATCHLIST_DOMAINS=0 diff --git a/.gitignore b/.gitignore index 0f20979..f1b0b01 100644 --- a/.gitignore +++ b/.gitignore @@ -43,6 +43,11 @@ yarn-error.log phpstan.neon ###< phpstan/phpstan ### +# Eclipse +.project +.buildpath +/.settings/ + public/images/*.png public/content/*.md public/favicon.ico diff --git a/README.md b/README.md index 63c0214..58ea540 100644 --- a/README.md +++ b/README.md @@ -53,8 +53,8 @@ The table below lists the supported API connector providers: |:---------:|---------------------------------------------------------------|:---------:| | OVH | https://api.ovh.com | **Yes** | | GANDI | https://api.gandi.net/docs/domains/ | **Yes** | +| NAMECHEAP | https://www.namecheap.com/support/api/methods/domains/create/ | **Yes** | | AUTODNS | https://cloud.autodns.com/ | **Yes** | -| NAMECHEAP | https://www.namecheap.com/support/api/methods/domains/create/ | | If a domain has expired and a connector is linked to the Watchlist, then Domain Watchdog will try to order it via the connector provider's API. diff --git a/assets/components/tracking/connector/ConnectorForm.tsx b/assets/components/tracking/connector/ConnectorForm.tsx index 37db087..af697e6 100644 --- a/assets/components/tracking/connector/ConnectorForm.tsx +++ b/assets/components/tracking/connector/ConnectorForm.tsx @@ -1,4 +1,4 @@ -import {Alert, Button, Checkbox, Form, FormInstance, Input, Popconfirm, Select, Space, Typography } from "antd"; +import {Alert, Button, Checkbox, Form, FormInstance, Input, Popconfirm, Select, Space, Typography} from "antd"; import React, {useState} from "react"; import {Connector, ConnectorProvider} from "../../../utils/api/connectors"; import {t} from "ttag"; @@ -134,9 +134,10 @@ export function ConnectorForm({form, onCreate}: { form: FormInstance, onCreate: } { provider === ConnectorProvider.AUTODNS && <> - - -
+ +
{t`The Contact ID for ownership of registered Domains. `}{t`You got from this page`}} - rules={[{required: true, message: t`Required`}]} + type='secondary'>{t`The Contact ID for ownership of registered Domains. `}{t`You got from this page`}} + rules={[{required: true, message: t`Required`}]} required={true}> @@ -169,20 +171,36 @@ export function ConnectorForm({form, onCreate}: { form: FormInstance, onCreate: type='secondary'>{t`If you not sure, use the default value 4`}} required={false}> - + {t`Owner confirms his consent of domain order jobs`} - + + + } + { + provider === ConnectorProvider.NAMECHEAP && <> + + + + + + } diff --git a/assets/utils/api/connectors.ts b/assets/utils/api/connectors.ts index 795738d..80bc73b 100644 --- a/assets/utils/api/connectors.ts +++ b/assets/utils/api/connectors.ts @@ -4,6 +4,7 @@ export enum ConnectorProvider { OVH = 'ovh', GANDI = 'gandi', AUTODNS = 'autodns', + NAMECHEAP = 'namecheap' } export type Connector = { diff --git a/assets/utils/providers/index.tsx b/assets/utils/providers/index.tsx index 6ad45d2..7a04219 100644 --- a/assets/utils/providers/index.tsx +++ b/assets/utils/providers/index.tsx @@ -15,7 +15,14 @@ export const helpGetTokenLink = (provider?: string) => { return {t`Retrieve a Personal Access Token from your customer account on the Provider's website`} - + case ConnectorProvider.NAMECHEAP: + return + {t`Retreive an API key and whitelist this instance's IP address on Namecheap's website`} + + case ConnectorProvider.AUTODNS: + return + {t`Because of some limitations in API of AutoDNS, we suggest to create an dedicated user for API with limited rights.`} + default: return <> diff --git a/composer.json b/composer.json index 21e9bc1..cc70b68 100644 --- a/composer.json +++ b/composer.json @@ -87,7 +87,8 @@ "symfony/zulip-notifier": "7.1.*", "symfonycasts/verify-email-bundle": "*", "twig/extra-bundle": "^2.12|^3.0", - "twig/twig": "^2.12|^3.0" + "twig/twig": "^2.12|^3.0", + "ext-simplexml": "*" }, "config": { "allow-plugins": { diff --git a/config/services.yaml b/config/services.yaml index 4ebaaab..62e314b 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -17,6 +17,8 @@ parameters: limit_max_watchlist_domains: '%env(int:LIMIT_MAX_WATCHLIST_DOMAINS)%' limit_max_watchlist_webhooks: '%env(int:LIMIT_MAX_WATCHLIST_WEBHOOKS)%' + outgoing_ip: '%env(string:OUTGOING_IP)%' + services: # default configuration for services in *this* file _defaults: @@ -25,6 +27,7 @@ services: bind: $mailerSenderEmail: '%mailer_sender_email%' $mailerSenderName: '%mailer_sender_name%' + $outgoingIp: '%outgoing_ip%' # makes classes in src/ available to be used as services # this creates a service per class whose id is the fully-qualified class name diff --git a/package.json b/package.json index 7af1b8c..26c0d49 100644 --- a/package.json +++ b/package.json @@ -64,6 +64,6 @@ "watch": "encore dev --watch", "build": "encore production --progress", "ttag:po2json": "cd translations; for i in $(find . -name \"*.po\"); do ttag po2json $i > ../public/locales/$i.json; done; cd ..", - "ttag:extract": "ttag extract $(find assets -name '*.ts' -or -name '*.tsx') -o translations/translations.pot" + "ttag:extract": "ttag extract $(find assets -name '*.ts' -or -name '*.tsx' | sort) -o translations/translations.pot" } } diff --git a/src/Config/ConnectorProvider.php b/src/Config/ConnectorProvider.php index 752a2ea..6051556 100644 --- a/src/Config/ConnectorProvider.php +++ b/src/Config/ConnectorProvider.php @@ -2,15 +2,17 @@ namespace App\Config; -use App\Config\Provider\AutodnsProvider; -use App\Config\Provider\GandiProvider; -use App\Config\Provider\OvhProvider; +use App\Service\Connector\AutodnsProvider; +use App\Service\Connector\GandiProvider; +use App\Service\Connector\NamecheapProvider; +use App\Service\Connector\OvhProvider; enum ConnectorProvider: string { case OVH = 'ovh'; case GANDI = 'gandi'; case AUTODNS = 'autodns'; + case NAMECHEAP = 'namecheap'; public function getConnectorProvider(): string { @@ -18,6 +20,7 @@ enum ConnectorProvider: string ConnectorProvider::OVH => OvhProvider::class, ConnectorProvider::GANDI => GandiProvider::class, ConnectorProvider::AUTODNS => AutodnsProvider::class, + ConnectorProvider::NAMECHEAP => NamecheapProvider::class, }; } } diff --git a/src/Controller/ConnectorController.php b/src/Controller/ConnectorController.php index df91dd5..f739147 100644 --- a/src/Controller/ConnectorController.php +++ b/src/Controller/ConnectorController.php @@ -2,13 +2,15 @@ namespace App\Controller; -use App\Config\Provider\AbstractProvider; use App\Entity\Connector; use App\Entity\User; +use App\Service\Connector\AbstractProvider; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\EntityManagerInterface; use Psr\Log\LoggerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; +use Symfony\Component\DependencyInjection\Attribute\Autowire; +use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; use Symfony\Component\Routing\Attribute\Route; @@ -20,7 +22,9 @@ class ConnectorController extends AbstractController public function __construct( private readonly SerializerInterface $serializer, private readonly EntityManagerInterface $em, - private readonly LoggerInterface $logger + private readonly LoggerInterface $logger, + #[Autowire(service: 'service_container')] + private ContainerInterface $locator ) { } @@ -71,11 +75,11 @@ class ConnectorController extends AbstractController throw new BadRequestHttpException('Provider not found'); } - /** @var AbstractProvider $connectorProviderClass */ - $connectorProviderClass = $provider->getConnectorProvider(); - - $authData = $connectorProviderClass::verifyAuthData($connector->getAuthData(), $client); + /** @var AbstractProvider $providerClient */ + $providerClient = $this->locator->get($provider->getConnectorProvider()); + $authData = $providerClient->verifyAuthData($connector->getAuthData()); $connector->setAuthData($authData); + $providerClient->authenticate($authData); $this->logger->info('User {username} authentication data with the {provider} provider has been validated.', [ 'username' => $user->getUserIdentifier(), diff --git a/src/Controller/WatchListController.php b/src/Controller/WatchListController.php index 6ab1e6b..dcc30e1 100644 --- a/src/Controller/WatchListController.php +++ b/src/Controller/WatchListController.php @@ -2,7 +2,6 @@ namespace App\Controller; -use App\Config\Provider\AbstractProvider; use App\Entity\Connector; use App\Entity\Domain; use App\Entity\DomainEntity; @@ -12,6 +11,7 @@ use App\Entity\WatchList; use App\Notifier\TestChatNotification; use App\Repository\WatchListRepository; use App\Service\ChatNotificationService; +use App\Service\Connector\AbstractProvider; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\Exception\ORMException; @@ -27,21 +27,20 @@ use Eluceo\iCal\Domain\ValueObject\Timestamp; use Eluceo\iCal\Presentation\Component\Property; use Eluceo\iCal\Presentation\Component\Property\Value\TextValue; use Eluceo\iCal\Presentation\Factory\CalendarFactory; -use Psr\Cache\CacheItemPoolInterface; use Psr\Log\LoggerInterface; use Sabre\VObject\EofException; use Sabre\VObject\InvalidDataException; use Sabre\VObject\ParseException; use Sabre\VObject\Reader; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; +use Symfony\Component\DependencyInjection\Attribute\Autowire; +use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; -use Symfony\Component\HttpKernel\KernelInterface; use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Serializer\SerializerInterface; -use Symfony\Contracts\HttpClient\HttpClientInterface; class WatchListController extends AbstractController { @@ -50,10 +49,9 @@ class WatchListController extends AbstractController private readonly EntityManagerInterface $em, private readonly WatchListRepository $watchListRepository, private readonly LoggerInterface $logger, - private readonly HttpClientInterface $httpClient, - private readonly CacheItemPoolInterface $cacheItemPool, - private readonly KernelInterface $kernel, - private readonly ChatNotificationService $chatNotificationService + private readonly ChatNotificationService $chatNotificationService, + #[Autowire(service: 'service_container')] + private ContainerInterface $locator ) { } @@ -182,9 +180,9 @@ class WatchListController extends AbstractController $connectorProviderClass = $connector->getProvider()->getConnectorProvider(); /** @var AbstractProvider $connectorProvider */ - $connectorProvider = new $connectorProviderClass($connector->getAuthData(), $this->httpClient, $this->cacheItemPool, $this->kernel); + $connectorProvider = $this->locator->get($connectorProviderClass); - $connectorProvider::verifyAuthData($connector->getAuthData(), $this->httpClient); // We want to check if the tokens are OK + $connectorProvider->authenticate($connector->getAuthData()); $supported = $connectorProvider->isSupported(...$watchList->getDomains()->toArray()); if (!$supported) { diff --git a/src/MessageHandler/OrderDomainHandler.php b/src/MessageHandler/OrderDomainHandler.php index 7dc028d..dc3dc6b 100644 --- a/src/MessageHandler/OrderDomainHandler.php +++ b/src/MessageHandler/OrderDomainHandler.php @@ -2,7 +2,6 @@ namespace App\MessageHandler; -use App\Config\Provider\AbstractProvider; use App\Entity\Domain; use App\Entity\WatchList; use App\Message\OrderDomain; @@ -11,16 +10,17 @@ use App\Notifier\DomainOrderNotification; use App\Repository\DomainRepository; use App\Repository\WatchListRepository; use App\Service\ChatNotificationService; +use App\Service\Connector\AbstractProvider; use App\Service\StatService; -use Psr\Cache\CacheItemPoolInterface; use Psr\Log\LoggerInterface; +use Symfony\Component\DependencyInjection\Attribute\Autowire; +use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpKernel\KernelInterface; use Symfony\Component\Mailer\Exception\TransportExceptionInterface; use Symfony\Component\Mailer\MailerInterface; use Symfony\Component\Messenger\Attribute\AsMessageHandler; use Symfony\Component\Mime\Address; use Symfony\Component\Notifier\Recipient\Recipient; -use Symfony\Contracts\HttpClient\HttpClientInterface; #[AsMessageHandler] final readonly class OrderDomainHandler @@ -33,12 +33,12 @@ final readonly class OrderDomainHandler private WatchListRepository $watchListRepository, private DomainRepository $domainRepository, private KernelInterface $kernel, - private HttpClientInterface $client, - private CacheItemPoolInterface $cacheItemPool, private MailerInterface $mailer, private LoggerInterface $logger, private StatService $statService, - private ChatNotificationService $chatNotificationService + private ChatNotificationService $chatNotificationService, + #[Autowire(service: 'service_container')] + private ContainerInterface $locator ) { $this->sender = new Address($mailerSenderEmail, $mailerSenderName); } @@ -72,7 +72,8 @@ final readonly class OrderDomainHandler $connectorProviderClass = $provider->getConnectorProvider(); /** @var AbstractProvider $connectorProvider */ - $connectorProvider = new $connectorProviderClass($connector->getAuthData(), $this->client, $this->cacheItemPool, $this->kernel); + $connectorProvider = $this->locator->get($connectorProviderClass); + $connectorProvider->authenticate($connector->getAuthData()); $connectorProvider->orderDomain($domain, $this->kernel->isDebug()); $this->statService->incrementStat('stats.domain.purchased'); diff --git a/src/Config/Provider/AbstractProvider.php b/src/Service/Connector/AbstractProvider.php similarity index 62% rename from src/Config/Provider/AbstractProvider.php rename to src/Service/Connector/AbstractProvider.php index 905a49f..3e83994 100644 --- a/src/Config/Provider/AbstractProvider.php +++ b/src/Service/Connector/AbstractProvider.php @@ -1,24 +1,38 @@ authenticate($authData); + * $provider->orderDomain($domain, $dryRun); + */ abstract class AbstractProvider { + protected array $authData; + public function __construct( - protected array $authData, - protected HttpClientInterface $client, - protected CacheItemPoolInterface $cacheItemPool, - protected KernelInterface $kernel + protected CacheItemPoolInterface $cacheItemPool ) { } - abstract public static function verifyAuthData(array $authData, HttpClientInterface $client): array; + /** + * @param array $authData raw authentication data as supplied by the user + * + * @return array a cleaned up version of the authentication data + */ + abstract public function verifyAuthData(array $authData): array; + + /** + * @throws \Exception when the registrar denies the authentication + */ + abstract public function assertAuthentication(): void; // TODO use dedicated exception type abstract public function orderDomain(Domain $domain, bool $dryRun): void; @@ -55,6 +69,15 @@ abstract class AbstractProvider return true; } + /** + * @throws \Exception + */ + public function authenticate(array $authData): void + { + $this->authData = $this->verifyAuthData($authData); + $this->assertAuthentication(); + } + abstract protected function getCachedTldList(): CacheItemInterface; abstract protected function getSupportedTldList(): array; diff --git a/src/Config/Provider/AutodnsProvider.php b/src/Service/Connector/AutodnsProvider.php similarity index 70% rename from src/Config/Provider/AutodnsProvider.php rename to src/Service/Connector/AutodnsProvider.php index 98783df..d97f94f 100644 --- a/src/Config/Provider/AutodnsProvider.php +++ b/src/Service/Connector/AutodnsProvider.php @@ -1,9 +1,11 @@ authData, $this->client); - - if($dryRun) { + if ($dryRun) { return; } @@ -47,49 +52,55 @@ class AutodnsProvider extends AbstractProvider 'POST', '/v1/domain', (new HttpOptions()) - ->setAuthBasic($authData['username'], $authData['password']) + ->setAuthBasic($this->authData['username'], $this->authData['password']) ->setHeader('Accept', 'application/json') - ->setHeader('X-Domainrobot-Context', $authData['context']) - + ->setHeader('X-Domainrobot-Context', $this->authData['context']) ->setBaseUri(self::BASE_URL) ->setJson([ 'name' => $ldhName, 'ownerc' => [ - 'id' => $authData['contactid'], + 'id' => $this->authData['contactid'], ], 'adminc' => [ - 'id' => $authData['contactid'], + 'id' => $this->authData['contactid'], ], 'techc' => [ - 'id' => $authData['contactid'], + 'id' => $this->authData['contactid'], ], - 'confirmOrder' => $authData['ownerConfirm'], + 'confirmOrder' => $this->authData['ownerConfirm'], 'nameServers' => [ [ - 'name' => 'a.ns14.net' + 'name' => 'a.ns14.net', ], [ - 'name' => 'b.ns14.net' + 'name' => 'b.ns14.net', ], [ - 'name' => 'c.ns14.net' + 'name' => 'c.ns14.net', ], [ - 'name' => 'd.ns14.net' + 'name' => 'd.ns14.net', ], - ] + ], ]) ->toArray() )->toArray(); } + /** + * @throws RedirectionExceptionInterface + * @throws DecodingExceptionInterface + * @throws ClientExceptionInterface + * @throws TransportExceptionInterface + * @throws ServerExceptionInterface + */ public function registerZone(Domain $domain, bool $dryRun = false): void { $authData = $this->authData; $ldhName = $domain->getLdhName(); - if($dryRun) { + if ($dryRun) { return; } @@ -100,7 +111,6 @@ class AutodnsProvider extends AbstractProvider ->setAuthBasic($authData['username'], $authData['password']) ->setHeader('Accept', 'application/json') ->setHeader('X-Domainrobot-Context', $authData['context']) - ->setBaseUri(self::BASE_URL) ->setJson([ 'filters' => [ @@ -108,7 +118,7 @@ class AutodnsProvider extends AbstractProvider 'key' => 'name', 'value' => $ldhName, 'operator' => 'EQUAL', - ] + ], ], ]) ->toArray() @@ -126,48 +136,42 @@ class AutodnsProvider extends AbstractProvider ->setAuthBasic($authData['username'], $authData['password']) ->setHeader('Accept', 'application/json') ->setHeader('X-Domainrobot-Context', $authData['context']) - ->setBaseUri(self::BASE_URL) ->setJson([ 'origin' => $ldhName, 'main' => [ - 'address' => $authData['dns_ip'] + 'address' => $authData['dns_ip'], ], 'soa' => [ 'refresh' => 3600, 'retry' => 7200, 'expire' => 604800, - 'ttl' => 600 + 'ttl' => 600, ], 'action' => 'COMPLETE', 'wwwInclude' => true, 'nameServers' => [ [ - 'name' => 'a.ns14.net' + 'name' => 'a.ns14.net', ], [ - 'name' => 'b.ns14.net' + 'name' => 'b.ns14.net', ], [ - 'name' => 'c.ns14.net' + 'name' => 'c.ns14.net', ], [ - 'name' => 'd.ns14.net' + 'name' => 'd.ns14.net', ], - ] - + ], ]) ->toArray() )->toArray(); } } - - /** - * @throws TransportExceptionInterface - */ - public static function verifyAuthData(array $authData, HttpClientInterface $client): array - { + public function verifyAuthData(array $authData): array + { $username = $authData['username']; $password = $authData['password']; @@ -187,33 +191,22 @@ class AutodnsProvider extends AbstractProvider if ( true !== $acceptConditions - || empty($authData['ownerConfirm']) + || true !== $authData['ownerConfirm'] || true !== $ownerLegalAge || true !== $waiveRetractationPeriod ) { throw new HttpException(451, 'The user has not given explicit consent'); } - try { - $response = $client->request( - 'GET', - '/v1/hello', - (new HttpOptions()) - ->setAuthBasic($authData['username'], $authData['password']) - ->setHeader('Accept', 'application/json') - ->setHeader('X-Domainrobot-Context', $authData['context']) - ->setBaseUri(self::BASE_URL) - ->toArray() - ); - } catch (\Exception $exp) { - throw new BadRequestHttpException('Invalid Login'); - } - - if (Response::HTTP_OK !== $response->getStatusCode()) { - throw new BadRequestHttpException('The status of these credentials is not valid'); - } - - return $authData; + return [ + 'username' => $authData['username'], + 'password' => $authData['password'], + 'acceptConditions' => $authData['acceptConditions'], + 'ownerLegalAge' => $authData['ownerLegalAge'], + 'ownerConfirm' => $authData['ownerConfirm'], + 'waiveRetractationPeriod' => $authData['waiveRetractationPeriod'], + 'context' => $authData['context'], + ]; } public function isSupported(Domain ...$domainList): bool @@ -221,14 +214,41 @@ class AutodnsProvider extends AbstractProvider return true; } - protected function getSupportedTldList(): array { + protected function getSupportedTldList(): array + { return []; } + /** - * @throws \Psr\Cache\InvalidArgumentException + * @throws InvalidArgumentException */ protected function getCachedTldList(): CacheItemInterface { return $this->cacheItemPool->getItem('app.provider.autodns.supported-tld'); } + + /** + * @throws TransportExceptionInterface + */ + public function assertAuthentication(): void + { + try { + $response = $this->client->request( + 'GET', + '/v1/hello', + (new HttpOptions()) + ->setAuthBasic($this->authData['username'], $this->authData['password']) + ->setHeader('Accept', 'application/json') + ->setHeader('X-Domainrobot-Context', $this->authData['context']) + ->setBaseUri(self::BASE_URL) + ->toArray() + ); + } catch (\Exception) { + throw new BadRequestHttpException('Invalid Login'); + } + + if (Response::HTTP_OK !== $response->getStatusCode()) { + throw new BadRequestHttpException('The status of these credentials is not valid'); + } + } } diff --git a/src/Config/Provider/GandiProvider.php b/src/Service/Connector/GandiProvider.php similarity index 85% rename from src/Config/Provider/GandiProvider.php rename to src/Service/Connector/GandiProvider.php index 1bbb988..348c134 100644 --- a/src/Config/Provider/GandiProvider.php +++ b/src/Service/Connector/GandiProvider.php @@ -1,9 +1,10 @@ authData, $this->client); - $user = $this->client->request('GET', '/v5/organization/user-info', (new HttpOptions()) - ->setAuthBearer($authData['token']) + ->setAuthBearer($this->authData['token']) ->setHeader('Accept', 'application/json') ->setBaseUri(self::BASE_URL) ->toArray() )->toArray(); $httpOptions = (new HttpOptions()) - ->setAuthBearer($authData['token']) + ->setAuthBearer($this->authData['token']) ->setHeader('Accept', 'application/json') ->setBaseUri(self::BASE_URL) ->setHeader('Dry-Run', $dryRun ? '1' : '0') @@ -68,9 +72,9 @@ class GandiProvider extends AbstractProvider 'tld_period' => 'golive', ]); - if (array_key_exists('sharingId', $authData)) { + if (array_key_exists('sharingId', $this->authData)) { $httpOptions->setQuery([ - 'sharing_id' => $authData['sharingId'], + 'sharing_id' => $this->authData['sharingId'], ]); } @@ -78,14 +82,11 @@ class GandiProvider extends AbstractProvider if ((!$dryRun && Response::HTTP_ACCEPTED !== $res->getStatusCode()) || ($dryRun && Response::HTTP_OK !== $res->getStatusCode())) { - throw new \HttpException($res->toArray()['message']); + throw new HttpException($res->toArray()['message']); } } - /** - * @throws TransportExceptionInterface - */ - public static function verifyAuthData(array $authData, HttpClientInterface $client): array + public function verifyAuthData(array $authData): array { $token = $authData['token']; @@ -105,17 +106,6 @@ class GandiProvider extends AbstractProvider throw new HttpException(451, 'The user has not given explicit consent'); } - $response = $client->request('GET', '/v5/organization/user-info', (new HttpOptions()) - ->setAuthBearer($token) - ->setHeader('Accept', 'application/json') - ->setBaseUri(self::BASE_URL) - ->toArray() - ); - - if (Response::HTTP_OK !== $response->getStatusCode()) { - throw new BadRequestHttpException('The status of these credentials is not valid'); - } - $authDataReturned = [ 'token' => $token, 'acceptConditions' => $acceptConditions, @@ -130,6 +120,23 @@ class GandiProvider extends AbstractProvider return $authDataReturned; } + /** + * @throws TransportExceptionInterface + */ + public function assertAuthentication(): void + { + $response = $this->client->request('GET', '/v5/organization/user-info', (new HttpOptions()) + ->setAuthBearer($this->authData['token']) + ->setHeader('Accept', 'application/json') + ->setBaseUri(self::BASE_URL) + ->toArray() + ); + + if (Response::HTTP_OK !== $response->getStatusCode()) { + throw new BadRequestHttpException('The status of these credentials is not valid'); + } + } + /** * @throws TransportExceptionInterface * @throws ServerExceptionInterface @@ -139,10 +146,8 @@ class GandiProvider extends AbstractProvider */ protected function getSupportedTldList(): array { - $authData = self::verifyAuthData($this->authData, $this->client); - $response = $this->client->request('GET', '/v5/domain/tlds', (new HttpOptions()) - ->setAuthBearer($authData['token']) + ->setAuthBearer($this->authData['token']) ->setHeader('Accept', 'application/json') ->setBaseUri(self::BASE_URL) ->toArray())->toArray(); diff --git a/src/Service/Connector/NamecheapProvider.php b/src/Service/Connector/NamecheapProvider.php new file mode 100644 index 0000000..e85fa44 --- /dev/null +++ b/src/Service/Connector/NamecheapProvider.php @@ -0,0 +1,148 @@ +call('namecheap.users.address.getList', [], $dryRun); + $addresses = $addressesRes->AddressGetListResult->List; + + if (count($addresses) < 1) { + throw new \Exception('Namecheap account requires at least one address to purchase a domain'); + } + + $addressId = (string) $addresses->attributes()['AddressId']; + $address = (array) $this->call('namecheap.users.address.getinfo', ['AddressId' => $addressId], $dryRun)->GetAddressInfoResult; + + if (empty($address['PostalCode'])) { + $address['PostalCode'] = $address['Zip']; + } + + $domainAddresses = []; + + self::mergePrefixKeys('Registrant', $address, $domainAddresses); + self::mergePrefixKeys('Tech', $address, $domainAddresses); + self::mergePrefixKeys('Admin', $address, $domainAddresses); + self::mergePrefixKeys('AuxBilling', $address, $domainAddresses); + + $this->call('namecheap.domains.create', array_merge([ + 'DomainName' => $domain->getLdhName(), + 'Years' => 1, + 'AddFreeWhoisguard' => 'yes', + 'WGEnabled' => 'yes', + ], $domainAddresses), $dryRun); + } + + private static function mergePrefixKeys(string $prefix, array|object $src, array &$dest): void + { + foreach ($src as $key => $value) { + $dest[$prefix.$key] = $value; + } + } + + /** + * @throws TransportExceptionInterface + * @throws ServerExceptionInterface + * @throws RedirectionExceptionInterface + * @throws ClientExceptionInterface + * @throws \Exception + */ + private function call(string $command, array $parameters = [], bool $dryRun = true): object + { + $actualParams = array_merge([ + 'Command' => $command, + 'UserName' => $this->authData['ApiUser'], + 'ApiUser' => $this->authData['ApiUser'], + 'ApiKey' => $this->authData['ApiKey'], + 'ClientIp' => $this->outgoingIp, + ], $parameters); + + $response = $this->client->request('POST', $dryRun ? self::SANDBOX_BASE_URL : self::BASE_URL, [ + 'query' => $actualParams, + ]); + + $data = new \SimpleXMLElement($response->getContent()); + + if ($data->Errors->Error) { + throw new \Exception($data->Errors->Error); // FIXME better exception type + } + + return $data->CommandResponse; + } + + public function verifyAuthData(array $authData): array + { + return [ + 'ApiUser' => $authData['ApiUser'], + 'ApiKey' => $authData['ApiKey'], + 'acceptConditions' => $authData['acceptConditions'], + 'ownerLegalAge' => $authData['ownerLegalAge'], + ]; + } + + /** + * @throws TransportExceptionInterface + * @throws ServerExceptionInterface + * @throws RedirectionExceptionInterface + * @throws ClientExceptionInterface + */ + public function assertAuthentication(): void + { + $this->call('namecheap.domains.gettldlist', [], false); + } + + /** + * @throws InvalidArgumentException + */ + protected function getCachedTldList(): CacheItemInterface + { + return $this->cacheItemPool->getItem('app.provider.namecheap.supported-tld'); + } + + /** + * @throws TransportExceptionInterface + * @throws ServerExceptionInterface + * @throws RedirectionExceptionInterface + * @throws ClientExceptionInterface + */ + protected function getSupportedTldList(): array + { + $supported = []; + + $tlds = $this->call('namecheap.domains.gettldlist', [], false)->Tlds->Tld; + + for ($i = 0; $i < $tlds->count(); ++$i) { + $supported[] = (string) $tlds[$i]['Name']; + } + + return $supported; + } +} diff --git a/src/Config/Provider/OvhProvider.php b/src/Service/Connector/OvhProvider.php similarity index 83% rename from src/Config/Provider/OvhProvider.php rename to src/Service/Connector/OvhProvider.php index 38f1138..1d917e9 100644 --- a/src/Config/Provider/OvhProvider.php +++ b/src/Service/Connector/OvhProvider.php @@ -1,16 +1,16 @@ authData, $this->client); - - $acceptConditions = $authData['acceptConditions']; - $ownerLegalAge = $authData['ownerLegalAge']; - $waiveRetractationPeriod = $authData['waiveRetractationPeriod']; + $acceptConditions = $this->authData['acceptConditions']; + $ownerLegalAge = $this->authData['ownerLegalAge']; + $waiveRetractationPeriod = $this->authData['waiveRetractationPeriod']; $conn = new Api( - $authData['appKey'], - $authData['appSecret'], - $authData['apiEndpoint'], - $authData['consumerKey'] + $this->authData['appKey'], + $this->authData['appSecret'], + $this->authData['apiEndpoint'], + $this->authData['consumerKey'] ); $cart = $conn->post('/order/cart', [ - 'ovhSubsidiary' => $authData['ovhSubsidiary'], + 'ovhSubsidiary' => $this->authData['ovhSubsidiary'], 'description' => 'Domain Watchdog', ]); $cartId = $cart['cartId']; @@ -81,8 +84,8 @@ class OvhProvider extends AbstractProvider ]); $pricingModes = ['create-default']; - if ('create-default' !== $authData['pricingMode']) { - $pricingModes[] = $authData['pricingMode']; + if ('create-default' !== $this->authData['pricingMode']) { + $pricingModes[] = $this->authData['pricingMode']; } $offer = array_filter($offers, fn ($offer) => 'create' === $offer['action'] @@ -131,7 +134,7 @@ class OvhProvider extends AbstractProvider /** * @throws \Exception */ - public static function verifyAuthData(array $authData, HttpClientInterface $client): array + public function verifyAuthData(array $authData): array { $appKey = $authData['appKey']; $appSecret = $authData['appSecret']; @@ -160,11 +163,26 @@ class OvhProvider extends AbstractProvider throw new HttpException(451, 'The user has not given explicit consent'); } + return [ + 'appKey' => $appKey, + 'appSecret' => $appSecret, + 'apiEndpoint' => $apiEndpoint, + 'consumerKey' => $consumerKey, + 'ovhSubsidiary' => $ovhSubsidiary, + 'pricingMode' => $pricingMode, + 'acceptConditions' => $acceptConditions, + 'ownerLegalAge' => $ownerLegalAge, + 'waiveRetractationPeriod' => $waiveRetractationPeriod, + ]; + } + + public function assertAuthentication(): void + { $conn = new Api( - $appKey, - $appSecret, - $apiEndpoint, - $consumerKey + $this->authData['appKey'], + $this->authData['appSecret'], + $this->authData['apiEndpoint'], + $this->authData['consumerKey'], ); try { @@ -197,18 +215,6 @@ class OvhProvider extends AbstractProvider throw new BadRequestHttpException('This Connector does not have enough permissions on the Provider API. Please recreate this Connector.'); } } - - return [ - 'appKey' => $appKey, - 'appSecret' => $appSecret, - 'apiEndpoint' => $apiEndpoint, - 'consumerKey' => $consumerKey, - 'ovhSubsidiary' => $ovhSubsidiary, - 'pricingMode' => $pricingMode, - 'acceptConditions' => $acceptConditions, - 'ownerLegalAge' => $ownerLegalAge, - 'waiveRetractationPeriod' => $waiveRetractationPeriod, - ]; } /** @@ -218,17 +224,15 @@ class OvhProvider extends AbstractProvider */ protected function getSupportedTldList(): array { - $authData = self::verifyAuthData($this->authData, $this->client); - $conn = new Api( - $authData['appKey'], - $authData['appSecret'], - $authData['apiEndpoint'], - $authData['consumerKey'] + $this->authData['appKey'], + $this->authData['appSecret'], + $this->authData['apiEndpoint'], + $this->authData['consumerKey'] ); return $conn->get('/domain/extensions', [ - 'ovhSubsidiary' => $authData['ovhSubsidiary'], + 'ovhSubsidiary' => $this->authData['ovhSubsidiary'], ]); } diff --git a/src/Service/RDAPService.php b/src/Service/RDAPService.php index 2805b27..f20c2cb 100644 --- a/src/Service/RDAPService.php +++ b/src/Service/RDAPService.php @@ -232,25 +232,27 @@ readonly class RDAPService $event->setDeleted(true); } - foreach ($res['events'] as $rdapEvent) { - if ($rdapEvent['eventAction'] === EventAction::LastUpdateOfRDAPDatabase->value) { - continue; - } + if (array_key_exists('events', $res) && is_array($res['events'])) { + foreach ($res['events'] as $rdapEvent) { + if ($rdapEvent['eventAction'] === EventAction::LastUpdateOfRDAPDatabase->value) { + continue; + } - $event = $this->domainEventRepository->findOneBy([ - 'action' => $rdapEvent['eventAction'], - 'date' => new \DateTimeImmutable($rdapEvent['eventDate']), - 'domain' => $domain, - ]); + $event = $this->domainEventRepository->findOneBy([ + 'action' => $rdapEvent['eventAction'], + 'date' => new \DateTimeImmutable($rdapEvent['eventDate']), + 'domain' => $domain, + ]); - if (null === $event) { - $event = new DomainEvent(); + if (null === $event) { + $event = new DomainEvent(); + } + $domain->addEvent($event + ->setAction($rdapEvent['eventAction']) + ->setDate(new \DateTimeImmutable($rdapEvent['eventDate'])) + ->setDeleted(false) + ); } - $domain->addEvent($event - ->setAction($rdapEvent['eventAction']) - ->setDate(new \DateTimeImmutable($rdapEvent['eventDate'])) - ->setDeleted(false) - ); } /** @var DomainEntity $domainEntity */ diff --git a/translations/de.po b/translations/de.po index 2d65aab..71295d9 100644 --- a/translations/de.po +++ b/translations/de.po @@ -10,6 +10,31 @@ msgstr "" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Generator: Weblate 5.7.2\n" +#: assets/App.tsx:101 +msgid "TOS" +msgstr "Nutzungsbedingungen" + +#: assets/App.tsx:102 +msgid "Privacy Policy" +msgstr "Datenschutzrichtlinie" + +#: assets/App.tsx:103 +msgid "FAQ" +msgstr "Häufig gestellte Fragen" + +#: assets/App.tsx:105 +msgid "Documentation" +msgstr "Dokumentation" + +#: assets/App.tsx:108 +#, javascript-format +msgid "" +"${ ProjectLink } is an open source project distributed under the " +"${ LicenseLink } license." +msgstr "" +"${ ProjectLink } ist ein Open-Source-Projekt, das unter der ${ LicenseLink }-" +"Lizenz vertrieben wird." + #: assets/components/LoginForm.tsx:52 assets/components/RegisterForm.tsx:39 msgid "Email address" msgstr "E-Mail-Adresse" @@ -43,22 +68,9 @@ msgstr "Senden" msgid "Log in with SSO" msgstr "Mit SSO anmelden" -#: assets/components/search/DomainResult.tsx:45 -msgid "EPP Status Codes" -msgstr "EPP-Statuscodes" - -#: assets/components/search/DomainResult.tsx:61 -msgid "Timeline" -msgstr "Zeitleiste" - -#: assets/components/search/DomainResult.tsx:68 -msgid "Entities" -msgstr "Entitäten" - -#: assets/components/search/DomainSearchBar.tsx:23 -#: assets/components/tracking/watchlist/WatchlistForm.tsx:118 -msgid "This domain name does not appear to be valid" -msgstr "Dieser Domainname scheint nicht gültig zu sein" +#: assets/components/RegisterForm.tsx:56 assets/pages/LoginPage.tsx:25 +msgid "Register" +msgstr "Registrieren" #: assets/components/search/DomainLifecycleSteps.tsx:15 #: assets/utils/functions/rdapTranslation.ts:43 @@ -77,6 +89,93 @@ msgstr "Einlösezeitraum" msgid "Pending Delete" msgstr "Ausstehende Löschung" +#: assets/components/search/DomainResult.tsx:45 +msgid "EPP Status Codes" +msgstr "EPP-Statuscodes" + +#: assets/components/search/DomainResult.tsx:61 +msgid "Timeline" +msgstr "Zeitleiste" + +#: assets/components/search/DomainResult.tsx:68 +msgid "Entities" +msgstr "Entitäten" + +#: assets/components/search/DomainSearchBar.tsx:23 +#: assets/components/tracking/watchlist/WatchlistForm.tsx:118 +msgid "This domain name does not appear to be valid" +msgstr "Dieser Domainname scheint nicht gültig zu sein" + +#: assets/components/Sider.tsx:28 +msgid "Home" +msgstr "Startseite" + +#: assets/components/Sider.tsx:34 +msgid "Search" +msgstr "Suchen" + +#: assets/components/Sider.tsx:40 +#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:46 +msgid "Domain" +msgstr "Domain" + +#: assets/components/Sider.tsx:41 +msgid "Domain Finder" +msgstr "Domänenfinder" + +#: assets/components/Sider.tsx:48 assets/pages/search/TldPage.tsx:65 +msgid "TLD" +msgstr "TLD" + +#: assets/components/Sider.tsx:49 +msgid "TLD list" +msgstr "TLD-Liste" + +#: assets/components/Sider.tsx:56 +msgid "Entity" +msgstr "Entität" + +#: assets/components/Sider.tsx:57 +msgid "Entity Finder" +msgstr "Entitätsfinder" + +#: assets/components/Sider.tsx:64 +msgid "Nameserver" +msgstr "Nameserver" + +#: assets/components/Sider.tsx:65 +msgid "Nameserver Finder" +msgstr "Nameserver-Finder" + +#: assets/components/Sider.tsx:73 +msgid "Tracking" +msgstr "Nachverfolgung" + +#: assets/components/Sider.tsx:79 +msgid "My Watchlists" +msgstr "Meine Watchlists" + +#: assets/components/Sider.tsx:86 +msgid "My Connectors" +msgstr "Meine Konnektoren" + +#: assets/components/Sider.tsx:95 +msgid "Statistics" +msgstr "Statistiken" + +#: assets/components/Sider.tsx:105 assets/pages/UserPage.tsx:16 +msgid "My Account" +msgstr "Mein Konto" + +#: assets/components/Sider.tsx:110 +msgid "Log out" +msgstr "Abmelden" + +#: assets/components/Sider.tsx:118 assets/pages/LoginPage.tsx:25 +#: assets/pages/LoginPage.tsx:33 +msgid "Log in" +msgstr "Anmelden" + #: assets/components/tracking/connector/ConnectorForm.tsx:40 msgid "Provider" msgstr "Anbieter" @@ -196,6 +295,82 @@ msgstr "Ja" msgid "No" msgstr "Nein" +#: assets/components/tracking/watchlist/CalendarWatchlistButton.tsx:14 +msgid "QR Code for iCalendar export" +msgstr "QR-Code für iCalendar-Export" + +#: assets/components/tracking/watchlist/CalendarWatchlistButton.tsx:17 +msgid "Export events to iCalendar format" +msgstr "Ereignisse in das iCalendar-Format exportieren" + +#: assets/components/tracking/watchlist/DeleteWatchlistButton.tsx:12 +#: assets/components/tracking/watchlist/DeleteWatchlistButton.tsx:19 +msgid "Delete the Watchlist" +msgstr "Löschen der Watchlist" + +#: assets/components/tracking/watchlist/DeleteWatchlistButton.tsx:13 +msgid "Are you sure to delete this Watchlist?" +msgstr "Möchten Sie diese Watchlist wirklich löschen?" + +#: assets/components/tracking/watchlist/diagram/ViewDiagramWatchlistButton.tsx:39 +msgid "View the Watchlist Entity Diagram" +msgstr "Sehen Sie sich das Watchlist-Entitätsdiagramm an" + +#: assets/components/tracking/watchlist/diagram/ViewDiagramWatchlistButton.tsx:44 +msgid "Watchlist Entity Diagram" +msgstr "Watchlist-Entitäten Diagramm" + +#: assets/components/tracking/watchlist/diagram/watchlistToEdges.tsx:37 +msgid "Registry" +msgstr "Registrierung" + +#: assets/components/tracking/watchlist/diagram/watchlistToNodes.tsx:30 +#, javascript-format +msgid ".${ tld.tld } Registry" +msgstr ".${ tld.tld } Registrierung" + +#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:50 +msgid "Expiration date" +msgstr "Verfallsdatum" + +#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:54 +msgid "Status" +msgstr "Status" + +#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:58 +msgid "Updated at" +msgstr "Aktualisiert am" + +#: assets/components/tracking/watchlist/UpdateWatchlistButton.tsx:31 +msgid "Edit the Watchlist" +msgstr "Bearbeiten der Watchlist" + +#: assets/components/tracking/watchlist/UpdateWatchlistButton.tsx:44 +msgid "Update a Watchlist" +msgstr "Aktualisieren einer Watchlist" + +#: assets/components/tracking/watchlist/UpdateWatchlistButton.tsx:54 +msgid "Cancel" +msgstr "Abbrechen" + +#: assets/components/tracking/watchlist/WatchlistCard.tsx:29 +#: assets/components/tracking/watchlist/WatchlistForm.tsx:106 +msgid "Domain names" +msgstr "Domänennamen" + +#: assets/components/tracking/watchlist/WatchlistCard.tsx:33 +#: assets/components/tracking/watchlist/WatchlistForm.tsx:148 +msgid "Tracked events" +msgstr "Verfolgte Ereignisse" + +#: assets/components/tracking/watchlist/WatchlistCard.tsx:47 +msgid "This Watchlist is not linked to a Connector." +msgstr "Diese Beobachtungsliste ist nicht mit einem Connector verknüpft." + +#: assets/components/tracking/watchlist/WatchlistCard.tsx:52 +msgid "Watchlist" +msgstr "Watchlist" + #: assets/components/tracking/watchlist/WatchlistForm.tsx:72 msgid "Name" msgstr "Name" @@ -214,11 +389,6 @@ msgstr "" msgid "At least one domain name" msgstr "Mindestens ein Domänenname" -#: assets/components/tracking/watchlist/WatchlistCard.tsx:29 -#: assets/components/tracking/watchlist/WatchlistForm.tsx:106 -msgid "Domain names" -msgstr "Domänennamen" - #: assets/components/tracking/watchlist/WatchlistForm.tsx:124 msgid "Domain name" msgstr "Domänenname" @@ -227,11 +397,6 @@ msgstr "Domänenname" msgid "Add a Domain name" msgstr "Einen Domänennamen hinzufügen" -#: assets/components/tracking/watchlist/WatchlistCard.tsx:33 -#: assets/components/tracking/watchlist/WatchlistForm.tsx:148 -msgid "Tracked events" -msgstr "Verfolgte Ereignisse" - #: assets/components/tracking/watchlist/WatchlistForm.tsx:150 msgid "At least one trigger" msgstr "Mindestens ein Auslöser" @@ -272,145 +437,13 @@ msgstr "Einen Webhook hinzufügen" msgid "Update" msgstr "Aktualisieren" -#: assets/components/tracking/watchlist/UpdateWatchlistButton.tsx:31 -msgid "Edit the Watchlist" -msgstr "Bearbeiten der Watchlist" - -#: assets/components/tracking/watchlist/UpdateWatchlistButton.tsx:44 -msgid "Update a Watchlist" -msgstr "Aktualisieren einer Watchlist" - -#: assets/components/tracking/watchlist/UpdateWatchlistButton.tsx:54 -msgid "Cancel" -msgstr "Abbrechen" - -#: assets/components/tracking/watchlist/diagram/ViewDiagramWatchlistButton.tsx:39 -msgid "View the Watchlist Entity Diagram" -msgstr "Sehen Sie sich das Watchlist-Entitätsdiagramm an" - -#: assets/components/tracking/watchlist/diagram/ViewDiagramWatchlistButton.tsx:44 -msgid "Watchlist Entity Diagram" -msgstr "Watchlist-Entitäten Diagramm" - -#: assets/components/tracking/watchlist/diagram/watchlistToEdges.tsx:37 -msgid "Registry" -msgstr "Registrierung" - -#: assets/components/tracking/watchlist/diagram/watchlistToNodes.tsx:30 -#, javascript-format -msgid ".${ tld.tld } Registry" -msgstr ".${ tld.tld } Registrierung" - -#: assets/components/tracking/watchlist/CalendarWatchlistButton.tsx:14 -msgid "QR Code for iCalendar export" -msgstr "QR-Code für iCalendar-Export" - -#: assets/components/tracking/watchlist/CalendarWatchlistButton.tsx:17 -msgid "Export events to iCalendar format" -msgstr "Ereignisse in das iCalendar-Format exportieren" - -#: assets/components/tracking/watchlist/DeleteWatchlistButton.tsx:12 -#: assets/components/tracking/watchlist/DeleteWatchlistButton.tsx:19 -msgid "Delete the Watchlist" -msgstr "Löschen der Watchlist" - -#: assets/components/tracking/watchlist/DeleteWatchlistButton.tsx:13 -msgid "Are you sure to delete this Watchlist?" -msgstr "Möchten Sie diese Watchlist wirklich löschen?" - -#: assets/components/Sider.tsx:40 -#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:46 -msgid "Domain" -msgstr "Domain" - -#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:50 -msgid "Expiration date" -msgstr "Verfallsdatum" - -#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:54 -msgid "Status" -msgstr "Status" - -#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:58 -msgid "Updated at" -msgstr "Aktualisiert am" - -#: assets/components/tracking/watchlist/WatchlistCard.tsx:47 -msgid "This Watchlist is not linked to a Connector." -msgstr "Diese Beobachtungsliste ist nicht mit einem Connector verknüpft." - -#: assets/components/tracking/watchlist/WatchlistCard.tsx:52 -msgid "Watchlist" -msgstr "Watchlist" - -#: assets/components/Sider.tsx:28 -msgid "Home" -msgstr "Startseite" - -#: assets/components/Sider.tsx:34 -msgid "Search" -msgstr "Suchen" - -#: assets/components/Sider.tsx:41 -msgid "Domain Finder" -msgstr "Domänenfinder" - -#: assets/components/Sider.tsx:48 assets/pages/search/TldPage.tsx:65 -msgid "TLD" -msgstr "TLD" - -#: assets/components/Sider.tsx:49 -msgid "TLD list" -msgstr "TLD-Liste" - -#: assets/components/Sider.tsx:56 -msgid "Entity" -msgstr "Entität" - -#: assets/components/Sider.tsx:57 -msgid "Entity Finder" -msgstr "Entitätsfinder" - -#: assets/components/Sider.tsx:64 -msgid "Nameserver" -msgstr "Nameserver" - -#: assets/components/Sider.tsx:65 -msgid "Nameserver Finder" -msgstr "Nameserver-Finder" - -#: assets/components/Sider.tsx:73 -msgid "Tracking" -msgstr "Nachverfolgung" - -#: assets/components/Sider.tsx:79 -msgid "My Watchlists" -msgstr "Meine Watchlists" - -#: assets/components/Sider.tsx:86 -msgid "My Connectors" -msgstr "Meine Konnektoren" - -#: assets/components/Sider.tsx:95 -msgid "Statistics" -msgstr "Statistiken" - -#: assets/components/Sider.tsx:105 assets/pages/UserPage.tsx:16 -msgid "My Account" -msgstr "Mein Konto" - -#: assets/components/Sider.tsx:110 -msgid "Log out" -msgstr "Abmelden" - -#: assets/components/Sider.tsx:118 assets/pages/LoginPage.tsx:25 #: assets/pages/LoginPage.tsx:33 -msgid "Log in" -msgstr "Anmelden" +msgid "Create an account" +msgstr "Ein Konto erstellen" -#: assets/components/RegisterForm.tsx:56 assets/pages/LoginPage.tsx:25 -msgid "Register" -msgstr "Registrieren" +#: assets/pages/NotFoundPage.tsx:10 +msgid "Sorry, the page you visited does not exist." +msgstr "Es tut uns leid, die von Ihnen besuchte Seite existiert nicht." #: assets/pages/search/DomainSearchPage.tsx:18 msgid "Found !" @@ -513,6 +546,44 @@ msgstr "" "Top-Level-Domains basieren auf Ländercodes und identifizieren Websites " "entsprechend ihrem Herkunftsland." +#: assets/pages/StatisticsPage.tsx:34 +msgid "RDAP queries" +msgstr "RDAP-Abfragen" + +#: assets/pages/StatisticsPage.tsx:43 +msgid "Alerts sent" +msgstr "Gesendete Warnungen" + +#: assets/pages/StatisticsPage.tsx:57 +msgid "Domain names in database" +msgstr "Domänennamen in der Datenbank" + +#: assets/pages/StatisticsPage.tsx:68 +#: assets/pages/tracking/WatchlistPage.tsx:111 +msgid "Tracked domain names" +msgstr "Verfolgte Domänennamen" + +#: assets/pages/StatisticsPage.tsx:82 +msgid "Purchased domain names" +msgstr "Gekaufte Domänennamen" + +#: assets/pages/StatisticsPage.tsx:92 +msgid "" +"This value is based on the status code of the HTTP response from the " +"providers following the domain order." +msgstr "" +"Dieser Wert basiert auf dem Statuscode der HTTP-Antwort der Anbieter nach " +"dem Domainkauf." + +#: assets/pages/StatisticsPage.tsx:95 +msgid "Success rate" +msgstr "Erfolgsrate" + +#: assets/pages/TextPage.tsx:26 +#, javascript-format +msgid "📝 Please create the /public/content/${ resource } file." +msgstr "📝 Bitte erstellen Sie die Datei /public/content/${ resource }." + #: assets/pages/tracking/ConnectorsPage.tsx:20 msgid "Connector created !" msgstr "Connector erstellt!" @@ -533,47 +604,6 @@ msgstr "Watchlist aktualisiert !" msgid "Create a Watchlist" msgstr "Erstellen Sie eine Watchlist" -#: assets/pages/StatisticsPage.tsx:68 -#: assets/pages/tracking/WatchlistPage.tsx:111 -msgid "Tracked domain names" -msgstr "Verfolgte Domänennamen" - -#: assets/pages/NotFoundPage.tsx:10 -msgid "Sorry, the page you visited does not exist." -msgstr "Es tut uns leid, die von Ihnen besuchte Seite existiert nicht." - -#: assets/pages/StatisticsPage.tsx:34 -msgid "RDAP queries" -msgstr "RDAP-Abfragen" - -#: assets/pages/StatisticsPage.tsx:43 -msgid "Alerts sent" -msgstr "Gesendete Warnungen" - -#: assets/pages/StatisticsPage.tsx:57 -msgid "Domain names in database" -msgstr "Domänennamen in der Datenbank" - -#: assets/pages/StatisticsPage.tsx:82 -msgid "Purchased domain names" -msgstr "Gekaufte Domänennamen" - -#: assets/pages/StatisticsPage.tsx:92 -msgid "" -"This value is based on the status code of the HTTP response from the " -"providers following the domain order." -msgstr "" -"Dieser Wert basiert auf dem Statuscode der HTTP-Antwort der Anbieter nach " -"dem Domainkauf." - -#: assets/pages/StatisticsPage.tsx:95 -msgid "Success rate" -msgstr "Erfolgsrate" - -#: assets/pages/LoginPage.tsx:33 -msgid "Create an account" -msgstr "Ein Konto erstellen" - #: assets/pages/UserPage.tsx:18 msgid "Username" msgstr "Benutzername" @@ -582,11 +612,6 @@ msgstr "Benutzername" msgid "Roles" msgstr "Rollen" -#: assets/pages/TextPage.tsx:26 -#, javascript-format -msgid "📝 Please create the /public/content/${ resource } file." -msgstr "📝 Bitte erstellen Sie die Datei /public/content/${ resource }." - #: assets/utils/functions/rdapTranslation.ts:7 msgid "Registrant" msgstr "Anmelder" @@ -1229,31 +1254,6 @@ msgstr "" "Die Domain ist kostenlos, kann aber Premium sein. Der Preis variiert von " "einer Domain zur anderen" -#: assets/App.tsx:101 -msgid "TOS" -msgstr "Nutzungsbedingungen" - -#: assets/App.tsx:102 -msgid "Privacy Policy" -msgstr "Datenschutzrichtlinie" - -#: assets/App.tsx:103 -msgid "FAQ" -msgstr "Häufig gestellte Fragen" - -#: assets/App.tsx:105 -msgid "Documentation" -msgstr "Dokumentation" - -#: assets/App.tsx:108 -#, javascript-format -msgid "" -"${ ProjectLink } is an open source project distributed under the " -"${ LicenseLink } license." -msgstr "" -"${ ProjectLink } ist ein Open-Source-Projekt, das unter der ${ LicenseLink }-" -"Lizenz vertrieben wird." - #, fuzzy #~ msgid "Tracked Domains" #~ msgstr "Verfolgte Domänennamen" diff --git a/translations/fr.po b/translations/fr.po index 7bda790..bb7dcde 100644 --- a/translations/fr.po +++ b/translations/fr.po @@ -11,6 +11,31 @@ msgstr "" "Plural-Forms: nplurals=2; plural=n > 1;\n" "X-Generator: Weblate 5.7.2\n" +#: assets/App.tsx:101 +msgid "TOS" +msgstr "CGU" + +#: assets/App.tsx:102 +msgid "Privacy Policy" +msgstr "Politique de confidentialité" + +#: assets/App.tsx:103 +msgid "FAQ" +msgstr "FAQ" + +#: assets/App.tsx:105 +msgid "Documentation" +msgstr "Documentation" + +#: assets/App.tsx:108 +#, javascript-format +msgid "" +"${ ProjectLink } is an open source project distributed under the " +"${ LicenseLink } license." +msgstr "" +"${ ProjectLink } est un projet open source distribué sous licence " +"${ LicenseLink }." + #: assets/components/LoginForm.tsx:52 assets/components/RegisterForm.tsx:39 msgid "Email address" msgstr "Adresse e-mail" @@ -44,22 +69,9 @@ msgstr "Se connecter" msgid "Log in with SSO" msgstr "Se connecter par SSO" -#: assets/components/search/DomainResult.tsx:45 -msgid "EPP Status Codes" -msgstr "Codes de statut EPP" - -#: assets/components/search/DomainResult.tsx:61 -msgid "Timeline" -msgstr "Chronologie" - -#: assets/components/search/DomainResult.tsx:68 -msgid "Entities" -msgstr "Entités" - -#: assets/components/search/DomainSearchBar.tsx:23 -#: assets/components/tracking/watchlist/WatchlistForm.tsx:118 -msgid "This domain name does not appear to be valid" -msgstr "Ce nom de domaine ne semble pas être valide" +#: assets/components/RegisterForm.tsx:56 assets/pages/LoginPage.tsx:25 +msgid "Register" +msgstr "S'enregistrer" #: assets/components/search/DomainLifecycleSteps.tsx:15 #: assets/utils/functions/rdapTranslation.ts:43 @@ -78,6 +90,93 @@ msgstr "Période de rédemption" msgid "Pending Delete" msgstr "En attente de suppression" +#: assets/components/search/DomainResult.tsx:45 +msgid "EPP Status Codes" +msgstr "Codes de statut EPP" + +#: assets/components/search/DomainResult.tsx:61 +msgid "Timeline" +msgstr "Chronologie" + +#: assets/components/search/DomainResult.tsx:68 +msgid "Entities" +msgstr "Entités" + +#: assets/components/search/DomainSearchBar.tsx:23 +#: assets/components/tracking/watchlist/WatchlistForm.tsx:118 +msgid "This domain name does not appear to be valid" +msgstr "Ce nom de domaine ne semble pas être valide" + +#: assets/components/Sider.tsx:28 +msgid "Home" +msgstr "Accueil" + +#: assets/components/Sider.tsx:34 +msgid "Search" +msgstr "Rechercher" + +#: assets/components/Sider.tsx:40 +#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:46 +msgid "Domain" +msgstr "Domaine" + +#: assets/components/Sider.tsx:41 +msgid "Domain Finder" +msgstr "Rechercher un domaine" + +#: assets/components/Sider.tsx:48 assets/pages/search/TldPage.tsx:65 +msgid "TLD" +msgstr "TLD" + +#: assets/components/Sider.tsx:49 +msgid "TLD list" +msgstr "Liste des TLD" + +#: assets/components/Sider.tsx:56 +msgid "Entity" +msgstr "Entité" + +#: assets/components/Sider.tsx:57 +msgid "Entity Finder" +msgstr "Rechercher une entité" + +#: assets/components/Sider.tsx:64 +msgid "Nameserver" +msgstr "Serveur DNS" + +#: assets/components/Sider.tsx:65 +msgid "Nameserver Finder" +msgstr "Rechercher un serveur DNS" + +#: assets/components/Sider.tsx:73 +msgid "Tracking" +msgstr "Suivi" + +#: assets/components/Sider.tsx:79 +msgid "My Watchlists" +msgstr "Mes Watchlists" + +#: assets/components/Sider.tsx:86 +msgid "My Connectors" +msgstr "Mes Connecteurs" + +#: assets/components/Sider.tsx:95 +msgid "Statistics" +msgstr "Statistiques" + +#: assets/components/Sider.tsx:105 assets/pages/UserPage.tsx:16 +msgid "My Account" +msgstr "Mon compte" + +#: assets/components/Sider.tsx:110 +msgid "Log out" +msgstr "Se déconnecter" + +#: assets/components/Sider.tsx:118 assets/pages/LoginPage.tsx:25 +#: assets/pages/LoginPage.tsx:33 +msgid "Log in" +msgstr "Se connecter" + #: assets/components/tracking/connector/ConnectorForm.tsx:40 msgid "Provider" msgstr "Fournisseur" @@ -196,6 +295,82 @@ msgstr "Oui" msgid "No" msgstr "Non" +#: assets/components/tracking/watchlist/CalendarWatchlistButton.tsx:14 +msgid "QR Code for iCalendar export" +msgstr "QR Code pour l'exportation iCalendar" + +#: assets/components/tracking/watchlist/CalendarWatchlistButton.tsx:17 +msgid "Export events to iCalendar format" +msgstr "Exporter les événements au format iCalendar" + +#: assets/components/tracking/watchlist/DeleteWatchlistButton.tsx:12 +#: assets/components/tracking/watchlist/DeleteWatchlistButton.tsx:19 +msgid "Delete the Watchlist" +msgstr "Supprimer la Watchlist" + +#: assets/components/tracking/watchlist/DeleteWatchlistButton.tsx:13 +msgid "Are you sure to delete this Watchlist?" +msgstr "Êtes-vous sûr de vouloir supprimer cette Watchlist ?" + +#: assets/components/tracking/watchlist/diagram/ViewDiagramWatchlistButton.tsx:39 +msgid "View the Watchlist Entity Diagram" +msgstr "Afficher le diagramme d'entités de la Watchlist" + +#: assets/components/tracking/watchlist/diagram/ViewDiagramWatchlistButton.tsx:44 +msgid "Watchlist Entity Diagram" +msgstr "Diagramme d'entités de la Watchlist" + +#: assets/components/tracking/watchlist/diagram/watchlistToEdges.tsx:37 +msgid "Registry" +msgstr "Registre" + +#: assets/components/tracking/watchlist/diagram/watchlistToNodes.tsx:30 +#, javascript-format +msgid ".${ tld.tld } Registry" +msgstr "Registre .${ tld.tld }" + +#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:50 +msgid "Expiration date" +msgstr "Date d'expiration" + +#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:54 +msgid "Status" +msgstr "Statuts" + +#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:58 +msgid "Updated at" +msgstr "Mis à jour le" + +#: assets/components/tracking/watchlist/UpdateWatchlistButton.tsx:31 +msgid "Edit the Watchlist" +msgstr "Modifier la Watchlist" + +#: assets/components/tracking/watchlist/UpdateWatchlistButton.tsx:44 +msgid "Update a Watchlist" +msgstr "Mise à jour d'une Watchlist" + +#: assets/components/tracking/watchlist/UpdateWatchlistButton.tsx:54 +msgid "Cancel" +msgstr "Annuler" + +#: assets/components/tracking/watchlist/WatchlistCard.tsx:29 +#: assets/components/tracking/watchlist/WatchlistForm.tsx:106 +msgid "Domain names" +msgstr "Noms de domaines" + +#: assets/components/tracking/watchlist/WatchlistCard.tsx:33 +#: assets/components/tracking/watchlist/WatchlistForm.tsx:148 +msgid "Tracked events" +msgstr "Événements suivis" + +#: assets/components/tracking/watchlist/WatchlistCard.tsx:47 +msgid "This Watchlist is not linked to a Connector." +msgstr "Cette Watchlist n'est pas liée à un connecteur." + +#: assets/components/tracking/watchlist/WatchlistCard.tsx:52 +msgid "Watchlist" +msgstr "Watchlist" + #: assets/components/tracking/watchlist/WatchlistForm.tsx:72 msgid "Name" msgstr "Nom" @@ -214,11 +389,6 @@ msgstr "" msgid "At least one domain name" msgstr "Au moins un nom de domaine" -#: assets/components/tracking/watchlist/WatchlistCard.tsx:29 -#: assets/components/tracking/watchlist/WatchlistForm.tsx:106 -msgid "Domain names" -msgstr "Noms de domaines" - #: assets/components/tracking/watchlist/WatchlistForm.tsx:124 msgid "Domain name" msgstr "Nom de domaine" @@ -227,11 +397,6 @@ msgstr "Nom de domaine" msgid "Add a Domain name" msgstr "Ajouter un nom de domaine" -#: assets/components/tracking/watchlist/WatchlistCard.tsx:33 -#: assets/components/tracking/watchlist/WatchlistForm.tsx:148 -msgid "Tracked events" -msgstr "Événements suivis" - #: assets/components/tracking/watchlist/WatchlistForm.tsx:150 msgid "At least one trigger" msgstr "Au moins un déclencheur" @@ -272,145 +437,13 @@ msgstr "Ajouter un Webhook" msgid "Update" msgstr "Mettre à jour" -#: assets/components/tracking/watchlist/UpdateWatchlistButton.tsx:31 -msgid "Edit the Watchlist" -msgstr "Modifier la Watchlist" - -#: assets/components/tracking/watchlist/UpdateWatchlistButton.tsx:44 -msgid "Update a Watchlist" -msgstr "Mise à jour d'une Watchlist" - -#: assets/components/tracking/watchlist/UpdateWatchlistButton.tsx:54 -msgid "Cancel" -msgstr "Annuler" - -#: assets/components/tracking/watchlist/diagram/ViewDiagramWatchlistButton.tsx:39 -msgid "View the Watchlist Entity Diagram" -msgstr "Afficher le diagramme d'entités de la Watchlist" - -#: assets/components/tracking/watchlist/diagram/ViewDiagramWatchlistButton.tsx:44 -msgid "Watchlist Entity Diagram" -msgstr "Diagramme d'entités de la Watchlist" - -#: assets/components/tracking/watchlist/diagram/watchlistToEdges.tsx:37 -msgid "Registry" -msgstr "Registre" - -#: assets/components/tracking/watchlist/diagram/watchlistToNodes.tsx:30 -#, javascript-format -msgid ".${ tld.tld } Registry" -msgstr "Registre .${ tld.tld }" - -#: assets/components/tracking/watchlist/CalendarWatchlistButton.tsx:14 -msgid "QR Code for iCalendar export" -msgstr "QR Code pour l'exportation iCalendar" - -#: assets/components/tracking/watchlist/CalendarWatchlistButton.tsx:17 -msgid "Export events to iCalendar format" -msgstr "Exporter les événements au format iCalendar" - -#: assets/components/tracking/watchlist/DeleteWatchlistButton.tsx:12 -#: assets/components/tracking/watchlist/DeleteWatchlistButton.tsx:19 -msgid "Delete the Watchlist" -msgstr "Supprimer la Watchlist" - -#: assets/components/tracking/watchlist/DeleteWatchlistButton.tsx:13 -msgid "Are you sure to delete this Watchlist?" -msgstr "Êtes-vous sûr de vouloir supprimer cette Watchlist ?" - -#: assets/components/Sider.tsx:40 -#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:46 -msgid "Domain" -msgstr "Domaine" - -#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:50 -msgid "Expiration date" -msgstr "Date d'expiration" - -#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:54 -msgid "Status" -msgstr "Statuts" - -#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:58 -msgid "Updated at" -msgstr "Mis à jour le" - -#: assets/components/tracking/watchlist/WatchlistCard.tsx:47 -msgid "This Watchlist is not linked to a Connector." -msgstr "Cette Watchlist n'est pas liée à un connecteur." - -#: assets/components/tracking/watchlist/WatchlistCard.tsx:52 -msgid "Watchlist" -msgstr "Watchlist" - -#: assets/components/Sider.tsx:28 -msgid "Home" -msgstr "Accueil" - -#: assets/components/Sider.tsx:34 -msgid "Search" -msgstr "Rechercher" - -#: assets/components/Sider.tsx:41 -msgid "Domain Finder" -msgstr "Rechercher un domaine" - -#: assets/components/Sider.tsx:48 assets/pages/search/TldPage.tsx:65 -msgid "TLD" -msgstr "TLD" - -#: assets/components/Sider.tsx:49 -msgid "TLD list" -msgstr "Liste des TLD" - -#: assets/components/Sider.tsx:56 -msgid "Entity" -msgstr "Entité" - -#: assets/components/Sider.tsx:57 -msgid "Entity Finder" -msgstr "Rechercher une entité" - -#: assets/components/Sider.tsx:64 -msgid "Nameserver" -msgstr "Serveur DNS" - -#: assets/components/Sider.tsx:65 -msgid "Nameserver Finder" -msgstr "Rechercher un serveur DNS" - -#: assets/components/Sider.tsx:73 -msgid "Tracking" -msgstr "Suivi" - -#: assets/components/Sider.tsx:79 -msgid "My Watchlists" -msgstr "Mes Watchlists" - -#: assets/components/Sider.tsx:86 -msgid "My Connectors" -msgstr "Mes Connecteurs" - -#: assets/components/Sider.tsx:95 -msgid "Statistics" -msgstr "Statistiques" - -#: assets/components/Sider.tsx:105 assets/pages/UserPage.tsx:16 -msgid "My Account" -msgstr "Mon compte" - -#: assets/components/Sider.tsx:110 -msgid "Log out" -msgstr "Se déconnecter" - -#: assets/components/Sider.tsx:118 assets/pages/LoginPage.tsx:25 #: assets/pages/LoginPage.tsx:33 -msgid "Log in" -msgstr "Se connecter" +msgid "Create an account" +msgstr "Créer un compte" -#: assets/components/RegisterForm.tsx:56 assets/pages/LoginPage.tsx:25 -msgid "Register" -msgstr "S'enregistrer" +#: assets/pages/NotFoundPage.tsx:10 +msgid "Sorry, the page you visited does not exist." +msgstr "Désolé, cette page n'existe pas." #: assets/pages/search/DomainSearchPage.tsx:18 msgid "Found !" @@ -512,6 +545,44 @@ msgstr "" "Domaines de premier niveau basés sur les codes de pays, identifiant les " "sites web en fonction de leur pays d'origine." +#: assets/pages/StatisticsPage.tsx:34 +msgid "RDAP queries" +msgstr "Requêtes RDAP" + +#: assets/pages/StatisticsPage.tsx:43 +msgid "Alerts sent" +msgstr "Alertes envoyées" + +#: assets/pages/StatisticsPage.tsx:57 +msgid "Domain names in database" +msgstr "Noms de domaine dans la base de données" + +#: assets/pages/StatisticsPage.tsx:68 +#: assets/pages/tracking/WatchlistPage.tsx:111 +msgid "Tracked domain names" +msgstr "Noms de domaine suivis" + +#: assets/pages/StatisticsPage.tsx:82 +msgid "Purchased domain names" +msgstr "Noms de domaine achetés" + +#: assets/pages/StatisticsPage.tsx:92 +msgid "" +"This value is based on the status code of the HTTP response from the " +"providers following the domain order." +msgstr "" +"Cette valeur est basée sur le code d'état de la réponse HTTP des Providers " +"suivant l'achat du domaine." + +#: assets/pages/StatisticsPage.tsx:95 +msgid "Success rate" +msgstr "Taux de succès" + +#: assets/pages/TextPage.tsx:26 +#, javascript-format +msgid "📝 Please create the /public/content/${ resource } file." +msgstr "📝 Veuillez créer le fichier /public/content/${ resource }." + #: assets/pages/tracking/ConnectorsPage.tsx:20 msgid "Connector created !" msgstr "Connecteur créé !" @@ -532,47 +603,6 @@ msgstr "Watchlist mise à jour !" msgid "Create a Watchlist" msgstr "Créer une Watchlist" -#: assets/pages/StatisticsPage.tsx:68 -#: assets/pages/tracking/WatchlistPage.tsx:111 -msgid "Tracked domain names" -msgstr "Noms de domaine suivis" - -#: assets/pages/NotFoundPage.tsx:10 -msgid "Sorry, the page you visited does not exist." -msgstr "Désolé, cette page n'existe pas." - -#: assets/pages/StatisticsPage.tsx:34 -msgid "RDAP queries" -msgstr "Requêtes RDAP" - -#: assets/pages/StatisticsPage.tsx:43 -msgid "Alerts sent" -msgstr "Alertes envoyées" - -#: assets/pages/StatisticsPage.tsx:57 -msgid "Domain names in database" -msgstr "Noms de domaine dans la base de données" - -#: assets/pages/StatisticsPage.tsx:82 -msgid "Purchased domain names" -msgstr "Noms de domaine achetés" - -#: assets/pages/StatisticsPage.tsx:92 -msgid "" -"This value is based on the status code of the HTTP response from the " -"providers following the domain order." -msgstr "" -"Cette valeur est basée sur le code d'état de la réponse HTTP des Providers " -"suivant l'achat du domaine." - -#: assets/pages/StatisticsPage.tsx:95 -msgid "Success rate" -msgstr "Taux de succès" - -#: assets/pages/LoginPage.tsx:33 -msgid "Create an account" -msgstr "Créer un compte" - #: assets/pages/UserPage.tsx:18 msgid "Username" msgstr "Nom d'utilisateur" @@ -581,11 +611,6 @@ msgstr "Nom d'utilisateur" msgid "Roles" msgstr "Rôles" -#: assets/pages/TextPage.tsx:26 -#, javascript-format -msgid "📝 Please create the /public/content/${ resource } file." -msgstr "📝 Veuillez créer le fichier /public/content/${ resource }." - #: assets/utils/functions/rdapTranslation.ts:7 msgid "Registrant" msgstr "Registrant" @@ -1228,31 +1253,6 @@ msgstr "" "Le domaine est libre mais il peut être premium. Son prix est variable d'un " "domaine à l'autre" -#: assets/App.tsx:101 -msgid "TOS" -msgstr "CGU" - -#: assets/App.tsx:102 -msgid "Privacy Policy" -msgstr "Politique de confidentialité" - -#: assets/App.tsx:103 -msgid "FAQ" -msgstr "FAQ" - -#: assets/App.tsx:105 -msgid "Documentation" -msgstr "Documentation" - -#: assets/App.tsx:108 -#, javascript-format -msgid "" -"${ ProjectLink } is an open source project distributed under the " -"${ LicenseLink } license." -msgstr "" -"${ ProjectLink } est un projet open source distribué sous licence " -"${ LicenseLink }." - #, fuzzy #~ msgid "Tracked Domains" #~ msgstr "Noms de domaine suivis" diff --git a/translations/translations.pot b/translations/translations.pot index f16e03b..30df91e 100644 --- a/translations/translations.pot +++ b/translations/translations.pot @@ -3,6 +3,29 @@ msgstr "" "Content-Type: text/plain; charset=utf-8\n" "Plural-Forms: nplurals=2; plural=(n!=1);\n" +#: assets/App.tsx:101 +msgid "TOS" +msgstr "" + +#: assets/App.tsx:102 +msgid "Privacy Policy" +msgstr "" + +#: assets/App.tsx:103 +msgid "FAQ" +msgstr "" + +#: assets/App.tsx:105 +msgid "Documentation" +msgstr "" + +#: assets/App.tsx:108 +#, javascript-format +msgid "" +"${ ProjectLink } is an open source project distributed under the ${ " +"LicenseLink } license." +msgstr "" + #: assets/components/LoginForm.tsx:52 #: assets/components/RegisterForm.tsx:39 msgid "Email address" @@ -19,9 +42,13 @@ msgstr "" #: assets/components/tracking/connector/ConnectorForm.tsx:84 #: assets/components/tracking/connector/ConnectorForm.tsx:92 #: assets/components/tracking/connector/ConnectorForm.tsx:122 -#: assets/components/tracking/connector/ConnectorForm.tsx:142 -#: assets/components/tracking/connector/ConnectorForm.tsx:156 -#: assets/components/tracking/connector/ConnectorForm.tsx:165 +#: assets/components/tracking/connector/ConnectorForm.tsx:146 +#: assets/components/tracking/connector/ConnectorForm.tsx:152 +#: assets/components/tracking/connector/ConnectorForm.tsx:162 +#: assets/components/tracking/connector/ConnectorForm.tsx:182 +#: assets/components/tracking/connector/ConnectorForm.tsx:213 +#: assets/components/tracking/connector/ConnectorForm.tsx:227 +#: assets/components/tracking/connector/ConnectorForm.tsx:236 #: assets/components/tracking/watchlist/WatchlistForm.tsx:115 #: assets/components/tracking/watchlist/WatchlistForm.tsx:212 msgid "Required" @@ -40,21 +67,9 @@ msgstr "" msgid "Log in with SSO" msgstr "" -#: assets/components/search/DomainResult.tsx:45 -msgid "EPP Status Codes" -msgstr "" - -#: assets/components/search/DomainResult.tsx:61 -msgid "Timeline" -msgstr "" - -#: assets/components/search/DomainResult.tsx:68 -msgid "Entities" -msgstr "" - -#: assets/components/search/DomainSearchBar.tsx:23 -#: assets/components/tracking/watchlist/WatchlistForm.tsx:118 -msgid "This domain name does not appear to be valid" +#: assets/components/RegisterForm.tsx:56 +#: assets/pages/LoginPage.tsx:25 +msgid "Register" msgstr "" #: assets/components/search/DomainLifecycleSteps.tsx:15 @@ -74,253 +89,21 @@ msgstr "" msgid "Pending Delete" msgstr "" -#: assets/components/tracking/connector/ConnectorForm.tsx:40 -msgid "Provider" +#: assets/components/search/DomainResult.tsx:45 +msgid "EPP Status Codes" msgstr "" -#: assets/components/tracking/connector/ConnectorForm.tsx:47 -msgid "Please select a Provider" +#: assets/components/search/DomainResult.tsx:61 +msgid "Timeline" msgstr "" -#: assets/components/tracking/connector/ConnectorForm.tsx:75 -msgid "OVH Endpoint" +#: assets/components/search/DomainResult.tsx:68 +msgid "Entities" msgstr "" -#: assets/components/tracking/connector/ConnectorForm.tsx:82 -msgid "OVH subsidiary" -msgstr "" - -#: assets/components/tracking/connector/ConnectorForm.tsx:90 -msgid "OVH pricing mode" -msgstr "" - -#: assets/components/tracking/connector/ConnectorForm.tsx:95 -msgid "Confirm pricing mode" -msgstr "" - -#: assets/components/tracking/connector/ConnectorForm.tsx:96 -msgid "" -"Are you sure about this setting? This may result in additional charges from " -"the API Provider" -msgstr "" - -#: assets/components/tracking/connector/ConnectorForm.tsx:120 -msgid "Personal Access Token (PAT)" -msgstr "" - -#: assets/components/tracking/connector/ConnectorForm.tsx:126 -msgid "Organization sharing ID" -msgstr "" - -#: assets/components/tracking/connector/ConnectorForm.tsx:129 -msgid "It indicates the organization that will pay for the ordered product" -msgstr "" - -#: assets/components/tracking/connector/ConnectorForm.tsx:140 -msgid "API Terms of Service" -msgstr "" - -#: assets/components/tracking/connector/ConnectorForm.tsx:148 -msgid "" -"I have read and accepted the conditions of use of the Provider API, " -"accessible from this hyperlink" -msgstr "" - -#: assets/components/tracking/connector/ConnectorForm.tsx:154 -msgid "Legal age" -msgstr "" - -#: assets/components/tracking/connector/ConnectorForm.tsx:159 -msgid "I am of the minimum age required to consent to these conditions" -msgstr "" - -#: assets/components/tracking/connector/ConnectorForm.tsx:163 -msgid "Withdrawal period" -msgstr "" - -#: assets/components/tracking/connector/ConnectorForm.tsx:168 -msgid "" -"I waive my right of withdrawal regarding the purchase of domain names via " -"the Provider's API" -msgstr "" - -#: assets/components/tracking/connector/ConnectorForm.tsx:176 -#: assets/components/tracking/watchlist/WatchlistForm.tsx:252 -msgid "Create" -msgstr "" - -#: assets/components/tracking/connector/ConnectorForm.tsx:179 -#: assets/components/tracking/watchlist/WatchlistForm.tsx:255 -msgid "Reset" -msgstr "" - -#: assets/components/tracking/connector/ConnectorsList.tsx:18 -msgid "" -"An error occurred while deleting the Connector. Make sure it is not used in " -"any Watchlist" -msgstr "" - -#: assets/components/tracking/connector/ConnectorsList.tsx:25 -#, javascript-format -msgid "Connector ${ connector.provider }" -msgstr "" - -#: assets/components/tracking/connector/ConnectorsList.tsx:28 -msgid "Delete the Connector" -msgstr "" - -#: assets/components/tracking/connector/ConnectorsList.tsx:29 -msgid "Are you sure to delete this Connector?" -msgstr "" - -#: assets/components/tracking/connector/ConnectorsList.tsx:31 -#: assets/components/tracking/watchlist/DeleteWatchlistButton.tsx:15 -msgid "Yes" -msgstr "" - -#: assets/components/tracking/connector/ConnectorsList.tsx:32 -#: assets/components/tracking/watchlist/DeleteWatchlistButton.tsx:16 -msgid "No" -msgstr "" - -#: assets/components/tracking/watchlist/WatchlistForm.tsx:72 -msgid "Name" -msgstr "" - -#: assets/components/tracking/watchlist/WatchlistForm.tsx:83 -msgid "Watchlist Name" -msgstr "" - -#: assets/components/tracking/watchlist/WatchlistForm.tsx:84 -msgid "Naming the Watchlist makes it easier to find in the list below." -msgstr "" - -#: assets/components/tracking/watchlist/WatchlistForm.tsx:95 -msgid "At least one domain name" -msgstr "" - -#: assets/components/tracking/watchlist/WatchlistCard.tsx:29 -#: assets/components/tracking/watchlist/WatchlistForm.tsx:106 -msgid "Domain names" -msgstr "" - -#: assets/components/tracking/watchlist/WatchlistForm.tsx:124 -msgid "Domain name" -msgstr "" - -#: assets/components/tracking/watchlist/WatchlistForm.tsx:141 -msgid "Add a Domain name" -msgstr "" - -#: assets/components/tracking/watchlist/WatchlistCard.tsx:33 -#: assets/components/tracking/watchlist/WatchlistForm.tsx:148 -msgid "Tracked events" -msgstr "" - -#: assets/components/tracking/watchlist/WatchlistForm.tsx:150 -msgid "At least one trigger" -msgstr "" - -#: assets/components/tracking/watchlist/WatchlistForm.tsx:173 -#: assets/components/tracking/watchlist/WatchlistForm.tsx:187 -msgid "Connector" -msgstr "" - -#: assets/components/tracking/watchlist/WatchlistForm.tsx:183 -msgid "" -"Please make sure the connector information is valid to purchase a domain " -"that may be available soon." -msgstr "" - -#: assets/components/tracking/watchlist/WatchlistForm.tsx:203 -msgid "DSN" -msgstr "" - -#: assets/components/tracking/watchlist/WatchlistForm.tsx:215 -msgid "This DSN does not appear to be valid" -msgstr "" - -#: assets/components/tracking/watchlist/WatchlistForm.tsx:233 -msgid "Check out this link to the Symfony documentation to help you build the DSN" -msgstr "" - -#: assets/components/tracking/watchlist/WatchlistForm.tsx:242 -msgid "Add a Webhook" -msgstr "" - -#: assets/components/tracking/watchlist/WatchlistForm.tsx:252 -msgid "Update" -msgstr "" - -#: assets/components/tracking/watchlist/UpdateWatchlistButton.tsx:31 -msgid "Edit the Watchlist" -msgstr "" - -#: assets/components/tracking/watchlist/UpdateWatchlistButton.tsx:44 -msgid "Update a Watchlist" -msgstr "" - -#: assets/components/tracking/watchlist/UpdateWatchlistButton.tsx:54 -msgid "Cancel" -msgstr "" - -#: assets/components/tracking/watchlist/diagram/ViewDiagramWatchlistButton.tsx:39 -msgid "View the Watchlist Entity Diagram" -msgstr "" - -#: assets/components/tracking/watchlist/diagram/ViewDiagramWatchlistButton.tsx:44 -msgid "Watchlist Entity Diagram" -msgstr "" - -#: assets/components/tracking/watchlist/diagram/watchlistToEdges.tsx:37 -msgid "Registry" -msgstr "" - -#: assets/components/tracking/watchlist/diagram/watchlistToNodes.tsx:30 -#, javascript-format -msgid ".${ tld.tld } Registry" -msgstr "" - -#: assets/components/tracking/watchlist/CalendarWatchlistButton.tsx:14 -msgid "QR Code for iCalendar export" -msgstr "" - -#: assets/components/tracking/watchlist/CalendarWatchlistButton.tsx:17 -msgid "Export events to iCalendar format" -msgstr "" - -#: assets/components/tracking/watchlist/DeleteWatchlistButton.tsx:12 -#: assets/components/tracking/watchlist/DeleteWatchlistButton.tsx:19 -msgid "Delete the Watchlist" -msgstr "" - -#: assets/components/tracking/watchlist/DeleteWatchlistButton.tsx:13 -msgid "Are you sure to delete this Watchlist?" -msgstr "" - -#: assets/components/Sider.tsx:40 -#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:46 -msgid "Domain" -msgstr "" - -#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:50 -msgid "Expiration date" -msgstr "" - -#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:54 -msgid "Status" -msgstr "" - -#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:58 -msgid "Updated at" -msgstr "" - -#: assets/components/tracking/watchlist/WatchlistCard.tsx:47 -msgid "This Watchlist is not linked to a Connector." -msgstr "" - -#: assets/components/tracking/watchlist/WatchlistCard.tsx:52 -msgid "Watchlist" +#: assets/components/search/DomainSearchBar.tsx:23 +#: assets/components/tracking/watchlist/WatchlistForm.tsx:118 +msgid "This domain name does not appear to be valid" msgstr "" #: assets/components/Sider.tsx:28 @@ -331,6 +114,11 @@ msgstr "" msgid "Search" msgstr "" +#: assets/components/Sider.tsx:40 +#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:46 +msgid "Domain" +msgstr "" + #: assets/components/Sider.tsx:41 msgid "Domain Finder" msgstr "" @@ -391,9 +179,313 @@ msgstr "" msgid "Log in" msgstr "" -#: assets/components/RegisterForm.tsx:56 -#: assets/pages/LoginPage.tsx:25 -msgid "Register" +#: assets/components/tracking/connector/ConnectorForm.tsx:40 +msgid "Provider" +msgstr "" + +#: assets/components/tracking/connector/ConnectorForm.tsx:47 +msgid "Please select a Provider" +msgstr "" + +#: assets/components/tracking/connector/ConnectorForm.tsx:75 +msgid "OVH Endpoint" +msgstr "" + +#: assets/components/tracking/connector/ConnectorForm.tsx:82 +msgid "OVH subsidiary" +msgstr "" + +#: assets/components/tracking/connector/ConnectorForm.tsx:90 +msgid "OVH pricing mode" +msgstr "" + +#: assets/components/tracking/connector/ConnectorForm.tsx:95 +msgid "Confirm pricing mode" +msgstr "" + +#: assets/components/tracking/connector/ConnectorForm.tsx:96 +msgid "" +"Are you sure about this setting? This may result in additional charges from " +"the API Provider" +msgstr "" + +#: assets/components/tracking/connector/ConnectorForm.tsx:120 +msgid "Personal Access Token (PAT)" +msgstr "" + +#: assets/components/tracking/connector/ConnectorForm.tsx:126 +msgid "Organization sharing ID" +msgstr "" + +#: assets/components/tracking/connector/ConnectorForm.tsx:129 +msgid "It indicates the organization that will pay for the ordered product" +msgstr "" + +#: assets/components/tracking/connector/ConnectorForm.tsx:138 +msgid "" +"This provider does not provide a list of supported TLD. Please double check " +"if the domain you want to register is supported." +msgstr "" + +#: assets/components/tracking/connector/ConnectorForm.tsx:142 +msgid "AutoDNS Username" +msgstr "" + +#: assets/components/tracking/connector/ConnectorForm.tsx:145 +msgid "" +"Attention: AutoDNS do not support 2-Factor Authentication on API Users for " +"automated systems" +msgstr "" + +#: assets/components/tracking/connector/ConnectorForm.tsx:150 +msgid "AutoDNS Password" +msgstr "" + +#: assets/components/tracking/connector/ConnectorForm.tsx:157 +msgid "Domain Contact Handle ID" +msgstr "" + +#: assets/components/tracking/connector/ConnectorForm.tsx:160 +msgid "The Contact ID for ownership of registered Domains. " +msgstr "" + +#: assets/components/tracking/connector/ConnectorForm.tsx:161 +msgid "You got from this page" +msgstr "" + +#: assets/components/tracking/connector/ConnectorForm.tsx:168 +msgid "Context Value" +msgstr "" + +#: assets/components/tracking/connector/ConnectorForm.tsx:171 +msgid "If you not sure, use the default value 4" +msgstr "" + +#: assets/components/tracking/connector/ConnectorForm.tsx:179 +msgid "Owner confirmation" +msgstr "" + +#: assets/components/tracking/connector/ConnectorForm.tsx:185 +msgid "Owner confirms his consent of domain order jobs" +msgstr "" + +#: assets/components/tracking/connector/ConnectorForm.tsx:193 +#: assets/pages/UserPage.tsx:18 +msgid "Username" +msgstr "" + +#: assets/components/tracking/connector/ConnectorForm.tsx:199 +msgid "API key" +msgstr "" + +#: assets/components/tracking/connector/ConnectorForm.tsx:211 +msgid "API Terms of Service" +msgstr "" + +#: assets/components/tracking/connector/ConnectorForm.tsx:219 +msgid "" +"I have read and accepted the conditions of use of the Provider API, " +"accessible from this hyperlink" +msgstr "" + +#: assets/components/tracking/connector/ConnectorForm.tsx:225 +msgid "Legal age" +msgstr "" + +#: assets/components/tracking/connector/ConnectorForm.tsx:230 +msgid "I am of the minimum age required to consent to these conditions" +msgstr "" + +#: assets/components/tracking/connector/ConnectorForm.tsx:234 +msgid "Withdrawal period" +msgstr "" + +#: assets/components/tracking/connector/ConnectorForm.tsx:239 +msgid "" +"I waive my right of withdrawal regarding the purchase of domain names via " +"the Provider's API" +msgstr "" + +#: assets/components/tracking/connector/ConnectorForm.tsx:247 +#: assets/components/tracking/watchlist/WatchlistForm.tsx:252 +msgid "Create" +msgstr "" + +#: assets/components/tracking/connector/ConnectorForm.tsx:250 +#: assets/components/tracking/watchlist/WatchlistForm.tsx:255 +msgid "Reset" +msgstr "" + +#: assets/components/tracking/connector/ConnectorsList.tsx:18 +msgid "" +"An error occurred while deleting the Connector. Make sure it is not used in " +"any Watchlist" +msgstr "" + +#: assets/components/tracking/connector/ConnectorsList.tsx:25 +#, javascript-format +msgid "Connector ${ connector.provider }" +msgstr "" + +#: assets/components/tracking/connector/ConnectorsList.tsx:28 +msgid "Delete the Connector" +msgstr "" + +#: assets/components/tracking/connector/ConnectorsList.tsx:29 +msgid "Are you sure to delete this Connector?" +msgstr "" + +#: assets/components/tracking/connector/ConnectorsList.tsx:31 +#: assets/components/tracking/watchlist/DeleteWatchlistButton.tsx:15 +msgid "Yes" +msgstr "" + +#: assets/components/tracking/connector/ConnectorsList.tsx:32 +#: assets/components/tracking/watchlist/DeleteWatchlistButton.tsx:16 +msgid "No" +msgstr "" + +#: assets/components/tracking/watchlist/CalendarWatchlistButton.tsx:14 +msgid "QR Code for iCalendar export" +msgstr "" + +#: assets/components/tracking/watchlist/CalendarWatchlistButton.tsx:17 +msgid "Export events to iCalendar format" +msgstr "" + +#: assets/components/tracking/watchlist/DeleteWatchlistButton.tsx:12 +#: assets/components/tracking/watchlist/DeleteWatchlistButton.tsx:19 +msgid "Delete the Watchlist" +msgstr "" + +#: assets/components/tracking/watchlist/DeleteWatchlistButton.tsx:13 +msgid "Are you sure to delete this Watchlist?" +msgstr "" + +#: assets/components/tracking/watchlist/diagram/ViewDiagramWatchlistButton.tsx:39 +msgid "View the Watchlist Entity Diagram" +msgstr "" + +#: assets/components/tracking/watchlist/diagram/ViewDiagramWatchlistButton.tsx:44 +msgid "Watchlist Entity Diagram" +msgstr "" + +#: assets/components/tracking/watchlist/diagram/watchlistToEdges.tsx:37 +msgid "Registry" +msgstr "" + +#: assets/components/tracking/watchlist/diagram/watchlistToNodes.tsx:30 +#, javascript-format +msgid ".${ tld.tld } Registry" +msgstr "" + +#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:50 +msgid "Expiration date" +msgstr "" + +#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:54 +msgid "Status" +msgstr "" + +#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:58 +msgid "Updated at" +msgstr "" + +#: assets/components/tracking/watchlist/UpdateWatchlistButton.tsx:31 +msgid "Edit the Watchlist" +msgstr "" + +#: assets/components/tracking/watchlist/UpdateWatchlistButton.tsx:44 +msgid "Update a Watchlist" +msgstr "" + +#: assets/components/tracking/watchlist/UpdateWatchlistButton.tsx:54 +msgid "Cancel" +msgstr "" + +#: assets/components/tracking/watchlist/WatchlistCard.tsx:29 +#: assets/components/tracking/watchlist/WatchlistForm.tsx:106 +msgid "Domain names" +msgstr "" + +#: assets/components/tracking/watchlist/WatchlistCard.tsx:33 +#: assets/components/tracking/watchlist/WatchlistForm.tsx:148 +msgid "Tracked events" +msgstr "" + +#: assets/components/tracking/watchlist/WatchlistCard.tsx:47 +msgid "This Watchlist is not linked to a Connector." +msgstr "" + +#: assets/components/tracking/watchlist/WatchlistCard.tsx:52 +msgid "Watchlist" +msgstr "" + +#: assets/components/tracking/watchlist/WatchlistForm.tsx:72 +msgid "Name" +msgstr "" + +#: assets/components/tracking/watchlist/WatchlistForm.tsx:83 +msgid "Watchlist Name" +msgstr "" + +#: assets/components/tracking/watchlist/WatchlistForm.tsx:84 +msgid "Naming the Watchlist makes it easier to find in the list below." +msgstr "" + +#: assets/components/tracking/watchlist/WatchlistForm.tsx:95 +msgid "At least one domain name" +msgstr "" + +#: assets/components/tracking/watchlist/WatchlistForm.tsx:124 +msgid "Domain name" +msgstr "" + +#: assets/components/tracking/watchlist/WatchlistForm.tsx:141 +msgid "Add a Domain name" +msgstr "" + +#: assets/components/tracking/watchlist/WatchlistForm.tsx:150 +msgid "At least one trigger" +msgstr "" + +#: assets/components/tracking/watchlist/WatchlistForm.tsx:173 +#: assets/components/tracking/watchlist/WatchlistForm.tsx:187 +msgid "Connector" +msgstr "" + +#: assets/components/tracking/watchlist/WatchlistForm.tsx:183 +msgid "" +"Please make sure the connector information is valid to purchase a domain " +"that may be available soon." +msgstr "" + +#: assets/components/tracking/watchlist/WatchlistForm.tsx:203 +msgid "DSN" +msgstr "" + +#: assets/components/tracking/watchlist/WatchlistForm.tsx:215 +msgid "This DSN does not appear to be valid" +msgstr "" + +#: assets/components/tracking/watchlist/WatchlistForm.tsx:233 +msgid "Check out this link to the Symfony documentation to help you build the DSN" +msgstr "" + +#: assets/components/tracking/watchlist/WatchlistForm.tsx:242 +msgid "Add a Webhook" +msgstr "" + +#: assets/components/tracking/watchlist/WatchlistForm.tsx:252 +msgid "Update" +msgstr "" + +#: assets/pages/LoginPage.tsx:33 +msgid "Create an account" +msgstr "" + +#: assets/pages/NotFoundPage.tsx:10 +msgid "Sorry, the page you visited does not exist." msgstr "" #: assets/pages/search/DomainSearchPage.tsx:18 @@ -475,6 +567,42 @@ msgid "" "their country of origin." msgstr "" +#: assets/pages/StatisticsPage.tsx:34 +msgid "RDAP queries" +msgstr "" + +#: assets/pages/StatisticsPage.tsx:43 +msgid "Alerts sent" +msgstr "" + +#: assets/pages/StatisticsPage.tsx:57 +msgid "Domain names in database" +msgstr "" + +#: assets/pages/StatisticsPage.tsx:68 +#: assets/pages/tracking/WatchlistPage.tsx:111 +msgid "Tracked domain names" +msgstr "" + +#: assets/pages/StatisticsPage.tsx:82 +msgid "Purchased domain names" +msgstr "" + +#: assets/pages/StatisticsPage.tsx:92 +msgid "" +"This value is based on the status code of the HTTP response from the " +"providers following the domain order." +msgstr "" + +#: assets/pages/StatisticsPage.tsx:95 +msgid "Success rate" +msgstr "" + +#: assets/pages/TextPage.tsx:26 +#, javascript-format +msgid "📝 Please create the /public/content/${ resource } file." +msgstr "" + #: assets/pages/tracking/ConnectorsPage.tsx:20 msgid "Connector created !" msgstr "" @@ -495,58 +623,10 @@ msgstr "" msgid "Create a Watchlist" msgstr "" -#: assets/pages/StatisticsPage.tsx:68 -#: assets/pages/tracking/WatchlistPage.tsx:111 -msgid "Tracked domain names" -msgstr "" - -#: assets/pages/NotFoundPage.tsx:10 -msgid "Sorry, the page you visited does not exist." -msgstr "" - -#: assets/pages/StatisticsPage.tsx:34 -msgid "RDAP queries" -msgstr "" - -#: assets/pages/StatisticsPage.tsx:43 -msgid "Alerts sent" -msgstr "" - -#: assets/pages/StatisticsPage.tsx:57 -msgid "Domain names in database" -msgstr "" - -#: assets/pages/StatisticsPage.tsx:82 -msgid "Purchased domain names" -msgstr "" - -#: assets/pages/StatisticsPage.tsx:92 -msgid "" -"This value is based on the status code of the HTTP response from the " -"providers following the domain order." -msgstr "" - -#: assets/pages/StatisticsPage.tsx:95 -msgid "Success rate" -msgstr "" - -#: assets/pages/LoginPage.tsx:33 -msgid "Create an account" -msgstr "" - -#: assets/pages/UserPage.tsx:18 -msgid "Username" -msgstr "" - #: assets/pages/UserPage.tsx:21 msgid "Roles" msgstr "" -#: assets/pages/TextPage.tsx:26 -#, javascript-format -msgid "📝 Please create the /public/content/${ resource } file." -msgstr "" - #: assets/utils/functions/rdapTranslation.ts:7 msgid "Registrant" msgstr "" @@ -1013,6 +1093,18 @@ msgid "" "Provider's website" msgstr "" +#: assets/utils/providers/index.tsx:20 +msgid "" +"Retreive an API key and whitelist this instance's IP address on Namecheap's " +"website" +msgstr "" + +#: assets/utils/providers/index.tsx:24 +msgid "" +"Because of some limitations in API of AutoDNS, we suggest to create an " +"dedicated user for API with limited rights." +msgstr "" + #: assets/utils/providers/ovh.tsx:5 msgid "Application key" msgstr "" @@ -1042,26 +1134,3 @@ msgid "" "The domain is free but can be premium. Its price varies from one domain to " "another" msgstr "" - -#: assets/App.tsx:101 -msgid "TOS" -msgstr "" - -#: assets/App.tsx:102 -msgid "Privacy Policy" -msgstr "" - -#: assets/App.tsx:103 -msgid "FAQ" -msgstr "" - -#: assets/App.tsx:105 -msgid "Documentation" -msgstr "" - -#: assets/App.tsx:108 -#, javascript-format -msgid "" -"${ ProjectLink } is an open source project distributed under the ${ " -"LicenseLink } license." -msgstr ""