Compare commits

..

3 Commits

Author SHA1 Message Date
b4f1776828 cleanup 2025-10-02 11:56:06 +02:00
5629330cb6 Remove voter & add tests 2025-10-02 11:54:12 +02:00
7e7674a4a6 Add availability to disable an importer 2025-05-26 16:37:13 +02:00
91 changed files with 1339 additions and 3160 deletions

2
.github/CODEOWNERS vendored
View File

@ -1,2 +0,0 @@
# Migrated rules from dependabot.yml
composer.* @Kdecherf @j0k3r @yguedidi

View File

@ -35,6 +35,10 @@ updates:
phpstan-dependencies:
patterns:
- "phpstan/*"
reviewers:
- j0k3r
- yguedidi
- Kdecherf
ignore:
- dependency-name: symfony/*
update-types: [ "version-update:semver-major" ]

View File

@ -17,7 +17,7 @@ jobs:
steps:
- name: "Checkout"
uses: "actions/checkout@v5"
uses: "actions/checkout@v4"
- name: "Install PHP"
uses: "shivammathur/setup-php@v2"

View File

@ -41,7 +41,7 @@ jobs:
steps:
- name: "Checkout"
uses: "actions/checkout@v5"
uses: "actions/checkout@v4"
with:
fetch-depth: 2
@ -116,7 +116,7 @@ jobs:
steps:
- name: "Checkout"
uses: "actions/checkout@v5"
uses: "actions/checkout@v4"
with:
fetch-depth: 2
@ -187,7 +187,7 @@ jobs:
steps:
- name: "Checkout"
uses: "actions/checkout@v5"
uses: "actions/checkout@v4"
with:
fetch-depth: 2

View File

@ -22,7 +22,7 @@ jobs:
steps:
- name: "Checkout"
uses: "actions/checkout@v5"
uses: "actions/checkout@v4"
- name: "Install PHP"
uses: "shivammathur/setup-php@v2"

View File

@ -16,7 +16,7 @@ jobs:
steps:
- name: "Checkout"
uses: "actions/checkout@v5"
uses: "actions/checkout@v4"
- name: "Install PHP"
uses: "shivammathur/setup-php@v2"

View File

@ -5,22 +5,6 @@
* **[BC BREAK]** Convert 403 errors to 404 errors by @yguedidi in https://github.com/wallabag/wallabag/pull/8075
* `wallassets/` folder renamed to `build/`
## [2.6.13](https://github.com/wallabag/wallabag/tree/2.6.13)
[Full Changelog](https://github.com/wallabag/wallabag/compare/2.6.12...2.6.13)
### Improvements
* Add support of Pocket CSV import by @kdecherf and @nicosomb in [https://github.com/wallabag/wallabag/pull/8240](https://github.com/wallabag/wallabag/pull/8240)
* Backport Pocket and Shaarli HTML imports from master by @nicosomb in [https://github.com/wallabag/wallabag/pull/8193](https://github.com/wallabag/wallabag/pull/8193)
### Fixes
* Avoid non-validated OTP to be enabled #8139 by @j0k3r in [https://github.com/wallabag/wallabag/pull/8139](https://github.com/wallabag/wallabag/pull/8139)
### Technical stuff
* Update j0k3r/php-readability:1.2.13 to fix regression (about latin1 instead of UTF-8 used for entries) by @nicosomb [https://github.com/wallabag/wallabag/pull/8194](https://github.com/wallabag/wallabag/pull/8194)
## [2.6.12](https://github.com/wallabag/wallabag/tree/2.6.12)
[Full Changelog](https://github.com/wallabag/wallabag/compare/2.6.11...2.6.12)
@ -29,6 +13,7 @@
* Fix changelog by @yguedidi in [https://github.com/wallabag/wallabag/pull/8135](https://github.com/wallabag/wallabag/pull/8135)
* Update dependencies by @yguedidi in [https://github.com/wallabag/wallabag/pull/8136](https://github.com/wallabag/wallabag/pull/8136)
## [2.6.11](https://github.com/wallabag/wallabag/tree/2.6.11)
[Full Changelog](https://github.com/wallabag/wallabag/compare/2.6.10...2.6.11)

View File

@ -1,6 +1,6 @@
# wallabag
[![CI](https://github.com/wallabag/wallabag/actions/workflows/continuous-integration.yml/badge.svg?branch=master)](https://github.com/wallabag/wallabag/actions/workflows/continuous-integration.yml?query=branch%3Amaster)
![CI](https://github.com/wallabag/wallabag/workflows/CI/badge.svg)
[![Matrix](https://matrix.to/img/matrix-badge.svg)](https://matrix.to/#/#wallabag:matrix.org)
[![Donation Status](https://img.shields.io/liberapay/goal/wallabag.svg?logo=liberapay)](https://liberapay.com/wallabag/donate)
[![Translation status](https://hosted.weblate.org/widgets/wallabag/-/svg-badge.svg)](https://hosted.weblate.org/engage/wallabag/?utm_source=widget)

View File

@ -305,11 +305,6 @@ old_sound_rabbit_mq:
exchange_options:
name: 'wallabag.import.pocket_html'
type: topic
import_pocket_csv:
connection: default
exchange_options:
name: 'wallabag.import.pocket_csv'
type: topic
consumers:
import_pocket:
connection: default
@ -428,15 +423,6 @@ old_sound_rabbit_mq:
name: 'wallabag.import.pocket_html'
callback: wallabag.consumer.amqp.pocket_html
qos_options: {prefetch_count: "%rabbitmq_prefetch_count%"}
import_pocket_csv:
connection: default
exchange_options:
name: 'wallabag.import.pocket_csv'
type: topic
queue_options:
name: 'wallabag.import.pocket_csv'
callback: wallabag.consumer.amqp.pocket_csv
qos_options: {prefetch_count: "%rabbitmq_prefetch_count%"}
fos_js_routing:
routes_to_expose:

View File

@ -108,11 +108,6 @@ services:
$rabbitMqProducer: '@old_sound_rabbit_mq.import_pocket_html_producer'
$redisProducer: '@wallabag.producer.redis.pocket_html'
Wallabag\Controller\Import\PocketCsvController:
arguments:
$rabbitMqProducer: '@old_sound_rabbit_mq.import_pocket_csv_producer'
$redisProducer: '@wallabag.producer.redis.pocket_csv'
Wallabag\Doctrine\MigrationFactoryDecorator:
decorates: doctrine.migrations.migrations_factory
@ -281,62 +276,83 @@ services:
Wallabag\Import\PocketImport:
calls:
- [ setEnabled, [ '@=service(''craue_config'').get(''pocket_enabled'')' ] ]
- [ setClient, [ '@Symfony\Contracts\HttpClient\HttpClientInterface $pocketClient' ] ]
tags:
- { name: wallabag.import, alias: pocket }
Wallabag\Import\WallabagV1Import:
calls:
- [ setEnabled, [ '@=service(''craue_config'').get(''wallabag_v1_enabled'')' ] ]
tags:
- { name: wallabag.import, alias: wallabag_v1 }
Wallabag\Import\WallabagV2Import:
calls:
- [ setEnabled, [ '@=service(''craue_config'').get(''wallabag_v2_enabled'')' ] ]
tags:
- { name: wallabag.import, alias: wallabag_v2 }
Wallabag\Import\ElcuratorImport:
calls:
- [ setEnabled, [ '@=service(''craue_config'').get(''elcurator_enabled'')' ] ]
tags:
- { name: wallabag.import, alias: elcurator }
Wallabag\Import\ReadabilityImport:
calls:
- [ setEnabled, [ '@=service(''craue_config'').get(''readability_enabled'')' ] ]
tags:
- { name: wallabag.import, alias: readability }
Wallabag\Import\InstapaperImport:
calls:
- [ setEnabled, [ '@=service(''craue_config'').get(''instapaper_enabled'')' ] ]
tags:
- { name: wallabag.import, alias: instapaper }
Wallabag\Import\PinboardImport:
calls:
- [ setEnabled, [ '@=service(''craue_config'').get(''pinboard_enabled'')' ] ]
tags:
- { name: wallabag.import, alias: pinboard }
Wallabag\Import\DeliciousImport:
calls:
- [ setEnabled, [ '@=service(''craue_config'').get(''delicious_enabled'')' ] ]
tags:
- { name: wallabag.import, alias: delicious }
Wallabag\Import\OmnivoreImport:
calls:
- [ setEnabled, [ '@=service(''craue_config'').get(''omnivore_enabled'')' ] ]
tags:
- { name: wallabag.import, alias: omnivore }
Wallabag\Import\FirefoxImport:
calls:
- [ setEnabled, [ '@=service(''craue_config'').get(''firefox_enabled'')' ] ]
tags:
- { name: wallabag.import, alias: firefox }
Wallabag\Import\ChromeImport:
calls:
- [ setEnabled, [ '@=service(''craue_config'').get(''chrome_enabled'')' ] ]
tags:
- { name: wallabag.import, alias: chrome }
Wallabag\Import\ShaarliImport:
calls:
- [ setEnabled, [ '@=service(''craue_config'').get(''shaarli_enabled'')' ] ]
tags:
- { name: wallabag.import, alias: shaarli }
Wallabag\Import\PocketHtmlImport:
calls:
- [ setEnabled, [ '@=service(''craue_config'').get(''pocket_html_enabled'')' ] ]
tags:
- { name: wallabag.import, alias: pocket_html }
Wallabag\Import\PocketCsvImport:
tags:
- { name: wallabag.import, alias: pocket_csv }
# to factorize the proximity and bypass translation for prev & next
pagerfanta.view.default_wallabag:
class: Pagerfanta\View\OptionableView

View File

@ -20,7 +20,6 @@ services:
$elcuratorConsumer: '@old_sound_rabbit_mq.import_elcurator_consumer'
$shaarliConsumer: '@old_sound_rabbit_mq.import_shaarli_consumer'
$pocketHtmlConsumer: '@old_sound_rabbit_mq.import_pocket_html_consumer'
$pocketCsvConsumer: '@old_sound_rabbit_mq.import_pocket_csv_consumer'
$omnivoreConsumer: '@old_sound_rabbit_mq.import_omnivore_consumer'
wallabag.consumer.amqp.pocket:
@ -87,8 +86,3 @@ services:
class: Wallabag\Consumer\AMQPEntryConsumer
arguments:
$import: '@Wallabag\Import\PocketHtmlImport'
wallabag.consumer.amqp.pocket_csv:
class: Wallabag\Consumer\AMQPEntryConsumer
arguments:
$import: '@Wallabag\Import\PocketCsvImport'

View File

@ -212,19 +212,3 @@ services:
class: Wallabag\Consumer\RedisEntryConsumer
arguments:
$import: '@Wallabag\Import\PocketHtmlImport'
# pocket csv
wallabag.queue.redis.pocket_csv:
class: Simpleue\Queue\RedisQueue
arguments:
$queueName: "wallabag.import.pocket_csv"
wallabag.producer.redis.pocket_csv:
class: Wallabag\Redis\Producer
arguments:
- "@wallabag.queue.redis.pocket_csv"
wallabag.consumer.redis.pocket_csv:
class: Wallabag\Consumer\RedisEntryConsumer
arguments:
$import: '@Wallabag\Import\PocketCsvImport'

View File

@ -126,6 +126,58 @@ parameters:
name: import_with_rabbitmq
value: 0
section: import
-
name: pocket_enabled
value: 1
section: import
-
name: wallabag_v1_enabled
value: 1
section: import
-
name: wallabag_v2_enabled
value: 1
section: import
-
name: elcurator_enabled
value: 1
section: import
-
name: readability_enabled
value: 1
section: import
-
name: instapaper_enabled
value: 1
section: import
-
name: pinboard_enabled
value: 1
section: import
-
name: delicious_enabled
value: 1
section: import
-
name: omnivore_enabled
value: 1
section: import
-
name: firefox_enabled
value: 1
section: import
-
name: chrome_enabled
value: 1
section: import
-
name: shaarli_enabled
value: 1
section: import
-
name: pocket_html_enabled
value: 1
section: import
-
name: matomo_enabled
value: 0

View File

@ -23,7 +23,6 @@ $config
'friendsoftwig/twigcs',
'incenteev/composer-parameter-handler',
'j0k3r/graby-site-config',
'j0k3r/php-readability',
'laminas/laminas-code',
'lcobucci/jwt',
'mgargano/simplehtmldom',

View File

@ -70,7 +70,7 @@
"doctrine/orm": "^2.20.2",
"doctrine/persistence": "^3.4",
"egulias/email-validator": "^4.0.4",
"enshrined/svg-sanitize": "^0.22",
"enshrined/svg-sanitize": "^0.21",
"friendsofsymfony/jsrouting-bundle": "^3.5",
"friendsofsymfony/oauth-server-bundle": "dev-master#dc8ff343363cf794d30eb1a123610d186a43f162",
"friendsofsymfony/rest-bundle": "^3.8",
@ -80,7 +80,6 @@
"incenteev/composer-parameter-handler": "^2.2",
"j0k3r/graby": "^2.4.6",
"j0k3r/graby-site-config": "^1.0.197",
"j0k3r/php-readability": "^1.2.13",
"javibravo/simpleue": "^2.1",
"jms/serializer": "^3.32.3",
"jms/serializer-bundle": "^5.5.1",

274
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "58a7696a7e938ab8a69c7faf2444cd09",
"content-hash": "00b8f95df6ec0572c06ad6f34847405c",
"packages": [
{
"name": "babdev/pagerfanta-bundle",
@ -776,16 +776,16 @@
},
{
"name": "doctrine/dbal",
"version": "3.9.5",
"version": "3.9.4",
"source": {
"type": "git",
"url": "https://github.com/doctrine/dbal.git",
"reference": "4a4e2eed3134036ee36a147ee0dac037dfa17868"
"reference": "ec16c82f20be1a7224e65ac67144a29199f87959"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/dbal/zipball/4a4e2eed3134036ee36a147ee0dac037dfa17868",
"reference": "4a4e2eed3134036ee36a147ee0dac037dfa17868",
"url": "https://api.github.com/repos/doctrine/dbal/zipball/ec16c82f20be1a7224e65ac67144a29199f87959",
"reference": "ec16c82f20be1a7224e65ac67144a29199f87959",
"shasum": ""
},
"require": {
@ -798,14 +798,14 @@
"psr/log": "^1|^2|^3"
},
"require-dev": {
"doctrine/coding-standard": "13.0.0",
"doctrine/coding-standard": "12.0.0",
"fig/log-test": "^1",
"jetbrains/phpstorm-stubs": "2023.1",
"phpstan/phpstan": "2.1.17",
"phpstan/phpstan": "2.1.1",
"phpstan/phpstan-strict-rules": "^2",
"phpunit/phpunit": "9.6.23",
"slevomat/coding-standard": "8.16.2",
"squizlabs/php_codesniffer": "3.13.1",
"phpunit/phpunit": "9.6.22",
"slevomat/coding-standard": "8.13.1",
"squizlabs/php_codesniffer": "3.10.2",
"symfony/cache": "^5.4|^6.0|^7.0",
"symfony/console": "^4.4|^5.4|^6.0|^7.0"
},
@ -867,7 +867,7 @@
],
"support": {
"issues": "https://github.com/doctrine/dbal/issues",
"source": "https://github.com/doctrine/dbal/tree/3.9.5"
"source": "https://github.com/doctrine/dbal/tree/3.9.4"
},
"funding": [
{
@ -883,7 +883,7 @@
"type": "tidelift"
}
],
"time": "2025-06-15T22:40:05+00:00"
"time": "2025-01-16T08:28:55+00:00"
},
{
"name": "doctrine/deprecations",
@ -1470,16 +1470,16 @@
},
{
"name": "doctrine/migrations",
"version": "3.9.1",
"version": "3.9.0",
"source": {
"type": "git",
"url": "https://github.com/doctrine/migrations.git",
"reference": "0f1e0c960ac29866d648a4f50142a74fe1cb6999"
"reference": "325b61e41d032f5f7d7e2d11cbefff656eadc9ab"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/migrations/zipball/0f1e0c960ac29866d648a4f50142a74fe1cb6999",
"reference": "0f1e0c960ac29866d648a4f50142a74fe1cb6999",
"url": "https://api.github.com/repos/doctrine/migrations/zipball/325b61e41d032f5f7d7e2d11cbefff656eadc9ab",
"reference": "325b61e41d032f5f7d7e2d11cbefff656eadc9ab",
"shasum": ""
},
"require": {
@ -1553,7 +1553,7 @@
],
"support": {
"issues": "https://github.com/doctrine/migrations/issues",
"source": "https://github.com/doctrine/migrations/tree/3.9.1"
"source": "https://github.com/doctrine/migrations/tree/3.9.0"
},
"funding": [
{
@ -1569,7 +1569,7 @@
"type": "tidelift"
}
],
"time": "2025-06-27T07:19:23+00:00"
"time": "2025-03-26T06:48:45+00:00"
},
{
"name": "doctrine/orm",
@ -1893,16 +1893,16 @@
},
{
"name": "enshrined/svg-sanitize",
"version": "0.22.0",
"version": "0.21.0",
"source": {
"type": "git",
"url": "https://github.com/darylldoyle/svg-sanitizer.git",
"reference": "0afa95ea74be155a7bcd6c6fb60c276c39984500"
"reference": "5e477468fac5c5ce933dce53af3e8e4e58dcccc9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/darylldoyle/svg-sanitizer/zipball/0afa95ea74be155a7bcd6c6fb60c276c39984500",
"reference": "0afa95ea74be155a7bcd6c6fb60c276c39984500",
"url": "https://api.github.com/repos/darylldoyle/svg-sanitizer/zipball/5e477468fac5c5ce933dce53af3e8e4e58dcccc9",
"reference": "5e477468fac5c5ce933dce53af3e8e4e58dcccc9",
"shasum": ""
},
"require": {
@ -1932,9 +1932,9 @@
"description": "An SVG sanitizer for PHP",
"support": {
"issues": "https://github.com/darylldoyle/svg-sanitizer/issues",
"source": "https://github.com/darylldoyle/svg-sanitizer/tree/0.22.0"
"source": "https://github.com/darylldoyle/svg-sanitizer/tree/0.21.0"
},
"time": "2025-08-12T10:13:48+00:00"
"time": "2025-01-13T09:32:25+00:00"
},
{
"name": "fossar/htmlawed",
@ -4146,16 +4146,16 @@
},
{
"name": "j0k3r/graby-site-config",
"version": "1.0.202",
"version": "1.0.199",
"source": {
"type": "git",
"url": "https://github.com/j0k3r/graby-site-config.git",
"reference": "870ff8f1f35cdbf87ff000b68c7bef5e712fd533"
"reference": "dbb352fd7931f813e286eed8f1684da6052737e3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/j0k3r/graby-site-config/zipball/870ff8f1f35cdbf87ff000b68c7bef5e712fd533",
"reference": "870ff8f1f35cdbf87ff000b68c7bef5e712fd533",
"url": "https://api.github.com/repos/j0k3r/graby-site-config/zipball/dbb352fd7931f813e286eed8f1684da6052737e3",
"reference": "dbb352fd7931f813e286eed8f1684da6052737e3",
"shasum": ""
},
"require": {
@ -4184,9 +4184,9 @@
"description": "Graby site config files",
"support": {
"issues": "https://github.com/j0k3r/graby-site-config/issues",
"source": "https://github.com/j0k3r/graby-site-config/tree/1.0.202"
"source": "https://github.com/j0k3r/graby-site-config/tree/1.0.199"
},
"time": "2025-08-01T07:03:24+00:00"
"time": "2025-05-01T02:32:13+00:00"
},
{
"name": "j0k3r/httplug-ssrf-plugin",
@ -4261,16 +4261,16 @@
},
{
"name": "j0k3r/php-readability",
"version": "1.2.13",
"version": "1.2.12",
"source": {
"type": "git",
"url": "https://github.com/j0k3r/php-readability.git",
"reference": "b9dde0f4cd46e9fc082bb37f75dc94ecd2f8faad"
"reference": "109a22662de0d703f01387e5714ad4f9a03b95c0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/j0k3r/php-readability/zipball/b9dde0f4cd46e9fc082bb37f75dc94ecd2f8faad",
"reference": "b9dde0f4cd46e9fc082bb37f75dc94ecd2f8faad",
"url": "https://api.github.com/repos/j0k3r/php-readability/zipball/109a22662de0d703f01387e5714ad4f9a03b95c0",
"reference": "109a22662de0d703f01387e5714ad4f9a03b95c0",
"shasum": ""
},
"require": {
@ -4332,7 +4332,7 @@
],
"support": {
"issues": "https://github.com/j0k3r/php-readability/issues",
"source": "https://github.com/j0k3r/php-readability/tree/1.2.13"
"source": "https://github.com/j0k3r/php-readability/tree/1.2.12"
},
"funding": [
{
@ -4340,7 +4340,7 @@
"type": "github"
}
],
"time": "2025-06-03T08:02:58+00:00"
"time": "2025-03-04T09:20:40+00:00"
},
{
"name": "javibravo/simpleue",
@ -4405,16 +4405,16 @@
},
{
"name": "jean85/pretty-package-versions",
"version": "2.1.1",
"version": "2.1.0",
"source": {
"type": "git",
"url": "https://github.com/Jean85/pretty-package-versions.git",
"reference": "4d7aa5dab42e2a76d99559706022885de0e18e1a"
"reference": "3c4e5f62ba8d7de1734312e4fff32f67a8daaf10"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/4d7aa5dab42e2a76d99559706022885de0e18e1a",
"reference": "4d7aa5dab42e2a76d99559706022885de0e18e1a",
"url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/3c4e5f62ba8d7de1734312e4fff32f67a8daaf10",
"reference": "3c4e5f62ba8d7de1734312e4fff32f67a8daaf10",
"shasum": ""
},
"require": {
@ -4424,9 +4424,8 @@
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.2",
"jean85/composer-provided-replaced-stub-package": "^1.0",
"phpstan/phpstan": "^2.0",
"phpstan/phpstan": "^1.4",
"phpunit/phpunit": "^7.5|^8.5|^9.6",
"rector/rector": "^2.0",
"vimeo/psalm": "^4.3 || ^5.0"
},
"type": "library",
@ -4459,9 +4458,9 @@
],
"support": {
"issues": "https://github.com/Jean85/pretty-package-versions/issues",
"source": "https://github.com/Jean85/pretty-package-versions/tree/2.1.1"
"source": "https://github.com/Jean85/pretty-package-versions/tree/2.1.0"
},
"time": "2025-03-19T14:43:43+00:00"
"time": "2024-11-18T16:19:46+00:00"
},
{
"name": "jms/metadata",
@ -4529,16 +4528,16 @@
},
{
"name": "jms/serializer",
"version": "3.32.5",
"version": "3.32.4",
"source": {
"type": "git",
"url": "https://github.com/schmittjoh/serializer.git",
"reference": "7c88b1b02ff868eecc870eeddbb3b1250e4bd89c"
"reference": "f5c6227b2664d1e75fda65f1e6c5686a0c034b31"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/schmittjoh/serializer/zipball/7c88b1b02ff868eecc870eeddbb3b1250e4bd89c",
"reference": "7c88b1b02ff868eecc870eeddbb3b1250e4bd89c",
"url": "https://api.github.com/repos/schmittjoh/serializer/zipball/f5c6227b2664d1e75fda65f1e6c5686a0c034b31",
"reference": "f5c6227b2664d1e75fda65f1e6c5686a0c034b31",
"shasum": ""
},
"require": {
@ -4615,7 +4614,7 @@
],
"support": {
"issues": "https://github.com/schmittjoh/serializer/issues",
"source": "https://github.com/schmittjoh/serializer/tree/3.32.5"
"source": "https://github.com/schmittjoh/serializer/tree/3.32.4"
},
"funding": [
{
@ -4627,7 +4626,7 @@
"type": "github"
}
],
"time": "2025-05-26T15:55:41+00:00"
"time": "2025-04-06T18:42:47+00:00"
},
{
"name": "jms/serializer-bundle",
@ -8050,16 +8049,16 @@
},
{
"name": "sentry/sentry",
"version": "4.14.1",
"version": "4.10.0",
"source": {
"type": "git",
"url": "https://github.com/getsentry/sentry-php.git",
"reference": "a28c4a6f5fda2bf730789a638501d7a737a64eda"
"reference": "2af937d47d8aadb8dab0b1d7b9557e495dd12856"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/getsentry/sentry-php/zipball/a28c4a6f5fda2bf730789a638501d7a737a64eda",
"reference": "a28c4a6f5fda2bf730789a638501d7a737a64eda",
"url": "https://api.github.com/repos/getsentry/sentry-php/zipball/2af937d47d8aadb8dab0b1d7b9557e495dd12856",
"reference": "2af937d47d8aadb8dab0b1d7b9557e495dd12856",
"shasum": ""
},
"require": {
@ -8123,7 +8122,7 @@
],
"support": {
"issues": "https://github.com/getsentry/sentry-php/issues",
"source": "https://github.com/getsentry/sentry-php/tree/4.14.1"
"source": "https://github.com/getsentry/sentry-php/tree/4.10.0"
},
"funding": [
{
@ -8135,27 +8134,27 @@
"type": "custom"
}
],
"time": "2025-06-23T15:25:52+00:00"
"time": "2024-11-06T07:44:19+00:00"
},
{
"name": "sentry/sentry-symfony",
"version": "5.3.0",
"version": "5.2.0",
"source": {
"type": "git",
"url": "https://github.com/getsentry/sentry-symfony.git",
"reference": "5081e7d842424ec09a96e3c79c5b48b89d1195b2"
"reference": "394576244d8ac03fd2f305b82d23a6fd7a083b45"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/getsentry/sentry-symfony/zipball/5081e7d842424ec09a96e3c79c5b48b89d1195b2",
"reference": "5081e7d842424ec09a96e3c79c5b48b89d1195b2",
"url": "https://api.github.com/repos/getsentry/sentry-symfony/zipball/394576244d8ac03fd2f305b82d23a6fd7a083b45",
"reference": "394576244d8ac03fd2f305b82d23a6fd7a083b45",
"shasum": ""
},
"require": {
"guzzlehttp/psr7": "^2.1.1",
"jean85/pretty-package-versions": "^1.5||^2.0",
"php": "^7.2||^8.0",
"sentry/sentry": "^4.14.1",
"sentry/sentry": "^4.10.0",
"symfony/cache-contracts": "^1.1||^2.4||^3.0",
"symfony/config": "^4.4.20||^5.0.11||^6.0||^7.0",
"symfony/console": "^4.4.20||^5.0.11||^6.0||^7.0",
@ -8225,7 +8224,7 @@
],
"support": {
"issues": "https://github.com/getsentry/sentry-symfony/issues",
"source": "https://github.com/getsentry/sentry-symfony/tree/5.3.0"
"source": "https://github.com/getsentry/sentry-symfony/tree/5.2.0"
},
"funding": [
{
@ -8237,7 +8236,7 @@
"type": "custom"
}
],
"time": "2025-07-07T14:14:08+00:00"
"time": "2025-03-03T07:47:12+00:00"
},
{
"name": "simplepie/simplepie",
@ -8816,16 +8815,16 @@
},
{
"name": "symfony/cache-contracts",
"version": "v3.6.0",
"version": "v3.5.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/cache-contracts.git",
"reference": "5d68a57d66910405e5c0b63d6f0af941e66fc868"
"reference": "15a4f8e5cd3bce9aeafc882b1acab39ec8de2c1b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/cache-contracts/zipball/5d68a57d66910405e5c0b63d6f0af941e66fc868",
"reference": "5d68a57d66910405e5c0b63d6f0af941e66fc868",
"url": "https://api.github.com/repos/symfony/cache-contracts/zipball/15a4f8e5cd3bce9aeafc882b1acab39ec8de2c1b",
"reference": "15a4f8e5cd3bce9aeafc882b1acab39ec8de2c1b",
"shasum": ""
},
"require": {
@ -8839,7 +8838,7 @@
"name": "symfony/contracts"
},
"branch-alias": {
"dev-main": "3.6-dev"
"dev-main": "3.5-dev"
}
},
"autoload": {
@ -8872,7 +8871,7 @@
"standards"
],
"support": {
"source": "https://github.com/symfony/cache-contracts/tree/v3.6.0"
"source": "https://github.com/symfony/cache-contracts/tree/v3.5.1"
},
"funding": [
{
@ -8888,7 +8887,7 @@
"type": "tidelift"
}
],
"time": "2025-03-13T15:25:07+00:00"
"time": "2024-09-25T14:20:29+00:00"
},
{
"name": "symfony/config",
@ -9159,16 +9158,16 @@
},
{
"name": "symfony/deprecation-contracts",
"version": "v3.6.0",
"version": "v3.5.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/deprecation-contracts.git",
"reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62"
"reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62",
"reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62",
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6",
"reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6",
"shasum": ""
},
"require": {
@ -9181,7 +9180,7 @@
"name": "symfony/contracts"
},
"branch-alias": {
"dev-main": "3.6-dev"
"dev-main": "3.5-dev"
}
},
"autoload": {
@ -9206,7 +9205,7 @@
"description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0"
"source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1"
},
"funding": [
{
@ -9222,7 +9221,7 @@
"type": "tidelift"
}
],
"time": "2024-09-25T14:21:43+00:00"
"time": "2024-09-25T14:20:29+00:00"
},
{
"name": "symfony/doctrine-bridge",
@ -12654,7 +12653,7 @@
},
{
"name": "symfony/stopwatch",
"version": "v7.3.0",
"version": "v7.2.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/stopwatch.git",
@ -12696,7 +12695,7 @@
"description": "Provides a way to profile code",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/stopwatch/tree/v7.3.0"
"source": "https://github.com/symfony/stopwatch/tree/v7.2.4"
},
"funding": [
{
@ -13456,21 +13455,20 @@
},
{
"name": "symfony/var-exporter",
"version": "v7.3.0",
"version": "v7.2.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/var-exporter.git",
"reference": "c9a1168891b5aaadfd6332ef44393330b3498c4c"
"reference": "422b8de94c738830a1e071f59ad14d67417d7007"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/var-exporter/zipball/c9a1168891b5aaadfd6332ef44393330b3498c4c",
"reference": "c9a1168891b5aaadfd6332ef44393330b3498c4c",
"url": "https://api.github.com/repos/symfony/var-exporter/zipball/422b8de94c738830a1e071f59ad14d67417d7007",
"reference": "422b8de94c738830a1e071f59ad14d67417d7007",
"shasum": ""
},
"require": {
"php": ">=8.2",
"symfony/deprecation-contracts": "^2.5|^3"
"php": ">=8.2"
},
"require-dev": {
"symfony/property-access": "^6.4|^7.0",
@ -13513,7 +13511,7 @@
"serialize"
],
"support": {
"source": "https://github.com/symfony/var-exporter/tree/v7.3.0"
"source": "https://github.com/symfony/var-exporter/tree/v7.2.6"
},
"funding": [
{
@ -13529,7 +13527,7 @@
"type": "tidelift"
}
],
"time": "2025-05-15T09:04:05+00:00"
"time": "2025-05-02T08:36:00+00:00"
},
{
"name": "symfony/webpack-encore-bundle",
@ -13678,16 +13676,16 @@
},
{
"name": "tecnickcom/tcpdf",
"version": "6.10.0",
"version": "6.9.4",
"source": {
"type": "git",
"url": "https://github.com/tecnickcom/TCPDF.git",
"reference": "ca5b6de294512145db96bcbc94e61696599c391d"
"reference": "c838d7f7babb0d35763acfb9ecf78c3f45966f83"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/tecnickcom/TCPDF/zipball/ca5b6de294512145db96bcbc94e61696599c391d",
"reference": "ca5b6de294512145db96bcbc94e61696599c391d",
"url": "https://api.github.com/repos/tecnickcom/TCPDF/zipball/c838d7f7babb0d35763acfb9ecf78c3f45966f83",
"reference": "c838d7f7babb0d35763acfb9ecf78c3f45966f83",
"shasum": ""
},
"require": {
@ -13737,7 +13735,7 @@
],
"support": {
"issues": "https://github.com/tecnickcom/TCPDF/issues",
"source": "https://github.com/tecnickcom/TCPDF/tree/6.10.0"
"source": "https://github.com/tecnickcom/TCPDF/tree/6.9.4"
},
"funding": [
{
@ -13745,7 +13743,7 @@
"type": "custom"
}
],
"time": "2025-05-27T18:02:28+00:00"
"time": "2025-05-13T11:34:35+00:00"
},
{
"name": "thecodingmachine/safe",
@ -15121,16 +15119,16 @@
},
{
"name": "doctrine/data-fixtures",
"version": "2.0.3",
"version": "2.0.2",
"source": {
"type": "git",
"url": "https://github.com/doctrine/data-fixtures.git",
"reference": "f65b353922b7ac48f360428e19b22fcce5aba134"
"reference": "f7f1e12d6bceb58c204b3e77210a103c1c57601e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/data-fixtures/zipball/f65b353922b7ac48f360428e19b22fcce5aba134",
"reference": "f65b353922b7ac48f360428e19b22fcce5aba134",
"url": "https://api.github.com/repos/doctrine/data-fixtures/zipball/f7f1e12d6bceb58c204b3e77210a103c1c57601e",
"reference": "f7f1e12d6bceb58c204b3e77210a103c1c57601e",
"shasum": ""
},
"require": {
@ -15144,14 +15142,14 @@
"doctrine/phpcr-odm": "<1.3.0"
},
"require-dev": {
"doctrine/coding-standard": "^13",
"doctrine/coding-standard": "^12",
"doctrine/dbal": "^3.5 || ^4",
"doctrine/mongodb-odm": "^1.3.0 || ^2.0.0",
"doctrine/orm": "^2.14 || ^3",
"ext-sqlite3": "*",
"fig/log-test": "^1",
"phpstan/phpstan": "2.1.17",
"phpunit/phpunit": "10.5.45",
"phpstan/phpstan": "^1.10",
"phpunit/phpunit": "^10.5.3",
"symfony/cache": "^6.4 || ^7",
"symfony/var-exporter": "^6.4 || ^7"
},
@ -15184,7 +15182,7 @@
],
"support": {
"issues": "https://github.com/doctrine/data-fixtures/issues",
"source": "https://github.com/doctrine/data-fixtures/tree/2.0.3"
"source": "https://github.com/doctrine/data-fixtures/tree/2.0.2"
},
"funding": [
{
@ -15200,7 +15198,7 @@
"type": "tidelift"
}
],
"time": "2025-06-27T19:59:58+00:00"
"time": "2025-01-21T13:21:31+00:00"
},
{
"name": "doctrine/doctrine-fixtures-bundle",
@ -15847,59 +15845,58 @@
},
{
"name": "friendsofphp/php-cs-fixer",
"version": "v3.84.0",
"version": "v3.75.0",
"source": {
"type": "git",
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
"reference": "38dad0767bf2a9b516b976852200ae722fe984ca"
"reference": "399a128ff2fdaf4281e4e79b755693286cdf325c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/38dad0767bf2a9b516b976852200ae722fe984ca",
"reference": "38dad0767bf2a9b516b976852200ae722fe984ca",
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/399a128ff2fdaf4281e4e79b755693286cdf325c",
"reference": "399a128ff2fdaf4281e4e79b755693286cdf325c",
"shasum": ""
},
"require": {
"clue/ndjson-react": "^1.0",
"composer/semver": "^3.4",
"composer/xdebug-handler": "^3.0.5",
"composer/xdebug-handler": "^3.0.3",
"ext-filter": "*",
"ext-hash": "*",
"ext-json": "*",
"ext-tokenizer": "*",
"fidry/cpu-core-counter": "^1.2",
"php": "^7.4 || ^8.0",
"react/child-process": "^0.6.6",
"react/child-process": "^0.6.5",
"react/event-loop": "^1.0",
"react/promise": "^2.11 || ^3.0",
"react/promise": "^2.0 || ^3.0",
"react/socket": "^1.0",
"react/stream": "^1.0",
"sebastian/diff": "^4.0.6 || ^5.1.1 || ^6.0.2 || ^7.0",
"symfony/console": "^5.4.45 || ^6.4.13 || ^7.0",
"symfony/event-dispatcher": "^5.4.45 || ^6.4.13 || ^7.0",
"symfony/filesystem": "^5.4.45 || ^6.4.13 || ^7.0",
"symfony/finder": "^5.4.45 || ^6.4.17 || ^7.0",
"symfony/options-resolver": "^5.4.45 || ^6.4.16 || ^7.0",
"symfony/polyfill-mbstring": "^1.32",
"symfony/polyfill-php80": "^1.32",
"symfony/polyfill-php81": "^1.32",
"symfony/process": "^5.4.47 || ^6.4.20 || ^7.2",
"symfony/stopwatch": "^5.4.45 || ^6.4.19 || ^7.0"
"sebastian/diff": "^4.0 || ^5.1 || ^6.0 || ^7.0",
"symfony/console": "^5.4 || ^6.4 || ^7.0",
"symfony/event-dispatcher": "^5.4 || ^6.4 || ^7.0",
"symfony/filesystem": "^5.4 || ^6.4 || ^7.0",
"symfony/finder": "^5.4 || ^6.4 || ^7.0",
"symfony/options-resolver": "^5.4 || ^6.4 || ^7.0",
"symfony/polyfill-mbstring": "^1.31",
"symfony/polyfill-php80": "^1.31",
"symfony/polyfill-php81": "^1.31",
"symfony/process": "^5.4 || ^6.4 || ^7.2",
"symfony/stopwatch": "^5.4 || ^6.4 || ^7.0"
},
"require-dev": {
"facile-it/paraunit": "^1.3.1 || ^2.6",
"infection/infection": "^0.29.14",
"justinrainbow/json-schema": "^5.3 || ^6.4",
"keradus/cli-executor": "^2.2",
"justinrainbow/json-schema": "^5.3 || ^6.2",
"keradus/cli-executor": "^2.1",
"mikey179/vfsstream": "^1.6.12",
"php-coveralls/php-coveralls": "^2.8",
"php-coveralls/php-coveralls": "^2.7",
"php-cs-fixer/accessible-object": "^1.1",
"php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.6",
"php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.6",
"phpunit/phpunit": "^9.6.23 || ^10.5.47 || ^11.5.25",
"symfony/polyfill-php84": "^1.32",
"symfony/var-dumper": "^5.4.48 || ^6.4.23 || ^7.3.1",
"symfony/yaml": "^5.4.45 || ^6.4.23 || ^7.3.1"
"phpunit/phpunit": "^9.6.22 || ^10.5.45 || ^11.5.12",
"symfony/var-dumper": "^5.4.48 || ^6.4.18 || ^7.2.3",
"symfony/yaml": "^5.4.45 || ^6.4.18 || ^7.2.3"
},
"suggest": {
"ext-dom": "For handling output formats in XML",
@ -15940,7 +15937,7 @@
],
"support": {
"issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues",
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.84.0"
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.75.0"
},
"funding": [
{
@ -15948,7 +15945,7 @@
"type": "github"
}
],
"time": "2025-07-15T18:21:57+00:00"
"time": "2025-03-31T18:40:42+00:00"
},
{
"name": "friendsoftwig/twigcs",
@ -19076,16 +19073,16 @@
},
{
"name": "symfony/phpunit-bridge",
"version": "v7.3.1",
"version": "v7.2.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/phpunit-bridge.git",
"reference": "71624984d8bcad6acf7a790d4e3ceafe04bc2485"
"reference": "6106ae85a0e3ed509d339b7f924788c9cc4e7cfb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/71624984d8bcad6acf7a790d4e3ceafe04bc2485",
"reference": "71624984d8bcad6acf7a790d4e3ceafe04bc2485",
"url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/6106ae85a0e3ed509d339b7f924788c9cc4e7cfb",
"reference": "6106ae85a0e3ed509d339b7f924788c9cc4e7cfb",
"shasum": ""
},
"require": {
@ -19137,11 +19134,8 @@
],
"description": "Provides utilities for PHPUnit, especially user deprecation notices management",
"homepage": "https://symfony.com",
"keywords": [
"testing"
],
"support": {
"source": "https://github.com/symfony/phpunit-bridge/tree/v7.3.1"
"source": "https://github.com/symfony/phpunit-bridge/tree/v7.2.6"
},
"funding": [
{
@ -19157,7 +19151,7 @@
"type": "tidelift"
}
],
"time": "2025-06-04T10:09:06+00:00"
"time": "2025-04-09T08:35:42+00:00"
},
{
"name": "symfony/process",
@ -19455,6 +19449,6 @@
"ext-tokenizer": "*",
"ext-xml": "*"
},
"platform-dev": {},
"plugin-api-version": "2.6.0"
"platform-dev": [],
"plugin-api-version": "2.3.0"
}

View File

@ -1,12 +1,3 @@
FROM golang as envsubst
ARG ENVSUBST_VERSION=v1.3.0
# envsubst from gettext can not replace env vars with default values
# this package is not available for ARM32 and we have to build it from source code
# flag -ldflags "-s -w" produces a smaller executable
RUN go install -ldflags "-s -w" -v github.com/a8m/envsubst/cmd/envsubst@${ENVSUBST_VERSION}
FROM php:8.2-fpm AS rootless
ARG DEBIAN_FRONTEND=noninteractive
@ -84,8 +75,10 @@ RUN mkdir -p /tmp/blackfire \
RUN npm install -g yarn
RUN curl -L -o /usr/local/bin/envsubst https://github.com/a8m/envsubst/releases/download/v1.1.0/envsubst-`uname -s`-`uname -m`; \
chmod +x /usr/local/bin/envsubst
COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer
COPY --from=envsubst /go/bin/envsubst /usr/local/bin/envsubst
COPY entrypoint.sh /entrypoint.sh
COPY config/ /opt/wallabag/config/

View File

@ -1,47 +0,0 @@
<?php
declare(strict_types=1);
namespace Application\Migrations;
use Doctrine\DBAL\Schema\Schema;
use Wallabag\Doctrine\WallabagMigration;
/**
* Add boolean for two-step setup for google authenticator.
*/
final class Version20250413133131 extends WallabagMigration
{
public function up(Schema $schema): void
{
$userTable = $schema->getTable($this->getTable('user'));
$this->skipIf($userTable->hasColumn('google_authenticator'), 'It seems that you already played this migration.');
$userTable->addColumn('google_authenticator', 'boolean', [
'default' => false,
'notnull' => true,
]);
}
/**
* Query to update data in user table, as it's not possible to perform this in the `up` method.
*/
public function postUp(Schema $schema): void
{
$this->skipIf(!$schema->getTable($this->getTable('user'))->hasColumn('google_authenticator'), 'Unable to update google_authenticator column');
$this->connection->executeQuery(
'UPDATE ' . $this->getTable('user') . ' SET google_authenticator = :googleAuthenticator WHERE googleAuthenticatorSecret IS NOT NULL AND googleAuthenticatorSecret <> :emptyString',
[
'googleAuthenticator' => true,
'emptyString' => '',
]
);
}
public function down(Schema $schema): void
{
$userTable = $schema->getTable($this->getTable('user'));
$userTable->dropColumn('google_authenticator');
}
}

View File

@ -0,0 +1,106 @@
<?php
declare(strict_types=1);
namespace Application\Migrations;
use Doctrine\DBAL\Schema\Schema;
use Wallabag\Doctrine\WallabagMigration;
/**
* Add setting to enable or disable each importer.
*/
final class Version20250526113708 extends WallabagMigration
{
private $settings = [
[
'name' => 'pocket_enabled',
'value' => '1',
'section' => 'import',
],
[
'name' => 'wallabag_v1_enabled',
'value' => '1',
'section' => 'import',
],
[
'name' => 'wallabag_v2_enabled',
'value' => '1',
'section' => 'import',
],
[
'name' => 'elcura_enabled',
'value' => '1',
'section' => 'import',
],
[
'name' => 'readability_enabled',
'value' => '1',
'section' => 'import',
],
[
'name' => 'instapaper_enabled',
'value' => '1',
'section' => 'import',
],
[
'name' => 'pinboard_enabled',
'value' => '1',
'section' => 'import',
],
[
'name' => 'delicious_enabled',
'value' => '1',
'section' => 'import',
],
[
'name' => 'omnivore_enabled',
'value' => '1',
'section' => 'import',
],
[
'name' => 'firefox_enabled',
'value' => '1',
'section' => 'import',
],
[
'name' => 'chrome_enabled',
'value' => '1',
'section' => 'import',
],
[
'name' => 'shaarli_enabled',
'value' => '1',
'section' => 'import',
],
[
'name' => 'pocket_html_enabled',
'value' => '1',
'section' => 'import',
],
[
'name' => 'elcurator_enabled',
'value' => '1',
'section' => 'import',
],
];
public function up(Schema $schema): void
{
foreach ($this->settings as $setting) {
$settingEnabled = $this->connection
->fetchOne('SELECT * FROM ' . $this->getTable('internal_setting') . " WHERE name = '" . $setting['name'] . "'");
if (false !== $settingEnabled) {
continue;
}
$this->addSql('INSERT INTO ' . $this->getTable('internal_setting') . " (name, value, section) VALUES ('" . $setting['name'] . "', '" . $setting['value'] . "', '" . $setting['section'] . "');");
}
}
public function down(Schema $schema): void
{
$this->skipIf(true, 'These settings are required and should not be removed.');
}
}

View File

@ -41,26 +41,26 @@
"url": "https://github.com/wallabag/wallabag/issues"
},
"devDependencies": {
"@babel/core": "^7.28.3",
"@babel/eslint-parser": "^7.28.0",
"@babel/preset-env": "^7.28.3",
"@babel/core": "^7.27.1",
"@babel/eslint-parser": "^7.27.1",
"@babel/preset-env": "^7.27.2",
"@symfony/webpack-encore": "^5.1.0",
"autoprefixer": "^10.4.21",
"babel-loader": "^10.0.0",
"core-js": "^3.45.0",
"core-js": "^3.42.0",
"css-loader": "^7.1.2",
"eslint": "^8.57.1",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-plugin-import": "^2.32.0",
"eslint-webpack-plugin": "^5.0.2",
"eslint-plugin-import": "^2.31.0",
"eslint-webpack-plugin": "^5.0.1",
"file-loader": "^6.2.0",
"lato-font": "^3.0.0",
"mini-css-extract-plugin": "^2.9.4",
"postcss": "^8.5.6",
"mini-css-extract-plugin": "^2.9.2",
"postcss": "^8.5.3",
"postcss-loader": "^8.1.1",
"postcss-scss": "^4.0.9",
"regenerator-runtime": "^0.14.1",
"sass-embedded": "^1.90.0",
"sass-embedded": "^1.89.0",
"sass-loader": "^16.0.5",
"style-loader": "^4.0.0",
"stylelint": "^15.11.0",
@ -69,17 +69,17 @@
"stylelint-scss": "^5.3.2",
"terser-webpack-plugin": "^5.3.14",
"url-loader": "^4.1.1",
"webpack": "^5.101.2",
"webpack": "^5.99.9",
"webpack-cli": "^5.1.4",
"webpack-manifest-plugin": "^5.0.1",
"webpack-merge": "^6.0.1",
"webpack-notifier": "^1.15.0"
},
"dependencies": {
"@fontsource/atkinson-hyperlegible": "^5.2.6",
"@fontsource/eb-garamond": "^5.2.6",
"@fontsource/montserrat": "^5.2.6",
"@fontsource/oswald": "^5.2.6",
"@fontsource/atkinson-hyperlegible": "^5.2.5",
"@fontsource/eb-garamond": "^5.2.5",
"@fontsource/montserrat": "^5.2.5",
"@fontsource/oswald": "^5.2.5",
"@hotwired/stimulus": "^3.2.2",
"@materializecss/materialize": "^1.2.2",
"@symfony/stimulus-bridge": "^4.0.1",

View File

@ -9,9 +9,8 @@ use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Wallabag\Entity\Entry;
use Wallabag\Entity\User;
use Wallabag\Event\EntryDeletedEvent;
use Wallabag\Repository\EntryRepository;
use Wallabag\Repository\UserRepository;
@ -27,7 +26,6 @@ class CleanDuplicatesCommand extends Command
private readonly EntityManagerInterface $entityManager,
private readonly EntryRepository $entryRepository,
private readonly UserRepository $userRepository,
private readonly EventDispatcherInterface $eventDispatcher,
) {
parent::__construct();
}
@ -88,12 +86,7 @@ class CleanDuplicatesCommand extends Command
if (\in_array($url, $urls, true)) {
++$duplicatesCount;
$entryToDelete = $this->entryRepository->find($entry['id']);
// entry deleted, dispatch event about it!
$this->eventDispatcher->dispatch(new EntryDeletedEvent($entryToDelete), EntryDeletedEvent::NAME);
$this->entityManager->remove($entryToDelete);
$this->entityManager->remove($this->entryRepository->find($entry['id']));
$this->entityManager->flush(); // Flushing at the end of the loop would require the instance not being online
} else {
$urls[] = $entry['url'];

View File

@ -21,7 +21,6 @@ use Wallabag\Import\FirefoxImport;
use Wallabag\Import\InstapaperImport;
use Wallabag\Import\OmnivoreImport;
use Wallabag\Import\PinboardImport;
use Wallabag\Import\PocketCsvImport;
use Wallabag\Import\PocketHtmlImport;
use Wallabag\Import\ReadabilityImport;
use Wallabag\Import\ShaarliImport;
@ -49,7 +48,6 @@ class ImportCommand extends Command
private readonly ElcuratorImport $elcuratorImport,
private readonly ShaarliImport $shaarliImport,
private readonly PocketHtmlImport $pocketHtmlImport,
private readonly PocketCsvImport $pocketCsvImport,
private readonly OmnivoreImport $omnivoreImport,
) {
parent::__construct();
@ -60,7 +58,7 @@ class ImportCommand extends Command
$this
->addArgument('username', InputArgument::REQUIRED, 'User to populate')
->addArgument('filepath', InputArgument::REQUIRED, 'Path to the JSON file')
->addOption('importer', null, InputOption::VALUE_OPTIONAL, 'The importer to use: v1, v2, instapaper, pinboard, delicious, readability, firefox, chrome, elcurator, shaarli, pocket or pocket_csv', 'v1')
->addOption('importer', null, InputOption::VALUE_OPTIONAL, 'The importer to use: v1, v2, instapaper, pinboard, delicious, readability, firefox, chrome, elcurator, shaarli or pocket', 'v1')
->addOption('markAsRead', null, InputOption::VALUE_OPTIONAL, 'Mark all entries as read', false)
->addOption('useUserId', null, InputOption::VALUE_NONE, 'Use user id instead of username to find account')
->addOption('disableContentUpdate', null, InputOption::VALUE_NONE, 'Disable fetching updated content from URL')
@ -111,7 +109,6 @@ class ImportCommand extends Command
'elcurator' => $this->elcuratorImport,
'shaarli' => $this->shaarliImport,
'pocket' => $this->pocketHtmlImport,
'pocket_csv' => $this->pocketCsvImport,
'omnivore' => $this->omnivoreImport,
default => $this->wallabagV1Import,
};

View File

@ -1,118 +0,0 @@
<?php
namespace Wallabag\Command\Import;
use Doctrine\DBAL\Driver\Middleware;
use Doctrine\DBAL\Logging\Middleware as LoggingMiddleware;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Config\Definition\Exception\Exception;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Wallabag\Entity\Entry;
use Wallabag\Entity\User;
use Wallabag\Helper\ContentProxy;
use Wallabag\Helper\TagsAssigner;
use Wallabag\Repository\UserRepository;
class UrlCommand extends Command
{
public function __construct(
private readonly EntityManagerInterface $entityManager,
private readonly TokenStorageInterface $tokenStorage,
private readonly UserRepository $userRepository,
private readonly ContentProxy $contentProxy,
private readonly TagsAssigner $tagsAssigner,
) {
parent::__construct();
}
protected function configure()
{
$this
->setName('wallabag:import:url')
->setDescription('Import a single URL')
->addArgument('username', InputArgument::REQUIRED, 'User to add the URL to (value: username or id)')
->addArgument('url', InputArgument::REQUIRED, 'URL to import')
->addArgument('tags', InputArgument::OPTIONAL, 'Comma-separated list of tags to add')
->addOption('markAsRead', null, InputOption::VALUE_OPTIONAL, 'Mark entry as read', false)
->addOption('useUserId', null, InputOption::VALUE_NONE, 'Use user id instead of username to find account')
;
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
// Turning off doctrine default logs queries for saving memory
$middlewares = $this->entityManager->getConnection()->getConfiguration()->getMiddlewares();
$middlewaresWithoutLogging = array_filter($middlewares, fn (Middleware $middleware) => !$middleware instanceof LoggingMiddleware);
$this->entityManager->getConnection()->getConfiguration()->setMiddlewares($middlewaresWithoutLogging);
if ($input->getOption('useUserId')) {
$entityUser = $this->userRepository->findOneById($input->getArgument('username'));
} else {
$entityUser = $this->userRepository->findOneByUsername($input->getArgument('username'));
}
if (!\is_object($entityUser)) {
throw new Exception(\sprintf('User "%s" not found', $input->getArgument('username')));
}
// Authenticate user for paywalled websites
$token = new UsernamePasswordToken(
$entityUser,
'main',
$entityUser->getRoles()
);
$this->tokenStorage->setToken($token);
$user = $this->tokenStorage->getToken()->getUser();
\assert($user instanceof User);
$url = $input->getArgument('url');
$existingEntry = $this->entityManager
->getRepository(Entry::class)
->findByUrlAndUserId($url, $user->getId());
if (false !== $existingEntry) {
$output->writeln(\sprintf('The URL %s is already in users entries.', $url));
return 1;
}
$entry = new Entry($user);
try {
$this->contentProxy->updateEntry($entry, $url);
} catch (\Exception $e) {
$output->writeln(\sprintf('Error trying to import the URL %s: %s.', $url, $e->getMessage()));
return 1;
}
if ($input->getOption('markAsRead')) {
$entry->updateArchived(true);
}
$this->entityManager->persist($entry);
$tags = explode(',', $input->getArgument('tags'));
if (\count($tags) > 1) {
$this->tagsAssigner->assignTagsToEntry(
$entry,
$tags,
$this->entityManager->getUnitOfWork()->getScheduledEntityInsertions()
);
}
$this->entityManager->flush();
$output->writeln(\sprintf('URL %s successfully imported.', $url));
return 0;
}
}

View File

@ -23,7 +23,6 @@ class RabbitMQConsumerTotalProxy
private readonly Consumer $elcuratorConsumer,
private readonly Consumer $shaarliConsumer,
private readonly Consumer $pocketHtmlConsumer,
private readonly Consumer $pocketCsvConsumer,
private readonly Consumer $omnivoreConsumer,
) {
}
@ -76,9 +75,6 @@ class RabbitMQConsumerTotalProxy
case 'pocket_html':
$consumer = $this->pocketHtmlConsumer;
break;
case 'pocket_csv':
$consumer = $this->pocketCsvConsumer;
break;
case 'omnivore':
$consumer = $this->omnivoreConsumer;
break;

View File

@ -290,17 +290,6 @@ class EntryRestController extends WallabagRestController
* example="200",
* )
* ),
* @OA\Parameter(
* name="annotations",
* in="query",
* description="filter entries with annotations. all entries by default",
* required=false,
* @OA\Schema(
* type="integer",
* enum={"1", "0"},
* default="0"
* )
* ),
* @OA\Response(
* response="200",
* description="Returned when successful"
@ -326,7 +315,6 @@ class EntryRestController extends WallabagRestController
$detail = strtolower($request->query->get('detail', 'full'));
$domainName = (null === $request->query->get('domain_name')) ? '' : (string) $request->query->get('domain_name');
$httpStatus = (!\array_key_exists((int) $request->query->get('http_status'), Response::$statusTexts)) ? null : (int) $request->query->get('http_status');
$hasAnnotations = (null === $request->query->get('annotations')) ? null : (bool) $request->query->get('annotations');
try {
/** @var Pagerfanta $pager */
@ -342,8 +330,7 @@ class EntryRestController extends WallabagRestController
$detail,
$domainName,
$isNotParsed,
$httpStatus,
$hasAnnotations
$httpStatus
);
} catch (\Exception $e) {
throw new BadRequestHttpException($e->getMessage());
@ -369,7 +356,6 @@ class EntryRestController extends WallabagRestController
'tags' => $tags,
'since' => $since,
'detail' => $detail,
'annotations' => $hasAnnotations,
],
true
)

View File

@ -313,7 +313,6 @@ class ConfigController extends AbstractController
$user = $this->getUser();
$user->setGoogleAuthenticatorSecret('');
$user->setGoogleAuthenticator(false);
$user->setBackupCodes(null);
$this->userManager->updateUser($user);
@ -355,6 +354,11 @@ class ConfigController extends AbstractController
$this->userManager->updateUser($user);
$this->entityManager->flush();
$this->addFlash(
'notice',
'flashes.config.notice.otp_enabled'
);
return $this->render('Config/otp_app.html.twig', [
'backupCodes' => $backupCodes,
'qr_code' => $googleAuthenticator->getQRContent($user),
@ -404,9 +408,6 @@ class ConfigController extends AbstractController
'notice',
'flashes.config.notice.otp_enabled'
);
$user->setGoogleAuthenticator(true);
$this->userManager->updateUser($user);
$this->entityManager->flush();
return $this->redirect($this->generateUrl('config') . '#set3');
}
@ -420,9 +421,8 @@ class ConfigController extends AbstractController
$user->setBackupCodes(null);
$this->userManager->updateUser($user);
$this->entityManager->flush();
return $this->redirect($this->generateUrl('config_otp_app'), 307);
return $this->redirect($this->generateUrl('config') . '#set3');
}
/**

View File

@ -627,16 +627,6 @@ class EntryController extends AbstractController
$currentEntryId = $request->attributes->getInt('id');
$formOptions = [];
$direction = 'desc';
$sortBy = null;
if (null !== $request->get('entry_filter') && null !== $request->get('entry_filter')['sortType'] && '' !== $request->get('entry_filter')['sortType']) {
$direction = (null !== $request->get('entry_filter')['sortOrder'] && \in_array($request->get('entry_filter')['sortOrder'], ['asc', 'desc'], true)) ? $request->get('entry_filter')['sortOrder'] : 'desc';
if (\in_array($request->get('entry_filter')['sortType'], ['id','title','createdAt', 'url', 'readingTime'], true)) {
$sortBy = $request->get('entry_filter')['sortType'];
}
}
switch ($type) {
case 'search':
@ -664,7 +654,7 @@ class EntryController extends AbstractController
$qb = $this->entryRepository->getBuilderForSameDomainByUser($this->getUser()->getId(), $currentEntryId);
break;
case 'all':
$qb = $this->entryRepository->getBuilderForAllByUser($this->getUser()->getId(), $sortBy, $direction);
$qb = $this->entryRepository->getBuilderForAllByUser($this->getUser()->getId());
break;
default:
throw new \InvalidArgumentException(\sprintf('Type "%s" is not implemented.', $type));

View File

@ -20,11 +20,15 @@ abstract class BrowserController extends AbstractController
#[IsGranted('IMPORT_ENTRIES')]
public function indexAction(Request $request, TranslatorInterface $translator)
{
$import = $this->getImportService();
if (!$import->isEnabled()) {
throw $this->createNotFoundException('Import is disabled');
}
$form = $this->createForm(UploadImportType::class);
$form->handleRequest($request);
$wallabag = $this->getImportService();
$wallabag->setUser($this->getUser());
$import->setUser($this->getUser());
if ($form->isSubmitted() && $form->isValid()) {
$file = $form->get('file')->getData();
@ -32,7 +36,7 @@ abstract class BrowserController extends AbstractController
$name = $this->getUser()->getId() . '.json';
if (null !== $file && \in_array($file->getClientMimeType(), $this->getParameter('wallabag.allow_mimetypes'), true) && $file->move($this->getParameter('wallabag.resource_dir'), $name)) {
$res = $wallabag
$res = $import
->setFilepath($this->getParameter('wallabag.resource_dir') . '/' . $name)
->setMarkAsRead($markAsRead)
->import();
@ -40,7 +44,7 @@ abstract class BrowserController extends AbstractController
$message = 'flashes.import.notice.failed';
if (true === $res) {
$summary = $wallabag->getSummary();
$summary = $import->getSummary();
$message = $translator->trans('flashes.import.notice.summary', [
'%imported%' => $summary['imported'],
'%skipped%' => $summary['skipped'],
@ -64,7 +68,7 @@ abstract class BrowserController extends AbstractController
return $this->render($this->getImportTemplate(), [
'form' => $form->createView(),
'import' => $wallabag,
'import' => $import,
]);
}

View File

@ -25,6 +25,10 @@ class DeliciousController extends AbstractController
#[IsGranted('IMPORT_ENTRIES')]
public function indexAction(Request $request, DeliciousImport $delicious, Config $craueConfig, TranslatorInterface $translator)
{
if (!$delicious->isEnabled()) {
throw $this->createNotFoundException('Import is disabled');
}
$form = $this->createForm(UploadImportType::class);
$form->handleRequest($request);

View File

@ -20,11 +20,15 @@ abstract class HtmlController extends AbstractController
#[IsGranted('IMPORT_ENTRIES')]
public function indexAction(Request $request, TranslatorInterface $translator)
{
$import = $this->getImportService();
if (!$import->isEnabled()) {
throw $this->createNotFoundException('Import is disabled');
}
$form = $this->createForm(UploadImportType::class);
$form->handleRequest($request);
$wallabag = $this->getImportService();
$wallabag->setUser($this->getUser());
$import->setUser($this->getUser());
if ($form->isSubmitted() && $form->isValid()) {
$file = $form->get('file')->getData();
@ -32,7 +36,7 @@ abstract class HtmlController extends AbstractController
$name = $this->getUser()->getId() . '.html';
if (null !== $file && \in_array($file->getClientMimeType(), $this->getParameter('wallabag.allow_mimetypes'), true) && $file->move($this->getParameter('wallabag.resource_dir'), $name)) {
$res = $wallabag
$res = $import
->setFilepath($this->getParameter('wallabag.resource_dir') . '/' . $name)
->setMarkAsRead($markAsRead)
->import();
@ -40,7 +44,7 @@ abstract class HtmlController extends AbstractController
$message = 'flashes.import.notice.failed';
if (true === $res) {
$summary = $wallabag->getSummary();
$summary = $import->getSummary();
$message = $translator->trans('flashes.import.notice.summary', [
'%imported%' => $summary['imported'],
'%skipped%' => $summary['skipped'],
@ -64,7 +68,7 @@ abstract class HtmlController extends AbstractController
return $this->render($this->getImportTemplate(), [
'form' => $form->createView(),
'import' => $wallabag,
'import' => $import,
]);
}

View File

@ -58,7 +58,6 @@ class ImportController extends AbstractController
+ $this->rabbitMQConsumerTotalProxy->getTotalMessage('elcurator')
+ $this->rabbitMQConsumerTotalProxy->getTotalMessage('shaarli')
+ $this->rabbitMQConsumerTotalProxy->getTotalMessage('pocket_html')
+ $this->rabbitMQConsumerTotalProxy->getTotalMessage('pocket_csv')
+ $this->rabbitMQConsumerTotalProxy->getTotalMessage('omnivore')
;
} catch (\Exception) {
@ -78,7 +77,6 @@ class ImportController extends AbstractController
+ $this->redisClient->llen('wallabag.import.elcurator')
+ $this->redisClient->llen('wallabag.import.shaarli')
+ $this->redisClient->llen('wallabag.import.pocket_html')
+ $this->redisClient->llen('wallabag.import.pocket_csv')
+ $this->redisClient->llen('wallabag.import.omnivore')
;
} catch (\Exception) {

View File

@ -25,6 +25,10 @@ class InstapaperController extends AbstractController
#[IsGranted('IMPORT_ENTRIES')]
public function indexAction(Request $request, InstapaperImport $instapaper, Config $craueConfig, TranslatorInterface $translator)
{
if (!$instapaper->isEnabled()) {
throw $this->createNotFoundException('Import is disabled');
}
$form = $this->createForm(UploadImportType::class);
$form->handleRequest($request);

View File

@ -25,6 +25,10 @@ class OmnivoreController extends AbstractController
#[IsGranted('IMPORT_ENTRIES')]
public function indexAction(Request $request, OmnivoreImport $omnivore, Config $craueConfig, TranslatorInterface $translator)
{
if (!$omnivore->isEnabled()) {
throw $this->createNotFoundException('Import is disabled');
}
$form = $this->createForm(UploadImportType::class);
$form->handleRequest($request);

View File

@ -25,6 +25,10 @@ class PinboardController extends AbstractController
#[IsGranted('IMPORT_ENTRIES')]
public function indexAction(Request $request, PinboardImport $pinboard, Config $craueConfig, TranslatorInterface $translator)
{
if (!$pinboard->isEnabled()) {
throw $this->createNotFoundException('Import is disabled');
}
$form = $this->createForm(UploadImportType::class);
$form->handleRequest($request);

View File

@ -29,6 +29,10 @@ class PocketController extends AbstractController
#[IsGranted('IMPORT_ENTRIES')]
public function indexAction(PocketImport $pocketImport)
{
if (!$pocketImport->isEnabled()) {
throw $this->createNotFoundException('Import is disabled');
}
$pocket = $this->getPocketImportService($pocketImport);
$form = $this->createFormBuilder($pocket)
@ -49,6 +53,10 @@ class PocketController extends AbstractController
#[IsGranted('IMPORT_ENTRIES')]
public function authAction(Request $request, PocketImport $pocketImport)
{
if (!$pocketImport->isEnabled()) {
throw $this->createNotFoundException('Import is disabled');
}
$requestToken = $this->getPocketImportService($pocketImport)
->getRequestToken($this->generateUrl('import', [], UrlGeneratorInterface::ABSOLUTE_URL));
@ -78,6 +86,10 @@ class PocketController extends AbstractController
#[IsGranted('IMPORT_ENTRIES')]
public function callbackAction(PocketImport $pocketImport, TranslatorInterface $translator)
{
if (!$pocketImport->isEnabled()) {
throw $this->createNotFoundException('Import is disabled');
}
$message = 'flashes.import.notice.failed';
$pocket = $this->getPocketImportService($pocketImport);

View File

@ -1,99 +0,0 @@
<?php
namespace Wallabag\Controller\Import;
use Craue\ConfigBundle\Util\Config;
use OldSound\RabbitMqBundle\RabbitMq\Producer as RabbitMqProducer;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Contracts\Translation\TranslatorInterface;
use Wallabag\Controller\AbstractController;
use Wallabag\Form\Type\UploadImportType;
use Wallabag\Import\PocketCsvImport;
use Wallabag\Redis\Producer as RedisProducer;
class PocketCsvController extends AbstractController
{
public function __construct(
private readonly PocketCsvImport $pocketCsvImport,
private readonly Config $craueConfig,
private readonly RabbitMqProducer $rabbitMqProducer,
private readonly RedisProducer $redisProducer,
) {
}
#[Route(path: '/import/pocket_csv', name: 'import_pocket_csv', methods: ['GET', 'POST'])]
#[IsGranted('IMPORT_ENTRIES')]
public function indexAction(Request $request, TranslatorInterface $translator)
{
$form = $this->createForm(UploadImportType::class);
$form->handleRequest($request);
$this->pocketCsvImport->setUser($this->getUser());
if ($this->craueConfig->get('import_with_rabbitmq')) {
$this->pocketCsvImport->setProducer($this->rabbitMqProducer);
} elseif ($this->craueConfig->get('import_with_redis')) {
$this->pocketCsvImport->setProducer($this->redisProducer);
}
if ($form->isSubmitted() && $form->isValid()) {
$file = $form->get('file')->getData();
$markAsRead = $form->get('mark_as_read')->getData();
$name = 'pocket_' . $this->getUser()->getId() . '.csv';
if (null !== $file && \in_array($file->getClientMimeType(), $this->getParameter('wallabag.allow_mimetypes'), true) && $file->move($this->getParameter('wallabag.resource_dir'), $name)) {
$res = $this->pocketCsvImport
->setFilepath($this->getParameter('wallabag.resource_dir') . '/' . $name)
->setMarkAsRead($markAsRead)
->import();
$message = 'flashes.import.notice.failed';
if (true === $res) {
$summary = $this->pocketCsvImport->getSummary();
$message = $translator->trans('flashes.import.notice.summary', [
'%imported%' => $summary['imported'],
'%skipped%' => $summary['skipped'],
]);
if (0 < $summary['queued']) {
$message = $translator->trans('flashes.import.notice.summary_with_queue', [
'%queued%' => $summary['queued'],
]);
}
unlink($this->getParameter('wallabag.resource_dir') . '/' . $name);
}
$this->addFlash('notice', $message);
return $this->redirect($this->generateUrl('homepage'));
}
$this->addFlash('notice', 'flashes.import.notice.failed_on_file');
}
return $this->render('Import/PocketCsv/index.html.twig', [
'form' => $form->createView(),
'import' => $this->pocketCsvImport,
]);
}
protected function getImportService()
{
if ($this->craueConfig->get('import_with_rabbitmq')) {
$this->pocketCsvImport->setProducer($this->rabbitMqProducer);
} elseif ($this->craueConfig->get('import_with_redis')) {
$this->pocketCsvImport->setProducer($this->redisProducer);
}
return $this->pocketCsvImport;
}
protected function getImportTemplate()
{
return 'Import/PocketCsv/index.html.twig';
}
}

View File

@ -25,6 +25,10 @@ class ReadabilityController extends AbstractController
#[IsGranted('IMPORT_ENTRIES')]
public function indexAction(Request $request, ReadabilityImport $readability, Config $craueConfig, TranslatorInterface $translator)
{
if (!$readability->isEnabled()) {
throw $this->createNotFoundException('Import is disabled');
}
$form = $this->createForm(UploadImportType::class);
$form->handleRequest($request);

View File

@ -22,11 +22,15 @@ abstract class WallabagController extends AbstractController
*/
public function indexAction(Request $request, TranslatorInterface $translator)
{
$import = $this->getImportService();
if (!$import->isEnabled()) {
throw $this->createNotFoundException('Import is disabled');
}
$form = $this->createForm(UploadImportType::class);
$form->handleRequest($request);
$wallabag = $this->getImportService();
$wallabag->setUser($this->getUser());
$import->setUser($this->getUser());
if ($form->isSubmitted() && $form->isValid()) {
$file = $form->get('file')->getData();
@ -34,7 +38,7 @@ abstract class WallabagController extends AbstractController
$name = $this->getUser()->getId() . '.json';
if (null !== $file && \in_array($file->getClientMimeType(), $this->getParameter('wallabag.allow_mimetypes'), true) && $file->move($this->getParameter('wallabag.resource_dir'), $name)) {
$res = $wallabag
$res = $import
->setFilepath($this->getParameter('wallabag.resource_dir') . '/' . $name)
->setMarkAsRead($markAsRead)
->import();
@ -42,7 +46,7 @@ abstract class WallabagController extends AbstractController
$message = 'flashes.import.notice.failed';
if (true === $res) {
$summary = $wallabag->getSummary();
$summary = $import->getSummary();
$message = $translator->trans('flashes.import.notice.summary', [
'%imported%' => $summary['imported'],
'%skipped%' => $summary['skipped'],
@ -67,7 +71,7 @@ abstract class WallabagController extends AbstractController
return $this->render($this->getImportTemplate(), [
'form' => $form->createView(),
'import' => $wallabag,
'import' => $import,
]);
}

View File

@ -147,11 +147,6 @@ class User extends BaseUser implements EmailTwoFactorInterface, GoogleTwoFactorI
#[ORM\Column(name: 'googleAuthenticatorSecret', type: 'string', nullable: true)]
private $googleAuthenticatorSecret;
// default value is explicitly set to false here to ensure that Doctrine
// does not complain about schema mapping mismatch
#[ORM\Column(name: 'google_authenticator', type: 'boolean', options: ['default' => false])]
private $googleAuthenticator = false;
/**
* @var array
*/
@ -269,11 +264,6 @@ class User extends BaseUser implements EmailTwoFactorInterface, GoogleTwoFactorI
$this->emailTwoFactor = $emailTwoFactor;
}
public function setGoogleAuthenticator(bool $googleAuthenticator): void
{
$this->googleAuthenticator = $googleAuthenticator;
}
/**
* Used in the user config form to be "like" the email option.
*/
@ -304,7 +294,7 @@ class User extends BaseUser implements EmailTwoFactorInterface, GoogleTwoFactorI
public function isGoogleAuthenticatorEnabled(): bool
{
return $this->googleAuthenticator;
return $this->googleAuthenticatorSecret ? true : false;
}
public function getGoogleAuthenticatorUsername(): string

View File

@ -205,24 +205,6 @@ class EntryFilterType extends AbstractType
'choices' => array_flip($this->repository->findDistinctLanguageByUser($user->getId())),
'label' => 'entry.filters.language_label',
])
->add('sortOrder', ChoiceFilterType::class, [
'apply_filter' => function (QueryInterface $filterQuery, $field, $values) { },
'choices' => [
'entry.sort.ascending' => 'asc',
'entry.sort.descending' => 'desc',
],
'label' => 'entry.sort.order_label',
])
->add('sortType', ChoiceFilterType::class, [
'apply_filter' => function (QueryInterface $filterQuery, $field, $values) { },
'choices' => [
'entry.sort.by.creation_date' => 'createdAt',
'entry.sort.by.title' => 'title',
'entry.sort.by.url' => 'url',
'entry.sort.by.reading_time' => 'readingTime',
],
'label' => 'entry.sort.status_label',
])
;
}

View File

@ -21,6 +21,7 @@ abstract class AbstractImport implements ImportInterface
protected $skippedEntries = 0;
protected $importedEntries = 0;
protected $queuedEntries = 0;
protected $enabled = true;
public function __construct(
protected EntityManagerInterface $em,
@ -74,6 +75,25 @@ abstract class AbstractImport implements ImportInterface
return $this->markAsRead;
}
/**
* Get whether the import is enabled.
* If not, the importer won't be available in the UI.
*/
public function isEnabled(): bool
{
return $this->enabled;
}
/**
* Set whether the import is enabled.
*/
public function setEnabled(bool $enabled): static
{
$this->enabled = $enabled;
return $this;
}
/**
* Set whether articles should be fetched for updated content.
*

View File

@ -63,4 +63,15 @@ interface ImportInterface extends LoggerAwareInterface
* @param bool $markAsRead
*/
public function setMarkAsRead($markAsRead): static;
/**
* Get whether the import is enabled.
* If not, the importer won't be available in the UI.
*/
public function isEnabled(): bool;
/**
* Set whether the import is enabled.
*/
public function setEnabled(bool $enabled): static;
}

View File

@ -1,133 +0,0 @@
<?php
namespace Wallabag\Import;
use Wallabag\Entity\Entry;
class PocketCsvImport extends AbstractImport
{
protected $filepath;
public function getName()
{
return 'Pocket CSV';
}
public function getUrl()
{
return 'import_pocket_csv';
}
public function getDescription()
{
return 'import.pocket_csv.description';
}
public function setFilepath($filepath): static
{
$this->filepath = $filepath;
return $this;
}
public function validateEntry(array $importedEntry)
{
if (empty($importedEntry['url'])) {
return false;
}
return true;
}
public function import()
{
if (!$this->user) {
$this->logger->error('Pocket CSV Import: user is not defined');
return false;
}
if (!file_exists($this->filepath) || !is_readable($this->filepath)) {
$this->logger->error('Pocket CSV Import: unable to read file', ['filepath' => $this->filepath]);
return false;
}
$entries = [];
$handle = fopen($this->filepath, 'r');
while (false !== ($data = fgetcsv($handle, 10240))) {
if ('title' === $data[0]) {
continue;
}
$entries[] = [
'url' => $data[1],
'title' => $data[0],
'is_archived' => 'archive' === $data[4],
'created_at' => $data[2],
'tags' => $data[3],
];
}
fclose($handle);
if (empty($entries)) {
$this->logger->error('PocketCsvImport: no entries in imported file');
return false;
}
if ($this->producer) {
$this->parseEntriesForProducer($entries);
return true;
}
$this->parseEntries($entries);
return true;
}
public function parseEntry(array $importedEntry)
{
$existingEntry = $this->em
->getRepository(Entry::class)
->findByUrlAndUserId($importedEntry['url'], $this->user->getId());
if (false !== $existingEntry) {
++$this->skippedEntries;
return null;
}
$entry = new Entry($this->user);
$entry->setUrl($importedEntry['url']);
$entry->setTitle($importedEntry['title']);
// update entry with content (in case fetching failed, the given entry will be return)
$this->fetchContent($entry, $importedEntry['url'], $importedEntry);
if (!empty($importedEntry['tags'])) {
$tags = str_replace('|', ',', $importedEntry['tags']);
$this->tagsAssigner->assignTagsToEntry(
$entry,
$tags,
$this->em->getUnitOfWork()->getScheduledEntityInsertions()
);
}
$entry->updateArchived($importedEntry['is_archived']);
$entry->setCreatedAt(\DateTime::createFromFormat('U', $importedEntry['created_at']));
$this->em->persist($entry);
++$this->importedEntries;
return $entry;
}
protected function setEntryAsRead(array $importedEntry)
{
$importedEntry['is_archived'] = 'archive';
return $importedEntry;
}
}

View File

@ -30,11 +30,10 @@ class EntryRepository extends ServiceEntityRepository
*
* @return QueryBuilder
*/
public function getBuilderForAllByUser($userId, $sortBy = 'createdAt', $direction = 'desc')
public function getBuilderForAllByUser($userId)
{
$sortBy = $sortBy ?: 'createdAt';
return $this
->getSortedQueryBuilderByUser($userId, $sortBy, $direction)
->getSortedQueryBuilderByUser($userId)
;
}
@ -269,17 +268,16 @@ class EntryRepository extends ServiceEntityRepository
* @param string $order
* @param int $since
* @param string $tags
* @param string $detail 'metadata' or 'full'. Include content field if 'full'
* @param string $detail 'metadata' or 'full'. Include content field if 'full'
* @param string $domainName
* @param int $httpStatus
* @param bool $isNotParsed
* @param bool $hasAnnotations
*
* @todo Breaking change: replace default detail=full by detail=metadata in a future version
*
* @return Pagerfanta
*/
public function findEntries($userId, $isArchived = null, $isStarred = null, $isPublic = null, $sort = 'created', $order = 'asc', $since = 0, $tags = '', $detail = 'full', $domainName = '', $isNotParsed = null, $httpStatus = null, $hasAnnotations = null)
public function findEntries($userId, $isArchived = null, $isStarred = null, $isPublic = null, $sort = 'created', $order = 'asc', $since = 0, $tags = '', $detail = 'full', $domainName = '', $isNotParsed = null, $httpStatus = null)
{
if (!\in_array(strtolower($detail), ['full', 'metadata'], true)) {
throw new \Exception('Detail "' . $detail . '" parameter is wrong, allowed: full or metadata');
@ -344,16 +342,6 @@ class EntryRepository extends ServiceEntityRepository
$qb->andWhere('e.domainName = :domainName')->setParameter('domainName', $domainName);
}
if (null !== $hasAnnotations) {
if ($hasAnnotations) {
$qb->leftJoin('e.annotations', 'a')
->andWhere('a.id IS NOT NULL');
} else {
$qb->leftJoin('e.annotations', 'a')
->andWhere('a.id IS NULL');
}
}
if (!\in_array(strtolower($order), ['asc', 'desc'], true)) {
throw new \Exception('Order "' . $order . '" parameter is wrong, allowed: asc or desc');
}

View File

@ -18,14 +18,14 @@
<img data-controller="qrcode" data-qrcode-url-value="{{ qr_code|raw }}" class="hide-on-med-and-down" />
</p>
<div id="config_otp_app_secret">
<div data-controller="highlight">
{{ 'config.otp.app.two_factor_code_description_5'|trans }} <pre><code>{{ secret }}</code></pre>
</div>
</li>
<li>
<p>{{ 'config.otp.app.two_factor_code_description_3'|trans }}</p>
<div><pre><code>{{ backupCodes|join("\n") }}</code></pre></div>
<div data-controller="highlight"><pre><code>{{ backupCodes|join("\n") }}</code></pre></div>
</li>
<li>
<p>{{ 'config.otp.app.two_factor_code_description_4'|trans }}</p>
@ -36,7 +36,7 @@
</div>
{% endfor %}
<form class="form" action="{{ path("config_otp_app_check") }}" method="post" name="config_otp_app_check">
<form class="form" action="{{ path("config_otp_app_check") }}" method="post">
<input type="hidden" name="token" value="{{ csrf_token('otp') }}" />
<div class="card-content">
<div class="row">

View File

@ -276,22 +276,6 @@
<label for="entry_filter_createdAt_right_date" class="active">{{ 'entry.filters.created_at.to'|trans }}</label>
</div>
<div class="col s6">
{{ form_label(form.sortType) }}
</div>
<div class="col s6">
{{ form_label(form.sortOrder) }}
</div>
<div class="col s6">
{{ form_widget(form.sortType) }}
</div>
<div class="col s6">
{{ form_widget(form.sortOrder) }}
</div>
<div class="col s6">
<button type="reset" class="center waves-effect waves-green btn-flat">{{ 'entry.filters.action.clear'|trans }}</button>
</div>

View File

@ -24,7 +24,7 @@
<header class="block">
<h1>{{ entry.title|e|raw }}</h1>
<a href="{{ entry.url|e }}" target="_blank" rel="noopener" title="{{ 'entry.view.original_article'|trans }} : {{ entry.title|e|raw }}" class="tool">{{ entry.domainName|removeWww }}</a>
<p class="shared-by">{{ "entry.public.shared_by_wallabag"|trans({'%wallabag_instance%': url('homepage'), '%username%': entry.user.name|escape})|raw }}.</p>
<p class="shared-by">{{ "entry.public.shared_by_wallabag"|trans({'%wallabag_instance%': url('homepage'), '%username%': entry.user.username|escape})|raw }}.</p>
</header>
<article class="block">
{{ entry.content|raw }}

View File

@ -1,47 +0,0 @@
{% extends "layout.html.twig" %}
{% block title %}{{ 'import.pocket_csv.page_title'|trans }}{% endblock %}
{% block content %}
<div class="row">
<div class="col s12">
<div class="card-panel settings">
{% include 'Import/_information.html.twig' %}
<div class="row">
<blockquote>{{ import.description|trans|raw }}</blockquote>
<p>{{ 'import.pocket_csv.how_to'|trans }}</p>
<div class="col s12">
{{ form_start(form, {'method': 'POST'}) }}
{{ form_errors(form) }}
<div class="row">
<div class="file-field input-field col s12">
{{ form_errors(form.file) }}
<div class="btn">
<span>{{ form.file.vars.label|trans }}</span>
{{ form_widget(form.file) }}
</div>
<div class="file-path-wrapper">
<input class="file-path validate" type="text">
</div>
</div>
<h6 class="col s12">{{ 'import.form.mark_as_read_title'|trans }}</h6>
<div class="col s6 with-checkbox">
<label for="{{ form.mark_as_read.vars.id }}">
{{ form_widget(form.mark_as_read) }}
<span>{{ form.mark_as_read.vars.label|trans }}</span>
</label>
</div>
</div>
{{ form_widget(form.save, {'attr': {'class': 'btn waves-effect waves-light'}}) }}
{{ form_rest(form) }}
</form>
</div>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -16,17 +16,17 @@
{{ 'import.page_description'|trans }}
<div class="row">
{% for import in imports %}
{% for import in imports | filter(i => i.isEnabled()) %}
<div class="col s6 m3">
<div class="card">
<div class="card-content">
<span class="card-title">{{ import.name }}</span>
</div>
<div class="card-action">
<a href="{{ path(import.url) }}">{{ 'import.action.import_contents'|trans }}</a>
</div>
<div class="card-content">
<span class="card-title">{{ import.name }}</span>
</div>
<div class="card-action">
<a href="{{ path(import.url) }}">{{ 'import.action.import_contents'|trans }}</a>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
</div>

View File

@ -20,11 +20,10 @@
<div id="set1" class="col s12">
<dt>{{ 'about.who_behind_wallabag.developped_by'|trans }}</dt>
<dd>Nicolas Lœuillet — <a href="https://nicolas.loeuillet.org">{{ 'about.who_behind_wallabag.website'|trans }}</a></dd>
<dd><a href="mailto:nicolas@loeuillet.org">Nicolas Lœuillet</a> — <a href="https://nicolas.loeuillet.org">{{ 'about.who_behind_wallabag.website'|trans }}</a></dd>
<dd>Thomas Citharel — <a href="https://tcit.fr">{{ 'about.who_behind_wallabag.website'|trans }}</a></dd>
<dd>Jérémy Benoist — <a href="https://www.j0k3r.net">{{ 'about.who_behind_wallabag.website'|trans }}</a></dd>
<dd>Kevin Decherf — <a href="https://kdecherf.com/">{{ 'about.who_behind_wallabag.website'|trans }}</a></dd>
<dd>Yassine Guedidi</dd>
<dt>{{ 'about.who_behind_wallabag.many_contributors'|trans|raw }}</dt>
<dt>{{ 'about.who_behind_wallabag.project_website'|trans }}</dt>
<dd><a href="https://www.wallabag.org">https://www.wallabag.org</a></dd>
@ -34,7 +33,11 @@
<div id="set2" class="col s12">
<dl>
<dt><a href="https://doc.wallabag.org/">{{ 'about.getting_help.documentation'|trans }}</a></dt>
<dt>{{ 'about.getting_help.documentation'|trans }}</dt>
<dd><a href="https://doc.wallabag.org/en/">english</a></dd>
<dd><a href="https://doc.wallabag.org/fr/">français</a></dd>
<dd><a href="https://doc.wallabag.org/de/">deutsch</a></dd>
<dd><a href="https://doc.wallabag.org/it/">italiano</a></dd>
<dt>{{ 'about.getting_help.bug_reports'|trans }}</dt>
<dd>{{ 'about.getting_help.support'|trans|raw }}</dd>

View File

@ -56,7 +56,7 @@
</div>
<div class="card-action">
<ul>
<li><a href="{{ path('import_pocket_csv') }}">{{ 'quickstart.migrate.pocket'|trans }}</a></li>
<li><a href="{{ path('import_pocket') }}">{{ 'quickstart.migrate.pocket'|trans }}</a></li>
<li><a href="{{ path('import_readability') }}">{{ 'quickstart.migrate.readability'|trans }}</a></li>
<li><a href="{{ path('import_instapaper') }}">{{ 'quickstart.migrate.instapaper'|trans }}</a></li>
<li><a href="{{ path('import') }}">{{ 'quickstart.more'|trans }}</a></li>
@ -75,6 +75,7 @@
<div class="card-action">
<ul>
<li><a href="{{ path('developer') }}">{{ 'quickstart.developer.create_application'|trans }}</a></li>
<li><a href="https://doc.wallabag.org/en/developer/docker.html">{{ 'quickstart.developer.use_docker'|trans }}</a></li>
<li><a href="https://doc.wallabag.org/">{{ 'quickstart.more'|trans }}</a></li>
</ul>
</div>

View File

@ -1,99 +0,0 @@
<?php
namespace Tests\Wallabag\Command\Import;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\NoResultException;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Component\Console\Exception\RuntimeException;
use Symfony\Component\Console\Tester\CommandTester;
use Tests\Wallabag\WallabagTestCase;
use Wallabag\Entity\Entry;
class UrlCommandTest extends WallabagTestCase
{
private $url = 'https://www.20minutes.fr/sport/football/4158082-20250612-euro-espoirs-su-souffrir-ensemble-decimes-bleuets-retiennent-positif-apres-nul-face-portugal';
public function testRunUrlCommandWithoutArguments()
{
$this->expectException(RuntimeException::class);
$this->expectExceptionMessage('Not enough arguments');
$application = new Application($this->getTestClient()->getKernel());
$command = $application->find('wallabag:import:url');
$tester = new CommandTester($command);
$tester->execute([]);
}
public function testRunUrlCommandWithWrongUsername()
{
$this->expectException(NoResultException::class);
$application = new Application($this->getTestClient()->getKernel());
$command = $application->find('wallabag:import:url');
$tester = new CommandTester($command);
$tester->execute([
'username' => 'random',
'url' => $this->url,
]);
}
public function testRunUrlCommand()
{
$application = new Application($this->getTestClient()->getKernel());
$command = $application->find('wallabag:import:url');
$tester = new CommandTester($command);
$tester->execute([
'username' => 'admin',
'url' => $this->url,
]);
$this->assertStringContainsString('successfully imported', $tester->getDisplay());
}
public function testRunUrlCommandWithTags()
{
$application = new Application($this->getTestClient()->getKernel());
$command = $application->find('wallabag:import:url');
$tester = new CommandTester($command);
$tester->execute([
'username' => 'admin',
'url' => $this->url,
'tags' => 'sport, football',
]);
$this->assertStringContainsString('successfully imported', $tester->getDisplay());
$client = $this->getTestClient();
$em = $client->getContainer()->get(EntityManagerInterface::class);
$entry = $em->getRepository(Entry::class)->findByUrlAndUserId($this->url, $this->getLoggedInUserId());
$this->assertContains('football', $entry->getTagsLabel());
$this->assertNotContains('basketball', $entry->getTagsLabel());
}
public function testRunUrlCommandWithUserId()
{
$this->logInAs('admin');
$application = new Application($this->getTestClient()->getKernel());
$command = $application->find('wallabag:import:url');
$tester = new CommandTester($command);
$tester->execute([
'username' => $this->getLoggedInUserId(),
'url' => $this->url,
'--useUserId' => true,
]);
$this->assertStringContainsString('successfully imported', $tester->getDisplay());
}
}

View File

@ -227,7 +227,6 @@ class EntryRestControllerTest extends WallabagApiTestCase
'public' => 0,
'notParsed' => 0,
'http_status' => 200,
'annotations' => 1,
]);
$this->assertSame(200, $this->client->getResponse()->getStatusCode());
@ -255,7 +254,6 @@ class EntryRestControllerTest extends WallabagApiTestCase
$this->assertStringContainsString('tags=foo', $content['_links'][$link]['href']);
$this->assertStringContainsString('since=1443274283', $content['_links'][$link]['href']);
$this->assertStringContainsString('public=0', $content['_links'][$link]['href']);
$this->assertStringContainsString('annotations=1', $content['_links'][$link]['href']);
}
$this->assertSame('application/json', $this->client->getResponse()->headers->get('Content-Type'));
@ -307,86 +305,6 @@ class EntryRestControllerTest extends WallabagApiTestCase
$this->assertSame('application/json', $this->client->getResponse()->headers->get('Content-Type'));
}
public function testGetEntriesWithAnnotationsFilter()
{
// Test filter for entries WITH annotations
// From fixtures: entry1 and entry2 have annotations, entry4, entry5, entry6, entry7 don't
$this->client->request('GET', '/api/entries', [
'annotations' => 1,
]);
$this->assertSame(200, $this->client->getResponse()->getStatusCode());
$content = json_decode($this->client->getResponse()->getContent(), true);
$this->assertArrayHasKey('items', $content['_embedded']);
// Check that only entries with annotations are returned
$entriesWithAnnotations = ['http://0.0.0.0/entry1', 'http://0.0.0.0/entry2'];
$entriesWithoutAnnotations = ['http://0.0.0.0/entry4', 'http://0.0.0.0/entry5', 'http://0.0.0.0/entry6', 'http://0.0.0.0/entry7'];
foreach ($content['_embedded']['items'] as $item) {
if (\in_array($item['url'], $entriesWithAnnotations, true)) {
$this->assertNotEmpty($item['annotations'], 'Entry with URL ' . $item['url'] . ' should have annotations');
}
$this->assertNotContains($item['url'], $entriesWithoutAnnotations, 'Entry without annotations should NOT be in the results');
}
// Ensure we have at least the entries with annotations
$foundUrls = array_column($content['_embedded']['items'], 'url');
$this->assertContains('http://0.0.0.0/entry1', $foundUrls, 'entry1 with annotations should be in the results');
$this->assertContains('http://0.0.0.0/entry2', $foundUrls, 'entry2 with annotations should be in the results');
// Check pagination links contain the filter
$this->assertArrayHasKey('_links', $content);
foreach (['self', 'first', 'last'] as $link) {
$this->assertArrayHasKey('href', $content['_links'][$link]);
$this->assertStringContainsString('annotations=1', $content['_links'][$link]['href']);
}
$this->assertSame('application/json', $this->client->getResponse()->headers->get('Content-Type'));
}
public function testGetEntriesWithoutAnnotationsFilter()
{
// Test filter for entries WITHOUT annotations
// From fixtures: entry1 and entry2 have annotations, entry4, entry5, entry6, entry7 don't
$this->client->request('GET', '/api/entries', [
'annotations' => 0,
]);
$this->assertSame(200, $this->client->getResponse()->getStatusCode());
$content = json_decode($this->client->getResponse()->getContent(), true);
$this->assertArrayHasKey('items', $content['_embedded']);
// Check that only entries without annotations are returned
$entriesWithAnnotations = ['http://0.0.0.0/entry1', 'http://0.0.0.0/entry2'];
$entriesWithoutAnnotations = ['http://0.0.0.0/entry4', 'http://0.0.0.0/entry5', 'http://0.0.0.0/entry6', 'http://0.0.0.0/entry7'];
foreach ($content['_embedded']['items'] as $item) {
$this->assertNotContains($item['url'], $entriesWithAnnotations, 'Entry with annotations should NOT be in the results');
if (\in_array($item['url'], $entriesWithoutAnnotations, true)) {
$this->assertEmpty($item['annotations'], 'Entry with URL ' . $item['url'] . ' should not have annotations');
}
}
// Ensure we have at least some entries without annotations
$foundUrls = array_column($content['_embedded']['items'], 'url');
$foundWithoutAnnotations = array_intersect($foundUrls, $entriesWithoutAnnotations);
$this->assertNotEmpty($foundWithoutAnnotations, 'Should have at least one entry without annotations in the results');
// Check pagination links contain the filter
$this->assertArrayHasKey('_links', $content);
foreach (['self', 'first', 'last'] as $link) {
$this->assertArrayHasKey('href', $content['_links'][$link]);
$this->assertStringContainsString('annotations=0', $content['_links'][$link]['href']);
}
$this->assertSame('application/json', $this->client->getResponse()->headers->get('Content-Type'));
}
public function testGetEntriesOnPageTwo()
{
$this->client->request('GET', '/api/entries', [

View File

@ -3,7 +3,6 @@
namespace Tests\Wallabag\Controller;
use Doctrine\ORM\EntityManagerInterface;
use Scheb\TwoFactorBundle\Security\TwoFactor\Provider\Google\GoogleAuthenticatorInterface;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
@ -1224,74 +1223,27 @@ class ConfigControllerTest extends WallabagTestCase
public function testUserEnable2faGoogle()
{
$googleAuthenticatorMock = $this->createMock(GoogleAuthenticatorInterface::class);
$googleAuthenticatorMock
->method('generateSecret')
->willReturn('DUMMYSECRET');
$googleAuthenticatorMock
->method('checkCode')
->willReturnCallback(function ($user, $code) {
return '123456' === $code;
});
$this->logInAs('admin');
$client = $this->getTestClient();
$client->disableReboot(); // Disable reboot to keep the mock in the container
// name::class notation does not work in this context
self::getContainer()->set('scheb_two_factor.security.google_authenticator', $googleAuthenticatorMock);
$crawler = $client->request('GET', '/config');
$form = $crawler->filter('form[name=config_otp_app]')->form();
$crawler = $client->submit($form);
$client->submit($form);
$this->assertSame(200, $client->getResponse()->getStatusCode());
$secret = $crawler->filter('div#config_otp_app_secret pre code')->innerText();
$this->assertSame('DUMMYSECRET', $secret);
$em = $this->getEntityManager();
$user = $em
->getRepository(User::class)
->findOneByUsername('admin');
// At this phase, the user should not have 2FA enabled
$this->assertFalse($user->isGoogleTwoFactor());
// First test: send invalid OTP code
$form = $crawler->filter('form[name=config_otp_app_check]')->form();
$data = [
'_auth_code' => '000000',
];
$client->submit($form, $data);
$this->assertSame(307, $client->getResponse()->getStatusCode());
$this->assertStringContainsString('flashes.config.notice.otp_code_invalid', $client->getContainer()->get(SessionInterface::class)->getFlashBag()->get('notice')[0]);
// Follow the redirect to the OTP check form again
$crawler = $client->followRedirect();
// Second test: send valid OTP code
$form = $crawler->filter('form[name=config_otp_app_check]')->form();
$data = [
'_auth_code' => '123456',
];
$client->submit($form, $data);
$this->assertSame(302, $client->getResponse()->getStatusCode());
$this->assertStringContainsString('flashes.config.notice.otp_enabled', $client->getContainer()->get(SessionInterface::class)->getFlashBag()->get('notice')[0]);
// restore user
$em = $this->getEntityManager();
$user = $em
->getRepository(User::class)
->findOneByUsername('admin');
$this->assertTrue($user->isGoogleTwoFactor());
$this->assertGreaterThan(0, \count($user->getBackupCodes()));
$this->assertGreaterThan(0, $user->getBackupCodes());
// Restore user
$user->setGoogleAuthenticatorSecret('');
$user->setGoogleAuthenticator(false);
$user->setBackupCodes([]);
$user->setGoogleAuthenticatorSecret(false);
$user->setBackupCodes(null);
$em->persist($user);
$em->flush();
}
@ -1307,7 +1259,6 @@ class ConfigControllerTest extends WallabagTestCase
->findOneByUsername('admin');
$user->setGoogleAuthenticatorSecret('Google2FA');
$user->setGoogleAuthenticator(true);
$em->persist($user);
$em->flush();
@ -1320,6 +1271,7 @@ class ConfigControllerTest extends WallabagTestCase
$this->assertStringContainsString('flashes.config.notice.otp_disabled', $client->getContainer()->get(SessionInterface::class)->getFlashBag()->get('notice')[0]);
// restore user
$em = $this->getEntityManager();
$user = $em
->getRepository(User::class)
@ -1327,7 +1279,6 @@ class ConfigControllerTest extends WallabagTestCase
$this->assertEmpty($user->getGoogleAuthenticatorSecret());
$this->assertEmpty($user->getBackupCodes());
$this->assertFalse($user->isGoogleTwoFactor());
}
public function testExportTaggingRule()

View File

@ -91,7 +91,7 @@ class ChromeControllerTest extends WallabagTestCase
$client->getContainer()->get(Config::class)->set('import_with_redis', 0);
}
public function testImportWallabagWithChromeFile()
public function testImportChromeWithFile()
{
$this->logInAs('admin');
$client = $this->getTestClient();
@ -132,7 +132,7 @@ class ChromeControllerTest extends WallabagTestCase
$this->assertSame('07', $createdAt->format('m'));
}
public function testImportWallabagWithEmptyFile()
public function testImportChromeWithEmptyFile()
{
$this->logInAs('admin');
$client = $this->getTestClient();
@ -155,4 +155,17 @@ class ChromeControllerTest extends WallabagTestCase
$this->assertGreaterThan(1, $body = $crawler->filter('body')->extract(['_text']));
$this->assertStringContainsString('flashes.import.notice.failed', $body[0]);
}
public function testImportChromeDisabled()
{
$this->logInAs('admin');
$client = $this->getTestClient();
$client->getContainer()->get(Config::class)->set('chrome_enabled', 0);
$client->request('GET', '/import/chrome');
$this->assertSame(404, $client->getResponse()->getStatusCode());
$client->getContainer()->get(Config::class)->set('chrome_enabled', 1);
}
}

View File

@ -200,4 +200,17 @@ class DeliciousControllerTest extends WallabagTestCase
$this->assertGreaterThan(1, $body = $crawler->filter('body')->extract(['_text']));
$this->assertStringContainsString('flashes.import.notice.failed', $body[0]);
}
public function testImportDeliciousDisabled()
{
$this->logInAs('admin');
$client = $this->getTestClient();
$client->getContainer()->get(Config::class)->set('delicious_enabled', 0);
$client->request('GET', '/import/delicious');
$this->assertSame(404, $client->getResponse()->getStatusCode());
$client->getContainer()->get(Config::class)->set('delicious_enabled', 1);
}
}

View File

@ -133,4 +133,17 @@ class ElcuratorControllerTest extends WallabagTestCase
$this->assertContains('tag1', $tags, 'It includes the "tag1" tag');
$this->assertContains('tag2', $tags, 'It includes the "tag2" tag');
}
public function testImportElcuratorDisabled()
{
$this->logInAs('admin');
$client = $this->getTestClient();
$client->getContainer()->get(Config::class)->set('elcurator_enabled', 0);
$client->request('GET', '/import/elcurator');
$this->assertSame(404, $client->getResponse()->getStatusCode());
$client->getContainer()->get(Config::class)->set('elcurator_enabled', 1);
}
}

View File

@ -91,7 +91,7 @@ class FirefoxControllerTest extends WallabagTestCase
$client->getContainer()->get(Config::class)->set('import_with_redis', 0);
}
public function testImportWallabagWithFirefoxFile()
public function testImportFirefoxWithFile()
{
$this->logInAs('admin');
$client = $this->getTestClient();
@ -129,7 +129,7 @@ class FirefoxControllerTest extends WallabagTestCase
$this->assertCount(3, $content->getTags());
}
public function testImportWallabagWithEmptyFile()
public function testImportFirefoxWithEmptyFile()
{
$this->logInAs('admin');
$client = $this->getTestClient();
@ -152,4 +152,17 @@ class FirefoxControllerTest extends WallabagTestCase
$this->assertGreaterThan(1, $body = $crawler->filter('body')->extract(['_text']));
$this->assertStringContainsString('flashes.import.notice.failed', $body[0]);
}
public function testImportFirefoxDisabled()
{
$this->logInAs('admin');
$client = $this->getTestClient();
$client->getContainer()->get(Config::class)->set('firefox_enabled', 0);
$client->request('GET', '/import/firefox');
$this->assertSame(404, $client->getResponse()->getStatusCode());
$client->getContainer()->get(Config::class)->set('firefox_enabled', 1);
}
}

View File

@ -23,6 +23,6 @@ class ImportControllerTest extends WallabagTestCase
$crawler = $client->request('GET', '/import/');
$this->assertSame(200, $client->getResponse()->getStatusCode());
$this->assertSame(14, $crawler->filter('.card-title')->count());
$this->assertSame(13, $crawler->filter('.card-title')->count());
}
}

View File

@ -213,4 +213,17 @@ class InstapaperControllerTest extends WallabagTestCase
$this->assertGreaterThan(1, $body = $crawler->filter('body')->extract(['_text']));
$this->assertStringContainsString('flashes.import.notice.failed', $body[0]);
}
public function testImportInstapaperDisabled()
{
$this->logInAs('admin');
$client = $this->getTestClient();
$client->getContainer()->get(Config::class)->set('instapaper_enabled', 0);
$client->request('GET', '/import/instapaper');
$this->assertSame(404, $client->getResponse()->getStatusCode());
$client->getContainer()->get(Config::class)->set('instapaper_enabled', 1);
}
}

View File

@ -200,4 +200,17 @@ class OmnivoreControllerTest extends WallabagTestCase
$this->assertGreaterThan(1, $body = $crawler->filter('body')->extract(['_text']));
$this->assertStringContainsString('flashes.import.notice.failed', $body[0]);
}
public function testImportOmnivoreDisabled()
{
$this->logInAs('admin');
$client = $this->getTestClient();
$client->getContainer()->get(Config::class)->set('omnivore_enabled', 0);
$client->request('GET', '/import/omnivore');
$this->assertSame(404, $client->getResponse()->getStatusCode());
$client->getContainer()->get(Config::class)->set('omnivore_enabled', 1);
}
}

View File

@ -207,4 +207,17 @@ class PinboardControllerTest extends WallabagTestCase
$this->assertGreaterThan(1, $body = $crawler->filter('body')->extract(['_text']));
$this->assertStringContainsString('flashes.import.notice.failed', $body[0]);
}
public function testImportPinboardDisabled()
{
$this->logInAs('admin');
$client = $this->getTestClient();
$client->getContainer()->get(Config::class)->set('pinboard_enabled', 0);
$client->request('GET', '/import/pinboard');
$this->assertSame(404, $client->getResponse()->getStatusCode());
$client->getContainer()->get(Config::class)->set('pinboard_enabled', 1);
}
}

View File

@ -75,6 +75,11 @@ class PocketControllerTest extends WallabagTestCase
->method('getRequestToken')
->willReturn('token');
$pocketImport
->expects($this->once())
->method('isEnabled')
->willReturn(true);
static::$kernel->getContainer()->set(PocketImport::class, $pocketImport);
$client->request('POST', '/import/pocket/auth');
@ -97,6 +102,11 @@ class PocketControllerTest extends WallabagTestCase
->method('authorize')
->willReturn(false);
$pocketImport
->expects($this->once())
->method('isEnabled')
->willReturn(true);
static::$kernel->getContainer()->set(PocketImport::class, $pocketImport);
$client->request('GET', '/import/pocket/callback');
@ -131,6 +141,11 @@ class PocketControllerTest extends WallabagTestCase
->method('import')
->willReturn(true);
$pocketImport
->expects($this->once())
->method('isEnabled')
->willReturn(true);
static::$kernel->getContainer()->set(PocketImport::class, $pocketImport);
$client->request('GET', '/import/pocket/callback');
@ -139,4 +154,17 @@ class PocketControllerTest extends WallabagTestCase
$this->assertStringContainsString('/', $client->getResponse()->headers->get('location'), 'Import is ok, redirect to homepage');
$this->assertSame('flashes.import.notice.summary', $client->getContainer()->get(SessionInterface::class)->getFlashBag()->peek('notice')[0]);
}
public function testImportPocketDisabled()
{
$this->logInAs('admin');
$client = $this->getTestClient();
$client->getContainer()->get(Config::class)->set('pocket_enabled', 0);
$client->request('GET', '/import/pocket');
$this->assertSame(404, $client->getResponse()->getStatusCode());
$client->getContainer()->get(Config::class)->set('pocket_enabled', 1);
}
}

View File

@ -1,168 +0,0 @@
<?php
namespace Tests\Wallabag\Controller\Import;
use Craue\ConfigBundle\Util\Config;
use Doctrine\ORM\EntityManagerInterface;
use Predis\Client;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Tests\Wallabag\WallabagTestCase;
use Wallabag\Entity\Entry;
class PocketCsvControllerTest extends WallabagTestCase
{
public function testImportPocketCsv()
{
$this->logInAs('admin');
$client = $this->getTestClient();
$crawler = $client->request('GET', '/import/pocket_csv');
$this->assertSame(200, $client->getResponse()->getStatusCode());
$this->assertSame(1, $crawler->filter('form[name=upload_import_file] > button[type=submit]')->count());
$this->assertSame(1, $crawler->filter('input[type=file]')->count());
}
public function testImportPocketCsvWithRabbitEnabled()
{
$this->logInAs('admin');
$client = $this->getTestClient();
$client->getContainer()->get(Config::class)->set('import_with_rabbitmq', 1);
$crawler = $client->request('GET', '/import/pocket_csv');
$this->assertSame(200, $client->getResponse()->getStatusCode());
$this->assertSame(1, $crawler->filter('form[name=upload_import_file] > button[type=submit]')->count());
$this->assertSame(1, $crawler->filter('input[type=file]')->count());
$client->getContainer()->get(Config::class)->set('import_with_rabbitmq', 0);
}
public function testImportPocketCsvBadFile()
{
$this->logInAs('admin');
$client = $this->getTestClient();
$crawler = $client->request('GET', '/import/pocket_csv');
$form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form();
$data = [
'upload_import_file[file]' => '',
];
$client->submit($form, $data);
$this->assertSame(200, $client->getResponse()->getStatusCode());
}
public function testImportPocketCsvWithRedisEnabled()
{
$this->checkRedis();
$this->logInAs('admin');
$client = $this->getTestClient();
$client->getContainer()->get(Config::class)->set('import_with_redis', 1);
$crawler = $client->request('GET', '/import/pocket_csv');
$this->assertSame(200, $client->getResponse()->getStatusCode());
$this->assertSame(1, $crawler->filter('form[name=upload_import_file] > button[type=submit]')->count());
$this->assertSame(1, $crawler->filter('input[type=file]')->count());
$form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form();
$file = new UploadedFile(__DIR__ . '/../../fixtures/Import/pocket.csv', 'Bookmarks');
$data = [
'upload_import_file[file]' => $file,
];
$client->submit($form, $data);
$this->assertSame(302, $client->getResponse()->getStatusCode());
$crawler = $client->followRedirect();
$this->assertGreaterThan(1, $body = $crawler->filter('body')->extract(['_text']));
$this->assertStringContainsString('flashes.import.notice.summary', $body[0]);
$this->assertNotEmpty($client->getContainer()->get(Client::class)->lpop('wallabag.import.pocket_csv'));
$client->getContainer()->get(Config::class)->set('import_with_redis', 0);
}
public function testImportWallabagWithPocketCsvFile()
{
$this->logInAs('admin');
$client = $this->getTestClient();
$crawler = $client->request('GET', '/import/pocket_csv');
$form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form();
$file = new UploadedFile(__DIR__ . '/../../fixtures/Import/pocket.csv', 'Bookmarks');
$data = [
'upload_import_file[file]' => $file,
];
$client->submit($form, $data);
$this->assertSame(302, $client->getResponse()->getStatusCode());
$crawler = $client->followRedirect();
$this->assertGreaterThan(1, $body = $crawler->filter('body')->extract(['_text']));
$this->assertStringContainsString('flashes.import.notice.summary', $body[0]);
$entries = $client->getContainer()
->get(EntityManagerInterface::class)
->getRepository(Entry::class)
->findBy(['user' => $this->getLoggedInUserId()]);
$expectedEntries = [
'http://youmightnotneedjquery.com/,1600322788',
'https://jp-lambert.me/est-ce-que-jai-besoin-d-un-scrum-master-604f5a471c73',
'https://www.monde-diplomatique.fr/2020/09/HALIMI/62165',
'https://www.reddit.com/r/DataHoarder/comments/ioupbk/archivebox_question_how_do_i_import_links_from_a/',
'https://www.numerama.com/politique/646826-tu-vas-pleurer-les-premieres-fois-que-se-passe-t-il-au-sein-du-studio-dubisoft-derriere-trackmania.html#utm_medium=distibuted&utm_source=rss&utm_campaign=646826',
'https://www.nouvelobs.com/rue89/20200911.OBS33165/comment-konbini-s-est-fait-pieger-par-un-pere-masculiniste.html',
'https://reporterre.net/Des-abeilles-pour-resoudre-les-conflits-entre-les-humains-et-les-elephants',
];
$matchedEntries = array_map(function ($expectedUrl) use ($entries) {
foreach ($entries as $entry) {
if ($entry->getUrl() === $expectedUrl) {
return $entry;
}
}
return null;
}, $expectedEntries);
$this->assertCount(\count($expectedEntries), $matchedEntries, 'Should have 7 entries imported from pocket.csv');
}
public function testImportWallabagWithEmptyFile()
{
$this->logInAs('admin');
$client = $this->getTestClient();
$crawler = $client->request('GET', '/import/pocket_csv');
$form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form();
$file = new UploadedFile(__DIR__ . '/../../fixtures/Import/test.csv', 'test.csv');
$data = [
'upload_import_file[file]' => $file,
];
$client->submit($form, $data);
$this->assertSame(302, $client->getResponse()->getStatusCode());
$crawler = $client->followRedirect();
$this->assertGreaterThan(1, $body = $crawler->filter('body')->extract(['_text']));
$this->assertStringContainsString('flashes.import.notice.failed', $body[0]);
}
}

View File

@ -91,7 +91,7 @@ class PocketHtmlControllerTest extends WallabagTestCase
$client->getContainer()->get(Config::class)->set('import_with_redis', 0);
}
public function testImportWallabagWithPocketHtmlFile()
public function testImportPocketHtmlWithFile()
{
$this->logInAs('admin');
$client = $this->getTestClient();
@ -129,7 +129,7 @@ class PocketHtmlControllerTest extends WallabagTestCase
$this->assertCount(3, $content->getTags());
}
public function testImportWallabagWithEmptyFile()
public function testImportPocketHtmlWithEmptyFile()
{
$this->logInAs('admin');
$client = $this->getTestClient();
@ -152,4 +152,17 @@ class PocketHtmlControllerTest extends WallabagTestCase
$this->assertGreaterThan(1, $body = $crawler->filter('body')->extract(['_text']));
$this->assertStringContainsString('flashes.import.notice.failed', $body[0]);
}
public function testImportPocketHtmlDisabled()
{
$this->logInAs('admin');
$client = $this->getTestClient();
$client->getContainer()->get(Config::class)->set('pocket_html_enabled', 0);
$client->request('GET', '/import/pocket_html');
$this->assertSame(404, $client->getResponse()->getStatusCode());
$client->getContainer()->get(Config::class)->set('pocket_html_enabled', 1);
}
}

View File

@ -205,4 +205,17 @@ class ReadabilityControllerTest extends WallabagTestCase
$this->assertGreaterThan(1, $body = $crawler->filter('body')->extract(['_text']));
$this->assertStringContainsString('flashes.import.notice.failed', $body[0]);
}
public function testImportReadabilityDisabled()
{
$this->logInAs('admin');
$client = $this->getTestClient();
$client->getContainer()->get(Config::class)->set('readability_enabled', 0);
$client->request('GET', '/import/readability');
$this->assertSame(404, $client->getResponse()->getStatusCode());
$client->getContainer()->get(Config::class)->set('readability_enabled', 1);
}
}

View File

@ -91,7 +91,7 @@ class ShaarliControllerTest extends WallabagTestCase
$client->getContainer()->get(Config::class)->set('import_with_redis', 0);
}
public function testImportWallabagWithShaarliFile()
public function testImportShaarliWithFile()
{
$this->logInAs('admin');
$client = $this->getTestClient();
@ -129,7 +129,7 @@ class ShaarliControllerTest extends WallabagTestCase
$this->assertCount(2, $content->getTags());
}
public function testImportWallabagWithEmptyFile()
public function testImportShaarliWithEmptyFile()
{
$this->logInAs('admin');
$client = $this->getTestClient();
@ -152,4 +152,17 @@ class ShaarliControllerTest extends WallabagTestCase
$this->assertGreaterThan(1, $body = $crawler->filter('body')->extract(['_text']));
$this->assertStringContainsString('flashes.import.notice.failed', $body[0]);
}
public function testImportShaarliDisabled()
{
$this->logInAs('admin');
$client = $this->getTestClient();
$client->getContainer()->get(Config::class)->set('shaarli_enabled', 0);
$client->request('GET', '/import/shaarli');
$this->assertSame(404, $client->getResponse()->getStatusCode());
$client->getContainer()->get(Config::class)->set('shaarli_enabled', 1);
}
}

View File

@ -11,7 +11,7 @@ use Wallabag\Entity\Entry;
class WallabagV1ControllerTest extends WallabagTestCase
{
public function testImportWallabag()
public function testImportWallabagV1()
{
$this->logInAs('admin');
$client = $this->getTestClient();
@ -23,7 +23,7 @@ class WallabagV1ControllerTest extends WallabagTestCase
$this->assertSame(1, $crawler->filter('input[type=file]')->count());
}
public function testImportWallabagWithRabbitEnabled()
public function testImportWallabagV1WithRabbitEnabled()
{
$this->logInAs('admin');
$client = $this->getTestClient();
@ -39,7 +39,7 @@ class WallabagV1ControllerTest extends WallabagTestCase
$client->getContainer()->get(Config::class)->set('import_with_rabbitmq', 0);
}
public function testImportWallabagBadFile()
public function testImportWallabagV1BadFile()
{
$this->logInAs('admin');
$client = $this->getTestClient();
@ -56,7 +56,7 @@ class WallabagV1ControllerTest extends WallabagTestCase
$this->assertSame(200, $client->getResponse()->getStatusCode());
}
public function testImportWallabagWithRedisEnabled()
public function testImportWallabagV1WithRedisEnabled()
{
$this->checkRedis();
$this->logInAs('admin');
@ -92,7 +92,7 @@ class WallabagV1ControllerTest extends WallabagTestCase
$client->getContainer()->get(Config::class)->set('import_with_redis', 0);
}
public function testImportWallabagWithFile()
public function testImportWallabagV1WithFile()
{
$this->logInAs('admin');
$client = $this->getTestClient();
@ -136,7 +136,7 @@ class WallabagV1ControllerTest extends WallabagTestCase
$this->assertInstanceOf(\DateTime::class, $content->getCreatedAt());
}
public function testImportWallabagWithFileAndMarkAllAsRead()
public function testImportWallabagV1WithFileAndMarkAllAsRead()
{
$this->logInAs('admin');
$client = $this->getTestClient();
@ -183,7 +183,7 @@ class WallabagV1ControllerTest extends WallabagTestCase
$this->assertStringContainsString('flashes.import.notice.summary', $body[0]);
}
public function testImportWallabagWithEmptyFile()
public function testImportWallabagV1WithEmptyFile()
{
$this->logInAs('admin');
$client = $this->getTestClient();
@ -206,4 +206,17 @@ class WallabagV1ControllerTest extends WallabagTestCase
$this->assertGreaterThan(1, $body = $crawler->filter('body')->extract(['_text']));
$this->assertStringContainsString('flashes.import.notice.failed', $body[0]);
}
public function testImportWallabagV1Disabled()
{
$this->logInAs('admin');
$client = $this->getTestClient();
$client->getContainer()->get(Config::class)->set('wallabag_v1_enabled', 0);
$client->request('GET', '/import/wallabag_v1');
$this->assertSame(404, $client->getResponse()->getStatusCode());
$client->getContainer()->get(Config::class)->set('wallabag_v1_enabled', 1);
}
}

View File

@ -11,7 +11,7 @@ use Wallabag\Entity\Entry;
class WallabagV2ControllerTest extends WallabagTestCase
{
public function testImportWallabag()
public function testImportWallabagV2()
{
$this->logInAs('admin');
$client = $this->getTestClient();
@ -23,7 +23,7 @@ class WallabagV2ControllerTest extends WallabagTestCase
$this->assertSame(1, $crawler->filter('input[type=file]')->count());
}
public function testImportWallabagWithRabbitEnabled()
public function testImportWallabagV2WithRabbitEnabled()
{
$this->logInAs('admin');
$client = $this->getTestClient();
@ -39,7 +39,7 @@ class WallabagV2ControllerTest extends WallabagTestCase
$client->getContainer()->get(Config::class)->set('import_with_rabbitmq', 0);
}
public function testImportWallabagBadFile()
public function testImportWallabagV2BadFile()
{
$this->logInAs('admin');
$client = $this->getTestClient();
@ -56,7 +56,7 @@ class WallabagV2ControllerTest extends WallabagTestCase
$this->assertSame(200, $client->getResponse()->getStatusCode());
}
public function testImportWallabagWithRedisEnabled()
public function testImportWallabagV2WithRedisEnabled()
{
$this->checkRedis();
$this->logInAs('admin');
@ -92,7 +92,7 @@ class WallabagV2ControllerTest extends WallabagTestCase
$client->getContainer()->get(Config::class)->set('import_with_redis', 0);
}
public function testImportWallabagWithFile()
public function testImportWallabagV2WithFile()
{
$this->logInAs('admin');
$client = $this->getTestClient();
@ -158,7 +158,7 @@ class WallabagV2ControllerTest extends WallabagTestCase
$this->assertTrue($content->isStarred(), 'Entry is starred');
}
public function testImportWallabagWithEmptyFile()
public function testImportWallabagV2WithEmptyFile()
{
$this->logInAs('admin');
$client = $this->getTestClient();
@ -181,4 +181,17 @@ class WallabagV2ControllerTest extends WallabagTestCase
$this->assertGreaterThan(1, $body = $crawler->filter('body')->extract(['_text']));
$this->assertStringContainsString('flashes.import.notice.failed', $body[0]);
}
public function testImportWallabagV2Disabled()
{
$this->logInAs('admin');
$client = $this->getTestClient();
$client->getContainer()->get(Config::class)->set('wallabag_v2_enabled', 0);
$client->request('GET', '/import/wallabag_v2');
$this->assertSame(404, $client->getResponse()->getStatusCode());
$client->getContainer()->get(Config::class)->set('wallabag_v2_enabled', 1);
}
}

View File

@ -66,7 +66,6 @@ class SecurityControllerTest extends WallabagTestCase
->getRepository(User::class)
->findOneByUsername('admin');
$user->setGoogleAuthenticatorSecret('26LDIHYGHNELOQEM');
$user->setGoogleAuthenticator(true);
$em->persist($user);
$em->flush();
@ -79,7 +78,6 @@ class SecurityControllerTest extends WallabagTestCase
->getRepository(User::class)
->findOneByUsername('admin');
$user->setGoogleAuthenticatorSecret(null);
$user->setGoogleAuthenticator(false);
$em->persist($user);
$em->flush();
}

View File

@ -1,252 +0,0 @@
<?php
namespace Tests\Wallabag\Import;
use Doctrine\ORM\EntityManager;
use M6Web\Component\RedisMock\RedisMockFactory;
use Monolog\Handler\TestHandler;
use Monolog\Logger;
use PHPUnit\Framework\TestCase;
use Predis\Client;
use Simpleue\Queue\RedisQueue;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Wallabag\Entity\Entry;
use Wallabag\Entity\User;
use Wallabag\Helper\ContentProxy;
use Wallabag\Helper\TagsAssigner;
use Wallabag\Import\PocketCsvImport;
use Wallabag\Redis\Producer;
use Wallabag\Repository\EntryRepository;
class PocketCsvImportTest extends TestCase
{
protected $user;
protected $em;
protected $logHandler;
protected $contentProxy;
protected $tagsAssigner;
public function testInit()
{
$pocketCsvImport = $this->getPocketCsvImport();
$this->assertSame('Pocket CSV', $pocketCsvImport->getName());
$this->assertNotEmpty($pocketCsvImport->getUrl());
$this->assertSame('import.pocket_csv.description', $pocketCsvImport->getDescription());
}
public function testImport()
{
$pocketCsvImport = $this->getPocketCsvImport(false, 7);
$pocketCsvImport->setFilepath(__DIR__ . '/../fixtures/Import/pocket.csv');
$entryRepo = $this->getMockBuilder(EntryRepository::class)
->disableOriginalConstructor()
->getMock();
$entryRepo->expects($this->exactly(7))
->method('findByUrlAndUserId')
->willReturn(false);
$this->em
->expects($this->any())
->method('getRepository')
->willReturn($entryRepo);
$entry = $this->getMockBuilder(Entry::class)
->disableOriginalConstructor()
->getMock();
$this->contentProxy
->expects($this->exactly(7))
->method('updateEntry')
->willReturn($entry);
$res = $pocketCsvImport->import();
$this->assertTrue($res);
$this->assertSame(['skipped' => 0, 'imported' => 7, 'queued' => 0], $pocketCsvImport->getSummary());
}
public function testImportAndMarkAllAsRead()
{
$pocketCsvImport = $this->getPocketCsvImport(false, 1);
$pocketCsvImport->setFilepath(__DIR__ . '/../fixtures/Import/pocket.csv');
$entryRepo = $this->getMockBuilder(EntryRepository::class)
->disableOriginalConstructor()
->getMock();
$entryRepo->expects($this->exactly(7))
->method('findByUrlAndUserId')
->will($this->onConsecutiveCalls(false, true));
$this->em
->expects($this->any())
->method('getRepository')
->willReturn($entryRepo);
$this->contentProxy
->expects($this->exactly(1))
->method('updateEntry')
->willReturn(new Entry($this->user));
// check that every entry persisted are archived
$this->em
->expects($this->any())
->method('persist')
->with($this->callback(fn ($persistedEntry) => (bool) $persistedEntry->isArchived()));
$res = $pocketCsvImport
->setMarkAsRead(true)
->import();
$this->assertTrue($res);
$this->assertSame(['skipped' => 6, 'imported' => 1, 'queued' => 0], $pocketCsvImport->getSummary());
}
public function testImportWithRabbit()
{
$pocketCsvImport = $this->getPocketCsvImport();
$pocketCsvImport->setFilepath(__DIR__ . '/../fixtures/Import/pocket.csv');
$entryRepo = $this->getMockBuilder(EntryRepository::class)
->disableOriginalConstructor()
->getMock();
$entryRepo->expects($this->never())
->method('findByUrlAndUserId');
$this->em
->expects($this->never())
->method('getRepository');
$entry = $this->getMockBuilder(Entry::class)
->disableOriginalConstructor()
->getMock();
$this->contentProxy
->expects($this->never())
->method('updateEntry');
$producer = $this->getMockBuilder(\OldSound\RabbitMqBundle\RabbitMq\Producer::class)
->disableOriginalConstructor()
->getMock();
$producer
->expects($this->exactly(7))
->method('publish');
$pocketCsvImport->setProducer($producer);
$res = $pocketCsvImport->setMarkAsRead(true)->import();
$this->assertTrue($res);
$this->assertSame(['skipped' => 0, 'imported' => 0, 'queued' => 7], $pocketCsvImport->getSummary());
}
public function testImportWithRedis()
{
$pocketCsvImport = $this->getPocketCsvImport();
$pocketCsvImport->setFilepath(__DIR__ . '/../fixtures/Import/pocket.csv');
$entryRepo = $this->getMockBuilder(EntryRepository::class)
->disableOriginalConstructor()
->getMock();
$entryRepo->expects($this->never())
->method('findByUrlAndUserId');
$this->em
->expects($this->never())
->method('getRepository');
$entry = $this->getMockBuilder(Entry::class)
->disableOriginalConstructor()
->getMock();
$this->contentProxy
->expects($this->never())
->method('updateEntry');
$factory = new RedisMockFactory();
$redisMock = $factory->getAdapter(Client::class, true);
$queue = new RedisQueue($redisMock, 'pocket_csv');
$producer = new Producer($queue);
$pocketCsvImport->setProducer($producer);
$res = $pocketCsvImport->setMarkAsRead(true)->import();
$this->assertTrue($res);
$this->assertSame(['skipped' => 0, 'imported' => 0, 'queued' => 7], $pocketCsvImport->getSummary());
$this->assertNotEmpty($redisMock->lpop('pocket_csv'));
}
public function testImportBadFile()
{
$pocketCsvImport = $this->getPocketCsvImport();
$pocketCsvImport->setFilepath(__DIR__ . '/../fixtures/Import/wallabag-v1.jsonx');
$res = $pocketCsvImport->import();
$this->assertFalse($res);
$records = $this->logHandler->getRecords();
$this->assertStringContainsString('Pocket CSV Import: unable to read file', $records[0]['message']);
$this->assertSame('ERROR', $records[0]['level_name']);
}
public function testImportUserNotDefined()
{
$pocketCsvImport = $this->getPocketCsvImport(true);
$pocketCsvImport->setFilepath(__DIR__ . '/../fixtures/Import/pocket.csv');
$res = $pocketCsvImport->import();
$this->assertFalse($res);
$records = $this->logHandler->getRecords();
$this->assertStringContainsString('Pocket CSV Import: user is not defined', $records[0]['message']);
$this->assertSame('ERROR', $records[0]['level_name']);
}
private function getPocketCsvImport($unsetUser = false, $dispatched = 0)
{
$this->user = new User();
$this->em = $this->getMockBuilder(EntityManager::class)
->disableOriginalConstructor()
->getMock();
$this->contentProxy = $this->getMockBuilder(ContentProxy::class)
->disableOriginalConstructor()
->getMock();
$this->tagsAssigner = $this->getMockBuilder(TagsAssigner::class)
->disableOriginalConstructor()
->getMock();
$dispatcher = $this->getMockBuilder(EventDispatcher::class)
->disableOriginalConstructor()
->getMock();
$dispatcher
->expects($this->exactly($dispatched))
->method('dispatch');
$this->logHandler = new TestHandler();
$logger = new Logger('test', [$this->logHandler]);
$wallabag = new PocketCsvImport($this->em, $this->contentProxy, $this->tagsAssigner, $dispatcher, $logger);
if (false === $unsetUser) {
$wallabag->setUser($this->user);
}
return $wallabag;
}
}

View File

@ -1,10 +0,0 @@
title,url,time_added,tags,status
You Might Not Need jQuery,http://youmightnotneedjquery.com/,1600322788,,unread
Est-ce que jai besoin dun Scrum Master ? | by Jean-Pierre Lambert | Jean-,https://jp-lambert.me/est-ce-que-jai-besoin-d-un-scrum-master-604f5a471c73,1600172739,,unread
"Avec les accusés dEl Halia, par Gisèle Halimi (Le Monde diplomatique, sept",https://www.monde-diplomatique.fr/2020/09/HALIMI/62165,1599806347,,unread
ArchiveBox question: How do I import links from a RSS feed?,https://www.reddit.com/r/DataHoarder/comments/ioupbk/archivebox_question_how_do_i_import_links_from_a/,1600961496,,archive
« Tu vas pleurer les premières fois » : que se passe-t-il au sein du studio,https://www.numerama.com/politique/646826-tu-vas-pleurer-les-premieres-fois-que-se-passe-t-il-au-sein-du-studio-dubisoft-derriere-trackmania.html#utm_medium=distibuted&utm_source=rss&utm_campaign=646826,1599809025,,unread
Comment Konbini sest fait piéger par un « père masculiniste »,https://www.nouvelobs.com/rue89/20200911.OBS33165/comment-konbini-s-est-fait-pieger-par-un-pere-masculiniste.html,1599819251,,archive
"Des abeilles pour résoudre les « conflits » entre les humains
et les élépha",https://reporterre.net/Des-abeilles-pour-resoudre-les-conflits-entre-les-humains-et-les-elephants,1599890673,,unread
1 title url time_added tags status
2 You Might Not Need jQuery http://youmightnotneedjquery.com/ 1600322788 unread
3 Est-ce que j’ai besoin d’un Scrum Master ? | by Jean-Pierre Lambert | Jean- https://jp-lambert.me/est-ce-que-jai-besoin-d-un-scrum-master-604f5a471c73 1600172739 unread
4 Avec les accusés d’El Halia, par Gisèle Halimi (Le Monde diplomatique, sept https://www.monde-diplomatique.fr/2020/09/HALIMI/62165 1599806347 unread
5 ArchiveBox question: How do I import links from a RSS feed? https://www.reddit.com/r/DataHoarder/comments/ioupbk/archivebox_question_how_do_i_import_links_from_a/ 1600961496 archive
6 « Tu vas pleurer les premières fois » : que se passe-t-il au sein du studio https://www.numerama.com/politique/646826-tu-vas-pleurer-les-premieres-fois-que-se-passe-t-il-au-sein-du-studio-dubisoft-derriere-trackmania.html#utm_medium=distibuted&utm_source=rss&utm_campaign=646826 1599809025 unread
7 Comment Konbini s’est fait piéger par un « père masculiniste » https://www.nouvelobs.com/rue89/20200911.OBS33165/comment-konbini-s-est-fait-pieger-par-un-pere-masculiniste.html 1599819251 archive
8 Des abeilles pour résoudre les « conflits » entre les humains et les élépha https://reporterre.net/Des-abeilles-pour-resoudre-les-conflits-entre-les-humains-et-les-elephants 1599890673 unread

View File

@ -9,7 +9,7 @@
<h1>Unread</h1>
<ul>
<li><a href="https://www.20minutes.fr/sport/4002755-20220928-tarn-lapins-ravagent-terrain-match-rugby-doit-etre-annule" time_added="1688628695" tags="ifttt,new_entry_simple">Tarn : Des lapins ravagent le terrain, le match de rugby doit être annulé</a></li>
<li><a href="https://www.20minutes.fr/paris/4100740-20240715-jo-paris-2024-courir-capitale-maintenant-quais-fermes" time_added="1688627412" tags="ifttt,new_entry_simple">JO Paris 2024 : Où courir dans la capitale maintenant que les quais sont fermés ?</a></li>
<li><a href="https://www.20minutes.fr/paris/4100740-20240715-jo-paris-2024-courir-capitale-maintenant-quais-fermes" time_added="1688627412" tags="ifttt,new_entry_simple">JO Paris 2024 : Où courir dans la capitale maintenant que les quais sont fermés ?</a></li>
</ul>

View File

@ -8,6 +8,6 @@
<DL><p>
<DT><A HREF="https://www.20minutes.fr/sport/4002755-20220928-tarn-lapins-ravagent-terrain-match-rugby-doit-etre-annule" ADD_DATE="1686813518" LAST_MODIFIED="1686813519" PRIVATE="0" TAGS="firefoxos">The Legacy of Firefox OS. In the two years or so since Mozilla… | by Ben Francis | Medium</A>
<DD>In the two years or so since Mozilla announced the end of Firefox OS as a Mozilla-run project, the B2G source code has found its way into a surprising number of commercial products.
<DT><A HREF="https://www.20minutes.fr/paris/4100740-20240715-jo-paris-2024-courir-capitale-maintenant-quais-fermes" ADD_DATE="1683376565" LAST_MODIFIED="1686813519" PRIVATE="0" TAGS="firefoxos">JO Paris 2024 : Où courir dans la capitale maintenant que les quais sont fermés ?</A>
<DT><A HREF="https://www.20minutes.fr/paris/4100740-20240715-jo-paris-2024-courir-capitale-maintenant-quais-fermes" ADD_DATE="1683376565" LAST_MODIFIED="1683376571" PRIVATE="0" TAGS="eleventy,this,javascript,filter,data">Template Filters — Eleventy</A>
</DL><p>
<script data-cfasync="false" src="/cdn-cgi/scripts/5c5dd728/cloudflare-static/email-decode.min.js"></script>

View File

View File

@ -1 +0,0 @@
{}

View File

@ -5,7 +5,7 @@ restricted_access: Schakel authenticatie voor betaalde websites in
download_images_enabled: Download afbeelding lokaal
matomo_enabled: Schakel Matomo in
matomo_site_id: ID van uw Matomo website
matomo_host: Adres van jouw Matomo website (zonder http:// of https://)
matomo_host: Adres van uw Matomo website (zonder http:// of https://)
modify_settings: bevestig
misc: overig
import: importeer
@ -32,5 +32,4 @@ export_epub: Schakel ePub-export in
download_pictures: Download foto's naar jouw server
settings_changed: Instellingen bijgewerkt
diaspora_url: diaspora* URL, als de dienst is aangezet
share_public: Sta openbare URL's toe voor artikelen
share_linkding: Sta delen met Linkding toe
share_public: Sta openbare URL's toe voor items

View File

@ -1,4 +1,4 @@
settings_changed: Ustawienia zostały zaktualizowane
settings_changed: Ustawienia zostały zaktualizowana
download_pictures: Pobierz obrazy na swój serwer
diaspora_url: Adres URL Diaspora, jeżeli ta usługa jest włączona
export_epub: Włącz eksport do ePub

View File

@ -558,15 +558,11 @@ import:
pocket_html:
how_to: Zvolte soubor zálohy záložek a kliknutím na níže uvedené tlačítko jej naimportujte. Pamatujte na to, že tento proces může trvat dlouho, protože je třeba načíst všechny články.
page_title: Import > Pocket HTML
description: Tento importér naimportuje všechny vaše záložky z Pocketu (prostřednictvím HTML exportu). Stačí přejít na https://getpocket.com/export a exportovat soubor HTML, který bude stažen (například „ril_export.html“).
description: Tento importér naimportuje všechny vaše záložky z Pocket. Stačí přejít na https://getpocket.com/export) a exportovat soubor HTML, který bude stažen (například „ril_export.html“).
omnivore:
how_to: Rozbalte prosím svůj export z Omnivoru, následně nahrajte jeden po druhém všechny JSON soubory s názevem "metadata_x_to_y.json".
page_title: Import > Omnivore
description: Tento importér naimportuje všechny vaše články z Omnivore.
pocket_csv:
page_title: Import > Pocket CSV
description: Tento importér naimportuje všechny vaše záložky z Pocketu (prostřednictvím CSV exportu). Stačí přejít na https://getpocket.com/export a exportovat soubor. Stáhne se ZIP soubor (např. „pocket.zip“). Po rozbalení získáte CSV soubor, nazvaný „part_000000.csv“.
how_to: Zvolte soubor zálohy záložek a kliknutím na níže uvedené tlačítko jej naimportujte. Pamatujte na to, že tento proces může trvat dlouho, protože je třeba načíst všechny články.
flashes:
config:
notice:
@ -589,7 +585,6 @@ flashes:
user_updated: Informace byla aktualizována
config_saved: Konfigurace byla uložena.
tagging_rules_reset: Pravidla štítkování byla obnovena
otp_code_invalid: Neplatný dvoufaktorový autentizační kód
ignore_origin_instance_rule:
notice:
deleted: Globální pravidlo ignorování bylo odstraněno

View File

@ -237,16 +237,6 @@ entry:
untagged: Untagged entries
all: All entries
same_domain: Same domain
sort:
status_label: Sort by
order_label: Order
by:
creation_date: Creation date
title: Title
url: URL
reading_time: Reading time
ascending: Ascending
descending: Descending
list:
number_on_the_page: '{0} There are no entries.|{1} There is one entry.|]1,Inf[ There are %count% entries.'
reading_time: estimated reading time
@ -563,10 +553,6 @@ import:
page_title: Import > Pocket HTML
description: This importer will import all your Pocket bookmarks (via HTML export). Just go to https://getpocket.com/export, then export the HTML file. An HTML file will be downloaded (like "ril_export.html").
how_to: Please choose the bookmark backup file and click on the button below to import it. Note that the process may take a long time since all articles have to be fetched.
pocket_csv:
page_title: Import > Pocket CSV
description: This importer will import all your Pocket bookmarks (via CSV export). Just go to https://getpocket.com/export, then export the file. A ZIP file will be downloaded (like "pocket.zip"). Extract it, you will obtain a CSV file, called "part_000000.csv".
how_to: Please choose the bookmark backup file and click on the button below to import it. Note that the process may take a long time since all articles have to be fetched.
developer:
page_title: API clients management
welcome_message: Welcome to the wallabag API

View File

@ -550,10 +550,6 @@ import:
page_title: Importer > Pocket HTML
description: Cet importateur importera toutes vos signets Pocket (via exportation HTML). Il suffit d'aller à https://getpocket.com/export, puis d'exporter le fichier HTML. Un fichier HTML sera téléchargé (comme « ril_export.html »).
how_to: Veuillez choisir le fichier de sauvegarde de signets et cliquez sur le bouton ci-dessous pour l'importer. Pensez au fait que le processus peut prendre longtemps puisque tous les articles doivent être récupérés.
pocket_csv:
page_title: Importer > Pocket CSV
description: Cet importateur importera toutes vos signets Pocket (via exportation CSV). Il suffit d'aller à https://getpocket.com/export, puis d'exporter le fichier. Un fichier ZIP sera téléchargé (comme « pocket.zip »). Décompressez le et vous obtiendrez un fichier CSV appelé "part_000000.csv".
how_to: Veuillez choisir le fichier de sauvegarde de signets et cliquez sur le bouton ci-dessous pour l'importer. Pensez au fait que le processus peut prendre longtemps puisque tous les articles doivent être récupérés.
omnivore:
description: Cet outil va importer tous vos articles depuis Omnivore.
page_title: Importer > Omnivore

View File

@ -485,10 +485,6 @@ import:
page_title: Importar > Omnivore
how_to: Descomprime a exportación de Omnivore, e despois sube un a un cada ficheiro JSON con nome «metadata_x_to_y.json".
description: Este importador vai traer todos os teus artigos de Omnivore.
pocket_csv:
how_to: Selecciona o ficheiro de copia de apoio dos marcadores e preme no botón inferior para importalo. Ten en conta que o proceso podería demorarse xa que deben procesarse todos os artigos.
description: Con este asistente vas importar os teus marcadores desde Pocket (usando a exportación CSV). Só tes que ir a https://getpocket.com/export e exportar un ficheiro. Descargarás un ficheiro ZIP (tipo «pocket.zip»). Extrae o ficheiro CSV que contén, ten nome «part_000000.csv».
page_title: Importar > CSV desde Pocket
export:
unknown: Descoñecido
footer_template: <div style="text-align:center;"><p>Creado por wallabag con %method%</p><p>Abre <a href="https://github.com/wallabag/wallabag/issues">unha incidencia</a> se tes problemas para visualizar este E-Book no teu dispositivo.</p></div>

View File

@ -1 +0,0 @@
{}

View File

@ -115,26 +115,6 @@ import:
action:
import_contents: 콘텐츠 가져오기
page_title: 가져오기
delicious:
how_to: Delicious 내보내기를 선택하고 아래 버튼을 클릭하여 업로드하고 가져오십시오.
page_title: 가져오기 > del.icio.us
description: '이 가져오기 도구는 모든 Delicious 북마크를 가져옵니다. 2021년부터 내보내기 페이지 (https://del.icio.us/export)를 사용하여 데이터를 다시 내보낼 수 있습니다. "JSON" 형식을 선택하고 다운로드하십시오 (예: "delicious_export.2021.02.06_21.10.json").'
shaarli:
page_title: 가져오기 > Shaarli
description: 이 가져오기 도구는 모든 Shaarli 북마크를 가져옵니다. 도구 섹션으로 이동한 다음 "데이터베이스 내보내기"에서 북마크를 선택하고 내보내십시오. HTML 파일을 얻게 됩니다.
how_to: 북마크 백업 파일을 선택하고 아래 버튼을 클릭하여 가져오십시오. 모든 문서를 가져와야하므로 처리 시간이 오래 걸릴 수 있습니다.
omnivore:
page_title: 가져오기 > Omnivore
description: 이 가져오기 도구는 모든 Omnivore 문서를 가져옵니다.
how_to: Omnivore 내보내기 압축을 풀고 "metadata_x_to_y.json" 이라는 각 JSON 파일을 하나씩 업로드하십시오.
pocket_html:
description: '이 가져오기 도구는 모든 Pocket 북마크 (HTML 내보내기 통해)를 가져옵니다. https://getpocket.com/export 로 이동한 다음 HTML 파일을 내보내십시오. HTML 파일이 다운로드됩니다 (예: "ril_export.html").'
page_title: 가져오기 > Pocket HTML
how_to: 북마크 백업 파일을 선택하고 아래 버튼을 클릭하여 가져오십시오. 모든 문서를 가져와야하므로 처리 시간이 오래 걸릴 수 있습니다.
pocket_csv:
description: '이 가져오기 도구는 모든 Pocket 북마크 (CSV 내보내기 통해)를 가져옵니다. https://getpocket.com/export 로 이동한 다음 파일을 내보내십시오. ZIP 파일이 다운로드됩니다 (예: "pocket.zip"). 압축을 풀면 "part_000000.csv" 라는 CSV 파일을 얻게 됩니다.'
how_to: 북마크 백업 파일을 선택하고 아래 버튼을 클릭하여 가져오십시오. 모든 문서를 가져와야하므로 처리 시간이 오래 걸릴 수 있습니다.
page_title: 가져오기 > Pocket CSV
about:
third_party:
description: '다음은 wallabag에 사용되는 타사 라이브러리 목록입니다 (저작권 포함):'
@ -219,8 +199,6 @@ entry:
starred_label: 즐겨찾기
status_label: 상태
title: 필터
annotated_label: 주석 있음
parsed_label: 올바르게 가져오지 못함
edit:
origin_url_label: 원본 URL (원본 문서의 위치)
page_title: 문서 수정
@ -241,13 +219,9 @@ entry:
filtered_tags: '태그로 필터링:'
filtered: 필터링한 기사
unread: 읽지않은 기사
with_annotations: 주석이 있는 문서
same_domain: 동일 도메인
confirm:
delete_tag: 문서에서 해당 태그를 제거 하시겠습니까?
delete: 해당 문서를 제거 하시겠습니까?
delete_entries: 이 문서를 제거 하시겠습니까?
reload: 해당 문서를 다시 로드 하시겠습니까?
public:
shared_by_wallabag: 이 문서는 %username% 님이 <a href='%wallabag_instance%'>wallabag</a>와 공유했습니다
metadata:
@ -264,18 +238,13 @@ entry:
toogle_as_read: 읽음으로 전환
toogle_as_star: 즐겨찾기 전환
original_article: 원본
reading_time_less_one_minute_short: '< 1 분'
reading_time_less_one_minute_short: '&lt; 1 분'
reading_time_minutes_short: '%readingTime% 분'
number_of_tags: '{1} 및 1 개의 다른 태그|]1,Inf[및 %count% 다른 태그'
reading_time_less_one_minute: '예상 읽기 시간: < 1 분'
reading_time_less_one_minute: '예상 읽기 시간: &lt; 1 분'
reading_time_minutes: '예상 읽기 시간: %readingTime% 분'
reading_time: 예상 읽기 시간
number_on_the_page: '{0} 기사가 없습니다.|{1} 기사가 하나 있습니다.|]1,Inf[ %count% 기사가 있습니다.'
assign_search_tag: 이 검색을 각 결과에 태그로 할당
show_same_domain: 동일 도메인을 가진 문서 보기
toggle_mass_action: 대량 작업 전환
mass_action_tags_input_placeholder: 태그1, 태그2, 태그3
add_tags: 태그 추가
number_on_the_page: '{0} 기사가 없습니다.|{1} 기사가 하나 있습니다.|]1,Inf[ %count % 기사가 있습니다.'
default_title: 기사의 제목
howto:
bookmarklet:
@ -314,7 +283,7 @@ howto:
via_google_play: 구글 플레이를 통해
via_f_droid: F-Droid를 통해
windows: 마이크로소프트 스토어에서
ios: 스토어에서
ios: 아이튠즈 스토어에서
browser_addons:
opera: 오페라 애드온
chrome: 크롬 애드온
@ -362,7 +331,6 @@ flashes:
tagging_rules_deleted: 태그 지정 규칙이 삭제되었습니다
tagging_rules_updated: 태그 지정 규칙이 업데이트되었습니다
password_updated: 비밀번호가 업데이트 되었습니다
otp_code_invalid: 2단계 인증 코드가 유효하지 않습니다
ignore_origin_instance_rule:
notice:
deleted: 전역 원본 무시 규칙이 삭제되었습니다
@ -395,7 +363,6 @@ flashes:
notice:
tag_renamed: 태그 이름이 변경되었습니다
tag_added: 태그가 추가되었습니다
too_much_tags: 성능 문제 방지를 위해 한 번에 %tags%개 이상의 태그나 %characters%자 이상의 태그를 추가할 수 없습니다.
config:
form_ignore_origin_rules:
faq:
@ -429,7 +396,7 @@ config:
title: 문서 제목
label: 변수
tagging_rules_definition_description: wallabag 에서 자동으로 새 문서에 태그를 지정하는 데 사용하는 규칙입니다. <br /> 태그 지정 규칙이 새 문서가 추가 될 때마다 태그를 구성하는 데 사용되므로, 수동으로 분류하는 수고를 덜 수 있습니다.
how_to_use_them_description: '읽기 시간이 3 분 미만인 경우 «<i> 짧은 읽기 </i>» 와 같은 새 기사에 태그를 지정한다고 가정합니다. <br />이 경우 <i> 규칙</i> 을 입력해야합니다. <i>태그</i> 필드에 « readingTime <= 3 » 을 입력하고 « <i>짧은 읽기</i>» 를 입력하십시오. <br /> 여러 태그를 쉼표로구분하여 한 번에 추가 할 수 있습니다: « <i> 짧은 읽기, 반드시 읽기</i> » <br /> 사전 정의 된 연산자를 사용하여 복잡한 규칙을 작성할 수 있습니다: 만약 « <i>readingTime >= 5 AND domainName = "www.php.net"</i> » 다음으로 태그 «<i> 긴 읽기, php</i>»'
how_to_use_them_description: '읽기 시간이 3 분 미만인 경우 «<i> 짧은 읽기 </i>» 와 같은 새 기사에 태그를 지정한다고 가정합니다. <br />이 경우 <i> 규칙</i> 을 입력해야합니다. <i>태그</i> 필드에 « readingTime &lt;= 3 » 을 입력하고 « <i>짧은 읽기</i>» 를 입력하십시오. <br /> 여러 태그를 쉼표로구분하여 한 번에 추가 할 수 있습니다: « <i> 짧은 읽기, 반드시 읽기</i> » <br /> 사전 정의 된 연산자를 사용하여 복잡한 규칙을 작성할 수 있습니다: 만약 « <i>readingTime &gt;= 5 AND domainName = "www.php.net"</i> » 다음으로 태그 «<i> 긴 읽기, php</i>»'
operator_description:
and: 하나의 규칙 그리고 다른 규칙
or: 하나의 규칙 또는 다른 규칙
@ -471,7 +438,6 @@ config:
annotations: 모든 주석 제거
confirm: 정말 하시겠습니까? (되돌릴 수 없습니다)
tags: 모든 태그 제거
tagging_rules: 모든 태그 지정 규칙 제거
form_feed:
feed_link:
archive: 보관
@ -527,16 +493,6 @@ config:
help_message: '온라인 도구를 사용하여 읽기 속도를 측정 할 수 있습니다:'
label: 읽기 속도
language_label: 언어
help_font: 사용하고 싶은 글꼴 모음을 선택할 수 있습니다.
help_fontsize: 사용하고 싶은 글꼴 크기를 선택할 수 있습니다.
help_lineheight: 사용하고 싶은 줄 높이를 선택할 수 있습니다.
lineheight_label: 줄 높이
maxwidth_label: 최대 너비
help_maxwidth: 사용하고 싶은 최대 너비를 선택할 수 있습니다.
font_label: 글꼴 모음
fontsize_label: 글꼴 크기
help_display_thumbnails: 문서 썸네일을 표시할지 여부를 결정할 수 있습니다. 느린 연결에 유용합니다.
display_thumbnails_label: 문서 썸네일 표시 (느린 연결에 유용).
otp:
app:
qrcode_label: QR 코드
@ -557,7 +513,6 @@ config:
user_info: 사용자 정보
feed: 피드
settings: 설정
article_display: 문서 표시
form:
save: 저장
page_title: 설정
@ -571,7 +526,7 @@ menu:
random_entry: 해당 목록에서 임의의 문서로 이동
add_new_entry: 새 문서 추가
filter_entries: 기사 필터
account: 계정
account: 나의 계정
export: 내보내기
search: 검색
left:
@ -586,7 +541,7 @@ menu:
theme_toggle_auto: 자동 테마
theme_toggle_dark: 어두운 테마
theme_toggle_light: 밝은 테마
quickstart: 빠른 시작
quickstart: 빠른시작
search: 검색
users_management: 사용자 관리
save_link: 링크 저장
@ -597,7 +552,6 @@ menu:
tags: 태그
config: 설정
starred: 즐겨찾기
with_annotations: 주석 있음
search_form:
input_label: 여기에 검색어 입력
error:
@ -682,7 +636,7 @@ quickstart:
configure:
tagging_rules: 문서를 자동으로 태그하는 규칙 작성
feed: 피드 활성화
language: 언어 및 인터페이스 변경
language: 언어 및 디자인 변경
description: 자신에게 맞는 앱을 얻으려면, wallabag의 구성을 살펴보십시오.
title: 응용 프로그램 구성
more: 더보기…
@ -739,5 +693,3 @@ tag:
see_untagged_entries: 태그가 없는 문서보기
number_on_the_page: '{0} 태그가 없습니다.|{1} 태그가 1 개 있습니다.|]1,Inf[태그가 %count% 개 있습니다.'
page_title: 태그
confirm:
delete: '%name% 태그 삭제'

View File

@ -9,32 +9,22 @@ config:
300_word: Ik lees ~300 woorden per minuut
200_word: Ik lees ~200 woorden per minuut
100_word: Ik lees ~100 woorden per minuut
help_message: 'Je kunt online programma''s gebruiken om je leessnelheid te bepalen:'
help_message: 'U can online tooling gebruiken om uw leessnelheid te bepalen:'
label: Leessnelheid
language_label: Taal
items_per_page_label: Artikelen per pagina
help_pocket_consumer_key: Verplicht voor het importeren uit Pocket. Je kan dit aanmaken in je Pocket account.
items_per_page_label: Items per pagina
help_pocket_consumer_key: Verplicht voor het importeren uit Pocket. U kan dit aanmaken in uw Pocket account.
help_language: U kan de taal van wallabag aanpassen.
help_reading_speed: wallabag berekend een leestijd voor ieder artikel aan de hand van hoe snel je leest. Hier kan je aangeven hoe snel je leest.
help_reading_speed: wallabag berekend een leestijd voor ieder artikel. U kan hier aangeven of u een snelle of langzame lezer bent waardoor wallabag een accurate tijd kan berekenen per artikel.
help_items_per_page: U kan de hoeveelheid getoonde artikelen per pagina aanpassen.
android_instruction: Tik hier om je Android-app vooraf in te vullen
android_configuration: Configureer je Android applicatie
android_instruction: Tik hier om uw Android-appvooraf in te vullen
android_configuration: Configureer uw Android applicatie
pocket_consumer_key_label: Consumer key voor Pocket om inhoud te importeren
help_display_thumbnails: Jij bepaalt of je de artikel mini-afbeelding wilt zien. Uitzetten is handig bij een langzame verbinding.
display_thumbnails_label: Toon artikel mini-afbeelding (handig bij langzame verbindingen).
help_font: Kies de lettertypefamilie die je wil gebruiken.
help_lineheight: Kies de regelhoogte die je wil gebruiken.
help_maxwidth: Kies de maximale breedte die je wil gebruiken.
font_label: Lettertypefamilie
help_fontsize: Kies de lettergrootte die je wil gebruiken.
fontsize_label: Lettergrootte
lineheight_label: Regelhoogte
maxwidth_label: Maximale breedte
form:
save: Opslaan
tab_menu:
new_user: Voeg gebruiker toe
rules: Labelregels
rules: Label regels
password: Wachtwoord
user_info: Gebruikers informatie
rss: RSS
@ -42,33 +32,32 @@ config:
ignore_origin: Negeer oorsprong regels
feed: Feeds
reset: Reset gebied
article_display: Artikel weergave
page_title: Configuratie
form_user:
delete:
title: Verwijder mijn account (a.k.a gevaarlijke zone)
button: Verwijder mijn account
confirm: Weet je het zeker? (DIT KAN NIET ONGEDAAN GEMAAKT WORDEN)
description: Als je je account verwijdert, worden AL je artikelen, AL je labels, AL je annotaties en je account PERMANENT verwijderd (het kan niet ONGEDAAN gemaakt worden). Je wordt vervolgens uitgelogd.
confirm: Weet u het zeker? (DIT KAN NIET ONGEDAAN GEMAAKT WORDEN)
description: Als je je account verwijdert, worden AL je artikelen, AL je tags, AL je annotaties en je account PERMANENT verwijderd (het kan niet ONGEDAAN gemaakt worden). U wordt vervolgens uitgelogd.
help_twoFactorAuthentication: Wanneer u 2FA inschakelt, krijgt u bij elke inlogactie bij wallabag een code per mail.
twoFactorAuthentication_label: Twee factor authenticatie
email_label: E-mailadres
name_label: Naam
two_factor_description: Inschakelen van tweestapsverificatie betekend dat je een e-mail krijgt met een code, elke keer als je verbinding maakt met een nieuw, niet vertrouwd apparaat.
two_factor_description: Inschakken van 2-factor-authenticatie betekend dat u een email krijgt met een code elke keer als verbinding maakt met een nieuw niet vertrouwd apparaat.
two_factor:
action_app: Gebruik OTP app
action_email: Gebruik e-mail
action_email: Gebruik email
state_disabled: Uitgeschakeld
state_enabled: Ingeschakeld
table_action: Actie
table_state: Status
table_method: Methode
googleTwoFactor_label: Gebruik tweestapsverificatie met eenmalige codes van een OTP app (zoals Google Authenticator, Authy of FreeOTP)
emailTwoFactor_label: Gebruik tweestapsverificatie met eenmalige codes die je per e-mail ontvangt
googleTwoFactor_label: Gebruik maken van OTP app (open de app, zoals Google Authenticator, Authy of FreeOTP, om een eenmalige code te krijgen)
emailTwoFactor_label: Gebruik maken van email (ontvang een code per mail)
login_label: Login (kan niet veranderd worden)
form_rules:
faq:
tagging_rules_definition_description: Dit zijn regels die door Wallabag worden gebruikt om automatisch nieuwe artikelen te labelen. <br /> Elke keer dat een nieuw artikel wordt toegevoegd, worden de labelregels gebruikt om labels toe te voegen. Hierdoor bespaar je de moeite van handmatig classificeren.
tagging_rules_definition_description: Dit zijn regels die door Wallabag worden gebruikt om automatisch nieuwe items te labelen. <br /> Elke keer dat een nieuw item wordt toegevoegd, worden alle labelregels gebruikt om de labels toe te voegen die je hebt geconfigureerd, waardoor je de moeite van het handmatig classificeren van je items bespaart.
operator_description:
matches: 'Valideert dat een <i>onderwerp</i> gelijk is aan <i>zoek</i> (hoofdletter-ongevoelig.<br />Voorbeeld: <code>titel gelijk aan "voetbal"</code>'
notmatches: 'Valideert dat een <i>onderwerp</i> niet gelijk is aan <i>zoek</i> (hoofdletter-ongevoelig.<br />Voorbeeld: <code>titel niet gelijk aan "voetbal"</code>'
@ -82,23 +71,23 @@ config:
less_than: Minder dan…
label: Operator
variable_description:
domainName: De domeinnaam van het artikel
readingTime: De verwachte leestijd van het artikel, in minuten
mimetype: Media type van het artikel
language: Taal van het artikel
content: Inhoud van het artikel
isStarred: Of het artikel een ster heeft of niet
isArchived: Of het artikel gearchiveerd is of niet
url: URL van het artikel
title: Titel van het artikel
domainName: De domeinnaam van het item
readingTime: De verwachte leestijd van het item, in minuten
mimetype: Media type van het item
language: Taal van het item
content: Inhoud van het item
isStarred: Of het item gemarkeerd is of niet
isArchived: Of het item gearchiveerd is of niet
url: URL van het item
title: Titel van het item
label: Variabel
meaning: Betekenis
variables_available_description: 'De volgende variabelen en operatoren kunnen gebruikt worden om labelregels te maken:'
variables_available_description: 'De volgende variabelen en operatoren kunnen gebruikt worden om label regels te maken:'
variables_available_title: Welke variabelen en operatoren kan ik gebruiken om regels te schrijven?
how_to_use_them_title: Hoe gebruik is ze?
tagging_rules_definition_title: Wat zijn “labelregels?
tagging_rules_definition_title: Wat betekend "label regels"?
title: FAQ
how_to_use_them_description: 'Als voorbeeld nemen we aan dat je artikelen wil labelen als « <i>korte lezing</i> » wanneer de leestijd minder dan 3 minuten is.<br />In dat geval zet je « readingTime &lt;= 3 » in het <i>Regelveld</i> en « <i>korte lezing</i> » in het <i>Labels</i> veld.<br />Meerdere labels kunnen tegelijkertijd worden toegevoegd door ze te scheiden met een komma: « <i>korte lezing, belangrijk</i> »<br />Complexe regels kunnen worden geschreven met behulp van de beschikbare operators: als « <i>readingTime &gt;= 5 AND domainName = "www.php.net"</i> » label dan als « <i>lange lezing, php</i> »'
how_to_use_them_description: 'Laten we aannemen dat u nieuwe vermeldingen wilt labelen als « <i>korte lezing</i> » wanneer de leestijd minder dan 3 minuten bedraagt.<br />In dat geval moet u « readingTime &lt;= 3 » in het <i>Regelveld</i> en « <i>korte lezing</i> » in het <i>Labels</i> veld.<br />Meerdere labels kunnen tegelijkertijd worden toegevoegd door ze te scheiden met een komma:« <i>korte lezing, belangrijk</i> »<br />Complexe regels kunnen worden geschreven met behulp van vooraf gedefinieerde operators: if « <i>readingTime &gt;= 5 AND domainName = "www.php.net"</i> » label dan als« <i>lange lezing, php</i> »'
tags_label: Labels
rule_label: Regel
edit_rule_label: wijzig
@ -109,36 +98,33 @@ config:
import_submit: Importeer
file_label: JSON bestand
card:
export_tagging_rules_detail: Hiermee wordt een JSON-bestand gedownload dat je kan gebruiken om labelregels elders te importeren of om er een back-up van te maken.
export_tagging_rules_detail: Hiermee wordt een JSON-bestand gedownload dat u kunt gebruiken om labelregels elders te importeren of om er een back-up van te maken.
new_tagging_rule: Maak een labelregel
import_tagging_rules: Importeer labelregels
export_tagging_rules: Exporteer labelregels
import_tagging_rules_detail: Kies het JSON-bestand dat je eerder hebt geëxporteerd.
import_tagging_rules_detail: Selecteer het JSON-bestand dat u eerder hebt geëxporteerd.
form_password:
repeat_new_password_label: Herhaal nieuw wachtwoord
new_password_label: Nieuw wachtwoord
old_password_label: Huidig wachtwoord
description: Je kan hier je wachtwoord wijzigen. Je nieuwe wachtwoord moet minimaal 8 tekens lang zijn.
description: U kan hier uw wachtwoord wijzigen. Uw nieuwe wachtwoord moet minimaal 8 tekens lang zijn.
reset:
confirm: Weet je het zeker? (DIT IS ONOMKEERBAAR)
archived: Verwijder ALLE gearchiveerde artikelen
entries: Verwijder ALLE artikelen
confirm: Weet u het zeker? (DIT IS ONOMKEERBAAR)
archived: Verwijder ALLE gearchiveerde items
entries: Verwijder ALLE items
tags: Verwijder ALLE labels
annotations: Verwijder ALLE annotaties
description: Door onderstaande knoppen te gebruiken kan je bepaalde informatie van je account verwijderen. Wees gewaarschuwd, de verwijderde informatie kan NIET HERSTELD worden.
description: Door onderstaande knoppen te gebruiken kan u bepaalde informatie van uw account verwijderen. Wees gewaarschuwd dat NIET niet ongedaan gemaakt kan worden.
title: Reset opties (a.k.a gevaarlijke zone)
tagging_rules: Verwijder ALLE labelregels
otp:
app:
enable: Inschakelen
cancel: Annuleer
two_factor_code_description_4: 'Test een OTP-code van jouw OTP-app:'
two_factor_code_description_3: 'Bewaar deze back-upcodes op een veilige plaats, je kunt deze gebruiken voor het geval je de toegang tot je OTP-app verliest:'
two_factor_code_description_2: 'Je kunt de QR-code scannen met jouw app:'
two_factor_code_description_1: Je hebt zojuist de tweestapsverificatie met OTP app ingeschakeld. Open jouw OTP-app en gebruik de QR-code om een eenmalig wachtwoord te krijgen. Let op, de QR-code verdwijnt na het verlaten of opnieuw laden van deze pagina.
qrcode_label: QR code
two_factor_code_description_5: 'Als je de QR code niet kan scannen, voer dan het geheim in:'
page_title: Tweestapsverificatie
two_factor_code_description_4: 'Test een OTP-code van uw geconfigureerde app:'
two_factor_code_description_3: 'Bewaar deze back-upcodes op een veilige plaats, u kunt dit gebruiken voor het geval u de toegang tot uw OTP-app verliest:'
two_factor_code_description_2: 'U kunt de QR-code scannen met uw app:'
two_factor_code_description_1: U hebt zojuist de OTP-tweefactorauthenticatie ingeschakeld, uw OTP-app geopend en die code gebruikt om een eenmalig wachtwoord te krijgen. Het verdwijnt nadat de pagina opnieuw is geladen.
page_title: Twee-factor authenticatie
form_ignore_origin_rules:
faq:
ignore_origin_rules_definition_title: Wat betekent “negeer oorsprong regels”?
@ -153,41 +139,41 @@ config:
meaning: Betekenis
variables_available_description: 'De volgende variabelen en operatoren kunnen worden gebruikt om regels voor het negeren van oorsprong te creëren:'
variables_available_title: Welke variabelen en operatoren kunnen gebruikt worden om regels te schrijven?
how_to_use_them_description: Als je de bron van een artikel wil negeren als het afkomstig is van «<i>rss.example.com</i>» (<i>wetende dat na een omleiding het daadwerkelijke adres example.com is</i>). <br />In dat geval kun je «host = "rss.example.com"» in het veld <i>Regel</i> plaatsen.
how_to_use_them_description: Laten we aannemen dat u de oorsprong van een item wilt negeren dat afkomstig is van «<i>rss.example.com</i>» (<i>wetende dat na een omleiding het daadwerkelijke adres example.com is</i>) . <br />In dat geval moet u «host =" rss.example.com "» in het veld <i> Regel </i> plaatsen.
how_to_use_them_title: Hoe gebruik ik ze?
ignore_origin_rules_definition_description: Ze worden door wallabag gebruikt om automatisch een bronadres te negeren na een omleiding. <br />Als een omleiding plaatsvindt tijdens het ophalen van een nieuw artikel, zullen alle regels voor het negeren van de bron (<i>door de gebruiker gedefinieerd en door het systeem gedefinieerd</i>) gebruikt worden om het bronadres te negeren.
ignore_origin_rules_definition_description: Ze worden door wallabag gebruikt om automatisch een oorsprongsadres te negeren na een omleiding. <br />Als een omleiding plaatsvindt tijdens het ophalen van een nieuw item, zullen alle regels voor het negeren van de oorsprong (<i>door de gebruiker gedefinieerd en door de instantie gedefinieerd</i>) gebruikt worden om het oorspronkelijke adres te negeren.
title: Veelgestelde vragen
form_feed:
feed_links: Feedlinks
feed_limit: Aantal artikelen in de feed
feed_limit: Aantal items in de feed
feed_link:
all: Alles
archive: Gearchiveerd
starred: Met ster
starred: Gemarkeerd
unread: Ongelezen
token_revoke: Token intrekken
token_reset: Token opnieuw genereren
token_create: Creëer een token
token_create: Creëer uw token
no_token: Geen token
token_label: Feed token
description: Met Atom-feeds van wallabag kunt je je opgeslagen artikelen lezen met je favoriete Atom-lezer. Je moet wel eerst een token genereren.
description: Met Atom-feeds van wallabag kunt u uw opgeslagen artikelen lezen met uw favoriete Atom-lezer. U moet wel eerst een token genereren.
footer:
stats: Sinds %user_creation% heb je %nb_archives% artikelen gelezen. Dat is ongeveer %per_day% per dag!
stats: Sinds %user_creation% heeft u %nb_archives% artikelen gelezen. Dat is ongeveer %per_day% per dag!
wallabag:
about: Over
powered_by: mogelijk gemaakt door
social: Sociaal
elsewhere: Neem wallabag met je mee
elsewhere: Neem wallabag met u mee
menu:
search_form:
input_label: Vul je zoeksuggestie hier in
input_label: Vul uw zoeksuggestie hier in
top:
export: Exporteer
filter_entries: Filter artikelen
filter_entries: Filter items
search: Zoeken
add_new_entry: Voeg nieuw artikel toe
add_new_entry: Voeg nieuw item toe
account: Mijn account
random_entry: Spring naar een willekeurig artikel in de lijst
random_entry: Spring naar een willekeurig item van de lijst
left:
site_credentials: Site inloggegevens
users_management: Gebruikersbeheer
@ -202,16 +188,15 @@ menu:
internal_settings: Interne Instellingen
tags: Labels
config: Configuratie
all_articles: Alle artikelen
all_articles: Alle items
archive: Archief
starred: Met ster
starred: Gemarkeerd
unread: Ongelezen
ignore_origin_instance_rules: Globaal negeer-oorsprongsregels
quickstart: Snelstart
theme_toggle_auto: Thema automatisch
theme_toggle_dark: Donker thema
theme_toggle_light: Licht thema
with_annotations: Met aantekeningen
security:
login:
password: Wachtwoord
@ -223,10 +208,10 @@ security:
forgot_password: Wachtwoord vergeten?
keep_logged_in: Houdt mij ingelogd
register:
go_to_account: Ga naar je account
go_to_account: Ga naar uw account
page_title: Maak een account
resetting:
description: Voer je e-mailadres hieronder in en wij sturen je instructies voor het opnieuw instellen van je wachtwoord.
description: Voer uw e-mailadres hieronder in en wij sturen u instructies voor het opnieuw instellen van uw wachtwoord.
flashes:
site_credential:
notice:
@ -246,33 +231,33 @@ flashes:
notice:
summary_with_queue: 'Importeren samenvatting: %queued% in wachtrij.'
summary: 'Importeren samenvatting: %imported% imported, %skipped% reeds opgeslagen.'
failed_on_file: Fout bij het verwerken van importeren. Controleer het geïmporteerde bestand.
failed: Importeren mislukt, probeer opnieuw.
failed_on_file: Fout bij het verwerken van importeren. Controleer uw geïmporteerde bestand.
failed: Importeren gefaald, probeer opnieuw.
error:
rabbit_enabled_not_installed: RabbitMQ is ingeschakeld voor het afhandelen van asynchroon importeren, maar het lijkt erop dat <u> we er geen verbinding mee kunnen maken </u>. Controleer de RabbitMQ-configuratie.
redis_enabled_not_installed: Redis is ingeschakeld voor het afhandelen van asynchroon importeren, maar het lijkt erop dat <u> we er geen verbinding mee kunnen maken </u>. Controleer de Redis-configuratie.
entry:
notice:
entry_reloaded_failed: Artikelen opnieuw geladen maar ophalen van inhoud mislukt
entry_saved_failed: Artikel opgeslagen maar ophalen van inhoud is mislukt
entry_already_saved: Artikel is reeds opgeslagen op %date%
entry_deleted: Artikel verwijderd
entry_unstarred: Artikel is nu zonder ster
entry_starred: Artikel is nu met ster
entry_unarchived: Artikel gedearchiveerd
entry_archived: Artikel gearchiveerd
entry_reloaded: Artikel is opnieuw geladen
entry_updated: Artikel geüpdatet
entry_saved: Artikel opgeslagen
entry_reloaded_failed: Item herladen maar ophalen van inhoud gefaald
entry_saved_failed: Item opgeslagen maar ophalen van inhoud is gefaald
entry_already_saved: Item is reeds opgeslagen op %date%
entry_deleted: Item verwijderd
entry_unstarred: Item gedemarkeerd
entry_starred: Item gemarkeerd
entry_unarchived: Item gedearchiveerd
entry_archived: Item gearchiveerd
entry_reloaded: Item herladen
entry_updated: Item geüpdatet
entry_saved: Item opgeslagen
no_random_entry: Er is geen artikel met deze criteria gevonden
config:
notice:
archived_reset: Gearchiveerde artikelen verwijderd
archived_reset: Gearchiveerde items verwijderd
rss_token_updated: RSS token geüpdatet
tagging_rules_deleted: Labelregel verwijderd
tagging_rules_updated: Labelregels geüpdatet
tagging_rules_deleted: Labeling regel verwijderd
tagging_rules_updated: Labeling regels geüpdatet
rss_updated: RSS informatie geüpdatet
entries_reset: Artikelen gereset
entries_reset: Items gereset
tags_reset: Labels gereset
annotations_reset: Annotaties gereset
user_updated: Informatie veranderd
@ -280,20 +265,17 @@ flashes:
config_saved: Configuratie opgeslagen.
ignore_origin_rules_updated: Negeer oorsprongregel gewijzigd
ignore_origin_rules_deleted: Negeer oorsprongregel verwijderd
tagging_rules_not_imported: Fout bij importeren van labelregels
tagging_rules_imported: Labelregels geïmporteerd
otp_disabled: Tweestapsverificatie uitgeschakeld
otp_enabled: Tweestapsverificatie ingeschakeld
tagging_rules_not_imported: Fout bij importeren van labeling regels
tagging_rules_imported: Labeling regels geïmporteerd
otp_disabled: Twee factor authenticatie uitgeschakeld
otp_enabled: Twee factor authenticatie ingeschakeld
feed_token_revoked: Feed token ingetrokken
feed_token_updated: Feed token gewijzigd
feed_updated: Feed informatie gewijzigd
tagging_rules_reset: Reset labelregels
otp_code_invalid: Foute tweestapsverificatie code
tag:
notice:
tag_added: Label toegevoegd
tag_renamed: Label hernoemd
too_much_tags: Om performance problemen te vermijden, kun je niet meer dan %tags% labels tegelijk toevoegen, en zijn labels met meer dan %characters% tekens niet toegestaan.
ignore_origin_instance_rule:
notice:
deleted: Globale oorsprongregel voor negeren verwijderd
@ -304,7 +286,7 @@ error:
site_credential:
form:
back_to_list: Terug naar lijst
delete_confirm: Weet je het zeker?
delete_confirm: Weet u het zeker?
delete: Verwijder
save: Opslaan
password_label: Wachtwoord
@ -319,7 +301,7 @@ site_credential:
edit_site_credential: Wijzig bestaande inloggegevens
new_site_credential: Creëer inloggegevens
page_title: Beheer van inloggegevens van de site
description: Hier kunt je alle inloggegevens beheren voor sites die dit nodig hebben (maken, bewerken en verwijderen), zoals een betaalmuur, een authenticatie, enz.
description: Hier kunt u alle inloggegevens beheren voor sites die dit nodig hebben (maken, bewerken en verwijderen), zoals een betaalmuur, een authenticatie, enz.
user:
form:
repeat_new_password_label: Herhaal nieuw wachtwoord
@ -327,7 +309,7 @@ user:
name_label: Naam
username_label: Gebruikersnaam
back_to_list: Terug naar lijst
delete_confirm: Weet je het zeker?
delete_confirm: Weet u het zeker?
delete: Verwijder
save: Opslaan
twofactor_label: Twee factor authenticatie
@ -335,37 +317,37 @@ user:
email_label: E-mail
plain_password_label: ????
last_login_label: Laatste login
twofactor_google_label: Tweestapsverificatie met OTP app
twofactor_email_label: Tweestapsverificatie via e-mail
twofactor_google_label: Twee factor authenticatie met OTP app
twofactor_email_label: Twee factor authenticatie met email
list:
create_new_one: Maak een nieuwe gebruiker
no: Nee
yes: Ja
edit_action: Wijzig
actions: Acties
description: Hier kan je alle gebruikers beheren (creëren, wijzigen en verwijderen)
description: Hier kan u alle gebruikers beheren (creëren, wijzigen en verwijderen)
edit_user: Wijzig een bestaande gebruiker
new_user: Maak een nieuwe gebruiker
search:
placeholder: Filter op gebruikersnaam of e-mail
placeholder: Filter op username of email
page_title: Gebruikersbeheer
developer:
howto:
back: Terug
description:
paragraph_7: Dit verzoek geeft als resultaat alle artikelen voor deze gebruiker.
paragraph_7: Dit verzoek geeft als resultaat alle items voor deze gebruiker.
paragraph_6: 'Het acces_token is handig om een verzoek op de API te doen. Bijvoorbeeld:'
paragraph_5: 'De API geeft een vergelijkbare reactie:'
paragraph_4: 'Dus, creëer een token(vervang client_id, client_geheim, gebruikersnaam en wachtwoord met de juiste waardes):'
paragraph_3: Om het token te maken, moet je <a href="%link%">een nieuwe client creëren</a>.
paragraph_2: Je hebt een token nodig om te communiceren tussen applicaties van derde partijen en de wallabag API.
paragraph_3: Om deze token te maken, moet u <a href="%link%">een nieuwe client creëren</a>.
paragraph_2: U heeft een token nodig om te communiceren tussen applicaties van derde partijen en de wallabag API.
paragraph_8: Als je alle API-eindpunten wilt zien, kun je <a href="%link%"> onze API-documentatie </a> bekijken.
paragraph_1: De volgende commando's maken gebruik van de <a href="https://github.com/jkbrzt/httpie">HTTPie-bibliotheek</a>. Zorg ervoor dat deze op jouw systeem is geïnstalleerd voordat je het gebruikt.
paragraph_1: De volgende commando's maken gebruik van de <a href="https://github.com/jkbrzt/httpie"> HTTPie-bibliotheek </a>. Zorg ervoor dat het op uw systeem is geïnstalleerd voordat u het gebruikt.
page_title: API client beheren > Hoe creëer je je eerste applicatie
client_parameter:
read_howto: Lees de beschrijving "Hoe creëer je je eerste applicatie"
back: Terug
page_description: Dit zijn de client parameters.
page_description: Dit zijn uw client parameters.
page_title: API client beheer > Client parameters
field_secret: Client geheim
field_id: Client ID
@ -377,7 +359,7 @@ developer:
save_label: Maak een nieuwe client
redirect_uris_label: Omleiding URLs (optioneel)
name_label: Naam van de client
page_description: Je staat op het punt een nieuwe client aan te maken. Vul het onderstaande veld in voor de omleidings-URI van jouw applicatie.
page_description: U staat op het punt een nieuwe client aan te maken. Vul het onderstaande veld in voor de omleidings-URI van uw applicatie.
copy_to_clipboard: Kopieer
existing_clients:
field_grant_types: Grant type toegestaan
@ -392,7 +374,7 @@ developer:
welcome_message: Welkom bij de wallabag API
remove:
action: Verwijder client %name%
warn_message_2: Als je dit verwijdert, kan elke app die met deze client is geconfigureerd, niet meer verbinden met jouw wallabag.
warn_message_2: Als u dit verwijdert, kan elke app die met die client is geconfigureerd, niet meer verbinden met uw wallabag.
warn_message_1: U heeft de mogelijkheid om client %name% te verwijderen. Deze actie is ONOMKEERBAAR!
clients:
create_new: Maak een nieuwe client
@ -401,28 +383,28 @@ developer:
page_title: API client beheren
import:
pinboard:
how_to: Kies je Pinboard exportbestand en klik op de knop om deze te uploaden en importeren.
how_to: Selecteer uw Pinboard exporteur en klik onderstaande knop om die te uploaden en importeren.
page_title: Importeer > Pinboard
description: Importeer je Pinboard-artikelen. Klik op de "back-uppagina" (https://pinboard.in/settings/backup) op "JSON" in het gedeelte "Bladwijzers". Er wordt een JSON-bestand gedownload (zoals "pinboard_export").
description: Deze importeur importeert al je Pinboard-artikelen. Klik op de "back-uppagina" (https://pinboard.in/settings/backup) op "JSON" in het gedeelte "Bladwijzers". Er wordt een JSON-bestand gedownload (zoals "pinboard_export").
instapaper:
how_to: Kies je Instapaper exportbestand en klik de knop om deze te uploaden en importeren.
how_to: Selecteer uw Instapaper exporteur en klik onderstaande knop om die te uploaden en importeren.
page_title: Importeer > Instapaper
description: Importeer je Instapaper-artikelen. Klik op de instellingenpagina (https://www.instapaper.com/user) op "Download .CSV-bestand" in het gedeelte "Exporteren". Er wordt een CSV-bestand gedownload (zoals "instapaper-export.csv").
description: Deze importeur importeert al uw Instapaper-artikelen. Klik op de instellingenpagina (https://www.instapaper.com/user) op "Download .CSV-bestand" in het gedeelte "Exporteren". Er wordt een CSV-bestand gedownload (zoals "instapaper-export.csv").
chrome:
description: 'Importeer je Chrome-bladwijzers. De locatie van het bestand is afhankelijk van je besturingssysteem: <ul><li>Onder Linux, ga naar de <code>~/.config/chromium/Default/</code>directory</li><li>In Windows, zou het in <code>%LOCALAPPDATA%\Google\Chrome\User Data\Default</code></li><li>Onder OS X moet het staan in <code>~/Library/Application Support/Google/Chrome/Default/Bookmarks</code></li></ul>Zodra je daar bent, kopieer je het <code>Bookmarks</code> bestand ergens waar je het kan vinden.<em><br>Let op dat als je Chromium gebruikt in plaats van Chrome, dat de paden dan aangepast moeten worden.</em></p>'
description: 'Deze importeur importeert al uw Chrome-bladwijzers. De locatie van het bestand is afhankelijk van uw besturingssysteem: <ul> <li> Onder Linux, ga naar de <code> ~ /.config/chromium/Default/</code>directory </li> <li> In Windows, het zou in <code>% LOCALAPPDATA%\Google\Chrome\User Data\Default </code> </li> <li> Op OS X moeten staan in <code> ~/Library/Application Support/Google/Chrome/Default /Bookmarks </code> </li> </ul> Zodra u daar bent, kopieert u het <code> bladwijzer </code> -bestand ergens waar u het kunt vinden. <em> <br> Let op dat als u Chromium in plaats van Chrome heeft, u de paden dienovereenkomstig corrigeren moet. </em> </p>'
page_title: Importeer > Chrome
how_to: Kies het back-upbestand van de bladwijzer en klik op de onderstaande knop om het te importeren. Houd er rekening mee dat het proces lang kan duren, aangezien alle artikelen moeten worden opgehaald.
readability:
how_to: Kies het Readability exportbestand en klik de knop om deze te uploaden en importeren.
how_to: Selecteer uw Readability exporteur en klik onderstaande knop om die te uploaden en importeren.
page_title: Importeer > Readability
description: Importeer je Readability-artikelen.
description: Deze importeur importeert al uw Readability-artikelen. Klik bij tools (https://www.readability.com/tools/) op "Uw gegevens exporteren" in het gedeelte "Gegevensexport". U ontvangt een e-mail om een json te downloaden (die in feite niet op .json eindigt).
wallabag_v2:
page_title: Importeren > Wallabag v2
description: Importeer al uw Wallabag v2-artikelen. Ga naar "Alle artikelen" en klik in de exporteer zijbalk op "JSON". Je hebt een "All Articles.json" -bestand.
description: Deze importeur importeert al uw Wallabag v2-artikelen. Ga naar "Alle artikelen" en klik in de exporteer zijbalk op "JSON". Je hebt een "All Articles.json" -bestand.
wallabag_v1:
how_to: Kies je wallabag exportbestand en klik op de knop om deze te uploaden en importeren.
how_to: Selecteer uw wallabag exporteur en klik onderstaande knop om die te uploaden en importeren.
page_title: Importeren > Wallabag v1
description: Importeer al je Wallabag v1-artikelen. Klik in de configuratiepagina op "JSON-exporteren" in de sectie "Exporteer je wallabag-gegevens". Je krijgt dan het bestand "wallabag-export-1-xxxx-xx-xx.json".
description: Deze importeur importeert al uw Wallabag v1-artikelen. Klik op je configuratiepagina op "JSON-exporteren" in de sectie "Exporteer je wallabag-gegevens". Je hebt het bestand "wallabag-export-1-xxxx-xx-xx.json".
pocket:
connect_to_pocket: Verbind Pocket en importeer data
config_missing:
@ -430,66 +412,43 @@ import:
admin_message: U moet %keyurls%a pocket_consumer_key%keyurle% definiëren.
description: Pocket importeren is niet geconfigureerd.
page_title: Importeer > Pocket
authorize_message: Je kunt je gegevens importeren vanuit jouw Pocket-account. Je hoeft alleen maar op de onderstaande knop te klikken en de applicatie te autoriseren om verbinding te maken met getpocket.com.
description: Importeer je gegevens van Pocket. Pocket staat het niet toe om inhoud van hun dienst op te halen, dus de leesbare inhoud van elk artikel wordt opnieuw opgehaald door wallabag.
authorize_message: U kunt uw gegevens importeren vanuit uw Pocket-account. U hoeft alleen maar op de onderstaande knop te klikken en de applicatie te autoriseren om verbinding te maken met getpocket.com.
description: Deze importeur importeert al uw Pocket-gegevens. Pocket staat niet toe om inhoud van hun dienst op te halen, dus de leesbare inhoud van elk artikel wordt opnieuw opgehaald door wallabag.
form:
file_label: Bestand
mark_as_read_label: Markeer alle geïmporteerde artikelen als gelezen
mark_as_read_label: Markeer alle geïmporteerde items als gelezen
mark_as_read_title: Markeer als gelezen?
save_label: Upload bestand
page_description: Welkom bij de wallabag importeur. Selecteer de dienst waarvan je wil migreren.
page_description: Welkom bij de wallabag importeur. Selecteer uw vorige dienst waarvan u wilt migreren.
page_title: Importeren
firefox:
page_title: Importeer > Firefox
description: Importeer je Firefox-bladwijzers. Ga naar je Bibliotheek (Ctrl + Shift + O), klik op de knop "↓↑" en dan "Reserve kopie maken…". Je krijgt een .json-bestand.
description: Deze importeur importeert al uw Firefox-bladwijzers. Ga naar uw bladwijzers (Ctrl + Shift + O), en kies dan "Importeren en back-up", kies "Back-up…". U krijgt een .json-bestand.
how_to: Kies het back-upbestand van de bladwijzer en klik op de onderstaande knop om het te importeren. Houd er rekening mee dat het proces lang kan duren, aangezien alle artikelen moeten worden opgehaald.
action:
import_contents: Importeer inhoud
worker:
enabled: 'Het importeren wordt asynchroon uitgevoerd. Zodra de importeer taak is gestart, zal een extern proces de taken één voor één afhandelen. De huidige service is:'
download_images_warning: Je hebt het downloaden van afbeeldingen voor je artikelen ingeschakeld. In combinatie met de klassieke import kan dat een eeuwigheid duren (of het mislukt misschien). We <strong>raden sterk aan</strong> om asynchroon importeren in te schakelen om fouten te voorkomen.
download_images_warning: U heeft het downloaden van afbeeldingen voor uw artikelen ingeschakeld. In combinatie met de klassieke import kan het eeuwen duren om door te gaan (of het mislukt misschien). We <strong> raden sterk aan </strong> om asynchroon importeren in te schakelen om fouten te voorkomen.
elcurator:
description: Importeer al je elCurator-artikelen.
description: Deze importeur importeert al je elCurator-artikelen. Ga naar voorkeuren in uw elCurator-account en exporteer vervolgens uw inhoud. Je krijgt een JSON-bestand.
page_title: Importeer > elCurator
how_to: Kies je elCurator exportbestand en druk op de knop om deze uploaden en importeren.
pocket_html:
page_title: Importeer > Pocket HTML
how_to: Kies het Pocket exportbestand en druk op de knop om het te importeren. Let op, het proces kan lang duren omdat alle artikelen opgehaald moeten worden.
description: Importeer je Pocket bookmarks (via HTML export). Ga naar https://getpocket.com/export, exporteer dan een HTML bestand. Een HTML bestand genaamd "ril_export.html" wordt gedownload.
shaarli:
how_to: Kies een bookmark-backupbestand en druk op de knop om het te importeren. Let op, het proces kan lang duren omdat alle artikelen opgehaald moeten worden.
description: Importeer je Shaarli bookmarks. Log in, ga naar de Tools sectie, kies "Export database", kies je bookmarks en exporteer. Je krijgt een HTML bestand.
page_title: Importeer > Shaarli
delicious:
how_to: Kies je Delicious exportbestand en druk op de knop om deze te importeren.
page_title: Importeer > del.icio.us
description: Importeer je Delicious bookmarks. Sinds 2021 kun je je data weer exporteren via de pagina https://del.icio.us/export. Kies het "JSON" formaat. Je krijgt een bestand met de naam die lijkt op "delicious_export.2021.02.06_21.10.json".
omnivore:
page_title: Importeer > Omnivore
how_to: Unzip het Omnivore exportbestand, upload dan, een voor een, elk JSON bestand met de naam "metadata_x_to_y.json".
description: Importeer al je Omnivore artikelen.
pocket_csv:
page_title: Importeer > Pocket CSV
how_to: Kies het bookmark backupbestand en druk op de knop om het te importeren. Let op, het proces kan lang duren omdat alle artikelen opgehaald moeten worden.
description: Importeer je Pocket bookmarks (via CSV export). Ga naar https://getpocket.com/export, exporteer dan een CSV bestand. Een ZIP bestand genaamd "pocket.zip" wordt gedownload. Unzip het krijgt dan een csv bestand genaamd "part_000000.csv".
export:
unknown: Onbekend
footer_template: <div style="text-align:center;"><p>Gemaakt door wallabag met %method%</p><p>Make een <a href="https://github.com/wallabag/wallabag/issues">issue</a> aan (in het Engels) als je problemen ondervind met dit E-Book op jouw apparaat.</p></div>
footer_template: <div style="text-align:center;"><p>Gemaakt door wallabag met %method%</p><p>Open <a href="https://github.com/wallabag/wallabag/issues">een probleem</a> als u problemen ondervind met dit E-Book op uw apparaat.</p></div>
tag:
new:
placeholder: Je kan meerdere labels toevoegen, gescheiden door een komma.
placeholder: U kan meerdere labels toevoegen door ze te splitsen met comma.
add: Toevoegen
list:
number_on_the_page: '{0} Er zijn geen labels.|{1} Er is één label.|]1,Inf[ Er zijn %count% labels.'
see_untagged_entries: Toon niet gelabelde artikelen
no_untagged_entries: Er zijn geen artikelen zonder label.
untagged: Niet gelabelde artikelen
see_untagged_entries: Toon niet gelabelde items
no_untagged_entries: Er zijn geen items zonder labels.
untagged: Niet gelabelde items
page_title: Labels
confirm:
delete: Verwijder het label %name%
quickstart:
support:
description: Als je wat hulp kan gebruiken, wij zijn er voor jou.
description: Wij zijn er voor u als u hulp nodig heeft.
title: Ondersteuning
matrix: Op Matrix
email: Per e-mail
@ -497,26 +456,26 @@ quickstart:
docs:
all_docs: En zo veel andere artikelen!
fetching_errors: Wat kan ik doen als bij het ophalen van een artikel iets fout gaat?
search_filters: Bekijk hoe je jouw artikelen kan vinden door middel van zoeken en filteren
export: Converteer je artikelen naar ePUB of PDF
annotate: Annoteer je artikel
search_filters: Bekijk hoe u uw artikelen kan vinden door middel van zoeken en filteren
export: Converteer uw artikelen naar ePUB of PDF
annotate: Annoteer uw artikel
title: Volledige documentatie
description: Er zijn zoveel functies in wallabag. Aarzel niet om de handleiding te lezen om ze te leren kennen en te leren hoe u ze kunt gebruiken.
developer:
use_docker: Gebruiker Docker om wallabag te installeren
create_application: Creëer applicaties van derden
create_application: Creëer uw applicaties van derden
description: 'We hebben ook aan de ontwikkelaars gedacht: Docker, API, vertalingen, etc.'
title: Ontwikkelaars
migrate:
wallabag_v2: Migreren van wallabag v2
wallabag_v1: Migreren van wallabag v1
description: Gebruik je een andere dienst? Wij helpen je jouw data naar wallabag te halen.
description: Gebruikt u een andere dienst? Wij helpen u uw data naar wallabag te halen.
title: Migreer van een bestaande dienst
instapaper: Migreer van Instapaper
readability: Migreer van Readability
pocket: Migreer van Pocket
first_steps:
new_article: Sla je eerste artikel op
new_article: Sla uw eerste artikel op
unread_articles: En classificeer het!
title: Eerste stappen
description: Nu wallabag goed is geconfigureerd, is het tijd om het web te archiveren. U kunt op het teken rechtsboven + klikken om een link toe te voegen.
@ -526,17 +485,17 @@ quickstart:
export: Configureer exporteren
analytics: Configureer analytics
new_user: Creëer een nieuwe gebruiker
description: 'Als een administrator heb je privileges op wallabag. Je kan:'
description: 'Als een administrator heeft u privileges op wallabag. U kan:'
title: Administratie
intro:
paragraph_1: We begeleiden je tijdens je bezoek aan wallabag en laten je enkele functies zien die je vast interesseren.
paragraph_1: We begeleiden u tijdens uw bezoek aan wallabag en laten u enkele functies zien die u mogelijk interesseren.
paragraph_2: Volg ons!
title: Welkom bij wallabag!
configure:
tagging_rules: Schrijf regels om automatisch labels toe te voegen aan artikelen
rss: Schakel RSS-feeds in
language: Verander taal en uiterlijk
description: Om een applicatie te vinden die bij je past kan je een kijkje nemen op de configuratiepagina van wallabag.
description: Om een applicatie te vinden die bij u past kan u een kijkje nemen op de configuratiepagina van wallabag.
title: Configureer de applicatie
feed: Ingeschakelde feeds
more: Meer…
@ -544,14 +503,14 @@ quickstart:
howto:
shortcuts:
article_title: Snelkoppelingen beschikbaar op startscherm
open_article: Toon het geselecteerde artikel
open_article: Toon het geselecteerde item
arrows_navigation: Navigeer door artikelen
hide_form: Verberg het huidige formulier (zoeken of nieuwe link)
add_link: Voeg nieuwe link toe
delete: Verwijder het artikel
toggle_archive: Verander lees status van het artikel
toggle_favorite: Wissel met/zonder ster van het artikel
open_original: Open originele URL van het artikel
delete: Verwijder het item
toggle_archive: Verander lees status van het item
toggle_favorite: Verander gemarkeerd status van het item
open_original: Open originele URL van het item
search: Toon het zoekformulier
list_title: Snelkoppelingen beschikbaar in overzicht pagina's
go_logout: Uitloggen
@ -560,9 +519,9 @@ howto:
go_import: Ga naar importeren
go_config: Ga naar configuratie
go_tags: Ga naar labels
go_all: Ga naar alle artikelen
go_all: Ga naar alle items
go_archive: Ga naar gearchiveerd
go_starred: Ga naar met ster
go_starred: Ga naar gemarkeerd
go_unread: Ga naar ongelezen
all_pages_title: Snelkoppelingen beschikbaar op alle paginas
action: Actie
@ -575,7 +534,7 @@ howto:
mobile_apps: Mobiele apps
browser_addons: Browser plugins
bookmarklet:
description: 'Sleep deze link naar je bladwijzerbalk:'
description: 'Sleep deze link naar uw bladwijzerbalk:'
mobile_apps:
ios: met de App Store
windows: met de Microsoft Store
@ -642,7 +601,7 @@ entry:
delete: Verwijder
re_fetch_content: Opnieuw ophalen van inhoud
view_original_article: Origineel artikel
set_as_starred: Wissel met/zonder ster
set_as_starred: Verander gemarkeerd
set_as_unread: Markeer als ongelezen
set_as_read: Markeer als gelezen
back_to_homepage: Terug
@ -658,25 +617,23 @@ entry:
reading_time: Geschatte leestijd
published_on: Gepubliceerd op
confirm:
delete_tag: Weet je zeker dat je dit label wilt verwijderen van dit artikel?
delete: Weet je zeker dat je dit artikel wilt verwijderen?
reload: Weet je zeker dat je dit artikel opnieuw wil ophalen?
delete_entries: Weet je zeker dat je deze artikelen wilt verwijderen?
delete_tag: Weet u zeker dat u dit label wilt verwijderen van dit artikel?
delete: Weet u zeker dat u dit artikel wilt verwijderen?
public:
shared_by_wallabag: Dit artikel is gedeeld door %username% met <a href='%wallabag_instance%'>wallabag</a>
edit:
save_label: Opslaan
origin_url_label: Oorspronkelijke url (waar je dit artikel gevonden hebt)
origin_url_label: Oorspronkelijke url (waar je dit item gevonden hebt)
url_label: Url
title_label: Titel
page_title: Wijzig een artikel
page_title: Wijzig een item
search:
placeholder: Waar ben je naar op zoek?
new:
form_new:
url_label: Url
placeholder: http://website.nl
page_title: Sla nieuw artikel op
page_title: Sla nieuw item op
filters:
action:
filter: Filter
@ -697,17 +654,15 @@ entry:
preview_picture_help: Voorbeeld afbeelding
preview_picture_label: Heeft een voorbeeld afbeelding
unread_label: Ongelezen
starred_label: Met ster
starred_label: Gemarkeerd
archived_label: Gearchiveerd
status_label: Status
title: Filters
parsed_label: Niet correct opgehaald
annotated_label: Geannoteerd
list:
export_title: Exporteer
delete: Verwijder
toogle_as_star: Wissel met/zonder ster
toogle_as_read: Als gelezen markeren
toogle_as_star: Verander gemarkeerd
toogle_as_read: Verander gemarkeerd als gelezen
original_article: origineel
reading_time_less_one_minute_short: '&lt; 1 min'
reading_time_minutes_short: '%readingTime% min'
@ -715,24 +670,17 @@ entry:
reading_time_less_one_minute: 'geschatte leestijd: &lt; 1 min'
reading_time_minutes: 'geschatte leestijd: %readingTime% min'
reading_time: geschatte leestijd
number_on_the_page: '{0} Er zijn geen artikelen.|{1} Er is één artikel.|]1,Inf[ Er zijn %count% artikelen.'
toggle_mass_action: Massaal schakelen actie
mass_action_tags_input_placeholder: label1, label2, label3
add_tags: Voeg labels toe
show_same_domain: Toon artikelen met hetzelfde domein
assign_search_tag: Label elke resultaat met deze zoekopdracht
number_on_the_page: '{0} Er zijn geen items.|{1} Er is één item.|]1,Inf[ Er zijn %count% items.'
page_titles:
all: Alle artikelen
untagged: Ongelabelde artikelen
all: Alle items
untagged: Ongelabelde items
filtered_search: 'Gefilterd met zoeken:'
filtered_tags: 'Gefilterd op labels:'
filtered: Gefilterde artikelen
archived: Gearchiveerde artikelen
starred: Artikelen met ster
unread: Ongelezen artikelen
with_annotations: Artikelen met annotatie
same_domain: Hetzelfde domein
default_title: Titel van het artikel
filtered: Gefilterde items
archived: Gearchiveerde items
starred: Gemarkeerde items
unread: Ongelezen items
default_title: Titel van het item
ignore_origin_instance_rule:
list:
edit_action: Wijzig
@ -740,13 +688,13 @@ ignore_origin_instance_rule:
create_new_one: Maak een nieuwe algemene regel voor het negeren van de oorsprong
no: Nee
yes: Ja
description: Hier kunt je de algemene regels voor het negeren van oorsprong beheren die worden gebruikt om bepaalde patronen van de oorspronkelijke URL te negeren.
description: Hier kunt u de algemene regels voor het negeren van oorsprong beheren die worden gebruikt om bepaalde patronen van de oorspronkelijke URL te negeren.
edit_ignore_origin_instance_rule: Bewerk een bestaande regel voor het negeren van de oorsprong
new_ignore_origin_instance_rule: Maak een algemene regel voor het negeren van de oorsprong
page_title: Globale negeer oorsprongsregels
form:
back_to_list: Terug naar lijst
delete_confirm: Weet je het zeker?
delete_confirm: Weet u het zeker?
delete: Verwijder
save: Opslaan
rule_label: Regel

View File

@ -51,7 +51,7 @@ footer:
wallabag:
elsewhere: Weż wallabag ze sobą
social: Społeczność
powered_by: działa dzięki
powered_by: Kontrolowany przez
about: O nas
stats: Od %user_creation% przeczytałeś %nb_archives% artykułów. To jest %per_day% dziennie!
config:
@ -231,13 +231,13 @@ entry:
default_title: Tytuł wpisu
page_titles:
unread: Nieprzeczytane wpisy
starred: Wyróżnione wpisy
starred: Wpisy wyróżnione
archived: Zarchiwizowane wpisy
filtered: Odfiltrowane wpisy
filtered_tags: 'Filtrowane po tagach:'
filtered_search: 'Filtrowanie po wyszukiwaniu:'
untagged: Nieotagowane wpisy
all: Wszystkie wpisy
all: Wszystkie przedmioty
with_annotations: Wpisy z adnotacjami
same_domain: Ta sama domena
list:
@ -557,10 +557,6 @@ import:
description: Ten importer zaimportuje wszystkie Twoje artykuły z Omnivore.
page_title: Importuj > Omnivore
how_to: Rozpakuj eksport z Omnivore, a następnie prześlij po kolei wszystkie pliki JSON o nazwie „metadata_x_to_y.json”.
pocket_csv:
description: Ten importer zaimportuje wszystkie zakładki Pocket (poprzez eksport CSV). Po prostu przejdź do https://getpocket.com/export, a następnie wyeksportuj plik. Zostanie pobrany plik ZIP (taki jak „pocket.zip”). Wypakuj go, otrzymasz plik CSV o nazwie „part_000000.csv”.
page_title: Importuj > Pocket CSV
how_to: Wybierz plik kopii zapasowej zakładek i kliknij przycisk poniżej, aby go zaimportować. Należy pamiętać, że proces ten może potrwać długo, ponieważ wszystkie artykuły muszą zostać pobrane.
developer:
page_title: Zarządzanie klientami API
welcome_message: Witaj w API wallabag

View File

@ -20,7 +20,7 @@ config:
tagging_rules_definition_title: “குறிச்சொல் விதிகள்” என்றால் என்ன?
tagging_rules_definition_description: அவை புதிய உள்ளீடுகளை தானாகக் குறிக்க வாலபாக் பயன்படுத்தும் விதிகள். <br /> ஒவ்வொரு முறையும் ஒரு புதிய நுழைவு சேர்க்கப்படும்போது, நீங்கள் கட்டமைத்த குறிச்சொற்களைச் சேர்க்க அனைத்து குறிச்சொல் விதிகளும் பயன்படுத்தப்படும், இதனால் உங்கள் உள்ளீடுகளை கைமுறையாக வகைப்படுத்துவதில் சிக்கலைச் சேமிக்கிறது.
how_to_use_them_title: அவற்றை எவ்வாறு பயன்படுத்துவது?
how_to_use_them_description: 'புதிய உள்ளீடுகளை «<i> குறுகிய வாசிப்பு </i>» எனக் குறிக்க விரும்புகிறீர்கள் என்று வைத்துக் கொள்வோம். வாசிப்பு நேரம் 3 நிமிடங்களுக்குள் இருக்கும்போது. <br /> அந்த விசயத்தில், நீங்கள் «வாசிப்பு நேரத்தை &lt; = 3» <i> விதி </i> புலம் மற்றும் «<i> குறுகிய வாசிப்பு </i>» <i> குறிச்சொற்கள் </i> புலத்தில். <br /> பல குறிச்சொற்கள் ஒரே நேரத்தில் கமாவுடன் பிரிப்பதன் மூலம் சேர்க்கலாம்: «<i> குறுகிய வாசிப்பு, கட்டாயம் படிக்க வேண்டும் </i> »<br /> முன் வரையறுக்கப்பட்ட ஆபரேட்டர்களைப் பயன்படுத்துவதன் மூலம் சிக்கலான விதிகளை எழுதலாம்: என்றால்« <i> வாசிப்பு நேரம் &gt; = 5 மற்றும் டொமைன் பெயர் = "www.php.net" </i> »பின்னர்« <i> நீண்ட வாசிப்பு, பிஎச்பி </i> »எனக் குறிக்கவும்'
how_to_use_them_description: 'புதிய உள்ளீடுகளை «<i> குறுகிய வாசிப்பு < /i>» எனக் குறிக்க விரும்புகிறீர்கள் என்று வைத்துக் கொள்வோம். வாசிப்பு நேரம் 3 நிமிடங்களுக்குள் இருக்கும்போது. <br /> அந்த விசயத்தில், நீங்கள் «வாசிப்பு நேரத்தை & lt; = 3» <i> விதி </i> புலம் மற்றும் «<i> குறுகிய வாசிப்பு </i>» <i> குறிச்சொற்கள் </i> புலத்தில். <br /> பல குறிச்சொற்கள் ஒரே நேரத்தில் கமாவுடன் பிரிப்பதன் மூலம் சேர்க்கலாம்: « <i> குறுகிய வாசிப்பு, கட்டாயம் படிக்க வேண்டும் </i> »<br /> முன் வரையறுக்கப்பட்ட ஆபரேட்டர்களைப் பயன்படுத்துவதன் மூலம் சிக்கலான விதிகளை எழுதலாம்: என்றால்« <i> வாசிப்பு நேரம் & gt; = 5 மற்றும் டொமைன் பெயர் = "www.php.net" </i > »பின்னர்« <i> நீண்ட வாசிப்பு, பிஎச்பி </i> »என குறிக்கவும்'
variables_available_title: விதிகளை எழுத எந்த மாறிகள் மற்றும் ஆபரேட்டர்கள் நான் பயன்படுத்தலாம்?
variables_available_description: 'குறிச்சொல் விதிகளை உருவாக்க பின்வரும் மாறிகள் மற்றும் ஆபரேட்டர்கள் பயன்படுத்தப்படலாம்:'
operator_description:
@ -33,8 +33,8 @@ config:
not_equal_to: சமமாக இல்லை…
or: ஒரு விதி அல்லது மற்றொரு
and: ஒரு விதி மற்றும் மற்றொரு விதி
matches: 'ஒரு <i> பொருள் </i> பொருந்தக்கூடிய சோதனைகள் <i> தேடல் </i> (வழக்கு-உணர்திறன்).<br />எடுத்துக்காட்டு: <code>தலைப்பு போட்டிகள் "கால்பந்து"</code>'
notmatches: 'ஒரு <i> பொருள் </i> பொருந்தாத சோதனைகள் ஒரு <i> தேடல் </i> (வழக்கு-பாதுகாப்பற்ற).<br />எடுத்துக்காட்டு: <code>தலைப்பு பெருந்தாதவைகள் "கால்பந்து"</code>'
matches: ஒரு <i> பொருள் </i> பொருந்தக்கூடிய சோதனைகள் <i> தேடல் </i> (வழக்கு-உணர்திறன்).
notmatches: ஒரு <i> பொருள் </i> பொருந்தாத சோதனைகள் ஒரு <i> தேடல் </is> (வழக்கு-பாதுகாப்பற்ற).
then_tag_as_label: பின்னர் குறிக்கவும்
delete_rule_label: அழி
edit_rule_label: தொகு
@ -143,9 +143,9 @@ config:
faq:
title: கேள்விகள்
ignore_origin_rules_definition_title: '"தோற்றம் விதிகளை புறக்கணிக்கவும்" என்றால் என்ன?'
ignore_origin_rules_definition_description: திருப்பிவிடப்பட்ட பிறகு ஒரு மூல முகவரியைத் தானாகவே புறக்கணிக்க அவை வாலபாக் பயன்படுத்துகின்றன. <br /> புதிய நுழைவைப் பெறும்போது ஒரு வழிமாற்றல் ஏற்பட்டால், அனைத்து புறக்கணிப்பு மூல விதிகளும் (<i> பயனர் வரையறுக்கப்பட்ட மற்றும் உதாரணமாக வரையறுக்கப்பட்ட </i>) மூல முகவரியைப் புறக்கணிக்கப் பயன்படுத்தப்படும்.
ignore_origin_rules_definition_description: திருப்பிவிடப்பட்ட பிறகு ஒரு மூல முகவரியை தானாக புறக்கணிக்க அவை வாலபாக் பயன்படுத்துகின்றன. தோற்றம் முகவரியை புறக்கணிக்கப் பயன்படுகிறது.
how_to_use_them_title: அவற்றை எவ்வாறு பயன்படுத்துவது?
how_to_use_them_description: «<i> rss.example.com </i>» என்பதிலிருந்து வரும் நுழைவின் தோற்றத்தை நீங்கள் புறக்கணிக்க விரும்புகிறீர்கள் என்று வைத்துக் கொள்வோம்(<i> திருப்பி விடப்பட்ட பிறகு, உண்மையான முகவரி எடுத்துக்காட்டு.காம் </i>). <br />அவ்வாறான நிலையில், நீங்கள் <i> விதி </i> புலத்தில் «புரவலன் =" rss.example.com "ஐ வைக்க வேண்டும்.
how_to_use_them_description: «<i> rss.example.com </i>» (<i> திருப்பி விடப்பட்ட பிறகு, உண்மையான முகவரி எடுத்துக்காட்டு.காம் </i> என்பதிலிருந்து வரும் நுழைவின் தோற்றத்தை நீங்கள் புறக்கணிக்க விரும்புகிறீர்கள் என்று வைத்துக் கொள்வோம்) .
variables_available_title: விதிகளை எழுத எந்த மாறிகள் மற்றும் ஆபரேட்டர்கள் நான் பயன்படுத்தலாம்?
variables_available_description: 'புறக்கணிப்பு தோற்றம் விதிகளை உருவாக்க பின்வரும் மாறிகள் மற்றும் ஆபரேட்டர்கள் பயன்படுத்தப்படலாம்:'
meaning: பொருள்
@ -156,7 +156,7 @@ config:
operator_description:
label: ஆபரேட்டர்
equal_to: சமமாக…
matches: 'ஒரு <i> பொருள் </i> ஒரு <i> தேடல் </i> (வழக்கு-கவர்ச்சியான) உடன் பொருந்துகிறது. <br />எடுத்துக்காட்டு: <code> _all~ "https?://rss.example.com/foobar/.*"</code>'
matches: ஒரு <i> பொருள் </i> ஒரு <i> தேடல் </i> (வழக்கு-கவர்ச்சியான) உடன் பொருந்துகிறது. foobar /.*"</ குறியீடு>
otp:
page_title: இரண்டு காரணி ஏற்பு
app:
@ -233,14 +233,13 @@ import:
elcurator:
page_title: இறக்குமதி> எல்குரேட்டர்
description: இந்த இறக்குமதியாளர் உங்கள் எல்குரேட்டர் கட்டுரைகள் அனைத்தையும் இறக்குமதி செய்வார்.
how_to: உங்கள் எல்குரேட்டர் ஏற்றுமதியைத் தேர்ந்தெடுத்து பதிவேற்றவும் இறக்குமதி செய்யவும் கீழே உள்ள பொத்தானைக் சொடுக்கு செய்க.
readability:
page_title: இறக்குமதி> வாசிப்பு
description: இந்த இறக்குமதியாளர் உங்கள் வாசிப்பு கட்டுரைகள் அனைத்தையும் இறக்குமதி செய்வார்.
how_to: உங்கள் வாசிப்பு ஏற்றுமதியைத் தேர்ந்தெடுத்து பதிவேற்றவும் இறக்குமதி செய்யவும் கீழே உள்ள பொத்தானைக் சொடுக்கு செய்க.
worker:
enabled: 'இறக்குமதி ஒத்திசைவற்ற முறையில் செய்யப்படுகிறது. இறக்குமதி பணி தொடங்கப்பட்டதும், ஒரு வெளிப்புற தொழிலாளி ஒரு நேரத்தில் வேலைகளை கையாள்வார். தற்போதைய சேவை:'
download_images_warning: உங்கள் கட்டுரைகளுக்கான படங்களைப் பதிவிறக்குவதற்கு உதவினீர்கள். கிளாசிக் இறக்குமதியுடன் இணைந்து, தொடர பல ஆண்டுகள் ஆகலாம் (அல்லது தோல்வியுற்றிருக்கலாம்). பிழைகளைத் தவிர்க்க ஒத்திசைவற்ற இறக்குமதியை இயக்குவதற்கு நாங்கள் <strong> கடுமையாகப் பரிந்துரைக்கிறோம் </strong>.
download_images_warning: உங்கள் கட்டுரைகளுக்கான படங்களை பதிவிறக்குவதற்கு உதவினீர்கள். கிளாசிக் இறக்குமதியுடன் இணைந்து, தொடர பல ஆண்டுகள் ஆகலாம் (அல்லது தோல்வியுற்றிருக்கலாம்). பிழைகளைத் தவிர்க்க ஒத்திசைவற்ற இறக்குமதியை இயக்குவதற்கு நாங்கள் <strong> கடுமையாக பரிந்துரைக்கிறோம் </strong.
firefox:
page_title: இறக்குமதி> பயர்பாக்ச்
description: இந்த இறக்குமதியாளர் உங்கள் பயர்பாக்ச் புக்மார்க்குகளை இறக்குமதி செய்வார். உங்கள் புக்மார்க்குகளுக்கு (Ctrl+Shift+O), பின்னர் "இறக்குமதி மற்றும் காப்புப்பிரதி" க்குச் செல்லுங்கள், "காப்புப்பிரதி…" என்பதைத் தேர்வுசெய்க. நீங்கள் ஒரு சாதொபொகு கோப்பைப் பெறுவீர்கள்.
@ -261,14 +260,6 @@ import:
page_title: இறக்குமதி> பாக்கெட் உஉகுமொ
description: இந்த இறக்குமதியாளர் உங்கள் அனைத்து பாக்கெட் புக்மார்க்குகளையும் (HTML ஏற்றுமதி வழியாக) இறக்குமதி செய்வார். Https://getpocket.com/export க்குச் சென்று, பின்னர் உஉகுமொ கோப்பை ஏற்றுமதி செய்யுங்கள். ஒரு உஉகுமொ கோப்பு பதிவிறக்கம் செய்யப்படும் ("RIL_EXPORT.HTML" போன்றவை).
how_to: புக்மார்க்கு காப்புப்பிரதி கோப்பைத் தேர்ந்தெடுத்து அதை இறக்குமதி செய்ய கீழே உள்ள பொத்தானைக் சொடுக்கு செய்க. அனைத்து கட்டுரைகளையும் பெற வேண்டியிருப்பதால் செயல்முறை நீண்ட நேரம் ஆகலாம் என்பதை நினைவில் கொள்க.
omnivore:
how_to: தயவுசெய்து உங்கள் சர்வவல்லமையுள்ள ஏற்றுமதியை அவிழ்த்து, பின்னர் "மெட்டாடேட்டா_எக்ச்_.டி.இ_ஒய்.சோன்" என்ற பெயரில் ஒவ்வொரு சாதொபொகு கோப்பையும் ஒவ்வொன்றாக பதிவேற்றவும்.
page_title: இறக்குமதி> சர்வவல்லவர்
description: இந்த இறக்குமதியாளர் உங்கள் சர்வவல்லமையுள்ள அனைத்து கட்டுரைகளையும் இறக்குமதி செய்வார்.
pocket_csv:
description: இந்த இறக்குமதியாளர் உங்கள் பாக்கெட் புக்மார்க்குகள் (சி.எச்.வி ஏற்றுமதி வழியாக) இறக்குமதி செய்வார். Https://getpocket.com/export க்குச் சென்று, பின்னர் கோப்பை ஏற்றுமதி செய்யுங்கள். ஒரு சிப் கோப்பு பதிவிறக்கம் செய்யப்படும் ("பாக்கெட்.சிப்" போன்றவை). அதைப் பிரித்தெடுக்கவும், "Part_000000.CSV" எனப்படும் காபிம கோப்பைப் பெறுவீர்கள்.
how_to: புக்மார்க்கு காப்புப்பிரதி கோப்பைத் தேர்ந்தெடுத்து அதை இறக்குமதி செய்ய கீழே உள்ள பொத்தானைக் சொடுக்கு செய்க. அனைத்து கட்டுரைகளையும் பெற வேண்டியிருப்பதால் செயல்முறை நீண்ட நேரம் ஆகலாம் என்பதை நினைவில் கொள்க.
page_title: இறக்குமதி> பாக்கெட் கபிம
developer:
howto:
description:
@ -279,7 +270,7 @@ developer:
paragraph_4: 'இப்போது, உங்கள் கிள்ளாக்கை உருவாக்கவும் (கிளையன்ட்_ஐடி, கிளையன்ட்_செக்ரெட், பயனர்பெயர் மற்றும் கடவுச்சொல்லை நல்ல மதிப்புகளுடன் மாற்றவும்):'
paragraph_6: 'பநிஇ இறுதிப்புள்ளிக்கு அழைப்பு செய்ய அணுகல்_டோகன் பயனுள்ளதாக இருக்கும். உதாரணமாக:'
paragraph_7: இந்த அழைப்பு உங்கள் பயனருக்கான அனைத்து உள்ளீடுகளையும் திருப்பித் தரும்.
paragraph_8: எல்லா பநிஇ இறுதிப் புள்ளிகளையும் நீங்கள் காண விரும்பினால், <a href="%link%">எங்கள் பநிஇ ஆவணங்களுக்கு </a> ஐப் பார்க்கலாம்.
paragraph_8: எல்லா பநிஇ இறுதிப் புள்ளிகளையும் நீங்கள் காண விரும்பினால், எங்கள் பநிஇ ஆவணங்களுக்கு </a> க்கு <a href = "%இணைப்பு%"> ஐப் பார்க்கலாம்.
back: பின்
page_title: பநிஇ கிளையண்ட்ச் மேனேச்மென்ட்> எனது முதல் பயன்பாட்டை எவ்வாறு உருவாக்குவது
page_title: பநிஇ கிளையண்ட்ச் மேலாண்மை
@ -391,7 +382,6 @@ flashes:
tagging_rules_not_imported: குறிச்சொல் விதிகளை இறக்குமதி செய்யும் போது பிழை
ignore_origin_rules_deleted: தோற்ற விதி நீக்கப்பட்டது
ignore_origin_rules_updated: தோற்ற விதி புதுப்பிக்கப்பட்டது
otp_code_invalid: தவறான இரண்டு காரணி அங்கீகாரக் குறியீடு
entry:
notice:
entry_already_saved: நுழைவு ஏற்கனவே %தேதியில் சேமிக்கப்பட்டது %
@ -618,7 +608,7 @@ howto:
description: இந்த படிவத்திற்கு நன்றி
browser_addons:
firefox: பயர்பாக்ச் addon
chrome: நிறமி செருகுநிரல்
chrome: Chrome addon
opera: ஓபரா துணை
mobile_apps:
android:
@ -707,7 +697,6 @@ quickstart:
github: கிட்அப்பில்
email: மின்னஞ்சல் மூலம்
gitter: கிட்டரில்
matrix: மேட்ரிக்சில்
tag:
confirm:
delete: '% பெயர் % குறிச்சொல்லை நீக்கவும்'
@ -721,7 +710,7 @@ tag:
add: கூட்டு
placeholder: கமாவால் பிரிக்கப்பட்ட பல குறிச்சொற்களை நீங்கள் சேர்க்கலாம்.
export:
footer_template: '<div style="text-align:center;"> <p> %முறையுடன் வாலபாக் தயாரித்த </p> <p> தயவுசெய்து <a href="https://github.com/wallabag/wallabag/issues"> ஒரு சிக்கல் </a>ஐத் திறக்கவும், உங்கள் சாதனத்தில் இந்த மின் புத்தகத்தின் காட்சியில் சிக்கல் இருந்தால். </p> </div>'
footer_template: '<div சூல் தண்டு = "text-align: மையம்;"> <p> %முறையுடன் வாலபாக் தயாரித்த </p> <p> தயவுசெய்து <a href = "https://github.com/wallabag/wallabag/issues ஐத் திறக்கவும் "> ஒரு சிக்கல் </a> உங்கள் சாதனத்தில் இந்த மின் புத்தகத்தின் காட்சியில் சிக்கல் இருந்தால். </p> </viv>'
unknown: தெரியவில்லை
site_credential:
page_title: தள நற்சான்றிதழ் மேலாண்மை

View File

@ -1 +0,0 @@
{}

View File

@ -1 +0,0 @@
{}

View File

@ -2,9 +2,9 @@ auth_code:
mailer:
body:
signature: Het wallabag team
support: 'Twijfel niet om contact met ons op te nemen als je problemen ervaart:'
support: 'Twijfel niet om contact met ons op te nemen als u problemen ervaart:'
second_para: 'Dit is de code:'
first_para: Omdat tweestapsverificatie verplicht is voor je wallabag account en een nieuw apparaat dit zojuist gebruikt heeft, sturen we je een code ter verificatie.
first_para: Omdat twee-factor-authenticatie verplicht is voor uw wallabag account en een nieuw apparaat dit zojuist gebruikt heeft, sturen we u een code ter verificatie.
hello: Hallo %user%,
subject: wallabag authenticatiecode
on: aan

1797
yarn.lock

File diff suppressed because it is too large Load Diff