]> git.immae.eu Git - github/wallabag/wallabag.git/commitdiff
Merge remote-tracking branch 'origin/master' into 2.2
authorJeremy Benoist <jeremy.benoist@gmail.com>
Thu, 3 Nov 2016 15:41:29 +0000 (16:41 +0100)
committerJeremy Benoist <jeremy.benoist@gmail.com>
Thu, 3 Nov 2016 15:41:29 +0000 (16:41 +0100)
21 files changed:
1  2 
app/config/config.yml
src/Wallabag/ApiBundle/Controller/EntryRestController.php
src/Wallabag/ApiBundle/Controller/WallabagRestController.php
src/Wallabag/ApiBundle/Resources/config/routing_rest.yml
src/Wallabag/CoreBundle/Controller/TagController.php
src/Wallabag/CoreBundle/Resources/config/services.yml
src/Wallabag/CoreBundle/Resources/translations/messages.da.yml
src/Wallabag/CoreBundle/Resources/translations/messages.de.yml
src/Wallabag/CoreBundle/Resources/translations/messages.en.yml
src/Wallabag/CoreBundle/Resources/translations/messages.es.yml
src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml
src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml
src/Wallabag/CoreBundle/Resources/translations/messages.it.yml
src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml
src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml
src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml
src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml
src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml
src/Wallabag/ImportBundle/Command/ImportCommand.php
src/Wallabag/UserBundle/Resources/config/services.yml
tests/Wallabag/ApiBundle/Controller/EntryRestControllerTest.php

diff --combined app/config/config.yml
index dfb0e3b27a181b4a313c248b95226a2a18400b3f,81d1728a3b9193b3c08d75bb6a3eb366f6235c30..7f24244df427a6336295b29a40a590129b672993
@@@ -44,13 -44,15 +44,15 @@@ wallabag_core
          es: 'Español'
          oc: 'Occitan'
          it: 'Italiano'
+         pt: 'Português'
      items_on_page: 12
      theme: material
      language: '%locale%'
      rss_limit: 50
      reading_speed: 1
      cache_lifetime: 10
-     fetching_error_message: "wallabag can't retrieve contents for this article. Please report this issue to us."
+     fetching_error_message: |
+         wallabag can't retrieve contents for this article. Please <a href="http://doc.wallabag.org/en/master/user/errors_during_fetching.html#how-can-i-help-to-fix-that">troubleshoot this issue</a>.
  
  wallabag_user:
      registration_enabled: "%fosuser_registration%"
@@@ -76,7 -78,7 +78,7 @@@ doctrine
          dbname: "%database_name%"
          user: "%database_user%"
          password: "%database_password%"
 -        charset: UTF8
 +        charset: "%database_charset%"
          path: "%database_path%"
          unix_socket: "%database_socket%"
          server_version: 5.6
@@@ -113,26 -115,12 +115,26 @@@ swiftmailer
  fos_rest:
      param_fetcher_listener: true
      body_listener: true
 -    format_listener: true
      view:
 +        mime_types:
 +            csv:
 +                - 'text/csv'
 +                - 'text/plain'
 +            pdf:
 +                - 'application/pdf'
 +            epub:
 +                - 'application/epub+zip'
 +            mobi:
 +                - 'application/x-mobipocket-ebook'
          view_response_listener: 'force'
          formats:
              xml: true
 -            json : true
 +            json: true
 +            txt: true
 +            csv: true
 +            pdf: true
 +            epub: true
 +            mobi: true
          templating_formats:
              html: true
          force_redirects:
          default_engine: twig
      routing_loader:
          default_format: json
 +    format_listener:
 +        enabled: true
 +        rules:
 +            - { path: "^/api/entries/([0-9]+)/export.(.*)", priorities: ['epub', 'mobi', 'pdf', 'txt', 'csv'], fallback_format: false, prefer_extension: false }
 +            - { path: "^/api", priorities: ['json', 'xml'], fallback_format: false, prefer_extension: false }
 +            - { path: "^/annotations", priorities: ['json', 'xml'], fallback_format: false, prefer_extension: false }
 +            # for an unknown reason, EACH REQUEST goes to FOS\RestBundle\EventListener\FormatListener
 +            # so we need to add custom rule for custom api export but also for all other routes of the application...
 +            - { path: '^/', priorities: ['text/html', '*/*'], fallback_format: html, prefer_extension: false }
  
  nelmio_api_doc:
      sandbox:
          enabled: false
 +    cache:
 +        enabled: true
      name: wallabag API documentation
  
  nelmio_cors:
index 0000000000000000000000000000000000000000,24fa7b3bdaadbe0944f883878ba8358574824349..b3622c62ce6382d496d9c383ac595553125f9d48
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,367 +1,374 @@@
 -
+ <?php
+ namespace Wallabag\ApiBundle\Controller;
+ use Hateoas\Configuration\Route;
+ use Hateoas\Representation\Factory\PagerfantaFactory;
+ use Nelmio\ApiDocBundle\Annotation\ApiDoc;
+ use Symfony\Component\HttpFoundation\Request;
+ use Symfony\Component\HttpFoundation\JsonResponse;
+ use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
+ use Wallabag\CoreBundle\Entity\Entry;
+ use Wallabag\CoreBundle\Entity\Tag;
++use Wallabag\CoreBundle\Event\EntrySavedEvent;
++use Wallabag\CoreBundle\Event\EntryDeletedEvent;
+ class EntryRestController extends WallabagRestController
+ {
+     /**
+      * Check if an entry exist by url.
+      *
+      * @ApiDoc(
+      *       parameters={
+      *          {"name"="url", "dataType"="string", "required"=true, "format"="An url", "description"="Url to check if it exists"},
+      *          {"name"="urls", "dataType"="string", "required"=false, "format"="An array of urls (?urls[]=http...&urls[]=http...)", "description"="Urls (as an array) to check if it exists"}
+      *       }
+      * )
+      *
+      * @return JsonResponse
+      */
+     public function getEntriesExistsAction(Request $request)
+     {
+         $this->validateAuthentication();
+         $urls = $request->query->get('urls', []);
+         // handle multiple urls first
+         if (!empty($urls)) {
+             $results = [];
+             foreach ($urls as $url) {
+                 $res = $this->getDoctrine()
+                     ->getRepository('WallabagCoreBundle:Entry')
+                     ->findByUrlAndUserId($url, $this->getUser()->getId());
+                 $results[$url] = false === $res ? false : true;
+             }
+             $json = $this->get('serializer')->serialize($results, 'json');
+             return (new JsonResponse())->setJson($json);
+         }
+         // let's see if it is a simple url?
+         $url = $request->query->get('url', '');
+         if (empty($url)) {
+             throw $this->createAccessDeniedException('URL is empty?, logged user id: '.$this->getUser()->getId());
+         }
+         $res = $this->getDoctrine()
+             ->getRepository('WallabagCoreBundle:Entry')
+             ->findByUrlAndUserId($url, $this->getUser()->getId());
+         $exists = false === $res ? false : true;
+         $json = $this->get('serializer')->serialize(['exists' => $exists], 'json');
+         return (new JsonResponse())->setJson($json);
+     }
+     /**
+      * Retrieve all entries. It could be filtered by many options.
+      *
+      * @ApiDoc(
+      *       parameters={
+      *          {"name"="archive", "dataType"="integer", "required"=false, "format"="1 or 0, all entries by default", "description"="filter by archived status."},
+      *          {"name"="starred", "dataType"="integer", "required"=false, "format"="1 or 0, all entries by default", "description"="filter by starred status."},
+      *          {"name"="sort", "dataType"="string", "required"=false, "format"="'created' or 'updated', default 'created'", "description"="sort entries by date."},
+      *          {"name"="order", "dataType"="string", "required"=false, "format"="'asc' or 'desc', default 'desc'", "description"="order of sort."},
+      *          {"name"="page", "dataType"="integer", "required"=false, "format"="default '1'", "description"="what page you want."},
+      *          {"name"="perPage", "dataType"="integer", "required"=false, "format"="default'30'", "description"="results per page."},
+      *          {"name"="tags", "dataType"="string", "required"=false, "format"="api,rest", "description"="a list of tags url encoded. Will returns entries that matches ALL tags."},
+      *          {"name"="since", "dataType"="integer", "required"=false, "format"="default '0'", "description"="The timestamp since when you want entries updated."},
+      *       }
+      * )
+      *
+      * @return JsonResponse
+      */
+     public function getEntriesAction(Request $request)
+     {
+         $this->validateAuthentication();
+         $isArchived = (null === $request->query->get('archive')) ? null : (bool) $request->query->get('archive');
+         $isStarred = (null === $request->query->get('starred')) ? null : (bool) $request->query->get('starred');
+         $sort = $request->query->get('sort', 'created');
+         $order = $request->query->get('order', 'desc');
+         $page = (int) $request->query->get('page', 1);
+         $perPage = (int) $request->query->get('perPage', 30);
+         $tags = $request->query->get('tags', '');
+         $since = $request->query->get('since', 0);
+         $pager = $this->getDoctrine()
+             ->getRepository('WallabagCoreBundle:Entry')
+             ->findEntries($this->getUser()->getId(), $isArchived, $isStarred, $sort, $order, $since, $tags);
+         $pager->setCurrentPage($page);
+         $pager->setMaxPerPage($perPage);
+         $pagerfantaFactory = new PagerfantaFactory('page', 'perPage');
+         $paginatedCollection = $pagerfantaFactory->createRepresentation(
+             $pager,
+             new Route(
+                 'api_get_entries',
+                 [
+                     'archive' => $isArchived,
+                     'starred' => $isStarred,
+                     'sort' => $sort,
+                     'order' => $order,
+                     'page' => $page,
+                     'perPage' => $perPage,
+                     'tags' => $tags,
+                     'since' => $since,
+                 ],
+                 UrlGeneratorInterface::ABSOLUTE_URL
+             )
+         );
+         $json = $this->get('serializer')->serialize($paginatedCollection, 'json');
+         return (new JsonResponse())->setJson($json);
+     }
+     /**
+      * Retrieve a single entry.
+      *
+      * @ApiDoc(
+      *      requirements={
+      *          {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"}
+      *      }
+      * )
+      *
+      * @return JsonResponse
+      */
+     public function getEntryAction(Entry $entry)
+     {
+         $this->validateAuthentication();
+         $this->validateUserAccess($entry->getUser()->getId());
+         $json = $this->get('serializer')->serialize($entry, 'json');
+         return (new JsonResponse())->setJson($json);
+     }
+     /**
+      * Create an entry.
+      *
+      * @ApiDoc(
+      *       parameters={
+      *          {"name"="url", "dataType"="string", "required"=true, "format"="http://www.test.com/article.html", "description"="Url for the entry."},
+      *          {"name"="title", "dataType"="string", "required"=false, "description"="Optional, we'll get the title from the page."},
+      *          {"name"="tags", "dataType"="string", "required"=false, "format"="tag1,tag2,tag3", "description"="a comma-separated list of tags."},
+      *          {"name"="starred", "dataType"="integer", "required"=false, "format"="1 or 0", "description"="entry already starred"},
+      *          {"name"="archive", "dataType"="integer", "required"=false, "format"="1 or 0", "description"="entry already archived"},
+      *       }
+      * )
+      *
+      * @return JsonResponse
+      */
+     public function postEntriesAction(Request $request)
+     {
+         $this->validateAuthentication();
+         $url = $request->request->get('url');
+         $title = $request->request->get('title');
+         $isArchived = $request->request->get('archive');
+         $isStarred = $request->request->get('starred');
+         $entry = $this->get('wallabag_core.entry_repository')->findByUrlAndUserId($url, $this->getUser()->getId());
+         if (false === $entry) {
+             $entry = $this->get('wallabag_core.content_proxy')->updateEntry(
+                 new Entry($this->getUser()),
+                 $url
+             );
+         }
+         if (!is_null($title)) {
+             $entry->setTitle($title);
+         }
+         $tags = $request->request->get('tags', '');
+         if (!empty($tags)) {
+             $this->get('wallabag_core.content_proxy')->assignTagsToEntry($entry, $tags);
+         }
+         if (!is_null($isStarred)) {
+             $entry->setStarred((bool) $isStarred);
+         }
+         if (!is_null($isArchived)) {
+             $entry->setArchived((bool) $isArchived);
+         }
+         $em = $this->getDoctrine()->getManager();
+         $em->persist($entry);
+         $em->flush();
++        // entry saved, dispatch event about it!
++        $this->get('event_dispatcher')->dispatch(EntrySavedEvent::NAME, new EntrySavedEvent($entry));
++
+         $json = $this->get('serializer')->serialize($entry, 'json');
+         return (new JsonResponse())->setJson($json);
+     }
+     /**
+      * Change several properties of an entry.
+      *
+      * @ApiDoc(
+      *      requirements={
+      *          {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"}
+      *      },
+      *      parameters={
+      *          {"name"="title", "dataType"="string", "required"=false},
+      *          {"name"="tags", "dataType"="string", "required"=false, "format"="tag1,tag2,tag3", "description"="a comma-separated list of tags."},
+      *          {"name"="archive", "dataType"="integer", "required"=false, "format"="1 or 0", "description"="archived the entry."},
+      *          {"name"="starred", "dataType"="integer", "required"=false, "format"="1 or 0", "description"="starred the entry."},
+      *      }
+      * )
+      *
+      * @return JsonResponse
+      */
+     public function patchEntriesAction(Entry $entry, Request $request)
+     {
+         $this->validateAuthentication();
+         $this->validateUserAccess($entry->getUser()->getId());
+         $title = $request->request->get('title');
+         $isArchived = $request->request->get('archive');
+         $isStarred = $request->request->get('starred');
+         if (!is_null($title)) {
+             $entry->setTitle($title);
+         }
+         if (!is_null($isArchived)) {
+             $entry->setArchived((bool) $isArchived);
+         }
+         if (!is_null($isStarred)) {
+             $entry->setStarred((bool) $isStarred);
+         }
+         $tags = $request->request->get('tags', '');
+         if (!empty($tags)) {
+             $this->get('wallabag_core.content_proxy')->assignTagsToEntry($entry, $tags);
+         }
+         $em = $this->getDoctrine()->getManager();
+         $em->flush();
+         $json = $this->get('serializer')->serialize($entry, 'json');
+         return (new JsonResponse())->setJson($json);
+     }
+     /**
+      * Delete **permanently** an entry.
+      *
+      * @ApiDoc(
+      *      requirements={
+      *          {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"}
+      *      }
+      * )
+      *
+      * @return JsonResponse
+      */
+     public function deleteEntriesAction(Entry $entry)
+     {
+         $this->validateAuthentication();
+         $this->validateUserAccess($entry->getUser()->getId());
+         $em = $this->getDoctrine()->getManager();
+         $em->remove($entry);
+         $em->flush();
++        // entry deleted, dispatch event about it!
++        $this->get('event_dispatcher')->dispatch(EntryDeletedEvent::NAME, new EntryDeletedEvent($entry));
++
+         $json = $this->get('serializer')->serialize($entry, 'json');
+         return (new JsonResponse())->setJson($json);
+     }
+     /**
+      * Retrieve all tags for an entry.
+      *
+      * @ApiDoc(
+      *      requirements={
+      *          {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"}
+      *      }
+      * )
+      *
+      * @return JsonResponse
+      */
+     public function getEntriesTagsAction(Entry $entry)
+     {
+         $this->validateAuthentication();
+         $this->validateUserAccess($entry->getUser()->getId());
+         $json = $this->get('serializer')->serialize($entry->getTags(), 'json');
+         return (new JsonResponse())->setJson($json);
+     }
+     /**
+      * Add one or more tags to an entry.
+      *
+      * @ApiDoc(
+      *      requirements={
+      *          {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"}
+      *      },
+      *      parameters={
+      *          {"name"="tags", "dataType"="string", "required"=false, "format"="tag1,tag2,tag3", "description"="a comma-separated list of tags."},
+      *       }
+      * )
+      *
+      * @return JsonResponse
+      */
+     public function postEntriesTagsAction(Request $request, Entry $entry)
+     {
+         $this->validateAuthentication();
+         $this->validateUserAccess($entry->getUser()->getId());
+         $tags = $request->request->get('tags', '');
+         if (!empty($tags)) {
+             $this->get('wallabag_core.content_proxy')->assignTagsToEntry($entry, $tags);
+         }
+         $em = $this->getDoctrine()->getManager();
+         $em->persist($entry);
+         $em->flush();
+         $json = $this->get('serializer')->serialize($entry, 'json');
+         return (new JsonResponse())->setJson($json);
+     }
+     /**
+      * Permanently remove one tag for an entry.
+      *
+      * @ApiDoc(
+      *      requirements={
+      *          {"name"="tag", "dataType"="integer", "requirement"="\w+", "description"="The tag ID"},
+      *          {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"}
+      *      }
+      * )
+      *
+      * @return JsonResponse
+      */
+     public function deleteEntriesTagsAction(Entry $entry, Tag $tag)
+     {
+         $this->validateAuthentication();
+         $this->validateUserAccess($entry->getUser()->getId());
+         $entry->removeTag($tag);
+         $em = $this->getDoctrine()->getManager();
+         $em->persist($entry);
+         $em->flush();
+         $json = $this->get('serializer')->serialize($entry, 'json');
+         return (new JsonResponse())->setJson($json);
+     }
+ }
index 50652b777e9fe9b9bf9127640193be9b7405cc85,e927a8903a26af16f796fa8016e6dad7322d5b5a..544c1ea936718413658758b5d2507d71c3566a18
  namespace Wallabag\ApiBundle\Controller;
  
  use FOS\RestBundle\Controller\FOSRestController;
- use Hateoas\Configuration\Route as HateoasRoute;
- use Hateoas\Representation\Factory\PagerfantaFactory;
- use Nelmio\ApiDocBundle\Annotation\ApiDoc;
- use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
- use Symfony\Component\HttpFoundation\Request;
- use Symfony\Component\HttpFoundation\JsonResponse;
- use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  use Symfony\Component\Security\Core\Exception\AccessDeniedException;
  use Wallabag\CoreBundle\Entity\Entry;
- use Wallabag\CoreBundle\Entity\Tag;
- use Wallabag\AnnotationBundle\Entity\Annotation;
- use Wallabag\CoreBundle\Event\EntrySavedEvent;
- use Wallabag\CoreBundle\Event\EntryDeletedEvent;
  
  class WallabagRestController extends FOSRestController
  {
-     private function validateAuthentication()
-     {
-         if (false === $this->get('security.authorization_checker')->isGranted('IS_AUTHENTICATED_FULLY')) {
-             throw new AccessDeniedException();
-         }
-     }
-     /**
-      * Check if an entry exist by url.
-      *
-      * @ApiDoc(
-      *       parameters={
-      *          {"name"="url", "dataType"="string", "required"=true, "format"="An url", "description"="Url to check if it exists"},
-      *          {"name"="urls", "dataType"="string", "required"=false, "format"="An array of urls (?urls[]=http...&urls[]=http...)", "description"="Urls (as an array) to check if it exists"}
-      *       }
-      * )
-      *
-      * @return JsonResponse
-      */
-     public function getEntriesExistsAction(Request $request)
-     {
-         $this->validateAuthentication();
-         $urls = $request->query->get('urls', []);
-         // handle multiple urls first
-         if (!empty($urls)) {
-             $results = [];
-             foreach ($urls as $url) {
-                 $res = $this->getDoctrine()
-                     ->getRepository('WallabagCoreBundle:Entry')
-                     ->findByUrlAndUserId($url, $this->getUser()->getId());
-                 $results[$url] = false === $res ? false : true;
-             }
-             $json = $this->get('serializer')->serialize($results, 'json');
-             return (new JsonResponse())->setJson($json);
-         }
-         // let's see if it is a simple url?
-         $url = $request->query->get('url', '');
-         if (empty($url)) {
-             throw $this->createAccessDeniedException('URL is empty?, logged user id: '.$this->getUser()->getId());
-         }
-         $res = $this->getDoctrine()
-             ->getRepository('WallabagCoreBundle:Entry')
-             ->findByUrlAndUserId($url, $this->getUser()->getId());
-         $exists = false === $res ? false : true;
-         $json = $this->get('serializer')->serialize(['exists' => $exists], 'json');
-         return (new JsonResponse())->setJson($json);
-     }
-     /**
-      * Retrieve all entries. It could be filtered by many options.
-      *
-      * @ApiDoc(
-      *       parameters={
-      *          {"name"="archive", "dataType"="integer", "required"=false, "format"="1 or 0, all entries by default", "description"="filter by archived status."},
-      *          {"name"="starred", "dataType"="integer", "required"=false, "format"="1 or 0, all entries by default", "description"="filter by starred status."},
-      *          {"name"="sort", "dataType"="string", "required"=false, "format"="'created' or 'updated', default 'created'", "description"="sort entries by date."},
-      *          {"name"="order", "dataType"="string", "required"=false, "format"="'asc' or 'desc', default 'desc'", "description"="order of sort."},
-      *          {"name"="page", "dataType"="integer", "required"=false, "format"="default '1'", "description"="what page you want."},
-      *          {"name"="perPage", "dataType"="integer", "required"=false, "format"="default'30'", "description"="results per page."},
-      *          {"name"="tags", "dataType"="string", "required"=false, "format"="api,rest", "description"="a list of tags url encoded. Will returns entries that matches ALL tags."},
-      *          {"name"="since", "dataType"="integer", "required"=false, "format"="default '0'", "description"="The timestamp since when you want entries updated."},
-      *       }
-      * )
-      *
-      * @return JsonResponse
-      */
-     public function getEntriesAction(Request $request)
-     {
-         $this->validateAuthentication();
-         $isArchived = (null === $request->query->get('archive')) ? null : (bool) $request->query->get('archive');
-         $isStarred = (null === $request->query->get('starred')) ? null : (bool) $request->query->get('starred');
-         $sort = $request->query->get('sort', 'created');
-         $order = $request->query->get('order', 'desc');
-         $page = (int) $request->query->get('page', 1);
-         $perPage = (int) $request->query->get('perPage', 30);
-         $tags = $request->query->get('tags', '');
-         $since = $request->query->get('since', 0);
-         $pager = $this->getDoctrine()
-             ->getRepository('WallabagCoreBundle:Entry')
-             ->findEntries($this->getUser()->getId(), $isArchived, $isStarred, $sort, $order, $since, $tags);
-         $pager->setCurrentPage($page);
-         $pager->setMaxPerPage($perPage);
-         $pagerfantaFactory = new PagerfantaFactory('page', 'perPage');
-         $paginatedCollection = $pagerfantaFactory->createRepresentation(
-             $pager,
-             new HateoasRoute(
-                 'api_get_entries',
-                 [
-                     'archive' => $isArchived,
-                     'starred' => $isStarred,
-                     'sort' => $sort,
-                     'order' => $order,
-                     'page' => $page,
-                     'perPage' => $perPage,
-                     'tags' => $tags,
-                     'since' => $since,
-                 ],
-                 UrlGeneratorInterface::ABSOLUTE_URL
-             )
-         );
-         $json = $this->get('serializer')->serialize($paginatedCollection, 'json');
-         return (new JsonResponse())->setJson($json);
-     }
-     /**
-      * Retrieve a single entry.
-      *
-      * @ApiDoc(
-      *      requirements={
-      *          {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"}
-      *      }
-      * )
-      *
-      * @return JsonResponse
-      */
-     public function getEntryAction(Entry $entry)
-     {
-         $this->validateAuthentication();
-         $this->validateUserAccess($entry->getUser()->getId());
-         $json = $this->get('serializer')->serialize($entry, 'json');
-         return (new JsonResponse())->setJson($json);
-     }
-     /**
-      * Retrieve a single entry as a predefined format.
-      *
-      * @ApiDoc(
-      *      requirements={
-      *          {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"}
-      *      }
-      * )
-      *
-      * @return Response
-      */
-     public function getEntryExportAction(Entry $entry, Request $request)
-     {
-         $this->validateAuthentication();
-         $this->validateUserAccess($entry->getUser()->getId());
-         return $this->get('wallabag_core.helper.entries_export')
-             ->setEntries($entry)
-             ->updateTitle('entry')
-             ->exportAs($request->attributes->get('_format'));
-     }
-     /**
-      * Create an entry.
-      *
-      * @ApiDoc(
-      *       parameters={
-      *          {"name"="url", "dataType"="string", "required"=true, "format"="http://www.test.com/article.html", "description"="Url for the entry."},
-      *          {"name"="title", "dataType"="string", "required"=false, "description"="Optional, we'll get the title from the page."},
-      *          {"name"="tags", "dataType"="string", "required"=false, "format"="tag1,tag2,tag3", "description"="a comma-separated list of tags."},
-      *          {"name"="starred", "dataType"="integer", "required"=false, "format"="1 or 0", "description"="entry already starred"},
-      *          {"name"="archive", "dataType"="integer", "required"=false, "format"="1 or 0", "description"="entry already archived"},
-      *       }
-      * )
-      *
-      * @return JsonResponse
-      */
-     public function postEntriesAction(Request $request)
-     {
-         $this->validateAuthentication();
-         $url = $request->request->get('url');
-         $title = $request->request->get('title');
-         $isArchived = $request->request->get('archive');
-         $isStarred = $request->request->get('starred');
-         $entry = $this->get('wallabag_core.entry_repository')->findByUrlAndUserId($url, $this->getUser()->getId());
-         if (false === $entry) {
-             $entry = $this->get('wallabag_core.content_proxy')->updateEntry(
-                 new Entry($this->getUser()),
-                 $url
-             );
-         }
-         if (!is_null($title)) {
-             $entry->setTitle($title);
-         }
-         $tags = $request->request->get('tags', '');
-         if (!empty($tags)) {
-             $this->get('wallabag_core.content_proxy')->assignTagsToEntry($entry, $tags);
-         }
-         if (!is_null($isStarred)) {
-             $entry->setStarred((bool) $isStarred);
-         }
-         if (!is_null($isArchived)) {
-             $entry->setArchived((bool) $isArchived);
-         }
-         $em = $this->getDoctrine()->getManager();
-         $em->persist($entry);
-         $em->flush();
-         // entry saved, dispatch event about it!
-         $this->get('event_dispatcher')->dispatch(EntrySavedEvent::NAME, new EntrySavedEvent($entry));
-         $json = $this->get('serializer')->serialize($entry, 'json');
-         return (new JsonResponse())->setJson($json);
-     }
-     /**
-      * Change several properties of an entry.
-      *
-      * @ApiDoc(
-      *      requirements={
-      *          {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"}
-      *      },
-      *      parameters={
-      *          {"name"="title", "dataType"="string", "required"=false},
-      *          {"name"="tags", "dataType"="string", "required"=false, "format"="tag1,tag2,tag3", "description"="a comma-separated list of tags."},
-      *          {"name"="archive", "dataType"="integer", "required"=false, "format"="1 or 0", "description"="archived the entry."},
-      *          {"name"="starred", "dataType"="integer", "required"=false, "format"="1 or 0", "description"="starred the entry."},
-      *      }
-      * )
-      *
-      * @return JsonResponse
-      */
-     public function patchEntriesAction(Entry $entry, Request $request)
-     {
-         $this->validateAuthentication();
-         $this->validateUserAccess($entry->getUser()->getId());
-         $title = $request->request->get('title');
-         $isArchived = $request->request->get('archive');
-         $isStarred = $request->request->get('starred');
-         if (!is_null($title)) {
-             $entry->setTitle($title);
-         }
-         if (!is_null($isArchived)) {
-             $entry->setArchived((bool) $isArchived);
-         }
-         if (!is_null($isStarred)) {
-             $entry->setStarred((bool) $isStarred);
-         }
-         $tags = $request->request->get('tags', '');
-         if (!empty($tags)) {
-             $this->get('wallabag_core.content_proxy')->assignTagsToEntry($entry, $tags);
-         }
-         $em = $this->getDoctrine()->getManager();
-         $em->flush();
-         $json = $this->get('serializer')->serialize($entry, 'json');
-         return (new JsonResponse())->setJson($json);
-     }
-     /**
-      * Delete **permanently** an entry.
-      *
-      * @ApiDoc(
-      *      requirements={
-      *          {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"}
-      *      }
-      * )
-      *
-      * @return JsonResponse
-      */
-     public function deleteEntriesAction(Entry $entry)
-     {
-         $this->validateAuthentication();
-         $this->validateUserAccess($entry->getUser()->getId());
-         // entry deleted, dispatch event about it!
-         $this->get('event_dispatcher')->dispatch(EntryDeletedEvent::NAME, new EntryDeletedEvent($entry));
-         $em = $this->getDoctrine()->getManager();
-         $em->remove($entry);
-         $em->flush();
-         $json = $this->get('serializer')->serialize($entry, 'json');
-         return (new JsonResponse())->setJson($json);
-     }
-     /**
-      * Retrieve all tags for an entry.
-      *
-      * @ApiDoc(
-      *      requirements={
-      *          {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"}
-      *      }
-      * )
-      *
-      * @return JsonResponse
-      */
-     public function getEntriesTagsAction(Entry $entry)
-     {
-         $this->validateAuthentication();
-         $this->validateUserAccess($entry->getUser()->getId());
-         $json = $this->get('serializer')->serialize($entry->getTags(), 'json');
-         return (new JsonResponse())->setJson($json);
-     }
-     /**
-      * Add one or more tags to an entry.
-      *
-      * @ApiDoc(
-      *      requirements={
-      *          {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"}
-      *      },
-      *      parameters={
-      *          {"name"="tags", "dataType"="string", "required"=false, "format"="tag1,tag2,tag3", "description"="a comma-separated list of tags."},
-      *       }
-      * )
-      *
-      * @return JsonResponse
-      */
-     public function postEntriesTagsAction(Request $request, Entry $entry)
-     {
-         $this->validateAuthentication();
-         $this->validateUserAccess($entry->getUser()->getId());
-         $tags = $request->request->get('tags', '');
-         if (!empty($tags)) {
-             $this->get('wallabag_core.content_proxy')->assignTagsToEntry($entry, $tags);
-         }
-         $em = $this->getDoctrine()->getManager();
-         $em->persist($entry);
-         $em->flush();
-         $json = $this->get('serializer')->serialize($entry, 'json');
-         return (new JsonResponse())->setJson($json);
-     }
-     /**
-      * Permanently remove one tag for an entry.
-      *
-      * @ApiDoc(
-      *      requirements={
-      *          {"name"="tag", "dataType"="integer", "requirement"="\w+", "description"="The tag ID"},
-      *          {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"}
-      *      }
-      * )
-      *
-      * @return JsonResponse
-      */
-     public function deleteEntriesTagsAction(Entry $entry, Tag $tag)
-     {
-         $this->validateAuthentication();
-         $this->validateUserAccess($entry->getUser()->getId());
-         $entry->removeTag($tag);
-         $em = $this->getDoctrine()->getManager();
-         $em->persist($entry);
-         $em->flush();
-         $json = $this->get('serializer')->serialize($entry, 'json');
-         return (new JsonResponse())->setJson($json);
-     }
-     /**
-      * Retrieve all tags.
-      *
-      * @ApiDoc()
-      *
-      * @return JsonResponse
-      */
-     public function getTagsAction()
-     {
-         $this->validateAuthentication();
-         $tags = $this->getDoctrine()
-             ->getRepository('WallabagCoreBundle:Tag')
-             ->findAllTags($this->getUser()->getId());
-         $json = $this->get('serializer')->serialize($tags, 'json');
-         return (new JsonResponse())->setJson($json);
-     }
-     /**
-      * Permanently remove one tag from **every** entry.
-      *
-      * @ApiDoc(
-      *      requirements={
-      *          {"name"="tag", "dataType"="string", "required"=true, "requirement"="\w+", "description"="Tag as a string"}
-      *      }
-      * )
-      *
-      * @return JsonResponse
-      */
-     public function deleteTagLabelAction(Request $request)
-     {
-         $this->validateAuthentication();
-         $label = $request->request->get('tag', '');
-         $tag = $this->getDoctrine()->getRepository('WallabagCoreBundle:Tag')->findOneByLabel($label);
-         if (empty($tag)) {
-             throw $this->createNotFoundException('Tag not found');
-         }
-         $this->getDoctrine()
-             ->getRepository('WallabagCoreBundle:Entry')
-             ->removeTag($this->getUser()->getId(), $tag);
-         $this->cleanOrphanTag($tag);
-         $json = $this->get('serializer')->serialize($tag, 'json');
-         return (new JsonResponse())->setJson($json);
-     }
-     /**
-      * Permanently remove some tags from **every** entry.
-      *
-      * @ApiDoc(
-      *      requirements={
-      *          {"name"="tags", "dataType"="string", "required"=true, "format"="tag1,tag2", "description"="Tags as strings (comma splitted)"}
-      *      }
-      * )
-      *
-      * @return JsonResponse
-      */
-     public function deleteTagsLabelAction(Request $request)
-     {
-         $this->validateAuthentication();
-         $tagsLabels = $request->request->get('tags', '');
-         $tags = [];
-         foreach (explode(',', $tagsLabels) as $tagLabel) {
-             $tagEntity = $this->getDoctrine()->getRepository('WallabagCoreBundle:Tag')->findOneByLabel($tagLabel);
-             if (!empty($tagEntity)) {
-                 $tags[] = $tagEntity;
-             }
-         }
-         if (empty($tags)) {
-             throw $this->createNotFoundException('Tags not found');
-         }
-         $this->getDoctrine()
-             ->getRepository('WallabagCoreBundle:Entry')
-             ->removeTags($this->getUser()->getId(), $tags);
-         $this->cleanOrphanTag($tags);
-         $json = $this->get('serializer')->serialize($tags, 'json');
-         return (new JsonResponse())->setJson($json);
-     }
-     /**
-      * Permanently remove one tag from **every** entry.
-      *
-      * @ApiDoc(
-      *      requirements={
-      *          {"name"="tag", "dataType"="integer", "requirement"="\w+", "description"="The tag"}
-      *      }
-      * )
-      *
-      * @return JsonResponse
-      */
-     public function deleteTagAction(Tag $tag)
-     {
-         $this->validateAuthentication();
-         $this->getDoctrine()
-             ->getRepository('WallabagCoreBundle:Entry')
-             ->removeTag($this->getUser()->getId(), $tag);
-         $this->cleanOrphanTag($tag);
-         $json = $this->get('serializer')->serialize($tag, 'json');
-         return (new JsonResponse())->setJson($json);
-     }
-     /**
-      * Retrieve annotations for an entry.
-      *
-      * @ApiDoc(
-      *      requirements={
-      *          {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"}
-      *      }
-      * )
-      *
-      * @param Entry $entry
-      *
-      * @return JsonResponse
-      */
-     public function getAnnotationsAction(Entry $entry)
-     {
-         $this->validateAuthentication();
-         return $this->forward('WallabagAnnotationBundle:WallabagAnnotation:getAnnotations', [
-             'entry' => $entry,
-         ]);
-     }
-     /**
-      * Creates a new annotation.
-      *
-      * @ApiDoc(
-      *      requirements={
-      *          {"name"="ranges", "dataType"="array", "requirement"="\w+", "description"="The range array for the annotation"},
-      *          {"name"="quote", "dataType"="string", "required"=false, "description"="Optional, quote for the annotation"},
-      *          {"name"="text", "dataType"="string", "required"=true, "description"=""},
-      *      }
-      * )
-      *
-      * @param Request $request
-      * @param Entry   $entry
-      *
-      * @return JsonResponse
-      */
-     public function postAnnotationAction(Request $request, Entry $entry)
-     {
-         $this->validateAuthentication();
-         return $this->forward('WallabagAnnotationBundle:WallabagAnnotation:postAnnotation', [
-             'request' => $request,
-             'entry' => $entry,
-         ]);
-     }
-     /**
-      * Updates an annotation.
-      *
-      * @ApiDoc(
-      *      requirements={
-      *          {"name"="annotation", "dataType"="string", "requirement"="\w+", "description"="The annotation ID"}
-      *      }
-      * )
-      *
-      * @ParamConverter("annotation", class="WallabagAnnotationBundle:Annotation")
-      *
-      * @param Annotation $annotation
-      * @param Request    $request
-      *
-      * @return JsonResponse
-      */
-     public function putAnnotationAction(Annotation $annotation, Request $request)
-     {
-         $this->validateAuthentication();
-         return $this->forward('WallabagAnnotationBundle:WallabagAnnotation:putAnnotation', [
-             'annotation' => $annotation,
-             'request' => $request,
-         ]);
-     }
-     /**
-      * Removes an annotation.
-      *
-      * @ApiDoc(
-      *      requirements={
-      *          {"name"="annotation", "dataType"="string", "requirement"="\w+", "description"="The annotation ID"}
-      *      }
-      * )
-      *
-      * @ParamConverter("annotation", class="WallabagAnnotationBundle:Annotation")
-      *
-      * @param Annotation $annotation
-      *
-      * @return JsonResponse
-      */
-     public function deleteAnnotationAction(Annotation $annotation)
-     {
-         $this->validateAuthentication();
-         return $this->forward('WallabagAnnotationBundle:WallabagAnnotation:deleteAnnotation', [
-             'annotation' => $annotation,
-         ]);
-     }
 +    /**
 +     * Retrieve version number.
 +     *
 +     * @ApiDoc()
 +     *
 +     * @return JsonResponse
 +     */
 +    public function getVersionAction()
 +    {
 +        $version = $this->container->getParameter('wallabag_core.version');
 +        $json = $this->get('serializer')->serialize($version, 'json');
 +        return (new JsonResponse())->setJson($json);
 +    }
 +
-     /**
-      * Remove orphan tag in case no entries are associated to it.
-      *
-      * @param Tag|array $tags
-      */
-     private function cleanOrphanTag($tags)
+     protected function validateAuthentication()
      {
-         if (!is_array($tags)) {
-             $tags = [$tags];
-         }
-         $em = $this->getDoctrine()->getManager();
-         foreach ($tags as $tag) {
-             if (count($tag->getEntries()) === 0) {
-                 $em->remove($tag);
-             }
+         if (false === $this->get('security.authorization_checker')->isGranted('IS_AUTHENTICATED_FULLY')) {
+             throw new AccessDeniedException();
          }
-         $em->flush();
      }
  
      /**
       *
       * @param int $requestUserId User id from the requested source
       */
-     private function validateUserAccess($requestUserId)
+     protected function validateUserAccess($requestUserId)
      {
          $user = $this->get('security.token_storage')->getToken()->getUser();
          if ($requestUserId != $user->getId()) {
index 35f8b2c1106c3525a720670910fb560a1b58ce3b,c1af9e023e91bfe1f43027057728ad14bb63f101..8e1886acc3c889af75f9aaa9056c4ecb3249b7ae
@@@ -1,4 -1,9 +1,14 @@@
- api:
-     type: rest
-     resource: "WallabagApiBundle:WallabagRest"
-     name_prefix:  api_
 -entries:
++entry:
+   type: rest
 -  resource:     "WallabagApiBundle:EntryRest"
++  resource: "WallabagApiBundle:EntryRest"
+   name_prefix:  api_
 -tags:
++tag:
+   type: rest
 -  resource:     "WallabagApiBundle:TagRest"
++  resource: "WallabagApiBundle:TagRest"
++  name_prefix:  api_
++
++misc:
++  type: rest
++  resource: "WallabagApiBundle:WallabagRest"
+   name_prefix:  api_
index 4542d484c3a2a9e9aaf4b003109e0d068860c2ec,707f3bbe3ea152a45964189baaf5f5ba313fbbfb..a3e70fd0aeabf2661d15560b1e40142836fd2357
@@@ -90,15 -90,15 +90,15 @@@ class TagController extends Controlle
  
          $flatTags = [];
  
 -        foreach ($tags as $key => $tag) {
 +        foreach ($tags as $tag) {
              $nbEntries = $this->getDoctrine()
                  ->getRepository('WallabagCoreBundle:Entry')
 -                ->countAllEntriesByUserIdAndTagId($this->getUser()->getId(), $tag['id']);
 +                ->countAllEntriesByUserIdAndTagId($this->getUser()->getId(), $tag->getId());
  
              $flatTags[] = [
 -                'id' => $tag['id'],
 -                'label' => $tag['label'],
 -                'slug' => $tag['slug'],
 +                'id' => $tag->getId(),
 +                'label' => $tag->getLabel(),
 +                'slug' => $tag->getSlug(),
                  'nbEntries' => $nbEntries,
              ];
          }
              'form' => null,
              'entries' => $entries,
              'currentPage' => $page,
+             'tag' => $tag->getLabel(),
          ]);
      }
  }
index 56d776adb94ff310990f5bc735151fc775f5f253,90a2419eab70534ab93cba6417a6c3f55bede724..9786ac279d8e5475c4754048fbf51f7a7fd3b3ed
@@@ -30,7 -30,7 +30,7 @@@ services
              - "@doctrine"
  
      wallabag_core.subscriber.table_prefix:
 -        class: Wallabag\CoreBundle\Subscriber\TablePrefixSubscriber
 +        class: Wallabag\CoreBundle\Event\Subscriber\TablePrefixSubscriber
          arguments:
              - "%database_table_prefix%"
          tags:
@@@ -55,6 -55,7 +55,7 @@@
                          '.fok.nl': 'Googlebot/2.1'
                          'getpocket.com': 'PHP/5.2'
                          'iansommerville.com': 'PHP/5.2'
+                         '.slashdot.org': 'PHP/5.2'
          calls:
              - [ setLogger, [ "@logger" ] ]
          tags:
@@@ -91,7 -92,7 +92,7 @@@
      wallabag_core.helper.entries_export:
          class: Wallabag\CoreBundle\Helper\EntriesExport
          arguments:
-             - "@craue_config"
+             - '@=service(''craue_config'').get(''wallabag_url'')'
              - src/Wallabag/CoreBundle/Resources/public/themes/_global/img/appicon/apple-touch-icon-152.png
  
      wallabag.operator.array.matches:
          arguments:
              - '@twig'
              - '%kernel.debug%'
 +
 +    wallabag_core.subscriber.sqlite_cascade_delete:
 +        class: Wallabag\CoreBundle\Event\Subscriber\SQLiteCascadeDeleteSubscriber
 +        arguments:
 +            - "@doctrine"
 +        tags:
 +            - { name: doctrine.event_subscriber }
 +
 +    wallabag_core.subscriber.download_images:
 +        class: Wallabag\CoreBundle\Event\Subscriber\DownloadImagesSubscriber
 +        arguments:
 +            - "@doctrine.orm.default_entity_manager"
 +            - "@wallabag_core.entry.download_images"
 +            - '@=service(''craue_config'').get(''download_images_enabled'')'
 +            - "@logger"
 +        tags:
 +            - { name: kernel.event_subscriber }
 +
 +    wallabag_core.entry.download_images:
 +        class: Wallabag\CoreBundle\Helper\DownloadImages
 +        arguments:
 +            - "@wallabag_core.entry.download_images.client"
 +            - "%kernel.root_dir%/../web/assets/images"
 +            - '@=service(''craue_config'').get(''wallabag_url'')'
 +            - "@logger"
 +
 +    wallabag_core.entry.download_images.client:
 +        class: GuzzleHttp\Client
index 21c260798d51df550cc8cad712e273f90be5f19d,6ca7e459c7a6ffaca14f1676de5e501481c0d2ef..aeae6bcff89753fbd842827cc590337433e661d2
@@@ -71,7 -71,6 +71,7 @@@ config
              # 300_word: 'I read ~300 words per minute'
              # 400_word: 'I read ~400 words per minute'
          pocket_consumer_key_label: Brugers nøgle til Pocket for at importere materialer
 +        # android_configuration: Configure your Android application
      form_rss:
          description: 'RSS-feeds fra wallabag gør det muligt at læse de artikler, der gemmes i wallabag, med din RSS-læser. Det kræver, at du genererer et token først.'
          token_label: 'RSS-Token'
          name_label: 'Navn'
          email_label: 'Emailadresse'
          # twoFactorAuthentication_label: 'Two factor authentication'
 +        delete:
 +            # title: Delete my account (a.k.a danger zone)
 +            # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out.
 +            # confirm: Are you really sure? (THIS CAN'T BE UNDONE)
 +            # button: Delete my account
 +    reset:
 +        # title: Reset area (a.k.a danger zone)
 +        # description: By hiting buttons below you'll have ability to remove some informations from your account. Be aware that these actions are IRREVERSIBLE.
 +        # annotations: Remove ALL annotations
 +        # tags: Remove ALL tags
 +        # entries: Remove ALL entries
 +        # confirm: Are you really really sure? (THIS CAN'T BE UNDONE)
      form_password:
          old_password_label: 'Gammel adgangskode'
          new_password_label: 'Ny adgangskode'
@@@ -150,7 -137,7 +150,7 @@@ entry
          # starred: 'Starred entries'
          # archived: 'Archived entries'
          # filtered: 'Filtered entries'
-         # filtered_tags: 'Filtered by tags'
+         # filtered_tags: 'Filtered by tags:'
          # untagged: 'Untagged entries'
      list:
          # number_on_the_page: '{0} There is no entry.|{1} There is one entry.|]1,Inf[ There are %count% entries.'
@@@ -368,7 -355,6 +368,7 @@@ import
      #     how_to: 'Please select your Readability export and click on the below button to upload and import it.'
      worker:
          # enabled: "Import is made asynchronously. Once the import task is started, an external worker will handle jobs one at a time. The current service is:"
 +        # download_images_warning: "You enabled downloading images for your articles. Combined with classic import it can take ages to proceed (or maybe failed). We <strong>strongly recommend</strong> to enable asynchronous import to avoid errors."
      # firefox:
      #    page_title: 'Import > Firefox'
      #    description: "This importer will import all your Firefox bookmarks. Just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file."
@@@ -472,11 -458,8 +472,10 @@@ flashes
              rss_updated: 'RSS-oplysninger opdateret'
              # tagging_rules_updated: 'Tagging rules updated'
              # tagging_rules_deleted: 'Tagging rule deleted'
--            # user_added: 'User "%username%" added'
              # rss_token_updated: 'RSS token updated'
 +            # annotations_reset: Annotations reset
 +            # tags_reset: Tags reset
 +            # entries_reset: Entries reset
      entry:
          notice:
              # entry_already_saved: 'Entry already saved on %date%'
          notice:
              # client_created: 'New client created.'
              # client_deleted: 'Client deleted'
 +    user:
 +        notice:
 +            # added: 'User "%username%" added'
 +            # updated: 'User "%username%" updated'
 +            # deleted: 'User "%username%" deleted'
index ff70cbee5811356263482060609a7989eb1fc347,8fd1d82a2f59e95308d667fe2a068fe48452ec08..2105d02daa1ee323ef98e58cdd6304a561896a50
@@@ -71,7 -71,6 +71,7 @@@ config
              300_word: 'Ich lese ~300 Wörter pro Minute'
              400_word: 'Ich lese ~400 Wörter pro Minute'
          pocket_consumer_key_label: Consumer-Key für Pocket, um Inhalte zu importieren
 +        # android_configuration: Configure your Android application
      form_rss:
          description: 'Die RSS-Feeds von wallabag erlauben es dir, deine gespeicherten Artikel mit deinem bevorzugten RSS-Reader zu lesen. Vorher musst du jedoch einen Token erstellen.'
          token_label: 'RSS-Token'
          name_label: 'Name'
          email_label: 'E-Mail-Adresse'
          twoFactorAuthentication_label: 'Zwei-Faktor-Authentifizierung'
 +        delete:
 +            # title: Delete my account (a.k.a danger zone)
 +            # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out.
 +            # confirm: Are you really sure? (THIS CAN'T BE UNDONE)
 +            # button: Delete my account
 +    reset:
 +        # title: Reset area (a.k.a danger zone)
 +        # description: By hiting buttons below you'll have ability to remove some informations from your account. Be aware that these actions are IRREVERSIBLE.
 +        # annotations: Remove ALL annotations
 +        # tags: Remove ALL tags
 +        # entries: Remove ALL entries
 +        # confirm: Are you really really sure? (THIS CAN'T BE UNDONE)
      form_password:
          old_password_label: 'Altes Kennwort'
          new_password_label: 'Neues Kennwort'
@@@ -150,7 -137,7 +150,7 @@@ entry
          starred: 'Favorisierte Einträge'
          archived: 'Archivierte Einträge'
          filtered: 'Gefilterte Einträge'
-         filtered_tags: 'Gefiltert nach Tags'
+         filtered_tags: 'Gefiltert nach Tags:'
          untagged: 'Nicht getaggte Einträge'
      list:
          number_on_the_page: '{0} Es gibt keine Einträge.|{1} Es gibt einen Eintrag.|]1,Inf[ Es gibt %count% Einträge.'
@@@ -368,7 -355,6 +368,7 @@@ import
          how_to: 'Bitte wähle deinen Readability Export aus und klicke den unteren Button für das Hochladen und Importieren dessen.'
      worker:
          enabled: "Der Import erfolgt asynchron. Sobald der Import gestartet ist, wird diese Aufgabe extern abgearbeitet. Der aktuelle Service dafür ist:"
 +        # download_images_warning: "You enabled downloading images for your articles. Combined with classic import it can take ages to proceed (or maybe failed). We <strong>strongly recommend</strong> to enable asynchronous import to avoid errors."
      firefox:
          page_title: 'Aus Firefox importieren'
          description: "Dieser Import wird all deine Lesezeichen aus Firefox importieren. Gehe zu deinen Lesezeichen (Strg+Shift+O), dann auf \"Importen und Sichern\", wähle \"Sichern…\". Du erhälst eine .json Datei."
@@@ -472,11 -458,8 +472,10 @@@ flashes
              rss_updated: 'RSS-Informationen aktualisiert'
              tagging_rules_updated: 'Tagging-Regeln aktualisiert'
              tagging_rules_deleted: 'Tagging-Regel gelöscht'
--            user_added: 'Benutzer "%username%" erstellt'
              rss_token_updated: 'RSS-Token aktualisiert'
 +            # annotations_reset: Annotations reset
 +            # tags_reset: Tags reset
 +            # entries_reset: Entries reset
      entry:
          notice:
              entry_already_saved: 'Eintrag bereits am %date% gespeichert'
          notice:
              client_created: 'Neuer Client erstellt.'
              client_deleted: 'Client gelöscht'
 +    user:
 +        notice:
 +            # added: 'User "%username%" added'
 +            # updated: 'User "%username%" updated'
 +            # deleted: 'User "%username%" deleted'
index 36382b6fab59321a7e7e2d64fb5993fcef1d6d31,02f56535cc4980dee2e206f2bc16a95eb62b7e41..2bb957283903e10d4548abe3498f44be788decfd
@@@ -71,7 -71,6 +71,7 @@@ config
              300_word: 'I read ~300 words per minute'
              400_word: 'I read ~400 words per minute'
          pocket_consumer_key_label: Consumer key for Pocket to import contents
 +        android_configuration: Configure your Android application
      form_rss:
          description: 'RSS feeds provided by wallabag allow you to read your saved articles with your favourite RSS reader. You need to generate a token first.'
          token_label: 'RSS token'
          name_label: 'Name'
          email_label: 'Email'
          twoFactorAuthentication_label: 'Two factor authentication'
 +        delete:
 +            title: Delete my account (a.k.a danger zone)
 +            description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out.
 +            confirm: Are you really sure? (THIS CAN'T BE UNDONE)
 +            button: Delete my account
 +    reset:
 +        title: Reset area (a.k.a danger zone)
 +        description: By hiting buttons below you'll have ability to remove some informations from your account. Be aware that these actions are IRREVERSIBLE.
 +        annotations: Remove ALL annotations
 +        tags: Remove ALL tags
 +        entries: Remove ALL entries
 +        confirm: Are you really really sure? (THIS CAN'T BE UNDONE)
      form_password:
          old_password_label: 'Current password'
          new_password_label: 'New password'
@@@ -150,7 -137,7 +150,7 @@@ entry
          starred: 'Starred entries'
          archived: 'Archived entries'
          filtered: 'Filtered entries'
-         filtered_tags: 'Filtered by tags'
+         filtered_tags: 'Filtered by tags:'
          untagged: 'Untagged entries'
      list:
          number_on_the_page: '{0} There are no entries.|{1} There is one entry.|]1,Inf[ There are %count% entries.'
@@@ -368,7 -355,6 +368,7 @@@ import
          how_to: 'Please select your Readability export and click on the below button to upload and import it.'
      worker:
          enabled: "Import is made asynchronously. Once the import task is started, an external worker will handle jobs one at a time. The current service is:"
 +        download_images_warning: "You enabled downloading images for your articles. Combined with classic import it can take ages to proceed (or maybe failed). We <strong>strongly recommend</strong> to enable asynchronous import to avoid errors."
      firefox:
          page_title: 'Import > Firefox'
          description: "This importer will import all your Firefox bookmarks. Just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file."
@@@ -472,11 -458,7 +472,10 @@@ flashes
              rss_updated: 'RSS information updated'
              tagging_rules_updated: 'Tagging rules updated'
              tagging_rules_deleted: 'Tagging rule deleted'
-             # user_added: 'User "%username%" added'
              rss_token_updated: 'RSS token updated'
 +            annotations_reset: Annotations reset
 +            tags_reset: Tags reset
 +            entries_reset: Entries reset
      entry:
          notice:
              entry_already_saved: 'Entry already saved on %date%'
index 2c80fe8f28cbd1bf56ef4443b337a970bff11c78,42ec8183fdab25fcc76075bc4e8f9b9375df5467..ca3db4878ff5d094c8044210dd7c8ee01c90c549
@@@ -71,7 -71,6 +71,7 @@@ config
              300_word: 'Leo ~300 palabras por minuto'
              400_word: 'Leo ~400 palabras por minuto'
          # pocket_consumer_key_label: Consumer key for Pocket to import contents
 +        # android_configuration: Configure your Android application
      form_rss:
          description: 'Los feeds RSS de wallabag permiten leer los artículos guardados con su lector RSS favorito. Necesita generar un token primero'
          token_label: 'RSS token'
          name_label: 'Nombre'
          email_label: 'Direccion e-mail'
          twoFactorAuthentication_label: 'Autentificación de dos factores'
 +        delete:
 +            # title: Delete my account (a.k.a danger zone)
 +            # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out.
 +            # confirm: Are you really sure? (THIS CAN'T BE UNDONE)
 +            # button: Delete my account
 +    reset:
 +        # title: Reset area (a.k.a danger zone)
 +        # description: By hiting buttons below you'll have ability to remove some informations from your account. Be aware that these actions are IRREVERSIBLE.
 +        # annotations: Remove ALL annotations
 +        # tags: Remove ALL tags
 +        # entries: Remove ALL entries
 +        # confirm: Are you really really sure? (THIS CAN'T BE UNDONE)
      form_password:
          old_password_label: 'Contraseña actual'
          new_password_label: 'Nueva contraseña'
@@@ -150,7 -137,7 +150,7 @@@ entry
          starred: 'Artículos favoritos'
          archived: 'Artículos archivados'
          filtered: 'Artículos filtrados'
-         # filtered_tags: 'Filtered by tags'
+         # filtered_tags: 'Filtered by tags:'
          # untagged: 'Untagged entries'
      list:
          number_on_the_page: '{0} No hay artículos.|{1} Hay un artículo.|]1,Inf[ Hay %count% artículos.'
@@@ -368,7 -355,6 +368,7 @@@ import
          # how_to: 'Please select your Readability export and click on the below button to upload and import it.'
      worker:
          # enabled: "Import is made asynchronously. Once the import task is started, an external worker will handle jobs one at a time. The current service is:"
 +        # download_images_warning: "You enabled downloading images for your articles. Combined with classic import it can take ages to proceed (or maybe failed). We <strong>strongly recommend</strong> to enable asynchronous import to avoid errors."
      firefox:
         page_title: 'Importar > Firefox'
         # description: "This importer will import all your Firefox bookmarks. Just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file."
@@@ -472,11 -458,8 +472,10 @@@ flashes
              rss_updated: 'La configuración de los feeds RSS ha sido actualizada'
              tagging_rules_updated: 'Regla de etiquetado borrada'
              tagging_rules_deleted: 'Regla de etiquetado actualizada'
--            user_added: 'Usuario "%username%" añadido'
              rss_token_updated: 'RSS token actualizado'
 +            # annotations_reset: Annotations reset
 +            # tags_reset: Tags reset
 +            # entries_reset: Entries reset
      entry:
          notice:
              entry_already_saved: 'Entrada ya guardada por %fecha%'
          notice:
              client_created: 'Nuevo cliente creado.'
              client_deleted: 'Cliente suprimido'
 +    user:
 +        notice:
 +            # added: 'User "%username%" added'
 +            # updated: 'User "%username%" updated'
 +            # deleted: 'User "%username%" deleted'
index 6b6211d603d0a570ad78f114dd3c239a6211b58b,f82167df9ebf8b7583506cdc7e10d9c323445251..1914215a3e0239922cbabb6ae4c026a2b4bf2e9a
@@@ -71,7 -71,6 +71,7 @@@ config
              300_word: 'من تقریباً ۳۰۰ واژه را در دقیقه می‌خوانم'
              400_word: 'من تقریباً ۴۰۰ واژه را در دقیقه می‌خوانم'
          pocket_consumer_key_label: کلید کاربری Pocket برای درون‌ریزی مطالب
 +        # android_configuration: Configure your Android application
      form_rss:
          description: 'با خوراک آر-اس-اس که wallabag در اختیارتان می‌گذارد، می‌توانید مقاله‌های ذخیره‌شده را در نرم‌افزار آر-اس-اس دلخواه خود بخوانید. برای این کار نخست باید یک کد بسازید.'
          token_label: 'کد آر-اس-اس'
          name_label: 'نام'
          email_label: 'نشانی ایمیل'
          twoFactorAuthentication_label: 'تأیید ۲مرحله‌ای'
 +        delete:
 +            # title: Delete my account (a.k.a danger zone)
 +            # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out.
 +            # confirm: Are you really sure? (THIS CAN'T BE UNDONE)
 +            # button: Delete my account
 +    reset:
 +        # title: Reset area (a.k.a danger zone)
 +        # description: By hiting buttons below you'll have ability to remove some informations from your account. Be aware that these actions are IRREVERSIBLE.
 +        # annotations: Remove ALL annotations
 +        # tags: Remove ALL tags
 +        # entries: Remove ALL entries
 +        # confirm: Are you really really sure? (THIS CAN'T BE UNDONE)
      form_password:
          old_password_label: 'رمز قدیمی'
          new_password_label: 'رمز تازه'
@@@ -150,7 -137,7 +150,7 @@@ entry
          starred: 'مقاله‌های برگزیده'
          archived: 'مقاله‌های بایگانی‌شده'
          filtered: 'مقاله‌های فیلترشده'
-         # filtered_tags: 'Filtered by tags'
+         # filtered_tags: 'Filtered by tags:'
          # untagged: 'Untagged entries'
      list:
          number_on_the_page: '{0} هیج مقاله‌ای نیست.|{1} یک مقاله هست.|]1,Inf[ %count% مقاله هست.'
@@@ -285,7 -272,6 +285,7 @@@ quickstart
          paragraph_2: 'ادامه دهید!'
      configure:
          title: 'برنامه را تنظیم کنید'
 +        # description: 'In order to have an application which suits you, have a look into the configuration of wallabag.'
          language: 'زبان و نمای برنامه را تغییر دهید'
          rss: 'خوراک آر-اس-اس را فعال کنید'
          tagging_rules: 'قانون‌های برچسب‌گذاری خودکار مقاله‌هایتان را تعریف کنید'
@@@ -368,7 -354,6 +368,7 @@@ import
          # how_to: 'Please select your Readability export and click on the below button to upload and import it.'
      worker:
          # enabled: "Import is made asynchronously. Once the import task is started, an external worker will handle jobs one at a time. The current service is:"
 +        # download_images_warning: "You enabled downloading images for your articles. Combined with classic import it can take ages to proceed (or maybe failed). We <strong>strongly recommend</strong> to enable asynchronous import to avoid errors."
      firefox:
         page_title: 'درون‌ریزی > Firefox'
         # description: "This importer will import all your Firefox bookmarks. Just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file."
@@@ -472,11 -457,8 +472,10 @@@ flashes
              rss_updated: 'اطلاعات آر-اس-اس به‌روز شد'
              tagging_rules_updated: 'برچسب‌گذاری خودکار به‌روز شد'
              tagging_rules_deleted: 'قانون برچسب‌گذاری پاک شد'
--            user_added: 'کابر "%username%" افزوده شد'
              rss_token_updated: 'کد آر-اس-اس به‌روز شد'
 +            # annotations_reset: Annotations reset
 +            # tags_reset: Tags reset
 +            # entries_reset: Entries reset
      entry:
          notice:
              entry_already_saved: 'این مقاله در تاریخ %date% ذخیره شده بود'
          notice:
              # client_created: 'New client created.'
              # client_deleted: 'Client deleted'
 +    user:
 +        notice:
 +            # added: 'User "%username%" added'
 +            # updated: 'User "%username%" updated'
 +            # deleted: 'User "%username%" deleted'
index 74d59e1a27157969f9d6e18d29505b67e9780a39,421cb8b5a754fef138c83d62581d2b3702b23d01..60fa9a3967395561e108142e1c1c874a8ab1116d
  security:
      login:
-         page_title: 'Bienvenue sur wallabag !'
-         keep_logged_in: 'Rester connecté'
-         forgot_password: 'Mot de passe oublié ?'
-         submit: 'Se connecter'
-         register: 'Créer un compte'
-         username: "Nom d'utilisateur"
-         password: 'Mot de passe'
-         cancel: 'Annuler'
+         page_title: "Bienvenue sur wallabag !"
+         keep_logged_in: "Rester connecté"
+         forgot_password: "Mot de passe oublié ?"
+         submit: "Se connecter"
+         register: "Créer un compte"
+         username: "Nom dutilisateur"
+         password: "Mot de passe"
+         cancel: "Annuler"
      resetting:
-         description: "Saisissez votre adresse e-mail ci-dessous, nous vous enverrons les instructions pour réinitialiser votre mot de passe."
+         description: "Saisissez votre adresse courriel ci-dessous, nous vous enverrons les instructions pour réinitialiser votre mot de passe."
      register:
-         page_title: 'Se créer un compte'
-         go_to_account: 'Aller sur votre compte'
+         page_title: "Se créer un compte"
+         go_to_account: "Aller sur votre compte"
  
  menu:
      left:
-         unread: 'Non lus'
-         starred: 'Favoris'
-         archive: 'Lus'
-         all_articles: 'Tous les articles'
-         config: 'Configuration'
-         tags: 'Tags'
-         internal_settings: 'Configuration interne'
-         import: 'Importer'
-         howto: 'Aide'
-         developer: 'Développeur'
-         logout: 'Déconnexion'
-         about: 'À propos'
-         search: 'Recherche'
-         save_link: 'Sauvegarder un nouvel article'
-         back_to_unread: 'Retour aux articles non lus'
-         users_management: 'Gestion des utilisateurs'
+         unread: "Non lus"
+         starred: "Favoris"
+         archive: "Lus"
+         all_articles: "Tous les articles"
+         config: "Configuration"
+         tags: "Tags"
+         internal_settings: "Configuration interne"
+         import: "Importer"
+         howto: "Aide"
+         developer: "Développeur"
+         logout: "Déconnexion"
+         about: "À propos"
+         search: "Recherche"
+         save_link: "Sauvegarder un nouvel article"
+         back_to_unread: "Retour aux articles non lus"
+         users_management: "Gestion des utilisateurs"
      top:
-         add_new_entry: 'Sauvegarder un nouvel article'
-         search: 'Rechercher'
-         filter_entries: 'Filtrer les articles'
-         export: 'Exporter'
+         add_new_entry: "Sauvegarder un nouvel article"
+         search: "Rechercher"
+         filter_entries: "Filtrer les articles"
+         export: "Exporter"
      search_form:
-         input_label: 'Saisissez votre terme de recherche'
+         input_label: "Saisissez votre terme de recherche"
  
  footer:
      wallabag:
-         elsewhere: 'Emportez wallabag avec vous'
-         social: 'Social'
-         powered_by: 'propulsé par'
-         about: 'À propos'
+         elsewhere: "Emportez wallabag avec vous"
+         social: "Social"
+         powered_by: "propulsé par"
+         about: "À propos"
      stats: Depuis le %user_creation% vous avez lu %nb_archives% articles. Ce qui fait %per_day% par jour !
  
  config:
-     page_title: 'Configuration'
+     page_title: "Configuration"
      tab_menu:
-         settings: 'Paramètres'
-         rss: 'RSS'
-         user_info: 'Mon compte'
-         password: 'Mot de passe'
-         rules: 'Règles de tag automatiques'
-         new_user: 'Créer un compte'
+         settings: "Paramètres"
+         rss: "RSS"
+         user_info: "Mon compte"
+         password: "Mot de passe"
+         rules: "Règles de tag automatiques"
+         new_user: "Créer un compte"
      form:
-         save: 'Enregistrer'
+         save: "Enregistrer"
      form_settings:
-         theme_label: 'Thème'
-         items_per_page_label: "Nombre d'articles par page"
-         language_label: 'Langue'
+         theme_label: "Thème"
+         items_per_page_label: "Nombre darticles par page"
+         language_label: "Langue"
          reading_speed:
-             label: 'Vitesse de lecture'
-             help_message: 'Vous pouvez utiliser un outil en ligne pour estimer votre vitesse de lecture :'
-             100_word: 'Je lis environ 100 mots par minute'
-             200_word: 'Je lis environ 200 mots par minute'
-             300_word: 'Je lis environ 300 mots par minute'
-             400_word: 'Je lis environ 400 mots par minute'
-         pocket_consumer_key_label: Clé d'authentification Pocket pour importer les données
+             label: "Vitesse de lecture"
+             help_message: "Vous pouvez utiliser un outil en ligne pour estimer votre vitesse de lecture :"
+             100_word: "Je lis environ 100 mots par minute"
+             200_word: "Je lis environ 200 mots par minute"
+             300_word: "Je lis environ 300 mots par minute"
+             400_word: "Je lis environ 400 mots par minute"
+         pocket_consumer_key_label: Clé d’authentification Pocket pour importer les données
 +        android_configuration: Configurez votre application Android
      form_rss:
-         description: "Les flux RSS fournis par wallabag vous permettent de lire vos articles sauvegardés dans votre lecteur de flux préféré. Pour pouvoir les utiliser, vous devez d'abord créer un jeton."
-         token_label: 'Jeton RSS'
-         no_token: 'Aucun jeton généré'
-         token_create: 'Créez votre jeton'
-         token_reset: 'Réinitialisez votre jeton'
-         rss_links: 'URL de vos flux RSS'
+         description: "Les flux RSS fournis par wallabag vous permettent de lire vos articles sauvegardés dans votre lecteur de flux préféré. Pour pouvoir les utiliser, vous devez dabord créer un jeton."
+         token_label: "Jeton RSS"
+         no_token: "Aucun jeton généré"
+         token_create: "Créez votre jeton"
+         token_reset: "Réinitialisez votre jeton"
+         rss_links: "Adresse de vos flux RSS"
          rss_link:
-             unread: 'non lus'
-             starred: 'favoris'
-             archive: 'lus'
-         rss_limit: "Nombre d'articles dans le flux"
+             unread: "non lus"
+             starred: "favoris"
+             archive: "lus"
+         rss_limit: "Nombre darticles dans le flux"
      form_user:
-         two_factor_description: "Activer l'authentification double-facteur veut dire que vous allez recevoir un code par email à chaque nouvelle connexion non approuvée."
-         name_label: 'Nom'
-         email_label: 'Adresse e-mail'
-         twoFactorAuthentication_label: 'Double authentification'
+         two_factor_description: "Activer l’authentification double-facteur veut dire que vous allez recevoir un code par courriel à chaque nouvelle connexion non approuvée."
+         name_label: "Nom"
+         email_label: "Adresse courriel"
+         twoFactorAuthentication_label: "Double authentification"
 +        delete:
 +            title: Supprimer mon compte (attention danger !)
 +            description: Si vous confirmez la suppression de votre compte, TOUS les articles, TOUS les tags, TOUTES les annotations et votre compte seront DÉFINITIVEMENT supprimé (c'est IRRÉVERSIBLE). Vous serez ensuite déconnecté.
 +            confirm: Vous êtes vraiment sûr ? (C'EST IRRÉVERSIBLE)
 +            button: 'Supprimer mon compte'
 +    reset:
 +        title: Réinitialisation (attention danger !)
 +        description: En cliquant sur les boutons ci-dessous vous avez la possibilité de supprimer certaines informations de votre compte. Attention, ces actions sont IRRÉVERSIBLES !
 +        annotations: Supprimer TOUTES les annotations
 +        tags: Supprimer TOUS les tags
 +        entries: Supprimer TOUS les articles
 +        confirm: Êtes-vous vraiment vraiment sûr ? (C'EST IRRÉVERSIBLE)
      form_password:
-         old_password_label: 'Mot de passe actuel'
-         new_password_label: 'Nouveau mot de passe'
-         repeat_new_password_label: 'Confirmez votre nouveau mot de passe'
+         old_password_label: "Mot de passe actuel"
+         new_password_label: "Nouveau mot de passe"
+         repeat_new_password_label: "Confirmez votre nouveau mot de passe"
      form_rules:
-         if_label: 'si'
-         then_tag_as_label: 'alors attribuer les tags'
-         delete_rule_label: 'supprimer'
-         edit_rule_label: 'éditer'
-         rule_label: 'Règle'
-         tags_label: 'Tags'
+         if_label: "si"
+         then_tag_as_label: "alors attribuer les tags"
+         delete_rule_label: "supprimer"
+         edit_rule_label: "éditer"
+         rule_label: "Règle"
+         tags_label: "Tags"
          faq:
-             title: 'FAQ'
-             tagging_rules_definition_title: 'Que signifient les règles de tag automatiques ?'
-             tagging_rules_definition_description: "Ce sont des règles utilisées par wallabag pour classer automatiquement vos nouveaux articles.<br />À chaque fois qu'un nouvel article est ajouté, toutes les règles de tag automatiques seront utilisées afin d'ajouter les tags que vous avez configurés, vous épargnant ainsi l'effort de classifier vos articles manuellement."
-             how_to_use_them_title: 'Comment les utiliser ?'
-             how_to_use_them_description: 'Imaginons que voulez attribuer aux nouveaux articles le tag « <i>lecture courte</i> » lorsque le temps de lecture est inférieur à 3 minutes.<br />Dans ce cas, vous devriez mettre « readingTime &lt;= 3 » dans le champ <i>Règle</i> et « <i>lecture courte</i> » dans le champ <i>Tag</i>.<br />Plusieurs tags peuvent être ajoutés simultanément en les séparant par des virgules : « <i>lecture courte, à lire</i> »<br />Des règles complexes peuvent être créées en utilisant des opérateurs prédéfinis: si « <i>readingTime &gt;= 5 AND domainName = \"github.com\"</i> » alors attribuer les tags « <i>lecture longue, github </i> »'
-             variables_available_title: 'Quelles variables et opérateurs puis-je utiliser pour écrire des règles ?'
-             variables_available_description: 'Les variables et opérateurs suivants peuvent être utilisés pour écrire des règles de tag automatiques :'
-             meaning: 'Signification'
+             title: "FAQ"
+             tagging_rules_definition_title: "Que signifient les règles de tag automatiques ?"
+             tagging_rules_definition_description: "Ce sont des règles utilisées par wallabag pour classer automatiquement vos nouveaux articles.<br />À chaque fois qu’un nouvel article est ajouté, toutes les règles de tag automatiques seront utilisées afin d’ajouter les tags que vous avez configurés, vous épargnant ainsi l’effort de classifier vos articles manuellement."
+             how_to_use_them_title: "Comment les utiliser ?"
+             how_to_use_them_description: "Imaginons que voulez attribuer aux nouveaux articles le tag « <i>lecture courte</i> » lorsque le temps de lecture est inférieur à 3 minutes.<br />Dans ce cas, vous devriez mettre « readingTime &lt;= 3 » dans le champ <i>Règle</i> et « <i>lecture courte</i> » dans le champ <i>Tag</i>.<br />Plusieurs tags peuvent être ajoutés simultanément en les séparant par des virgules : « <i>lecture courte, à lire</i> »<br />Des règles complexes peuvent être créées en utilisant des opérateurs prédéfinis: si « <i>readingTime &gt;= 5 AND domainName = \"github.com\"</i> » alors attribuer les tags « <i>lecture longue, github</i> »"
+             variables_available_title: "Quelles variables et opérateurs puis-je utiliser pour écrire des règles ?"
+             variables_available_description: "Les variables et opérateurs suivants peuvent être utilisés pour écrire des règles de tag automatiques :"
+             meaning: "Signification"
              variable_description:
-                 label: 'Variable'
-                 title: "Titre de l'article"
-                 url: "URL de l'article"
-                 isArchived: "Si l'article est archivé ou non"
-                 isStarred: "Si l'article est favori ou non"
-                 content: "Le contenu de l'article"
-                 language: "La langue de l'article"
-                 mimetype: "Le type MIME de l'article"
-                 readingTime: "Le temps de lecture estimé de l'article, en minutes"
-                 domainName: "Le nom de domaine de l'article"
+                 label: "Variable"
+                 title: "Titre de larticle"
+                 url: "Adresse de l’article"
+                 isArchived: "Si larticle est archivé ou non"
+                 isStarred: "Si larticle est favori ou non"
+                 content: "Le contenu de larticle"
+                 language: "La langue de larticle"
+                 mimetype: "Le type MIME de larticle"
+                 readingTime: "Le temps de lecture estimé de larticle, en minutes"
+                 domainName: "Le nom de domaine de larticle"
              operator_description:
-                 label: 'Opérateur'
-                 less_than: 'Moins que…...'
-                 strictly_less_than: 'Strictement moins que…'
-                 greater_than: 'Plus que…'
-                 strictly_greater_than: 'Strictement plus que…'
-                 equal_to: 'Égal à…'
-                 not_equal_to: 'Différent de…'
-                 or: "Une règle OU l'autre"
-                 and: "Une règle ET l'autre"
-                 matches: 'Teste si un <i>sujet</i> correspond à une <i>recherche</i> (non sensible à la casse).<br />Exemple : <code>title matches "football"</code>'
+                 label: "Opérateur"
+                 less_than: "Moins que…..."
+                 strictly_less_than: "Strictement moins que…"
+                 greater_than: "Plus que…"
+                 strictly_greater_than: "Strictement plus que…"
+                 equal_to: "Égal à…"
+                 not_equal_to: "Différent de…"
+                 or: "Une règle OU lautre"
+                 and: "Une règle ET lautre"
+                 matches: "Teste si un <i>sujet</i> correspond à une <i>recherche</i> (non sensible à la casse).<br />Exemple : <code>title matches \"football\"</code>"
  
  entry:
      page_titles:
-         unread: 'Articles non lus'
-         starred: 'Articles favoris'
-         archived: 'Articles lus'
-         filtered: 'Articles filtrés'
-         filtered_tags: 'Articles filtrés par tags'
-         untagged: 'Article sans tag'
+         unread: "Articles non lus"
+         starred: "Articles favoris"
+         archived: "Articles lus"
+         filtered: "Articles filtrés"
+         filtered_tags: "Articles filtrés par tags :"
+         untagged: "Article sans tag"
      list:
-         number_on_the_page: "{0} Il n'y a pas d'articles.|{1} Il y a un article.|]1,Inf[ Il y a %count% articles."
-         reading_time: 'durée de lecture'
-         reading_time_minutes: 'durée de lecture: %readingTime% min'
-         reading_time_less_one_minute: 'durée de lecture: <small class="inferieur">&lt;</small> 1 min'
-         number_of_tags: '{1}et un autre tag|]1,Inf[et %count% autres tags'
-         reading_time_minutes_short: '%readingTime% min'
-         reading_time_less_one_minute_short: '<small class="inferieur">&lt;</small> 1 min'
-         original_article: 'original'
-         toogle_as_read: 'Marquer comme lu/non lu'
-         toogle_as_star: 'Marquer comme favori'
-         delete: 'Supprimer'
-         export_title: 'Exporter'
+         number_on_the_page: "{0} Il n’y a pas d’articles.|{1} Il y a un article.|]1,Inf[ Il y a %count% articles."
+         reading_time: "durée de lecture"
+         reading_time_minutes: "durée de lecture: %readingTime% min"
+         reading_time_less_one_minute: "durée de lecture: <small class=\"inferieur\">&lt;</small> 1 min"
+         number_of_tags: "{1}et un autre tag|]1,Inf[et %count% autres tags"
+         reading_time_minutes_short: "%readingTime% min"
+         reading_time_less_one_minute_short: "<small class=\"inferieur\">&lt;</small> 1 min"
+         original_article: "original"
+         toogle_as_read: "Marquer comme lu/non lu"
+         toogle_as_star: "Marquer comme favori"
+         delete: "Supprimer"
+         export_title: "Exporter"
      filters:
-         title: 'Filtres'
-         status_label: 'Status'
-         archived_label: 'Lus'
-         starred_label: 'Favoris'
-         unread_label: 'Non lus'
-         preview_picture_label: 'A une photo'
-         preview_picture_help: 'Photo'
-         language_label: 'Langue'
+         title: "Filtres"
+         status_label: "Status"
+         archived_label: "Lus"
+         starred_label: "Favoris"
+         unread_label: "Non lus"
+         preview_picture_label: "A une photo"
+         preview_picture_help: "Photo"
+         language_label: "Langue"
          reading_time:
-             label: 'Durée de lecture en minutes'
-             from: 'de'
-             to: 'à'
-         domain_label: 'Nom de domaine'
+             label: "Durée de lecture en minutes"
+             from: "de"
+             to: "à"
+         domain_label: "Nom de domaine"
          created_at:
-             label: 'Date de création'
-             from: 'de'
-             to: 'à'
+             label: "Date de création"
+             from: "de"
+             to: "à"
          action:
-             clear: 'Effacer'
-             filter: 'Filtrer'
+             clear: "Effacer"
+             filter: "Filtrer"
      view:
          left_menu:
-             back_to_top: 'Revenir en haut'
-             back_to_homepage: 'Retour'
-             set_as_read: 'Marquer comme lu'
-             set_as_unread: 'Marquer comme non lu'
-             set_as_starred: 'Mettre en favori'
-             view_original_article: 'Article original'
-             re_fetch_content: 'Recharger le contenu'
-             delete: 'Supprimer'
-             add_a_tag: 'Ajouter un tag'
-             share_content: 'Partager'
-             share_email_label: 'Email'
-             public_link: 'Lien public'
-             delete_public_link: 'Supprimer lien public'
-             download: 'Télécharger'
-             print: 'Imprimer'
+             back_to_top: "Revenir en haut"
+             back_to_homepage: "Retour"
+             set_as_read: "Marquer comme lu"
+             set_as_unread: "Marquer comme non lu"
+             set_as_starred: "Mettre en favori"
+             view_original_article: "Article original"
+             re_fetch_content: "Recharger le contenu"
+             delete: "Supprimer"
+             add_a_tag: "Ajouter un tag"
+             share_content: "Partager"
+             share_email_label: "Courriel"
+             public_link: "Lien public"
+             delete_public_link: "Supprimer le lien public"
+             download: "Télécharger"
+             print: "Imprimer"
              problem:
-                 label: 'Un problème ?'
-                 description: "Est-ce que cet article s'affiche mal ?"
-         edit_title: 'Modifier le titre'
-         original_article: 'original'
-         annotations_on_the_entry: '{0} Aucune annotation|{1} Une annotation|]1,Inf[ %count% annotations'
-         created_at: 'Date de création'
+                 label: "Un problème ?"
+                 description: "Est-ce que cet article saffiche mal ?"
+         edit_title: "Modifier le titre"
+         original_article: "original"
+         annotations_on_the_entry: "{0} Aucune annotation|{1} Une annotation|]1,Inf[ %count% annotations"
+         created_at: "Date de création"
      new:
-         page_title: 'Sauvegarder un nouvel article'
-         placeholder: 'http://website.com'
+         page_title: "Sauvegarder un nouvel article"
+         placeholder: "http://website.com"
          form_new:
-             url_label: Url
+             url_label: "Adresse"
      edit:
-         page_title: 'Éditer un article'
-         title_label: 'Titre'
-         url_label: 'Url'
-         is_public_label: 'Public'
-         save_label: 'Enregistrer'
+         page_title: "Éditer un article"
+         title_label: "Titre"
+         url_label: "Adresse"
+         is_public_label: "Public"
+         save_label: "Enregistrer"
      public:
-         shared_by_wallabag: "Cet article a été partagé par <a href='%wallabag_instance%'>wallabag</a>"
+         shared_by_wallabag: "Cet article a été partagé par <a href=\"%wallabag_instance%\">wallabag</a>"
  
  about:
-     page_title: 'À propos'
+     page_title: "À propos"
      top_menu:
-         who_behind_wallabag: "L'équipe derrière wallabag"
-         getting_help: "Besoin d'aide"
-         helping: 'Aider wallabag'
-         contributors: 'Contributeurs'
-         third_party: 'Librairies tierces'
+         who_behind_wallabag: "Léquipe derrière wallabag"
+         getting_help: "Besoin daide"
+         helping: "Aider wallabag"
+         contributors: "Contributeurs"
+         third_party: "Librairies tierces"
      who_behind_wallabag:
-         developped_by: 'Développé par'
-         website: 'Site web'
-         many_contributors: 'Et plein de contributeurs ♥ <a href="https://github.com/wallabag/wallabag/graphs/contributors">sur Github</a>'
-         project_website: 'Site web du projet'
-         license: 'Licence'
-         version: 'Version'
+         developped_by: "Développé par"
+         website: "Site web"
+         many_contributors: "Et plein de contributeurs ♥ <a href=\"https://github.com/wallabag/wallabag/graphs/contributors\">sur Github</a>"
+         project_website: "Site web du projet"
+         license: "Licence"
+         version: "Version"
      getting_help:
-         documentation: 'Documentation'
-         bug_reports: 'Rapport de bugs'
-         support: '<a href="https://support.wallabag.org">Sur notre site de support</a> ou <a href="https://github.com/wallabag/wallabag/issues">sur GitHub</a>'
+         documentation: "Documentation"
+         bug_reports: "Rapport de bogue"
+         support: "<a href=\"https://support.wallabag.org\">Sur notre site de support</a> ou <a href=\"https://github.com/wallabag/wallabag/issues\">sur GitHub</a>"
      helping:
-         description: 'wallabag est gratuit et opensource. Vous pouvez nous aider :'
-         by_contributing: 'en contribuant au projet :'
-         by_contributing_2: 'un ticket recense tous nos besoins'
-         by_paypal: 'via Paypal'
+         description: "wallabag est gratuit et opensource. Vous pouvez nous aider :"
+         by_contributing: "en contribuant au projet :"
+         by_contributing_2: "un ticket recense tous nos besoins"
+         by_paypal: "via Paypal"
      contributors:
-         description: "Merci aux contributeurs de l'application web de wallabag"
+         description: "Merci aux contributeurs de lapplication web de wallabag"
      third_party:
-         description: 'Voici la liste des dépendances utilisées dans wallabag (et leur license) :'
-         package: 'Dépendance'
-         license: 'Licence'
+         description: "Voici la liste des dépendances utilisées dans wallabag (et leur license) :"
+         package: "Dépendance"
+         license: "Licence"
  
  howto:
-     page_title: 'Aide'
-     page_description: "Il y a plusieurs façon d'enregistrer un article :"
+     page_title: "Aide"
+     page_description: "Il y a plusieurs façon denregistrer un article :"
      top_menu:
-         browser_addons: 'Extensions de navigateur'
-         mobile_apps: 'Applications smartphone'
-         bookmarklet: 'Bookmarklet'
+         browser_addons: "Extensions de navigateur"
+         mobile_apps: "Applications smartphone"
+         bookmarklet: "Bookmarklet"
      form:
-         description: 'Grâce à ce formulaire'
+         description: "Grâce à ce formulaire"
      browser_addons:
-         firefox: 'Extension Firefox'
-         chrome: 'Extension Chrome'
+         firefox: "Extension Firefox"
+         chrome: "Extension Chrome"
      mobile_apps:
          android:
-             via_f_droid: 'via F-Droid'
-             via_google_play: 'via Google Play'
-         ios: 'sur iTunes Store'
-         windows: 'sur Microsoft Store'
+             via_f_droid: "via F-Droid"
+             via_google_play: "via Google Play"
+         ios: "sur iTunes Store"
+         windows: "sur Microsoft Store"
      bookmarklet:
-         description: 'Glissez et déposez ce lien dans votre barre de favoris :'
+         description: "Glissez et déposez ce lien dans votre barre de favoris :"
  
  quickstart:
-     page_title: 'Pour bien débuter'
-     more: 'Et plus encore…'
+     page_title: "Pour bien débuter"
+     more: "Et plus encore…"
      intro:
-         title: 'Bienvenue sur wallabag !'
+         title: "Bienvenue sur wallabag !"
          paragraph_1: "Nous allons vous accompagner pour vous faire faire le tour de la maison et vous présenter quelques fonctionnalités qui pourraient vous intéresser pour vous approprier cet outil."
-         paragraph_2: 'Suivez-nous !'
+         paragraph_2: "Suivez-nous !"
      configure:
-         title: "Configurez l'application"
-         description: 'Pour voir une application qui vous correspond, allez voir du côté de la configuration de wallabag.'
-         language: "Changez la langue et le design de l'application"
-         rss: 'Activez les flux RSS'
-         tagging_rules: 'Écrivez des règles pour classer automatiquement vos articles'
+         title: "Configurez lapplication"
+         description: "Pour voir une application qui vous correspond, allez voir du côté de la configuration de wallabag."
+         language: "Changez la langue et le design de lapplication"
+         rss: "Activez les flux RSS"
+         tagging_rules: "Écrivez des règles pour classer automatiquement vos articles"
      admin:
-         title: 'Administration'
-         description: "En tant qu'administrateur sur wallabag, vous avez des privilèges qui vous permettent de :"
-         new_user: 'Créer un nouvel utilisateur'
-         analytics: 'Configurer les statistiques'
-         sharing: 'Activer des paramètres de partages'
-         export: "Configurer les formats d'export"
-         import: "Configurer l'import"
+         title: "Administration"
+         description: "En tant quadministrateur sur wallabag, vous avez des privilèges qui vous permettent de :"
+         new_user: "Créer un nouvel utilisateur"
+         analytics: "Configurer les statistiques"
+         sharing: "Activer des paramètres de partages"
+         export: "Configurer les formats dexport"
+         import: "Configurer limport"
      first_steps:
-         title: 'Premiers pas'
-         description: "Maintenant que wallabag est bien configuré, il est temps d'archiver le web. Vous pouvez cliquer sur le signe + dans le coin en haut à droite."
-         new_article: 'Ajoutez votre premier article'
-         unread_articles: 'Et rangez-le !'
+         title: "Premiers pas"
+         description: "Maintenant que wallabag est bien configuré, il est temps darchiver le web. Vous pouvez cliquer sur le signe + dans le coin en haut à droite."
+         new_article: "Ajoutez votre premier article"
+         unread_articles: "Et rangez-le !"
      migrate:
-         title: 'Migrer depuis un service existant'
-         description: "Vous êtes un ancien utilisateur d'un service existant ? Nous allons vous aider à récupérer vos données sur wallabag."
-         pocket: 'Migrer depuis Pocket'
-         wallabag_v1: 'Migrer depuis wallabag v1'
-         wallabag_v2: 'Migrer depuis wallabag v2'
-         readability: 'Migrer depuis Readability'
-         instapaper: 'Migrer depuis Instapaper'
+         title: "Migrer depuis un service existant"
+         description: "Vous êtes un ancien utilisateur dun service existant ? Nous allons vous aider à récupérer vos données sur wallabag."
+         pocket: "Migrer depuis Pocket"
+         wallabag_v1: "Migrer depuis wallabag v1"
+         wallabag_v2: "Migrer depuis wallabag v2"
+         readability: "Migrer depuis Readability"
+         instapaper: "Migrer depuis Instapaper"
      developer:
-         title: 'Pour les développeurs'
-         description: 'Nous avons aussi pensé aux développeurs : Docker, API, traductions, etc.'
-         create_application: 'Créer votre application tierce'
-         use_docker: 'Utiliser Docker pour installer wallabag'
+         title: "Pour les développeurs"
+         description: "Nous avons aussi pensé aux développeurs : Docker, API, traductions, etc."
+         create_application: "Créer votre application tierce"
+         use_docker: "Utiliser Docker pour installer wallabag"
      docs:
-         title: 'Documentation complète'
-         description: "Il y a tellement de fonctionnalités dans wallabag. N'hésitez pas à lire le manuel pour les connaitre et apprendre comment les utiliser."
-         annotate: 'Annoter votre article'
-         export: 'Convertissez vos articles en ePub ou en PDF'
-         search_filters: "Apprenez à utiliser le moteur de recherche et les filtres pour retrouver l'article qui vous intéresse"
-         fetching_errors: "Que faire si mon article n'est pas correctement récupéré ?"
-         all_docs: "Et encore plein d'autres choses !"
+         title: "Documentation complète"
+         description: "Il y a tellement de fonctionnalités dans wallabag. Nhésitez pas à lire le manuel pour les connaitre et apprendre comment les utiliser."
+         annotate: "Annoter votre article"
+         export: "Convertissez vos articles en ePub ou en PDF"
+         search_filters: "Apprenez à utiliser le moteur de recherche et les filtres pour retrouver larticle qui vous intéresse"
+         fetching_errors: "Que faire si mon article nest pas correctement récupéré ?"
+         all_docs: "Et encore plein dautres choses !"
      support:
-         title: 'Support'
-         description: 'Parce que vous avez peut-être besoin de nous poser une question, nous sommes disponibles pour vous.'
-         github: 'Sur GitHub'
-         email: 'Par e-mail'
-         gitter: 'Sur Gitter'
+         title: "Support"
+         description: "Parce que vous avez peut-être besoin de nous poser une question, nous sommes disponibles pour vous."
+         github: "Sur GitHub"
+         email: "Par courriel"
+         gitter: "Sur Gitter"
  
  tag:
-     page_title: 'Tags'
+     page_title: "Tags"
      list:
-         number_on_the_page: "{0} Il n'y a pas de tag.|{1} Il y a un tag.|]1,Inf[ Il y a %count% tags."
-         see_untagged_entries: 'Voir les articles sans tag'
+         number_on_the_page: "{0} Il ny a pas de tag.|{1} Il y a un tag.|]1,Inf[ Il y a %count% tags."
+         see_untagged_entries: "Voir les articles sans tag"
  
  import:
-     page_title: 'Importer'
-     page_description: "Bienvenue dans l'outil de migration de wallabag. Choisissez ci-dessous le service depuis lequel vous souhaitez migrer."
+     page_title: "Importer"
+     page_description: "Bienvenue dans loutil de migration de wallabag. Choisissez ci-dessous le service depuis lequel vous souhaitez migrer."
      action:
-         import_contents: 'Importer les contenus'
+         import_contents: "Importer les contenus"
      form:
-         mark_as_read_title: 'Marquer tout comme lu ?'
-         mark_as_read_label: 'Marquer tous les contenus importés comme lus'
-         file_label: 'Fichier'
-         save_label: 'Importer le fichier'
+         mark_as_read_title: "Marquer tout comme lu ?"
+         mark_as_read_label: "Marquer tous les contenus importés comme lus"
+         file_label: "Fichier"
+         save_label: "Importer le fichier"
      pocket:
-         page_title: 'Importer > Pocket'
+         page_title: "Importer > Pocket"
          description: "Cet outil va importer toutes vos données de Pocket. Pocket ne nous autorise pas à récupérer le contenu depuis leur service, donc wallabag doit reparcourir chaque article pour récupérer son contenu."
          config_missing:
-             description: "L'import à partir de Pocket n'est pas configuré."
-             admin_message: "Vous devez définir %keyurls%une clé pour l'API Pocket%keyurle%."
-             user_message: "L'administrateur de votre serveur doit définir une clé pour l'API Pocket."
-         authorize_message: "Vous pouvez importer vos données depuis votre compte Pocket. Vous n'avez qu'à cliquer sur le bouton ci-dessous et à autoriser wallabag à se connecter à getpocket.com."
-         connect_to_pocket: 'Se connecter à Pocket et importer les données'
+             description: "L’import à partir de Pocket n’est pas configuré."
+             admin_message: "Vous devez définir %keyurls%une clé pour lAPI Pocket%keyurle%."
+             user_message: "L’administrateur de votre serveur doit définir une clé pour l’API Pocket."
+         authorize_message: "Vous pouvez importer vos données depuis votre compte Pocket. Vous n’avez qu’à cliquer sur le bouton ci-dessous et à autoriser wallabag à se connecter à getpocket.com."
+         connect_to_pocket: "Se connecter à Pocket et importer les données"
      wallabag_v1:
-         page_title: 'Importer > Wallabag v1'
-         description: 'Cet outil va importer toutes vos données de wallabag v1. Sur votre page de configuration de wallabag v1, cliquez sur "Export JSON" dans la section "Exporter vos données de wallabag". Vous allez récupérer un fichier "wallabag-export-1-xxxx-xx-xx.json".'
-         how_to: "Choisissez le fichier de votre export wallabag v1 et cliquez sur le bouton ci-dessous pour l'importer."
+         page_title: "Importer > wallabag v1"
+         description: "Cet outil va importer toutes vos données de wallabag v1. Sur votre page de configuration de wallabag v1, cliquez sur « Export JSON » dans la section « Exporter vos données de wallabag ». Vous allez récupérer un fichier « wallabag-export-1-xxxx-xx-xx.json »."
+         how_to: "Choisissez le fichier de votre export wallabag v1 et cliquez sur le bouton ci-dessous pour limporter."
      wallabag_v2:
-         page_title: 'Importer > Wallabag v2'
-         description: "Cet outil va importer tous vos articles d'une autre instance de wallabag v2. Allez dans tous vos articles, puis, sur la barre latérale, cliquez sur \"JSON\". Vous allez récupérer un fichier \"All articles.json\""
+         page_title: "Importer > wallabag v2"
+         description: "Cet outil va importer tous vos articles d’une autre instance de wallabag v2. Allez dans tous vos articles, puis, sur la barre latérale, cliquez sur « JSON ». Vous allez récupérer un fichier « All articles.json »"
      readability:
-         page_title: 'Importer > Readability'
-         description: 'Cet outil va importer toutes vos données de Readability. Sur la page des outils (https://www.readability.com/tools/), cliquez sur "Export your data" dans la section "Data Export". Vous allez recevoir un email avec un lien pour télécharger le json.'
-         how_to: "Choisissez le fichier de votre export Readability et cliquez sur le bouton ci-dessous pour l'importer."
+         page_title: "Importer > Readability"
+         description: "Cet outil va importer toutes vos données de Readability. Sur la page des outils (https://www.readability.com/tools/), cliquez sur « Export your data » dans la section « Data Export ». Vous allez recevoir un courriel avec un lien pour télécharger le json."
+         how_to: "Choisissez le fichier de votre export Readability et cliquez sur le bouton ci-dessous pour limporter."
      worker:
-         enabled: "Les imports sont asynchrones. Une fois l'import commencé un worker externe traitera les messages un par un. Le service activé est :"
+         enabled: "Les imports sont asynchrones. Une fois l’import commencé un worker externe traitera les messages un par un. Le service activé est :"
 +        download_images_warning: "Vous avez configuré le téléchagement des images pour vos articles. Combiné à l'import classique, cette opération peut être très très longue (voire échouer). Nous vous conseillons <strong>vivement</strong> d'activer les imports asynchrones."
      firefox:
-         page_title: 'Import > Firefox'
-         description: "Cet outil va vous permettre d'importer tous vos marques-pages de Firefox. Ouvrez le panneau des marques-pages (Ctrl+Maj+O), puis dans « Importation et sauvegarde », choisissez « Sauvegarde... ». Vous allez récupérer un fichier .json. </p>"
-         how_to: "Choisissez le fichier de sauvegarde de vos marques-page et cliquez sur le bouton pour l'importer. Soyez avertis que le processus peut prendre un temps assez long car tous les articles doivent être récupérés en ligne."
+         page_title: "Import > Firefox"
+         description: "Cet outil va vous permettre dimporter tous vos marques-pages de Firefox. Ouvrez le panneau des marques-pages (Ctrl+Maj+O), puis dans « Importation et sauvegarde », choisissez « Sauvegarde... ». Vous allez récupérer un fichier .json. </p>"
+         how_to: "Choisissez le fichier de sauvegarde de vos marques-page et cliquez sur le bouton pour limporter. Soyez avertis que le processus peut prendre un temps assez long car tous les articles doivent être récupérés en ligne."
      chrome:
-         page_title: 'Import > Chrome'
-         description: "Cet outil va vous permettre d'importer tous vos marques-pages de Google Chrome/Chromium. Pour Google Chrome, la situation du fichier dépend de votre système d'exploitation : <ul><li>Sur GNU/Linux, allez dans le répertoire <code>~/.config/google-chrome/Default/</code></li><li>Sous Windows, il devrait se trouver à <code>%LOCALAPPDATA%\\Google\\Chrome\\User Data\\Default</code></li><li>Sur OS X, il devrait se trouver dans le fichier <code>~/Library/Application Support/Google/Chrome/Default/Bookmarks</code></li></ul>Une fois que vous y êtes, copiez le fichier Bookmarks à un endroit où vous le retrouverez.<em><br>Notez que si vous utilisez Chromium à la place de Chrome, vous devez corriger les chemins en conséquence.</em></p>"
-         how_to: "Choisissez le fichier de sauvegarde de vos marques-page et cliquez sur le bouton pour l'importer. Soyez avertis que le processus peut prendre un temps assez long car tous les articles doivent être récupérés en ligne."
+         page_title: "Import > Chrome"
+         description: "Cet outil va vous permettre d’importer tous vos marques-pages de Google Chrome/Chromium. Pour Google Chrome, la situation du fichier dépend de votre système d’exploitation : <ul><li>Sur GNU/Linux, allez dans le répertoire <code>~/.config/google-chrome/Default/</code></li><li>Sous Windows, il devrait se trouver à <code>%LOCALAPPDATA%\\Google\\Chrome\\User Data\\Default</code></li><li>Sur OS X, il devrait se trouver dans le fichier <code>~/Library/Application Support/Google/Chrome/Default/Bookmarks</code></li></ul>Une fois que vous y êtes, copiez le fichier Bookmarks à un endroit où vous le retrouverez.<em><br>Notez que si vous utilisez Chromium à la place de Chrome, vous devez corriger les chemins en conséquence.</em></p>"
+         how_to: "Choisissez le fichier de sauvegarde de vos marques-page et cliquez sur le bouton pour limporter. Soyez avertis que le processus peut prendre un temps assez long car tous les articles doivent être récupérés en ligne."
      instapaper:
-         page_title: 'Import > Instapaper'
-         description: 'Sur la page des paramètres (https://www.instapaper.com/user), cliquez sur "Download .CSV file" dans la section "Export". Un fichier CSV se téléchargera ("instapaper-export.csv").'
-         how_to: "Choisissez le fichier de votre export Instapaper et cliquez sur le bouton ci-dessous pour l'importer."
+         page_title: "Import > Instapaper"
+         description: "Sur la page des paramètres (https://www.instapaper.com/user), cliquez sur « Download .CSV file » dans la section « Export ». Un fichier CSV sera téléchargé (« instapaper-export.csv »)."
+         how_to: "Choisissez le fichier de votre export Instapaper et cliquez sur le bouton ci-dessous pour limporter."
  
  developer:
-     page_title: 'Développeur'
-     welcome_message: "Bienvenue sur l'API de wallabag"
-     documentation: 'Documentation'
-     how_to_first_app: 'Comment créer votre première application'
-     full_documentation: "Voir la documentation complète de l'API"
-     list_methods: "Lister toutes les méthodes de l'API"
+     page_title: "Développeur"
+     welcome_message: "Bienvenue sur lAPI de wallabag"
+     documentation: "Documentation"
+     how_to_first_app: "Comment créer votre première application"
+     full_documentation: "Voir la documentation complète de lAPI"
+     list_methods: "Lister toutes les méthodes de lAPI"
      clients:
-         title: 'Clients'
-         create_new: 'Créer un nouveau client'
+         title: "Clients"
+         create_new: "Créer un nouveau client"
      existing_clients:
-         title: 'Les clients existants'
-         field_id: 'ID Client'
-         field_secret: 'Clé secrète'
-         field_uris: 'URLs de redirection'
-         field_grant_types: 'Type de privilège accordé'
-         no_client: 'Aucun client pour le moment'
+         title: "Les clients existants"
+         field_id: "ID Client"
+         field_secret: "Clé secrète"
+         field_uris: "Adresse de redirection"
+         field_grant_types: "Type de privilège accordé"
+         no_client: "Aucun client pour le moment"
      remove:
-         warn_message_1: 'Vous avez la possibilité de supprimer le client %name%. Cette action est IRRÉVERSIBLE !'
-         warn_message_2: "Si vous supprimez le client %name%, toutes les applications qui l'utilisaient ne fonctionneront plus avec votre compte wallabag."
-         action: 'Supprimer le client %name%'
+         warn_message_1: "Vous avez la possibilité de supprimer le client %name%. Cette action est IRRÉVERSIBLE !"
+         warn_message_2: "Si vous supprimez le client %name%, toutes les applications qui lutilisaient ne fonctionneront plus avec votre compte wallabag."
+         action: "Supprimer le client %name%"
      client:
-         page_title: 'Développeur > Nouveau client'
-         page_description: "Vous allez créer un nouveau client. Merci de remplir l'url de redirection vers votre application."
+         page_title: "Développeur > Nouveau client"
+         page_description: "Vous allez créer un nouveau client. Merci de remplir l’adresse de redirection vers votre application."
          form:
              name_label: "Nom du client"
-             redirect_uris_label: 'URLs de redirection (optionnel)'
-             save_label: 'Créer un nouveau client'
-         action_back: 'Retour'
+             redirect_uris_label: "Adresses de redirection (optionnel)"
+             save_label: "Créer un nouveau client"
+         action_back: "Retour"
      client_parameter:
-         page_title: 'Développeur > Les paramètres de votre client'
-         page_description: 'Voilà les paramètres de votre client'
-         field_name: 'Nom du client'
-         field_id: 'ID Client'
-         field_secret: 'Clé secrète'
-         back: 'Retour'
-         read_howto: 'Lire "comment créer ma première application"'
+         page_title: "Développeur > Les paramètres de votre client"
+         page_description: "Voilà les paramètres de votre client"
+         field_name: "Nom du client"
+         field_id: "ID client"
+         field_secret: "Clé secrète"
+         back: "Retour"
+         read_howto: "Lire « comment créer ma première application »"
      howto:
-         page_title: 'Développeur > Comment créer votre première application'
+         page_title: "Développeur > Comment créer votre première application"
          description:
-             paragraph_1: "Les commandes suivantes utilisent la <a href=\"https://github.com/jkbrzt/httpie\">librarie HTTPie</a>. Assurez-vous qu'elle soit installée avant de l'utiliser."
-             paragraph_2: "Vous avez besoin d'un token pour échanger entre votre application et l'API de wallabag."
-             paragraph_3: 'Pour créer un token, vous devez <a href="%link%">créer un nouveau client</a>.'
-             paragraph_4: 'Maintenant créez votre token (remplacer client_id, client_secret, username et password avec les bonnes valeurs):'
-             paragraph_5: "L'API vous retournera une réponse comme ça :"
-             paragraph_6: "L'access_token doit être utilisé pour faire un appel à l'API. Par exemple :"
-             paragraph_7: "Cet appel va retourner tous les articles de l'utilisateur."
-             paragraph_8: "Si vous voulez toutes les méthodes de l'API, jetez un oeil <a href=\"%link%\">à la documentation de l'API</a>."
-         back: 'Retour'
+             paragraph_1: "Les commandes suivantes utilisent la <a href=\"https://github.com/jkbrzt/httpie\">librarie HTTPie</a>. Assurez-vous qu’elle soit installée avant de l’utiliser."
+             paragraph_2: "Vous avez besoin d’un token pour échanger entre votre application et l’API de wallabag."
+             paragraph_3: "Pour créer un token, vous devez <a href=\"%link%\">créer un nouveau client</a>."
+             paragraph_4: "Maintenant créez votre token (remplacer client_id, client_secret, username et password avec les bonnes valeurs):"
+             paragraph_5: "LAPI vous retournera une réponse comme ça :"
+             paragraph_6: "L’access_token doit être utilisé pour faire un appel à l’API. Par exemple :"
+             paragraph_7: "Cet appel va retourner tous les articles de lutilisateur."
+             paragraph_8: "Si vous voulez toutes les méthodes de l’API, jetez un oeil <a href=\"%link%\">à la documentation de l’API</a>."
+         back: "Retour"
  
  user:
      page_title: Gestion des utilisateurs
          no: Non
          create_new_one: Créer un nouvel utilisateur
      form:
-         username_label: "Nom d'utilisateur"
-         name_label: 'Nom'
-         password_label: 'Mot de passe'
-         repeat_new_password_label: 'Confirmez votre nouveau mot de passe'
-         plain_password_label: 'Mot de passe en clair'
-         email_label: 'Adresse e-mail'
-         enabled_label: 'Activé'
-         locked_label: 'Bloqué'
-         last_login_label: 'Dernière connexion'
-         twofactor_label: Double authentification
-         save: Sauvegarder
-         delete: Supprimer
-         delete_confirm: Êtes-vous sûr?
-         back_to_list: Revenir à la liste
+         username_label: "Nom dutilisateur"
+         name_label: "Nom"
+         password_label: "Mot de passe"
+         repeat_new_password_label: "Confirmez votre nouveau mot de passe"
+         plain_password_label: "Mot de passe en clair"
+         email_label: "Adresse courriel"
+         enabled_label: "Activé"
+         locked_label: "Bloqué"
+         last_login_label: "Dernière connexion"
+         twofactor_label: "Double authentification"
+         save: "Sauvegarder"
+         delete: "Supprimer"
+         delete_confirm: "Voulez-vous vraiment ?"
+         back_to_list: "Revenir à la liste"
  
  error:
      page_title: Une erreur est survenue
  flashes:
      config:
          notice:
-             config_saved: 'Les paramètres ont bien été mis à jour. Certains seront pris en compte après déconnexion.'
-             password_updated: 'Votre mot de passe a bien été mis à jour'
+             config_saved: "Les paramètres ont bien été mis à jour. Certains seront pris en compte après déconnexion."
+             password_updated: "Votre mot de passe a bien été mis à jour"
              password_not_updated_demo: "En démo, vous ne pouvez pas changer le mot de passe de cet utilisateur."
-             user_updated: 'Vos informations personnelles ont bien été mises à jour'
-             rss_updated: 'La configuration des flux RSS a bien été mise à jour'
-             tagging_rules_updated: 'Règles mises à jour'
-             tagging_rules_deleted: 'Règle supprimée'
-             user_added: 'Utilisateur "%username%" ajouté'
-             rss_token_updated: 'Jeton RSS mis à jour'
+             user_updated: "Vos informations personnelles ont bien été mises à jour"
+             rss_updated: "La configuration des flux RSS a bien été mise à jour"
+             tagging_rules_updated: "Règles mises à jour"
+             tagging_rules_deleted: "Règle supprimée"
 -            user_added: "Utilisateur \"%username%\" ajouté"
+             rss_token_updated: "Jeton RSS mis à jour"
 +            annotations_reset: Annotations supprimées
 +            tags_reset: Tags supprimés
 +            entries_reset: Articles supprimés
      entry:
          notice:
-             entry_already_saved: 'Article déjà sauvegardé le %date%'
-             entry_saved: 'Article enregistré'
-             entry_saved_failed: 'Article enregistré mais impossible de récupérer le contenu'
-             entry_updated: 'Article mis à jour'
-             entry_reloaded: 'Article rechargé'
+             entry_already_saved: "Article déjà sauvergardé le %date%"
+             entry_saved: "Article enregistré"
+             entry_saved_failed: "Article enregistré mais impossible de récupérer le contenu"
+             entry_updated: "Article mis à jour"
+             entry_reloaded: "Article rechargé"
              entry_reloaded_failed: "Article mis à jour mais impossible de récupérer le contenu"
-             entry_archived: 'Article marqué comme lu'
-             entry_unarchived: 'Article marqué comme non lu'
-             entry_starred: 'Article ajouté dans les favoris'
-             entry_unstarred: 'Article retiré des favoris'
-             entry_deleted: 'Article supprimé'
+             entry_archived: "Article marqué comme lu"
+             entry_unarchived: "Article marqué comme non lu"
+             entry_starred: "Article ajouté dans les favoris"
+             entry_unstarred: "Article retiré des favoris"
+             entry_deleted: "Article supprimé"
      tag:
          notice:
-             tag_added: 'Tag ajouté'
+             tag_added: "Tag ajouté"
      import:
          notice:
-             failed: "L'import a échoué, veuillez ré-essayer"
-             failed_on_file: "Erreur lors du traitement de l'import. Vérifier votre fichier."
-             summary: "Rapport d'import: %imported% importés, %skipped% déjà présents."
-             summary_with_queue: "Rapport d'import: %queued% en cours de traitement."
+             failed: "Limport a échoué, veuillez ré-essayer"
+             failed_on_file: "Erreur lors du traitement de l’import. Vérifiez votre fichier."
+             summary: "Rapport d’import : %imported% importés, %skipped% déjà présents."
+             summary_with_queue: "Rapport d’import:  %queued% en cours de traitement."
          error:
-             redis_enabled_not_installed: Redis est activé pour les imports asynchrones mais <u>impossible de s'y connecter</u>. Vérifier la configuration de Redis.
-             rabbit_enabled_not_installed: RabbitMQ est activé pour les imports asynchrones mais <u>impossible de s'y connecter</u>. Vérifier la configuration de RabbitMQ.
+             redis_enabled_not_installed: "Redis est activé pour les imports asynchrones mais <u>impossible de s’y connecter</u>. Vérifier la configuration de Redis."
+             rabbit_enabled_not_installed: "RabbitMQ est activé pour les imports asynchrones mais <u>impossible de s’y connecter</u>. Vérifier la configuration de RabbitMQ."
      developer:
          notice:
-             client_created: 'Nouveau client %name% créé'
-             client_deleted: 'Client %name% supprimé'
+             client_created: "Nouveau client %name% créé"
+             client_deleted: "Client %name% supprimé"
 +    user:
 +        notice:
 +            added: 'Utilisateur "%username%" ajouté'
 +            updated: 'Utilisateur "%username%" mis à jour'
 +            deleted: 'Utilisateur "%username%" supprimé'
index a448b602ce3550560f26587edb4ca3413eac5dc9,d679ef003240aa9a043d9e9f97ab94646fbc4692..7f401684a9d558e205a40de789ec4994b92f3f28
@@@ -71,7 -71,6 +71,7 @@@ config
              300_word: 'Leggo ~300 parole al minuto'
              400_word: 'Leggo ~400 parole al minuto'
          pocket_consumer_key_label: Consumer key per Pocket per importare i contenuti
 +        # android_configuration: Configure your Android application
      form_rss:
          description: 'I feed RSS generati da wallabag ti permettono di leggere i tuoi contenuti salvati con il tuo lettore di RSS preferito. Prima, devi generare un token.'
          token_label: 'RSS token'
          name_label: 'Nome'
          email_label: 'E-mail'
          twoFactorAuthentication_label: 'Two factor authentication'
 +        delete:
 +            # title: Delete my account (a.k.a danger zone)
 +            # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out.
 +            # confirm: Are you really sure? (THIS CAN'T BE UNDONE)
 +            # button: Delete my account
 +    reset:
 +        # title: Reset area (a.k.a danger zone)
 +        # description: By hiting buttons below you'll have ability to remove some informations from your account. Be aware that these actions are IRREVERSIBLE.
 +        # annotations: Remove ALL annotations
 +        # tags: Remove ALL tags
 +        # entries: Remove ALL entries
 +        # confirm: Are you really really sure? (THIS CAN'T BE UNDONE)
      form_password:
          old_password_label: 'Password corrente'
          new_password_label: 'Nuova password'
@@@ -150,7 -137,7 +150,7 @@@ entry
          starred: 'Contenuti preferiti'
          archived: 'Contenuti archiviati'
          filtered: 'Contenuti filtrati'
-         # filtered_tags: 'Filtered by tags'
+         # filtered_tags: 'Filtered by tags:'
          # untagged: 'Untagged entries'
      list:
          number_on_the_page: "{0} Non ci sono contenuti.|{1} C'è un contenuto.|]1,Inf[ Ci sono %count% contenuti."
@@@ -368,7 -355,6 +368,7 @@@ import
          # how_to: 'Please select your Readability export and click on the below button to upload and import it.'
      worker:
          # enabled: "Import is made asynchronously. Once the import task is started, an external worker will handle jobs one at a time. The current service is:"
 +        # download_images_warning: "You enabled downloading images for your articles. Combined with classic import it can take ages to proceed (or maybe failed). We <strong>strongly recommend</strong> to enable asynchronous import to avoid errors."
      firefox:
         page_title: 'Importa da > Firefox'
         # description: "This importer will import all your Firefox bookmarks. Just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file."
@@@ -472,11 -458,8 +472,10 @@@ flashes
              rss_updated: 'Informazioni RSS aggiornate'
              tagging_rules_updated: 'Regole di tagging aggiornate'
              tagging_rules_deleted: 'Regola di tagging aggiornate'
--            user_added: 'Utente "%username%" aggiunto'
              rss_token_updated: 'RSS token aggiornato'
 +            # annotations_reset: Annotations reset
 +            # tags_reset: Tags reset
 +            # entries_reset: Entries reset
      entry:
          notice:
              entry_already_saved: 'Contenuto già salvato in data %date%'
          notice:
              client_created: 'Nuovo client creato.'
              client_deleted: 'Client eliminato'
 +    user:
 +        notice:
 +            # added: 'User "%username%" added'
 +            # updated: 'User "%username%" updated'
 +            # deleted: 'User "%username%" deleted'
index a61f7cdd24be1ebd5414696e20e10b1e59b197c0,af0fba0dc409dac909604cf992cc39a7ce9e94ce..c3282b0e83d73fd9b2a38704da1c9b2edb66c7f2
@@@ -25,13 -25,13 +25,13 @@@ menu
          internal_settings: 'Configuracion interna'
          import: 'Importar'
          howto: 'Ajuda'
 -        developer: 'Desvolopador'
 +        developer: 'Desvolopaire'
          logout: 'Desconnexion'
          about: 'A prepaus'
          search: 'Cercar'
          save_link: 'Enregistrar un novèl article'
          back_to_unread: 'Tornar als articles pas legits'
 -        # users_management: 'Users management'
 +        users_management: 'Gestion dels utilizaires'
      top:
          add_new_entry: 'Enregistrar un novèl article'
          search: 'Cercar'
@@@ -46,7 -46,7 +46,7 @@@ footer
          social: 'Social'
          powered_by: 'propulsat per'
          about: 'A prepaus'
 -    # stats: Since %user_creation% you read %nb_archives% articles. That is about %per_day% a day!
 +    stats: "Dempuèi %user_creation% avètz legit %nb_archives% articles. Es a l'entorn de %per_day% per jorn !"
  
  config:
      page_title: 'Configuracion'
@@@ -71,7 -71,6 +71,7 @@@
              300_word: "Legissi a l'entorn de 300 mots per minuta"
              400_word: "Legissi a l'entorn de 400 mots per minuta"
          pocket_consumer_key_label: Clau d'autentificacion Pocket per importar las donadas
 +        # android_configuration: Configure your Android application
      form_rss:
          description: "Los fluxes RSS fornits per wallabag vos permeton de legir vòstres articles salvagardats dins vòstre lector de fluxes preferit. Per los poder emplegar, vos cal, d'en primièr crear un geton."
          token_label: 'Geton RSS'
          name_label: 'Nom'
          email_label: 'Adreça de corrièl'
          twoFactorAuthentication_label: 'Dobla autentificacion'
 +        delete:
 +            # title: Delete my account (a.k.a danger zone)
 +            # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out.
 +            # confirm: Are you really sure? (THIS CAN'T BE UNDONE)
 +            # button: Delete my account
 +    reset:
 +        # title: Reset area (a.k.a danger zone)
 +        # description: By hiting buttons below you'll have ability to remove some informations from your account. Be aware that these actions are IRREVERSIBLE.
 +        # annotations: Remove ALL annotations
 +        # tags: Remove ALL tags
 +        # entries: Remove ALL entries
 +        # confirm: Are you really really sure? (THIS CAN'T BE UNDONE)
      form_password:
          old_password_label: 'Senhal actual'
          new_password_label: 'Senhal novèl'
          if_label: 'se'
          then_tag_as_label: 'alara atribuir las etiquetas'
          delete_rule_label: 'suprimir'
 -        # edit_rule_label: 'edit'
 +        edit_rule_label: 'modificar'
          rule_label: 'Règla'
          tags_label: 'Etiquetas'
          faq:
@@@ -150,7 -137,7 +150,7 @@@ entry
          starred: 'Articles favorits'
          archived: 'Articles legits'
          filtered: 'Articles filtrats'
-         filtered_tags: 'Filtats per etiquetas'
+         filtered_tags: 'Filtats per etiquetas:'
          untagged: 'Articles sens etiqueta'
      list:
          number_on_the_page: "{0} I a pas cap d'article.|{1} I a un article.|]1,Inf[ I a %count% articles."
          is_public_label: 'Public'
          save_label: 'Enregistrar'
      public:
 -        # shared_by_wallabag: "This article has been shared by <a href='%wallabag_instance%'>wallabag</a>"
 +        shared_by_wallabag: "Aqueste article es estat partejat per <a href='%wallabag_instance%'>wallabag</a>"
  
  about:
      page_title: 'A prepaus'
@@@ -278,14 -265,14 +278,14 @@@ howto
  
  quickstart:
      page_title: 'Per ben començar'
 -    # more: 'More…'
 +    more: 'Mai…'
      intro:
          title: 'Benvenguda sus wallabag !'
          paragraph_1: "Anem vos guidar per far lo torn de la proprietat e vos presentar unas fonccionalitats que vos poirián interessar per vos apropriar aquesta aisina."
          paragraph_2: 'Seguètz-nos '
      configure:
 -        title: "Configuratz l'aplicacio"
 -        # description: 'In order to have an application which suits you, have a look into the configuration of wallabag.'
 +        title: "Configuratz l'aplicacion"
 +        description: "Per fin d'aver una aplicacion que vos va ben, anatz veire la configuracion de wallabag."
          language: "Cambiatz la lenga e l'estil de l'aplicacion"
          rss: 'Activatz los fluxes RSS'
          tagging_rules: 'Escrivètz de règlas per classar automaticament vòstres articles'
          import: 'Configurar los impòrt'
      first_steps:
          title: 'Primièrs passes'
 -        # description: "Now wallabag is well configured, it's time to archive the web. You can click on the top right sign + to add a link."
 +        description: "Ara wallabag es ben configurat, es lo moment d'archivar lo web. Podètz clicar sul signe + a man drecha amont per ajustar un ligam."
          new_article: 'Ajustatz vòstre primièr article'
          unread_articles: 'E racaptatz-lo !'
      migrate:
          readability: 'Migrar dempuèi Readability'
          instapaper: 'Migrar dempuèi Instapaper'
      developer:
 -        title: 'Pels desvolopadors'
 -        # description: 'We also thought to the developers: Docker, API, translations, etc.'
 +        title: 'Pels desvolopaires'
 +        description: 'Avèm tanben pensat als desvolopaires : Docker, API, traduccions, etc.'
          create_application: 'Crear vòstra aplicacion tèrça'
 -        # use_docker: 'Use Docker to install wallabag'
 +        use_docker: 'Utilizar Docker per installar wallabag'
      docs:
          title: 'Documentacion complèta'
 -        # description: "There are so much features in wallabag. Don't hesitate to read the manual to know them and to learn how to use them."
 -        annotate: 'Anotatar vòstre article'
 +        description: "I a un fum de fonccionalitats dins wallabag. Esitetz pas a legir lo manual per las conéisser e aprendre a las utilizar."
 +        annotate: 'Anotar vòstre article'
          export: 'Convertissètz vòstres articles en ePub o en PDF'
          search_filters: "Aprenètz a utilizar lo motor de recèrca e los filtres per retrobar l'article que vos interèssa"
          fetching_errors: "Qué far se mon article es pas recuperat coma cal ?"
@@@ -368,7 -355,6 +368,7 @@@ import
          how_to: "Mercés de seleccionar vòstre Readability fichièr e de clicar sul boton dejós per lo telecargar e l'importar."
      worker:
          enabled: "L'importacion se fa de manièra asincròna. Un còp l'importacion lançada, una aisina externa s'ocuparà dels messatges un per un. Lo servici actual es : "
 +        # download_images_warning: "You enabled downloading images for your articles. Combined with classic import it can take ages to proceed (or maybe failed). We <strong>strongly recommend</strong> to enable asynchronous import to avoid errors."
      firefox:
          page_title: 'Importar > Firefox'
          description: "Aquesta aisina importarà totas vòstres favorits de Firefox. Just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file."
@@@ -404,7 -390,7 +404,7 @@@ developer
          warn_message_2: "Se suprimissètz un client, totas las aplicacions que l'emplegan foncionaràn pas mai amb vòstre compte wallabag."
          action: 'Suprimir aqueste client'
      client:
 -        page_title: 'Desvlopador > Novèl client'
 +        page_title: 'Desvolopaire > Novèl client'
          page_description: "Anatz crear un novèl client. Mercés de cumplir l'url de redireccion cap a vòstra aplicacion."
          form:
              name_label: "Nom del client"
              save_label: 'Crear un novèl client'
          action_back: 'Retorn'
      client_parameter:
 -        page_title: 'Desvolopador > Los paramètres de vòstre client'
 +        page_title: 'Desvolopaire > Los paramètres de vòstre client'
          page_description: 'Vaquí los paramètres de vòstre client'
          field_name: 'Nom del client'
          field_id: 'ID Client'
          back: 'Retour'
          read_howto: 'Legir "cossí crear ma primièra aplicacion"'
      howto:
 -        page_title: 'Desvolopador > Cossí crear ma primièra aplicacion'
 +        page_title: 'Desvolopaire > Cossí crear ma primièra aplicacion'
          description:
              paragraph_1: "Las comandas seguentas utilizan la <a href=\"https://github.com/jkbrzt/httpie\">bibliotèca HTTPie</a>. Asseguratz-vos que siasqueòu installadas abans de l'utilizar."
              paragraph_2: "Vos cal un geton per escambiar entre vòstra aplicacion e l'API de wallabar."
          back: 'Retorn'
  
  user:
 -    # page_title: Users management
 -    # new_user: Create a new user
 -    # edit_user: Edit an existing user
 -    # description: "Here you can manage all users (create, edit and delete)"
 -    list:
 -    #     actions: Actions
 -    #     edit_action: Edit
 -    #     yes: Yes
 -    #     no: No
 -    #     create_new_one: Create a new user
 +    page_title: 'Gestion dels utilizaires'
 +    new_user: 'Crear un novèl utilizaire'
 +    edit_user: 'Modificar un utilizaire existent'
 +    description: "Aquí podètz gerir totes los utilizaires (crear, modificar e suprimir)"
 +    list:
 +         actions: 'Accions'
 +         edit_action: 'Modificar'
 +         yes: 'Òc'
 +         no: 'Non'
 +         create_new_one: 'Crear un novèl utilizaire'
      form:
          username_label: "Nom d'utilizaire"
 -        # name_label: 'Name'
 +        name_label: 'Nom'
          password_label: 'Senhal'
          repeat_new_password_label: 'Confirmatz vòstre novèl senhal'
          plain_password_label: 'Senhal en clar'
          email_label: 'Adreça de corrièl'
 -        # enabled_label: 'Enabled'
 -        # locked_label: 'Locked'
 -        # last_login_label: 'Last login'
 -        # twofactor_label: Two factor authentication
 -        # save: Save
 -        # delete: Delete
 -        # delete_confirm: Are you sure?
 -        # back_to_list: Back to list
 +        enabled_label: 'Actiu'
 +        locked_label: 'Varrolhat'
 +        last_login_label: 'Darrièra connexion'
 +        twofactor_label: 'Autentificacion doble-factor'
 +        save: 'Enregistrar'
 +        delete: 'Suprimir'
 +        delete_confirm: 'Sètz segur ?'
 +        back_to_list: 'Tornar a la lista'
  
  error:
      # page_title: An error occurred
@@@ -472,11 -458,8 +472,10 @@@ flashes
              rss_updated: 'La configuracion dels fluxes RSS es ben estada mesa a jorn'
              tagging_rules_updated: 'Règlas misa a jorn'
              tagging_rules_deleted: 'Règla suprimida'
-             user_added: 'Utilizaire "%username%" ajustat'
 -            user_added: 'Utilizaire "%username%" apondut'
              rss_token_updated: 'Geton RSS mes a jorn'
 +            # annotations_reset: Annotations reset
 +            # tags_reset: Tags reset
 +            # entries_reset: Entries reset
      entry:
          notice:
              entry_already_saved: 'Article ja salvargardat lo %date%'
              entry_reloaded_failed: "L'article es estat cargat de nòu mai la recuperacion del contengut a fracassat"
              entry_archived: 'Article marcat coma legit'
              entry_unarchived: 'Article marcat coma pas legit'
 -            entry_starred: 'Article apondut dins los favorits'
 +            entry_starred: 'Article ajustat dins los favorits'
              entry_unstarred: 'Article quitat dels favorits'
              entry_deleted: 'Article suprimit'
      tag:
          notice:
 -            tag_added: 'Etiqueta aponduda'
 +            tag_added: 'Etiqueta ajustada'
      import:
          notice:
              failed: "L'importacion a fracassat, mercés de tornar ensajar"
          notice:
              client_created: 'Novèl client creat'
              client_deleted: 'Client suprimit'
 +    user:
 +        notice:
 +            # added: 'User "%username%" added'
 +            # updated: 'User "%username%" updated'
 +            # deleted: 'User "%username%" deleted'
index a7387b79a889719e93f3c5898b5e532641113e58,bf47b58a72e3ad602ea92f350917f2581fee9933..87731faf1c447a924ff71381a1a8af706479abe4
@@@ -71,7 -71,6 +71,7 @@@ config
              300_word: 'Czytam ~300 słów na minutę'
              400_word: 'Czytam ~400 słów na minutę'
          pocket_consumer_key_label: 'Klucz klienta Pocket do importu zawartości'
 +        # android_configuration: Configure your Android application
      form_rss:
          description: 'Kanały RSS prowadzone przez wallabag pozwalają Ci na czytanie twoich zapisanych artykułów w twoium ulubionym czytniku RSS. Musisz najpierw wynegenerować tokena.‌'
          token_label: 'Token RSS'
          name_label: 'Nazwa'
          email_label: 'Adres email'
          twoFactorAuthentication_label: 'Autoryzacja dwuetapowa'
 +        delete:
 +            title: Usuń moje konto (niebezpieczna strefa !)
 +            description: Jeżeli usuniesz swoje konto, wszystkie twoje artykuły, tagi, adnotacje, oraz konto zostaną trwale usunięte (operacja jest NIEODWRACALNA). Następnie zostaniesz wylogowany.
 +            confirm: Jesteś pewien? (tej operacji NIE MOŻNA cofnąć)
 +            button: Usuń moje konto
 +    reset:
 +        title: Reset (niebezpieczna strefa)
 +        description: Poniższe przyciski pozwalają usunąć pewne informacje z twojego konta. Uważaj te operacje są NIEODWRACALNE.
 +        annotations: Usuń WSZYSTKIE adnotacje
 +        tags: Usuń WSZYSTKIE tagi
 +        entries: usuń WSZYTSTKIE wpisy
 +        confirm: Jesteś pewien? (tej operacji NIE MOŻNA cofnąć)
      form_password:
          old_password_label: 'Stare hasło'
          new_password_label: 'Nowe hasło'
@@@ -150,7 -137,7 +150,7 @@@ entry
          starred: 'Wpisy oznaczone gwiazdką'
          archived: 'Zarchiwizowane wpisy'
          filtered: 'Odfiltrowane wpisy'
-         filtered_tags: 'Filtrowane po tagach'
+         filtered_tags: 'Filtrowane po tagach:'
          untagged: 'Odtaguj wpisy'
      list:
          number_on_the_page: '{0} Nie ma wpisów.|{1} Jest jeden wpis.|]1,Inf[ Są %count% wpisy.'
@@@ -368,7 -355,6 +368,7 @@@ import
          how_to: 'Wybierz swój plik eksportu z Readability i kliknij poniższy przycisk, aby go załadować.'
      worker:
          enabled: "Import jest wykonywany asynchronicznie. Od momentu rozpoczęcia importu, zewnętrzna usługa może zajmować się na raz tylko jednym zadaniem. Bieżącą usługą jest:"
 +        # download_images_warning: "You enabled downloading images for your articles. Combined with classic import it can take ages to proceed (or maybe failed). We <strong>strongly recommend</strong> to enable asynchronous import to avoid errors."
      firefox:
         page_title: 'Import > Firefox'
         description: "Ten importer zaimportuje wszystkie twoje zakładki z Firefoksa. Idź do twoich zakładek (Ctrl+Shift+O), następnie w \"Import i kopie zapasowe\", wybierz \"Utwórz kopię zapasową...\". Uzyskasz plik .json."
@@@ -460,7 -446,7 +460,7 @@@ user
          back_to_list: Powrót do listy
  
  error:
 -    # page_title: An error occurred
 +    page_title: Wystąpił błąd
  
  flashes:
      config:
              rss_updated: 'Informacje RSS zaktualizowane'
              tagging_rules_updated: 'Reguły tagowania zaktualizowane'
              tagging_rules_deleted: 'Reguła tagowania usunięta'
--            user_added: 'Użytkownik "%username%" dodany'
              rss_token_updated: 'Token kanału RSS zaktualizowany'
 +            annotations_reset: Zresetuj adnotacje
 +            tags_reset: Zresetuj tagi
 +            entries_reset: Zresetuj wpisy
      entry:
          notice:
              entry_already_saved: 'Wpis już został dodany %date%'
          notice:
              client_created: 'Nowy klient utworzony.'
              client_deleted: 'Klient usunięty'
 +    user:
 +        notice:
 +            # added: 'User "%username%" added'
 +            # updated: 'User "%username%" updated'
 +            # deleted: 'User "%username%" deleted'
index 0000000000000000000000000000000000000000,f10dc9aa20cfc1b8a2493db8c7e737f52821cc35..c1c60430aa11df4e742dc27d50be60873a13cbe0
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,492 +1,491 @@@
 -            user_updated: 'Informação atualizada'
+ security:
+     login:
+         page_title: 'Bem vindo ao wallabag!'
+         keep_logged_in: 'Mantenha-me autenticado'
+         forgot_password: 'Esqueceu a senha?'
+         submit: 'Login'
+         register: 'Registre-se'
+         username: 'Nome de usuário'
+         password: 'Senha'
+         cancel: 'Cancelar'
+     resetting:
+         description: 'Digite seu endereço de e-mail abaixo e enviaremos instruções para resetar sua senha.'
+     register:
+         page_title: 'Criar uma conta'
+         go_to_account: 'Ir para sua conta'
+ menu:
+     left:
+         unread: 'Não lido'
+         starred: 'Destacado'
+         archive: 'Arquivo'
+         all_articles: 'Todas as entradas'
+         config: 'Configurações'
+         tags: 'Tags'
+         internal_settings: 'Configurações Internas'
+         import: 'Importar'
+         howto: 'How to'
+         developer: 'Desenvolvedor'
+         logout: 'Sair'
+         about: 'Sobre'
+         search: 'Pesquisa'
+         save_link: 'Salvar um link'
+         back_to_unread: 'Voltar para os artigos não lidos'
+         users_management: 'Gestão de Usuários'
+     top:
+         add_new_entry: 'Adicionar uma nova entrada'
+         search: 'Pesquisa'
+         filter_entries: 'Filtrar entradas'
+         export: 'Exportar'
+     search_form:
+         input_label: 'Digite aqui sua pesquisa'
+ footer:
+     wallabag:
+         elsewhere: 'Leve o wallabag com você'
+         social: 'Social'
+         powered_by: 'provido por'
+         about: 'Sobre'
+     stats: 'Desde %user_creation% você leu %nb_archives% artigos. Isso é %per_day% por dia!'
+ config:
+     page_title: 'Config'
+     tab_menu:
+         settings: 'Configurações'
+         rss: 'RSS'
+         user_info: 'Informação do Usuário'
+         password: 'Senha'
+         rules: 'Regras de tags'
+         new_user: 'Adicionar um usuário'
+     form:
+         save: 'Salvar'
+     form_settings:
+         theme_label: 'Tema'
+         items_per_page_label: 'Itens por página'
+         language_label: 'Idioma'
+         reading_speed:
+             label: 'Velocidade de leitura'
+             help_message: 'Você pode usar ferramentas online para estimar sua velocidade de leitura:'
+             100_word: 'Posso ler ~100 palavras por minuto'
+             200_word: 'Posso ler ~200 palavras por minuto'
+             300_word: 'Posso ler ~300 palavras por minuto'
+             400_word: 'Posso ler ~400 palavras por minuto'
+         pocket_consumer_key_label: 'Chave do consumidor do Pocket para importar conteúdo'
+     form_rss:
+         description: 'Feeds RSS providos pelo wallabag permitem que você leia seus artigos salvos em seu leitor de RSS favorito. Você precisa gerar um token primeiro.'
+         token_label: 'Token RSS'
+         no_token: 'Nenhum Token'
+         token_create: 'Criar seu token'
+         token_reset: 'Gerar novamente seu token'
+         rss_links: 'Links RSS'
+         rss_link:
+             unread: 'não lido'
+             starred: 'destacado'
+             archive: 'arquivado'
+         rss_limit: 'Número de itens no feed'
+     form_user:
+         two_factor_description: 'Habilitar autenticação de dois passos significa que você receberá um e-mail com um código a cada nova conexão desconhecida.'
+         name_label: 'Nome'
+         email_label: 'E-mail'
+         twoFactorAuthentication_label: 'Autenticação de dois passos'
+     form_password:
+         old_password_label: 'Senha atual'
+         new_password_label: 'Nova senha'
+         repeat_new_password_label: 'Repita a nova senha'
+     form_rules:
+         if_label: 'if'
+         then_tag_as_label: 'então coloque a tag'
+         delete_rule_label: 'apagar'
+         edit_rule_label: 'editar'
+         rule_label: 'Regras'
+         tags_label: 'Tags'
+         faq:
+             title: 'FAQ'
+             tagging_rules_definition_title: 'O que as « regras de tags » significam?'
+             tagging_rules_definition_description: 'São regras usadas pelo Wallabag para automaticamente adicionar tags em novos artigos.<br />Cada vez que um novo artigo é adicionado, todas as regras de tags podem ser usadas para adicionar as tags que você configurou, ajudando-o com o problema de classificar manualmente seus artigos.'
+             how_to_use_them_title: 'Como eu as utilizo?'
+             how_to_use_them_description: 'Vamos dizer que você deseja adicionar a tag « <i>leitura rápida</i> » quando o tempo de leitura for menor que 3 minutos.<br />Neste caso, você deve « readingTime &lt;= 3 » no campo <i>Regra</i> e « <i>leitura rápida</i> » no campo <i>Tags</i>.<br />Diversas tags podem ser adicionadas simultâneamente separando-as com vírgula: « <i>leitura rápida, precisa ser lido</i> »<br />Regras complexas podem ser escritas usando os seguintes operadores pré-definidos: if « <i>readingTime &gt;= 5 AND domainName = "github.com"</i> » então adicione a tag « <i>leitura longa, github </i> »'
+             variables_available_title: 'Quais variáveis e operadores eu posso usar para escrever regras?'
+             variables_available_description: 'As seguintes variáveis e operadores podem ser usados para criar regras de tags:'
+             meaning: 'Meaning'
+             variable_description:
+                 label: 'Variável'
+                 title: 'Título da entrada'
+                 url: 'URL da entrada'
+                 isArchived: 'Se a entrada está arquivada ou não'
+                 isDestacado: 'Se a entrada está destacada ou não'
+                 content: 'O conteúdo da entrada'
+                 language: 'O idioma da entrada'
+                 mimetype: 'O mime-type da entrada'
+                 readingTime: 'O tempo estimado de leitura da entrada, em minutos'
+                 domainName: 'O domínio da entrada'
+             operator_description:
+                 label: 'Operador'
+                 less_than: 'Menor que...'
+                 strictly_less_than: 'Estritamente menor que...'
+                 greater_than: 'Maior que...'
+                 strictly_greater_than: 'Estritamente maior que...'
+                 equal_to: 'Igual a...'
+                 not_equal_to: 'Diferente de...'
+                 or: 'Uma regra OU outra'
+                 and: 'Uma regra E outra'
+                 matches: 'Testa que um <i>assunto</i> corresponde a uma <i>pesquisa</i> (maiúscula ou minúscula).<br />Exemplo: <code>título corresponde a "futebol"</code>'
+ entry:
+     page_titles:
+         unread: 'Entradas não lidas'
+         starred: 'Entradas destacadas'
+         archived: 'Entradas arquivadas'
+         filtered: 'Entradas filtradas'
+         filtered_tags: 'Filtrar por tags:'
+         untagged: 'Entradas sem tags'
+     list:
+         number_on_the_page: '{0} Não existem entradas.|{1} Existe uma entrada.|]1,Inf[ Existem %count% entradas.'
+         reading_time: 'tempo estimado de leitura'
+         reading_time_minutes: 'tempo estimado de leitura: %readingTime% min'
+         reading_time_less_one_minute: 'tempo estimado de leitura: <small class="inferieur">&lt;</small> 1 min'
+         number_of_tags: '{1}e uma outra tag|]1,Inf[e %count% outras tags'
+         reading_time_minutes_short: '%readingTime% min'
+         reading_time_less_one_minute_short: '<small class="inferieur">&lt;</small> 1 min'
+         original_article: 'original'
+         toogle_as_read: 'Marcar como lido'
+         toogle_as_star: 'Marcar como destacado'
+         delete: 'Apagar'
+         export_title: 'Exportar'
+     filters:
+         title: 'Filtros'
+         status_label: 'Status'
+         archived_label: 'Arquivado'
+         starred_label: 'Destacado'
+         unread_label: 'Não Lido'
+         preview_picture_label: 'Possui uma imagem de preview'
+         preview_picture_help: 'Imagem de preview'
+         language_label: 'Idioma'
+         reading_time:
+             label: 'Tempo de leitura em minutos'
+             from: 'de'
+             to: 'para'
+         domain_label: 'Nome do domínio'
+         created_at:
+             label: 'Data de criação'
+             from: 'de'
+             to: 'para'
+         action:
+             clear: 'Limpar'
+             filter: 'Filtro'
+     view:
+         left_menu:
+             back_to_top: 'Voltar ao topo'
+             back_to_homepage: 'Voltar'
+             set_as_read: 'Marcar como lido'
+             set_as_unread: 'Marcar como não lido'
+             set_as_starred: 'Alternar destaque'
+             view_original_article: 'Artigo original'
+             re_fetch_content: 'Recapturar o conteúdo'
+             delete: 'Apagar'
+             add_a_tag: 'Adicionar uma tag'
+             share_content: 'Compartilhar'
+             share_email_label: 'E-mail'
+             public_link: 'link público'
+             delete_public_link: 'apagar link público'
+             download: 'Download'
+             print: 'Imprimir'
+             problem:
+                 label: 'Problemas?'
+                 description: 'este artigo aparece errado?'
+         edit_title: 'Editar título'
+         original_article: 'original'
+         annotations_on_the_entry: '{0} Sem anotações|{1} Uma anotação|]1,Inf[ %nbAnnotations% anotações'
+         created_at: 'Data de criação'
+     new:
+         page_title: 'Salvar nova entrada'
+         placeholder: 'http://website.com'
+         form_new:
+             url_label: Url
+     edit:
+         page_title: 'Editar uma entrada'
+         title_label: 'Título'
+         url_label: 'Url'
+         is_public_label: 'Público'
+         save_label: 'Salvar'
+     public:
+         shared_by_wallabag: "Este artigo foi compartilhado pelo <a href='%wallabag_instance%'>wallabag</a>"
+ about:
+     page_title: 'Sobre'
+     top_menu:
+         who_behind_wallabag: 'Quem está por trás do wallabag'
+         getting_help: 'Obtendo ajuda'
+         helping: 'Ajudando o wallabag'
+         contributors: 'Contribuidores'
+         third_party: 'Bibliotecas terceiras'
+     who_behind_wallabag:
+         developped_by: 'Desenvolvido por'
+         website: 'website'
+         many_contributors: 'E muitos outros contribuidores ♥ <a href="https://github.com/wallabag/wallabag/graphs/contributors">no Github</a>'
+         project_website: 'Website do projeto'
+         license: 'Licença'
+         version: 'Versão'
+     getting_help:
+         documentation: 'Documentação'
+         bug_reports: 'Informar bugs'
+         support: '<a href="https://support.wallabag.org">Em nosso site de suporte</a> ou <a href="https://github.com/wallabag/wallabag/issues">no GitHub</a>'
+     helping:
+         description: 'wallabag é livre e software livre. Você pode nos ajudar:'
+         by_contributing: 'contribuindo com o projeto:'
+         by_contributing_2: 'uma lista de todas as nossas necessidades'
+         by_paypal: 'via Paypal'
+     contributors:
+         description: 'Obrigado por contribuir com a aplicação web wallabag'
+     third_party:
+         description: 'Aqui está a lista de bibliotecas terceiras usadas no wallabag (com suas licenças):'
+         package: 'Pacote'
+         license: 'Licença'
+ howto:
+     page_title: 'How to'
+     page_description: 'Existem diferentes formas de salvar um artigo:'
+     top_menu:
+         browser_addons: 'Extensões de navegadores'
+         mobile_apps: "App's móveis"
+         bookmarklet: 'Bookmarklet'
+     form:
+         description: 'Obrigado por este formulário'
+     browser_addons:
+         firefox: 'Extensão padrão do Firefox'
+         chrome: 'Extensão do Chrome'
+     mobile_apps:
+         android:
+             via_f_droid: 'via F-Droid'
+             via_google_play: 'via Google Play'
+         ios: 'na iTunes Store'
+         windows: 'na Microsoft Store'
+     bookmarklet:
+         description: 'Arraste e solve este link na sua barra de favoritos:'
+ quickstart:
+     page_title: 'Começo Rápido'
+     more: 'Mais...'
+     intro:
+         title: 'Bem-vindo ao wallabag!'
+         paragraph_1: 'Nós podemos acompanhar você em sua visita ao wallabag e mostrar algumas funcionalidades que podem lhe interessar.'
+         paragraph_2: 'Siga-nos!'
+     configure:
+         title: 'Configurar a aplicação'
+         description: 'Para ter uma aplicação que atende você, dê uma olhada na configuração do wallabag.'
+         language: 'Alterar idioma e design'
+         rss: 'Habilitar feeds RSS'
+         tagging_rules: 'Escrever regras para acrescentar tags automaticamente em seus artigos'
+     admin:
+         title: 'Administração'
+         description: 'Como administrador você tem privilégios no wallabag. Você pode:'
+         new_user: 'Criar um novo usuário'
+         analytics: 'Configurar o analytics'
+         sharing: 'habilitar alguns parâmetros para compartilhamento de artigos'
+         export: 'Configurar exportação'
+         import: 'Configurar importação'
+     first_steps:
+         title: 'Primeiros passos'
+         description: "Agora o wallabag está bem configurado, é hora de arquivar a web. Você pode clicar no sinal de + no topo a direita para adicionar um link."
+         new_article: 'Salvar seu primeiro artigo'
+         unread_articles: 'E classificá-lo!'
+     migrate:
+         title: 'Migrar de um serviço existente'
+         description: 'Você está usando um outro serviço? Nós podemos ajudá-lo a recuperar seus dados para o wallabag.'
+         pocket: 'Migrar do Pocket'
+         wallabag_v1: 'Migrar do wallabag v1'
+         wallabag_v2: 'Migrar do wallabag v2'
+         readability: 'Migrate from Readability'
+         instapaper: 'Migrate from Instapaper'
+     developer:
+         title: 'Desenvolvedores'
+         description: 'Nós também agradecemos os desenvolvedores: Docker, API, traduções, etc.'
+         create_application: 'Criar sua aplicação terceira'
+         use_docker: 'Usar o Docker para instalar o wallabag'
+     docs:
+         title: 'Documentação completa'
+         description: "Existem muitas funcionalidades no wallabag. Não hesite em ler o manual para conhecê-las e aprender como usá-las."
+         annotate: 'Anotar seu artigo'
+         export: 'Converter seu artigo em ePUB ou PDF'
+         search_filters: 'veja coo você pode encontrar um artigo usanndo o motor de busca e filtros'
+         fetching_errors: 'O que eu posso fazer quando um artigo encontra erros na recuperação?'
+         all_docs: 'E outros muitos artigos!'
+     support:
+         title: 'Suporte'
+         description: 'Se você precisa de ajuda, nós estamos aqui.'
+         github: 'No GitHub'
+         email: 'Por e-mail'
+         gitter: 'No Gitter'
+ tag:
+     page_title: 'Tags'
+     list:
+         number_on_the_page: '{0} Não existem tags.|{1} Uma tag.|]1,Inf[ Existem %count% tags.'
+         see_untagged_entries: 'Ver entradas sem tags'
+ import:
+     page_title: 'Importar'
+     page_description: 'Bem-vindo ao importador do wallabag. Por favo selecione o serviço do qual deseja migrar.'
+     action:
+         import_contents: 'Importar conteúdos'
+     form:
+         mark_as_read_title: 'Marcar todos como lidos?'
+         mark_as_read_label: 'Marcar todas as entradas importadas como lidas'
+         file_label: 'Arquivo'
+         save_label: 'Carregar arquivo'
+     pocket:
+         page_title: 'Importar > Pocket'
+         description: 'Com este importador você importa todos os seus dados do Pocket. O Pocket não nos permite recuperar o conteúdo de seu serviço, então o conteúdo que pode ser lido é recarregado pelo wallabag.'
+         config_missing:
+             description: 'O importador do Pocket não está configurado.'
+             admin_message: 'Você precisa definir uma %keyurls%a pocket_consumer_key%keyurle%.'
+             user_message: 'Seu administrador do servidor precisa definir uma chave de API para o Pocket.'
+         authorize_message: 'Você pode importar seus dados de sua conta do Pocket. Você somente precisa clicar no botão abaixo e autorizar a aplicação a conectar-se ao getpocket.com.'
+         connect_to_pocket: 'Conecte ao Pocket e importe os dados'
+     wallabag_v1:
+         page_title: 'Importar > Wallabag v1'
+         description: 'Com este importador você importa todos os seus artigos do wallabag v1. Na sua página de configuração, clique em "JSON export" na opção "Export your wallabag data". Você irá criar um arquivo "wallabag-export-1-xxxx-xx-xx.json".'
+         how_to: 'Por favor, selecione seu exportador wallabag e clique no botão abaixo para carregar e importar.'
+     wallabag_v2:
+         page_title: 'Importar > Wallabag v2'
+         description: 'Com este importador você importa todos os seus artigos do wallabag v2. Vá em Todos os artigos e então, na barra lateral de exportação, clique em "JSON". Você irá criar um arquivo "All articles.json".'
+     readability:
+         page_title: 'Importar > Readability'
+         description: 'Este importador pode importar todos os artigos do Readability. Nas página ferramentas (https://www.readability.com/tools/), clique em "Export your data" na seção "Data Export". Você receberá um e-mail para fazer o download de um json (que de fato não termina com .json).'
+         how_to: 'Por favor, selecione sua exportação do Readability e clique no botão abaixo para importá-la.'
+     worker:
+         enabled: "A importação é feita assíncronamente. Uma vez que a tarefa de importação é iniciada, um trabalho externo pode executar tarefas uma por vez. O serviço atual é:"
+     firefox:
+         page_title: 'Importar > Firefox'
+         description: "Com este importador você importa todos os favoritos de seu Firefox. Somente vá até seus favoritos (Ctrl+Maj+O), e em \"Importar e Backup\" e escolha \"Backup...\". Você terá então um arquivo .json."
+         how_to: "Por favor, escolha o arquivo de backup dos favoritos e clique no botão abaixo para importá-lo. Note que o processo pode demorar até que todos os artigos tenham sido copiados."
+     chrome:
+         page_title: 'Importar > Chrome'
+         description: "Com este importador você importa todos os favoritos de seu Chrome. A localização do arquivo depende de seu sistema operacional: <ul><li>Em Linux, vá para o diretório <code>~/.config/chromium/Default/</code></li><li>Em Windows, ele deve estar em <code>%LOCALAPPDATA%\\Google\\Chrome\\User Data\\Default</code></li><li>Em OS X, ele deve estar em <code>~/Library/Application Support/Google/Chrome/Default/Bookmarks</code></li></ul>Uma vez que você pegou o arquivo, copie-o para algum lugar que você o encontre.<em><br>Note que se você possui o Chromium ao invés do Chrome, você precisa corrigir os caminhos.</em></p>"
+         how_to: "Por favor, escolha o arquivo de backup dos favoritos e clique no botão abaixo para importá-lo. Note que o processo pode demorar até que todos os artigos tenham sido copiados."
+     instapaper:
+         page_title: 'Importar > Instapaper'
+         description: 'Este importador pode importar todos os artigos do seu Instapaper. Nas página de configurações (https://www.instapaper.com/user), clique em "Download .CSV file" na seção "Export". Um arquivo CSV será baixado (algo como "instapaper-export.csv").'
+         how_to: 'Por favor, selecione sua exportação do seu Instapaper e clique no botão abaixo para importá-la.'
+ developer:
+     page_title: 'Desenvolvedor'
+     welcome_message: 'Bem-vindo a API do wallabag'
+     documentation: 'Documentação'
+     how_to_first_app: 'Como criar minha primeira aplicação'
+     full_documentation: 'Ver a documentação completa da API'
+     list_methods: 'Lista de métodos da API'
+     clients:
+         title: 'Clientes'
+         create_new: 'Criar um novo cliente'
+     existing_clients:
+         title: 'Clientes existentes'
+         field_id: 'ID do cliente'
+         field_secret: 'Chave do cliente'
+         field_uris: 'URIs de redirecionamento'
+         field_grant_types: 'Tipo permitido'
+         no_client: 'Nenhum cliente até agora.'
+     remove:
+         warn_message_1: 'Você tem permissão pare remover este cliente. Esta ação é IRREVERSÍVEL !'
+         warn_message_2: 'Se você remover isso, todo o aplicativo configurado com este cliente não poderá se autenticar no seu wallabag.'
+         action: 'Remover este cliente'
+     client:
+         page_title: 'Desenvolvedor > Novo cliente'
+         page_description: 'Você está prestes a criar um novo cliente. Por favor preencha o campo abaixo para a URI de redirecionamento de sua aplicação.'
+         form:
+             name_label: 'Nome do cliente'
+             redirect_uris_label: 'URIs de redirecionamento'
+             save_label: 'Criar um novo cliente'
+         action_back: 'Voltar'
+     client_parameter:
+         page_title: 'Desenvolvedor > Parâmetros de clientes'
+         page_description: 'Aqui estão os parâmetros de seus clientes.'
+         field_name: 'Nome do cliente'
+         field_id: 'ID do cliente'
+         field_secret: 'Chave do cliente'
+         back: 'Voltar'
+         read_howto: 'Leia o how-to "Criar minha primeira aplicação"'
+     howto:
+         page_title: 'Desenvolvedor > Criar minha primeira aplicação'
+         description:
+             paragraph_1: 'Os seguintes comandos fazem uso da <a href="https://github.com/jkbrzt/httpie">biblioteca HTTPie</a>. Tenha certeza que ela está instalada em seu servidor antes de usá-la.'
+             paragraph_2: 'Você precisa de um token para a comunicação entre sua aplicação terceira e a API do wallabag.'
+             paragraph_3: 'Para criar este token, você precisa <a href="%link%">criar um novo cliente</a>.'
+             paragraph_4: 'Agora, crie seu token (altere client_id, client_secret, username e password com os valores corretos):'
+             paragraph_5: 'A API pode retornar uma resposta como essa:'
+             paragraph_6: 'O access_token é utilizável para fazer uma chamada para o endpoint da API. Por exemplo:'
+             paragraph_7: 'Esta chamada pode retornar todas as entradas de seu usuário.'
+             paragraph_8: 'Se você deseja ver todos os endpoints da API, dê uma olhada <a href="%link%">em nossa documentação da API</a>.'
+         back: 'Voltar'
+ user:
+     page_title: 'Gerenciamento de Usuários'
+     new_user: 'Criar um novo usuário'
+     edit_user: 'Editar um usuário existente'
+     description: 'Aqui você gerencia todos os usuários (cria, edita e apaga)'
+     list:
+         actions: 'Ações'
+         edit_action: 'Editar'
+         yes: 'Sim'
+         no: 'Não'
+         create_new_one: 'Criar um novo usuário'
+     form:
+         username_label: 'Nome de Usuário'
+         name_label: 'Nome'
+         password_label: 'Senha'
+         repeat_new_password_label: 'Repita a nova senha'
+         plain_password_label: '????'
+         email_label: 'E-mail'
+         enabled_label: 'Habilitado'
+         locked_label: 'Travado'
+         last_login_label: 'Último login'
+         twofactor_label: 'Autenticação de dois passos'
+         save: 'Salvar'
+         delete: 'Apagar'
+         delete_confirm: 'Tem certeza?'
+         back_to_list: 'Voltar para a lista'
+ flashes:
+     config:
+         notice:
+             config_saved: 'Configiração salva. Alguns parâmetros podem ser considerados depois da desconexão.'
+             password_updated: 'Senha atualizada'
+             password_not_updated_demo: 'Em modo de demonstração, você não pode alterar a senha deste usuário.'
+             rss_updated: 'Informação de RSS atualizada'
+             tagging_rules_updated: 'Regras de tags atualizadas'
+             tagging_rules_deleted: 'Regra de tag apagada'
+             rss_token_updated: 'Token RSS atualizado'
+     entry:
+         notice:
+             entry_already_saved: 'Entrada já foi salva em %date%'
+             entry_saved: 'Entrada salva'
+             entry_saved_failed: 'Failed to save entry'
+             entry_updated: 'Entrada atualizada'
+             entry_reloaded: 'Entrada recarregada'
+             entry_reloaded_failed: 'Falha em recarregar a entrada'
+             entry_archived: 'Entrada arquivada'
+             entry_unarchived: 'Entrada desarquivada'
+             entry_starred: 'Entrada destacada'
+             entry_unstarred: 'Entrada não destacada'
+             entry_deleted: 'Entrada apagada'
+     tag:
+         notice:
+             tag_added: 'Tag adicionada'
+     import:
+         notice:
+             failed: 'Importação falhou, por favor tente novamente.'
+             failed_on_file: 'Erro ao processar a importação. Por favor verifique seu arquivo de importação.'
+             summary: 'relatório de importação: %imported% importados, %skipped% já existem.'
+             summary_with_queue: 'Importar sumáario: %queued% agendados.'
+         error:
+             redis_enabled_not_installed: 'O Redis está habilitado para importação assíncrona mas parece que <u>não podemos nos conectar nele</u>. Por favor verifique as configurações do Redis.'
+             rabbit_enabled_not_installed: 'O RabbitMQ está habilitado para importação assíncrona mas parece que <u>não podemos nos conectar nele</u>. Por favor verifique as configurações do RabbitMQ.'
+     developer:
+         notice:
+             client_created: 'Novo cliente criado.'
+             client_deleted: 'Cliente removido'
+     user:
+         notice:
+             added: 'Usuário "%username%" adicionado'
+             updated: 'Usuário "%username%" atualizado'
+             deleted: 'Usuário "%username%" removido'
index 070abe274d9223e08600ec3821bf0a845832a617,875c82e8372b29b5bc3195e20b592821fcb5b014..50f1b6a24e1b061cba29bfe24dd7751a60cb978c
@@@ -71,7 -71,6 +71,7 @@@ config
              # 300_word: 'I read ~300 words per minute'
              # 400_word: 'I read ~400 words per minute'
          pocket_consumer_key_label: Cheie consumator pentru importarea contentului din Pocket
 +        # android_configuration: Configure your Android application
      form_rss:
          description: 'Feed-urile RSS oferite de wallabag îți permit să-ți citești articolele salvate în reader-ul tău preferat RSS.'
          token_label: 'RSS-Token'
          name_label: 'Nume'
          email_label: 'E-mail'
          # twoFactorAuthentication_label: 'Two factor authentication'
 +        delete:
 +            # title: Delete my account (a.k.a danger zone)
 +            # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out.
 +            # confirm: Are you really sure? (THIS CAN'T BE UNDONE)
 +            # button: Delete my account
 +    reset:
 +        # title: Reset area (a.k.a danger zone)
 +        # description: By hiting buttons below you'll have ability to remove some informations from your account. Be aware that these actions are IRREVERSIBLE.
 +        # annotations: Remove ALL annotations
 +        # tags: Remove ALL tags
 +        # entries: Remove ALL entries
 +        # confirm: Are you really really sure? (THIS CAN'T BE UNDONE)
      form_password:
          old_password_label: 'Parola veche'
          new_password_label: 'Parola nouă'
@@@ -150,7 -137,7 +150,7 @@@ entry
          # starred: 'Starred entries'
          # archived: 'Archived entries'
          # filtered: 'Filtered entries'
-         # filtered_tags: 'Filtered by tags'
+         # filtered_tags: 'Filtered by tags:'
          # untagged: 'Untagged entries'
      list:
          # number_on_the_page: '{0} There is no entry.|{1} There is one entry.|]1,Inf[ There are %count% entries.'
@@@ -368,7 -355,6 +368,7 @@@ import
      #     how_to: 'Please select your Readability export and click on the below button to upload and import it.'
      worker:
          # enabled: "Import is made asynchronously. Once the import task is started, an external worker will handle jobs one at a time. The current service is:"
 +        # download_images_warning: "You enabled downloading images for your articles. Combined with classic import it can take ages to proceed (or maybe failed). We <strong>strongly recommend</strong> to enable asynchronous import to avoid errors."
      # firefox:
      #    page_title: 'Import > Firefox'
      #    description: "This importer will import all your Firefox bookmarks. Just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file."
@@@ -472,11 -458,8 +472,10 @@@ flashes
              rss_updated: 'Informație RSS actualizată'
              # tagging_rules_updated: 'Tagging rules updated'
              # tagging_rules_deleted: 'Tagging rule deleted'
--            # user_added: 'User "%username%" added'
              # rss_token_updated: 'RSS token updated'
 +            # annotations_reset: Annotations reset
 +            # tags_reset: Tags reset
 +            # entries_reset: Entries reset
      entry:
          notice:
              # entry_already_saved: 'Entry already saved on %date%'
          notice:
              # client_created: 'New client created.'
              # client_deleted: 'Client deleted'
 +    user:
 +        notice:
 +            # added: 'User "%username%" added'
 +            # updated: 'User "%username%" updated'
 +            # deleted: 'User "%username%" deleted'
index 7679b32a6a6121bd6990f2e7a46f4330f1153d03,f50f629a0224261c3eff8f81917874de9bb7d404..07939ebc8e315bb89adb4c356d160c15d03d7ffc
@@@ -71,7 -71,6 +71,7 @@@ config
              # 300_word: 'I read ~300 words per minute'
              # 400_word: 'I read ~400 words per minute'
          # pocket_consumer_key_label: Consumer key for Pocket to import contents
 +        # android_configuration: Configure your Android application
      form_rss:
          description: 'wallabag RSS akışı kaydetmiş olduğunuz makalelerini favori RSS okuyucunuzda görüntülemenizi sağlar. Bunu yapabilmek için öncelikle belirteç (token) oluşturmalısınız.'
          token_label: 'RSS belirteci (token)'
          name_label: 'İsim'
          email_label: 'E-posta'
          twoFactorAuthentication_label: 'İki adımlı doğrulama'
 +        delete:
 +            # title: Delete my account (a.k.a danger zone)
 +            # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out.
 +            # confirm: Are you really sure? (THIS CAN'T BE UNDONE)
 +            # button: Delete my account
 +    reset:
 +        # title: Reset area (a.k.a danger zone)
 +        # description: By hiting buttons below you'll have ability to remove some informations from your account. Be aware that these actions are IRREVERSIBLE.
 +        # annotations: Remove ALL annotations
 +        # tags: Remove ALL tags
 +        # entries: Remove ALL entries
 +        # confirm: Are you really really sure? (THIS CAN'T BE UNDONE)
      form_password:
          old_password_label: 'Eski şifre'
          new_password_label: 'Yeni şifre'
          # if_label: 'if'
          # then_tag_as_label: 'then tag as'
          # delete_rule_label: 'delete'
 +        # edit_rule_label: 'edit'
          rule_label: 'Kural'
          tags_label: 'Etiketler'
          faq:
@@@ -150,7 -136,7 +150,7 @@@ entry
          # starred: 'Starred entries'
          # archived: 'Archived entries'
          # filtered: 'Filtered entries'
-         # filtered_tags: 'Filtered by tags'
+         # filtered_tags: 'Filtered by tags:'
          # untagged: 'Untagged entries'
      list:
          number_on_the_page: '{0} Herhangi bir makale yok.|{1} Burada bir adet makale var.|]1,Inf[ Burada %count% adet makale var.'
@@@ -368,7 -354,6 +368,7 @@@ import
          # how_to: 'Please select your Readability export and click on the below button to upload and import it.'
      worker:
          # enabled: "Import is made asynchronously. Once the import task is started, an external worker will handle jobs one at a time. The current service is:"
 +        # download_images_warning: "You enabled downloading images for your articles. Combined with classic import it can take ages to proceed (or maybe failed). We <strong>strongly recommend</strong> to enable asynchronous import to avoid errors."
      firefox:
         page_title: 'İçe Aktar > Firefox'
         # description: "This importer will import all your Firefox bookmarks. Just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file."
@@@ -472,11 -457,8 +472,10 @@@ flashes
              rss_updated: 'RSS bilgiler güncellendi'
              tagging_rules_updated: 'Tagging rules updated'
              tagging_rules_deleted: 'Tagging rule deleted'
--            user_added: 'User "%username%" added'
              rss_token_updated: 'RSS token updated'
 +            # annotations_reset: Annotations reset
 +            # tags_reset: Tags reset
 +            # entries_reset: Entries reset
      entry:
          notice:
              entry_already_saved: 'Entry already saved on %date%'
          notice:
              # client_created: 'New client created.'
              # client_deleted: 'Client deleted'
 +    user:
 +        notice:
 +            # added: 'User "%username%" added'
 +            # updated: 'User "%username%" updated'
 +            # deleted: 'User "%username%" deleted'
index 2f7a906e38e9752bf3ec39038328445bd72a0c1f,d1325338ddc8125f82dc3d0460b1515b0865859b..13f3dcb994dbf54899356919fcb119f50ee78187
@@@ -14,10 -14,10 +14,10 @@@ class ImportCommand extends ContainerAw
      {
          $this
              ->setName('wallabag:import')
 -            ->setDescription('Import entries from a JSON export from a wallabag v1 instance')
 +            ->setDescription('Import entries from a JSON export')
              ->addArgument('userId', InputArgument::REQUIRED, 'User ID to populate')
              ->addArgument('filepath', InputArgument::REQUIRED, 'Path to the JSON file')
 -            ->addOption('importer', null, InputArgument::OPTIONAL, 'The importer to use: wallabag v1, v2, firefox or chrome', 'v1')
 +            ->addOption('importer', null, InputArgument::OPTIONAL, 'The importer to use: v1, v2, instapaper, readability, firefox or chrome', 'v1')
              ->addOption('markAsRead', null, InputArgument::OPTIONAL, 'Mark all entries as read', false)
          ;
      }
  
          switch ($input->getOption('importer')) {
              case 'v2':
 -                $wallabag = $this->getContainer()->get('wallabag_import.wallabag_v2.import');
 +                $import = $this->getContainer()->get('wallabag_import.wallabag_v2.import');
                  break;
              case 'firefox':
 -                $wallabag = $this->getContainer()->get('wallabag_import.firefox.import');
 +                $import = $this->getContainer()->get('wallabag_import.firefox.import');
                  break;
              case 'chrome':
 -                $wallabag = $this->getContainer()->get('wallabag_import.chrome.import');
 +                $import = $this->getContainer()->get('wallabag_import.chrome.import');
 +                break;
 +            case 'readability':
 +                $import = $this->getContainer()->get('wallabag_import.readability.import');
 +                break;
 +            case 'instapaper':
 +                $import = $this->getContainer()->get('wallabag_import.instapaper.import');
                  break;
+             case 'instapaper':
+                 $wallabag = $this->getContainer()->get('wallabag_import.instapaper.import');
+                 break;
              case 'v1':
              default:
 -                $wallabag = $this->getContainer()->get('wallabag_import.wallabag_v1.import');
 +                $import = $this->getContainer()->get('wallabag_import.wallabag_v1.import');
                  break;
          }
  
 -        $wallabag->setMarkAsRead($input->getOption('markAsRead'));
 -        $wallabag->setUser($user);
 +        $import->setMarkAsRead($input->getOption('markAsRead'));
 +        $import->setUser($user);
  
 -        $res = $wallabag
 +        $res = $import
              ->setFilepath($input->getArgument('filepath'))
              ->import();
  
          if (true === $res) {
 -            $summary = $wallabag->getSummary();
 +            $summary = $import->getSummary();
              $output->writeln('<info>'.$summary['imported'].' imported</info>');
              $output->writeln('<comment>'.$summary['skipped'].' already saved</comment>');
          }
index 8062e53f12fd1a76c3a0b1ad3690c0e5e9468473,a8ee721b9e60f70a66071cc6e698849a92a02152..164a25ec1e77060ec32d9cadcaa61ee1c89fc49b
@@@ -6,7 -6,8 +6,8 @@@ services
              - "@twig"
              - "%scheb_two_factor.email.sender_email%"
              - "%scheb_two_factor.email.sender_name%"
-             - "@craue_config"
+             - '@=service(''craue_config'').get(''wallabag_support_url'')'
+             - '@=service(''craue_config'').get(''wallabag_url'')'
  
      wallabag_user.password_resetting:
          class: Wallabag\UserBundle\EventListener\PasswordResettingListener
@@@ -21,7 -22,7 +22,7 @@@
          arguments:
              - WallabagUserBundle:User
  
 -    wallabag_user.create_config:
 +    wallabag_user.listener.create_config:
          class: Wallabag\UserBundle\EventListener\CreateConfigListener
          arguments:
              - "@doctrine.orm.entity_manager"
index 0000000000000000000000000000000000000000,825f8f7adf4171f45100423aba05abb426257764..566e9493ae811e057daaf28836769f5e4c561e07
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,673 +1,681 @@@
 -        $this->assertTrue(
 -            $this->client->getResponse()->headers->contains(
 -                'Content-Type',
 -                'application/json'
 -            )
 -        );
+ <?php
+ namespace Tests\Wallabag\ApiBundle\Controller;
+ use Tests\Wallabag\ApiBundle\WallabagApiTestCase;
+ use Wallabag\CoreBundle\Entity\Tag;
+ class EntryRestControllerTest extends WallabagApiTestCase
+ {
+     public function testGetOneEntry()
+     {
+         $entry = $this->client->getContainer()
+             ->get('doctrine.orm.entity_manager')
+             ->getRepository('WallabagCoreBundle:Entry')
+             ->findOneBy(['user' => 1, 'isArchived' => false]);
+         if (!$entry) {
+             $this->markTestSkipped('No content found in db.');
+         }
+         $this->client->request('GET', '/api/entries/'.$entry->getId().'.json');
+         $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+         $content = json_decode($this->client->getResponse()->getContent(), true);
+         $this->assertEquals($entry->getTitle(), $content['title']);
+         $this->assertEquals($entry->getUrl(), $content['url']);
+         $this->assertCount(count($entry->getTags()), $content['tags']);
+         $this->assertEquals($entry->getUserName(), $content['user_name']);
+         $this->assertEquals($entry->getUserEmail(), $content['user_email']);
+         $this->assertEquals($entry->getUserId(), $content['user_id']);
 -        $this->assertTrue(
 -            $this->client->getResponse()->headers->contains(
 -                'Content-Type',
 -                'application/json'
 -            )
 -        );
++        $this->assertEquals('application/json', $this->client->getResponse()->headers->get('Content-Type'));
++    }
++
++    public function testExportEntry()
++    {
++        $entry = $this->client->getContainer()
++            ->get('doctrine.orm.entity_manager')
++            ->getRepository('WallabagCoreBundle:Entry')
++            ->findOneBy(['user' => 1, 'isArchived' => false]);
++
++        if (!$entry) {
++            $this->markTestSkipped('No content found in db.');
++        }
++
++        $this->client->request('GET', '/api/entries/'.$entry->getId().'/export.epub');
++        $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
++
++        // epub format got the content type in the content
++        $this->assertContains('application/epub', $this->client->getResponse()->getContent());
++        $this->assertEquals('application/epub+zip', $this->client->getResponse()->headers->get('Content-Type'));
++
++        // re-auth client for mobi
++        $client = $this->createAuthorizedClient();
++        $client->request('GET', '/api/entries/'.$entry->getId().'/export.mobi');
++        $this->assertEquals(200, $client->getResponse()->getStatusCode());
++
++        $this->assertEquals('application/x-mobipocket-ebook', $client->getResponse()->headers->get('Content-Type'));
++
++        // re-auth client for pdf
++        $client = $this->createAuthorizedClient();
++        $client->request('GET', '/api/entries/'.$entry->getId().'/export.pdf');
++        $this->assertEquals(200, $client->getResponse()->getStatusCode());
++
++        $this->assertContains('PDF-', $client->getResponse()->getContent());
++        $this->assertEquals('application/pdf', $client->getResponse()->headers->get('Content-Type'));
++
++        // re-auth client for pdf
++        $client = $this->createAuthorizedClient();
++        $client->request('GET', '/api/entries/'.$entry->getId().'/export.txt');
++        $this->assertEquals(200, $client->getResponse()->getStatusCode());
++
++        $this->assertContains('text/plain', $client->getResponse()->headers->get('Content-Type'));
++
++        // re-auth client for pdf
++        $client = $this->createAuthorizedClient();
++        $client->request('GET', '/api/entries/'.$entry->getId().'/export.csv');
++        $this->assertEquals(200, $client->getResponse()->getStatusCode());
++
++        $this->assertContains('application/csv', $client->getResponse()->headers->get('Content-Type'));
+     }
+     public function testGetOneEntryWrongUser()
+     {
+         $entry = $this->client->getContainer()
+             ->get('doctrine.orm.entity_manager')
+             ->getRepository('WallabagCoreBundle:Entry')
+             ->findOneBy(['user' => 2, 'isArchived' => false]);
+         if (!$entry) {
+             $this->markTestSkipped('No content found in db.');
+         }
+         $this->client->request('GET', '/api/entries/'.$entry->getId().'.json');
+         $this->assertEquals(403, $this->client->getResponse()->getStatusCode());
+     }
+     public function testGetEntries()
+     {
+         $this->client->request('GET', '/api/entries');
+         $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+         $content = json_decode($this->client->getResponse()->getContent(), true);
+         $this->assertGreaterThanOrEqual(1, count($content));
+         $this->assertNotEmpty($content['_embedded']['items']);
+         $this->assertGreaterThanOrEqual(1, $content['total']);
+         $this->assertEquals(1, $content['page']);
+         $this->assertGreaterThanOrEqual(1, $content['pages']);
 -        $this->assertTrue(
 -            $this->client->getResponse()->headers->contains(
 -                'Content-Type',
 -                'application/json'
 -            )
 -        );
++        $this->assertEquals('application/json', $this->client->getResponse()->headers->get('Content-Type'));
+     }
+     public function testGetEntriesWithFullOptions()
+     {
+         $this->client->request('GET', '/api/entries', [
+             'archive' => 1,
+             'starred' => 1,
+             'sort' => 'updated',
+             'order' => 'asc',
+             'page' => 1,
+             'perPage' => 2,
+             'tags' => 'foo',
+             'since' => 1443274283,
+         ]);
+         $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+         $content = json_decode($this->client->getResponse()->getContent(), true);
+         $this->assertGreaterThanOrEqual(1, count($content));
+         $this->assertArrayHasKey('items', $content['_embedded']);
+         $this->assertGreaterThanOrEqual(0, $content['total']);
+         $this->assertEquals(1, $content['page']);
+         $this->assertEquals(2, $content['limit']);
+         $this->assertGreaterThanOrEqual(1, $content['pages']);
+         $this->assertArrayHasKey('_links', $content);
+         $this->assertArrayHasKey('self', $content['_links']);
+         $this->assertArrayHasKey('first', $content['_links']);
+         $this->assertArrayHasKey('last', $content['_links']);
+         foreach (['self', 'first', 'last'] as $link) {
+             $this->assertArrayHasKey('href', $content['_links'][$link]);
+             $this->assertContains('archive=1', $content['_links'][$link]['href']);
+             $this->assertContains('starred=1', $content['_links'][$link]['href']);
+             $this->assertContains('sort=updated', $content['_links'][$link]['href']);
+             $this->assertContains('order=asc', $content['_links'][$link]['href']);
+             $this->assertContains('tags=foo', $content['_links'][$link]['href']);
+             $this->assertContains('since=1443274283', $content['_links'][$link]['href']);
+         }
 -        $this->assertTrue(
 -            $this->client->getResponse()->headers->contains(
 -                'Content-Type',
 -                'application/json'
 -            )
 -        );
++        $this->assertEquals('application/json', $this->client->getResponse()->headers->get('Content-Type'));
+     }
+     public function testGetStarredEntries()
+     {
+         $this->client->request('GET', '/api/entries', ['starred' => 1, 'sort' => 'updated']);
+         $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+         $content = json_decode($this->client->getResponse()->getContent(), true);
+         $this->assertGreaterThanOrEqual(1, count($content));
+         $this->assertNotEmpty($content['_embedded']['items']);
+         $this->assertGreaterThanOrEqual(1, $content['total']);
+         $this->assertEquals(1, $content['page']);
+         $this->assertGreaterThanOrEqual(1, $content['pages']);
+         $this->assertArrayHasKey('_links', $content);
+         $this->assertArrayHasKey('self', $content['_links']);
+         $this->assertArrayHasKey('first', $content['_links']);
+         $this->assertArrayHasKey('last', $content['_links']);
+         foreach (['self', 'first', 'last'] as $link) {
+             $this->assertArrayHasKey('href', $content['_links'][$link]);
+             $this->assertContains('starred=1', $content['_links'][$link]['href']);
+             $this->assertContains('sort=updated', $content['_links'][$link]['href']);
+         }
 -        $this->assertTrue(
 -            $this->client->getResponse()->headers->contains(
 -                'Content-Type',
 -                'application/json'
 -            )
 -        );
++        $this->assertEquals('application/json', $this->client->getResponse()->headers->get('Content-Type'));
+     }
+     public function testGetArchiveEntries()
+     {
+         $this->client->request('GET', '/api/entries', ['archive' => 1]);
+         $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+         $content = json_decode($this->client->getResponse()->getContent(), true);
+         $this->assertGreaterThanOrEqual(1, count($content));
+         $this->assertNotEmpty($content['_embedded']['items']);
+         $this->assertGreaterThanOrEqual(1, $content['total']);
+         $this->assertEquals(1, $content['page']);
+         $this->assertGreaterThanOrEqual(1, $content['pages']);
+         $this->assertArrayHasKey('_links', $content);
+         $this->assertArrayHasKey('self', $content['_links']);
+         $this->assertArrayHasKey('first', $content['_links']);
+         $this->assertArrayHasKey('last', $content['_links']);
+         foreach (['self', 'first', 'last'] as $link) {
+             $this->assertArrayHasKey('href', $content['_links'][$link]);
+             $this->assertContains('archive=1', $content['_links'][$link]['href']);
+         }
 -        $this->assertTrue(
 -            $this->client->getResponse()->headers->contains(
 -                'Content-Type',
 -                'application/json'
 -            )
 -        );
++        $this->assertEquals('application/json', $this->client->getResponse()->headers->get('Content-Type'));
+     }
+     public function testGetTaggedEntries()
+     {
+         $this->client->request('GET', '/api/entries', ['tags' => 'foo,bar']);
+         $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+         $content = json_decode($this->client->getResponse()->getContent(), true);
+         $this->assertGreaterThanOrEqual(1, count($content));
+         $this->assertNotEmpty($content['_embedded']['items']);
+         $this->assertGreaterThanOrEqual(1, $content['total']);
+         $this->assertEquals(1, $content['page']);
+         $this->assertGreaterThanOrEqual(1, $content['pages']);
+         $this->assertArrayHasKey('_links', $content);
+         $this->assertArrayHasKey('self', $content['_links']);
+         $this->assertArrayHasKey('first', $content['_links']);
+         $this->assertArrayHasKey('last', $content['_links']);
+         foreach (['self', 'first', 'last'] as $link) {
+             $this->assertArrayHasKey('href', $content['_links'][$link]);
+             $this->assertContains('tags='.urlencode('foo,bar'), $content['_links'][$link]['href']);
+         }
 -        $this->assertTrue(
 -            $this->client->getResponse()->headers->contains(
 -                'Content-Type',
 -                'application/json'
 -            )
 -        );
++        $this->assertEquals('application/json', $this->client->getResponse()->headers->get('Content-Type'));
+     }
+     public function testGetDatedEntries()
+     {
+         $this->client->request('GET', '/api/entries', ['since' => 1443274283]);
+         $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+         $content = json_decode($this->client->getResponse()->getContent(), true);
+         $this->assertGreaterThanOrEqual(1, count($content));
+         $this->assertNotEmpty($content['_embedded']['items']);
+         $this->assertGreaterThanOrEqual(1, $content['total']);
+         $this->assertEquals(1, $content['page']);
+         $this->assertGreaterThanOrEqual(1, $content['pages']);
+         $this->assertArrayHasKey('_links', $content);
+         $this->assertArrayHasKey('self', $content['_links']);
+         $this->assertArrayHasKey('first', $content['_links']);
+         $this->assertArrayHasKey('last', $content['_links']);
+         foreach (['self', 'first', 'last'] as $link) {
+             $this->assertArrayHasKey('href', $content['_links'][$link]);
+             $this->assertContains('since=1443274283', $content['_links'][$link]['href']);
+         }
 -        $this->assertTrue(
 -            $this->client->getResponse()->headers->contains(
 -                'Content-Type',
 -                'application/json'
 -            )
 -        );
++        $this->assertEquals('application/json', $this->client->getResponse()->headers->get('Content-Type'));
+     }
+     public function testGetDatedSupEntries()
+     {
+         $future = new \DateTime(date('Y-m-d H:i:s'));
+         $this->client->request('GET', '/api/entries', ['since' => $future->getTimestamp() + 1000]);
+         $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+         $content = json_decode($this->client->getResponse()->getContent(), true);
+         $this->assertGreaterThanOrEqual(1, count($content));
+         $this->assertEmpty($content['_embedded']['items']);
+         $this->assertEquals(0, $content['total']);
+         $this->assertEquals(1, $content['page']);
+         $this->assertEquals(1, $content['pages']);
+         $this->assertArrayHasKey('_links', $content);
+         $this->assertArrayHasKey('self', $content['_links']);
+         $this->assertArrayHasKey('first', $content['_links']);
+         $this->assertArrayHasKey('last', $content['_links']);
+         foreach (['self', 'first', 'last'] as $link) {
+             $this->assertArrayHasKey('href', $content['_links'][$link]);
+             $this->assertContains('since='.($future->getTimestamp() + 1000), $content['_links'][$link]['href']);
+         }
++        $this->assertEquals('application/json', $this->client->getResponse()->headers->get('Content-Type'));
+     }
+     public function testDeleteEntry()
+     {
+         $entry = $this->client->getContainer()
+             ->get('doctrine.orm.entity_manager')
+             ->getRepository('WallabagCoreBundle:Entry')
+             ->findOneByUser(1);
+         if (!$entry) {
+             $this->markTestSkipped('No content found in db.');
+         }
+         $this->client->request('DELETE', '/api/entries/'.$entry->getId().'.json');
+         $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+         $content = json_decode($this->client->getResponse()->getContent(), true);
+         $this->assertEquals($entry->getTitle(), $content['title']);
+         $this->assertEquals($entry->getUrl(), $content['url']);
+         // We'll try to delete this entry again
+         $this->client->request('DELETE', '/api/entries/'.$entry->getId().'.json');
+         $this->assertEquals(404, $this->client->getResponse()->getStatusCode());
+     }
+     public function testPostEntry()
+     {
+         $this->client->request('POST', '/api/entries.json', [
+             'url' => 'http://www.lemonde.fr/pixels/article/2015/03/28/plongee-dans-l-univers-d-ingress-le-jeu-de-google-aux-frontieres-du-reel_4601155_4408996.html',
+             'tags' => 'google',
+             'title' => 'New title for my article',
+         ]);
+         $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+         $content = json_decode($this->client->getResponse()->getContent(), true);
+         $this->assertGreaterThan(0, $content['id']);
+         $this->assertEquals('http://www.lemonde.fr/pixels/article/2015/03/28/plongee-dans-l-univers-d-ingress-le-jeu-de-google-aux-frontieres-du-reel_4601155_4408996.html', $content['url']);
+         $this->assertEquals(false, $content['is_archived']);
+         $this->assertEquals(false, $content['is_starred']);
+         $this->assertEquals('New title for my article', $content['title']);
+         $this->assertEquals(1, $content['user_id']);
+         $this->assertCount(1, $content['tags']);
+     }
+     public function testPostSameEntry()
+     {
+         $this->client->request('POST', '/api/entries.json', [
+             'url' => 'http://www.lemonde.fr/pixels/article/2015/03/28/plongee-dans-l-univers-d-ingress-le-jeu-de-google-aux-frontieres-du-reel_4601155_4408996.html',
+             'archive' => '1',
+             'tags' => 'google, apple',
+         ]);
+         $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+         $content = json_decode($this->client->getResponse()->getContent(), true);
+         $this->assertGreaterThan(0, $content['id']);
+         $this->assertEquals('http://www.lemonde.fr/pixels/article/2015/03/28/plongee-dans-l-univers-d-ingress-le-jeu-de-google-aux-frontieres-du-reel_4601155_4408996.html', $content['url']);
+         $this->assertEquals(true, $content['is_archived']);
+         $this->assertEquals(false, $content['is_starred']);
+         $this->assertCount(2, $content['tags']);
+     }
+     public function testPostArchivedAndStarredEntry()
+     {
+         $this->client->request('POST', '/api/entries.json', [
+             'url' => 'http://www.lemonde.fr/idees/article/2016/02/08/preserver-la-liberte-d-expression-sur-les-reseaux-sociaux_4861503_3232.html',
+             'archive' => '1',
+             'starred' => '1',
+         ]);
+         $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+         $content = json_decode($this->client->getResponse()->getContent(), true);
+         $this->assertGreaterThan(0, $content['id']);
+         $this->assertEquals('http://www.lemonde.fr/idees/article/2016/02/08/preserver-la-liberte-d-expression-sur-les-reseaux-sociaux_4861503_3232.html', $content['url']);
+         $this->assertEquals(true, $content['is_archived']);
+         $this->assertEquals(true, $content['is_starred']);
+         $this->assertEquals(1, $content['user_id']);
+     }
+     public function testPostArchivedAndStarredEntryWithoutQuotes()
+     {
+         $this->client->request('POST', '/api/entries.json', [
+             'url' => 'http://www.lemonde.fr/idees/article/2016/02/08/preserver-la-liberte-d-expression-sur-les-reseaux-sociaux_4861503_3232.html',
+             'archive' => 0,
+             'starred' => 1,
+         ]);
+         $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+         $content = json_decode($this->client->getResponse()->getContent(), true);
+         $this->assertGreaterThan(0, $content['id']);
+         $this->assertEquals('http://www.lemonde.fr/idees/article/2016/02/08/preserver-la-liberte-d-expression-sur-les-reseaux-sociaux_4861503_3232.html', $content['url']);
+         $this->assertEquals(false, $content['is_archived']);
+         $this->assertEquals(true, $content['is_starred']);
+     }
+     public function testPatchEntry()
+     {
+         $entry = $this->client->getContainer()
+             ->get('doctrine.orm.entity_manager')
+             ->getRepository('WallabagCoreBundle:Entry')
+             ->findOneByUser(1);
+         if (!$entry) {
+             $this->markTestSkipped('No content found in db.');
+         }
+         // hydrate the tags relations
+         $nbTags = count($entry->getTags());
+         $this->client->request('PATCH', '/api/entries/'.$entry->getId().'.json', [
+             'title' => 'New awesome title',
+             'tags' => 'new tag '.uniqid(),
+             'starred' => '1',
+             'archive' => '0',
+         ]);
+         $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+         $content = json_decode($this->client->getResponse()->getContent(), true);
+         $this->assertEquals($entry->getId(), $content['id']);
+         $this->assertEquals($entry->getUrl(), $content['url']);
+         $this->assertEquals('New awesome title', $content['title']);
+         $this->assertGreaterThan($nbTags, count($content['tags']));
+         $this->assertEquals(1, $content['user_id']);
+     }
+     public function testPatchEntryWithoutQuotes()
+     {
+         $entry = $this->client->getContainer()
+             ->get('doctrine.orm.entity_manager')
+             ->getRepository('WallabagCoreBundle:Entry')
+             ->findOneByUser(1);
+         if (!$entry) {
+             $this->markTestSkipped('No content found in db.');
+         }
+         // hydrate the tags relations
+         $nbTags = count($entry->getTags());
+         $this->client->request('PATCH', '/api/entries/'.$entry->getId().'.json', [
+             'title' => 'New awesome title',
+             'tags' => 'new tag '.uniqid(),
+             'starred' => 1,
+             'archive' => 0,
+         ]);
+         $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+         $content = json_decode($this->client->getResponse()->getContent(), true);
+         $this->assertEquals($entry->getId(), $content['id']);
+         $this->assertEquals($entry->getUrl(), $content['url']);
+         $this->assertEquals('New awesome title', $content['title']);
+         $this->assertGreaterThan($nbTags, count($content['tags']));
+     }
+     public function testGetTagsEntry()
+     {
+         $entry = $this->client->getContainer()
+             ->get('doctrine.orm.entity_manager')
+             ->getRepository('WallabagCoreBundle:Entry')
+             ->findOneWithTags($this->user->getId());
+         $entry = $entry[0];
+         if (!$entry) {
+             $this->markTestSkipped('No content found in db.');
+         }
+         $tags = [];
+         foreach ($entry->getTags() as $tag) {
+             $tags[] = ['id' => $tag->getId(), 'label' => $tag->getLabel(), 'slug' => $tag->getSlug()];
+         }
+         $this->client->request('GET', '/api/entries/'.$entry->getId().'/tags');
+         $this->assertEquals(json_encode($tags, JSON_HEX_QUOT), $this->client->getResponse()->getContent());
+     }
+     public function testPostTagsOnEntry()
+     {
+         $entry = $this->client->getContainer()
+             ->get('doctrine.orm.entity_manager')
+             ->getRepository('WallabagCoreBundle:Entry')
+             ->findOneByUser(1);
+         if (!$entry) {
+             $this->markTestSkipped('No content found in db.');
+         }
+         $nbTags = count($entry->getTags());
+         $newTags = 'tag1,tag2,tag3';
+         $this->client->request('POST', '/api/entries/'.$entry->getId().'/tags', ['tags' => $newTags]);
+         $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+         $content = json_decode($this->client->getResponse()->getContent(), true);
+         $this->assertArrayHasKey('tags', $content);
+         $this->assertEquals($nbTags + 3, count($content['tags']));
+         $entryDB = $this->client->getContainer()
+             ->get('doctrine.orm.entity_manager')
+             ->getRepository('WallabagCoreBundle:Entry')
+             ->find($entry->getId());
+         $tagsInDB = [];
+         foreach ($entryDB->getTags()->toArray() as $tag) {
+             $tagsInDB[$tag->getId()] = $tag->getLabel();
+         }
+         foreach (explode(',', $newTags) as $tag) {
+             $this->assertContains($tag, $tagsInDB);
+         }
+     }
+     public function testDeleteOneTagEntry()
+     {
+         $entry = $this->client->getContainer()
+             ->get('doctrine.orm.entity_manager')
+             ->getRepository('WallabagCoreBundle:Entry')
+             ->findOneWithTags($this->user->getId());
+         $entry = $entry[0];
+         if (!$entry) {
+             $this->markTestSkipped('No content found in db.');
+         }
+         // hydrate the tags relations
+         $nbTags = count($entry->getTags());
+         $tag = $entry->getTags()[0];
+         $this->client->request('DELETE', '/api/entries/'.$entry->getId().'/tags/'.$tag->getId().'.json');
+         $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+         $content = json_decode($this->client->getResponse()->getContent(), true);
+         $this->assertArrayHasKey('tags', $content);
+         $this->assertEquals($nbTags - 1, count($content['tags']));
+     }
+     public function testSaveIsArchivedAfterPost()
+     {
+         $entry = $this->client->getContainer()
+             ->get('doctrine.orm.entity_manager')
+             ->getRepository('WallabagCoreBundle:Entry')
+             ->findOneBy(['user' => 1, 'isArchived' => true]);
+         if (!$entry) {
+             $this->markTestSkipped('No content found in db.');
+         }
+         $this->client->request('POST', '/api/entries.json', [
+             'url' => $entry->getUrl(),
+         ]);
+         $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+         $content = json_decode($this->client->getResponse()->getContent(), true);
+         $this->assertEquals(true, $content['is_archived']);
+     }
+     public function testSaveIsStarredAfterPost()
+     {
+         $entry = $this->client->getContainer()
+             ->get('doctrine.orm.entity_manager')
+             ->getRepository('WallabagCoreBundle:Entry')
+             ->findOneBy(['user' => 1, 'isStarred' => true]);
+         if (!$entry) {
+             $this->markTestSkipped('No content found in db.');
+         }
+         $this->client->request('POST', '/api/entries.json', [
+             'url' => $entry->getUrl(),
+         ]);
+         $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+         $content = json_decode($this->client->getResponse()->getContent(), true);
+         $this->assertEquals(true, $content['is_starred']);
+     }
+     public function testSaveIsArchivedAfterPatch()
+     {
+         $entry = $this->client->getContainer()
+             ->get('doctrine.orm.entity_manager')
+             ->getRepository('WallabagCoreBundle:Entry')
+             ->findOneBy(['user' => 1, 'isArchived' => true]);
+         if (!$entry) {
+             $this->markTestSkipped('No content found in db.');
+         }
+         $this->client->request('PATCH', '/api/entries/'.$entry->getId().'.json', [
+             'title' => $entry->getTitle().'++',
+         ]);
+         $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+         $content = json_decode($this->client->getResponse()->getContent(), true);
+         $this->assertEquals(true, $content['is_archived']);
+     }
+     public function testSaveIsStarredAfterPatch()
+     {
+         $entry = $this->client->getContainer()
+             ->get('doctrine.orm.entity_manager')
+             ->getRepository('WallabagCoreBundle:Entry')
+             ->findOneBy(['user' => 1, 'isStarred' => true]);
+         if (!$entry) {
+             $this->markTestSkipped('No content found in db.');
+         }
+         $this->client->request('PATCH', '/api/entries/'.$entry->getId().'.json', [
+             'title' => $entry->getTitle().'++',
+         ]);
+         $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+         $content = json_decode($this->client->getResponse()->getContent(), true);
+         $this->assertEquals(true, $content['is_starred']);
+     }
+     public function testGetEntriesExists()
+     {
+         $this->client->request('GET', '/api/entries/exists?url=http://0.0.0.0/entry2');
+         $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+         $content = json_decode($this->client->getResponse()->getContent(), true);
+         $this->assertEquals(true, $content['exists']);
+     }
+     public function testGetEntriesExistsWithManyUrls()
+     {
+         $url1 = 'http://0.0.0.0/entry2';
+         $url2 = 'http://0.0.0.0/entry10';
+         $this->client->request('GET', '/api/entries/exists?urls[]='.$url1.'&urls[]='.$url2);
+         $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+         $content = json_decode($this->client->getResponse()->getContent(), true);
+         $this->assertArrayHasKey($url1, $content);
+         $this->assertArrayHasKey($url2, $content);
+         $this->assertEquals(true, $content[$url1]);
+         $this->assertEquals(false, $content[$url2]);
+     }
+     public function testGetEntriesExistsWhichDoesNotExists()
+     {
+         $this->client->request('GET', '/api/entries/exists?url=http://google.com/entry2');
+         $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+         $content = json_decode($this->client->getResponse()->getContent(), true);
+         $this->assertEquals(false, $content['exists']);
+     }
+     public function testGetEntriesExistsWithNoUrl()
+     {
+         $this->client->request('GET', '/api/entries/exists?url=');
+         $this->assertEquals(403, $this->client->getResponse()->getStatusCode());
+     }
+ }