From 3a3c6b866b52721431bed22426d9abfcd0d2dfe0 Mon Sep 17 00:00:00 2001
From: Paulino Michelazzo
Date: Tue, 18 Oct 2016 20:51:31 +0200
Subject: [PATCH 01/42] Portuguese (Brazilian) translation
This the Portuguese (Brazilian) for the Wallaby v2.
---
.../translations/CraueConfigBundle.pt.yml | 29 ++
.../translations/FOSUserBundle.pt.yml | 2 +
.../Resources/translations/messages.pt.yml | 423 ++++++++++++++++++
.../Resources/translations/validators.pt.yml | 6 +
4 files changed, 460 insertions(+)
create mode 100644 app/Resources/CraueConfigBundle/translations/CraueConfigBundle.pt.yml
create mode 100644 app/Resources/FOSUserBundle/translations/FOSUserBundle.pt.yml
create mode 100644 src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml
create mode 100644 src/Wallabag/CoreBundle/Resources/translations/validators.pt.yml
diff --git a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.pt.yml b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.pt.yml
new file mode 100644
index 000000000..e82604220
--- /dev/null
+++ b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.pt.yml
@@ -0,0 +1,29 @@
+download_pictures: Download imagens no seu servidor
+carrot: Habilitar compartilhamento para o Carrot
+diaspora_url: URL Diaspora, se o serviço está habilitado
+export_epub: Habilita exportação para ePub
+export_mobi: Habilita exportação para .mobi
+export_pdf: Habilita exportação para PDF
+export_csv: Habilita exportação para CSV
+export_json: Habilita exportação para JSON
+export_txt: Habilita exportação para TXT
+export_xml: Habilita exportação para XML
+pocket_consumer_key: Chave de consumidor do Pocket para importar conteúdo (https://getpocket.com/developer/docs/authentication)
+shaarli_url: URL Shaarli, se o serviço está habilitado
+share_diaspora: Habilitar compartilhamento para o Diaspora
+share_mail: Habilitar compartilhamento por e-mail
+share_shaarli: Habilitar compartilhamento para o Shaarli
+share_twitter: Habilitar compartilhamento para o Twitter
+show_printlink: Mostrar um link para imprimir o conteúdo
+wallabag_support_url: URL de Suporte do wallabag
+wallabag_url: URL de *sua* instância do wallabag
+entry: "artigo"
+export: "exportar"
+import: "importar"
+misc: "misc"
+modify_settings: "aplicar"
+piwik_host: Host de seu website Piwik
+piwik_site_id: ID de seu website Piwik
+piwik_enabled: Habilitar Piwik
+demo_mode_enabled: "Habilitar modo demo? (somente usado para o demo público do wallabag)"
+demo_mode_username: "Usuário demo"
diff --git a/app/Resources/FOSUserBundle/translations/FOSUserBundle.pt.yml b/app/Resources/FOSUserBundle/translations/FOSUserBundle.pt.yml
new file mode 100644
index 000000000..85eadfd87
--- /dev/null
+++ b/app/Resources/FOSUserBundle/translations/FOSUserBundle.pt.yml
@@ -0,0 +1,2 @@
+Login: "Login"
+Enter your email address below and we'll send you password reset instructions.: "Digite seu endereço de e-mail para enviarmos as instruções de recupeção de sua senha."
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml
new file mode 100644
index 000000000..df5adb758
--- /dev/null
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml
@@ -0,0 +1,423 @@
+security:
+ login:
+ page_title: 'Bem vindo ao wallabag!'
+ keep_logged_in: 'Mantenha-me autenticado'
+ forgot_password: 'Esqueceu a senha?'
+ submit: 'Login'
+ register: 'Registre-se'
+ username: 'Nome de usuário'
+ password: 'Senha'
+ cancel: 'Cancelar'
+ resetting:
+ description: 'Digite seu endereço de e-mail abaixo e enviaremos instruções para resetar sua senha.'
+ register:
+ page_title: 'Criar uma conta'
+ go_to_account: 'Ir para sua conta'
+
+menu:
+ left:
+ unread: 'Não lido'
+ starred: 'Destacado'
+ archive: 'Arquivo'
+ all_articles: 'Todas as entradas'
+ config: 'Configurações'
+ tags: 'Tags'
+ internal_settings: 'Configurações Internas'
+ import: 'Importar'
+ howto: 'How to'
+ developer: 'Desenvolvedor'
+ logout: 'Sair'
+ about: 'Sobre'
+ search: 'Pesquisa'
+ save_link: 'Salvar um link'
+ back_to_unread: 'Voltar para os artigos não lidos'
+ top:
+ add_new_entry: 'Adicionar uma nova entrada'
+ search: 'Pesquisa'
+ filter_entries: 'Filtrar entradas'
+ export: 'Exportar'
+ search_form:
+ input_label: 'Digite aqui sua pesquisa'
+
+footer:
+ wallabag:
+ elsewhere: 'Leve o wallabag com você'
+ social: 'Social'
+ powered_by: 'provido por'
+ about: 'Sobre'
+
+config:
+ page_title: 'Config'
+ tab_menu:
+ settings: 'Configurações'
+ rss: 'RSS'
+ user_info: 'Informação do Usuário'
+ password: 'Senha'
+ rules: 'Regras de tags'
+ new_user: 'Adicionar um usuário'
+ form:
+ save: 'Salvar'
+ form_settings:
+ theme_label: 'Tema'
+ items_per_page_label: 'Itens por página'
+ language_label: 'Idioma'
+ reading_speed:
+ label: 'Velocidade de leitura'
+ help_message: 'Você pode usar ferramentas online para estimar sua velocidade de leitura:'
+ 100_word: 'Posso ler ~100 palavras por minuto'
+ 200_word: 'Posso ler ~200 palavras por minuto'
+ 300_word: 'Posso ler ~300 palavras por minuto'
+ 400_word: 'Posso ler ~400 palavras por minuto'
+ form_rss:
+ description: 'Feeds RSS providos pelo wallabag permitem que você leia seus artigos salvos em seu leitor de RSS favorito. Você precisa gerar um token primeiro.'
+ token_label: 'Token RSS'
+ no_token: 'Nenhum Token'
+ token_create: 'Criar seu token'
+ token_reset: 'Gerar novamente seu token'
+ rss_links: 'Links RSS'
+ rss_link:
+ unread: 'não lido'
+ starred: 'destacado'
+ archive: 'arquivado'
+ rss_limit: 'Número de itens no feed'
+ form_user:
+ two_factor_description: 'Habilitar autenticação de dois passos significa que você receberá um e-mail com um código a cada nova conexão desconhecida.'
+ name_label: 'Nome'
+ email_label: 'E-mail'
+ twoFactorAuthentication_label: 'Autenticação de dois passos'
+ form_password:
+ old_password_label: 'Senha atual'
+ new_password_label: 'Nova senha'
+ repeat_new_password_label: 'Repita a nova senha'
+ form_rules:
+ if_label: 'if'
+ then_tag_as_label: 'então coloque a tag'
+ delete_rule_label: 'apagar'
+ rule_label: 'Regras'
+ tags_label: 'Tags'
+ faq:
+ title: 'FAQ'
+ tagging_rules_definition_title: 'O que as « regras de tags » significam?'
+ tagging_rules_definition_description: 'São regras usadas pelo Wallabag para automaticamente adicionar tags em novos artigos.
Cada vez que um novo artigo é adicionado, todas as regras de tags podem ser usadas para adicionar as tags que você configurou, ajudando-o com o problema de classificar manualmente seus artigos.'
+ how_to_use_them_title: 'Como eu as utilizo?'
+ how_to_use_them_description: 'Vamos dizer que você deseja adicionar a tag « leitura rápida » quando o tempo de leitura for menor que 3 minutos.
Neste caso, você deve « readingTime <= 3 » no campo Regra e « leitura rápida » no campo Tags.
Diversas tags podem ser adicionadas simultâneamente separando-as com vírgula: « leitura rápida, precisa ser lido »
Regras complexas podem ser escritas usando os seguintes operadores pré-definidos: if « readingTime >= 5 AND domainName = "github.com" » então adicione a tag « leitura longa, github »'
+ variables_available_title: 'Quais variáveis e operadores eu posso usar para escrever regras?'
+ variables_available_description: 'As seguintes variáveis e operadores podem ser usados para criar regras de tags:'
+ meaning: 'Meaning'
+ variable_description:
+ label: 'Variável'
+ title: 'Título da entrada'
+ url: 'URL da entrada'
+ isArchived: 'Se a entrada está arquivada ou não'
+ isDestacado: 'Se a entrada está destacada ou não'
+ content: 'O conteúdo da entrada'
+ language: 'O idioma da entrada'
+ mimetype: 'O mime-type da entrada'
+ readingTime: 'O tempo estimado de leitura da entrada, em minutos'
+ domainName: 'O domínio da entrada'
+ operator_description:
+ label: 'Operador'
+ less_than: 'Menor que...'
+ strictly_less_than: 'Estritamente menor que...'
+ greater_than: 'Maior que...'
+ strictly_greater_than: 'Estritamente maior que...'
+ equal_to: 'Igual a...'
+ not_equal_to: 'Diferente de...'
+ or: 'Uma regra OU outra'
+ and: 'Uma regra E outra'
+ matches: 'Testa que um assunto corresponde a uma pesquisa (maiúscula ou minúscula).
Exemplo: título corresponde a "futebol"
'
+ form_new_user:
+ username_label: 'Nome de Usuário'
+ password_label: 'Senha'
+ repeat_new_password_label: 'Repita a nova senha'
+ plain_password_label: '????'
+ email_label: 'E-mail'
+
+entry:
+ page_titles:
+ unread: 'Entradas não lidas'
+ starred: 'Entradas destacadas'
+ archived: 'Entradas arquivadas'
+ filtered: 'Entradas filtradas'
+ list:
+ number_on_the_page: '{0} Não existem entradas.|{1} Existe uma entrada.|]1,Inf[ Existem %count% entradas.'
+ reading_time: 'tempo estimado de leitura'
+ reading_time_minutes: 'tempo estimado de leitura: %readingTime% min'
+ reading_time_less_one_minute: 'tempo estimado de leitura: < 1 min'
+ reading_time_minutes_short: '%readingTime% min'
+ reading_time_less_one_minute_short: '< 1 min'
+ original_article: 'original'
+ toogle_as_read: 'Marcar como lido'
+ toogle_as_star: 'Marcar como destacado'
+ delete: 'Apagar'
+ export_title: 'Exportar'
+ filters:
+ title: 'Filtros'
+ status_label: 'Status'
+ archived_label: 'Arquivado'
+ starred_label: 'Destacado'
+ unread_label: 'Não Lido'
+ preview_picture_label: 'Possui uma imagem de preview'
+ preview_picture_help: 'Imagem de preview'
+ language_label: 'Idioma'
+ reading_time:
+ label: 'Tempo de leitura em minutos'
+ from: 'de'
+ to: 'para'
+ domain_label: 'Nome do domínio'
+ created_at:
+ label: 'Data de criação'
+ from: 'de'
+ to: 'para'
+ action:
+ clear: 'Limpar'
+ filter: 'Filtro'
+ view:
+ left_menu:
+ back_to_top: 'Voltar ao topo'
+ back_to_homepage: 'Voltar'
+ set_as_read: 'Marcar como lido'
+ set_as_unread: 'Marcar como não lido'
+ set_as_starred: 'Alternar destaque'
+ view_original_article: 'Artigo original'
+ re_fetch_content: 'Recapturar o conteúdo'
+ delete: 'Apagar'
+ add_a_tag: 'Adicionar uma tag'
+ share_content: 'Compartilhar'
+ share_email_label: 'E-mail'
+ download: 'Download'
+ print: 'Imprimir'
+ problem:
+ label: 'Problemas?'
+ description: 'este artigo aparece errado?'
+ edit_title: 'Editar título'
+ original_article: 'original'
+ annotations_on_the_entry: '{0} Sem anotações|{1} Uma anotação|]1,Inf[ %nbAnnotations% anotações'
+ created_at: 'Data de criação'
+ new:
+ page_title: 'Salvar nova entrada'
+ placeholder: 'http://website.com'
+ form_new:
+ url_label: Url
+ edit:
+ page_title: 'Editar uma entrada'
+ title_label: 'Título'
+ url_label: 'Url'
+ is_public_label: 'Público'
+ save_label: 'Salvar'
+
+about:
+ page_title: 'Sobre'
+ top_menu:
+ who_behind_wallabag: 'Quem está por trás do wallabag'
+ getting_help: 'Obtendo ajuda'
+ helping: 'Ajudando o wallabag'
+ contributors: 'Contribuidores'
+ third_party: 'Bibliotecas terceiras'
+ who_behind_wallabag:
+ developped_by: 'Desenvolvido por'
+ website: 'website'
+ many_contributors: 'E muitos outros contribuidores ♥ no Github'
+ project_website: 'Website do projeto'
+ license: 'Licença'
+ version: 'Versão'
+ getting_help:
+ documentation: 'Documentação'
+ bug_reports: 'Informar bugs'
+ support: 'Em nosso site de suporte ou no GitHub'
+ helping:
+ description: 'wallabag é livre e software livre. Você pode nos ajudar:'
+ by_contributing: 'contribuindo com o projeto:'
+ by_contributing_2: 'uma lista de todas as nossas necessidades'
+ by_paypal: 'via Paypal'
+ contributors:
+ description: 'Obrigado por contribuir com a aplicação web wallabag'
+ third_party:
+ description: 'Aqui está a lista de bibliotecas terceiras usadas no wallabag (com suas licenças):'
+ package: 'Pacote'
+ license: 'Licença'
+
+howto:
+ page_title: 'How to'
+ page_description: 'Existem diferentes formas de salvar um artigo:'
+ top_menu:
+ browser_addons: 'Extensões de navegadores'
+ mobile_apps: 'App's móveis'
+ bookmarklet: 'Bookmarklet'
+ form:
+ description: 'Obrigado por este formulário'
+ browser_addons:
+ firefox: 'Extensão padrão do Firefox'
+ chrome: 'Extensão do Chrome'
+ mobile_apps:
+ android:
+ via_f_droid: 'via F-Droid'
+ via_google_play: 'via Google Play'
+ ios: 'na iTunes Store'
+ windows: 'na Microsoft Store'
+ bookmarklet:
+ description: 'Arraste e solve este link na sua barra de favoritos:'
+
+quickstart:
+ page_title: 'Começo Rápido'
+ intro:
+ title: 'Bem-vindo ao wallabag!'
+ paragraph_1: 'Nós podemos acompanhar você em sua visita ao wallabag e mostrar algumas funcionalidades que podem lhe interessar.'
+ paragraph_2: 'Siga-nos!'
+ configure:
+ title: 'Configurar a aplicação'
+ language: 'Alterar idioma e design'
+ rss: 'Habilitar feeds RSS'
+ tagging_rules: 'Escrever regras para acrescentar tags automaticamente em seus artigos'
+ admin:
+ title: 'Administração'
+ description: 'Como administrador você tem privilégios no wallabag. Você pode:'
+ new_user: 'Criar um novo usuário'
+ analytics: 'Configurar o analytics'
+ sharing: 'habilitar alguns parâmetros para compartilhamento de artigos'
+ export: 'Configurar exportação'
+ import: 'Configurar importação'
+ first_steps:
+ title: 'Primeiros passos'
+ new_article: 'Salvar seu primeiro artigo'
+ unread_articles: 'E classificá-lo!'
+ migrate:
+ title: 'Migrar de um serviço existente'
+ description: 'Você está usando um outro serviço? Nós podemos ajudá-lo a recuperar seus dados para o wallabag.'
+ pocket: 'Migrar do Pocket'
+ wallabag_v1: 'Migrar do wallabag v1'
+ wallabag_v2: 'Migrar do wallabag v2'
+ developer:
+ title: 'Desenvolvedores'
+ create_application: 'Criar sua aplicação terceira'
+ docs:
+ title: 'Documentação completa'
+ annotate: 'Anotar seu artigo'
+ export: 'Converter seu artigo em ePUB ou PDF'
+ search_filters: 'veja coo você pode encontrar um artigo usanndo o motor de busca e filtros'
+ fetching_errors: 'O que eu posso fazer quando um artigo encontra erros na recuperação?'
+ all_docs: 'E outros muitos artigos!'
+ support:
+ title: 'Suporte'
+ description: 'Se você precisa de ajuda, nós estamos aqui.'
+ github: 'No GitHub'
+ email: 'Por e-mail'
+ gitter: 'No Gitter'
+
+tag:
+ page_title: 'Tags'
+ list:
+ number_on_the_page: '{0} Não existem tags.|{1} Uma tag.|]1,Inf[ Existem %count% tags.'
+
+import:
+ page_title: 'Importar'
+ page_description: 'Bem-vindo ao importador do wallabag. Por favo selecione o serviço do qual deseja migrar.'
+ action:
+ import_contents: 'Importar conteúdos'
+ form:
+ mark_as_read_title: 'Marcar todos como lidos?'
+ mark_as_read_label: 'Marcar todas as entradas importadas como lidas'
+ file_label: 'Arquivo'
+ save_label: 'Carregar arquivo'
+ pocket:
+ page_title: 'Importar > Pocket'
+ description: 'Com este importador você importa todos os seus dados do Pocket. O Pocket não nos permite recuperar o conteúdo de seu serviço, então o conteúdo que pode ser lido é recarregado pelo wallabag.'
+ config_missing:
+ description: 'O importador do Pocket não está configurado.'
+ admin_message: 'Você precisa definir uma %keyurls%a pocket_consumer_key%keyurle%.'
+ user_message: 'Seu administrador do servidor precisa definir uma chave de API para o Pocket.'
+ authorize_message: 'Você pode importar seus dados de sua conta do Pocket. Você somente precisa clicar no botão abaixo e autorizar a aplicação a conectar-se ao getpocket.com.'
+ connect_to_pocket: 'Conecte ao Pocket e importe os dados'
+ wallabag_v1:
+ page_title: 'Importar > Wallabag v1'
+ description: 'Com este importador você importa todos os seus artigos do wallabag v1. Na sua página de configuração, clique em "JSON export" na opção "Export your wallabag data". Você irá criar um arquivo "wallabag-export-1-xxxx-xx-xx.json".'
+ how_to: 'Por favor, selecione seu exportador wallabag e clique no botão abaixo para carregar e importar.'
+ wallabag_v2:
+ page_title: 'Importar > Wallabag v2'
+ description: 'Com este importador você importa todos os seus artigos do wallabag v2. Vá em Todos os artigos e então, na barra lateral de exportação, clique em "JSON". Você irá criar um arquivo "All articles.json".'
+
+developer:
+ page_title: 'Desenvolvedor'
+ welcome_message: 'Bem-vindo a API do wallabag'
+ documentation: 'Documentação'
+ how_to_first_app: 'Como criar minha primeira aplicação'
+ full_documentation: 'Ver a documentação completa da API'
+ list_methods: 'Lista de métodos da API'
+ clients:
+ title: 'Clientes'
+ create_new: 'Criar um novo cliente'
+ existing_clients:
+ title: 'Clientes existentes'
+ field_id: 'ID do cliente'
+ field_secret: 'Chave do cliente'
+ field_uris: 'URIs de redirecionamento'
+ field_grant_types: 'Tipo permitido'
+ no_client: 'Nenhum cliente até agora.'
+ remove:
+ warn_message_1: 'Você tem permissão pare remover este cliente. Esta ação é IRREVERSÍVEL !'
+ warn_message_2: 'Se você remover isso, todo o aplicativo configurado com este cliente não poderá se autenticar no seu wallabag.'
+ action: 'Remover este cliente'
+ client:
+ page_title: 'Desenvolvedor > Novo cliente'
+ page_description: 'Você está prestes a criar um novo cliente. Por favor preencha o campo abaixo para a URI de redirecionamento de sua aplicação.'
+ form:
+ redirect_uris_label: 'URIs de redirecionamento'
+ save_label: 'Criar um novo cliente'
+ action_back: 'Voltar'
+ client_parameter:
+ page_title: 'Desenvolvedor > Parâmetros de clientes'
+ page_description: 'Aqui estão os parâmetros de seus clientes.'
+ field_id: 'ID do cliente'
+ field_secret: 'Chave do cliente'
+ back: 'Voltar'
+ read_howto: 'Leia o how-to "Criar minha primeira aplicação"'
+ howto:
+ page_title: 'Desenvolvedor > Criar minha primeira aplicação'
+ description:
+ paragraph_1: 'Os seguintes comandos fazem uso da biblioteca HTTPie. Tenha certeza que ela está instalada em seu servidor antes de usá-la.'
+ paragraph_2: 'Você precisa de um token para a comunicação entre sua aplicação terceira e a API do wallabag.'
+ paragraph_3: 'Para criar este token, você precisa criar um novo cliente.'
+ paragraph_4: 'Agora, crie seu token (altere client_id, client_secret, username e password com os valores corretos):'
+ paragraph_5: 'A API pode retornar uma resposta como essa:'
+ paragraph_6: 'O access_token é utilizável para fazer uma chamada para o endpoint da API. Por exemplo:'
+ paragraph_7: 'Esta chamada pode retornar todas as entradas de seu usuário.'
+ paragraph_8: 'Se você deseja ver todos os endpoints da API, dê uma olhada em nossa documentação da API.'
+ back: 'Voltar'
+
+flashes:
+ config:
+ notice:
+ config_saved: 'Configiração salva. Alguns parâmetros podem ser considerados depois da desconexão.'
+ password_updated: 'Senha atualizada'
+ password_not_updated_demo: 'Em modo de demonstração, você não pode alterar a senha deste usuário.'
+ user_updated: 'Informação atualizada'
+ rss_updated: 'Informação de RSS atualizada'
+ tagging_rules_updated: 'Regras de tags atualizadas'
+ tagging_rules_deleted: 'Regra de tag apagada'
+ user_added: 'Usuário "%username%" adicionado'
+ rss_token_updated: 'Token RSS atualizado'
+ entry:
+ notice:
+ entry_already_saved: 'Entrada já foi salva em %date%'
+ entry_saved: 'Entrada salva'
+ entry_saved_failed: 'Failed to save entry'
+ entry_updated: 'Entrada atualizada'
+ entry_reloaded: 'Entrada recarregada'
+ entry_reload_failed: 'Falha em recarregar a entrada'
+ entry_archived: 'Entrada arquivada'
+ entry_unarchived: 'Entrada desarquivada'
+ entry_starred: 'Entrada destacada'
+ entry_unstarred: 'Entrada não destacada'
+ entry_deleted: 'Entrada apagada'
+ tag:
+ notice:
+ tag_added: 'Tag adicionada'
+ import:
+ notice:
+ failed: 'Importação falhou, por favor tente novamente.'
+ failed_on_file: 'Erro ao processar a importação. Por favor verifique seu arquivo de importação.'
+ summary: 'relatório de importação: %imported% importados, %skipped% já existem.'
+ developer:
+ notice:
+ client_created: 'Novo cliente criado.'
+ client_deleted: 'Cliente removido'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/validators.pt.yml b/src/Wallabag/CoreBundle/Resources/translations/validators.pt.yml
new file mode 100644
index 000000000..cdfa46a6d
--- /dev/null
+++ b/src/Wallabag/CoreBundle/Resources/translations/validators.pt.yml
@@ -0,0 +1,6 @@
+validator:
+ password_must_match: 'The password fields must match.'
+ password_too_short: 'Password should by at least 8 chars long'
+ password_wrong_value: 'Wrong value for your current password'
+ item_per_page_too_high: 'This will certainly kill the app'
+ rss_limit_too_hight: 'This will certainly kill the app'
From 5d6cffedb19e6d6106f519e378d0e91248bf6be9 Mon Sep 17 00:00:00 2001
From: Paulino Michelazzo
Date: Wed, 19 Oct 2016 19:25:48 +0200
Subject: [PATCH 02/42] Update Portuguese (Brazilian) translation
Adding the config.yml on the package.
---
app/config/config.yml | 1 +
1 file changed, 1 insertion(+)
diff --git a/app/config/config.yml b/app/config/config.yml
index 5127c8cf7..0b4494d3d 100644
--- a/app/config/config.yml
+++ b/app/config/config.yml
@@ -44,6 +44,7 @@ wallabag_core:
es: 'Español'
oc: 'Occitan'
it: 'Italiano'
+ pt: 'Português'
items_on_page: 12
theme: material
language: '%locale%'
From a42cc6ff89d8139bbbf0cc1cdea455f3c7f84ec4 Mon Sep 17 00:00:00 2001
From: Paulino Michelazzo
Date: Thu, 20 Oct 2016 08:57:24 +0200
Subject: [PATCH 03/42] Update validators.pt.yml file
Some missed strings translated.
---
.../Resources/translations/validators.pt.yml | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/Wallabag/CoreBundle/Resources/translations/validators.pt.yml b/src/Wallabag/CoreBundle/Resources/translations/validators.pt.yml
index cdfa46a6d..498908306 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/validators.pt.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/validators.pt.yml
@@ -1,6 +1,6 @@
validator:
- password_must_match: 'The password fields must match.'
- password_too_short: 'Password should by at least 8 chars long'
- password_wrong_value: 'Wrong value for your current password'
- item_per_page_too_high: 'This will certainly kill the app'
- rss_limit_too_hight: 'This will certainly kill the app'
+ password_must_match: 'Os campos de senha devem coincidir.'
+ password_too_short: 'A senha deve ter pelo menos 8 caracteres'
+ password_wrong_value: 'A senha atual informada está errada'
+ item_per_page_too_high: 'Certamente isso pode matar a aplicação'
+ rss_limit_too_hight: 'Certamente isso pode matar a aplicação'
From b669224762f876b877b14e5f564ae3a1007953a4 Mon Sep 17 00:00:00 2001
From: Jeremy Benoist
Date: Wed, 19 Oct 2016 20:10:42 +0200
Subject: [PATCH 04/42] Validate ALL translations files
---
.travis.yml | 2 ++
1 file changed, 2 insertions(+)
diff --git a/.travis.yml b/.travis.yml
index c7bb05fb1..a8f6a7441 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -75,4 +75,6 @@ script:
- if [[ $VALIDATE_TRANSLATION_FILE = '' ]]; then phpunit -v ; fi;
- if [[ $CS_FIXER = run ]]; then php bin/php-cs-fixer fix src/ --verbose --dry-run ; fi;
- if [[ $VALIDATE_TRANSLATION_FILE = run ]]; then php bin/console lint:yaml src/Wallabag/CoreBundle/Resources/translations -v ; fi;
+ - if [[ $VALIDATE_TRANSLATION_FILE = run ]]; then php bin/console lint:yaml app/Resources/CraueConfigBundle/translations -v ; fi;
+ - if [[ $VALIDATE_TRANSLATION_FILE = run ]]; then php bin/console lint:yaml app/Resources/FOSUserBundle/translations -v ; fi;
- if [[ $ASSETS = build ]]; then ./node_modules/grunt-cli/bin/grunt tests; fi;
From 1cad9416c9fda6a99aa03213844341c20bb84518 Mon Sep 17 00:00:00 2001
From: Jeremy Benoist
Date: Wed, 19 Oct 2016 20:11:10 +0200
Subject: [PATCH 05/42] Update Portuguese translations
---
.../Resources/translations/messages.pt.yml | 87 +++++++++++++++++--
1 file changed, 78 insertions(+), 9 deletions(-)
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml
index df5adb758..30e8b00ec 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml
@@ -31,6 +31,7 @@ menu:
search: 'Pesquisa'
save_link: 'Salvar um link'
back_to_unread: 'Voltar para os artigos não lidos'
+ # users_management: 'Users management'
top:
add_new_entry: 'Adicionar uma nova entrada'
search: 'Pesquisa'
@@ -45,6 +46,7 @@ footer:
social: 'Social'
powered_by: 'provido por'
about: 'Sobre'
+ # stats: Since %user_creation% you read %nb_archives% articles. That is about %per_day% a day!
config:
page_title: 'Config'
@@ -68,6 +70,7 @@ config:
200_word: 'Posso ler ~200 palavras por minuto'
300_word: 'Posso ler ~300 palavras por minuto'
400_word: 'Posso ler ~400 palavras por minuto'
+ # pocket_consumer_key_label: Consumer key for Pocket to import contents
form_rss:
description: 'Feeds RSS providos pelo wallabag permitem que você leia seus artigos salvos em seu leitor de RSS favorito. Você precisa gerar um token primeiro.'
token_label: 'Token RSS'
@@ -93,6 +96,7 @@ config:
if_label: 'if'
then_tag_as_label: 'então coloque a tag'
delete_rule_label: 'apagar'
+ # edit_rule_label: 'edit'
rule_label: 'Regras'
tags_label: 'Tags'
faq:
@@ -126,12 +130,6 @@ config:
or: 'Uma regra OU outra'
and: 'Uma regra E outra'
matches: 'Testa que um assunto corresponde a uma pesquisa (maiúscula ou minúscula).
Exemplo: título corresponde a "futebol"
'
- form_new_user:
- username_label: 'Nome de Usuário'
- password_label: 'Senha'
- repeat_new_password_label: 'Repita a nova senha'
- plain_password_label: '????'
- email_label: 'E-mail'
entry:
page_titles:
@@ -139,11 +137,14 @@ entry:
starred: 'Entradas destacadas'
archived: 'Entradas arquivadas'
filtered: 'Entradas filtradas'
+ # filtered_tags: 'Filtered by tags'
+ # untagged: 'Untagged entries'
list:
number_on_the_page: '{0} Não existem entradas.|{1} Existe uma entrada.|]1,Inf[ Existem %count% entradas.'
reading_time: 'tempo estimado de leitura'
reading_time_minutes: 'tempo estimado de leitura: %readingTime% min'
reading_time_less_one_minute: 'tempo estimado de leitura: < 1 min'
+ number_of_tags: '{1}and one other tag|]1,Inf[and %count% other tags'
reading_time_minutes_short: '%readingTime% min'
reading_time_less_one_minute_short: '< 1 min'
original_article: 'original'
@@ -185,6 +186,8 @@ entry:
add_a_tag: 'Adicionar uma tag'
share_content: 'Compartilhar'
share_email_label: 'E-mail'
+ # public_link: 'public link'
+ # delete_public_link: 'delete public link'
download: 'Download'
print: 'Imprimir'
problem:
@@ -205,6 +208,8 @@ entry:
url_label: 'Url'
is_public_label: 'Público'
save_label: 'Salvar'
+ public:
+ # shared_by_wallabag: "This article has been shared by wallabag"
about:
page_title: 'Sobre'
@@ -242,7 +247,7 @@ howto:
page_description: 'Existem diferentes formas de salvar um artigo:'
top_menu:
browser_addons: 'Extensões de navegadores'
- mobile_apps: 'App's móveis'
+ mobile_apps: "App's móveis"
bookmarklet: 'Bookmarklet'
form:
description: 'Obrigado por este formulário'
@@ -260,12 +265,14 @@ howto:
quickstart:
page_title: 'Começo Rápido'
+ # more: 'More…'
intro:
title: 'Bem-vindo ao wallabag!'
paragraph_1: 'Nós podemos acompanhar você em sua visita ao wallabag e mostrar algumas funcionalidades que podem lhe interessar.'
paragraph_2: 'Siga-nos!'
configure:
title: 'Configurar a aplicação'
+ # description: 'In order to have an application which suits you, have a look into the configuration of wallabag.'
language: 'Alterar idioma e design'
rss: 'Habilitar feeds RSS'
tagging_rules: 'Escrever regras para acrescentar tags automaticamente em seus artigos'
@@ -279,6 +286,7 @@ quickstart:
import: 'Configurar importação'
first_steps:
title: 'Primeiros passos'
+ # description: "Now wallabag is well configured, it's time to archive the web. You can click on the top right sign + to add a link."
new_article: 'Salvar seu primeiro artigo'
unread_articles: 'E classificá-lo!'
migrate:
@@ -287,11 +295,16 @@ quickstart:
pocket: 'Migrar do Pocket'
wallabag_v1: 'Migrar do wallabag v1'
wallabag_v2: 'Migrar do wallabag v2'
+ readability: 'Migrate from Readability'
+ instapaper: 'Migrate from Instapaper'
developer:
title: 'Desenvolvedores'
+ # description: 'We also thought to the developers: Docker, API, translations, etc.'
create_application: 'Criar sua aplicação terceira'
+ # use_docker: 'Use Docker to install wallabag'
docs:
title: 'Documentação completa'
+ # description: "There are so much features in wallabag. Don't hesitate to read the manual to know them and to learn how to use them."
annotate: 'Anotar seu artigo'
export: 'Converter seu artigo em ePUB ou PDF'
search_filters: 'veja coo você pode encontrar um artigo usanndo o motor de busca e filtros'
@@ -308,6 +321,7 @@ tag:
page_title: 'Tags'
list:
number_on_the_page: '{0} Não existem tags.|{1} Uma tag.|]1,Inf[ Existem %count% tags.'
+ # see_untagged_entries: 'See untagged entries'
import:
page_title: 'Importar'
@@ -335,6 +349,24 @@ import:
wallabag_v2:
page_title: 'Importar > Wallabag v2'
description: 'Com este importador você importa todos os seus artigos do wallabag v2. Vá em Todos os artigos e então, na barra lateral de exportação, clique em "JSON". Você irá criar um arquivo "All articles.json".'
+ readability:
+ # page_title: 'Import > Readability'
+ # description: 'This importer will import all your Readability articles. On the tools (https://www.readability.com/tools/) page, click on "Export your data" in the "Data Export" section. You will received an email to download a json (which does not end with .json in fact).'
+ # how_to: 'Please select your Readability export and click on the below button to upload and import it.'
+ worker:
+ # enabled: "Import is made asynchronously. Once the import task is started, an external worker will handle jobs one at a time. The current service is:"
+ firefox:
+ # page_title: 'Import > Firefox'
+ # description: "This importer will import all your Firefox bookmarks. Just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file."
+ # 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."
+ chrome:
+ # page_title: 'Import > Chrome'
+ # description: "This importer will import all your Chrome bookmarks. The location of the file depends on your operating system : - On Linux, go into the
~/.config/chromium/Default/
directory - On Windows, it should be at
%LOCALAPPDATA%\\Google\\Chrome\\User Data\\Default
- On OS X, it should be at
~/Library/Application Support/Google/Chrome/Default/Bookmarks
Once you got there, copy the Bookmarks
file someplace you'll find.
Note that if you have Chromium instead of Chrome, you'll have to correct paths accordingly.
"
+ # 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."
+ instapaper:
+ # page_title: 'Import > Instapaper'
+ # description: 'This importer will import all your Instapaper articles. On the settings (https://www.instapaper.com/user) page, click on "Download .CSV file" in the "Export" section. A CSV file will be downloaded (like "instapaper-export.csv").'
+ # how_to: 'Please select your Instapaper export and click on the below button to upload and import it.'
developer:
page_title: 'Desenvolvedor'
@@ -361,12 +393,14 @@ developer:
page_title: 'Desenvolvedor > Novo cliente'
page_description: 'Você está prestes a criar um novo cliente. Por favor preencha o campo abaixo para a URI de redirecionamento de sua aplicação.'
form:
+ # name_label: 'Name of the client'
redirect_uris_label: 'URIs de redirecionamento'
save_label: 'Criar um novo cliente'
action_back: 'Voltar'
client_parameter:
page_title: 'Desenvolvedor > Parâmetros de clientes'
page_description: 'Aqui estão os parâmetros de seus clientes.'
+ # field_name: 'Client name'
field_id: 'ID do cliente'
field_secret: 'Chave do cliente'
back: 'Voltar'
@@ -384,6 +418,33 @@ developer:
paragraph_8: 'Se você deseja ver todos os endpoints da API, dê uma olhada em nossa documentação da API.'
back: 'Voltar'
+user:
+ # page_title: Users management
+ # new_user: Create a new user
+ # edit_user: Edit an existing user
+ # description: "Here you can manage all users (create, edit and delete)"
+ list:
+ # actions: Actions
+ # edit_action: Edit
+ # yes: Yes
+ # no: No
+ # create_new_one: Create a new user
+ form:
+ # username_label: 'Username'
+ # name_label: 'Name'
+ # password_label: 'Password'
+ # repeat_new_password_label: 'Repeat new password'
+ # plain_password_label: '????'
+ # email_label: 'Email'
+ # enabled_label: 'Enabled'
+ # locked_label: 'Locked'
+ # last_login_label: 'Last login'
+ # twofactor_label: Two factor authentication
+ # save: Save
+ # delete: Delete
+ # delete_confirm: Are you sure?
+ # back_to_list: Back to list
+
flashes:
config:
notice:
@@ -394,7 +455,6 @@ flashes:
rss_updated: 'Informação de RSS atualizada'
tagging_rules_updated: 'Regras de tags atualizadas'
tagging_rules_deleted: 'Regra de tag apagada'
- user_added: 'Usuário "%username%" adicionado'
rss_token_updated: 'Token RSS atualizado'
entry:
notice:
@@ -403,7 +463,7 @@ flashes:
entry_saved_failed: 'Failed to save entry'
entry_updated: 'Entrada atualizada'
entry_reloaded: 'Entrada recarregada'
- entry_reload_failed: 'Falha em recarregar a entrada'
+ entry_reloaded_failed: 'Falha em recarregar a entrada'
entry_archived: 'Entrada arquivada'
entry_unarchived: 'Entrada desarquivada'
entry_starred: 'Entrada destacada'
@@ -417,7 +477,16 @@ flashes:
failed: 'Importação falhou, por favor tente novamente.'
failed_on_file: 'Erro ao processar a importação. Por favor verifique seu arquivo de importação.'
summary: 'relatório de importação: %imported% importados, %skipped% já existem.'
+ # summary_with_queue: 'Import summary: %queued% queued.'
+ error:
+ # redis_enabled_not_installed: Redis is enabled for handle asynchronous import but it looks like we can't connect to it. Please check Redis configuration.
+ # rabbit_enabled_not_installed: RabbitMQ is enabled for handle asynchronous import but it looks like we can't connect to it. Please check RabbitMQ configuration.
developer:
notice:
client_created: 'Novo cliente criado.'
client_deleted: 'Cliente removido'
+ user:
+ notice:
+ # added: 'User "%username%" added'
+ # updated: 'User "%username%" updated'
+ # deleted: 'User "%username%" deleted'
From 8e53bf3aa19a43001b0bd207409be49a5e0f8b7a Mon Sep 17 00:00:00 2001
From: Paulino Michelazzo
Date: Fri, 21 Oct 2016 00:12:53 +0200
Subject: [PATCH 06/42] Update translation
---
.../Resources/translations/messages.pt.yml | 120 +++++++++---------
1 file changed, 60 insertions(+), 60 deletions(-)
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml
index 30e8b00ec..d30c67c1b 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml
@@ -31,7 +31,7 @@ menu:
search: 'Pesquisa'
save_link: 'Salvar um link'
back_to_unread: 'Voltar para os artigos não lidos'
- # users_management: 'Users management'
+ users_management: 'Gestão de Usuários'
top:
add_new_entry: 'Adicionar uma nova entrada'
search: 'Pesquisa'
@@ -46,7 +46,7 @@ footer:
social: 'Social'
powered_by: 'provido por'
about: 'Sobre'
- # stats: Since %user_creation% you read %nb_archives% articles. That is about %per_day% a day!
+ stats: 'Desde %user_creation% você leu %nb_archives% artigos. Isso é %per_day% por dia!'
config:
page_title: 'Config'
@@ -70,7 +70,7 @@ config:
200_word: 'Posso ler ~200 palavras por minuto'
300_word: 'Posso ler ~300 palavras por minuto'
400_word: 'Posso ler ~400 palavras por minuto'
- # pocket_consumer_key_label: Consumer key for Pocket to import contents
+ pocket_consumer_key_label: 'Chave do consumidor do Pocket para importar conteúdo'
form_rss:
description: 'Feeds RSS providos pelo wallabag permitem que você leia seus artigos salvos em seu leitor de RSS favorito. Você precisa gerar um token primeiro.'
token_label: 'Token RSS'
@@ -96,7 +96,7 @@ config:
if_label: 'if'
then_tag_as_label: 'então coloque a tag'
delete_rule_label: 'apagar'
- # edit_rule_label: 'edit'
+ edit_rule_label: 'editar'
rule_label: 'Regras'
tags_label: 'Tags'
faq:
@@ -137,8 +137,8 @@ entry:
starred: 'Entradas destacadas'
archived: 'Entradas arquivadas'
filtered: 'Entradas filtradas'
- # filtered_tags: 'Filtered by tags'
- # untagged: 'Untagged entries'
+ filtered_tags: 'Filtrar por tags'
+ untagged: 'Entradas sem tags'
list:
number_on_the_page: '{0} Não existem entradas.|{1} Existe uma entrada.|]1,Inf[ Existem %count% entradas.'
reading_time: 'tempo estimado de leitura'
@@ -186,8 +186,8 @@ entry:
add_a_tag: 'Adicionar uma tag'
share_content: 'Compartilhar'
share_email_label: 'E-mail'
- # public_link: 'public link'
- # delete_public_link: 'delete public link'
+ public_link: 'link público'
+ delete_public_link: 'apagar link público'
download: 'Download'
print: 'Imprimir'
problem:
@@ -209,7 +209,7 @@ entry:
is_public_label: 'Público'
save_label: 'Salvar'
public:
- # shared_by_wallabag: "This article has been shared by wallabag"
+ shared_by_wallabag: "Este artigo foi compartilhado pelo wallabag"
about:
page_title: 'Sobre'
@@ -265,14 +265,14 @@ howto:
quickstart:
page_title: 'Começo Rápido'
- # more: 'More…'
+ more: 'Mais...'
intro:
title: 'Bem-vindo ao wallabag!'
paragraph_1: 'Nós podemos acompanhar você em sua visita ao wallabag e mostrar algumas funcionalidades que podem lhe interessar.'
paragraph_2: 'Siga-nos!'
configure:
title: 'Configurar a aplicação'
- # description: 'In order to have an application which suits you, have a look into the configuration of wallabag.'
+ description: 'Para ter uma aplicação que atende você, dê uma olhada na configuração do wallabag.'
language: 'Alterar idioma e design'
rss: 'Habilitar feeds RSS'
tagging_rules: 'Escrever regras para acrescentar tags automaticamente em seus artigos'
@@ -286,7 +286,7 @@ quickstart:
import: 'Configurar importação'
first_steps:
title: 'Primeiros passos'
- # description: "Now wallabag is well configured, it's time to archive the web. You can click on the top right sign + to add a link."
+ description: "Agora o wallabag está bem configurado, é hora de arquivar a web. Você pode clicar no sinal de + no topo a direita para adicionar um link."
new_article: 'Salvar seu primeiro artigo'
unread_articles: 'E classificá-lo!'
migrate:
@@ -299,12 +299,12 @@ quickstart:
instapaper: 'Migrate from Instapaper'
developer:
title: 'Desenvolvedores'
- # description: 'We also thought to the developers: Docker, API, translations, etc.'
+ description: 'Nós também agradecemos os desenvolvedores: Docker, API, traduções, etc.'
create_application: 'Criar sua aplicação terceira'
- # use_docker: 'Use Docker to install wallabag'
+ use_docker: 'Usar o Docker para instalar o wallabag'
docs:
title: 'Documentação completa'
- # description: "There are so much features in wallabag. Don't hesitate to read the manual to know them and to learn how to use them."
+ description: "Existem muitas funcionalidades no wallabag. Não hesite em ler o manual para conhecê-las e aprender como usá-las."
annotate: 'Anotar seu artigo'
export: 'Converter seu artigo em ePUB ou PDF'
search_filters: 'veja coo você pode encontrar um artigo usanndo o motor de busca e filtros'
@@ -321,7 +321,7 @@ tag:
page_title: 'Tags'
list:
number_on_the_page: '{0} Não existem tags.|{1} Uma tag.|]1,Inf[ Existem %count% tags.'
- # see_untagged_entries: 'See untagged entries'
+ see_untagged_entries: 'Ver entradas sem tags'
import:
page_title: 'Importar'
@@ -350,23 +350,23 @@ import:
page_title: 'Importar > Wallabag v2'
description: 'Com este importador você importa todos os seus artigos do wallabag v2. Vá em Todos os artigos e então, na barra lateral de exportação, clique em "JSON". Você irá criar um arquivo "All articles.json".'
readability:
- # page_title: 'Import > Readability'
- # description: 'This importer will import all your Readability articles. On the tools (https://www.readability.com/tools/) page, click on "Export your data" in the "Data Export" section. You will received an email to download a json (which does not end with .json in fact).'
- # how_to: 'Please select your Readability export and click on the below button to upload and import it.'
+ page_title: 'Importar > Readability'
+ description: 'Este importador pode importar todos os artigos do Readability. Nas página ferramentas (https://www.readability.com/tools/), clique em "Export your data" na seção "Data Export". Você receberá um e-mail para fazer o download de um json (que de fato não termina com .json).'
+ how_to: 'Por favor, selecione sua exportação do Readability e clique no botão abaixo para importá-la.'
worker:
- # enabled: "Import is made asynchronously. Once the import task is started, an external worker will handle jobs one at a time. The current service is:"
+ enabled: "A importação é feita assíncronamente. Uma vez que a tarefa de importação é iniciada, um trabalho externo pode executar tarefas uma por vez. O serviço atual é:"
firefox:
- # page_title: 'Import > Firefox'
- # description: "This importer will import all your Firefox bookmarks. Just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file."
- # 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."
+ page_title: 'Importar > Firefox'
+ description: "Com este importador você importa todos os favoritos de seu Firefox. Somente vá até seus favoritos (Ctrl+Maj+O), e em \"Importar e Backup\" e escolha \"Backup...\". Você terá então um arquivo .json."
+ how_to: "Por favor, escolha o arquivo de backup dos favoritos e clique no botão abaixo para importá-lo. Note que o processo pode demorar até que todos os artigos tenham sido copiados."
chrome:
- # page_title: 'Import > Chrome'
- # description: "This importer will import all your Chrome bookmarks. The location of the file depends on your operating system : - On Linux, go into the
~/.config/chromium/Default/
directory - On Windows, it should be at
%LOCALAPPDATA%\\Google\\Chrome\\User Data\\Default
- On OS X, it should be at
~/Library/Application Support/Google/Chrome/Default/Bookmarks
Once you got there, copy the Bookmarks
file someplace you'll find.
Note that if you have Chromium instead of Chrome, you'll have to correct paths accordingly."
- # 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."
+ page_title: 'Importar > Chrome'
+ description: "Com este importador você importa todos os favoritos de seu Chrome. A localização do arquivo depende de seu sistema operacional: - Em Linux, vá para o diretório
~/.config/chromium/Default/
- Em Windows, ele deve estar em
%LOCALAPPDATA%\\Google\\Chrome\\User Data\\Default
- Em OS X, ele deve estar em
~/Library/Application Support/Google/Chrome/Default/Bookmarks
Uma vez que você pegou o arquivo, copie-o para algum lugar que você o encontre.
Note que se você possui o Chromium ao invés do Chrome, você precisa corrigir os caminhos."
+ how_to: "Por favor, escolha o arquivo de backup dos favoritos e clique no botão abaixo para importá-lo. Note que o processo pode demorar até que todos os artigos tenham sido copiados."
instapaper:
- # page_title: 'Import > Instapaper'
- # description: 'This importer will import all your Instapaper articles. On the settings (https://www.instapaper.com/user) page, click on "Download .CSV file" in the "Export" section. A CSV file will be downloaded (like "instapaper-export.csv").'
- # how_to: 'Please select your Instapaper export and click on the below button to upload and import it.'
+ page_title: 'Importar > Instapaper'
+ description: 'Este importador pode importar todos os artigos do seu Instapaper. Nas página de configurações (https://www.instapaper.com/user), clique em "Download .CSV file" na seção "Export". Um arquivo CSV será baixado (algo como "instapaper-export.csv").'
+ how_to: 'Por favor, selecione sua exportação do seu Instapaper e clique no botão abaixo para importá-la.'
developer:
page_title: 'Desenvolvedor'
@@ -393,14 +393,14 @@ developer:
page_title: 'Desenvolvedor > Novo cliente'
page_description: 'Você está prestes a criar um novo cliente. Por favor preencha o campo abaixo para a URI de redirecionamento de sua aplicação.'
form:
- # name_label: 'Name of the client'
+ name_label: 'Nome do cliente'
redirect_uris_label: 'URIs de redirecionamento'
save_label: 'Criar um novo cliente'
action_back: 'Voltar'
client_parameter:
page_title: 'Desenvolvedor > Parâmetros de clientes'
page_description: 'Aqui estão os parâmetros de seus clientes.'
- # field_name: 'Client name'
+ field_name: 'Nome do cliente'
field_id: 'ID do cliente'
field_secret: 'Chave do cliente'
back: 'Voltar'
@@ -419,31 +419,31 @@ developer:
back: 'Voltar'
user:
- # page_title: Users management
- # new_user: Create a new user
- # edit_user: Edit an existing user
- # description: "Here you can manage all users (create, edit and delete)"
+ page_title: 'Gerenciamento de Usuários'
+ new_user: 'Criar um novo usuário'
+ edit_user: 'Editar um usuário existente'
+ description: 'Aqui você gerencia todos os usuários (cria, edita e apaga)'
list:
- # actions: Actions
- # edit_action: Edit
- # yes: Yes
- # no: No
- # create_new_one: Create a new user
+ actions: 'Ações'
+ edit_action: 'Editar'
+ yes: 'Sim'
+ no: 'Não'
+ create_new_one: 'Criar um novo usuário'
form:
- # username_label: 'Username'
- # name_label: 'Name'
- # password_label: 'Password'
- # repeat_new_password_label: 'Repeat new password'
- # plain_password_label: '????'
- # email_label: 'Email'
- # enabled_label: 'Enabled'
- # locked_label: 'Locked'
- # last_login_label: 'Last login'
- # twofactor_label: Two factor authentication
- # save: Save
- # delete: Delete
- # delete_confirm: Are you sure?
- # back_to_list: Back to list
+ username_label: 'Nome de Usuário'
+ name_label: 'Nome'
+ password_label: 'Senha'
+ repeat_new_password_label: 'Repita a nova senha'
+ plain_password_label: '????'
+ email_label: 'E-mail'
+ enabled_label: 'Habilitado'
+ locked_label: 'Travado'
+ last_login_label: 'Último login'
+ twofactor_label: 'Autenticação de dois passos'
+ save: 'Salvar'
+ delete: 'Apagar'
+ delete_confirm: 'Tem certeza?'
+ back_to_list: 'Voltar para a lista'
flashes:
config:
@@ -477,16 +477,16 @@ flashes:
failed: 'Importação falhou, por favor tente novamente.'
failed_on_file: 'Erro ao processar a importação. Por favor verifique seu arquivo de importação.'
summary: 'relatório de importação: %imported% importados, %skipped% já existem.'
- # summary_with_queue: 'Import summary: %queued% queued.'
+ summary_with_queue: 'Importar sumáario: %queued% agendados.'
error:
- # redis_enabled_not_installed: Redis is enabled for handle asynchronous import but it looks like we can't connect to it. Please check Redis configuration.
- # rabbit_enabled_not_installed: RabbitMQ is enabled for handle asynchronous import but it looks like we can't connect to it. Please check RabbitMQ configuration.
+ redis_enabled_not_installed: 'O Redis está habilitado para importação assíncrona mas parece que não podemos nos conectar nele. Por favor verifique as configurações do Redis.'
+ rabbit_enabled_not_installed: 'O RabbitMQ está habilitado para importação assíncrona mas parece que não podemos nos conectar nele. Por favor verifique as configurações do RabbitMQ.'
developer:
notice:
client_created: 'Novo cliente criado.'
client_deleted: 'Cliente removido'
user:
notice:
- # added: 'User "%username%" added'
- # updated: 'User "%username%" updated'
- # deleted: 'User "%username%" deleted'
+ added: 'Usuário "%username%" adicionado'
+ updated: 'Usuário "%username%" atualizado'
+ deleted: 'Usuário "%username%" removido'
From 818cbe1feeab901c7bdfc533195de785acde9809 Mon Sep 17 00:00:00 2001
From: Jeremy Benoist
Date: Fri, 21 Oct 2016 07:18:41 +0200
Subject: [PATCH 07/42] Fix Portuguese translation
---
.../CoreBundle/Resources/translations/messages.pt.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml
index d30c67c1b..01fd9610e 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml
@@ -46,7 +46,7 @@ footer:
social: 'Social'
powered_by: 'provido por'
about: 'Sobre'
- stats: 'Desde %user_creation% você leu %nb_archives% artigos. Isso é %per_day% por dia!'
+ stats: 'Desde %user_creation% você leu %nb_archives% artigos. Isso é %per_day% por dia!'
config:
page_title: 'Config'
@@ -70,7 +70,7 @@ config:
200_word: 'Posso ler ~200 palavras por minuto'
300_word: 'Posso ler ~300 palavras por minuto'
400_word: 'Posso ler ~400 palavras por minuto'
- pocket_consumer_key_label: 'Chave do consumidor do Pocket para importar conteúdo'
+ pocket_consumer_key_label: 'Chave do consumidor do Pocket para importar conteúdo'
form_rss:
description: 'Feeds RSS providos pelo wallabag permitem que você leia seus artigos salvos em seu leitor de RSS favorito. Você precisa gerar um token primeiro.'
token_label: 'Token RSS'
From d1b075509dff22e191bcf912d7eef9fb7b1661cc Mon Sep 17 00:00:00 2001
From: Baptiste Mille-Mathias
Date: Sun, 23 Oct 2016 15:34:52 +0200
Subject: [PATCH 08/42] Add relevant links to fetch content error pages.
We link to the troubleshooting guide and give the mail link.
---
app/config/config.yml | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/app/config/config.yml b/app/config/config.yml
index a56cbdd9e..65187ecab 100644
--- a/app/config/config.yml
+++ b/app/config/config.yml
@@ -50,7 +50,8 @@ wallabag_core:
rss_limit: 50
reading_speed: 1
cache_lifetime: 10
- fetching_error_message: "wallabag can't retrieve contents for this article. Please report this issue to us."
+ fetching_error_message: |
+ wallabag can't retrieve contents for this article. Please first troubleshoot this issue and report it to us.
wallabag_user:
registration_enabled: "%fosuser_registration%"
From d36e5e20a5627faed81d3865470b032d95b86916 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nicolas=20L=C5=93uillet?=
Date: Mon, 24 Oct 2016 21:01:13 +0200
Subject: [PATCH 09/42] Removed the email part
---
app/config/config.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/config/config.yml b/app/config/config.yml
index 65187ecab..84eba759d 100644
--- a/app/config/config.yml
+++ b/app/config/config.yml
@@ -51,7 +51,7 @@ wallabag_core:
reading_speed: 1
cache_lifetime: 10
fetching_error_message: |
- wallabag can't retrieve contents for this article. Please first troubleshoot this issue and report it to us.
+ wallabag can't retrieve contents for this article. Please troubleshoot this issue.
wallabag_user:
registration_enabled: "%fosuser_registration%"
From c5ad143e750254adb185ab6956dc87d2585ae54d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nicolas=20L=C5=93uillet?=
Date: Mon, 24 Oct 2016 22:28:44 +0200
Subject: [PATCH 10/42] Added a check in Makefile to see if composer is
installed Fix #2498
---
Makefile | 2 +-
scripts/install.sh | 2 ++
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/Makefile b/Makefile
index 1df4d6327..83c5f37ad 100755
--- a/Makefile
+++ b/Makefile
@@ -41,6 +41,6 @@ travis: ## Make some stuff for Travis-CI
deploy: ## Deploy wallabag
@bundle exec cap staging deploy
-.PHONY: help clean install update build test release travis deploy
+.PHONY: help clean install update build test release travis deploy run dev
.DEFAULT_GOAL := install
diff --git a/scripts/install.sh b/scripts/install.sh
index 54d0bb785..d7b05a1ec 100644
--- a/scripts/install.sh
+++ b/scripts/install.sh
@@ -2,6 +2,8 @@
# You can execute this file to install wallabag
# eg: `sh install.sh prod`
+command -v composer >/dev/null 2>&1 || { echo >&2 "wallabag requires composer but it's not installed (see http://doc.wallabag.org/en/master/user/installation.html). Aborting."; exit 1; }
+
ENV=$1
TAG=$(git describe --tags $(git rev-list --tags --max-count=1))
From e8eec07ae63997c4b311b32da392e4e0379d3953 Mon Sep 17 00:00:00 2001
From: Paulino Michelazzo
Date: Tue, 25 Oct 2016 07:25:08 -0200
Subject: [PATCH 11/42] Translated missed line 147
---
src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml
index 01fd9610e..45dc52c9e 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml
@@ -144,7 +144,7 @@ entry:
reading_time: 'tempo estimado de leitura'
reading_time_minutes: 'tempo estimado de leitura: %readingTime% min'
reading_time_less_one_minute: 'tempo estimado de leitura: < 1 min'
- number_of_tags: '{1}and one other tag|]1,Inf[and %count% other tags'
+ number_of_tags: '{1}e uma outra tag|]1,Inf[e %count% outras tags'
reading_time_minutes_short: '%readingTime% min'
reading_time_less_one_minute_short: '< 1 min'
original_article: 'original'
From 7a5043f187a1f9aac37f359c8f407e5febea50f7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nicolas=20L=C5=93uillet?=
Date: Wed, 26 Oct 2016 13:53:23 +0200
Subject: [PATCH 12/42] Added tag label in the page title Fix #2472
---
src/Wallabag/CoreBundle/Controller/TagController.php | 1 +
.../CoreBundle/Resources/translations/messages.da.yml | 2 +-
.../CoreBundle/Resources/translations/messages.de.yml | 2 +-
.../CoreBundle/Resources/translations/messages.en.yml | 2 +-
.../CoreBundle/Resources/translations/messages.es.yml | 2 +-
.../CoreBundle/Resources/translations/messages.fa.yml | 2 +-
.../CoreBundle/Resources/translations/messages.fr.yml | 2 +-
.../CoreBundle/Resources/translations/messages.it.yml | 2 +-
.../CoreBundle/Resources/translations/messages.oc.yml | 2 +-
.../CoreBundle/Resources/translations/messages.pl.yml | 2 +-
.../CoreBundle/Resources/translations/messages.pt.yml | 2 +-
.../CoreBundle/Resources/translations/messages.ro.yml | 2 +-
.../CoreBundle/Resources/translations/messages.tr.yml | 2 +-
.../Resources/views/themes/baggy/Entry/entries.html.twig | 6 +++++-
.../Resources/views/themes/common/Entry/_title.html.twig | 2 +-
.../Resources/views/themes/material/Entry/entries.html.twig | 6 +++++-
16 files changed, 24 insertions(+), 15 deletions(-)
diff --git a/src/Wallabag/CoreBundle/Controller/TagController.php b/src/Wallabag/CoreBundle/Controller/TagController.php
index 5acc68528..707f3bbe3 100644
--- a/src/Wallabag/CoreBundle/Controller/TagController.php
+++ b/src/Wallabag/CoreBundle/Controller/TagController.php
@@ -143,6 +143,7 @@ class TagController extends Controller
'form' => null,
'entries' => $entries,
'currentPage' => $page,
+ 'tag' => $tag->getLabel(),
]);
}
}
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.da.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.da.yml
index 714ced14d..6ca7e459c 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.da.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.da.yml
@@ -137,7 +137,7 @@ entry:
# starred: 'Starred entries'
# archived: 'Archived entries'
# filtered: 'Filtered entries'
- # filtered_tags: 'Filtered by tags'
+ # filtered_tags: 'Filtered by tags:'
# untagged: 'Untagged entries'
list:
# number_on_the_page: '{0} There is no entry.|{1} There is one entry.|]1,Inf[ There are %count% entries.'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.de.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.de.yml
index 57e49f84e..8fd1d82a2 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.de.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.de.yml
@@ -137,7 +137,7 @@ entry:
starred: 'Favorisierte Einträge'
archived: 'Archivierte Einträge'
filtered: 'Gefilterte Einträge'
- filtered_tags: 'Gefiltert nach Tags'
+ filtered_tags: 'Gefiltert nach Tags:'
untagged: 'Nicht getaggte Einträge'
list:
number_on_the_page: '{0} Es gibt keine Einträge.|{1} Es gibt einen Eintrag.|]1,Inf[ Es gibt %count% Einträge.'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.en.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.en.yml
index 4a59c75eb..02f56535c 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.en.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.en.yml
@@ -137,7 +137,7 @@ entry:
starred: 'Starred entries'
archived: 'Archived entries'
filtered: 'Filtered entries'
- filtered_tags: 'Filtered by tags'
+ filtered_tags: 'Filtered by tags:'
untagged: 'Untagged entries'
list:
number_on_the_page: '{0} There are no entries.|{1} There is one entry.|]1,Inf[ There are %count% entries.'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.es.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.es.yml
index 1b1e0cb10..42ec8183f 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.es.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.es.yml
@@ -137,7 +137,7 @@ entry:
starred: 'Artículos favoritos'
archived: 'Artículos archivados'
filtered: 'Artículos filtrados'
- # filtered_tags: 'Filtered by tags'
+ # filtered_tags: 'Filtered by tags:'
# untagged: 'Untagged entries'
list:
number_on_the_page: '{0} No hay artículos.|{1} Hay un artículo.|]1,Inf[ Hay %count% artículos.'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml
index 41dc8acf4..f82167df9 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml
@@ -137,7 +137,7 @@ entry:
starred: 'مقالههای برگزیده'
archived: 'مقالههای بایگانیشده'
filtered: 'مقالههای فیلترشده'
- # filtered_tags: 'Filtered by tags'
+ # filtered_tags: 'Filtered by tags:'
# untagged: 'Untagged entries'
list:
number_on_the_page: '{0} هیج مقالهای نیست.|{1} یک مقاله هست.|]1,Inf[ %count% مقاله هست.'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml
index 7fb9681d9..574cc1a74 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml
@@ -137,7 +137,7 @@ entry:
starred: 'Articles favoris'
archived: 'Articles lus'
filtered: 'Articles filtrés'
- filtered_tags: 'Articles filtrés par tags'
+ filtered_tags: 'Articles filtrés par tags :'
untagged: 'Article sans tag'
list:
number_on_the_page: "{0} Il n'y a pas d'articles.|{1} Il y a un article.|]1,Inf[ Il y a %count% articles."
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.it.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.it.yml
index b279ae40e..d679ef003 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.it.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.it.yml
@@ -137,7 +137,7 @@ entry:
starred: 'Contenuti preferiti'
archived: 'Contenuti archiviati'
filtered: 'Contenuti filtrati'
- # filtered_tags: 'Filtered by tags'
+ # filtered_tags: 'Filtered by tags:'
# untagged: 'Untagged entries'
list:
number_on_the_page: "{0} Non ci sono contenuti.|{1} C'è un contenuto.|]1,Inf[ Ci sono %count% contenuti."
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml
index a4659620b..af0fba0dc 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml
@@ -137,7 +137,7 @@ entry:
starred: 'Articles favorits'
archived: 'Articles legits'
filtered: 'Articles filtrats'
- filtered_tags: 'Filtats per etiquetas'
+ filtered_tags: 'Filtats per etiquetas:'
untagged: 'Articles sens etiqueta'
list:
number_on_the_page: "{0} I a pas cap d'article.|{1} I a un article.|]1,Inf[ I a %count% articles."
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml
index 798b39c22..bf47b58a7 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml
@@ -137,7 +137,7 @@ entry:
starred: 'Wpisy oznaczone gwiazdką'
archived: 'Zarchiwizowane wpisy'
filtered: 'Odfiltrowane wpisy'
- filtered_tags: 'Filtrowane po tagach'
+ filtered_tags: 'Filtrowane po tagach:'
untagged: 'Odtaguj wpisy'
list:
number_on_the_page: '{0} Nie ma wpisów.|{1} Jest jeden wpis.|]1,Inf[ Są %count% wpisy.'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml
index 45dc52c9e..f10dc9aa2 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml
@@ -137,7 +137,7 @@ entry:
starred: 'Entradas destacadas'
archived: 'Entradas arquivadas'
filtered: 'Entradas filtradas'
- filtered_tags: 'Filtrar por tags'
+ filtered_tags: 'Filtrar por tags:'
untagged: 'Entradas sem tags'
list:
number_on_the_page: '{0} Não existem entradas.|{1} Existe uma entrada.|]1,Inf[ Existem %count% entradas.'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml
index 21f27e088..875c82e83 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml
@@ -137,7 +137,7 @@ entry:
# starred: 'Starred entries'
# archived: 'Archived entries'
# filtered: 'Filtered entries'
- # filtered_tags: 'Filtered by tags'
+ # filtered_tags: 'Filtered by tags:'
# untagged: 'Untagged entries'
list:
# number_on_the_page: '{0} There is no entry.|{1} There is one entry.|]1,Inf[ There are %count% entries.'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml
index f137ec996..f50f629a0 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml
@@ -136,7 +136,7 @@ entry:
# starred: 'Starred entries'
# archived: 'Archived entries'
# filtered: 'Filtered entries'
- # filtered_tags: 'Filtered by tags'
+ # filtered_tags: 'Filtered by tags:'
# untagged: 'Untagged entries'
list:
number_on_the_page: '{0} Herhangi bir makale yok.|{1} Burada bir adet makale var.|]1,Inf[ Burada %count% adet makale var.'
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Entry/entries.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Entry/entries.html.twig
index 3af88b237..f7c9392d6 100644
--- a/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Entry/entries.html.twig
+++ b/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Entry/entries.html.twig
@@ -1,7 +1,11 @@
{% extends "WallabagCoreBundle::layout.html.twig" %}
{% block title %}
- {% include "@WallabagCore/themes/common/Entry/_title.html.twig" %}
+ {% set params = {} %}
+ {% if tag is defined %}
+ {% set params = {'label': tag} %}
+ {% endif %}
+ {% include "@WallabagCore/themes/common/Entry/_title.html.twig" with {'params': params} %}
{% endblock %}
{% block content %}
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/common/Entry/_title.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/common/Entry/_title.html.twig
index d1c2f2037..42dfee583 100644
--- a/src/Wallabag/CoreBundle/Resources/views/themes/common/Entry/_title.html.twig
+++ b/src/Wallabag/CoreBundle/Resources/views/themes/common/Entry/_title.html.twig
@@ -7,7 +7,7 @@
{% elseif currentRoute == 'all' %}
{{ 'entry.page_titles.filtered'|trans }}
{% elseif currentRoute == 'tag_entries' %}
- {{ 'entry.page_titles.filtered_tags'|trans }}
+ {{ 'entry.page_titles.filtered_tags'|trans }} {{ params['label'] }}
{% elseif currentRoute == 'untagged' %}
{{ 'entry.page_titles.untagged'|trans }}
{% else %}
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entries.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entries.html.twig
index 919f94eca..3e678a326 100644
--- a/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entries.html.twig
+++ b/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entries.html.twig
@@ -1,7 +1,11 @@
{% extends "WallabagCoreBundle::layout.html.twig" %}
{% block title %}
- {% include "@WallabagCore/themes/common/Entry/_title.html.twig" %}
+ {% set params = {} %}
+ {% if tag is defined %}
+ {% set params = {'label': tag} %}
+ {% endif %}
+ {% include "@WallabagCore/themes/common/Entry/_title.html.twig" with {'params': params} %}
{% endblock %}
{% block content %}
From 73e8df9e444c60b532d923b22e4dbe2efff18ede Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nicolas=20L=C5=93uillet?=
Date: Wed, 26 Oct 2016 15:49:44 +0200
Subject: [PATCH 13/42] Renamed variable for page title
---
.../views/themes/baggy/Entry/entries.html.twig | 6 +++---
.../views/themes/common/Entry/_title.html.twig | 2 +-
.../views/themes/material/Entry/entries.html.twig | 10 +++++-----
3 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Entry/entries.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Entry/entries.html.twig
index f7c9392d6..f19f2922c 100644
--- a/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Entry/entries.html.twig
+++ b/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Entry/entries.html.twig
@@ -1,11 +1,11 @@
{% extends "WallabagCoreBundle::layout.html.twig" %}
{% block title %}
- {% set params = {} %}
+ {% set currentTag = '' %}
{% if tag is defined %}
- {% set params = {'label': tag} %}
+ {% set currentTag = tag %}
{% endif %}
- {% include "@WallabagCore/themes/common/Entry/_title.html.twig" with {'params': params} %}
+ {% include "@WallabagCore/themes/common/Entry/_title.html.twig" with {'currentTag': currentTag} %}
{% endblock %}
{% block content %}
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/common/Entry/_title.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/common/Entry/_title.html.twig
index 42dfee583..92cabdd92 100644
--- a/src/Wallabag/CoreBundle/Resources/views/themes/common/Entry/_title.html.twig
+++ b/src/Wallabag/CoreBundle/Resources/views/themes/common/Entry/_title.html.twig
@@ -7,7 +7,7 @@
{% elseif currentRoute == 'all' %}
{{ 'entry.page_titles.filtered'|trans }}
{% elseif currentRoute == 'tag_entries' %}
- {{ 'entry.page_titles.filtered_tags'|trans }} {{ params['label'] }}
+ {{ 'entry.page_titles.filtered_tags'|trans }} {{ currentTag }}
{% elseif currentRoute == 'untagged' %}
{{ 'entry.page_titles.untagged'|trans }}
{% else %}
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entries.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entries.html.twig
index 3e678a326..5c7cfd653 100644
--- a/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entries.html.twig
+++ b/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entries.html.twig
@@ -1,11 +1,11 @@
{% extends "WallabagCoreBundle::layout.html.twig" %}
{% block title %}
- {% set params = {} %}
- {% if tag is defined %}
- {% set params = {'label': tag} %}
- {% endif %}
- {% include "@WallabagCore/themes/common/Entry/_title.html.twig" with {'params': params} %}
+ {% set currentTag = '' %}
+ {% if tag is defined %}
+ {% set currentTag = tag %}
+ {% endif %}
+ {% include "@WallabagCore/themes/common/Entry/_title.html.twig" with {'currentTag': currentTag} %}
{% endblock %}
{% block content %}
From 9998c725330b4a99d6d12df60ac8234052e80b6a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nicolas=20L=C5=93uillet?=
Date: Thu, 27 Oct 2016 09:53:09 +0200
Subject: [PATCH 14/42] Added require.sh to check if composer is installed
---
scripts/dev.sh | 8 ++++++--
scripts/install.sh | 4 +++-
scripts/require.sh | 8 ++++++++
scripts/update.sh | 4 ++++
4 files changed, 21 insertions(+), 3 deletions(-)
create mode 100644 scripts/require.sh
diff --git a/scripts/dev.sh b/scripts/dev.sh
index 9b89da35f..9f5b2432b 100644
--- a/scripts/dev.sh
+++ b/scripts/dev.sh
@@ -1,6 +1,10 @@
#! /usr/bin/env bash
-# You can execute this file to install wallabag dev environmnet
-# eg: `sh install.sh prod`
+# You can execute this file to install wallabag dev environment
+# eg: `sh dev.sh`
+
+DIR="${BASH_SOURCE%/*}"
+if [[ ! -d "$DIR" ]]; then DIR="$PWD"; fi
+. "$DIR/require.sh"
composer install
php bin/console wallabag:install
diff --git a/scripts/install.sh b/scripts/install.sh
index d7b05a1ec..cf966a0dd 100644
--- a/scripts/install.sh
+++ b/scripts/install.sh
@@ -2,7 +2,9 @@
# You can execute this file to install wallabag
# eg: `sh install.sh prod`
-command -v composer >/dev/null 2>&1 || { echo >&2 "wallabag requires composer but it's not installed (see http://doc.wallabag.org/en/master/user/installation.html). Aborting."; exit 1; }
+DIR="${BASH_SOURCE%/*}"
+if [[ ! -d "$DIR" ]]; then DIR="$PWD"; fi
+. "$DIR/require.sh"
ENV=$1
TAG=$(git describe --tags $(git rev-list --tags --max-count=1))
diff --git a/scripts/require.sh b/scripts/require.sh
new file mode 100644
index 000000000..851d065dd
--- /dev/null
+++ b/scripts/require.sh
@@ -0,0 +1,8 @@
+#! /usr/bin/env bash
+# File used to check dependencies
+
+if [ ! -f composer.phar ]; then
+ echo "composer.phar not found, we'll see if composer is installed globally."
+fi
+
+command -v composer >/dev/null 2>&1 || { echo >&2 "wallabag requires composer but it's not installed (see http://doc.wallabag.org/en/master/user/installation.html). Aborting."; exit 1; }
diff --git a/scripts/update.sh b/scripts/update.sh
index b920a829b..96a48217f 100644
--- a/scripts/update.sh
+++ b/scripts/update.sh
@@ -2,6 +2,10 @@
# You can execute this file to update wallabag
# eg: `sh update.sh prod`
+DIR="${BASH_SOURCE%/*}"
+if [[ ! -d "$DIR" ]]; then DIR="$PWD"; fi
+. "$DIR/require.sh"
+
ENV=$1
TAG=$(git describe --tags $(git rev-list --tags --max-count=1))
From c4d9a8d6d0db2be5c502e257bbeb963e3870d521 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nicolas=20L=C5=93uillet?=
Date: Thu, 27 Oct 2016 10:09:43 +0200
Subject: [PATCH 15/42] Usage of composer.phar if it's found
---
scripts/dev.sh | 4 +++-
scripts/install.sh | 4 +++-
scripts/require.sh | 5 +++--
scripts/update.sh | 4 +++-
4 files changed, 12 insertions(+), 5 deletions(-)
diff --git a/scripts/dev.sh b/scripts/dev.sh
index 9f5b2432b..fa3b2d5d5 100644
--- a/scripts/dev.sh
+++ b/scripts/dev.sh
@@ -2,10 +2,12 @@
# You can execute this file to install wallabag dev environment
# eg: `sh dev.sh`
+COMPOSER_COMMAND='composer'
+
DIR="${BASH_SOURCE%/*}"
if [[ ! -d "$DIR" ]]; then DIR="$PWD"; fi
. "$DIR/require.sh"
-composer install
+$COMPOSER_COMMAND install
php bin/console wallabag:install
php bin/console server:run
diff --git a/scripts/install.sh b/scripts/install.sh
index cf966a0dd..7a1f02bd8 100644
--- a/scripts/install.sh
+++ b/scripts/install.sh
@@ -2,6 +2,8 @@
# You can execute this file to install wallabag
# eg: `sh install.sh prod`
+COMPOSER_COMMAND='composer'
+
DIR="${BASH_SOURCE%/*}"
if [[ ! -d "$DIR" ]]; then DIR="$PWD"; fi
. "$DIR/require.sh"
@@ -10,5 +12,5 @@ ENV=$1
TAG=$(git describe --tags $(git rev-list --tags --max-count=1))
git checkout $TAG
-SYMFONY_ENV=$ENV composer install --no-dev -o --prefer-dist
+SYMFONY_ENV=$ENV $COMPOSER_COMMAND install --no-dev -o --prefer-dist
php bin/console wallabag:install --env=$ENV
diff --git a/scripts/require.sh b/scripts/require.sh
index 851d065dd..ddfb3dd2a 100644
--- a/scripts/require.sh
+++ b/scripts/require.sh
@@ -3,6 +3,7 @@
if [ ! -f composer.phar ]; then
echo "composer.phar not found, we'll see if composer is installed globally."
+ command -v composer >/dev/null 2>&1 || { echo >&2 "wallabag requires composer but it's not installed (see http://doc.wallabag.org/en/master/user/installation.html). Aborting."; exit 1; }
+else
+ COMPOSER_COMMAND='composer.phar'
fi
-
-command -v composer >/dev/null 2>&1 || { echo >&2 "wallabag requires composer but it's not installed (see http://doc.wallabag.org/en/master/user/installation.html). Aborting."; exit 1; }
diff --git a/scripts/update.sh b/scripts/update.sh
index 96a48217f..45e93f363 100644
--- a/scripts/update.sh
+++ b/scripts/update.sh
@@ -2,6 +2,8 @@
# You can execute this file to update wallabag
# eg: `sh update.sh prod`
+COMPOSER_COMMAND='composer'
+
DIR="${BASH_SOURCE%/*}"
if [[ ! -d "$DIR" ]]; then DIR="$PWD"; fi
. "$DIR/require.sh"
@@ -13,5 +15,5 @@ rm -rf var/cache/*
git fetch origin
git fetch --tags
git checkout $TAG --force
-SYMFONY_ENV=$ENV composer install --no-dev -o --prefer-dist
+SYMFONY_ENV=$ENV $COMPOSER_COMMAND install --no-dev -o --prefer-dist
php bin/console cache:clear --env=$ENV
From 37da178696c2f23b8a3b85f10e3c885ecf425173 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nicolas=20L=C5=93uillet?=
Date: Thu, 27 Oct 2016 14:46:21 +0200
Subject: [PATCH 16/42] Added the whole path to parameters.yml file
---
docs/de/developer/rabbitmq.rst | 2 +-
docs/de/developer/redis.rst | 2 +-
docs/en/developer/rabbitmq.rst | 2 +-
docs/en/developer/redis.rst | 2 +-
docs/fr/developer/rabbitmq.rst | 2 +-
docs/fr/developer/redis.rst | 2 +-
6 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/docs/de/developer/rabbitmq.rst b/docs/de/developer/rabbitmq.rst
index f81e07e3e..143b64a1c 100644
--- a/docs/de/developer/rabbitmq.rst
+++ b/docs/de/developer/rabbitmq.rst
@@ -37,7 +37,7 @@ RabbitMQ stoppen
Konfigure RabbitMQ in wallabag
------------------------------
-Bearbeite die Datei ``parameters.yml``, um die RabbitMQ Konfiguration einzurichten. Die Standardkonfiguration sollte ok sein:
+Bearbeite die Datei ``app/config/parameters.yml``, um die RabbitMQ Konfiguration einzurichten. Die Standardkonfiguration sollte ok sein:
.. code:: yaml
diff --git a/docs/de/developer/redis.rst b/docs/de/developer/redis.rst
index 57b415506..2505bf24d 100644
--- a/docs/de/developer/redis.rst
+++ b/docs/de/developer/redis.rst
@@ -28,7 +28,7 @@ Der Redis Service läuft eventuell schon direkt nach der Installation. Falls nic
Konfigure Redis in wallabag
---------------------------
-Bearbeite die Datei ``parameters.yml``, um die RabbitMQ Konfiguration einzurichten. Die Standardkonfiguration sollte ok sein:
+Bearbeite die Datei ``app/config/parameters.yml``, um die RabbitMQ Konfiguration einzurichten. Die Standardkonfiguration sollte ok sein:
.. code:: yaml
diff --git a/docs/en/developer/rabbitmq.rst b/docs/en/developer/rabbitmq.rst
index 673228e9f..7ee8a5ce2 100644
--- a/docs/en/developer/rabbitmq.rst
+++ b/docs/en/developer/rabbitmq.rst
@@ -37,7 +37,7 @@ Stop RabbitMQ
Configure RabbitMQ in wallabag
------------------------------
-Edit your ``parameters.yml`` file to edit RabbitMQ configuration. The default one should be ok:
+Edit your ``app/config/parameters.yml`` file to edit RabbitMQ configuration. The default one should be ok:
.. code:: yaml
diff --git a/docs/en/developer/redis.rst b/docs/en/developer/redis.rst
index 2e2bbbeaf..ea084e667 100644
--- a/docs/en/developer/redis.rst
+++ b/docs/en/developer/redis.rst
@@ -28,7 +28,7 @@ The server might be already running after installing, if not you can launch it u
Configure Redis in wallabag
---------------------------
-Edit your ``parameters.yml`` file to edit Redis configuration. The default one should be ok:
+Edit your ``app/config/parameters.yml`` file to edit Redis configuration. The default one should be ok:
.. code:: yaml
diff --git a/docs/fr/developer/rabbitmq.rst b/docs/fr/developer/rabbitmq.rst
index 92db5a28d..b534a48b8 100644
--- a/docs/fr/developer/rabbitmq.rst
+++ b/docs/fr/developer/rabbitmq.rst
@@ -37,7 +37,7 @@ Arrêter RabbitMQ
Configurer RabbitMQ dans wallabag
---------------------------------
-Modifiez votre fichier ``parameters.yml`` pour éditer la configuration RabbitMQ. Celle par défaut devrait convenir :
+Modifiez votre fichier ``app/config/parameters.yml`` pour éditer la configuration RabbitMQ. Celle par défaut devrait convenir :
.. code:: yaml
diff --git a/docs/fr/developer/redis.rst b/docs/fr/developer/redis.rst
index 8a212e8aa..58204d571 100644
--- a/docs/fr/developer/redis.rst
+++ b/docs/fr/developer/redis.rst
@@ -28,7 +28,7 @@ Le serveur devrait déjà être démarré après l'installation. Si ce n'est pas
Configurer Redis dans wallabag
-------------------------------
-Modifiez votre fichier ``parameters.yml`` pour éditer la configuration Redis. Celle par défaut devrait convenir :
+Modifiez votre fichier ``app/config/parameters.yml`` pour éditer la configuration Redis. Celle par défaut devrait convenir :
.. code:: yaml
From 900c844861eac95fc41afbbbc121584b8f9e6c32 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nicolas=20L=C5=93uillet?=
Date: Fri, 28 Oct 2016 14:46:30 +0200
Subject: [PATCH 17/42] Exploded WallabagRestController into many controllers
Fix #2503
---
.../Controller/EntryRestController.php | 367 ++++++++
.../Controller/TagRestController.php | 171 ++++
.../Controller/WallabagRestController.php | 522 +----------
.../Resources/config/routing_rest.yml | 12 +-
.../Controller/EntryRestControllerTest.php | 673 ++++++++++++++
.../Controller/TagRestControllerTest.php | 162 ++++
.../Controller/WallabagRestControllerTest.php | 820 ------------------
7 files changed, 1386 insertions(+), 1341 deletions(-)
create mode 100644 src/Wallabag/ApiBundle/Controller/EntryRestController.php
create mode 100644 src/Wallabag/ApiBundle/Controller/TagRestController.php
create mode 100644 tests/Wallabag/ApiBundle/Controller/EntryRestControllerTest.php
create mode 100644 tests/Wallabag/ApiBundle/Controller/TagRestControllerTest.php
diff --git a/src/Wallabag/ApiBundle/Controller/EntryRestController.php b/src/Wallabag/ApiBundle/Controller/EntryRestController.php
new file mode 100644
index 000000000..24fa7b3bd
--- /dev/null
+++ b/src/Wallabag/ApiBundle/Controller/EntryRestController.php
@@ -0,0 +1,367 @@
+validateAuthentication();
+
+ $urls = $request->query->get('urls', []);
+
+ // handle multiple urls first
+ if (!empty($urls)) {
+ $results = [];
+ foreach ($urls as $url) {
+ $res = $this->getDoctrine()
+ ->getRepository('WallabagCoreBundle:Entry')
+ ->findByUrlAndUserId($url, $this->getUser()->getId());
+
+ $results[$url] = false === $res ? false : true;
+ }
+
+ $json = $this->get('serializer')->serialize($results, 'json');
+
+ return (new JsonResponse())->setJson($json);
+ }
+
+ // let's see if it is a simple url?
+ $url = $request->query->get('url', '');
+
+ if (empty($url)) {
+ throw $this->createAccessDeniedException('URL is empty?, logged user id: '.$this->getUser()->getId());
+ }
+
+ $res = $this->getDoctrine()
+ ->getRepository('WallabagCoreBundle:Entry')
+ ->findByUrlAndUserId($url, $this->getUser()->getId());
+
+ $exists = false === $res ? false : true;
+
+ $json = $this->get('serializer')->serialize(['exists' => $exists], 'json');
+
+ return (new JsonResponse())->setJson($json);
+ }
+
+ /**
+ * Retrieve all entries. It could be filtered by many options.
+ *
+ * @ApiDoc(
+ * parameters={
+ * {"name"="archive", "dataType"="integer", "required"=false, "format"="1 or 0, all entries by default", "description"="filter by archived status."},
+ * {"name"="starred", "dataType"="integer", "required"=false, "format"="1 or 0, all entries by default", "description"="filter by starred status."},
+ * {"name"="sort", "dataType"="string", "required"=false, "format"="'created' or 'updated', default 'created'", "description"="sort entries by date."},
+ * {"name"="order", "dataType"="string", "required"=false, "format"="'asc' or 'desc', default 'desc'", "description"="order of sort."},
+ * {"name"="page", "dataType"="integer", "required"=false, "format"="default '1'", "description"="what page you want."},
+ * {"name"="perPage", "dataType"="integer", "required"=false, "format"="default'30'", "description"="results per page."},
+ * {"name"="tags", "dataType"="string", "required"=false, "format"="api,rest", "description"="a list of tags url encoded. Will returns entries that matches ALL tags."},
+ * {"name"="since", "dataType"="integer", "required"=false, "format"="default '0'", "description"="The timestamp since when you want entries updated."},
+ * }
+ * )
+ *
+ * @return JsonResponse
+ */
+ public function getEntriesAction(Request $request)
+ {
+ $this->validateAuthentication();
+
+ $isArchived = (null === $request->query->get('archive')) ? null : (bool) $request->query->get('archive');
+ $isStarred = (null === $request->query->get('starred')) ? null : (bool) $request->query->get('starred');
+ $sort = $request->query->get('sort', 'created');
+ $order = $request->query->get('order', 'desc');
+ $page = (int) $request->query->get('page', 1);
+ $perPage = (int) $request->query->get('perPage', 30);
+ $tags = $request->query->get('tags', '');
+ $since = $request->query->get('since', 0);
+
+ $pager = $this->getDoctrine()
+ ->getRepository('WallabagCoreBundle:Entry')
+ ->findEntries($this->getUser()->getId(), $isArchived, $isStarred, $sort, $order, $since, $tags);
+
+ $pager->setCurrentPage($page);
+ $pager->setMaxPerPage($perPage);
+
+ $pagerfantaFactory = new PagerfantaFactory('page', 'perPage');
+ $paginatedCollection = $pagerfantaFactory->createRepresentation(
+ $pager,
+ new Route(
+ 'api_get_entries',
+ [
+ 'archive' => $isArchived,
+ 'starred' => $isStarred,
+ 'sort' => $sort,
+ 'order' => $order,
+ 'page' => $page,
+ 'perPage' => $perPage,
+ 'tags' => $tags,
+ 'since' => $since,
+ ],
+ UrlGeneratorInterface::ABSOLUTE_URL
+ )
+ );
+
+ $json = $this->get('serializer')->serialize($paginatedCollection, 'json');
+
+ return (new JsonResponse())->setJson($json);
+ }
+
+ /**
+ * Retrieve a single entry.
+ *
+ * @ApiDoc(
+ * requirements={
+ * {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"}
+ * }
+ * )
+ *
+ * @return JsonResponse
+ */
+ public function getEntryAction(Entry $entry)
+ {
+ $this->validateAuthentication();
+ $this->validateUserAccess($entry->getUser()->getId());
+
+ $json = $this->get('serializer')->serialize($entry, 'json');
+
+ return (new JsonResponse())->setJson($json);
+ }
+
+ /**
+ * Create an entry.
+ *
+ * @ApiDoc(
+ * parameters={
+ * {"name"="url", "dataType"="string", "required"=true, "format"="http://www.test.com/article.html", "description"="Url for the entry."},
+ * {"name"="title", "dataType"="string", "required"=false, "description"="Optional, we'll get the title from the page."},
+ * {"name"="tags", "dataType"="string", "required"=false, "format"="tag1,tag2,tag3", "description"="a comma-separated list of tags."},
+ * {"name"="starred", "dataType"="integer", "required"=false, "format"="1 or 0", "description"="entry already starred"},
+ * {"name"="archive", "dataType"="integer", "required"=false, "format"="1 or 0", "description"="entry already archived"},
+ * }
+ * )
+ *
+ * @return JsonResponse
+ */
+ public function postEntriesAction(Request $request)
+ {
+ $this->validateAuthentication();
+
+ $url = $request->request->get('url');
+ $title = $request->request->get('title');
+ $isArchived = $request->request->get('archive');
+ $isStarred = $request->request->get('starred');
+
+ $entry = $this->get('wallabag_core.entry_repository')->findByUrlAndUserId($url, $this->getUser()->getId());
+
+ if (false === $entry) {
+ $entry = $this->get('wallabag_core.content_proxy')->updateEntry(
+ new Entry($this->getUser()),
+ $url
+ );
+ }
+
+ if (!is_null($title)) {
+ $entry->setTitle($title);
+ }
+
+ $tags = $request->request->get('tags', '');
+ if (!empty($tags)) {
+ $this->get('wallabag_core.content_proxy')->assignTagsToEntry($entry, $tags);
+ }
+
+ if (!is_null($isStarred)) {
+ $entry->setStarred((bool) $isStarred);
+ }
+
+ if (!is_null($isArchived)) {
+ $entry->setArchived((bool) $isArchived);
+ }
+
+ $em = $this->getDoctrine()->getManager();
+ $em->persist($entry);
+
+ $em->flush();
+
+ $json = $this->get('serializer')->serialize($entry, 'json');
+
+ return (new JsonResponse())->setJson($json);
+ }
+
+ /**
+ * Change several properties of an entry.
+ *
+ * @ApiDoc(
+ * requirements={
+ * {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"}
+ * },
+ * parameters={
+ * {"name"="title", "dataType"="string", "required"=false},
+ * {"name"="tags", "dataType"="string", "required"=false, "format"="tag1,tag2,tag3", "description"="a comma-separated list of tags."},
+ * {"name"="archive", "dataType"="integer", "required"=false, "format"="1 or 0", "description"="archived the entry."},
+ * {"name"="starred", "dataType"="integer", "required"=false, "format"="1 or 0", "description"="starred the entry."},
+ * }
+ * )
+ *
+ * @return JsonResponse
+ */
+ public function patchEntriesAction(Entry $entry, Request $request)
+ {
+ $this->validateAuthentication();
+ $this->validateUserAccess($entry->getUser()->getId());
+
+ $title = $request->request->get('title');
+ $isArchived = $request->request->get('archive');
+ $isStarred = $request->request->get('starred');
+
+ if (!is_null($title)) {
+ $entry->setTitle($title);
+ }
+
+ if (!is_null($isArchived)) {
+ $entry->setArchived((bool) $isArchived);
+ }
+
+ if (!is_null($isStarred)) {
+ $entry->setStarred((bool) $isStarred);
+ }
+
+ $tags = $request->request->get('tags', '');
+ if (!empty($tags)) {
+ $this->get('wallabag_core.content_proxy')->assignTagsToEntry($entry, $tags);
+ }
+
+ $em = $this->getDoctrine()->getManager();
+ $em->flush();
+
+ $json = $this->get('serializer')->serialize($entry, 'json');
+
+ return (new JsonResponse())->setJson($json);
+ }
+
+ /**
+ * Delete **permanently** an entry.
+ *
+ * @ApiDoc(
+ * requirements={
+ * {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"}
+ * }
+ * )
+ *
+ * @return JsonResponse
+ */
+ public function deleteEntriesAction(Entry $entry)
+ {
+ $this->validateAuthentication();
+ $this->validateUserAccess($entry->getUser()->getId());
+
+ $em = $this->getDoctrine()->getManager();
+ $em->remove($entry);
+ $em->flush();
+
+ $json = $this->get('serializer')->serialize($entry, 'json');
+
+ return (new JsonResponse())->setJson($json);
+ }
+
+ /**
+ * Retrieve all tags for an entry.
+ *
+ * @ApiDoc(
+ * requirements={
+ * {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"}
+ * }
+ * )
+ *
+ * @return JsonResponse
+ */
+ public function getEntriesTagsAction(Entry $entry)
+ {
+ $this->validateAuthentication();
+ $this->validateUserAccess($entry->getUser()->getId());
+
+ $json = $this->get('serializer')->serialize($entry->getTags(), 'json');
+
+ return (new JsonResponse())->setJson($json);
+ }
+
+ /**
+ * Add one or more tags to an entry.
+ *
+ * @ApiDoc(
+ * requirements={
+ * {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"}
+ * },
+ * parameters={
+ * {"name"="tags", "dataType"="string", "required"=false, "format"="tag1,tag2,tag3", "description"="a comma-separated list of tags."},
+ * }
+ * )
+ *
+ * @return JsonResponse
+ */
+ public function postEntriesTagsAction(Request $request, Entry $entry)
+ {
+ $this->validateAuthentication();
+ $this->validateUserAccess($entry->getUser()->getId());
+
+ $tags = $request->request->get('tags', '');
+ if (!empty($tags)) {
+ $this->get('wallabag_core.content_proxy')->assignTagsToEntry($entry, $tags);
+ }
+
+ $em = $this->getDoctrine()->getManager();
+ $em->persist($entry);
+ $em->flush();
+
+ $json = $this->get('serializer')->serialize($entry, 'json');
+
+ return (new JsonResponse())->setJson($json);
+ }
+
+ /**
+ * Permanently remove one tag for an entry.
+ *
+ * @ApiDoc(
+ * requirements={
+ * {"name"="tag", "dataType"="integer", "requirement"="\w+", "description"="The tag ID"},
+ * {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"}
+ * }
+ * )
+ *
+ * @return JsonResponse
+ */
+ public function deleteEntriesTagsAction(Entry $entry, Tag $tag)
+ {
+ $this->validateAuthentication();
+ $this->validateUserAccess($entry->getUser()->getId());
+
+ $entry->removeTag($tag);
+ $em = $this->getDoctrine()->getManager();
+ $em->persist($entry);
+ $em->flush();
+
+ $json = $this->get('serializer')->serialize($entry, 'json');
+
+ return (new JsonResponse())->setJson($json);
+ }
+}
diff --git a/src/Wallabag/ApiBundle/Controller/TagRestController.php b/src/Wallabag/ApiBundle/Controller/TagRestController.php
new file mode 100644
index 000000000..4e7ddc662
--- /dev/null
+++ b/src/Wallabag/ApiBundle/Controller/TagRestController.php
@@ -0,0 +1,171 @@
+validateAuthentication();
+
+ $tags = $this->getDoctrine()
+ ->getRepository('WallabagCoreBundle:Tag')
+ ->findAllTags($this->getUser()->getId());
+
+ $json = $this->get('serializer')->serialize($tags, 'json');
+
+ return (new JsonResponse())->setJson($json);
+ }
+
+ /**
+ * Permanently remove one tag from **every** entry.
+ *
+ * @ApiDoc(
+ * requirements={
+ * {"name"="tag", "dataType"="string", "required"=true, "requirement"="\w+", "description"="Tag as a string"}
+ * }
+ * )
+ *
+ * @return JsonResponse
+ */
+ public function deleteTagLabelAction(Request $request)
+ {
+ $this->validateAuthentication();
+ $label = $request->request->get('tag', '');
+
+ $tag = $this->getDoctrine()->getRepository('WallabagCoreBundle:Tag')->findOneByLabel($label);
+
+ if (empty($tag)) {
+ throw $this->createNotFoundException('Tag not found');
+ }
+
+ $this->getDoctrine()
+ ->getRepository('WallabagCoreBundle:Entry')
+ ->removeTag($this->getUser()->getId(), $tag);
+
+ $this->cleanOrphanTag($tag);
+
+ $json = $this->get('serializer')->serialize($tag, 'json');
+
+ return (new JsonResponse())->setJson($json);
+ }
+
+ /**
+ * Permanently remove some tags from **every** entry.
+ *
+ * @ApiDoc(
+ * requirements={
+ * {"name"="tags", "dataType"="string", "required"=true, "format"="tag1,tag2", "description"="Tags as strings (comma splitted)"}
+ * }
+ * )
+ *
+ * @return JsonResponse
+ */
+ public function deleteTagsLabelAction(Request $request)
+ {
+ $this->validateAuthentication();
+
+ $tagsLabels = $request->request->get('tags', '');
+
+ $tags = [];
+
+ foreach (explode(',', $tagsLabels) as $tagLabel) {
+ $tagEntity = $this->getDoctrine()->getRepository('WallabagCoreBundle:Tag')->findOneByLabel($tagLabel);
+
+ if (!empty($tagEntity)) {
+ $tags[] = $tagEntity;
+ }
+ }
+
+ if (empty($tags)) {
+ throw $this->createNotFoundException('Tags not found');
+ }
+
+ $this->getDoctrine()
+ ->getRepository('WallabagCoreBundle:Entry')
+ ->removeTags($this->getUser()->getId(), $tags);
+
+ $this->cleanOrphanTag($tags);
+
+ $json = $this->get('serializer')->serialize($tags, 'json');
+
+ return (new JsonResponse())->setJson($json);
+ }
+
+ /**
+ * Permanently remove one tag from **every** entry.
+ *
+ * @ApiDoc(
+ * requirements={
+ * {"name"="tag", "dataType"="integer", "requirement"="\w+", "description"="The tag"}
+ * }
+ * )
+ *
+ * @return JsonResponse
+ */
+ public function deleteTagAction(Tag $tag)
+ {
+ $this->validateAuthentication();
+
+ $this->getDoctrine()
+ ->getRepository('WallabagCoreBundle:Entry')
+ ->removeTag($this->getUser()->getId(), $tag);
+
+ $this->cleanOrphanTag($tag);
+
+ $json = $this->get('serializer')->serialize($tag, 'json');
+
+ return (new JsonResponse())->setJson($json);
+ }
+
+ /**
+ * Retrieve version number.
+ *
+ * @ApiDoc()
+ *
+ * @return JsonResponse
+ */
+ public function getVersionAction()
+ {
+ $version = $this->container->getParameter('wallabag_core.version');
+
+ $json = $this->get('serializer')->serialize($version, 'json');
+
+ return (new JsonResponse())->setJson($json);
+ }
+
+ /**
+ * Remove orphan tag in case no entries are associated to it.
+ *
+ * @param Tag|array $tags
+ */
+ private function cleanOrphanTag($tags)
+ {
+ if (!is_array($tags)) {
+ $tags = [$tags];
+ }
+
+ $em = $this->getDoctrine()->getManager();
+
+ foreach ($tags as $tag) {
+ if (count($tag->getEntries()) === 0) {
+ $em->remove($tag);
+ }
+ }
+
+ $em->flush();
+ }
+}
diff --git a/src/Wallabag/ApiBundle/Controller/WallabagRestController.php b/src/Wallabag/ApiBundle/Controller/WallabagRestController.php
index 9997913d2..e927a8903 100644
--- a/src/Wallabag/ApiBundle/Controller/WallabagRestController.php
+++ b/src/Wallabag/ApiBundle/Controller/WallabagRestController.php
@@ -3,543 +3,25 @@
namespace Wallabag\ApiBundle\Controller;
use FOS\RestBundle\Controller\FOSRestController;
-use Hateoas\Configuration\Route;
-use Hateoas\Representation\Factory\PagerfantaFactory;
-use Nelmio\ApiDocBundle\Annotation\ApiDoc;
-use Symfony\Component\HttpFoundation\Request;
-use Symfony\Component\HttpFoundation\JsonResponse;
-use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Wallabag\CoreBundle\Entity\Entry;
-use Wallabag\CoreBundle\Entity\Tag;
class WallabagRestController extends FOSRestController
{
- private function validateAuthentication()
+ protected function validateAuthentication()
{
if (false === $this->get('security.authorization_checker')->isGranted('IS_AUTHENTICATED_FULLY')) {
throw new AccessDeniedException();
}
}
- /**
- * Check if an entry exist by url.
- *
- * @ApiDoc(
- * parameters={
- * {"name"="url", "dataType"="string", "required"=true, "format"="An url", "description"="Url to check if it exists"},
- * {"name"="urls", "dataType"="string", "required"=false, "format"="An array of urls (?urls[]=http...&urls[]=http...)", "description"="Urls (as an array) to check if it exists"}
- * }
- * )
- *
- * @return JsonResponse
- */
- public function getEntriesExistsAction(Request $request)
- {
- $this->validateAuthentication();
-
- $urls = $request->query->get('urls', []);
-
- // handle multiple urls first
- if (!empty($urls)) {
- $results = [];
- foreach ($urls as $url) {
- $res = $this->getDoctrine()
- ->getRepository('WallabagCoreBundle:Entry')
- ->findByUrlAndUserId($url, $this->getUser()->getId());
-
- $results[$url] = false === $res ? false : true;
- }
-
- $json = $this->get('serializer')->serialize($results, 'json');
-
- return (new JsonResponse())->setJson($json);
- }
-
- // let's see if it is a simple url?
- $url = $request->query->get('url', '');
-
- if (empty($url)) {
- throw $this->createAccessDeniedException('URL is empty?, logged user id: '.$this->getUser()->getId());
- }
-
- $res = $this->getDoctrine()
- ->getRepository('WallabagCoreBundle:Entry')
- ->findByUrlAndUserId($url, $this->getUser()->getId());
-
- $exists = false === $res ? false : true;
-
- $json = $this->get('serializer')->serialize(['exists' => $exists], 'json');
-
- return (new JsonResponse())->setJson($json);
- }
-
- /**
- * Retrieve all entries. It could be filtered by many options.
- *
- * @ApiDoc(
- * parameters={
- * {"name"="archive", "dataType"="integer", "required"=false, "format"="1 or 0, all entries by default", "description"="filter by archived status."},
- * {"name"="starred", "dataType"="integer", "required"=false, "format"="1 or 0, all entries by default", "description"="filter by starred status."},
- * {"name"="sort", "dataType"="string", "required"=false, "format"="'created' or 'updated', default 'created'", "description"="sort entries by date."},
- * {"name"="order", "dataType"="string", "required"=false, "format"="'asc' or 'desc', default 'desc'", "description"="order of sort."},
- * {"name"="page", "dataType"="integer", "required"=false, "format"="default '1'", "description"="what page you want."},
- * {"name"="perPage", "dataType"="integer", "required"=false, "format"="default'30'", "description"="results per page."},
- * {"name"="tags", "dataType"="string", "required"=false, "format"="api,rest", "description"="a list of tags url encoded. Will returns entries that matches ALL tags."},
- * {"name"="since", "dataType"="integer", "required"=false, "format"="default '0'", "description"="The timestamp since when you want entries updated."},
- * }
- * )
- *
- * @return JsonResponse
- */
- public function getEntriesAction(Request $request)
- {
- $this->validateAuthentication();
-
- $isArchived = (null === $request->query->get('archive')) ? null : (bool) $request->query->get('archive');
- $isStarred = (null === $request->query->get('starred')) ? null : (bool) $request->query->get('starred');
- $sort = $request->query->get('sort', 'created');
- $order = $request->query->get('order', 'desc');
- $page = (int) $request->query->get('page', 1);
- $perPage = (int) $request->query->get('perPage', 30);
- $tags = $request->query->get('tags', '');
- $since = $request->query->get('since', 0);
-
- $pager = $this->getDoctrine()
- ->getRepository('WallabagCoreBundle:Entry')
- ->findEntries($this->getUser()->getId(), $isArchived, $isStarred, $sort, $order, $since, $tags);
-
- $pager->setCurrentPage($page);
- $pager->setMaxPerPage($perPage);
-
- $pagerfantaFactory = new PagerfantaFactory('page', 'perPage');
- $paginatedCollection = $pagerfantaFactory->createRepresentation(
- $pager,
- new Route(
- 'api_get_entries',
- [
- 'archive' => $isArchived,
- 'starred' => $isStarred,
- 'sort' => $sort,
- 'order' => $order,
- 'page' => $page,
- 'perPage' => $perPage,
- 'tags' => $tags,
- 'since' => $since,
- ],
- UrlGeneratorInterface::ABSOLUTE_URL
- )
- );
-
- $json = $this->get('serializer')->serialize($paginatedCollection, 'json');
-
- return (new JsonResponse())->setJson($json);
- }
-
- /**
- * Retrieve a single entry.
- *
- * @ApiDoc(
- * requirements={
- * {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"}
- * }
- * )
- *
- * @return JsonResponse
- */
- public function getEntryAction(Entry $entry)
- {
- $this->validateAuthentication();
- $this->validateUserAccess($entry->getUser()->getId());
-
- $json = $this->get('serializer')->serialize($entry, 'json');
-
- return (new JsonResponse())->setJson($json);
- }
-
- /**
- * Create an entry.
- *
- * @ApiDoc(
- * parameters={
- * {"name"="url", "dataType"="string", "required"=true, "format"="http://www.test.com/article.html", "description"="Url for the entry."},
- * {"name"="title", "dataType"="string", "required"=false, "description"="Optional, we'll get the title from the page."},
- * {"name"="tags", "dataType"="string", "required"=false, "format"="tag1,tag2,tag3", "description"="a comma-separated list of tags."},
- * {"name"="starred", "dataType"="integer", "required"=false, "format"="1 or 0", "description"="entry already starred"},
- * {"name"="archive", "dataType"="integer", "required"=false, "format"="1 or 0", "description"="entry already archived"},
- * }
- * )
- *
- * @return JsonResponse
- */
- public function postEntriesAction(Request $request)
- {
- $this->validateAuthentication();
-
- $url = $request->request->get('url');
- $title = $request->request->get('title');
- $isArchived = $request->request->get('archive');
- $isStarred = $request->request->get('starred');
-
- $entry = $this->get('wallabag_core.entry_repository')->findByUrlAndUserId($url, $this->getUser()->getId());
-
- if (false === $entry) {
- $entry = $this->get('wallabag_core.content_proxy')->updateEntry(
- new Entry($this->getUser()),
- $url
- );
- }
-
- if (!is_null($title)) {
- $entry->setTitle($title);
- }
-
- $tags = $request->request->get('tags', '');
- if (!empty($tags)) {
- $this->get('wallabag_core.content_proxy')->assignTagsToEntry($entry, $tags);
- }
-
- if (!is_null($isStarred)) {
- $entry->setStarred((bool) $isStarred);
- }
-
- if (!is_null($isArchived)) {
- $entry->setArchived((bool) $isArchived);
- }
-
- $em = $this->getDoctrine()->getManager();
- $em->persist($entry);
-
- $em->flush();
-
- $json = $this->get('serializer')->serialize($entry, 'json');
-
- return (new JsonResponse())->setJson($json);
- }
-
- /**
- * Change several properties of an entry.
- *
- * @ApiDoc(
- * requirements={
- * {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"}
- * },
- * parameters={
- * {"name"="title", "dataType"="string", "required"=false},
- * {"name"="tags", "dataType"="string", "required"=false, "format"="tag1,tag2,tag3", "description"="a comma-separated list of tags."},
- * {"name"="archive", "dataType"="integer", "required"=false, "format"="1 or 0", "description"="archived the entry."},
- * {"name"="starred", "dataType"="integer", "required"=false, "format"="1 or 0", "description"="starred the entry."},
- * }
- * )
- *
- * @return JsonResponse
- */
- public function patchEntriesAction(Entry $entry, Request $request)
- {
- $this->validateAuthentication();
- $this->validateUserAccess($entry->getUser()->getId());
-
- $title = $request->request->get('title');
- $isArchived = $request->request->get('archive');
- $isStarred = $request->request->get('starred');
-
- if (!is_null($title)) {
- $entry->setTitle($title);
- }
-
- if (!is_null($isArchived)) {
- $entry->setArchived((bool) $isArchived);
- }
-
- if (!is_null($isStarred)) {
- $entry->setStarred((bool) $isStarred);
- }
-
- $tags = $request->request->get('tags', '');
- if (!empty($tags)) {
- $this->get('wallabag_core.content_proxy')->assignTagsToEntry($entry, $tags);
- }
-
- $em = $this->getDoctrine()->getManager();
- $em->flush();
-
- $json = $this->get('serializer')->serialize($entry, 'json');
-
- return (new JsonResponse())->setJson($json);
- }
-
- /**
- * Delete **permanently** an entry.
- *
- * @ApiDoc(
- * requirements={
- * {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"}
- * }
- * )
- *
- * @return JsonResponse
- */
- public function deleteEntriesAction(Entry $entry)
- {
- $this->validateAuthentication();
- $this->validateUserAccess($entry->getUser()->getId());
-
- $em = $this->getDoctrine()->getManager();
- $em->remove($entry);
- $em->flush();
-
- $json = $this->get('serializer')->serialize($entry, 'json');
-
- return (new JsonResponse())->setJson($json);
- }
-
- /**
- * Retrieve all tags for an entry.
- *
- * @ApiDoc(
- * requirements={
- * {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"}
- * }
- * )
- *
- * @return JsonResponse
- */
- public function getEntriesTagsAction(Entry $entry)
- {
- $this->validateAuthentication();
- $this->validateUserAccess($entry->getUser()->getId());
-
- $json = $this->get('serializer')->serialize($entry->getTags(), 'json');
-
- return (new JsonResponse())->setJson($json);
- }
-
- /**
- * Add one or more tags to an entry.
- *
- * @ApiDoc(
- * requirements={
- * {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"}
- * },
- * parameters={
- * {"name"="tags", "dataType"="string", "required"=false, "format"="tag1,tag2,tag3", "description"="a comma-separated list of tags."},
- * }
- * )
- *
- * @return JsonResponse
- */
- public function postEntriesTagsAction(Request $request, Entry $entry)
- {
- $this->validateAuthentication();
- $this->validateUserAccess($entry->getUser()->getId());
-
- $tags = $request->request->get('tags', '');
- if (!empty($tags)) {
- $this->get('wallabag_core.content_proxy')->assignTagsToEntry($entry, $tags);
- }
-
- $em = $this->getDoctrine()->getManager();
- $em->persist($entry);
- $em->flush();
-
- $json = $this->get('serializer')->serialize($entry, 'json');
-
- return (new JsonResponse())->setJson($json);
- }
-
- /**
- * Permanently remove one tag for an entry.
- *
- * @ApiDoc(
- * requirements={
- * {"name"="tag", "dataType"="integer", "requirement"="\w+", "description"="The tag ID"},
- * {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"}
- * }
- * )
- *
- * @return JsonResponse
- */
- public function deleteEntriesTagsAction(Entry $entry, Tag $tag)
- {
- $this->validateAuthentication();
- $this->validateUserAccess($entry->getUser()->getId());
-
- $entry->removeTag($tag);
- $em = $this->getDoctrine()->getManager();
- $em->persist($entry);
- $em->flush();
-
- $json = $this->get('serializer')->serialize($entry, 'json');
-
- return (new JsonResponse())->setJson($json);
- }
-
- /**
- * Retrieve all tags.
- *
- * @ApiDoc()
- *
- * @return JsonResponse
- */
- public function getTagsAction()
- {
- $this->validateAuthentication();
-
- $tags = $this->getDoctrine()
- ->getRepository('WallabagCoreBundle:Tag')
- ->findAllTags($this->getUser()->getId());
-
- $json = $this->get('serializer')->serialize($tags, 'json');
-
- return (new JsonResponse())->setJson($json);
- }
-
- /**
- * Permanently remove one tag from **every** entry.
- *
- * @ApiDoc(
- * requirements={
- * {"name"="tag", "dataType"="string", "required"=true, "requirement"="\w+", "description"="Tag as a string"}
- * }
- * )
- *
- * @return JsonResponse
- */
- public function deleteTagLabelAction(Request $request)
- {
- $this->validateAuthentication();
- $label = $request->request->get('tag', '');
-
- $tag = $this->getDoctrine()->getRepository('WallabagCoreBundle:Tag')->findOneByLabel($label);
-
- if (empty($tag)) {
- throw $this->createNotFoundException('Tag not found');
- }
-
- $this->getDoctrine()
- ->getRepository('WallabagCoreBundle:Entry')
- ->removeTag($this->getUser()->getId(), $tag);
-
- $this->cleanOrphanTag($tag);
-
- $json = $this->get('serializer')->serialize($tag, 'json');
-
- return (new JsonResponse())->setJson($json);
- }
-
- /**
- * Permanently remove some tags from **every** entry.
- *
- * @ApiDoc(
- * requirements={
- * {"name"="tags", "dataType"="string", "required"=true, "format"="tag1,tag2", "description"="Tags as strings (comma splitted)"}
- * }
- * )
- *
- * @return JsonResponse
- */
- public function deleteTagsLabelAction(Request $request)
- {
- $this->validateAuthentication();
-
- $tagsLabels = $request->request->get('tags', '');
-
- $tags = [];
-
- foreach (explode(',', $tagsLabels) as $tagLabel) {
- $tagEntity = $this->getDoctrine()->getRepository('WallabagCoreBundle:Tag')->findOneByLabel($tagLabel);
-
- if (!empty($tagEntity)) {
- $tags[] = $tagEntity;
- }
- }
-
- if (empty($tags)) {
- throw $this->createNotFoundException('Tags not found');
- }
-
- $this->getDoctrine()
- ->getRepository('WallabagCoreBundle:Entry')
- ->removeTags($this->getUser()->getId(), $tags);
-
- $this->cleanOrphanTag($tags);
-
- $json = $this->get('serializer')->serialize($tags, 'json');
-
- return (new JsonResponse())->setJson($json);
- }
-
- /**
- * Permanently remove one tag from **every** entry.
- *
- * @ApiDoc(
- * requirements={
- * {"name"="tag", "dataType"="integer", "requirement"="\w+", "description"="The tag"}
- * }
- * )
- *
- * @return JsonResponse
- */
- public function deleteTagAction(Tag $tag)
- {
- $this->validateAuthentication();
-
- $this->getDoctrine()
- ->getRepository('WallabagCoreBundle:Entry')
- ->removeTag($this->getUser()->getId(), $tag);
-
- $this->cleanOrphanTag($tag);
-
- $json = $this->get('serializer')->serialize($tag, 'json');
-
- return (new JsonResponse())->setJson($json);
- }
-
- /**
- * Retrieve version number.
- *
- * @ApiDoc()
- *
- * @return JsonResponse
- */
- public function getVersionAction()
- {
- $version = $this->container->getParameter('wallabag_core.version');
-
- $json = $this->get('serializer')->serialize($version, 'json');
-
- return (new JsonResponse())->setJson($json);
- }
-
- /**
- * Remove orphan tag in case no entries are associated to it.
- *
- * @param Tag|array $tags
- */
- private function cleanOrphanTag($tags)
- {
- if (!is_array($tags)) {
- $tags = [$tags];
- }
-
- $em = $this->getDoctrine()->getManager();
-
- foreach ($tags as $tag) {
- if (count($tag->getEntries()) === 0) {
- $em->remove($tag);
- }
- }
-
- $em->flush();
- }
-
/**
* Validate that the first id is equal to the second one.
* If not, throw exception. It means a user try to access information from an other user.
*
* @param int $requestUserId User id from the requested source
*/
- private function validateUserAccess($requestUserId)
+ protected function validateUserAccess($requestUserId)
{
$user = $this->get('security.token_storage')->getToken()->getUser();
if ($requestUserId != $user->getId()) {
diff --git a/src/Wallabag/ApiBundle/Resources/config/routing_rest.yml b/src/Wallabag/ApiBundle/Resources/config/routing_rest.yml
index 5f43f9716..901cf449c 100644
--- a/src/Wallabag/ApiBundle/Resources/config/routing_rest.yml
+++ b/src/Wallabag/ApiBundle/Resources/config/routing_rest.yml
@@ -1,4 +1,14 @@
-entries:
+api:
type: rest
resource: "WallabagApiBundle:WallabagRest"
name_prefix: api_
+
+entries:
+ type: rest
+ resource: "WallabagApiBundle:EntryRest"
+ name_prefix: api_
+
+tags:
+ type: rest
+ resource: "WallabagApiBundle:TagRest"
+ name_prefix: api_
diff --git a/tests/Wallabag/ApiBundle/Controller/EntryRestControllerTest.php b/tests/Wallabag/ApiBundle/Controller/EntryRestControllerTest.php
new file mode 100644
index 000000000..825f8f7ad
--- /dev/null
+++ b/tests/Wallabag/ApiBundle/Controller/EntryRestControllerTest.php
@@ -0,0 +1,673 @@
+client->getContainer()
+ ->get('doctrine.orm.entity_manager')
+ ->getRepository('WallabagCoreBundle:Entry')
+ ->findOneBy(['user' => 1, 'isArchived' => false]);
+
+ if (!$entry) {
+ $this->markTestSkipped('No content found in db.');
+ }
+
+ $this->client->request('GET', '/api/entries/'.$entry->getId().'.json');
+ $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+
+ $content = json_decode($this->client->getResponse()->getContent(), true);
+
+ $this->assertEquals($entry->getTitle(), $content['title']);
+ $this->assertEquals($entry->getUrl(), $content['url']);
+ $this->assertCount(count($entry->getTags()), $content['tags']);
+ $this->assertEquals($entry->getUserName(), $content['user_name']);
+ $this->assertEquals($entry->getUserEmail(), $content['user_email']);
+ $this->assertEquals($entry->getUserId(), $content['user_id']);
+
+ $this->assertTrue(
+ $this->client->getResponse()->headers->contains(
+ 'Content-Type',
+ 'application/json'
+ )
+ );
+ }
+
+ public function testGetOneEntryWrongUser()
+ {
+ $entry = $this->client->getContainer()
+ ->get('doctrine.orm.entity_manager')
+ ->getRepository('WallabagCoreBundle:Entry')
+ ->findOneBy(['user' => 2, 'isArchived' => false]);
+
+ if (!$entry) {
+ $this->markTestSkipped('No content found in db.');
+ }
+
+ $this->client->request('GET', '/api/entries/'.$entry->getId().'.json');
+
+ $this->assertEquals(403, $this->client->getResponse()->getStatusCode());
+ }
+
+ public function testGetEntries()
+ {
+ $this->client->request('GET', '/api/entries');
+
+ $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+
+ $content = json_decode($this->client->getResponse()->getContent(), true);
+
+ $this->assertGreaterThanOrEqual(1, count($content));
+ $this->assertNotEmpty($content['_embedded']['items']);
+ $this->assertGreaterThanOrEqual(1, $content['total']);
+ $this->assertEquals(1, $content['page']);
+ $this->assertGreaterThanOrEqual(1, $content['pages']);
+
+ $this->assertTrue(
+ $this->client->getResponse()->headers->contains(
+ 'Content-Type',
+ 'application/json'
+ )
+ );
+ }
+
+ public function testGetEntriesWithFullOptions()
+ {
+ $this->client->request('GET', '/api/entries', [
+ 'archive' => 1,
+ 'starred' => 1,
+ 'sort' => 'updated',
+ 'order' => 'asc',
+ 'page' => 1,
+ 'perPage' => 2,
+ 'tags' => 'foo',
+ 'since' => 1443274283,
+ ]);
+
+ $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+
+ $content = json_decode($this->client->getResponse()->getContent(), true);
+
+ $this->assertGreaterThanOrEqual(1, count($content));
+ $this->assertArrayHasKey('items', $content['_embedded']);
+ $this->assertGreaterThanOrEqual(0, $content['total']);
+ $this->assertEquals(1, $content['page']);
+ $this->assertEquals(2, $content['limit']);
+ $this->assertGreaterThanOrEqual(1, $content['pages']);
+
+ $this->assertArrayHasKey('_links', $content);
+ $this->assertArrayHasKey('self', $content['_links']);
+ $this->assertArrayHasKey('first', $content['_links']);
+ $this->assertArrayHasKey('last', $content['_links']);
+
+ foreach (['self', 'first', 'last'] as $link) {
+ $this->assertArrayHasKey('href', $content['_links'][$link]);
+ $this->assertContains('archive=1', $content['_links'][$link]['href']);
+ $this->assertContains('starred=1', $content['_links'][$link]['href']);
+ $this->assertContains('sort=updated', $content['_links'][$link]['href']);
+ $this->assertContains('order=asc', $content['_links'][$link]['href']);
+ $this->assertContains('tags=foo', $content['_links'][$link]['href']);
+ $this->assertContains('since=1443274283', $content['_links'][$link]['href']);
+ }
+
+ $this->assertTrue(
+ $this->client->getResponse()->headers->contains(
+ 'Content-Type',
+ 'application/json'
+ )
+ );
+ }
+
+ public function testGetStarredEntries()
+ {
+ $this->client->request('GET', '/api/entries', ['starred' => 1, 'sort' => 'updated']);
+
+ $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+
+ $content = json_decode($this->client->getResponse()->getContent(), true);
+
+ $this->assertGreaterThanOrEqual(1, count($content));
+ $this->assertNotEmpty($content['_embedded']['items']);
+ $this->assertGreaterThanOrEqual(1, $content['total']);
+ $this->assertEquals(1, $content['page']);
+ $this->assertGreaterThanOrEqual(1, $content['pages']);
+
+ $this->assertArrayHasKey('_links', $content);
+ $this->assertArrayHasKey('self', $content['_links']);
+ $this->assertArrayHasKey('first', $content['_links']);
+ $this->assertArrayHasKey('last', $content['_links']);
+
+ foreach (['self', 'first', 'last'] as $link) {
+ $this->assertArrayHasKey('href', $content['_links'][$link]);
+ $this->assertContains('starred=1', $content['_links'][$link]['href']);
+ $this->assertContains('sort=updated', $content['_links'][$link]['href']);
+ }
+
+ $this->assertTrue(
+ $this->client->getResponse()->headers->contains(
+ 'Content-Type',
+ 'application/json'
+ )
+ );
+ }
+
+ public function testGetArchiveEntries()
+ {
+ $this->client->request('GET', '/api/entries', ['archive' => 1]);
+
+ $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+
+ $content = json_decode($this->client->getResponse()->getContent(), true);
+
+ $this->assertGreaterThanOrEqual(1, count($content));
+ $this->assertNotEmpty($content['_embedded']['items']);
+ $this->assertGreaterThanOrEqual(1, $content['total']);
+ $this->assertEquals(1, $content['page']);
+ $this->assertGreaterThanOrEqual(1, $content['pages']);
+
+ $this->assertArrayHasKey('_links', $content);
+ $this->assertArrayHasKey('self', $content['_links']);
+ $this->assertArrayHasKey('first', $content['_links']);
+ $this->assertArrayHasKey('last', $content['_links']);
+
+ foreach (['self', 'first', 'last'] as $link) {
+ $this->assertArrayHasKey('href', $content['_links'][$link]);
+ $this->assertContains('archive=1', $content['_links'][$link]['href']);
+ }
+
+ $this->assertTrue(
+ $this->client->getResponse()->headers->contains(
+ 'Content-Type',
+ 'application/json'
+ )
+ );
+ }
+
+ public function testGetTaggedEntries()
+ {
+ $this->client->request('GET', '/api/entries', ['tags' => 'foo,bar']);
+
+ $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+
+ $content = json_decode($this->client->getResponse()->getContent(), true);
+
+ $this->assertGreaterThanOrEqual(1, count($content));
+ $this->assertNotEmpty($content['_embedded']['items']);
+ $this->assertGreaterThanOrEqual(1, $content['total']);
+ $this->assertEquals(1, $content['page']);
+ $this->assertGreaterThanOrEqual(1, $content['pages']);
+
+ $this->assertArrayHasKey('_links', $content);
+ $this->assertArrayHasKey('self', $content['_links']);
+ $this->assertArrayHasKey('first', $content['_links']);
+ $this->assertArrayHasKey('last', $content['_links']);
+
+ foreach (['self', 'first', 'last'] as $link) {
+ $this->assertArrayHasKey('href', $content['_links'][$link]);
+ $this->assertContains('tags='.urlencode('foo,bar'), $content['_links'][$link]['href']);
+ }
+
+ $this->assertTrue(
+ $this->client->getResponse()->headers->contains(
+ 'Content-Type',
+ 'application/json'
+ )
+ );
+ }
+
+ public function testGetDatedEntries()
+ {
+ $this->client->request('GET', '/api/entries', ['since' => 1443274283]);
+
+ $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+
+ $content = json_decode($this->client->getResponse()->getContent(), true);
+
+ $this->assertGreaterThanOrEqual(1, count($content));
+ $this->assertNotEmpty($content['_embedded']['items']);
+ $this->assertGreaterThanOrEqual(1, $content['total']);
+ $this->assertEquals(1, $content['page']);
+ $this->assertGreaterThanOrEqual(1, $content['pages']);
+
+ $this->assertArrayHasKey('_links', $content);
+ $this->assertArrayHasKey('self', $content['_links']);
+ $this->assertArrayHasKey('first', $content['_links']);
+ $this->assertArrayHasKey('last', $content['_links']);
+
+ foreach (['self', 'first', 'last'] as $link) {
+ $this->assertArrayHasKey('href', $content['_links'][$link]);
+ $this->assertContains('since=1443274283', $content['_links'][$link]['href']);
+ }
+
+ $this->assertTrue(
+ $this->client->getResponse()->headers->contains(
+ 'Content-Type',
+ 'application/json'
+ )
+ );
+ }
+
+ public function testGetDatedSupEntries()
+ {
+ $future = new \DateTime(date('Y-m-d H:i:s'));
+ $this->client->request('GET', '/api/entries', ['since' => $future->getTimestamp() + 1000]);
+
+ $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+
+ $content = json_decode($this->client->getResponse()->getContent(), true);
+
+ $this->assertGreaterThanOrEqual(1, count($content));
+ $this->assertEmpty($content['_embedded']['items']);
+ $this->assertEquals(0, $content['total']);
+ $this->assertEquals(1, $content['page']);
+ $this->assertEquals(1, $content['pages']);
+
+ $this->assertArrayHasKey('_links', $content);
+ $this->assertArrayHasKey('self', $content['_links']);
+ $this->assertArrayHasKey('first', $content['_links']);
+ $this->assertArrayHasKey('last', $content['_links']);
+
+ foreach (['self', 'first', 'last'] as $link) {
+ $this->assertArrayHasKey('href', $content['_links'][$link]);
+ $this->assertContains('since='.($future->getTimestamp() + 1000), $content['_links'][$link]['href']);
+ }
+
+ $this->assertTrue(
+ $this->client->getResponse()->headers->contains(
+ 'Content-Type',
+ 'application/json'
+ )
+ );
+ }
+
+ public function testDeleteEntry()
+ {
+ $entry = $this->client->getContainer()
+ ->get('doctrine.orm.entity_manager')
+ ->getRepository('WallabagCoreBundle:Entry')
+ ->findOneByUser(1);
+
+ if (!$entry) {
+ $this->markTestSkipped('No content found in db.');
+ }
+
+ $this->client->request('DELETE', '/api/entries/'.$entry->getId().'.json');
+
+ $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+
+ $content = json_decode($this->client->getResponse()->getContent(), true);
+
+ $this->assertEquals($entry->getTitle(), $content['title']);
+ $this->assertEquals($entry->getUrl(), $content['url']);
+
+ // We'll try to delete this entry again
+ $this->client->request('DELETE', '/api/entries/'.$entry->getId().'.json');
+
+ $this->assertEquals(404, $this->client->getResponse()->getStatusCode());
+ }
+
+ public function testPostEntry()
+ {
+ $this->client->request('POST', '/api/entries.json', [
+ 'url' => 'http://www.lemonde.fr/pixels/article/2015/03/28/plongee-dans-l-univers-d-ingress-le-jeu-de-google-aux-frontieres-du-reel_4601155_4408996.html',
+ 'tags' => 'google',
+ 'title' => 'New title for my article',
+ ]);
+
+ $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+
+ $content = json_decode($this->client->getResponse()->getContent(), true);
+
+ $this->assertGreaterThan(0, $content['id']);
+ $this->assertEquals('http://www.lemonde.fr/pixels/article/2015/03/28/plongee-dans-l-univers-d-ingress-le-jeu-de-google-aux-frontieres-du-reel_4601155_4408996.html', $content['url']);
+ $this->assertEquals(false, $content['is_archived']);
+ $this->assertEquals(false, $content['is_starred']);
+ $this->assertEquals('New title for my article', $content['title']);
+ $this->assertEquals(1, $content['user_id']);
+ $this->assertCount(1, $content['tags']);
+ }
+
+ public function testPostSameEntry()
+ {
+ $this->client->request('POST', '/api/entries.json', [
+ 'url' => 'http://www.lemonde.fr/pixels/article/2015/03/28/plongee-dans-l-univers-d-ingress-le-jeu-de-google-aux-frontieres-du-reel_4601155_4408996.html',
+ 'archive' => '1',
+ 'tags' => 'google, apple',
+ ]);
+
+ $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+
+ $content = json_decode($this->client->getResponse()->getContent(), true);
+
+ $this->assertGreaterThan(0, $content['id']);
+ $this->assertEquals('http://www.lemonde.fr/pixels/article/2015/03/28/plongee-dans-l-univers-d-ingress-le-jeu-de-google-aux-frontieres-du-reel_4601155_4408996.html', $content['url']);
+ $this->assertEquals(true, $content['is_archived']);
+ $this->assertEquals(false, $content['is_starred']);
+ $this->assertCount(2, $content['tags']);
+ }
+
+ public function testPostArchivedAndStarredEntry()
+ {
+ $this->client->request('POST', '/api/entries.json', [
+ 'url' => 'http://www.lemonde.fr/idees/article/2016/02/08/preserver-la-liberte-d-expression-sur-les-reseaux-sociaux_4861503_3232.html',
+ 'archive' => '1',
+ 'starred' => '1',
+ ]);
+
+ $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+
+ $content = json_decode($this->client->getResponse()->getContent(), true);
+
+ $this->assertGreaterThan(0, $content['id']);
+ $this->assertEquals('http://www.lemonde.fr/idees/article/2016/02/08/preserver-la-liberte-d-expression-sur-les-reseaux-sociaux_4861503_3232.html', $content['url']);
+ $this->assertEquals(true, $content['is_archived']);
+ $this->assertEquals(true, $content['is_starred']);
+ $this->assertEquals(1, $content['user_id']);
+ }
+
+ public function testPostArchivedAndStarredEntryWithoutQuotes()
+ {
+ $this->client->request('POST', '/api/entries.json', [
+ 'url' => 'http://www.lemonde.fr/idees/article/2016/02/08/preserver-la-liberte-d-expression-sur-les-reseaux-sociaux_4861503_3232.html',
+ 'archive' => 0,
+ 'starred' => 1,
+ ]);
+
+ $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+
+ $content = json_decode($this->client->getResponse()->getContent(), true);
+
+ $this->assertGreaterThan(0, $content['id']);
+ $this->assertEquals('http://www.lemonde.fr/idees/article/2016/02/08/preserver-la-liberte-d-expression-sur-les-reseaux-sociaux_4861503_3232.html', $content['url']);
+ $this->assertEquals(false, $content['is_archived']);
+ $this->assertEquals(true, $content['is_starred']);
+ }
+
+ public function testPatchEntry()
+ {
+ $entry = $this->client->getContainer()
+ ->get('doctrine.orm.entity_manager')
+ ->getRepository('WallabagCoreBundle:Entry')
+ ->findOneByUser(1);
+
+ if (!$entry) {
+ $this->markTestSkipped('No content found in db.');
+ }
+
+ // hydrate the tags relations
+ $nbTags = count($entry->getTags());
+
+ $this->client->request('PATCH', '/api/entries/'.$entry->getId().'.json', [
+ 'title' => 'New awesome title',
+ 'tags' => 'new tag '.uniqid(),
+ 'starred' => '1',
+ 'archive' => '0',
+ ]);
+
+ $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+
+ $content = json_decode($this->client->getResponse()->getContent(), true);
+
+ $this->assertEquals($entry->getId(), $content['id']);
+ $this->assertEquals($entry->getUrl(), $content['url']);
+ $this->assertEquals('New awesome title', $content['title']);
+ $this->assertGreaterThan($nbTags, count($content['tags']));
+ $this->assertEquals(1, $content['user_id']);
+ }
+
+ public function testPatchEntryWithoutQuotes()
+ {
+ $entry = $this->client->getContainer()
+ ->get('doctrine.orm.entity_manager')
+ ->getRepository('WallabagCoreBundle:Entry')
+ ->findOneByUser(1);
+
+ if (!$entry) {
+ $this->markTestSkipped('No content found in db.');
+ }
+
+ // hydrate the tags relations
+ $nbTags = count($entry->getTags());
+
+ $this->client->request('PATCH', '/api/entries/'.$entry->getId().'.json', [
+ 'title' => 'New awesome title',
+ 'tags' => 'new tag '.uniqid(),
+ 'starred' => 1,
+ 'archive' => 0,
+ ]);
+
+ $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+
+ $content = json_decode($this->client->getResponse()->getContent(), true);
+
+ $this->assertEquals($entry->getId(), $content['id']);
+ $this->assertEquals($entry->getUrl(), $content['url']);
+ $this->assertEquals('New awesome title', $content['title']);
+ $this->assertGreaterThan($nbTags, count($content['tags']));
+ }
+
+ public function testGetTagsEntry()
+ {
+ $entry = $this->client->getContainer()
+ ->get('doctrine.orm.entity_manager')
+ ->getRepository('WallabagCoreBundle:Entry')
+ ->findOneWithTags($this->user->getId());
+
+ $entry = $entry[0];
+
+ if (!$entry) {
+ $this->markTestSkipped('No content found in db.');
+ }
+
+ $tags = [];
+ foreach ($entry->getTags() as $tag) {
+ $tags[] = ['id' => $tag->getId(), 'label' => $tag->getLabel(), 'slug' => $tag->getSlug()];
+ }
+
+ $this->client->request('GET', '/api/entries/'.$entry->getId().'/tags');
+
+ $this->assertEquals(json_encode($tags, JSON_HEX_QUOT), $this->client->getResponse()->getContent());
+ }
+
+ public function testPostTagsOnEntry()
+ {
+ $entry = $this->client->getContainer()
+ ->get('doctrine.orm.entity_manager')
+ ->getRepository('WallabagCoreBundle:Entry')
+ ->findOneByUser(1);
+
+ if (!$entry) {
+ $this->markTestSkipped('No content found in db.');
+ }
+
+ $nbTags = count($entry->getTags());
+
+ $newTags = 'tag1,tag2,tag3';
+
+ $this->client->request('POST', '/api/entries/'.$entry->getId().'/tags', ['tags' => $newTags]);
+
+ $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+
+ $content = json_decode($this->client->getResponse()->getContent(), true);
+
+ $this->assertArrayHasKey('tags', $content);
+ $this->assertEquals($nbTags + 3, count($content['tags']));
+
+ $entryDB = $this->client->getContainer()
+ ->get('doctrine.orm.entity_manager')
+ ->getRepository('WallabagCoreBundle:Entry')
+ ->find($entry->getId());
+
+ $tagsInDB = [];
+ foreach ($entryDB->getTags()->toArray() as $tag) {
+ $tagsInDB[$tag->getId()] = $tag->getLabel();
+ }
+
+ foreach (explode(',', $newTags) as $tag) {
+ $this->assertContains($tag, $tagsInDB);
+ }
+ }
+
+ public function testDeleteOneTagEntry()
+ {
+ $entry = $this->client->getContainer()
+ ->get('doctrine.orm.entity_manager')
+ ->getRepository('WallabagCoreBundle:Entry')
+ ->findOneWithTags($this->user->getId());
+ $entry = $entry[0];
+
+ if (!$entry) {
+ $this->markTestSkipped('No content found in db.');
+ }
+
+ // hydrate the tags relations
+ $nbTags = count($entry->getTags());
+ $tag = $entry->getTags()[0];
+
+ $this->client->request('DELETE', '/api/entries/'.$entry->getId().'/tags/'.$tag->getId().'.json');
+
+ $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+
+ $content = json_decode($this->client->getResponse()->getContent(), true);
+
+ $this->assertArrayHasKey('tags', $content);
+ $this->assertEquals($nbTags - 1, count($content['tags']));
+ }
+
+ public function testSaveIsArchivedAfterPost()
+ {
+ $entry = $this->client->getContainer()
+ ->get('doctrine.orm.entity_manager')
+ ->getRepository('WallabagCoreBundle:Entry')
+ ->findOneBy(['user' => 1, 'isArchived' => true]);
+
+ if (!$entry) {
+ $this->markTestSkipped('No content found in db.');
+ }
+
+ $this->client->request('POST', '/api/entries.json', [
+ 'url' => $entry->getUrl(),
+ ]);
+
+ $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+
+ $content = json_decode($this->client->getResponse()->getContent(), true);
+
+ $this->assertEquals(true, $content['is_archived']);
+ }
+
+ public function testSaveIsStarredAfterPost()
+ {
+ $entry = $this->client->getContainer()
+ ->get('doctrine.orm.entity_manager')
+ ->getRepository('WallabagCoreBundle:Entry')
+ ->findOneBy(['user' => 1, 'isStarred' => true]);
+
+ if (!$entry) {
+ $this->markTestSkipped('No content found in db.');
+ }
+
+ $this->client->request('POST', '/api/entries.json', [
+ 'url' => $entry->getUrl(),
+ ]);
+
+ $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+
+ $content = json_decode($this->client->getResponse()->getContent(), true);
+
+ $this->assertEquals(true, $content['is_starred']);
+ }
+
+ public function testSaveIsArchivedAfterPatch()
+ {
+ $entry = $this->client->getContainer()
+ ->get('doctrine.orm.entity_manager')
+ ->getRepository('WallabagCoreBundle:Entry')
+ ->findOneBy(['user' => 1, 'isArchived' => true]);
+
+ if (!$entry) {
+ $this->markTestSkipped('No content found in db.');
+ }
+
+ $this->client->request('PATCH', '/api/entries/'.$entry->getId().'.json', [
+ 'title' => $entry->getTitle().'++',
+ ]);
+
+ $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+
+ $content = json_decode($this->client->getResponse()->getContent(), true);
+
+ $this->assertEquals(true, $content['is_archived']);
+ }
+
+ public function testSaveIsStarredAfterPatch()
+ {
+ $entry = $this->client->getContainer()
+ ->get('doctrine.orm.entity_manager')
+ ->getRepository('WallabagCoreBundle:Entry')
+ ->findOneBy(['user' => 1, 'isStarred' => true]);
+
+ if (!$entry) {
+ $this->markTestSkipped('No content found in db.');
+ }
+ $this->client->request('PATCH', '/api/entries/'.$entry->getId().'.json', [
+ 'title' => $entry->getTitle().'++',
+ ]);
+
+ $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+
+ $content = json_decode($this->client->getResponse()->getContent(), true);
+
+ $this->assertEquals(true, $content['is_starred']);
+ }
+
+ public function testGetEntriesExists()
+ {
+ $this->client->request('GET', '/api/entries/exists?url=http://0.0.0.0/entry2');
+
+ $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+
+ $content = json_decode($this->client->getResponse()->getContent(), true);
+
+ $this->assertEquals(true, $content['exists']);
+ }
+
+ public function testGetEntriesExistsWithManyUrls()
+ {
+ $url1 = 'http://0.0.0.0/entry2';
+ $url2 = 'http://0.0.0.0/entry10';
+ $this->client->request('GET', '/api/entries/exists?urls[]='.$url1.'&urls[]='.$url2);
+
+ $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+
+ $content = json_decode($this->client->getResponse()->getContent(), true);
+
+ $this->assertArrayHasKey($url1, $content);
+ $this->assertArrayHasKey($url2, $content);
+ $this->assertEquals(true, $content[$url1]);
+ $this->assertEquals(false, $content[$url2]);
+ }
+
+ public function testGetEntriesExistsWhichDoesNotExists()
+ {
+ $this->client->request('GET', '/api/entries/exists?url=http://google.com/entry2');
+
+ $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+
+ $content = json_decode($this->client->getResponse()->getContent(), true);
+
+ $this->assertEquals(false, $content['exists']);
+ }
+
+ public function testGetEntriesExistsWithNoUrl()
+ {
+ $this->client->request('GET', '/api/entries/exists?url=');
+
+ $this->assertEquals(403, $this->client->getResponse()->getStatusCode());
+ }
+}
diff --git a/tests/Wallabag/ApiBundle/Controller/TagRestControllerTest.php b/tests/Wallabag/ApiBundle/Controller/TagRestControllerTest.php
new file mode 100644
index 000000000..bde5251f5
--- /dev/null
+++ b/tests/Wallabag/ApiBundle/Controller/TagRestControllerTest.php
@@ -0,0 +1,162 @@
+client->request('GET', '/api/tags.json');
+
+ $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+
+ $content = json_decode($this->client->getResponse()->getContent(), true);
+
+ $this->assertGreaterThan(0, $content);
+ $this->assertArrayHasKey('id', $content[0]);
+ $this->assertArrayHasKey('label', $content[0]);
+
+ return end($content);
+ }
+
+ /**
+ * @depends testGetUserTags
+ */
+ public function testDeleteUserTag($tag)
+ {
+ $tagName = $tag['label'];
+
+ $this->client->request('DELETE', '/api/tags/'.$tag['id'].'.json');
+
+ $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+
+ $content = json_decode($this->client->getResponse()->getContent(), true);
+
+ $this->assertArrayHasKey('label', $content);
+ $this->assertEquals($tag['label'], $content['label']);
+ $this->assertEquals($tag['slug'], $content['slug']);
+
+ $entries = $this->client->getContainer()
+ ->get('doctrine.orm.entity_manager')
+ ->getRepository('WallabagCoreBundle:Entry')
+ ->findAllByTagId($this->user->getId(), $tag['id']);
+
+ $this->assertCount(0, $entries);
+
+ $tag = $this->client->getContainer()
+ ->get('doctrine.orm.entity_manager')
+ ->getRepository('WallabagCoreBundle:Tag')
+ ->findOneByLabel($tagName);
+
+ $this->assertNull($tag, $tagName.' was removed because it begun an orphan tag');
+ }
+
+ public function testDeleteTagByLabel()
+ {
+ $em = $this->client->getContainer()->get('doctrine.orm.entity_manager');
+ $entry = $this->client->getContainer()
+ ->get('doctrine.orm.entity_manager')
+ ->getRepository('WallabagCoreBundle:Entry')
+ ->findOneWithTags($this->user->getId());
+
+ $entry = $entry[0];
+
+ $tag = new Tag();
+ $tag->setLabel('Awesome tag for test');
+ $em->persist($tag);
+
+ $entry->addTag($tag);
+
+ $em->persist($entry);
+ $em->flush();
+
+ $this->client->request('DELETE', '/api/tag/label.json', ['tag' => $tag->getLabel()]);
+
+ $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+
+ $content = json_decode($this->client->getResponse()->getContent(), true);
+
+ $this->assertArrayHasKey('label', $content);
+ $this->assertEquals($tag->getLabel(), $content['label']);
+ $this->assertEquals($tag->getSlug(), $content['slug']);
+
+ $entries = $this->client->getContainer()
+ ->get('doctrine.orm.entity_manager')
+ ->getRepository('WallabagCoreBundle:Entry')
+ ->findAllByTagId($this->user->getId(), $tag->getId());
+
+ $this->assertCount(0, $entries);
+ }
+
+ public function testDeleteTagByLabelNotFound()
+ {
+ $this->client->request('DELETE', '/api/tag/label.json', ['tag' => 'does not exist']);
+
+ $this->assertEquals(404, $this->client->getResponse()->getStatusCode());
+ }
+
+ public function testDeleteTagsByLabel()
+ {
+ $em = $this->client->getContainer()->get('doctrine.orm.entity_manager');
+ $entry = $this->client->getContainer()
+ ->get('doctrine.orm.entity_manager')
+ ->getRepository('WallabagCoreBundle:Entry')
+ ->findOneWithTags($this->user->getId());
+
+ $entry = $entry[0];
+
+ $tag = new Tag();
+ $tag->setLabel('Awesome tag for tagsLabel');
+ $em->persist($tag);
+
+ $tag2 = new Tag();
+ $tag2->setLabel('Awesome tag for tagsLabel 2');
+ $em->persist($tag2);
+
+ $entry->addTag($tag);
+ $entry->addTag($tag2);
+
+ $em->persist($entry);
+ $em->flush();
+
+ $this->client->request('DELETE', '/api/tags/label.json', ['tags' => $tag->getLabel().','.$tag2->getLabel()]);
+
+ $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+
+ $content = json_decode($this->client->getResponse()->getContent(), true);
+
+ $this->assertCount(2, $content);
+
+ $this->assertArrayHasKey('label', $content[0]);
+ $this->assertEquals($tag->getLabel(), $content[0]['label']);
+ $this->assertEquals($tag->getSlug(), $content[0]['slug']);
+
+ $this->assertArrayHasKey('label', $content[1]);
+ $this->assertEquals($tag2->getLabel(), $content[1]['label']);
+ $this->assertEquals($tag2->getSlug(), $content[1]['slug']);
+
+ $entries = $this->client->getContainer()
+ ->get('doctrine.orm.entity_manager')
+ ->getRepository('WallabagCoreBundle:Entry')
+ ->findAllByTagId($this->user->getId(), $tag->getId());
+
+ $this->assertCount(0, $entries);
+
+ $entries = $this->client->getContainer()
+ ->get('doctrine.orm.entity_manager')
+ ->getRepository('WallabagCoreBundle:Entry')
+ ->findAllByTagId($this->user->getId(), $tag2->getId());
+
+ $this->assertCount(0, $entries);
+ }
+
+ public function testDeleteTagsByLabelNotFound()
+ {
+ $this->client->request('DELETE', '/api/tags/label.json', ['tags' => 'does not exist']);
+
+ $this->assertEquals(404, $this->client->getResponse()->getStatusCode());
+ }
+}
diff --git a/tests/Wallabag/ApiBundle/Controller/WallabagRestControllerTest.php b/tests/Wallabag/ApiBundle/Controller/WallabagRestControllerTest.php
index 5dcb3e000..c87e58de0 100644
--- a/tests/Wallabag/ApiBundle/Controller/WallabagRestControllerTest.php
+++ b/tests/Wallabag/ApiBundle/Controller/WallabagRestControllerTest.php
@@ -3,697 +3,9 @@
namespace Tests\Wallabag\ApiBundle\Controller;
use Tests\Wallabag\ApiBundle\WallabagApiTestCase;
-use Wallabag\CoreBundle\Entity\Tag;
class WallabagRestControllerTest extends WallabagApiTestCase
{
- protected static $salt;
-
- public function testGetOneEntry()
- {
- $entry = $this->client->getContainer()
- ->get('doctrine.orm.entity_manager')
- ->getRepository('WallabagCoreBundle:Entry')
- ->findOneBy(['user' => 1, 'isArchived' => false]);
-
- if (!$entry) {
- $this->markTestSkipped('No content found in db.');
- }
-
- $this->client->request('GET', '/api/entries/'.$entry->getId().'.json');
- $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
-
- $content = json_decode($this->client->getResponse()->getContent(), true);
-
- $this->assertEquals($entry->getTitle(), $content['title']);
- $this->assertEquals($entry->getUrl(), $content['url']);
- $this->assertCount(count($entry->getTags()), $content['tags']);
- $this->assertEquals($entry->getUserName(), $content['user_name']);
- $this->assertEquals($entry->getUserEmail(), $content['user_email']);
- $this->assertEquals($entry->getUserId(), $content['user_id']);
-
- $this->assertTrue(
- $this->client->getResponse()->headers->contains(
- 'Content-Type',
- 'application/json'
- )
- );
- }
-
- public function testGetOneEntryWrongUser()
- {
- $entry = $this->client->getContainer()
- ->get('doctrine.orm.entity_manager')
- ->getRepository('WallabagCoreBundle:Entry')
- ->findOneBy(['user' => 2, 'isArchived' => false]);
-
- if (!$entry) {
- $this->markTestSkipped('No content found in db.');
- }
-
- $this->client->request('GET', '/api/entries/'.$entry->getId().'.json');
-
- $this->assertEquals(403, $this->client->getResponse()->getStatusCode());
- }
-
- public function testGetEntries()
- {
- $this->client->request('GET', '/api/entries');
-
- $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
-
- $content = json_decode($this->client->getResponse()->getContent(), true);
-
- $this->assertGreaterThanOrEqual(1, count($content));
- $this->assertNotEmpty($content['_embedded']['items']);
- $this->assertGreaterThanOrEqual(1, $content['total']);
- $this->assertEquals(1, $content['page']);
- $this->assertGreaterThanOrEqual(1, $content['pages']);
-
- $this->assertTrue(
- $this->client->getResponse()->headers->contains(
- 'Content-Type',
- 'application/json'
- )
- );
- }
-
- public function testGetEntriesWithFullOptions()
- {
- $this->client->request('GET', '/api/entries', [
- 'archive' => 1,
- 'starred' => 1,
- 'sort' => 'updated',
- 'order' => 'asc',
- 'page' => 1,
- 'perPage' => 2,
- 'tags' => 'foo',
- 'since' => 1443274283,
- ]);
-
- $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
-
- $content = json_decode($this->client->getResponse()->getContent(), true);
-
- $this->assertGreaterThanOrEqual(1, count($content));
- $this->assertArrayHasKey('items', $content['_embedded']);
- $this->assertGreaterThanOrEqual(0, $content['total']);
- $this->assertEquals(1, $content['page']);
- $this->assertEquals(2, $content['limit']);
- $this->assertGreaterThanOrEqual(1, $content['pages']);
-
- $this->assertArrayHasKey('_links', $content);
- $this->assertArrayHasKey('self', $content['_links']);
- $this->assertArrayHasKey('first', $content['_links']);
- $this->assertArrayHasKey('last', $content['_links']);
-
- foreach (['self', 'first', 'last'] as $link) {
- $this->assertArrayHasKey('href', $content['_links'][$link]);
- $this->assertContains('archive=1', $content['_links'][$link]['href']);
- $this->assertContains('starred=1', $content['_links'][$link]['href']);
- $this->assertContains('sort=updated', $content['_links'][$link]['href']);
- $this->assertContains('order=asc', $content['_links'][$link]['href']);
- $this->assertContains('tags=foo', $content['_links'][$link]['href']);
- $this->assertContains('since=1443274283', $content['_links'][$link]['href']);
- }
-
- $this->assertTrue(
- $this->client->getResponse()->headers->contains(
- 'Content-Type',
- 'application/json'
- )
- );
- }
-
- public function testGetStarredEntries()
- {
- $this->client->request('GET', '/api/entries', ['starred' => 1, 'sort' => 'updated']);
-
- $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
-
- $content = json_decode($this->client->getResponse()->getContent(), true);
-
- $this->assertGreaterThanOrEqual(1, count($content));
- $this->assertNotEmpty($content['_embedded']['items']);
- $this->assertGreaterThanOrEqual(1, $content['total']);
- $this->assertEquals(1, $content['page']);
- $this->assertGreaterThanOrEqual(1, $content['pages']);
-
- $this->assertArrayHasKey('_links', $content);
- $this->assertArrayHasKey('self', $content['_links']);
- $this->assertArrayHasKey('first', $content['_links']);
- $this->assertArrayHasKey('last', $content['_links']);
-
- foreach (['self', 'first', 'last'] as $link) {
- $this->assertArrayHasKey('href', $content['_links'][$link]);
- $this->assertContains('starred=1', $content['_links'][$link]['href']);
- $this->assertContains('sort=updated', $content['_links'][$link]['href']);
- }
-
- $this->assertTrue(
- $this->client->getResponse()->headers->contains(
- 'Content-Type',
- 'application/json'
- )
- );
- }
-
- public function testGetArchiveEntries()
- {
- $this->client->request('GET', '/api/entries', ['archive' => 1]);
-
- $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
-
- $content = json_decode($this->client->getResponse()->getContent(), true);
-
- $this->assertGreaterThanOrEqual(1, count($content));
- $this->assertNotEmpty($content['_embedded']['items']);
- $this->assertGreaterThanOrEqual(1, $content['total']);
- $this->assertEquals(1, $content['page']);
- $this->assertGreaterThanOrEqual(1, $content['pages']);
-
- $this->assertArrayHasKey('_links', $content);
- $this->assertArrayHasKey('self', $content['_links']);
- $this->assertArrayHasKey('first', $content['_links']);
- $this->assertArrayHasKey('last', $content['_links']);
-
- foreach (['self', 'first', 'last'] as $link) {
- $this->assertArrayHasKey('href', $content['_links'][$link]);
- $this->assertContains('archive=1', $content['_links'][$link]['href']);
- }
-
- $this->assertTrue(
- $this->client->getResponse()->headers->contains(
- 'Content-Type',
- 'application/json'
- )
- );
- }
-
- public function testGetTaggedEntries()
- {
- $this->client->request('GET', '/api/entries', ['tags' => 'foo,bar']);
-
- $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
-
- $content = json_decode($this->client->getResponse()->getContent(), true);
-
- $this->assertGreaterThanOrEqual(1, count($content));
- $this->assertNotEmpty($content['_embedded']['items']);
- $this->assertGreaterThanOrEqual(1, $content['total']);
- $this->assertEquals(1, $content['page']);
- $this->assertGreaterThanOrEqual(1, $content['pages']);
-
- $this->assertArrayHasKey('_links', $content);
- $this->assertArrayHasKey('self', $content['_links']);
- $this->assertArrayHasKey('first', $content['_links']);
- $this->assertArrayHasKey('last', $content['_links']);
-
- foreach (['self', 'first', 'last'] as $link) {
- $this->assertArrayHasKey('href', $content['_links'][$link]);
- $this->assertContains('tags='.urlencode('foo,bar'), $content['_links'][$link]['href']);
- }
-
- $this->assertTrue(
- $this->client->getResponse()->headers->contains(
- 'Content-Type',
- 'application/json'
- )
- );
- }
-
- public function testGetDatedEntries()
- {
- $this->client->request('GET', '/api/entries', ['since' => 1443274283]);
-
- $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
-
- $content = json_decode($this->client->getResponse()->getContent(), true);
-
- $this->assertGreaterThanOrEqual(1, count($content));
- $this->assertNotEmpty($content['_embedded']['items']);
- $this->assertGreaterThanOrEqual(1, $content['total']);
- $this->assertEquals(1, $content['page']);
- $this->assertGreaterThanOrEqual(1, $content['pages']);
-
- $this->assertArrayHasKey('_links', $content);
- $this->assertArrayHasKey('self', $content['_links']);
- $this->assertArrayHasKey('first', $content['_links']);
- $this->assertArrayHasKey('last', $content['_links']);
-
- foreach (['self', 'first', 'last'] as $link) {
- $this->assertArrayHasKey('href', $content['_links'][$link]);
- $this->assertContains('since=1443274283', $content['_links'][$link]['href']);
- }
-
- $this->assertTrue(
- $this->client->getResponse()->headers->contains(
- 'Content-Type',
- 'application/json'
- )
- );
- }
-
- public function testGetDatedSupEntries()
- {
- $future = new \DateTime(date('Y-m-d H:i:s'));
- $this->client->request('GET', '/api/entries', ['since' => $future->getTimestamp() + 1000]);
-
- $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
-
- $content = json_decode($this->client->getResponse()->getContent(), true);
-
- $this->assertGreaterThanOrEqual(1, count($content));
- $this->assertEmpty($content['_embedded']['items']);
- $this->assertEquals(0, $content['total']);
- $this->assertEquals(1, $content['page']);
- $this->assertEquals(1, $content['pages']);
-
- $this->assertArrayHasKey('_links', $content);
- $this->assertArrayHasKey('self', $content['_links']);
- $this->assertArrayHasKey('first', $content['_links']);
- $this->assertArrayHasKey('last', $content['_links']);
-
- foreach (['self', 'first', 'last'] as $link) {
- $this->assertArrayHasKey('href', $content['_links'][$link]);
- $this->assertContains('since='.($future->getTimestamp() + 1000), $content['_links'][$link]['href']);
- }
-
- $this->assertTrue(
- $this->client->getResponse()->headers->contains(
- 'Content-Type',
- 'application/json'
- )
- );
- }
-
- public function testDeleteEntry()
- {
- $entry = $this->client->getContainer()
- ->get('doctrine.orm.entity_manager')
- ->getRepository('WallabagCoreBundle:Entry')
- ->findOneByUser(1);
-
- if (!$entry) {
- $this->markTestSkipped('No content found in db.');
- }
-
- $this->client->request('DELETE', '/api/entries/'.$entry->getId().'.json');
-
- $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
-
- $content = json_decode($this->client->getResponse()->getContent(), true);
-
- $this->assertEquals($entry->getTitle(), $content['title']);
- $this->assertEquals($entry->getUrl(), $content['url']);
-
- // We'll try to delete this entry again
- $this->client->request('DELETE', '/api/entries/'.$entry->getId().'.json');
-
- $this->assertEquals(404, $this->client->getResponse()->getStatusCode());
- }
-
- public function testPostEntry()
- {
- $this->client->request('POST', '/api/entries.json', [
- 'url' => 'http://www.lemonde.fr/pixels/article/2015/03/28/plongee-dans-l-univers-d-ingress-le-jeu-de-google-aux-frontieres-du-reel_4601155_4408996.html',
- 'tags' => 'google',
- 'title' => 'New title for my article',
- ]);
-
- $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
-
- $content = json_decode($this->client->getResponse()->getContent(), true);
-
- $this->assertGreaterThan(0, $content['id']);
- $this->assertEquals('http://www.lemonde.fr/pixels/article/2015/03/28/plongee-dans-l-univers-d-ingress-le-jeu-de-google-aux-frontieres-du-reel_4601155_4408996.html', $content['url']);
- $this->assertEquals(false, $content['is_archived']);
- $this->assertEquals(false, $content['is_starred']);
- $this->assertEquals('New title for my article', $content['title']);
- $this->assertEquals(1, $content['user_id']);
- $this->assertCount(1, $content['tags']);
- }
-
- public function testPostSameEntry()
- {
- $this->client->request('POST', '/api/entries.json', [
- 'url' => 'http://www.lemonde.fr/pixels/article/2015/03/28/plongee-dans-l-univers-d-ingress-le-jeu-de-google-aux-frontieres-du-reel_4601155_4408996.html',
- 'archive' => '1',
- 'tags' => 'google, apple',
- ]);
-
- $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
-
- $content = json_decode($this->client->getResponse()->getContent(), true);
-
- $this->assertGreaterThan(0, $content['id']);
- $this->assertEquals('http://www.lemonde.fr/pixels/article/2015/03/28/plongee-dans-l-univers-d-ingress-le-jeu-de-google-aux-frontieres-du-reel_4601155_4408996.html', $content['url']);
- $this->assertEquals(true, $content['is_archived']);
- $this->assertEquals(false, $content['is_starred']);
- $this->assertCount(2, $content['tags']);
- }
-
- public function testPostArchivedAndStarredEntry()
- {
- $this->client->request('POST', '/api/entries.json', [
- 'url' => 'http://www.lemonde.fr/idees/article/2016/02/08/preserver-la-liberte-d-expression-sur-les-reseaux-sociaux_4861503_3232.html',
- 'archive' => '1',
- 'starred' => '1',
- ]);
-
- $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
-
- $content = json_decode($this->client->getResponse()->getContent(), true);
-
- $this->assertGreaterThan(0, $content['id']);
- $this->assertEquals('http://www.lemonde.fr/idees/article/2016/02/08/preserver-la-liberte-d-expression-sur-les-reseaux-sociaux_4861503_3232.html', $content['url']);
- $this->assertEquals(true, $content['is_archived']);
- $this->assertEquals(true, $content['is_starred']);
- $this->assertEquals(1, $content['user_id']);
- }
-
- public function testPostArchivedAndStarredEntryWithoutQuotes()
- {
- $this->client->request('POST', '/api/entries.json', [
- 'url' => 'http://www.lemonde.fr/idees/article/2016/02/08/preserver-la-liberte-d-expression-sur-les-reseaux-sociaux_4861503_3232.html',
- 'archive' => 0,
- 'starred' => 1,
- ]);
-
- $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
-
- $content = json_decode($this->client->getResponse()->getContent(), true);
-
- $this->assertGreaterThan(0, $content['id']);
- $this->assertEquals('http://www.lemonde.fr/idees/article/2016/02/08/preserver-la-liberte-d-expression-sur-les-reseaux-sociaux_4861503_3232.html', $content['url']);
- $this->assertEquals(false, $content['is_archived']);
- $this->assertEquals(true, $content['is_starred']);
- }
-
- public function testPatchEntry()
- {
- $entry = $this->client->getContainer()
- ->get('doctrine.orm.entity_manager')
- ->getRepository('WallabagCoreBundle:Entry')
- ->findOneByUser(1);
-
- if (!$entry) {
- $this->markTestSkipped('No content found in db.');
- }
-
- // hydrate the tags relations
- $nbTags = count($entry->getTags());
-
- $this->client->request('PATCH', '/api/entries/'.$entry->getId().'.json', [
- 'title' => 'New awesome title',
- 'tags' => 'new tag '.uniqid(),
- 'starred' => '1',
- 'archive' => '0',
- ]);
-
- $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
-
- $content = json_decode($this->client->getResponse()->getContent(), true);
-
- $this->assertEquals($entry->getId(), $content['id']);
- $this->assertEquals($entry->getUrl(), $content['url']);
- $this->assertEquals('New awesome title', $content['title']);
- $this->assertGreaterThan($nbTags, count($content['tags']));
- $this->assertEquals(1, $content['user_id']);
- }
-
- public function testPatchEntryWithoutQuotes()
- {
- $entry = $this->client->getContainer()
- ->get('doctrine.orm.entity_manager')
- ->getRepository('WallabagCoreBundle:Entry')
- ->findOneByUser(1);
-
- if (!$entry) {
- $this->markTestSkipped('No content found in db.');
- }
-
- // hydrate the tags relations
- $nbTags = count($entry->getTags());
-
- $this->client->request('PATCH', '/api/entries/'.$entry->getId().'.json', [
- 'title' => 'New awesome title',
- 'tags' => 'new tag '.uniqid(),
- 'starred' => 1,
- 'archive' => 0,
- ]);
-
- $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
-
- $content = json_decode($this->client->getResponse()->getContent(), true);
-
- $this->assertEquals($entry->getId(), $content['id']);
- $this->assertEquals($entry->getUrl(), $content['url']);
- $this->assertEquals('New awesome title', $content['title']);
- $this->assertGreaterThan($nbTags, count($content['tags']));
- }
-
- public function testGetTagsEntry()
- {
- $entry = $this->client->getContainer()
- ->get('doctrine.orm.entity_manager')
- ->getRepository('WallabagCoreBundle:Entry')
- ->findOneWithTags($this->user->getId());
-
- $entry = $entry[0];
-
- if (!$entry) {
- $this->markTestSkipped('No content found in db.');
- }
-
- $tags = [];
- foreach ($entry->getTags() as $tag) {
- $tags[] = ['id' => $tag->getId(), 'label' => $tag->getLabel(), 'slug' => $tag->getSlug()];
- }
-
- $this->client->request('GET', '/api/entries/'.$entry->getId().'/tags');
-
- $this->assertEquals(json_encode($tags, JSON_HEX_QUOT), $this->client->getResponse()->getContent());
- }
-
- public function testPostTagsOnEntry()
- {
- $entry = $this->client->getContainer()
- ->get('doctrine.orm.entity_manager')
- ->getRepository('WallabagCoreBundle:Entry')
- ->findOneByUser(1);
-
- if (!$entry) {
- $this->markTestSkipped('No content found in db.');
- }
-
- $nbTags = count($entry->getTags());
-
- $newTags = 'tag1,tag2,tag3';
-
- $this->client->request('POST', '/api/entries/'.$entry->getId().'/tags', ['tags' => $newTags]);
-
- $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
-
- $content = json_decode($this->client->getResponse()->getContent(), true);
-
- $this->assertArrayHasKey('tags', $content);
- $this->assertEquals($nbTags + 3, count($content['tags']));
-
- $entryDB = $this->client->getContainer()
- ->get('doctrine.orm.entity_manager')
- ->getRepository('WallabagCoreBundle:Entry')
- ->find($entry->getId());
-
- $tagsInDB = [];
- foreach ($entryDB->getTags()->toArray() as $tag) {
- $tagsInDB[$tag->getId()] = $tag->getLabel();
- }
-
- foreach (explode(',', $newTags) as $tag) {
- $this->assertContains($tag, $tagsInDB);
- }
- }
-
- public function testDeleteOneTagEntry()
- {
- $entry = $this->client->getContainer()
- ->get('doctrine.orm.entity_manager')
- ->getRepository('WallabagCoreBundle:Entry')
- ->findOneWithTags($this->user->getId());
- $entry = $entry[0];
-
- if (!$entry) {
- $this->markTestSkipped('No content found in db.');
- }
-
- // hydrate the tags relations
- $nbTags = count($entry->getTags());
- $tag = $entry->getTags()[0];
-
- $this->client->request('DELETE', '/api/entries/'.$entry->getId().'/tags/'.$tag->getId().'.json');
-
- $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
-
- $content = json_decode($this->client->getResponse()->getContent(), true);
-
- $this->assertArrayHasKey('tags', $content);
- $this->assertEquals($nbTags - 1, count($content['tags']));
- }
-
- public function testGetUserTags()
- {
- $this->client->request('GET', '/api/tags.json');
-
- $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
-
- $content = json_decode($this->client->getResponse()->getContent(), true);
-
- $this->assertGreaterThan(0, $content);
- $this->assertArrayHasKey('id', $content[0]);
- $this->assertArrayHasKey('label', $content[0]);
-
- return end($content);
- }
-
- /**
- * @depends testGetUserTags
- */
- public function testDeleteUserTag($tag)
- {
- $tagName = $tag['label'];
-
- $this->client->request('DELETE', '/api/tags/'.$tag['id'].'.json');
-
- $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
-
- $content = json_decode($this->client->getResponse()->getContent(), true);
-
- $this->assertArrayHasKey('label', $content);
- $this->assertEquals($tag['label'], $content['label']);
- $this->assertEquals($tag['slug'], $content['slug']);
-
- $entries = $this->client->getContainer()
- ->get('doctrine.orm.entity_manager')
- ->getRepository('WallabagCoreBundle:Entry')
- ->findAllByTagId($this->user->getId(), $tag['id']);
-
- $this->assertCount(0, $entries);
-
- $tag = $this->client->getContainer()
- ->get('doctrine.orm.entity_manager')
- ->getRepository('WallabagCoreBundle:Tag')
- ->findOneByLabel($tagName);
-
- $this->assertNull($tag, $tagName.' was removed because it begun an orphan tag');
- }
-
- public function testDeleteTagByLabel()
- {
- $em = $this->client->getContainer()->get('doctrine.orm.entity_manager');
- $entry = $this->client->getContainer()
- ->get('doctrine.orm.entity_manager')
- ->getRepository('WallabagCoreBundle:Entry')
- ->findOneWithTags($this->user->getId());
-
- $entry = $entry[0];
-
- $tag = new Tag();
- $tag->setLabel('Awesome tag for test');
- $em->persist($tag);
-
- $entry->addTag($tag);
-
- $em->persist($entry);
- $em->flush();
-
- $this->client->request('DELETE', '/api/tag/label.json', ['tag' => $tag->getLabel()]);
-
- $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
-
- $content = json_decode($this->client->getResponse()->getContent(), true);
-
- $this->assertArrayHasKey('label', $content);
- $this->assertEquals($tag->getLabel(), $content['label']);
- $this->assertEquals($tag->getSlug(), $content['slug']);
-
- $entries = $this->client->getContainer()
- ->get('doctrine.orm.entity_manager')
- ->getRepository('WallabagCoreBundle:Entry')
- ->findAllByTagId($this->user->getId(), $tag->getId());
-
- $this->assertCount(0, $entries);
- }
-
- public function testDeleteTagByLabelNotFound()
- {
- $this->client->request('DELETE', '/api/tag/label.json', ['tag' => 'does not exist']);
-
- $this->assertEquals(404, $this->client->getResponse()->getStatusCode());
- }
-
- public function testDeleteTagsByLabel()
- {
- $em = $this->client->getContainer()->get('doctrine.orm.entity_manager');
- $entry = $this->client->getContainer()
- ->get('doctrine.orm.entity_manager')
- ->getRepository('WallabagCoreBundle:Entry')
- ->findOneWithTags($this->user->getId());
-
- $entry = $entry[0];
-
- $tag = new Tag();
- $tag->setLabel('Awesome tag for tagsLabel');
- $em->persist($tag);
-
- $tag2 = new Tag();
- $tag2->setLabel('Awesome tag for tagsLabel 2');
- $em->persist($tag2);
-
- $entry->addTag($tag);
- $entry->addTag($tag2);
-
- $em->persist($entry);
- $em->flush();
-
- $this->client->request('DELETE', '/api/tags/label.json', ['tags' => $tag->getLabel().','.$tag2->getLabel()]);
-
- $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
-
- $content = json_decode($this->client->getResponse()->getContent(), true);
-
- $this->assertCount(2, $content);
-
- $this->assertArrayHasKey('label', $content[0]);
- $this->assertEquals($tag->getLabel(), $content[0]['label']);
- $this->assertEquals($tag->getSlug(), $content[0]['slug']);
-
- $this->assertArrayHasKey('label', $content[1]);
- $this->assertEquals($tag2->getLabel(), $content[1]['label']);
- $this->assertEquals($tag2->getSlug(), $content[1]['slug']);
-
- $entries = $this->client->getContainer()
- ->get('doctrine.orm.entity_manager')
- ->getRepository('WallabagCoreBundle:Entry')
- ->findAllByTagId($this->user->getId(), $tag->getId());
-
- $this->assertCount(0, $entries);
-
- $entries = $this->client->getContainer()
- ->get('doctrine.orm.entity_manager')
- ->getRepository('WallabagCoreBundle:Entry')
- ->findAllByTagId($this->user->getId(), $tag2->getId());
-
- $this->assertCount(0, $entries);
- }
-
- public function testDeleteTagsByLabelNotFound()
- {
- $this->client->request('DELETE', '/api/tags/label.json', ['tags' => 'does not exist']);
-
- $this->assertEquals(404, $this->client->getResponse()->getStatusCode());
- }
-
public function testGetVersion()
{
$this->client->request('GET', '/api/version');
@@ -704,136 +16,4 @@ class WallabagRestControllerTest extends WallabagApiTestCase
$this->assertEquals($this->client->getContainer()->getParameter('wallabag_core.version'), $content);
}
-
- public function testSaveIsArchivedAfterPost()
- {
- $entry = $this->client->getContainer()
- ->get('doctrine.orm.entity_manager')
- ->getRepository('WallabagCoreBundle:Entry')
- ->findOneBy(['user' => 1, 'isArchived' => true]);
-
- if (!$entry) {
- $this->markTestSkipped('No content found in db.');
- }
-
- $this->client->request('POST', '/api/entries.json', [
- 'url' => $entry->getUrl(),
- ]);
-
- $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
-
- $content = json_decode($this->client->getResponse()->getContent(), true);
-
- $this->assertEquals(true, $content['is_archived']);
- }
-
- public function testSaveIsStarredAfterPost()
- {
- $entry = $this->client->getContainer()
- ->get('doctrine.orm.entity_manager')
- ->getRepository('WallabagCoreBundle:Entry')
- ->findOneBy(['user' => 1, 'isStarred' => true]);
-
- if (!$entry) {
- $this->markTestSkipped('No content found in db.');
- }
-
- $this->client->request('POST', '/api/entries.json', [
- 'url' => $entry->getUrl(),
- ]);
-
- $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
-
- $content = json_decode($this->client->getResponse()->getContent(), true);
-
- $this->assertEquals(true, $content['is_starred']);
- }
-
- public function testSaveIsArchivedAfterPatch()
- {
- $entry = $this->client->getContainer()
- ->get('doctrine.orm.entity_manager')
- ->getRepository('WallabagCoreBundle:Entry')
- ->findOneBy(['user' => 1, 'isArchived' => true]);
-
- if (!$entry) {
- $this->markTestSkipped('No content found in db.');
- }
-
- $this->client->request('PATCH', '/api/entries/'.$entry->getId().'.json', [
- 'title' => $entry->getTitle().'++',
- ]);
-
- $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
-
- $content = json_decode($this->client->getResponse()->getContent(), true);
-
- $this->assertEquals(true, $content['is_archived']);
- }
-
- public function testSaveIsStarredAfterPatch()
- {
- $entry = $this->client->getContainer()
- ->get('doctrine.orm.entity_manager')
- ->getRepository('WallabagCoreBundle:Entry')
- ->findOneBy(['user' => 1, 'isStarred' => true]);
-
- if (!$entry) {
- $this->markTestSkipped('No content found in db.');
- }
- $this->client->request('PATCH', '/api/entries/'.$entry->getId().'.json', [
- 'title' => $entry->getTitle().'++',
- ]);
-
- $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
-
- $content = json_decode($this->client->getResponse()->getContent(), true);
-
- $this->assertEquals(true, $content['is_starred']);
- }
-
- public function testGetEntriesExists()
- {
- $this->client->request('GET', '/api/entries/exists?url=http://0.0.0.0/entry2');
-
- $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
-
- $content = json_decode($this->client->getResponse()->getContent(), true);
-
- $this->assertEquals(true, $content['exists']);
- }
-
- public function testGetEntriesExistsWithManyUrls()
- {
- $url1 = 'http://0.0.0.0/entry2';
- $url2 = 'http://0.0.0.0/entry10';
- $this->client->request('GET', '/api/entries/exists?urls[]='.$url1.'&urls[]='.$url2);
-
- $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
-
- $content = json_decode($this->client->getResponse()->getContent(), true);
-
- $this->assertArrayHasKey($url1, $content);
- $this->assertArrayHasKey($url2, $content);
- $this->assertEquals(true, $content[$url1]);
- $this->assertEquals(false, $content[$url2]);
- }
-
- public function testGetEntriesExistsWhichDoesNotExists()
- {
- $this->client->request('GET', '/api/entries/exists?url=http://google.com/entry2');
-
- $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
-
- $content = json_decode($this->client->getResponse()->getContent(), true);
-
- $this->assertEquals(false, $content['exists']);
- }
-
- public function testGetEntriesExistsWithNoUrl()
- {
- $this->client->request('GET', '/api/entries/exists?url=');
-
- $this->assertEquals(403, $this->client->getResponse()->getStatusCode());
- }
}
From bc4564a709ccae949999af77aa456287a72f1591 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nicolas=20L=C5=93uillet?=
Date: Fri, 28 Oct 2016 15:24:58 +0200
Subject: [PATCH 18/42] Removed useless route
---
src/Wallabag/ApiBundle/Resources/config/routing_rest.yml | 5 -----
1 file changed, 5 deletions(-)
diff --git a/src/Wallabag/ApiBundle/Resources/config/routing_rest.yml b/src/Wallabag/ApiBundle/Resources/config/routing_rest.yml
index 901cf449c..c1af9e023 100644
--- a/src/Wallabag/ApiBundle/Resources/config/routing_rest.yml
+++ b/src/Wallabag/ApiBundle/Resources/config/routing_rest.yml
@@ -1,8 +1,3 @@
-api:
- type: rest
- resource: "WallabagApiBundle:WallabagRest"
- name_prefix: api_
-
entries:
type: rest
resource: "WallabagApiBundle:EntryRest"
From 920d88599a077a7624574345243caf45c6bc5820 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nicolas=20L=C5=93uillet?=
Date: Thu, 27 Oct 2016 09:41:19 +0200
Subject: [PATCH 19/42] Fixed entries export filtered with a tag Fix #2505
---
.../Controller/ExportController.php | 23 ++++++++++++++-----
.../themes/baggy/Entry/entries.html.twig | 18 +++++++++------
.../themes/material/Entry/entries.html.twig | 18 +++++++++------
3 files changed, 39 insertions(+), 20 deletions(-)
diff --git a/src/Wallabag/CoreBundle/Controller/ExportController.php b/src/Wallabag/CoreBundle/Controller/ExportController.php
index 6191d5d79..79653cfe8 100644
--- a/src/Wallabag/CoreBundle/Controller/ExportController.php
+++ b/src/Wallabag/CoreBundle/Controller/ExportController.php
@@ -4,8 +4,10 @@ namespace Wallabag\CoreBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
+use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Wallabag\CoreBundle\Entity\Entry;
+use Wallabag\CoreBundle\Entity\Tag;
/**
* The try/catch can be removed once all formats will be implemented.
@@ -51,15 +53,24 @@ class ExportController extends Controller
*
* @return \Symfony\Component\HttpFoundation\Response
*/
- public function downloadEntriesAction($format, $category)
+ public function downloadEntriesAction(Request $request, $format, $category)
{
$method = ucfirst($category);
$methodBuilder = 'getBuilderFor'.$method.'ByUser';
- $entries = $this->getDoctrine()
- ->getRepository('WallabagCoreBundle:Entry')
- ->$methodBuilder($this->getUser()->getId())
- ->getQuery()
- ->getResult();
+
+ if ($category == 'tag_entries') {
+ $tag = $this->getDoctrine()->getRepository('WallabagCoreBundle:Tag')->findOneBySlug($request->query->get('tag'));
+
+ $entries = $this->getDoctrine()
+ ->getRepository('WallabagCoreBundle:Entry')
+ ->findAllByTagId($this->getUser()->getId(), $tag->getId());
+ } else {
+ $entries = $this->getDoctrine()
+ ->getRepository('WallabagCoreBundle:Entry')
+ ->$methodBuilder($this->getUser()->getId())
+ ->getQuery()
+ ->getResult();
+ }
try {
return $this->get('wallabag_core.helper.entries_export')
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Entry/entries.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Entry/entries.html.twig
index f19f2922c..5d657c7e7 100644
--- a/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Entry/entries.html.twig
+++ b/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Entry/entries.html.twig
@@ -53,19 +53,23 @@
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entries.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entries.html.twig
index 5c7cfd653..1225e6806 100644
--- a/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entries.html.twig
+++ b/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entries.html.twig
@@ -99,18 +99,22 @@
{% set currentRoute = app.request.attributes.get('_route') %}
+ {% set currentTag = '' %}
+ {% if tag is defined %}
+ {% set currentTag = tag %}
+ {% endif %}
{% if currentRoute == 'homepage' %}
{% set currentRoute = 'unread' %}
{% endif %}
{{ 'entry.list.export_title'|trans }}
- {% if craue_setting('export_epub') %}- EPUB
{% endif %}
- {% if craue_setting('export_mobi') %}- MOBI
{% endif %}
- {% if craue_setting('export_pdf') %}- PDF
{% endif %}
- {% if craue_setting('export_csv') %}- JSON
{% endif %}
- {% if craue_setting('export_json') %}- CSV
{% endif %}
- {% if craue_setting('export_txt') %}- TXT
{% endif %}
- {% if craue_setting('export_xml') %}- XML
{% endif %}
+ {% if craue_setting('export_epub') %}- EPUB
{% endif %}
+ {% if craue_setting('export_mobi') %}- MOBI
{% endif %}
+ {% if craue_setting('export_pdf') %}- PDF
{% endif %}
+ {% if craue_setting('export_csv') %}- JSON
{% endif %}
+ {% if craue_setting('export_json') %}- CSV
{% endif %}
+ {% if craue_setting('export_txt') %}- TXT
{% endif %}
+ {% if craue_setting('export_xml') %}- XML
{% endif %}
From 794ac861cbd0a050915126a1fad6e1e5e5de2083 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nicolas=20L=C5=93uillet?=
Date: Sat, 29 Oct 2016 14:03:55 +0200
Subject: [PATCH 20/42] Added test for export by filtering with tag
---
.../CoreBundle/Controller/ExportControllerTest.php | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/tests/Wallabag/CoreBundle/Controller/ExportControllerTest.php b/tests/Wallabag/CoreBundle/Controller/ExportControllerTest.php
index 9ecd8bc4e..5ca886bd4 100644
--- a/tests/Wallabag/CoreBundle/Controller/ExportControllerTest.php
+++ b/tests/Wallabag/CoreBundle/Controller/ExportControllerTest.php
@@ -117,6 +117,17 @@ class ExportControllerTest extends WallabagCoreTestCase
$this->assertEquals('application/pdf', $headers->get('content-type'));
$this->assertEquals('attachment; filename="All articles.pdf"', $headers->get('content-disposition'));
$this->assertEquals('binary', $headers->get('content-transfer-encoding'));
+
+ ob_start();
+ $crawler = $client->request('GET', '/export/tag_entries.pdf?tag=foo');
+ ob_end_clean();
+
+ $this->assertEquals(200, $client->getResponse()->getStatusCode());
+
+ $headers = $client->getResponse()->headers;
+ $this->assertEquals('application/pdf', $headers->get('content-type'));
+ $this->assertEquals('attachment; filename="Tag_entries articles.pdf"', $headers->get('content-disposition'));
+ $this->assertEquals('binary', $headers->get('content-transfer-encoding'));
}
public function testTxtExport()
From c4b3933bae583da1bdd4b97471bdcca08ab92312 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nicolas=20L=C5=93uillet?=
Date: Sat, 29 Oct 2016 14:14:20 +0200
Subject: [PATCH 21/42] Updated Capistrano configuration
---
Capfile | 2 ++
Gemfile | 3 ++-
Gemfile.lock | 5 +++--
app/config/capistrano/deploy.rb | 9 +--------
4 files changed, 8 insertions(+), 11 deletions(-)
diff --git a/Capfile b/Capfile
index b80a5646b..cc8071120 100644
--- a/Capfile
+++ b/Capfile
@@ -7,6 +7,8 @@ require 'capistrano/setup'
# Include default deployment tasks
require 'capistrano/deploy'
+require 'capistrano/composer'
+require 'capistrano/file-permissions'
require 'capistrano/symfony'
# Load custom tasks from `lib/capistrano/tasks` if you have any defined
diff --git a/Gemfile b/Gemfile
index 31f887a98..233be899c 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,5 +1,6 @@
source "https://rubygems.org"
gem 'capistrano', '~> 3.4'
+gem 'capistrano-composer'
gem 'capistrano-symfony', '~> 1.0.0.rc1'
-gem 'capistrano-composer', '~> 0.0.3'
+gem 'capistrano-file-permissions'
diff --git a/Gemfile.lock b/Gemfile.lock
index aebbeba27..7b13b3991 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -29,8 +29,9 @@ PLATFORMS
DEPENDENCIES
capistrano (~> 3.4)
- capistrano-composer (~> 0.0.3)
+ capistrano-composer
+ capistrano-file-permissions
capistrano-symfony (~> 1.0.0.rc1)
BUNDLED WITH
- 1.11.2
+ 1.13.5
diff --git a/app/config/capistrano/deploy.rb b/app/config/capistrano/deploy.rb
index f15eef300..fee04620d 100644
--- a/app/config/capistrano/deploy.rb
+++ b/app/config/capistrano/deploy.rb
@@ -1,9 +1,4 @@
# config valid only for current version of Capistrano
-lock '3.4.0'
-
-set :log_path, "var/logs"
-set :cache_path, "var/cache"
-set :symfony_console_path, 'bin/console'
set :application, 'wallabag'
set :repo_url, 'git@github.com:wallabag/wallabag.git'
@@ -11,8 +6,6 @@ set :repo_url, 'git@github.com:wallabag/wallabag.git'
set :ssh_user, 'framasoft_bag'
server '78.46.248.87', user: fetch(:ssh_user), roles: %w{web app db}
-set :scm, :git
-
set :format, :pretty
set :log_level, :info
# set :log_level, :debug
@@ -23,4 +16,4 @@ set :linked_files, %w{app/config/parameters.yml}
set :linked_dirs, [fetch(:log_path), "var/sessions", "web/uploads", "data"]
set :keep_releases, 3
-after 'deploy:finishing', 'deploy:cleanup'
+after 'deploy:updated', 'symfony:cache:clear'
From a40b2b7ee4f5aec502c4ddc755ed7d15f9b7a756 Mon Sep 17 00:00:00 2001
From: Sven Fischer
Date: Sat, 29 Oct 2016 19:59:05 +0200
Subject: [PATCH 22/42] docs: update 3rd party projects by Strubbl
---
docs/de/developer/api.rst | 3 ++-
docs/en/developer/api.rst | 3 ++-
docs/fr/developer/api.rst | 3 ++-
3 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/docs/de/developer/api.rst b/docs/de/developer/api.rst
index f89111819..22b87608b 100644
--- a/docs/de/developer/api.rst
+++ b/docs/de/developer/api.rst
@@ -264,7 +264,8 @@ Drittanbieter Ressourcen
Einige Applikationen oder Bibliotheken nutzen unsere API. Hier ist eine nicht abschließende Aufzählung von ihnen:
-- `Java wrapper for the wallabag API `_ von Strubbl.
+- `Java wrapper for the wallabag API `_ von Strubbl.
- `.NET library for the wallabag v2 API `_ von Julian Oster.
- `Python API for wallabag `_ von FoxMaSk, für sein Projekt `Trigger Happy `_.
- `A plugin `_ entworfen für `Tiny Tiny RSS `_, das die wallabag v2 API nutzt. Von Josh Panter.
+- `Golang wrapper for the wallabag API `_ von Strubbl, für sein Projekt `wallabag-stats Graph`_.
diff --git a/docs/en/developer/api.rst b/docs/en/developer/api.rst
index 4828cddd1..d61591f48 100644
--- a/docs/en/developer/api.rst
+++ b/docs/en/developer/api.rst
@@ -263,7 +263,8 @@ Third party resources
Some applications or libraries use our API. Here is a non-exhaustive list of them:
-- `Java wrapper for the wallabag API `_ by Strubbl.
+- `Java wrapper for the wallabag API `_ by Strubbl.
- `.NET library for the wallabag v2 API `_ by Julian Oster.
- `Python API for wallabag `_ by FoxMaSk, for his project `Trigger Happy `_.
- `A plugin `_ designed for `Tiny Tiny RSS `_ that makes use of the wallabag v2 API. By Josh Panter.
+- `Golang wrapper for the wallabag API `_ by Strubbl, for his project `wallabag-stats graph`_.
diff --git a/docs/fr/developer/api.rst b/docs/fr/developer/api.rst
index a0710a961..738c8f042 100644
--- a/docs/fr/developer/api.rst
+++ b/docs/fr/developer/api.rst
@@ -263,7 +263,8 @@ Ressources tierces
Certaines applications ou bibliothèques utilisent notre API. En voici une liste non exhaustive :
-- `Java wrapper for the wallabag API `_ par Strubbl.
+- `Java wrapper for the wallabag API `_ par Strubbl.
- `.NET library for the wallabag v2 API `_ par Julian Oster.
- `Python API for wallabag `_ par FoxMaSk, pour son projet `Trigger Happy `_.
- `Un plugin `_ conçu pour `Tiny Tiny RSS `_ qui utilise l'API wallabag v2. Par Josh Panter.
+- `Golang wrapper for the wallabag API `_ par Strubbl, pour son projet `wallabag-stats graphe`_.
From 90ec78f05aa0b20b98c0ca9030c7a69817e7602a Mon Sep 17 00:00:00 2001
From: Sven Fischer
Date: Sun, 30 Oct 2016 12:01:24 +0100
Subject: [PATCH 23/42] docs: fix link to wallabag-stats project
---
docs/de/developer/api.rst | 2 +-
docs/en/developer/api.rst | 2 +-
docs/fr/developer/api.rst | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/docs/de/developer/api.rst b/docs/de/developer/api.rst
index 22b87608b..bb21154d9 100644
--- a/docs/de/developer/api.rst
+++ b/docs/de/developer/api.rst
@@ -268,4 +268,4 @@ Einige Applikationen oder Bibliotheken nutzen unsere API. Hier ist eine nicht ab
- `.NET library for the wallabag v2 API `_ von Julian Oster.
- `Python API for wallabag `_ von FoxMaSk, für sein Projekt `Trigger Happy `_.
- `A plugin `_ entworfen für `Tiny Tiny RSS `_, das die wallabag v2 API nutzt. Von Josh Panter.
-- `Golang wrapper for the wallabag API `_ von Strubbl, für sein Projekt `wallabag-stats Graph`_.
+- `Golang wrapper for the wallabag API `_ von Strubbl, für sein Projekt `wallabag-stats Graph `_.
diff --git a/docs/en/developer/api.rst b/docs/en/developer/api.rst
index d61591f48..b6c9ed3fc 100644
--- a/docs/en/developer/api.rst
+++ b/docs/en/developer/api.rst
@@ -267,4 +267,4 @@ Some applications or libraries use our API. Here is a non-exhaustive list of the
- `.NET library for the wallabag v2 API `_ by Julian Oster.
- `Python API for wallabag `_ by FoxMaSk, for his project `Trigger Happy `_.
- `A plugin `_ designed for `Tiny Tiny RSS `_ that makes use of the wallabag v2 API. By Josh Panter.
-- `Golang wrapper for the wallabag API `_ by Strubbl, for his project `wallabag-stats graph`_.
+- `Golang wrapper for the wallabag API `_ by Strubbl, for his project `wallabag-stats graph `_.
diff --git a/docs/fr/developer/api.rst b/docs/fr/developer/api.rst
index 738c8f042..8a6e2a136 100644
--- a/docs/fr/developer/api.rst
+++ b/docs/fr/developer/api.rst
@@ -267,4 +267,4 @@ Certaines applications ou bibliothèques utilisent notre API. En voici une liste
- `.NET library for the wallabag v2 API `_ par Julian Oster.
- `Python API for wallabag `_ par FoxMaSk, pour son projet `Trigger Happy `_.
- `Un plugin `_ conçu pour `Tiny Tiny RSS `_ qui utilise l'API wallabag v2. Par Josh Panter.
-- `Golang wrapper for the wallabag API `_ par Strubbl, pour son projet `wallabag-stats graphe`_.
+- `Golang wrapper for the wallabag API `_ par Strubbl, pour son projet `wallabag-stats graphe `_.
From a0eddc598e00873ea66d4b1f2beba4fdcc119798 Mon Sep 17 00:00:00 2001
From: Jean-Baptiste
Date: Sun, 30 Oct 2016 12:09:08 +0100
Subject: [PATCH 24/42] Translation update - French
---
app/Resources/FOSUserBundle/translations/FOSUserBundle.fr.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/Resources/FOSUserBundle/translations/FOSUserBundle.fr.yml b/app/Resources/FOSUserBundle/translations/FOSUserBundle.fr.yml
index 1ccad137a..1c5ea6400 100644
--- a/app/Resources/FOSUserBundle/translations/FOSUserBundle.fr.yml
+++ b/app/Resources/FOSUserBundle/translations/FOSUserBundle.fr.yml
@@ -1,2 +1,2 @@
Login: "Se connecter"
-Enter your email address below and we'll send you password reset instructions.: "Renseignez votre adresse email, nous vous enverrons les instructions pour réinitialiser votre mot de passe."
+Enter your email address below and we'll send you password reset instructions.: "Renseignez votre adresse courriel, nous vous enverrons les instructions pour réinitialiser votre mot de passe."
From 431d038aa7c1a123db1f3f6885222f166d1fc8a8 Mon Sep 17 00:00:00 2001
From: Jean-Baptiste
Date: Sun, 30 Oct 2016 12:10:14 +0100
Subject: [PATCH 25/42] Translation update - French
From f6aff9a7a8e2622a0911555a8b49ca516dda0cf5 Mon Sep 17 00:00:00 2001
From: Jean-Baptiste
Date: Sun, 30 Oct 2016 12:10:59 +0100
Subject: [PATCH 26/42] Translation update - French
---
.../Resources/translations/messages.fr.yml | 724 +++++++++---------
.../Resources/translations/validators.fr.yml | 10 +-
2 files changed, 367 insertions(+), 367 deletions(-)
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml
index 574cc1a74..ae5e78cbe 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml
@@ -1,422 +1,422 @@
security:
login:
- page_title: 'Bienvenue sur wallabag !'
- keep_logged_in: 'Rester connecté'
- forgot_password: 'Mot de passe oublié ?'
- submit: 'Se connecter'
- register: 'Créer un compte'
- username: "Nom d'utilisateur"
- password: 'Mot de passe'
- cancel: 'Annuler'
+ page_title: "Bienvenue sur wallabag !"
+ keep_logged_in: "Rester connecté"
+ forgot_password: "Mot de passe oublié ?"
+ submit: "Se connecter"
+ register: "Créer un compte"
+ username: "Nom d’utilisateur"
+ password: "Mot de passe"
+ cancel: "Annuler"
resetting:
- description: "Saisissez votre adresse e-mail ci-dessous, nous vous enverrons les instructions pour réinitialiser votre mot de passe."
+ description: "Saisissez votre adresse courriel ci-dessous, nous vous enverrons les instructions pour réinitialiser votre mot de passe."
register:
- page_title: 'Se créer un compte'
- go_to_account: 'Aller sur votre compte'
+ page_title: "Se créer un compte"
+ go_to_account: "Aller sur votre compte"
menu:
left:
- unread: 'Non lus'
- starred: 'Favoris'
- archive: 'Lus'
- all_articles: 'Tous les articles'
- config: 'Configuration'
- tags: 'Tags'
- internal_settings: 'Configuration interne'
- import: 'Importer'
- howto: 'Aide'
- developer: 'Développeur'
- logout: 'Déconnexion'
- about: 'À propos'
- search: 'Recherche'
- save_link: 'Sauvegarder un nouvel article'
- back_to_unread: 'Retour aux articles non lus'
- users_management: 'Gestion des utilisateurs'
+ unread: "Non lus"
+ starred: "Favoris"
+ archive: "Lus"
+ all_articles: "Tous les articles"
+ config: "Configuration"
+ tags: "Tags"
+ internal_settings: "Configuration interne"
+ import: "Importer"
+ howto: "Aide"
+ developer: "Développeur"
+ logout: "Déconnexion"
+ about: "À propos"
+ search: "Recherche"
+ save_link: "Sauvegarder un nouvel article"
+ back_to_unread: "Retour aux articles non lus"
+ users_management: "Gestion des utilisateurs"
top:
- add_new_entry: 'Sauvegarder un nouvel article'
- search: 'Rechercher'
- filter_entries: 'Filtrer les articles'
- export: 'Exporter'
+ add_new_entry: "Sauvegarder un nouvel article"
+ search: "Rechercher"
+ filter_entries: "Filtrer les articles"
+ export: "Exporter"
search_form:
- input_label: 'Saisissez votre terme de recherche'
+ input_label: "Saisissez votre terme de recherche"
footer:
wallabag:
- elsewhere: 'Emportez wallabag avec vous'
- social: 'Social'
- powered_by: 'propulsé par'
- about: 'À propos'
+ elsewhere: "Emportez wallabag avec vous"
+ social: "Social"
+ powered_by: "propulsé par"
+ about: "À propos"
stats: Depuis le %user_creation% vous avez lu %nb_archives% articles. Ce qui fait %per_day% par jour !
config:
- page_title: 'Configuration'
+ page_title: "Configuration"
tab_menu:
- settings: 'Paramètres'
- rss: 'RSS'
- user_info: 'Mon compte'
- password: 'Mot de passe'
- rules: 'Règles de tag automatiques'
- new_user: 'Créer un compte'
+ settings: "Paramètres"
+ rss: "RSS"
+ user_info: "Mon compte"
+ password: "Mot de passe"
+ rules: "Règles de tag automatiques"
+ new_user: "Créer un compte"
form:
- save: 'Enregistrer'
+ save: "Enregistrer"
form_settings:
- theme_label: 'Thème'
- items_per_page_label: "Nombre d'articles par page"
- language_label: 'Langue'
+ theme_label: "Thème"
+ items_per_page_label: "Nombre d’articles par page"
+ language_label: "Langue"
reading_speed:
- label: 'Vitesse de lecture'
- help_message: 'Vous pouvez utiliser un outil en ligne pour estimer votre vitesse de lecture :'
- 100_word: 'Je lis environ 100 mots par minute'
- 200_word: 'Je lis environ 200 mots par minute'
- 300_word: 'Je lis environ 300 mots par minute'
- 400_word: 'Je lis environ 400 mots par minute'
- pocket_consumer_key_label: Clé d'authentification Pocket pour importer les données
+ label: "Vitesse de lecture"
+ help_message: "Vous pouvez utiliser un outil en ligne pour estimer votre vitesse de lecture :"
+ 100_word: "Je lis environ 100 mots par minute"
+ 200_word: "Je lis environ 200 mots par minute"
+ 300_word: "Je lis environ 300 mots par minute"
+ 400_word: "Je lis environ 400 mots par minute"
+ pocket_consumer_key_label: Clé d’authentification Pocket pour importer les données
form_rss:
- description: "Les flux RSS fournis par wallabag vous permettent de lire vos articles sauvegardés dans votre lecteur de flux préféré. Pour pouvoir les utiliser, vous devez d'abord créer un jeton."
- token_label: 'Jeton RSS'
- no_token: 'Aucun jeton généré'
- token_create: 'Créez votre jeton'
- token_reset: 'Réinitialisez votre jeton'
- rss_links: 'URL de vos flux RSS'
+ description: "Les flux RSS fournis par wallabag vous permettent de lire vos articles sauvegardés dans votre lecteur de flux préféré. Pour pouvoir les utiliser, vous devez d’abord créer un jeton."
+ token_label: "Jeton RSS"
+ no_token: "Aucun jeton généré"
+ token_create: "Créez votre jeton"
+ token_reset: "Réinitialisez votre jeton"
+ rss_links: "Adresse de vos flux RSS"
rss_link:
- unread: 'non lus'
- starred: 'favoris'
- archive: 'lus'
- rss_limit: "Nombre d'articles dans le flux"
+ unread: "non lus"
+ starred: "favoris"
+ archive: "lus"
+ rss_limit: "Nombre d’articles dans le flux"
form_user:
- two_factor_description: "Activer l'authentification double-facteur veut dire que vous allez recevoir un code par email à chaque nouvelle connexion non approuvée."
- name_label: 'Nom'
- email_label: 'Adresse e-mail'
- twoFactorAuthentication_label: 'Double authentification'
+ two_factor_description: "Activer l’authentification double-facteur veut dire que vous allez recevoir un code par courriel à chaque nouvelle connexion non approuvée."
+ name_label: "Nom"
+ email_label: "Adresse courriel"
+ twoFactorAuthentication_label: "Double authentification"
form_password:
- old_password_label: 'Mot de passe actuel'
- new_password_label: 'Nouveau mot de passe'
- repeat_new_password_label: 'Confirmez votre nouveau mot de passe'
+ old_password_label: "Mot de passe actuel"
+ new_password_label: "Nouveau mot de passe"
+ repeat_new_password_label: "Confirmez votre nouveau mot de passe"
form_rules:
- if_label: 'si'
- then_tag_as_label: 'alors attribuer les tags'
- delete_rule_label: 'supprimer'
- edit_rule_label: 'éditer'
- rule_label: 'Règle'
- tags_label: 'Tags'
+ if_label: "si"
+ then_tag_as_label: "alors attribuer les tags"
+ delete_rule_label: "supprimer"
+ edit_rule_label: "éditer"
+ rule_label: "Règle"
+ tags_label: "Tags"
faq:
- title: 'FAQ'
- tagging_rules_definition_title: 'Que signifient les règles de tag automatiques ?'
- tagging_rules_definition_description: "Ce sont des règles utilisées par wallabag pour classer automatiquement vos nouveaux articles.
À chaque fois qu'un nouvel article est ajouté, toutes les règles de tag automatiques seront utilisées afin d'ajouter les tags que vous avez configurés, vous épargnant ainsi l'effort de classifier vos articles manuellement."
- how_to_use_them_title: 'Comment les utiliser ?'
- how_to_use_them_description: 'Imaginons que voulez attribuer aux nouveaux articles le tag « lecture courte » lorsque le temps de lecture est inférieur à 3 minutes.
Dans ce cas, vous devriez mettre « readingTime <= 3 » dans le champ Règle et « lecture courte » dans le champ Tag.
Plusieurs tags peuvent être ajoutés simultanément en les séparant par des virgules : « lecture courte, à lire »
Des règles complexes peuvent être créées en utilisant des opérateurs prédéfinis: si « readingTime >= 5 AND domainName = \"github.com\" » alors attribuer les tags « lecture longue, github »'
- variables_available_title: 'Quelles variables et opérateurs puis-je utiliser pour écrire des règles ?'
- variables_available_description: 'Les variables et opérateurs suivants peuvent être utilisés pour écrire des règles de tag automatiques :'
- meaning: 'Signification'
+ title: "FAQ"
+ tagging_rules_definition_title: "Que signifient les règles de tag automatiques ?"
+ tagging_rules_definition_description: "Ce sont des règles utilisées par wallabag pour classer automatiquement vos nouveaux articles.
À chaque fois qu’un nouvel article est ajouté, toutes les règles de tag automatiques seront utilisées afin d’ajouter les tags que vous avez configurés, vous épargnant ainsi l’effort de classifier vos articles manuellement."
+ how_to_use_them_title: "Comment les utiliser ?"
+ how_to_use_them_description: "Imaginons que voulez attribuer aux nouveaux articles le tag « lecture courte » lorsque le temps de lecture est inférieur à 3 minutes.
Dans ce cas, vous devriez mettre « readingTime <= 3 » dans le champ Règle et « lecture courte » dans le champ Tag.
Plusieurs tags peuvent être ajoutés simultanément en les séparant par des virgules : « lecture courte, à lire »
Des règles complexes peuvent être créées en utilisant des opérateurs prédéfinis: si « readingTime >= 5 AND domainName = \"github.com\" » alors attribuer les tags « lecture longue, github »"
+ variables_available_title: "Quelles variables et opérateurs puis-je utiliser pour écrire des règles ?"
+ variables_available_description: "Les variables et opérateurs suivants peuvent être utilisés pour écrire des règles de tag automatiques :"
+ meaning: "Signification"
variable_description:
- label: 'Variable'
- title: "Titre de l'article"
- url: "URL de l'article"
- isArchived: "Si l'article est archivé ou non"
- isStarred: "Si l'article est favori ou non"
- content: "Le contenu de l'article"
- language: "La langue de l'article"
- mimetype: "Le type MIME de l'article"
- readingTime: "Le temps de lecture estimé de l'article, en minutes"
- domainName: "Le nom de domaine de l'article"
+ label: "Variable"
+ title: "Titre de l’article"
+ url: "Adresse de l’article"
+ isArchived: "Si l’article est archivé ou non"
+ isStarred: "Si l’article est favori ou non"
+ content: "Le contenu de l’article"
+ language: "La langue de l’article"
+ mimetype: "Le type MIME de l’article"
+ readingTime: "Le temps de lecture estimé de l’article, en minutes"
+ domainName: "Le nom de domaine de l’article"
operator_description:
- label: 'Opérateur'
- less_than: 'Moins que…...'
- strictly_less_than: 'Strictement moins que…'
- greater_than: 'Plus que…'
- strictly_greater_than: 'Strictement plus que…'
- equal_to: 'Égal à…'
- not_equal_to: 'Différent de…'
- or: "Une règle OU l'autre"
- and: "Une règle ET l'autre"
- matches: 'Teste si un sujet correspond à une recherche (non sensible à la casse).
Exemple : title matches "football"
'
+ label: "Opérateur"
+ less_than: "Moins que…..."
+ strictly_less_than: "Strictement moins que…"
+ greater_than: "Plus que…"
+ strictly_greater_than: "Strictement plus que…"
+ equal_to: "Égal à…"
+ not_equal_to: "Différent de…"
+ or: "Une règle OU l’autre"
+ and: "Une règle ET l’autre"
+ matches: "Teste si un sujet correspond à une recherche (non sensible à la casse).
Exemple : title matches "football"
"
entry:
page_titles:
- unread: 'Articles non lus'
- starred: 'Articles favoris'
- archived: 'Articles lus'
- filtered: 'Articles filtrés'
- filtered_tags: 'Articles filtrés par tags :'
- untagged: 'Article sans tag'
+ unread: "Articles non lus"
+ starred: "Articles favoris"
+ archived: "Articles lus"
+ filtered: "Articles filtrés"
+ filtered_tags: "Articles filtrés par tags :"
+ untagged: "Article sans tag"
list:
- number_on_the_page: "{0} Il n'y a pas d'articles.|{1} Il y a un article.|]1,Inf[ Il y a %count% articles."
- reading_time: 'durée de lecture'
- reading_time_minutes: 'durée de lecture: %readingTime% min'
- reading_time_less_one_minute: 'durée de lecture: < 1 min'
- number_of_tags: '{1}et un autre tag|]1,Inf[et %count% autres tags'
- reading_time_minutes_short: '%readingTime% min'
- reading_time_less_one_minute_short: '< 1 min'
- original_article: 'original'
- toogle_as_read: 'Marquer comme lu/non lu'
- toogle_as_star: 'Marquer comme favori'
- delete: 'Supprimer'
- export_title: 'Exporter'
+ number_on_the_page: "{0} Il n’y a pas d’articles.|{1} Il y a un article.|]1,Inf[ Il y a %count% articles."
+ reading_time: "durée de lecture"
+ reading_time_minutes: "durée de lecture: %readingTime% min"
+ reading_time_less_one_minute: "durée de lecture: < 1 min"
+ number_of_tags: "{1}et un autre tag|]1,Inf[et %count% autres tags"
+ reading_time_minutes_short: "%readingTime% min"
+ reading_time_less_one_minute_short: "< 1 min"
+ original_article: "original"
+ toogle_as_read: "Marquer comme lu/non lu"
+ toogle_as_star: "Marquer comme favori"
+ delete: "Supprimer"
+ export_title: "Exporter"
filters:
- title: 'Filtres'
- status_label: 'Status'
- archived_label: 'Lus'
- starred_label: 'Favoris'
- unread_label: 'Non lus'
- preview_picture_label: 'A une photo'
- preview_picture_help: 'Photo'
- language_label: 'Langue'
+ title: "Filtres"
+ status_label: "Status"
+ archived_label: "Lus"
+ starred_label: "Favoris"
+ unread_label: "Non lus"
+ preview_picture_label: "A une photo"
+ preview_picture_help: "Photo"
+ language_label: "Langue"
reading_time:
- label: 'Durée de lecture en minutes'
- from: 'de'
- to: 'à'
- domain_label: 'Nom de domaine'
+ label: "Durée de lecture en minutes"
+ from: "de"
+ to: "à"
+ domain_label: "Nom de domaine"
created_at:
- label: 'Date de création'
- from: 'de'
- to: 'à'
+ label: "Date de création"
+ from: "de"
+ to: "à"
action:
- clear: 'Effacer'
- filter: 'Filtrer'
+ clear: "Effacer"
+ filter: "Filtrer"
view:
left_menu:
- back_to_top: 'Revenir en haut'
- back_to_homepage: 'Retour'
- set_as_read: 'Marquer comme lu'
- set_as_unread: 'Marquer comme non lu'
- set_as_starred: 'Mettre en favori'
- view_original_article: 'Article original'
- re_fetch_content: 'Recharger le contenu'
- delete: 'Supprimer'
- add_a_tag: 'Ajouter un tag'
- share_content: 'Partager'
- share_email_label: 'Email'
- public_link: 'Lien public'
- delete_public_link: 'Supprimer lien public'
- download: 'Télécharger'
- print: 'Imprimer'
+ back_to_top: "Revenir en haut"
+ back_to_homepage: "Retour"
+ set_as_read: "Marquer comme lu"
+ set_as_unread: "Marquer comme non lu"
+ set_as_starred: "Mettre en favori"
+ view_original_article: "Article original"
+ re_fetch_content: "Recharger le contenu"
+ delete: "Supprimer"
+ add_a_tag: "Ajouter un tag"
+ share_content: "Partager"
+ share_email_label: "Courriel"
+ public_link: "Lien public"
+ delete_public_link: "Supprimer lien public"
+ download: "Télécharger"
+ print: "Imprimer"
problem:
- label: 'Un problème ?'
- description: "Est-ce que cet article s'affiche mal ?"
- edit_title: 'Modifier le titre'
- original_article: 'original'
- annotations_on_the_entry: '{0} Aucune annotation|{1} Une annotation|]1,Inf[ %count% annotations'
- created_at: 'Date de création'
+ label: "Un problème ?"
+ description: "Est-ce que cet article s’affiche mal ?"
+ edit_title: "Modifier le titre"
+ original_article: "original"
+ annotations_on_the_entry: "{0} Aucune annotation|{1} Une annotation|]1,Inf[ %count% annotations"
+ created_at: "Date de création"
new:
- page_title: 'Sauvegarder un nouvel article'
- placeholder: 'http://website.com'
+ page_title: "Sauvegarder un nouvel article"
+ placeholder: "http://website.com"
form_new:
- url_label: Url
+ url_label: "Adresse"
edit:
- page_title: 'Éditer un article'
- title_label: 'Titre'
- url_label: 'Url'
- is_public_label: 'Public'
- save_label: 'Enregistrer'
+ page_title: "Éditer un article"
+ title_label: "Titre"
+ url_label: "Adresse"
+ is_public_label: "Public"
+ save_label: "Enregistrer"
public:
- shared_by_wallabag: "Cet article a été partagé par wallabag"
+ shared_by_wallabag: "Cet article a été partagé par wallabag"
about:
- page_title: 'À propos'
+ page_title: "À propos"
top_menu:
- who_behind_wallabag: "L'équipe derrière wallabag"
- getting_help: "Besoin d'aide"
- helping: 'Aider wallabag'
- contributors: 'Contributeurs'
- third_party: 'Librairies tierces'
+ who_behind_wallabag: "L’équipe derrière wallabag"
+ getting_help: "Besoin d’aide"
+ helping: "Aider wallabag"
+ contributors: "Contributeurs"
+ third_party: "Librairies tierces"
who_behind_wallabag:
- developped_by: 'Développé par'
- website: 'Site web'
- many_contributors: 'Et plein de contributeurs ♥ sur Github'
- project_website: 'Site web du projet'
- license: 'Licence'
- version: 'Version'
+ developped_by: "Développé par"
+ website: "Site web"
+ many_contributors: "Et plein de contributeurs ♥ sur Github"
+ project_website: "Site web du projet"
+ license: "Licence"
+ version: "Version"
getting_help:
- documentation: 'Documentation'
- bug_reports: 'Rapport de bugs'
- support: 'Sur notre site de support ou sur GitHub'
+ documentation: "Documentation"
+ bug_reports: "Rapport de bogue"
+ support: "Sur notre site de support ou sur GitHub"
helping:
- description: 'wallabag est gratuit et opensource. Vous pouvez nous aider :'
- by_contributing: 'en contribuant au projet :'
- by_contributing_2: 'un ticket recense tous nos besoins'
- by_paypal: 'via Paypal'
+ description: "wallabag est gratuit et opensource. Vous pouvez nous aider :"
+ by_contributing: "en contribuant au projet :"
+ by_contributing_2: "un ticket recense tous nos besoins"
+ by_paypal: "via Paypal"
contributors:
- description: "Merci aux contributeurs de l'application web de wallabag"
+ description: "Merci aux contributeurs de l’application web de wallabag"
third_party:
- description: 'Voici la liste des dépendances utilisées dans wallabag (et leur license) :'
- package: 'Dépendance'
- license: 'Licence'
+ description: "Voici la liste des dépendances utilisées dans wallabag (et leur license) :"
+ package: "Dépendance"
+ license: "Licence"
howto:
- page_title: 'Aide'
- page_description: "Il y a plusieurs façon d'enregistrer un article :"
+ page_title: "Aide"
+ page_description: "Il y a plusieurs façon d’enregistrer un article :"
top_menu:
- browser_addons: 'Extensions de navigateur'
- mobile_apps: 'Applications smartphone'
- bookmarklet: 'Bookmarklet'
+ browser_addons: "Extensions de navigateur"
+ mobile_apps: "Applications smartphone"
+ bookmarklet: "Bookmarklet"
form:
- description: 'Grâce à ce formulaire'
+ description: "Grâce à ce formulaire"
browser_addons:
- firefox: 'Extension Firefox'
- chrome: 'Extension Chrome'
+ firefox: "Extension Firefox"
+ chrome: "Extension Chrome"
mobile_apps:
android:
- via_f_droid: 'via F-Droid'
- via_google_play: 'via Google Play'
- ios: 'sur iTunes Store'
- windows: 'sur Microsoft Store'
+ via_f_droid: "via F-Droid"
+ via_google_play: "via Google Play"
+ ios: "sur iTunes Store"
+ windows: "sur Microsoft Store"
bookmarklet:
- description: 'Glissez et déposez ce lien dans votre barre de favoris :'
+ description: "Glissez et déposez ce lien dans votre barre de favoris :"
quickstart:
- page_title: 'Pour bien débuter'
- more: 'Et plus encore…'
+ page_title: "Pour bien débuter"
+ more: "Et plus encore…"
intro:
- title: 'Bienvenue sur wallabag !'
+ title: "Bienvenue sur wallabag !"
paragraph_1: "Nous allons vous accompagner pour vous faire faire le tour de la maison et vous présenter quelques fonctionnalités qui pourraient vous intéresser pour vous approprier cet outil."
- paragraph_2: 'Suivez-nous !'
+ paragraph_2: "Suivez-nous !"
configure:
- title: "Configurez l'application"
- description: 'Pour voir une application qui vous correspond, allez voir du côté de la configuration de wallabag.'
- language: "Changez la langue et le design de l'application"
- rss: 'Activez les flux RSS'
- tagging_rules: 'Écrivez des règles pour classer automatiquement vos articles'
+ title: "Configurez l’application"
+ description: "Pour voir une application qui vous correspond, allez voir du côté de la configuration de wallabag."
+ language: "Changez la langue et le design de l’application"
+ rss: "Activez les flux RSS"
+ tagging_rules: "Écrivez des règles pour classer automatiquement vos articles"
admin:
- title: 'Administration'
- description: "En tant qu'administrateur sur wallabag, vous avez des privilèges qui vous permettent de :"
- new_user: 'Créer un nouvel utilisateur'
- analytics: 'Configurer les statistiques'
- sharing: 'Activer des paramètres de partages'
- export: "Configurer les formats d'export"
- import: "Configurer l'import"
+ title: "Administration"
+ description: "En tant qu’administrateur sur wallabag, vous avez des privilèges qui vous permettent de :"
+ new_user: "Créer un nouvel utilisateur"
+ analytics: "Configurer les statistiques"
+ sharing: "Activer des paramètres de partages"
+ export: "Configurer les formats d’export"
+ import: "Configurer l’import"
first_steps:
- title: 'Premiers pas'
- description: "Maintenant que wallabag est bien configuré, il est temps d'archiver le web. Vous pouvez cliquer sur le signe + dans le coin en haut à droite."
- new_article: 'Ajoutez votre premier article'
- unread_articles: 'Et rangez-le !'
+ title: "Premiers pas"
+ description: "Maintenant que wallabag est bien configuré, il est temps d’archiver le web. Vous pouvez cliquer sur le signe + dans le coin en haut à droite."
+ new_article: "Ajoutez votre premier article"
+ unread_articles: "Et rangez-le !"
migrate:
- title: 'Migrer depuis un service existant'
- description: "Vous êtes un ancien utilisateur d'un service existant ? Nous allons vous aider à récupérer vos données sur wallabag."
- pocket: 'Migrer depuis Pocket'
- wallabag_v1: 'Migrer depuis wallabag v1'
- wallabag_v2: 'Migrer depuis wallabag v2'
- readability: 'Migrer depuis Readability'
- instapaper: 'Migrer depuis Instapaper'
+ title: "Migrer depuis un service existant"
+ description: "Vous êtes un ancien utilisateur d’un service existant ? Nous allons vous aider à récupérer vos données sur wallabag."
+ pocket: "Migrer depuis Pocket"
+ wallabag_v1: "Migrer depuis wallabag v1"
+ wallabag_v2: "Migrer depuis wallabag v2"
+ readability: "Migrer depuis Readability"
+ instapaper: "Migrer depuis Instapaper"
developer:
- title: 'Pour les développeurs'
- description: 'Nous avons aussi pensé aux développeurs : Docker, API, traductions, etc.'
- create_application: 'Créer votre application tierce'
- use_docker: 'Utiliser Docker pour installer wallabag'
+ title: "Pour les développeurs"
+ description: "Nous avons aussi pensé aux développeurs : Docker, API, traductions, etc."
+ create_application: "Créer votre application tierce"
+ use_docker: "Utiliser Docker pour installer wallabag"
docs:
- title: 'Documentation complète'
- description: "Il y a tellement de fonctionnalités dans wallabag. N'hésitez pas à lire le manuel pour les connaitre et apprendre comment les utiliser."
- annotate: 'Annoter votre article'
- export: 'Convertissez vos articles en ePub ou en PDF'
- search_filters: "Apprenez à utiliser le moteur de recherche et les filtres pour retrouver l'article qui vous intéresse"
- fetching_errors: "Que faire si mon article n'est pas correctement récupéré ?"
- all_docs: "Et encore plein d'autres choses !"
+ title: "Documentation complète"
+ description: "Il y a tellement de fonctionnalités dans wallabag. N’hésitez pas à lire le manuel pour les connaitre et apprendre comment les utiliser."
+ annotate: "Annoter votre article"
+ export: "Convertissez vos articles en ePub ou en PDF"
+ search_filters: "Apprenez à utiliser le moteur de recherche et les filtres pour retrouver l’article qui vous intéresse"
+ fetching_errors: "Que faire si mon article n’est pas correctement récupéré ?"
+ all_docs: "Et encore plein d’autres choses !"
support:
- title: 'Support'
- description: 'Parce que vous avez peut-être besoin de nous poser une question, nous sommes disponibles pour vous.'
- github: 'Sur GitHub'
- email: 'Par e-mail'
- gitter: 'Sur Gitter'
+ title: "Support"
+ description: "Parce que vous avez peut-être besoin de nous poser une question, nous sommes disponibles pour vous."
+ github: "Sur GitHub"
+ email: "Par courriel"
+ gitter: "Sur Gitter"
tag:
- page_title: 'Tags'
+ page_title: "Tags"
list:
- number_on_the_page: "{0} Il n'y a pas de tag.|{1} Il y a un tag.|]1,Inf[ Il y a %count% tags."
- see_untagged_entries: 'Voir les articles sans tag'
+ number_on_the_page: "{0} Il n’y a pas de tag.|{1} Il y a un tag.|]1,Inf[ Il y a %count% tags."
+ see_untagged_entries: "Voir les articles sans tag"
import:
- page_title: 'Importer'
- page_description: "Bienvenue dans l'outil de migration de wallabag. Choisissez ci-dessous le service depuis lequel vous souhaitez migrer."
+ page_title: "Importer"
+ page_description: "Bienvenue dans l’outil de migration de wallabag. Choisissez ci-dessous le service depuis lequel vous souhaitez migrer."
action:
- import_contents: 'Importer les contenus'
+ import_contents: "Importer les contenus"
form:
- mark_as_read_title: 'Marquer tout comme lu ?'
- mark_as_read_label: 'Marquer tous les contenus importés comme lus'
- file_label: 'Fichier'
- save_label: 'Importer le fichier'
+ mark_as_read_title: "Marquer tout comme lu ?"
+ mark_as_read_label: "Marquer tous les contenus importés comme lus"
+ file_label: "Fichier"
+ save_label: "Importer le fichier"
pocket:
- page_title: 'Importer > Pocket'
+ page_title: "Importer > Pocket"
description: "Cet outil va importer toutes vos données de Pocket. Pocket ne nous autorise pas à récupérer le contenu depuis leur service, donc wallabag doit reparcourir chaque article pour récupérer son contenu."
config_missing:
- description: "L'import à partir de Pocket n'est pas configuré."
- admin_message: "Vous devez définir %keyurls%une clé pour l'API Pocket%keyurle%."
- user_message: "L'administrateur de votre serveur doit définir une clé pour l'API Pocket."
- authorize_message: "Vous pouvez importer vos données depuis votre compte Pocket. Vous n'avez qu'à cliquer sur le bouton ci-dessous et à autoriser wallabag à se connecter à getpocket.com."
- connect_to_pocket: 'Se connecter à Pocket et importer les données'
+ description: "L’import à partir de Pocket n’est pas configuré."
+ admin_message: "Vous devez définir %keyurls%une clé pour l’API Pocket%keyurle%."
+ user_message: "L’administrateur de votre serveur doit définir une clé pour l’API Pocket."
+ authorize_message: "Vous pouvez importer vos données depuis votre compte Pocket. Vous n’avez qu’à cliquer sur le bouton ci-dessous et à autoriser wallabag à se connecter à getpocket.com."
+ connect_to_pocket: "Se connecter à Pocket et importer les données"
wallabag_v1:
- page_title: 'Importer > Wallabag v1'
- description: 'Cet outil va importer toutes vos données de wallabag v1. Sur votre page de configuration de wallabag v1, cliquez sur "Export JSON" dans la section "Exporter vos données de wallabag". Vous allez récupérer un fichier "wallabag-export-1-xxxx-xx-xx.json".'
- how_to: "Choisissez le fichier de votre export wallabag v1 et cliquez sur le bouton ci-dessous pour l'importer."
+ page_title: "Importer > Wallabag v1"
+ description: "Cet outil va importer toutes vos données de wallabag v1. Sur votre page de configuration de wallabag v1, cliquez sur "Export JSON" dans la section "Exporter vos données de wallabag". Vous allez récupérer un fichier "wallabag-export-1-xxxx-xx-xx.json"."
+ how_to: "Choisissez le fichier de votre export wallabag v1 et cliquez sur le bouton ci-dessous pour l’importer."
wallabag_v2:
- page_title: 'Importer > Wallabag v2'
- description: "Cet outil va importer tous vos articles d'une autre instance de wallabag v2. Allez dans tous vos articles, puis, sur la barre latérale, cliquez sur \"JSON\". Vous allez récupérer un fichier \"All articles.json\""
+ page_title: "Importer > Wallabag v2"
+ description: "Cet outil va importer tous vos articles d’une autre instance de wallabag v2. Allez dans tous vos articles, puis, sur la barre latérale, cliquez sur \"JSON\". Vous allez récupérer un fichier \"All articles.json\""
readability:
- page_title: 'Importer > Readability'
- description: 'Cet outil va importer toutes vos données de Readability. Sur la page des outils (https://www.readability.com/tools/), cliquez sur "Export your data" dans la section "Data Export". Vous allez recevoir un email avec un lien pour télécharger le json.'
- how_to: "Choisissez le fichier de votre export Readability et cliquez sur le bouton ci-dessous pour l'importer."
+ page_title: "Importer > Readability"
+ description: "Cet outil va importer toutes vos données de Readability. Sur la page des outils (https://www.readability.com/tools/), cliquez sur "Export your data" dans la section "Data Export". Vous allez recevoir un courriel avec un lien pour télécharger le json."
+ how_to: "Choisissez le fichier de votre export Readability et cliquez sur le bouton ci-dessous pour l’importer."
worker:
- enabled: "Les imports sont asynchrones. Une fois l'import commencé un worker externe traitera les messages un par un. Le service activé est :"
+ enabled: "Les imports sont asynchrones. Une fois l’import commencé un worker externe traitera les messages un par un. Le service activé est :"
firefox:
- page_title: 'Import > Firefox'
- description: "Cet outil va vous permettre d'importer tous vos marques-pages de Firefox. Ouvrez le panneau des marques-pages (Ctrl+Maj+O), puis dans « Importation et sauvegarde », choisissez « Sauvegarde... ». Vous allez récupérer un fichier .json. "
- how_to: "Choisissez le fichier de sauvegarde de vos marques-page et cliquez sur le bouton pour l'importer. Soyez avertis que le processus peut prendre un temps assez long car tous les articles doivent être récupérés en ligne."
+ page_title: "Import > Firefox"
+ description: "Cet outil va vous permettre d’importer tous vos marques-pages de Firefox. Ouvrez le panneau des marques-pages (Ctrl+Maj+O), puis dans « Importation et sauvegarde », choisissez « Sauvegarde... ». Vous allez récupérer un fichier .json. "
+ how_to: "Choisissez le fichier de sauvegarde de vos marques-page et cliquez sur le bouton pour l’importer. Soyez avertis que le processus peut prendre un temps assez long car tous les articles doivent être récupérés en ligne."
chrome:
- page_title: 'Import > Chrome'
- description: "Cet outil va vous permettre d'importer tous vos marques-pages de Google Chrome/Chromium. Pour Google Chrome, la situation du fichier dépend de votre système d'exploitation : - Sur GNU/Linux, allez dans le répertoire
~/.config/google-chrome/Default/
- Sous Windows, il devrait se trouver à
%LOCALAPPDATA%\\Google\\Chrome\\User Data\\Default
- Sur OS X, il devrait se trouver dans le fichier
~/Library/Application Support/Google/Chrome/Default/Bookmarks
Une fois que vous y êtes, copiez le fichier Bookmarks à un endroit où vous le retrouverez.
Notez que si vous utilisez Chromium à la place de Chrome, vous devez corriger les chemins en conséquence."
- how_to: "Choisissez le fichier de sauvegarde de vos marques-page et cliquez sur le bouton pour l'importer. Soyez avertis que le processus peut prendre un temps assez long car tous les articles doivent être récupérés en ligne."
+ page_title: "Import > Chrome"
+ description: "Cet outil va vous permettre d’importer tous vos marques-pages de Google Chrome/Chromium. Pour Google Chrome, la situation du fichier dépend de votre système d’exploitation : - Sur GNU/Linux, allez dans le répertoire
~/.config/google-chrome/Default/
- Sous Windows, il devrait se trouver à
%LOCALAPPDATA%\\Google\\Chrome\\User Data\\Default
- Sur OS X, il devrait se trouver dans le fichier
~/Library/Application Support/Google/Chrome/Default/Bookmarks
Une fois que vous y êtes, copiez le fichier Bookmarks à un endroit où vous le retrouverez.
Notez que si vous utilisez Chromium à la place de Chrome, vous devez corriger les chemins en conséquence."
+ how_to: "Choisissez le fichier de sauvegarde de vos marques-page et cliquez sur le bouton pour l’importer. Soyez avertis que le processus peut prendre un temps assez long car tous les articles doivent être récupérés en ligne."
instapaper:
- page_title: 'Import > Instapaper'
- description: 'Sur la page des paramètres (https://www.instapaper.com/user), cliquez sur "Download .CSV file" dans la section "Export". Un fichier CSV se téléchargera ("instapaper-export.csv").'
- how_to: "Choisissez le fichier de votre export Instapaper et cliquez sur le bouton ci-dessous pour l'importer."
+ page_title: "Import > Instapaper"
+ description: "Sur la page des paramètres (https://www.instapaper.com/user), cliquez sur "Download .CSV file" dans la section "Export". Un fichier CSV se téléchargera ("instapaper-export.csv")."
+ how_to: "Choisissez le fichier de votre export Instapaper et cliquez sur le bouton ci-dessous pour l’importer."
developer:
- page_title: 'Développeur'
- welcome_message: "Bienvenue sur l'API de wallabag"
- documentation: 'Documentation'
- how_to_first_app: 'Comment créer votre première application'
- full_documentation: "Voir la documentation complète de l'API"
- list_methods: "Lister toutes les méthodes de l'API"
+ page_title: "Développeur"
+ welcome_message: "Bienvenue sur l’API de wallabag"
+ documentation: "Documentation"
+ how_to_first_app: "Comment créer votre première application"
+ full_documentation: "Voir la documentation complète de l’API"
+ list_methods: "Lister toutes les méthodes de l’API"
clients:
- title: 'Clients'
- create_new: 'Créer un nouveau client'
+ title: "Clients"
+ create_new: "Créer un nouveau client"
existing_clients:
- title: 'Les clients existants'
- field_id: 'ID Client'
- field_secret: 'Clé secrète'
- field_uris: 'URLs de redirection'
- field_grant_types: 'Type de privilège accordé'
- no_client: 'Aucun client pour le moment'
+ title: "Les clients existants"
+ field_id: "ID Client"
+ field_secret: "Clé secrète"
+ field_uris: "Adresse de redirection"
+ field_grant_types: "Type de privilège accordé"
+ no_client: "Aucun client pour le moment"
remove:
- warn_message_1: 'Vous avez la possibilité de supprimer le client %name%. Cette action est IRREVERSIBLE !'
- warn_message_2: "Si vous supprimez le client %name%, toutes les applications qui l'utilisaient ne fonctionneront plus avec votre compte wallabag."
- action: 'Supprimer le client %name%'
+ warn_message_1: "Vous avez la possibilité de supprimer le client %name%. Cette action est IRRÉVERSIBLE !"
+ warn_message_2: "Si vous supprimez le client %name%, toutes les applications qui l’utilisaient ne fonctionneront plus avec votre compte wallabag."
+ action: "Supprimer le client %name%"
client:
- page_title: 'Développeur > Nouveau client'
- page_description: "Vous allez créer un nouveau client. Merci de remplir l'url de redirection vers votre application."
+ page_title: "Développeur > Nouveau client"
+ page_description: "Vous allez créer un nouveau client. Merci de remplir l’adresse de redirection vers votre application."
form:
name_label: "Nom du client"
- redirect_uris_label: 'URLs de redirection (optionnel)'
- save_label: 'Créer un nouveau client'
- action_back: 'Retour'
+ redirect_uris_label: "Adresse de redirection (optionnel)"
+ save_label: "Créer un nouveau client"
+ action_back: "Retour"
client_parameter:
- page_title: 'Développeur > Les paramètres de votre client'
- page_description: 'Voilà les paramètres de votre client'
- field_name: 'Nom du client'
- field_id: 'ID Client'
- field_secret: 'Clé secrète'
- back: 'Retour'
- read_howto: 'Lire "comment créer ma première application"'
+ page_title: "Développeur > Les paramètres de votre client"
+ page_description: "Voilà les paramètres de votre client"
+ field_name: "Nom du client"
+ field_id: "ID Client"
+ field_secret: "Clé secrète"
+ back: "Retour"
+ read_howto: "Lire "comment créer ma première application""
howto:
- page_title: 'Développeur > Comment créer votre première application'
+ page_title: "Développeur > Comment créer votre première application"
description:
- paragraph_1: "Les commandes suivantes utilisent la librarie HTTPie. Assurez-vous qu'elle soit installée avant de l'utiliser."
- paragraph_2: "Vous avez besoin d'un token pour échanger entre votre application et l'API de wallabag."
- paragraph_3: 'Pour créer un token, vous devez créer un nouveau client.'
- paragraph_4: 'Maintenant créez votre token (remplacer client_id, client_secret, username et password avec les bonnes valeurs):'
- paragraph_5: "L'API vous retournera une réponse comme ça :"
- paragraph_6: "L'access_token doit être utilisé pour faire un appel à l'API. Par exemple :"
- paragraph_7: "Cet appel va retourner tous les articles de l'utilisateur."
- paragraph_8: "Si vous voulez toutes les méthodes de l'API, jetez un oeil à la documentation de l'API."
- back: 'Retour'
+ paragraph_1: "Les commandes suivantes utilisent la librarie HTTPie. Assurez-vous qu’elle soit installée avant de l’utiliser."
+ paragraph_2: "Vous avez besoin d’un token pour échanger entre votre application et l’API de wallabag."
+ paragraph_3: "Pour créer un token, vous devez créer un nouveau client."
+ paragraph_4: "Maintenant créez votre token (remplacer client_id, client_secret, username et password avec les bonnes valeurs):"
+ paragraph_5: "L’API vous retournera une réponse comme ça :"
+ paragraph_6: "L’access_token doit être utilisé pour faire un appel à l’API. Par exemple :"
+ paragraph_7: "Cet appel va retourner tous les articles de l’utilisateur."
+ paragraph_8: "Si vous voulez toutes les méthodes de l’API, jetez un oeil à la documentation de l’API."
+ back: "Retour"
user:
page_title: Gestion des utilisateurs
@@ -430,20 +430,20 @@ user:
no: Non
create_new_one: Créer un nouvel utilisateur
form:
- username_label: "Nom d'utilisateur"
- name_label: 'Nom'
- password_label: 'Mot de passe'
- repeat_new_password_label: 'Confirmez votre nouveau mot de passe'
- plain_password_label: 'Mot de passe en clair'
- email_label: 'Adresse e-mail'
- enabled_label: 'Activé'
- locked_label: 'Bloqué'
- last_login_label: 'Dernière connexion'
+ username_label: "Nom d’utilisateur"
+ name_label: "Nom"
+ password_label: "Mot de passe"
+ repeat_new_password_label: "Confirmez votre nouveau mot de passe"
+ plain_password_label: "Mot de passe en clair"
+ email_label: "Adresse courriel"
+ enabled_label: "Activé"
+ locked_label: "Bloqué"
+ last_login_label: "Dernière connexion"
twofactor_label: Double authentification
- save: Sauvegarder
- delete: Supprimer
- delete_confirm: Êtes-vous sûr?
- back_to_list: Revenir à la liste
+ save: "Sauvegarder"
+ delete: "Supprimer"
+ delete_confirm: "Êtes-vous sûr?"
+ back_to_list: "Revenir à la liste"
error:
page_title: Une erreur est survenue
@@ -451,41 +451,41 @@ error:
flashes:
config:
notice:
- config_saved: 'Les paramètres ont bien été mis à jour. Certains seront pris en compte après déconnexion.'
- password_updated: 'Votre mot de passe a bien été mis à jour'
+ config_saved: "Les paramètres ont bien été mis à jour. Certains seront pris en compte après déconnexion."
+ password_updated: "Votre mot de passe a bien été mis à jour"
password_not_updated_demo: "En démo, vous ne pouvez pas changer le mot de passe de cet utilisateur."
- user_updated: 'Vos informations personnelles ont bien été mises à jour'
- rss_updated: 'La configuration des flux RSS a bien été mise à jour'
- tagging_rules_updated: 'Règles mises à jour'
- tagging_rules_deleted: 'Règle supprimée'
- user_added: 'Utilisateur "%username%" ajouté'
- rss_token_updated: 'Jeton RSS mis à jour'
+ user_updated: "Vos informations personnelles ont bien été mises à jour"
+ rss_updated: "La configuration des flux RSS a bien été mise à jour"
+ tagging_rules_updated: "Règles mises à jour"
+ tagging_rules_deleted: "Règle supprimée"
+ user_added: "Utilisateur "%username%" ajouté"
+ rss_token_updated: "Jeton RSS mis à jour"
entry:
notice:
- entry_already_saved: 'Article déjà sauvergardé le %date%'
- entry_saved: 'Article enregistré'
- entry_saved_failed: 'Article enregistré mais impossible de récupérer le contenu'
- entry_updated: 'Article mis à jour'
- entry_reloaded: 'Article rechargé'
+ entry_already_saved: "Article déjà sauvergardé le %date%"
+ entry_saved: "Article enregistré"
+ entry_saved_failed: "Article enregistré mais impossible de récupérer le contenu"
+ entry_updated: "Article mis à jour"
+ entry_reloaded: "Article rechargé"
entry_reloaded_failed: "Article mis à jour mais impossible de récupérer le contenu"
- entry_archived: 'Article marqué comme lu'
- entry_unarchived: 'Article marqué comme non lu'
- entry_starred: 'Article ajouté dans les favoris'
- entry_unstarred: 'Article retiré des favoris'
- entry_deleted: 'Article supprimé'
+ entry_archived: "Article marqué comme lu"
+ entry_unarchived: "Article marqué comme non lu"
+ entry_starred: "Article ajouté dans les favoris"
+ entry_unstarred: "Article retiré des favoris"
+ entry_deleted: "Article supprimé"
tag:
notice:
- tag_added: 'Tag ajouté'
+ tag_added: "Tag ajouté"
import:
notice:
- failed: "L'import a échoué, veuillez ré-essayer"
- failed_on_file: "Erreur lors du traitement de l'import. Vérifier votre fichier."
- summary: "Rapport d'import: %imported% importés, %skipped% déjà présents."
- summary_with_queue: "Rapport d'import: %queued% en cours de traitement."
+ failed: "L’import a échoué, veuillez ré-essayer"
+ failed_on_file: "Erreur lors du traitement de l’import. Vérifier votre fichier."
+ summary: "Rapport d’import: %imported% importés, %skipped% déjà présents."
+ summary_with_queue: "Rapport d’import: %queued% en cours de traitement."
error:
- redis_enabled_not_installed: Redis est activé pour les imports asynchrones mais impossible de s'y connecter. Vérifier la configuration de Redis.
- rabbit_enabled_not_installed: RabbitMQ est activé pour les imports asynchrones mais impossible de s'y connecter. Vérifier la configuration de RabbitMQ.
+ redis_enabled_not_installed: "Redis est activé pour les imports asynchrones mais impossible de s’y connecter. Vérifier la configuration de Redis."
+ rabbit_enabled_not_installed: "RabbitMQ est activé pour les imports asynchrones mais impossible de s’y connecter. Vérifier la configuration de RabbitMQ."
developer:
notice:
- client_created: 'Nouveau client %name% créé'
- client_deleted: 'Client %name% supprimé'
+ client_created: "Nouveau client %name% créé"
+ client_deleted: "Client %name% supprimé’
diff --git a/src/Wallabag/CoreBundle/Resources/translations/validators.fr.yml b/src/Wallabag/CoreBundle/Resources/translations/validators.fr.yml
index 7ecb4acf6..2d5eca295 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/validators.fr.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/validators.fr.yml
@@ -1,6 +1,6 @@
validator:
- password_must_match: 'Les deux mots de passe doivent être les mêmes'
- password_too_short: 'Le mot de passe doit contenir au moins 8 caractères'
- password_wrong_value: 'Votre mot de passe actuel est faux'
- item_per_page_too_high: "Ca ne va pas plaire à l'application"
- rss_limit_too_hight: "Ca ne va pas plaire à l'application"
+ password_must_match: "Les deux mots de passe doivent être les mêmes"
+ password_too_short: "Le mot de passe doit contenir au moins 8 caractères"
+ password_wrong_value: "Votre mot de passe actuel est faux"
+ item_per_page_too_high: "Ça ne va pas plaire à l’application"
+ rss_limit_too_hight: "Ça ne va pas plaire à l’application"
From 2087e499b4493c7b69032bbef8b7debfdd8cd45c Mon Sep 17 00:00:00 2001
From: Jean-Baptiste
Date: Sun, 30 Oct 2016 12:11:24 +0100
Subject: [PATCH 27/42] Translation update - French
---
.../Resources/translations/wallabag_user.fr.yml | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/Wallabag/UserBundle/Resources/translations/wallabag_user.fr.yml b/src/Wallabag/UserBundle/Resources/translations/wallabag_user.fr.yml
index 30ab5dd9e..fbc95a050 100644
--- a/src/Wallabag/UserBundle/Resources/translations/wallabag_user.fr.yml
+++ b/src/Wallabag/UserBundle/Resources/translations/wallabag_user.fr.yml
@@ -1,11 +1,11 @@
# Two factor mail
auth_code:
- on: 'sur'
+ on: "sur"
mailer:
- subject: "Code d'authentification wallabag"
+ subject: "Code d’authentification wallabag"
body:
hello: "Bonjour %user%,"
first_para: "Comme vous avez activé la double authentification sur votre compte wallabag et que vous venez de vous connecter depuis un nouvel appareil (ordinateur, téléphone, etc.), nous vous envoyons un code pour valider votre connexion."
second_para: "Voici le code à renseigner :"
- support: "Si vous avez un problème de connexion, n'hésitez pas à contacter le support :"
- signature: "L'équipe wallabag"
+ support: "Si vous avez un problème de connexion, n’hésitez pas à contacter le support :"
+ signature: "L’équipe wallabag"
From 4b3c983ab85af2ab09540c4849a9e65843a7ab67 Mon Sep 17 00:00:00 2001
From: Jeremy Benoist
Date: Sun, 30 Oct 2016 20:27:41 +0100
Subject: [PATCH 28/42] Inject parameter instead of service
We are injecting CraueConfig service when we only need to retrieve one or two values from it.
Instead I discovered we can directly inject a value from a service in the service definition!
---
src/Wallabag/CoreBundle/Helper/EntriesExport.php | 7 +++----
src/Wallabag/CoreBundle/Resources/config/services.yml | 2 +-
.../ImportBundle/Resources/config/services.yml | 1 -
src/Wallabag/UserBundle/Mailer/AuthCodeMailer.php | 10 +++++-----
src/Wallabag/UserBundle/Resources/config/services.yml | 3 ++-
5 files changed, 11 insertions(+), 12 deletions(-)
diff --git a/src/Wallabag/CoreBundle/Helper/EntriesExport.php b/src/Wallabag/CoreBundle/Helper/EntriesExport.php
index e50c68a67..4bf292a4f 100644
--- a/src/Wallabag/CoreBundle/Helper/EntriesExport.php
+++ b/src/Wallabag/CoreBundle/Helper/EntriesExport.php
@@ -8,7 +8,6 @@ use JMS\Serializer\SerializerBuilder;
use PHPePub\Core\EPub;
use PHPePub\Core\Structure\OPF\DublinCore;
use Symfony\Component\HttpFoundation\Response;
-use Craue\ConfigBundle\Util\Config;
/**
* This class doesn't have unit test BUT it's fully covered by a functional test with ExportControllerTest.
@@ -27,12 +26,12 @@ class EntriesExport
';
/**
- * @param Config $craueConfig CraueConfig instance to get wallabag instance url from database
+ * @param string $wallabagUrl Wallabag instance url
* @param string $logoPath Path to the logo FROM THE BUNDLE SCOPE
*/
- public function __construct(Config $craueConfig, $logoPath)
+ public function __construct($wallabagUrl, $logoPath)
{
- $this->wallabagUrl = $craueConfig->get('wallabag_url');
+ $this->wallabagUrl = $wallabagUrl;
$this->logoPath = $logoPath;
}
diff --git a/src/Wallabag/CoreBundle/Resources/config/services.yml b/src/Wallabag/CoreBundle/Resources/config/services.yml
index 614488a64..b7b1b61be 100644
--- a/src/Wallabag/CoreBundle/Resources/config/services.yml
+++ b/src/Wallabag/CoreBundle/Resources/config/services.yml
@@ -91,7 +91,7 @@ services:
wallabag_core.helper.entries_export:
class: Wallabag\CoreBundle\Helper\EntriesExport
arguments:
- - "@craue_config"
+ - '@=service(''craue_config'').get(''wallabag_url'')'
- src/Wallabag/CoreBundle/Resources/public/themes/_global/img/appicon/apple-touch-icon-152.png
wallabag.operator.array.matches:
diff --git a/src/Wallabag/ImportBundle/Resources/config/services.yml b/src/Wallabag/ImportBundle/Resources/config/services.yml
index 89adc71b3..d600be0f8 100644
--- a/src/Wallabag/ImportBundle/Resources/config/services.yml
+++ b/src/Wallabag/ImportBundle/Resources/config/services.yml
@@ -20,7 +20,6 @@ services:
arguments:
- "@doctrine.orm.entity_manager"
- "@wallabag_core.content_proxy"
- - "@craue_config"
calls:
- [ setClient, [ "@wallabag_import.pocket.client" ] ]
- [ setLogger, [ "@logger" ]]
diff --git a/src/Wallabag/UserBundle/Mailer/AuthCodeMailer.php b/src/Wallabag/UserBundle/Mailer/AuthCodeMailer.php
index ca9d18f17..961208f27 100644
--- a/src/Wallabag/UserBundle/Mailer/AuthCodeMailer.php
+++ b/src/Wallabag/UserBundle/Mailer/AuthCodeMailer.php
@@ -4,7 +4,6 @@ namespace Wallabag\UserBundle\Mailer;
use Scheb\TwoFactorBundle\Model\Email\TwoFactorInterface;
use Scheb\TwoFactorBundle\Mailer\AuthCodeMailerInterface;
-use Craue\ConfigBundle\Util\Config;
/**
* Custom mailer for TwoFactorBundle email.
@@ -61,16 +60,17 @@ class AuthCodeMailer implements AuthCodeMailerInterface
* @param \Twig_Environment $twig
* @param string $senderEmail
* @param string $senderName
- * @param Config $craueConfig Craue\Config instance to get wallabag support url from database
+ * @param string $supportUrl wallabag support url
+ * @param string $wallabagUrl wallabag instance url
*/
- public function __construct(\Swift_Mailer $mailer, \Twig_Environment $twig, $senderEmail, $senderName, Config $craueConfig)
+ public function __construct(\Swift_Mailer $mailer, \Twig_Environment $twig, $senderEmail, $senderName, $supportUrl, $wallabagUrl)
{
$this->mailer = $mailer;
$this->twig = $twig;
$this->senderEmail = $senderEmail;
$this->senderName = $senderName;
- $this->supportUrl = $craueConfig->get('wallabag_support_url');
- $this->wallabagUrl = $craueConfig->get('wallabag_url');
+ $this->supportUrl = $supportUrl;
+ $this->wallabagUrl = $wallabagUrl;
}
/**
diff --git a/src/Wallabag/UserBundle/Resources/config/services.yml b/src/Wallabag/UserBundle/Resources/config/services.yml
index eb9c8e676..a8ee721b9 100644
--- a/src/Wallabag/UserBundle/Resources/config/services.yml
+++ b/src/Wallabag/UserBundle/Resources/config/services.yml
@@ -6,7 +6,8 @@ services:
- "@twig"
- "%scheb_two_factor.email.sender_email%"
- "%scheb_two_factor.email.sender_name%"
- - "@craue_config"
+ - '@=service(''craue_config'').get(''wallabag_support_url'')'
+ - '@=service(''craue_config'').get(''wallabag_url'')'
wallabag_user.password_resetting:
class: Wallabag\UserBundle\EventListener\PasswordResettingListener
From e1632cea0e19475ff0cc642ea05b365ce651912b Mon Sep 17 00:00:00 2001
From: Jeremy Benoist
Date: Sun, 30 Oct 2016 20:43:37 +0100
Subject: [PATCH 29/42] Fix tests
---
.../UserBundle/Mailer/AuthCodeMailerTest.php | 12 ++----------
1 file changed, 2 insertions(+), 10 deletions(-)
diff --git a/tests/Wallabag/UserBundle/Mailer/AuthCodeMailerTest.php b/tests/Wallabag/UserBundle/Mailer/AuthCodeMailerTest.php
index 441d6519f..21412da6e 100644
--- a/tests/Wallabag/UserBundle/Mailer/AuthCodeMailerTest.php
+++ b/tests/Wallabag/UserBundle/Mailer/AuthCodeMailerTest.php
@@ -26,7 +26,6 @@ class AuthCodeMailerTest extends \PHPUnit_Framework_TestCase
protected $mailer;
protected $spool;
protected $twig;
- protected $config;
protected function setUp()
{
@@ -44,14 +43,6 @@ class AuthCodeMailerTest extends \PHPUnit_Framework_TestCase
TWIG;
$this->twig = new \Twig_Environment(new \Twig_Loader_Array(['WallabagUserBundle:TwoFactor:email_auth_code.html.twig' => $twigTemplate]));
-
- $this->config = $this->getMockBuilder('Craue\ConfigBundle\Util\Config')
- ->disableOriginalConstructor()
- ->getMock();
-
- $this->config->expects($this->any())
- ->method('get')
- ->willReturn('http://0.0.0.0/support');
}
public function testSendEmail()
@@ -67,7 +58,8 @@ TWIG;
$this->twig,
'nobody@test.io',
'wallabag test',
- $this->config
+ 'http://0.0.0.0/support',
+ 'http://0.0.0.0/'
);
$authCodeMailer->sendAuthCode($user);
From 038469e73f651621e8a5c12cf089d0c239031b57 Mon Sep 17 00:00:00 2001
From: FoxMaSk
Date: Sun, 30 Oct 2016 22:38:38 +0100
Subject: [PATCH 30/42] fix path for in install scripts
---
scripts/dev.sh | 6 +++---
scripts/install.sh | 6 +++---
scripts/update.sh | 6 +++---
3 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/scripts/dev.sh b/scripts/dev.sh
index fa3b2d5d5..233830e7c 100644
--- a/scripts/dev.sh
+++ b/scripts/dev.sh
@@ -1,11 +1,11 @@
-#! /usr/bin/env bash
+#!/usr/bin/env bash
# You can execute this file to install wallabag dev environment
# eg: `sh dev.sh`
COMPOSER_COMMAND='composer'
-DIR="${BASH_SOURCE%/*}"
-if [[ ! -d "$DIR" ]]; then DIR="$PWD"; fi
+DIR="${BASH_SOURCE}"
+if [[ ! -d "$DIR" ]]; then DIR="$PWD/scripts"; fi
. "$DIR/require.sh"
$COMPOSER_COMMAND install
diff --git a/scripts/install.sh b/scripts/install.sh
index 7a1f02bd8..e131929ce 100644
--- a/scripts/install.sh
+++ b/scripts/install.sh
@@ -1,11 +1,11 @@
-#! /usr/bin/env bash
+#!/usr/bin/env bash
# You can execute this file to install wallabag
# eg: `sh install.sh prod`
COMPOSER_COMMAND='composer'
-DIR="${BASH_SOURCE%/*}"
-if [[ ! -d "$DIR" ]]; then DIR="$PWD"; fi
+DIR="${BASH_SOURCE}"
+if [[ ! -d "$DIR" ]]; then DIR="$PWD/scripts"; fi
. "$DIR/require.sh"
ENV=$1
diff --git a/scripts/update.sh b/scripts/update.sh
index 45e93f363..6fff8a723 100644
--- a/scripts/update.sh
+++ b/scripts/update.sh
@@ -1,11 +1,11 @@
-#! /usr/bin/env bash
+#!/usr/bin/env bash
# You can execute this file to update wallabag
# eg: `sh update.sh prod`
COMPOSER_COMMAND='composer'
-DIR="${BASH_SOURCE%/*}"
-if [[ ! -d "$DIR" ]]; then DIR="$PWD"; fi
+DIR="${BASH_SOURCE}"
+if [[ ! -d "$DIR" ]]; then DIR="$PWD/scripts"; fi
. "$DIR/require.sh"
ENV=$1
From 99692e8c3322f31fa19b010ce488f88c5f3ce43a Mon Sep 17 00:00:00 2001
From: FoxMaSk
Date: Sun, 30 Oct 2016 22:46:09 +0100
Subject: [PATCH 31/42] fix path for in install scripts
---
scripts/dev.sh | 2 +-
scripts/install.sh | 2 +-
scripts/update.sh | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/scripts/dev.sh b/scripts/dev.sh
index 233830e7c..0703ced1e 100644
--- a/scripts/dev.sh
+++ b/scripts/dev.sh
@@ -5,7 +5,7 @@
COMPOSER_COMMAND='composer'
DIR="${BASH_SOURCE}"
-if [[ ! -d "$DIR" ]]; then DIR="$PWD/scripts"; fi
+if [ ! -d "$DIR" ]; then DIR="$PWD/scripts"; fi
. "$DIR/require.sh"
$COMPOSER_COMMAND install
diff --git a/scripts/install.sh b/scripts/install.sh
index e131929ce..62a46f4fb 100644
--- a/scripts/install.sh
+++ b/scripts/install.sh
@@ -5,7 +5,7 @@
COMPOSER_COMMAND='composer'
DIR="${BASH_SOURCE}"
-if [[ ! -d "$DIR" ]]; then DIR="$PWD/scripts"; fi
+if [ ! -d "$DIR" ]; then DIR="$PWD/scripts"; fi
. "$DIR/require.sh"
ENV=$1
diff --git a/scripts/update.sh b/scripts/update.sh
index 6fff8a723..f43c4f24c 100644
--- a/scripts/update.sh
+++ b/scripts/update.sh
@@ -5,7 +5,7 @@
COMPOSER_COMMAND='composer'
DIR="${BASH_SOURCE}"
-if [[ ! -d "$DIR" ]]; then DIR="$PWD/scripts"; fi
+if [ ! -d "$DIR" ]; then DIR="$PWD/scripts"; fi
. "$DIR/require.sh"
ENV=$1
From 337b47c216c1ae822db17f88273a042dc2138183 Mon Sep 17 00:00:00 2001
From: Jean-Baptiste
Date: Mon, 31 Oct 2016 20:01:07 +0100
Subject: [PATCH 32/42] Translation - French - tiny escape correction
---
src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml
index ae5e78cbe..3f670fbdc 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml
@@ -209,7 +209,7 @@ entry:
is_public_label: "Public"
save_label: "Enregistrer"
public:
- shared_by_wallabag: "Cet article a été partagé par wallabag"
+ shared_by_wallabag: "Cet article a été partagé par wallabag"
about:
page_title: "À propos"
From 31dd328df421f2bb012c3ff7632fd4a5e58bb408 Mon Sep 17 00:00:00 2001
From: Jean-Baptiste
Date: Mon, 31 Oct 2016 20:12:29 +0100
Subject: [PATCH 33/42] Translation - French - tiny escape correction
---
.../Resources/translations/messages.fr.yml | 48 +++++++++----------
1 file changed, 24 insertions(+), 24 deletions(-)
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml
index 3f670fbdc..5da721a44 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml
@@ -104,7 +104,7 @@ config:
tagging_rules_definition_title: "Que signifient les règles de tag automatiques ?"
tagging_rules_definition_description: "Ce sont des règles utilisées par wallabag pour classer automatiquement vos nouveaux articles.
À chaque fois qu’un nouvel article est ajouté, toutes les règles de tag automatiques seront utilisées afin d’ajouter les tags que vous avez configurés, vous épargnant ainsi l’effort de classifier vos articles manuellement."
how_to_use_them_title: "Comment les utiliser ?"
- how_to_use_them_description: "Imaginons que voulez attribuer aux nouveaux articles le tag « lecture courte » lorsque le temps de lecture est inférieur à 3 minutes.
Dans ce cas, vous devriez mettre « readingTime <= 3 » dans le champ Règle et « lecture courte » dans le champ Tag.
Plusieurs tags peuvent être ajoutés simultanément en les séparant par des virgules : « lecture courte, à lire »
Des règles complexes peuvent être créées en utilisant des opérateurs prédéfinis: si « readingTime >= 5 AND domainName = \"github.com\" » alors attribuer les tags « lecture longue, github »"
+ how_to_use_them_description: "Imaginons que voulez attribuer aux nouveaux articles le tag « lecture courte » lorsque le temps de lecture est inférieur à 3 minutes.
Dans ce cas, vous devriez mettre « readingTime <= 3 » dans le champ Règle et « lecture courte » dans le champ Tag.
Plusieurs tags peuvent être ajoutés simultanément en les séparant par des virgules : « lecture courte, à lire »
Des règles complexes peuvent être créées en utilisant des opérateurs prédéfinis: si « readingTime >= 5 AND domainName = \"github.com\" » alors attribuer les tags « lecture longue, github »"
variables_available_title: "Quelles variables et opérateurs puis-je utiliser pour écrire des règles ?"
variables_available_description: "Les variables et opérateurs suivants peuvent être utilisés pour écrire des règles de tag automatiques :"
meaning: "Signification"
@@ -129,7 +129,7 @@ config:
not_equal_to: "Différent de…"
or: "Une règle OU l’autre"
and: "Une règle ET l’autre"
- matches: "Teste si un sujet correspond à une recherche (non sensible à la casse).
Exemple : title matches "football"
"
+ matches: "Teste si un sujet correspond à une recherche (non sensible à la casse).
Exemple : title matches \"football\"
"
entry:
page_titles:
@@ -143,10 +143,10 @@ entry:
number_on_the_page: "{0} Il n’y a pas d’articles.|{1} Il y a un article.|]1,Inf[ Il y a %count% articles."
reading_time: "durée de lecture"
reading_time_minutes: "durée de lecture: %readingTime% min"
- reading_time_less_one_minute: "durée de lecture: < 1 min"
+ reading_time_less_one_minute: "durée de lecture: < 1 min"
number_of_tags: "{1}et un autre tag|]1,Inf[et %count% autres tags"
reading_time_minutes_short: "%readingTime% min"
- reading_time_less_one_minute_short: "< 1 min"
+ reading_time_less_one_minute_short: "< 1 min"
original_article: "original"
toogle_as_read: "Marquer comme lu/non lu"
toogle_as_star: "Marquer comme favori"
@@ -187,7 +187,7 @@ entry:
share_content: "Partager"
share_email_label: "Courriel"
public_link: "Lien public"
- delete_public_link: "Supprimer lien public"
+ delete_public_link: "Supprimer le lien public"
download: "Télécharger"
print: "Imprimer"
problem:
@@ -214,24 +214,24 @@ entry:
about:
page_title: "À propos"
top_menu:
- who_behind_wallabag: "L’équipe derrière wallabag"
+ who_behind_wallabag: "L’équipe derrière Wallabag"
getting_help: "Besoin d’aide"
- helping: "Aider wallabag"
+ helping: "Aider Wallabag"
contributors: "Contributeurs"
third_party: "Librairies tierces"
who_behind_wallabag:
developped_by: "Développé par"
website: "Site web"
- many_contributors: "Et plein de contributeurs ♥ sur Github"
+ many_contributors: "Et plein de contributeurs ♥ sur Github"
project_website: "Site web du projet"
license: "Licence"
version: "Version"
getting_help:
documentation: "Documentation"
bug_reports: "Rapport de bogue"
- support: "Sur notre site de support ou sur GitHub"
+ support: "Sur notre site de support ou sur GitHub"
helping:
- description: "wallabag est gratuit et opensource. Vous pouvez nous aider :"
+ description: "Wallabag est gratuit et opensource. Vous pouvez nous aider :"
by_contributing: "en contribuant au projet :"
by_contributing_2: "un ticket recense tous nos besoins"
by_paypal: "via Paypal"
@@ -325,7 +325,7 @@ tag:
import:
page_title: "Importer"
- page_description: "Bienvenue dans l’outil de migration de wallabag. Choisissez ci-dessous le service depuis lequel vous souhaitez migrer."
+ page_description: "Bienvenue dans l’outil de migration de Wallabag. Choisissez ci-dessous le service depuis lequel vous souhaitez migrer."
action:
import_contents: "Importer les contenus"
form:
@@ -344,14 +344,14 @@ import:
connect_to_pocket: "Se connecter à Pocket et importer les données"
wallabag_v1:
page_title: "Importer > Wallabag v1"
- description: "Cet outil va importer toutes vos données de wallabag v1. Sur votre page de configuration de wallabag v1, cliquez sur "Export JSON" dans la section "Exporter vos données de wallabag". Vous allez récupérer un fichier "wallabag-export-1-xxxx-xx-xx.json"."
+ description: "Cet outil va importer toutes vos données de wallabag v1. Sur votre page de configuration de wallabag v1, cliquez sur « Export JSON » dans la section « Exporter vos données de wallabag ». Vous allez récupérer un fichier « wallabag-export-1-xxxx-xx-xx.json »."
how_to: "Choisissez le fichier de votre export wallabag v1 et cliquez sur le bouton ci-dessous pour l’importer."
wallabag_v2:
page_title: "Importer > Wallabag v2"
- description: "Cet outil va importer tous vos articles d’une autre instance de wallabag v2. Allez dans tous vos articles, puis, sur la barre latérale, cliquez sur \"JSON\". Vous allez récupérer un fichier \"All articles.json\""
+ description: "Cet outil va importer tous vos articles d’une autre instance de wallabag v2. Allez dans tous vos articles, puis, sur la barre latérale, cliquez sur « JSON ». Vous allez récupérer un fichier « All articles.json »"
readability:
page_title: "Importer > Readability"
- description: "Cet outil va importer toutes vos données de Readability. Sur la page des outils (https://www.readability.com/tools/), cliquez sur "Export your data" dans la section "Data Export". Vous allez recevoir un courriel avec un lien pour télécharger le json."
+ description: "Cet outil va importer toutes vos données de Readability. Sur la page des outils (https://www.readability.com/tools/), cliquez sur « Export your data » dans la section « Data Export ». Vous allez recevoir un courriel avec un lien pour télécharger le json."
how_to: "Choisissez le fichier de votre export Readability et cliquez sur le bouton ci-dessous pour l’importer."
worker:
enabled: "Les imports sont asynchrones. Une fois l’import commencé un worker externe traitera les messages un par un. Le service activé est :"
@@ -365,7 +365,7 @@ import:
how_to: "Choisissez le fichier de sauvegarde de vos marques-page et cliquez sur le bouton pour l’importer. Soyez avertis que le processus peut prendre un temps assez long car tous les articles doivent être récupérés en ligne."
instapaper:
page_title: "Import > Instapaper"
- description: "Sur la page des paramètres (https://www.instapaper.com/user), cliquez sur "Download .CSV file" dans la section "Export". Un fichier CSV se téléchargera ("instapaper-export.csv")."
+ description: "Sur la page des paramètres (https://www.instapaper.com/user), cliquez sur « Download .CSV file » dans la section « Export ». Un fichier CSV sera téléchargé (« instapaper-export.csv »)."
how_to: "Choisissez le fichier de votre export Instapaper et cliquez sur le bouton ci-dessous pour l’importer."
developer:
@@ -401,16 +401,16 @@ developer:
page_title: "Développeur > Les paramètres de votre client"
page_description: "Voilà les paramètres de votre client"
field_name: "Nom du client"
- field_id: "ID Client"
+ field_id: "ID client"
field_secret: "Clé secrète"
back: "Retour"
- read_howto: "Lire "comment créer ma première application""
+ read_howto: "Lire « comment créer ma première application »"
howto:
page_title: "Développeur > Comment créer votre première application"
description:
paragraph_1: "Les commandes suivantes utilisent la librarie HTTPie. Assurez-vous qu’elle soit installée avant de l’utiliser."
paragraph_2: "Vous avez besoin d’un token pour échanger entre votre application et l’API de wallabag."
- paragraph_3: "Pour créer un token, vous devez créer un nouveau client."
+ paragraph_3: "Pour créer un token, vous devez créer un nouveau client."
paragraph_4: "Maintenant créez votre token (remplacer client_id, client_secret, username et password avec les bonnes valeurs):"
paragraph_5: "L’API vous retournera une réponse comme ça :"
paragraph_6: "L’access_token doit être utilisé pour faire un appel à l’API. Par exemple :"
@@ -439,10 +439,10 @@ user:
enabled_label: "Activé"
locked_label: "Bloqué"
last_login_label: "Dernière connexion"
- twofactor_label: Double authentification
+ twofactor_label: "Double authentification"
save: "Sauvegarder"
delete: "Supprimer"
- delete_confirm: "Êtes-vous sûr?"
+ delete_confirm: "Voulez-vous vraiment ?"
back_to_list: "Revenir à la liste"
error:
@@ -458,7 +458,7 @@ flashes:
rss_updated: "La configuration des flux RSS a bien été mise à jour"
tagging_rules_updated: "Règles mises à jour"
tagging_rules_deleted: "Règle supprimée"
- user_added: "Utilisateur "%username%" ajouté"
+ user_added: "Utilisateur \"%username%\" ajouté"
rss_token_updated: "Jeton RSS mis à jour"
entry:
notice:
@@ -479,9 +479,9 @@ flashes:
import:
notice:
failed: "L’import a échoué, veuillez ré-essayer"
- failed_on_file: "Erreur lors du traitement de l’import. Vérifier votre fichier."
- summary: "Rapport d’import: %imported% importés, %skipped% déjà présents."
- summary_with_queue: "Rapport d’import: %queued% en cours de traitement."
+ failed_on_file: "Erreur lors du traitement de l’import. Vérifiez votre fichier."
+ summary: "Rapport d’import : %imported% importés, %skipped% déjà présents."
+ summary_with_queue: "Rapport d’import: %queued% en cours de traitement."
error:
redis_enabled_not_installed: "Redis est activé pour les imports asynchrones mais impossible de s’y connecter. Vérifier la configuration de Redis."
rabbit_enabled_not_installed: "RabbitMQ est activé pour les imports asynchrones mais impossible de s’y connecter. Vérifier la configuration de RabbitMQ."
From 303b3c61a7a69f05336a24f8e5f6d4a37fc89205 Mon Sep 17 00:00:00 2001
From: Jean-Baptiste
Date: Mon, 31 Oct 2016 20:16:36 +0100
Subject: [PATCH 34/42] Translation - French - tiny typo
---
src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml
index 5da721a44..fabe3aea2 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml
@@ -394,7 +394,7 @@ developer:
page_description: "Vous allez créer un nouveau client. Merci de remplir l’adresse de redirection vers votre application."
form:
name_label: "Nom du client"
- redirect_uris_label: "Adresse de redirection (optionnel)"
+ redirect_uris_label: "Adresses de redirection (optionnel)"
save_label: "Créer un nouveau client"
action_back: "Retour"
client_parameter:
From 995d909d0f10c9cbdafb92fc10445c959b476740 Mon Sep 17 00:00:00 2001
From: Laurent
Date: Tue, 1 Nov 2016 18:33:32 +0800
Subject: [PATCH 35/42] Add Instapaper to CLI import
---
src/Wallabag/ImportBundle/Command/ImportCommand.php | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/Wallabag/ImportBundle/Command/ImportCommand.php b/src/Wallabag/ImportBundle/Command/ImportCommand.php
index 1df38295f..d1325338d 100644
--- a/src/Wallabag/ImportBundle/Command/ImportCommand.php
+++ b/src/Wallabag/ImportBundle/Command/ImportCommand.php
@@ -50,6 +50,9 @@ class ImportCommand extends ContainerAwareCommand
case 'chrome':
$wallabag = $this->getContainer()->get('wallabag_import.chrome.import');
break;
+ case 'instapaper':
+ $wallabag = $this->getContainer()->get('wallabag_import.instapaper.import');
+ break;
case 'v1':
default:
$wallabag = $this->getContainer()->get('wallabag_import.wallabag_v1.import');
From 22ef6f96e26e8678399e2a53a7e45407ce5a1b1b Mon Sep 17 00:00:00 2001
From: Kevin Decherf
Date: Tue, 1 Nov 2016 19:51:45 +0100
Subject: [PATCH 36/42] Force user-agent for .slashdot.org
Slashdot replaces actual content with a form regarding cookies when
requests originate from France. By forcing the user-agent, the warning
seems to go away.
Signed-off-by: Kevin Decherf
---
src/Wallabag/CoreBundle/Resources/config/services.yml | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/Wallabag/CoreBundle/Resources/config/services.yml b/src/Wallabag/CoreBundle/Resources/config/services.yml
index b7b1b61be..90a2419ea 100644
--- a/src/Wallabag/CoreBundle/Resources/config/services.yml
+++ b/src/Wallabag/CoreBundle/Resources/config/services.yml
@@ -55,6 +55,7 @@ services:
'.fok.nl': 'Googlebot/2.1'
'getpocket.com': 'PHP/5.2'
'iansommerville.com': 'PHP/5.2'
+ '.slashdot.org': 'PHP/5.2'
calls:
- [ setLogger, [ "@logger" ] ]
tags:
From 9c1547069178e8395ce4d43eac760d61e03aa2b0 Mon Sep 17 00:00:00 2001
From: Jeremy Benoist
Date: Wed, 2 Nov 2016 07:15:24 +0100
Subject: [PATCH 37/42] wallabag is full lowercase
---
.../Resources/translations/messages.fr.yml | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml
index fabe3aea2..421cb8b5a 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml
@@ -214,9 +214,9 @@ entry:
about:
page_title: "À propos"
top_menu:
- who_behind_wallabag: "L’équipe derrière Wallabag"
+ who_behind_wallabag: "L’équipe derrière wallabag"
getting_help: "Besoin d’aide"
- helping: "Aider Wallabag"
+ helping: "Aider wallabag"
contributors: "Contributeurs"
third_party: "Librairies tierces"
who_behind_wallabag:
@@ -231,7 +231,7 @@ about:
bug_reports: "Rapport de bogue"
support: "Sur notre site de support ou sur GitHub"
helping:
- description: "Wallabag est gratuit et opensource. Vous pouvez nous aider :"
+ description: "wallabag est gratuit et opensource. Vous pouvez nous aider :"
by_contributing: "en contribuant au projet :"
by_contributing_2: "un ticket recense tous nos besoins"
by_paypal: "via Paypal"
@@ -325,7 +325,7 @@ tag:
import:
page_title: "Importer"
- page_description: "Bienvenue dans l’outil de migration de Wallabag. Choisissez ci-dessous le service depuis lequel vous souhaitez migrer."
+ page_description: "Bienvenue dans l’outil de migration de wallabag. Choisissez ci-dessous le service depuis lequel vous souhaitez migrer."
action:
import_contents: "Importer les contenus"
form:
@@ -343,11 +343,11 @@ import:
authorize_message: "Vous pouvez importer vos données depuis votre compte Pocket. Vous n’avez qu’à cliquer sur le bouton ci-dessous et à autoriser wallabag à se connecter à getpocket.com."
connect_to_pocket: "Se connecter à Pocket et importer les données"
wallabag_v1:
- page_title: "Importer > Wallabag v1"
+ page_title: "Importer > wallabag v1"
description: "Cet outil va importer toutes vos données de wallabag v1. Sur votre page de configuration de wallabag v1, cliquez sur « Export JSON » dans la section « Exporter vos données de wallabag ». Vous allez récupérer un fichier « wallabag-export-1-xxxx-xx-xx.json »."
how_to: "Choisissez le fichier de votre export wallabag v1 et cliquez sur le bouton ci-dessous pour l’importer."
wallabag_v2:
- page_title: "Importer > Wallabag v2"
+ page_title: "Importer > wallabag v2"
description: "Cet outil va importer tous vos articles d’une autre instance de wallabag v2. Allez dans tous vos articles, puis, sur la barre latérale, cliquez sur « JSON ». Vous allez récupérer un fichier « All articles.json »"
readability:
page_title: "Importer > Readability"
@@ -488,4 +488,4 @@ flashes:
developer:
notice:
client_created: "Nouveau client %name% créé"
- client_deleted: "Client %name% supprimé’
+ client_deleted: "Client %name% supprimé"
From 585fd2a4ad39b40413c61d1a8e00bd7507a87833 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nicolas=20L=C5=93uillet?=
Date: Wed, 2 Nov 2016 16:58:20 +0100
Subject: [PATCH 38/42] Added documentation about failed to load external
entity error Fix #2529
---
docs/de/user/faq.rst | 5 +++++
docs/en/user/faq.rst | 5 +++++
docs/fr/user/faq.rst | 5 +++++
3 files changed, 15 insertions(+)
diff --git a/docs/de/user/faq.rst b/docs/de/user/faq.rst
index 1a199c1c5..a3c6a8642 100644
--- a/docs/de/user/faq.rst
+++ b/docs/de/user/faq.rst
@@ -43,3 +43,8 @@ Ich habe mein Passwort vergessen
Du kannst dein Passwort zurücksetzen, indem du auf den Link ``Kennwort vergessen?`` auf der Loginseite klickst. Fülle dann das Formular mit deiner E-Mail-Adresse oder deinem Nutzernamen aus
und du wirst eine E-Mail zum Passwort zurücksetzen erhalten.
+
+I've got the ``failed to load external entity`` error when I try to install wallabag
+------------------------------------------------------------------------------------
+
+As described `here `_, please edit your ``web/app.php`` file and add this line: ``libxml_disable_entity_loader(false);`` on line 5.
diff --git a/docs/en/user/faq.rst b/docs/en/user/faq.rst
index 61303604f..b759ed1b7 100644
--- a/docs/en/user/faq.rst
+++ b/docs/en/user/faq.rst
@@ -46,3 +46,8 @@ I forgot my password
You can reset your password by clicking on ``Forgot your password?`` link,
on the login page. Then, fill the form with your email address or your username,
you'll receive an email to reset your password.
+
+I've got the ``failed to load external entity`` error when I try to install wallabag
+------------------------------------------------------------------------------------
+
+As described `here `_, please edit your ``web/app.php`` file and add this line: ``libxml_disable_entity_loader(false);`` on line 5.
diff --git a/docs/fr/user/faq.rst b/docs/fr/user/faq.rst
index e220c8a70..8286a3113 100644
--- a/docs/fr/user/faq.rst
+++ b/docs/fr/user/faq.rst
@@ -33,3 +33,8 @@ J'ai oublié mon mot de passe
Vous pouvez réinitialiser votre mot de passe en cliquant sur ``Mot de passe oublié ?``,
sur la page de connexion. Ensuite, renseignez votre adresse email ou votre nom d'utilisateur,
un email vous sera envoyé.
+
+J'ai l'erreur ``failed to load external entity`` quand j'essaie d'installer wallabag
+------------------------------------------------------------------------------------
+
+Comme décrit `ici `_, modifiez le fichier ``web/app.php`` et ajoutez la ligne ``libxml_disable_entity_loader(false);`` à la ligne 5.
From 4b5e95c0e52d0627f33cae7cb5f486a53561f5c0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nicolas=20L=C5=93uillet?=
Date: Wed, 2 Nov 2016 17:02:48 +0100
Subject: [PATCH 39/42] Added more info about Doctrine / PHP bug
---
docs/de/user/faq.rst | 2 ++
docs/en/user/faq.rst | 2 ++
docs/fr/user/faq.rst | 2 ++
3 files changed, 6 insertions(+)
diff --git a/docs/de/user/faq.rst b/docs/de/user/faq.rst
index a3c6a8642..51ce5b189 100644
--- a/docs/de/user/faq.rst
+++ b/docs/de/user/faq.rst
@@ -48,3 +48,5 @@ I've got the ``failed to load external entity`` error when I try to install wall
------------------------------------------------------------------------------------
As described `here `_, please edit your ``web/app.php`` file and add this line: ``libxml_disable_entity_loader(false);`` on line 5.
+
+This is a Doctrine / PHP bug, nothing we can do about it.
diff --git a/docs/en/user/faq.rst b/docs/en/user/faq.rst
index b759ed1b7..0f995ce5d 100644
--- a/docs/en/user/faq.rst
+++ b/docs/en/user/faq.rst
@@ -51,3 +51,5 @@ I've got the ``failed to load external entity`` error when I try to install wall
------------------------------------------------------------------------------------
As described `here `_, please edit your ``web/app.php`` file and add this line: ``libxml_disable_entity_loader(false);`` on line 5.
+
+This is a Doctrine / PHP bug, nothing we can do about it.
diff --git a/docs/fr/user/faq.rst b/docs/fr/user/faq.rst
index 8286a3113..717472f93 100644
--- a/docs/fr/user/faq.rst
+++ b/docs/fr/user/faq.rst
@@ -38,3 +38,5 @@ J'ai l'erreur ``failed to load external entity`` quand j'essaie d'installer wall
------------------------------------------------------------------------------------
Comme décrit `ici `_, modifiez le fichier ``web/app.php`` et ajoutez la ligne ``libxml_disable_entity_loader(false);`` à la ligne 5.
+
+C'est un bug lié à PHP et Doctrine, rien que nous ne puissions faire de notre côté.
From cce77ebc2d8186408c4efcca69588fa525618dee Mon Sep 17 00:00:00 2001
From: Strubbl
Date: Wed, 2 Nov 2016 17:15:32 +0100
Subject: [PATCH 40/42] update German faq.rst
---
docs/de/user/faq.rst | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/docs/de/user/faq.rst b/docs/de/user/faq.rst
index 51ce5b189..d541eb3d6 100644
--- a/docs/de/user/faq.rst
+++ b/docs/de/user/faq.rst
@@ -44,9 +44,9 @@ Ich habe mein Passwort vergessen
Du kannst dein Passwort zurücksetzen, indem du auf den Link ``Kennwort vergessen?`` auf der Loginseite klickst. Fülle dann das Formular mit deiner E-Mail-Adresse oder deinem Nutzernamen aus
und du wirst eine E-Mail zum Passwort zurücksetzen erhalten.
-I've got the ``failed to load external entity`` error when I try to install wallabag
-------------------------------------------------------------------------------------
+Ich erhalte den ``failed to load external entity`` Fehler, wenn ich wallabag installiere
+----------------------------------------------------------------------------------------
-As described `here `_, please edit your ``web/app.php`` file and add this line: ``libxml_disable_entity_loader(false);`` on line 5.
+Wie `hier `_ beschrieben, bearbeite bitte deine Datei ``web/app.php``und füge ihr diese Zeile ``libxml_disable_entity_loader(false);`` in Zeile 5 hinzu.
-This is a Doctrine / PHP bug, nothing we can do about it.
+Dies ist ein Doctrine / PHP Fehler - nichts, woran wir etwas ändern können.
From b1057c6a5e0cffcae1b34b8e2affee72a8110460 Mon Sep 17 00:00:00 2001
From: Strubbl
Date: Wed, 2 Nov 2016 17:16:57 +0100
Subject: [PATCH 41/42] update German faq.rst
---
docs/de/user/faq.rst | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/docs/de/user/faq.rst b/docs/de/user/faq.rst
index d541eb3d6..c14cb3efc 100644
--- a/docs/de/user/faq.rst
+++ b/docs/de/user/faq.rst
@@ -44,9 +44,9 @@ Ich habe mein Passwort vergessen
Du kannst dein Passwort zurücksetzen, indem du auf den Link ``Kennwort vergessen?`` auf der Loginseite klickst. Fülle dann das Formular mit deiner E-Mail-Adresse oder deinem Nutzernamen aus
und du wirst eine E-Mail zum Passwort zurücksetzen erhalten.
-Ich erhalte den ``failed to load external entity`` Fehler, wenn ich wallabag installiere
+Ich erhalte den Fehler ``failed to load external entity``, wenn ich wallabag installiere
----------------------------------------------------------------------------------------
-Wie `hier `_ beschrieben, bearbeite bitte deine Datei ``web/app.php``und füge ihr diese Zeile ``libxml_disable_entity_loader(false);`` in Zeile 5 hinzu.
+Wie `hier `_ beschrieben, bearbeite bitte deine Datei ``web/app.php`` und füge ihr diese Zeile ``libxml_disable_entity_loader(false);`` in Zeile 5 hinzu.
Dies ist ein Doctrine / PHP Fehler - nichts, woran wir etwas ändern können.
From a49159e9ebc3390c7658898d814bb11ebd8da188 Mon Sep 17 00:00:00 2001
From: Jeremy Benoist
Date: Wed, 2 Nov 2016 18:08:25 +0100
Subject: [PATCH 42/42] Update faq.rst
---
docs/fr/user/faq.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/fr/user/faq.rst b/docs/fr/user/faq.rst
index 717472f93..49aa94ba3 100644
--- a/docs/fr/user/faq.rst
+++ b/docs/fr/user/faq.rst
@@ -39,4 +39,4 @@ J'ai l'erreur ``failed to load external entity`` quand j'essaie d'installer wall
Comme décrit `ici `_, modifiez le fichier ``web/app.php`` et ajoutez la ligne ``libxml_disable_entity_loader(false);`` à la ligne 5.
-C'est un bug lié à PHP et Doctrine, rien que nous ne puissions faire de notre côté.
+C'est un bug lié à PHP et Doctrine, nous ne pouvons rien faire de notre côté.