From a345479de20bb508ef576af54427c35888deb0cc Mon Sep 17 00:00:00 2001 From: Masoud Abkenar Date: Mon, 11 Sep 2017 01:35:27 +0200 Subject: l10n: update Persian translation (#4880) * l10n: update Persian translation * l10n: fix missing Persian translation --- app/javascript/mastodon/locales/fa.json | 2 ++ 1 file changed, 2 insertions(+) (limited to 'app/javascript') diff --git a/app/javascript/mastodon/locales/fa.json b/app/javascript/mastodon/locales/fa.json index d05b26eb9..284c5a812 100644 --- a/app/javascript/mastodon/locales/fa.json +++ b/app/javascript/mastodon/locales/fa.json @@ -34,6 +34,7 @@ "column.mutes": "کاربران بی‌صداشده", "column.notifications": "اعلان‌ها", "column.public": "نوشته‌های همه‌جا", + "column.pins": "نوشته‌های ثابت", "column_back_button.label": "بازگشت", "column_header.hide_settings": "نهفتن تنظیمات", "column_header.moveLeft_settings": "انتقال ستون به چپ", @@ -111,6 +112,7 @@ "navigation_bar.mutes": "کاربران بی‌صداشده", "navigation_bar.preferences": "ترجیحات", "navigation_bar.public_timeline": "نوشته‌های همه‌جا", + "navigation_bar.pins": "نوشته‌های ثابت", "notification.favourite": "‫{name}‬ نوشتهٔ شما را پسندید", "notification.follow": "‫{name}‬ پیگیر شما شد", "notification.mention": "‫{name}‬ از شما نام برد", -- cgit From c2bee07dbc12c799f412a39a4d5499264baac81e Mon Sep 17 00:00:00 2001 From: Anna e só Date: Sun, 10 Sep 2017 20:40:29 -0300 Subject: l10n: Full PT-BR translation (#4882) * devise.pt-BR.yml now fully translated * pt-BR.json now fully translated * pt-BR.yml partially translated; 46 lines left * pt-BR.yml now fully translated * simple_form.pt-BR.yml fully translated * doorkeeper.pt-BR.yml now fully translated * E-mail instructions on app/views/user_mailer added and fully translated * PT-BR translation for #4871 * Deleted an unwanted caracter on pt-BR.yml * Fixing typos on pt-BR.yml * Added translation for Pinned toots tab on pt-BR.json * Added missing translation for navigation_bar.pins --- app/javascript/mastodon/locales/pt-BR.json | 176 ++++--- .../confirmation_instructions.pt-BR.html.erb | 12 + .../confirmation_instructions.pt-BR.text.erb | 12 + .../user_mailer/password_change.pt-BR.html.erb | 3 + .../user_mailer/password_change.pt-BR.text.erb | 3 + .../reset_password_instructions.pt-BR.html.erb | 8 + .../reset_password_instructions.pt-BR.text.erb | 8 + config/locales/devise.pt-BR.yml | 70 +-- config/locales/doorkeeper.pt-BR.yml | 115 ++-- config/locales/pt-BR.yml | 581 +++++++++++++++------ config/locales/simple_form.pt-BR.yml | 75 +-- 11 files changed, 683 insertions(+), 380 deletions(-) create mode 100644 app/views/user_mailer/confirmation_instructions.pt-BR.html.erb create mode 100644 app/views/user_mailer/confirmation_instructions.pt-BR.text.erb create mode 100644 app/views/user_mailer/password_change.pt-BR.html.erb create mode 100644 app/views/user_mailer/password_change.pt-BR.text.erb create mode 100644 app/views/user_mailer/reset_password_instructions.pt-BR.html.erb create mode 100644 app/views/user_mailer/reset_password_instructions.pt-BR.text.erb (limited to 'app/javascript') diff --git a/app/javascript/mastodon/locales/pt-BR.json b/app/javascript/mastodon/locales/pt-BR.json index e861bf73f..87f8097aa 100644 --- a/app/javascript/mastodon/locales/pt-BR.json +++ b/app/javascript/mastodon/locales/pt-BR.json @@ -6,25 +6,25 @@ "account.follow": "Seguir", "account.followers": "Seguidores", "account.follows": "Segue", - "account.follows_you": "É seu seguidor", + "account.follows_you": "Segue você", "account.media": "Mídia", "account.mention": "Mencionar @{name}", "account.mute": "Silenciar @{name}", "account.posts": "Posts", "account.report": "Denunciar @{name}", - "account.requested": "Aguardando aprovação", + "account.requested": "Aguardando aprovação. Clique para cancelar a solicitação.", "account.share": "Compartilhar perfil de @{name}", - "account.unblock": "Não bloquear @{name}", + "account.unblock": "Desbloquear @{name}", "account.unblock_domain": "Desbloquear {domain}", "account.unfollow": "Deixar de seguir", "account.unmute": "Não silenciar @{name}", "account.view_full_profile": "Ver perfil completo", - "boost_modal.combo": "Pode clicar {combo} para não voltar a ver", - "bundle_column_error.body": "Something went wrong while loading this component.", + "boost_modal.combo": "Você pode pressionar {combo} para ignorar este diálogo na próxima vez", + "bundle_column_error.body": "Algo de errado aconteceu enquanto este componente era carregado.", "bundle_column_error.retry": "Tente novamente", - "bundle_column_error.title": "Network error", + "bundle_column_error.title": "Erro de rede", "bundle_modal_error.close": "Fechar", - "bundle_modal_error.message": "Something went wrong while loading this component.", + "bundle_modal_error.message": "Algo de errado aconteceu enquanto este componente era carregado.", "bundle_modal_error.retry": "Tente novamente", "column.blocks": "Usuários bloqueados", "column.community": "Local", @@ -34,6 +34,7 @@ "column.mutes": "Usuários silenciados", "column.notifications": "Notificações", "column.public": "Global", + "column.pins": "Postagens fixadas", "column_back_button.label": "Voltar", "column_header.hide_settings": "Esconder configurações", "column_header.moveLeft_settings": "Mover coluna para a esquerda", @@ -43,156 +44,157 @@ "column_header.unpin": "Desafixar", "column_subheading.navigation": "Navegação", "column_subheading.settings": "Configurações", - "compose_form.lock_disclaimer": "A sua conta não está {locked}. Qualquer pessoa pode te seguir e visualizar as suas postagens só para seguidores.", - "compose_form.lock_disclaimer.lock": "locked", + "compose_form.lock_disclaimer": "A sua conta não está {locked}. Qualquer pessoa pode te seguir e visualizar postagens direcionadas a apenas seguidores.", + "compose_form.lock_disclaimer.lock": "trancado", "compose_form.placeholder": "No que você está pensando?", - "compose_form.privacy_disclaimer": "O seu conteúdo privado será compartilhado com os usuários do {domains}. Você confia {domainsCount, plural, one {neste servidor} other {nestes servidores}}? As configurações de privacidade só funcionam em instâncias do Mastodon. Se {domains} {domainsCount, plural, one {não é uma instância} other {não são instâncias}}, não há como garantir a privacidade de suas postagens, e elas podem ser compartilhadas com outros.", + "compose_form.privacy_disclaimer": "O seu conteúdo privado será compartilhado com os usuários de {domains}. Você confia {domainsCount, plural, one {neste servidor} other {nestes servidores}}? As configurações de privacidade só funcionam em instâncias do Mastodon. Se {domains} {domainsCount, plural, one {não é uma instância} other {não são instâncias}}, não há como garantir a privacidade de suas postagens, e elas podem ser compartilhadas com destinatários indesejados.", "compose_form.publish": "Publicar", "compose_form.publish_loud": "{publish}!", "compose_form.sensitive": "Marcar mídia como conteúdo sensível", - "compose_form.spoiler": "Esconder texto com aviso", + "compose_form.spoiler": "Esconder texto com aviso de conteúdo", "compose_form.spoiler_placeholder": "Aviso de conteúdo", "confirmation_modal.cancel": "Cancelar", "confirmations.block.confirm": "Bloquear", "confirmations.block.message": "Você tem certeza de que quer bloquear {name}?", "confirmations.delete.confirm": "Excluir", - "confirmations.delete.message": "Você tem certeza de que quer excluir este status?", + "confirmations.delete.message": "Você tem certeza de que quer excluir esta postagem?", "confirmations.domain_block.confirm": "Esconder o domínio inteiro", "confirmations.domain_block.message": "Você quer mesmo bloquear {domain} inteiro? Na maioria dos casos, silenciar ou bloquear alguns usuários é o suficiente e o recomendado.", "confirmations.mute.confirm": "Silenciar", "confirmations.mute.message": "Você tem certeza de que quer silenciar {name}?", "confirmations.unfollow.confirm": "Deixar de seguir", "confirmations.unfollow.message": "Você tem certeza de que quer deixar de seguir {name}?", - "embed.instructions": "Embed this status on your website by copying the code below.", - "embed.preview": "Here is what it will look like:", - "emoji_button.activity": "Activity", - "emoji_button.flags": "Flags", - "emoji_button.food": "Food & Drink", + "embed.instructions": "Incorpore esta postagem em seu site copiando o código abaixo:", + "embed.preview": "Aqui está uma previsão de como ficará:", + "emoji_button.activity": "Atividades", + "emoji_button.flags": "Bandeiras", + "emoji_button.food": "Comidas & Bebidas", "emoji_button.label": "Inserir Emoji", - "emoji_button.nature": "Nature", - "emoji_button.objects": "Objects", - "emoji_button.people": "People", - "emoji_button.search": "Search...", - "emoji_button.symbols": "Symbols", - "emoji_button.travel": "Travel & Places", - "empty_column.community": "Ainda não existem conteúdo local para mostrar!", - "empty_column.hashtag": "Ainda não existe qualquer conteúdo com essa hashtag", - "empty_column.home": "Ainda não segues qualquer utilizador. Visita {public} ou utiliza a pesquisa para procurar outros utilizadores.", - "empty_column.home.inactivity": "Your home feed is empty. If you have been inactive for a while, it will be regenerated for you soon.", + "emoji_button.nature": "Natureza", + "emoji_button.objects": "Objetos", + "emoji_button.people": "Pessoas", + "emoji_button.search": "Buscar...", + "emoji_button.symbols": "Símbolos", + "emoji_button.travel": "Viagens & Lugares", + "empty_column.community": "A timeline local está vazia. Escreva algo publicamente para começar!", + "empty_column.hashtag": "Ainda não há qualquer conteúdo com essa hashtag", + "empty_column.home": "Você ainda não segue usuário algo. Visite a timeline {public} ou use o buscador para procurar e conhecer outros usuários.", + "empty_column.home.inactivity": "A sua página inicial está vazia. Se você esteve inativo por um tempo, ela irá se regenerar em alguns intantes.", "empty_column.home.public_timeline": "global", - "empty_column.notifications": "Não tens notificações. Interage com outros utilizadores para iniciar uma conversa.", - "empty_column.public": "Não há nada aqui! Escreve algo publicamente ou segue outros utilizadores para ver aqui os conteúdos públicos.", + "empty_column.notifications": "Você ainda não possui notificações. Interaja com outros usuários para começar a conversar!", + "empty_column.public": "Não há nada aqui! Escreva algo publicamente ou siga manualmente usuários de outras instâncias.", "follow_request.authorize": "Autorizar", "follow_request.reject": "Rejeitar", "getting_started.appsshort": "Apps", "getting_started.faq": "FAQ", "getting_started.heading": "Primeiros passos", - "getting_started.open_source_notice": "Mastodon é software de fonte aberta. Podes contribuir ou repostar problemas no GitHub do projecto: {github}.", - "getting_started.userguide": "User Guide", + "getting_started.open_source_notice": "Mastodon é um software de código aberto. Você pode contribuir ou reportar problemas na página do GitHub do projeto: {github}.", + "getting_started.userguide": "Guia de usuário", "home.column_settings.advanced": "Avançado", "home.column_settings.basic": "Básico", "home.column_settings.filter_regex": "Filtrar com uma expressão regular", - "home.column_settings.show_reblogs": "Mostrar as partilhas", + "home.column_settings.show_reblogs": "Mostrar compartilhamentos", "home.column_settings.show_replies": "Mostrar as respostas", - "home.settings": "Parâmetros da listagem", + "home.settings": "Configurações de colunas", "lightbox.close": "Fechar", - "lightbox.next": "Next", - "lightbox.previous": "Previous", + "lightbox.next": "Próximo", + "lightbox.previous": "Anterior", "loading_indicator.label": "Carregando...", "media_gallery.toggle_visible": "Esconder/Mostrar", "missing_indicator.label": "Não encontrado", - "navigation_bar.blocks": "Utilizadores bloqueados", + "navigation_bar.blocks": "Usuários bloqueados", "navigation_bar.community_timeline": "Local", "navigation_bar.edit_profile": "Editar perfil", "navigation_bar.favourites": "Favoritos", "navigation_bar.follow_requests": "Seguidores pendentes", "navigation_bar.info": "Mais informações", "navigation_bar.logout": "Sair", - "navigation_bar.mutes": "Utilizadores silenciados", + "navigation_bar.mutes": "Usuários silenciados", "navigation_bar.preferences": "Preferências", "navigation_bar.public_timeline": "Global", - "notification.favourite": "{name} adicionou o teu post aos favoritos", - "notification.follow": "{name} seguiu-te", - "notification.mention": "{name} mencionou-te", - "notification.reblog": "{name} partilhou o teu post", + "navigation_bar.pins": "Postagens fixadas", + "notification.favourite": "{name} adicionou a sua postagem aos favoritos", + "notification.follow": "{name} te seguiu", + "notification.mention": "{name} te mencionou", + "notification.reblog": "{name} compartilhou a sua postagem", "notifications.clear": "Limpar notificações", - "notifications.clear_confirmation": "Queres mesmo limpar todas as notificações?", + "notifications.clear_confirmation": "Você tem certeza de que quer limpar todas as suas notificações permanentemente?", "notifications.column_settings.alert": "Notificações no computador", "notifications.column_settings.favourite": "Favoritos:", "notifications.column_settings.follow": "Novos seguidores:", "notifications.column_settings.mention": "Menções:", - "notifications.column_settings.push": "Push notifications", - "notifications.column_settings.push_meta": "This device", - "notifications.column_settings.reblog": "Partilhas:", + "notifications.column_settings.push": "Enviar notificações", + "notifications.column_settings.push_meta": "Este aparelho", + "notifications.column_settings.reblog": "Compartilhamento:", "notifications.column_settings.show": "Mostrar nas colunas", "notifications.column_settings.sound": "Reproduzir som", - "onboarding.done": "Done", - "onboarding.next": "Next", - "onboarding.page_five.public_timelines": "The local timeline shows public posts from everyone on {domain}. The federated timeline shows public posts from everyone who people on {domain} follow. These are the Public Timelines, a great way to discover new people.", - "onboarding.page_four.home": "The home timeline shows posts from people you follow.", - "onboarding.page_four.notifications": "The notifications column shows when someone interacts with you.", - "onboarding.page_one.federation": "Mastodon is a network of independent servers joining up to make one larger social network. We call these servers instances.", - "onboarding.page_one.handle": "You are on {domain}, so your full handle is {handle}", - "onboarding.page_one.welcome": "Welcome to Mastodon!", - "onboarding.page_six.admin": "Your instance's admin is {admin}.", - "onboarding.page_six.almost_done": "Almost done...", + "onboarding.done": "Pronto", + "onboarding.next": "Próximo", + "onboarding.page_five.public_timelines": "A timeline local mostra postagens públicas de todos os usuários no {domain}. A timeline federada mostra todas as postagens de todas as pessoas que pessoas no {domain} seguem. Estas são as timelines públicas, uma ótima maneira de conhecer novas pessoas.", + "onboarding.page_four.home": "A página inicial mostra postagens de pessoas que você segue.", + "onboarding.page_four.notifications": "A coluna de notificações te mostra quando alguém interage com você.", + "onboarding.page_one.federation": "Mastodon é uma rede d servidores independentes se juntando para fazer uma grande rede social. Nós chamamos estes servidores de instâncias.", + "onboarding.page_one.handle": "Você está no {domain}, então o seu nome de usuário completo é {handle}", + "onboarding.page_one.welcome": "Seja bem-vindo(a) ao Mastodon!", + "onboarding.page_six.admin": "O administrador de sua instância é {admin}.", + "onboarding.page_six.almost_done": "Quase acabando...", "onboarding.page_six.appetoot": "Bon Appetoot!", - "onboarding.page_six.apps_available": "There are {apps} available for iOS, Android and other platforms.", - "onboarding.page_six.github": "Mastodon is free open-source software. You can report bugs, request features, or contribute to the code on {github}.", - "onboarding.page_six.guidelines": "community guidelines", - "onboarding.page_six.read_guidelines": "Please read {domain}'s {guidelines}!", - "onboarding.page_six.various_app": "mobile apps", - "onboarding.page_three.profile": "Edit your profile to change your avatar, bio, and display name. There, you will also find other preferences.", - "onboarding.page_three.search": "Use the search bar to find people and look at hashtags, such as {illustration} and {introductions}. To look for a person who is not on this instance, use their full handle.", - "onboarding.page_two.compose": "Write posts from the compose column. You can upload images, change privacy settings, and add content warnings with the icons below.", - "onboarding.skip": "Skip", + "onboarding.page_six.apps_available": "Há {apps} disponíveis para iOS, Android e outras plataformas.", + "onboarding.page_six.github": "Mastodon é um software gratuito e de código aberto. Você pode reportar bugs, prequisitar novas funções ou contribuir para o código no {github}.", + "onboarding.page_six.guidelines": "diretrizes da comunidade", + "onboarding.page_six.read_guidelines": "Por favor, leia as {guidelines} do {domain}!", + "onboarding.page_six.various_app": "aplicativos móveis", + "onboarding.page_three.profile": "Edite o seu perfil para mudar o seu o seu avatar, bio e nome de exibição. No menu de configurações, você também encontrará outras preferências.", + "onboarding.page_three.search": "Use a barra de buscas para encontrar pessoas e consultar hashtahs, como #illustrations e #introductions. Para procurar por uma pessoa que não estiver nesta instância, use o nome de usuário completo dela.", + "onboarding.page_two.compose": "Escreva postagens na coluna de escrita. Você pode hospedar imagens, mudar as configurações de privacidade e adicionar alertas de conteúdo através dos ícones abaixo.", + "onboarding.skip": "Pular", "privacy.change": "Ajustar a privacidade da mensagem", - "privacy.direct.long": "Apenas para utilizadores mencionados", - "privacy.direct.short": "Directo", - "privacy.private.long": "Apenas para os seguidores", - "privacy.private.short": "Privado", + "privacy.direct.long": "Apenas para usuários mencionados", + "privacy.direct.short": "Direta", + "privacy.private.long": "Apenas para seus seguidores", + "privacy.private.short": "Privada", "privacy.public.long": "Publicar em todos os feeds", - "privacy.public.short": "Público", - "privacy.unlisted.long": "Não publicar nos feeds públicos", - "privacy.unlisted.short": "Não listar", + "privacy.public.short": "Pública", + "privacy.unlisted.long": "Não publicar em feeds públicos", + "privacy.unlisted.short": "Não listada", "reply_indicator.cancel": "Cancelar", "report.placeholder": "Comentários adicionais", "report.submit": "Enviar", "report.target": "Denunciar", "search.placeholder": "Pesquisar", "search_results.total": "{count, number} {count, plural, one {resultado} other {resultados}}", - "standalone.public_title": "A look inside...", - "status.cannot_reblog": "This post cannot be boosted", + "standalone.public_title": "Dê uma espiada...", + "status.cannot_reblog": "Esta postagem não pode ser compartilhada", "status.delete": "Eliminar", - "status.embed": "Embed", + "status.embed": "Incorporar", "status.favourite": "Adicionar aos favoritos", "status.load_more": "Carregar mais", - "status.media_hidden": "Media escondida", + "status.media_hidden": "Mídia escondida", "status.mention": "Mencionar @{name}", - "status.mute_conversation": "Mute conversation", + "status.mute_conversation": "Silenciar conversa", "status.open": "Expandir", - "status.pin": "Pin on profile", - "status.reblog": "Partilhar", - "status.reblogged_by": "{name} partilhou", + "status.pin": "Fixar no perfil", + "status.reblog": "Compartilhar", + "status.reblogged_by": "{name} compartilhou", "status.reply": "Responder", - "status.replyAll": "Reply to thread", - "status.report": "Denúnciar @{name}", + "status.replyAll": "Responder à sequência", + "status.report": "Denunciar @{name}", "status.sensitive_toggle": "Clique para ver", "status.sensitive_warning": "Conteúdo sensível", - "status.share": "Share", + "status.share": "Compartilhar", "status.show_less": "Mostrar menos", "status.show_more": "Mostrar mais", - "status.unmute_conversation": "Unmute conversation", - "status.unpin": "Unpin from profile", + "status.unmute_conversation": "Desativar silêncio desta conversa", + "status.unpin": "Desafixar do perfil", "tabs_bar.compose": "Criar", "tabs_bar.federated_timeline": "Global", - "tabs_bar.home": "Home", + "tabs_bar.home": "Página inicial", "tabs_bar.local_timeline": "Local", "tabs_bar.notifications": "Notificações", "upload_area.title": "Arraste e solte para enviar", - "upload_button.label": "Adicionar media", + "upload_button.label": "Adicionar mídia", "upload_form.undo": "Anular", - "upload_progress.label": "A gravar...", + "upload_progress.label": "Salvando...", "video_player.expand": "Expandir vídeo", "video_player.toggle_sound": "Ligar/Desligar som", "video_player.toggle_visible": "Ligar/Desligar vídeo", diff --git a/app/views/user_mailer/confirmation_instructions.pt-BR.html.erb b/app/views/user_mailer/confirmation_instructions.pt-BR.html.erb new file mode 100644 index 000000000..80edcfda7 --- /dev/null +++ b/app/views/user_mailer/confirmation_instructions.pt-BR.html.erb @@ -0,0 +1,12 @@ +

Boas vindas, <%= @resource.email %>!

+ +

Você acabou de criar uma conta no <%= @instance %>.

+ +

Para confirmar o seu cadastro, por favor clique no link a seguir:
+<%= link_to 'Confirmar cadastro', confirmation_url(@resource, confirmation_token: @token) %> + +

Por favor, leia também os nossos <%= link_to 'termos de serviços', terms_url %>.

+ +

Atenciosamente,

+ +

A equipe do <%= @instance %>

diff --git a/app/views/user_mailer/confirmation_instructions.pt-BR.text.erb b/app/views/user_mailer/confirmation_instructions.pt-BR.text.erb new file mode 100644 index 000000000..95efb3436 --- /dev/null +++ b/app/views/user_mailer/confirmation_instructions.pt-BR.text.erb @@ -0,0 +1,12 @@ +Boas vindas, <%= @resource.email %>! + +Você acabou de criar uma conta no <%= @instance %>. + +Para confirmar o seu cadastro, por favor clique no link a seguir: +<%= confirmation_url(@resource, confirmation_token: @token) %> + +Por favor, leia também os nossos termos e condições de uso <%= terms_url %> + +Atenciosamente, + +A equipe do <%= @instance %> diff --git a/app/views/user_mailer/password_change.pt-BR.html.erb b/app/views/user_mailer/password_change.pt-BR.html.erb new file mode 100644 index 000000000..5f707ba09 --- /dev/null +++ b/app/views/user_mailer/password_change.pt-BR.html.erb @@ -0,0 +1,3 @@ +

Olá, <%= @resource.email %>!

+ +

Estamos te contatando para te notificar que a senha senha no <%= @instance %> foi modificada.

diff --git a/app/views/user_mailer/password_change.pt-BR.text.erb b/app/views/user_mailer/password_change.pt-BR.text.erb new file mode 100644 index 000000000..d8b76648c --- /dev/null +++ b/app/views/user_mailer/password_change.pt-BR.text.erb @@ -0,0 +1,3 @@ +Olá, <%= @resource.email %>! + +Estamos te contatando para te notificar que a senha senha no <%= @instance %> foi modificada. diff --git a/app/views/user_mailer/reset_password_instructions.pt-BR.html.erb b/app/views/user_mailer/reset_password_instructions.pt-BR.html.erb new file mode 100644 index 000000000..940438b7c --- /dev/null +++ b/app/views/user_mailer/reset_password_instructions.pt-BR.html.erb @@ -0,0 +1,8 @@ +

Olá, <%= @resource.email %>!

+ +

Alguém solicitou um link para mudar a sua senha no <%= @instance %>. Você pode fazer isso através do link abaixo:

+ +

<%= link_to 'Mudar a minha senha', edit_password_url(@resource, reset_password_token: @token) %>

+ +

Se você não solicitou isso, por favor ignore este e-mail.

+

A senha senha não será modificada até que você acesse o link acima e crie uma nova.

diff --git a/app/views/user_mailer/reset_password_instructions.pt-BR.text.erb b/app/views/user_mailer/reset_password_instructions.pt-BR.text.erb new file mode 100644 index 000000000..f574fe08f --- /dev/null +++ b/app/views/user_mailer/reset_password_instructions.pt-BR.text.erb @@ -0,0 +1,8 @@ +Olá, <%= @resource.email %>! + +Alguém solicitou um link para mudar a sua senha no <%= @instance %>. Você pode fazer isso através do link abaixo: + +<%= edit_password_url(@resource, reset_password_token: @token) %> + +Se você não solicitou isso, por favor ignore este e-mail. +A senha senha não será modificada até que você acesse o link acima e crie uma nova. diff --git a/config/locales/devise.pt-BR.yml b/config/locales/devise.pt-BR.yml index c647fabbd..13736b3a3 100644 --- a/config/locales/devise.pt-BR.yml +++ b/config/locales/devise.pt-BR.yml @@ -2,60 +2,60 @@ pt-BR: devise: confirmations: - confirmed: O seu endereço de email foi confirmado. - send_instructions: Você irá receber um email com instruções em como confirmar o seu endereço de email dentro de alguns minutos. - send_paranoid_instructions: Se o seu endereço de email já existir na nossa base de dados, irá receber um email com instruções em como confirmá-lo dentro de alguns minutos. + confirmed: O seu endereço de e-mail foi confirmado. + send_instructions: Você receberá uma mensagem em sua caixa de entrada com instruções sobre como confirmar o seu endereço de e-mail dentro de alguns minutos. Por favor, cheque a sua pasta de spam caso não tenha recebido esta mensagem. + send_paranoid_instructions: Se o seu endereço de e-mail já existir em nossa base de dados, você receberá uma mensagem em sua caixa de entrada com instruções sobre confirmá-lo dentro de alguns minutos. Por favor, cheque a sua pasta de spam caso não tenha recebido esta mensagem. failure: already_authenticated: A sua sessão já está aberta. inactive: A sua contra ainda não está ativada. - invalid: "%{authentication_keys} ou password inválidos." - last_attempt: Tem mais uma tentativa antes de a sua conta ser protegida. - locked: A sua conta está protegida - not_found_in_database: "%{authentication_keys} ou password inválidos." - timeout: A sua sessão expirou. Por favore entre de novo para continuar. - unauthenticated: Você precsa de entrar ou registar-se antes de continuar. - unconfirmed: Você tem de confirmar o seu endereço de email antes de continuar. + invalid: "%{authentication_keys} ou senha inválida." + last_attempt: Você tem apenas mais uma tentativa sobrando antes que a sua conta seja bloqueada. + locked: A sua conta está bloqueada. + not_found_in_database: "%{authentication_keys} ou senha inválida." + timeout: A sua sessão expirou. Por favor, entre novamente para continuar. + unauthenticated: Você precisa entrar ou registar-se antes de continuar. + unconfirmed: Você precisa confirmar o seu endereço de e-mail antes de continuar. mailer: confirmation_instructions: subject: 'Mastodon: Instruções de confirmação' password_change: - subject: 'Mastodon: Password nova' + subject: 'Mastodon: Senha modificada' reset_password_instructions: - subject: 'Mastodon: Instruções para editar a password' + subject: 'Mastodon: Instruções para mudança de senha' unlock_instructions: - subject: 'Mastodon: Instruções para desproteger a sua conta' + subject: 'Mastodon: Instruções de desbloqueio' omniauth_callbacks: - failure: Could not authenticate you from %{kind} because "%{reason}". - success: Successfully authenticated from %{kind} account. + failure: Não foi possível autenticá-lo como %{kind} porque "%{reason}". + success: Autenticado com sucesso como %{kind}. passwords: - no_token: Você não pode aceder a esta página sem ter vindo de um email para mudar a password. Se este for o case, por favor faça questão de verificar que usou o URL no email. - send_instructions: Irá receber um email com instruções em como mudar a sua password dentro de algns minutos. - send_paranoid_instructions: Se seu endereço de email existe na nossa base de dados, irá receber um link para recuperar a sua password dentro de alguns minutos. - updated: A sua password foi alterada. A sua sessão está aberta. - updated_not_active: A sua password foi alterada. + no_token: Você não pode acessar esta página se não tiver vindo de uma mensagem de mudança de senha. Se este for o caso, por favor verifique se a URL utilizada está completa. + send_instructions: Se o seu endereço de e-mail já estiver cadastrado em nossa base de dados, você receberá uma mensagem com um link para realizar a mudança de senha em alguns minutos. Por favor, cheque a sua pasta de spam caso não tenha recebido esta mensagem. + send_paranoid_instructions: Se o seu endereço de e-mail já estiver cadastrado em nossa base de dados, você receberá uma mensagem com um link para realizar a mudança de senha em alguns minutos. Por favor, cheque a sua pasta de spam caso não tenha recebido esta mensagem. + updated: A sua senha foi alterada. A sua sessão está aberta. + updated_not_active: A sua senha foi alterada. registrations: destroyed: Adeus! A sua conta foi cancelada. Esperamos vê-lo em breve. - signed_up: Bem vindo! A sua conta foi registada com sucesso. - signed_up_but_inactive: A sua conta foi registada. No entanto, não abrimos a sua sessão porque a sua conta ainda não foi ativada. - signed_up_but_locked: A sua conta foi registada. No entanto, não abrimos a sua sessão porque a sua conta está protegida. - signed_up_but_unconfirmed: Uma mensagem com um link de confirmação foi enviada para o seu email. Por favor siga o link para ativar a sua conta. - update_needs_confirmation: Você mudou o seu endereço de email ou password, mas é necessário confirmar a mudança. Por favor siga o link que foi enviado para o seu novo endereço de email. + signed_up: Bem vindo! A sua conta foi registrada com sucesso. + signed_up_but_inactive: A sua conta foi registrada. No entanto, não abrimos a sua sessão porque a sua conta ainda não foi ativada. + signed_up_but_locked: A sua conta foi registrada. No entanto, não abrimos a sua sessão porque a sua conta está bloqueada. + signed_up_but_unconfirmed: Uma mensagem com um link de confirmação foi enviada para o seu endereço de e-mail. Por favor, siga o link para ativar a sua conta e, caso não tenha recebido esta mensagem, cheque a sua pasta de spam. + update_needs_confirmation: Você mudou o seu endereço de e-mail ou a sua senha, mas é necessário confirmar a mudança. Por favor siga o link que foi enviado para o seu novo endereço de e-mail e, caso não tenha recebido esta mensagem, cheque a sua pasta de spam. updated: A sua conta foi alterada com sucesso. sessions: - already_signed_out: Sessão fechada. + already_signed_out: Sessão encerrada. signed_in: Sessão iniciada. - signed_out: Sessão fechada. + signed_out: Sessão encerrada. unlocks: - send_instructions: Irá receber um email com instruções para desproteger a sua conta dentro de alguns minutos. - send_paranoid_instructions: Se a sua conta existe, irá receber um email com instruções a detalhar como a desproteger dentro de alguns minutos. - unlocked: A sua conta foi desprotegida. Por favor inicie sessão para continuar. + send_instructions: Você receberá uma mensagem com instruções para desbloquear a sua conta em alguns instantes. Por favor, cheque a sua pasta de spam caso não tenha recebido esta mensagem. + send_paranoid_instructions: Se a sua conta já existe, você receberá uma mensagem com instruções para desbloquear a sua conta em alguns instantes. Por favor, cheque a sua pasta de spam caso não tenha recebido esta mensagem. + unlocked: A sua conta foi desbloqueada com sucesso. Por favor inicie sessão para continuar. errors: messages: already_confirmed: já foi confirmado, por favor tente iniciar sessão - confirmation_period_expired: tem de ser confirmado dentro de %{period}, por favor tente outra vez - expired: expirou, por favor tente outra vez + confirmation_period_expired: precisa ser confirmada em até %{period}, por favor, solicite novo link de confirmação + expired: expirou, por favor solicite uma nova not_found: não encontrado - not_locked: não está protegido + not_locked: não está bloqueada not_saved: - one: '1 erro impediu este %{resource} de ser guardado:' - other: "%{count} erros impediram este %{resource} de ser guardado:" + one: '1 erro impediu este %{resource} de ser salvo(a):' + other: "%{count} erros impediram este %{resource} de ser salvo(a):" diff --git a/config/locales/doorkeeper.pt-BR.yml b/config/locales/doorkeeper.pt-BR.yml index 85ea3bfcc..f0f3c6893 100644 --- a/config/locales/doorkeeper.pt-BR.yml +++ b/config/locales/doorkeeper.pt-BR.yml @@ -3,17 +3,19 @@ pt-BR: activerecord: attributes: doorkeeper/application: - name: Nome - redirect_uri: Redirect URI + name: Nome do aplicativo + redirect_uri: URI de redirecionamento + scopes: Autorizações + website: Website do aplicativo errors: models: doorkeeper/application: attributes: redirect_uri: fragment_present: não pode conter um fragmento. - invalid_uri: tem de ser um URI válido. - relative_uri: tem de ser um URI absoluto. - secured_uri: tem de ser um HTTPS/SSL URI. + invalid_uri: precisa ser uma URI válida. + relative_uri: precisa ser uma URI absoluta. + secured_uri: precisa ser uma URI HTTPS/SSL. doorkeeper: applications: buttons: @@ -21,92 +23,97 @@ pt-BR: cancel: Cancelar destroy: Destruir edit: Editar - submit: Submeter + submit: Enviar confirmations: - destroy: Tem a certeza? + destroy: Você tem certeza? edit: - title: Editar aplicação + title: Editar aplicativo form: - error: Oops! Verifique que o formulário não tem erros + error: Oops! Verifique o seu formulário para saber de possíveis erros help: native_redirect_uri: Use %{native_redirect_uri} para testes locais - redirect_uri: Utilize uma linha por URI - scopes: Separate scopes with spaces. Leave blank to use the default scopes. + redirect_uri: Use uma linha para cada URI + scopes: Separe autorizações com espaços. Deixe em branco para usar autorizações padrões. index: - callback_url: Callback URL + application: Aplicativos + callback_url: URL de retorno + delete: Excluir name: Nome - new: Nova Aplicação - title: As suas aplicações + new: Novo aplicativo + scopes: Autorizações + show: Mostrar + title: Seus aplicativos new: - title: Nova aplicação + title: Novos aplicativos show: actions: Ações - application_id: Id de Aplicação - callback_urls: Callback urls - scopes: Scopes - secret: Segredo - title: 'Aplicação: %{name}' + application_id: Chave do cliente + callback_urls: URLs de retorno + scopes: Autorizações + secret: Segredo do cliente + title: 'Application: %{name}' authorizations: buttons: - authorize: Autorize - deny: Não autorize + authorize: Autorizar + deny: Negar error: title: Ocorreu um erro new: - able_to: Vai poder - prompt: Aplicação %{client_name} requisita acesso à sua conta - title: Autorização é necessária + able_to: Será capaz de + prompt: O aplicativo %{client_name} solicita acesso à sua conta + title: Autorização necessária show: title: Código de autorização authorized_applications: buttons: revoke: Revogar confirmations: - revoke: Tem a certeza? + revoke: Você tem certeza? index: - application: Aplicação - created_at: Criada em - date_format: "%Y-%m-%d %H:%M:%S" - title: As suas aplicações autorizadas + application: Aplicativos + created_at: Autorizados + date_format: "%d-%m-%Y %H:%M:%S" + scopes: Autorizações + title: Aplicativos autorizados errors: messages: - access_denied: The resource owner or authorization server denied the request. - credential_flow_not_configured: Resource Owner Password Credentials flow failed due to Doorkeeper.configure.resource_owner_from_credentials being unconfigured. - invalid_client: Client authentication failed due to unknown client, no client authentication included, or unsupported authentication method. - invalid_grant: The provided authorization grant is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client. - invalid_redirect_uri: The redirect uri included is not valid. - invalid_request: The request is missing a required parameter, includes an unsupported parameter value, or is otherwise malformed. - invalid_resource_owner: The provided resource owner credentials are not valid, or resource owner cannot be found - invalid_scope: The requested scope is invalid, unknown, or malformed. + access_denied: O proprietário ou servidor de autorização negou a solicitação. + credential_flow_not_configured: Cadeira de Credenciais de Senha do Proprietário falhou porque Doorkeeper.configure.resource_owner_from_credentials não foram configuradas. + invalid_client: Autenticação do cliente falhou por causa de um cliente desconhecido, nenhum cliente de autenticação incluído ou método de autenticação não suportado. + invalid_grant: A garantia de autorização é inválida, expirou, foi revogada, não é equivalente à URI de redirecionamento usada da solicitação de autorização ou foi emitida por outro cliente. + invalid_redirect_uri: A URI de redirecionamento incluída não é válida. + invalid_request: A solicitação não possui um parâmetro obrigatório, inclui um valor não suportado ou está mal formatada. + invalid_resource_owner: As credenciais do proprietário não são válidas ou o proprietário não pôde ser encontrado. + invalid_scope: A autorização requirida é inválida, desconhecida ou está mal formatada. invalid_token: expired: O token de acesso expirou revoked: O token de acesso foi revogado unknown: O token de acesso é inválido - resource_owner_authenticator_not_configured: Resource Owner find failed due to Doorkeeper.configure.resource_owner_authenticator being unconfiged. - server_error: The authorization server encountered an unexpected condition which prevented it from fulfilling the request. - temporarily_unavailable: The authorization server is currently unable to handle the request due to a temporary overloading or maintenance of the server. - unauthorized_client: The client is not authorized to perform this request using this method. - unsupported_grant_type: The authorization grant type is not supported by the authorization server. - unsupported_response_type: The authorization server does not support this response type. + resource_owner_authenticator_not_configured: Procura pelo proprietário falhou porque Doorkeeper.configure.resource_owner_authenticator não foi configurado. + server_error: O servidor de autorização encontrou uma condição inesperada que preveniu a solicitação de ser respondida. + temporarily_unavailable: O servidor de autorização é incapaz de lidar com a solicitação no momento por causa d múltiplas requisições ou manutenção programada. + unauthorized_client: O cliente não possui autorização para performar esta solicitação usando este método. + unsupported_grant_type: O tipo de garantia de autorização não é suportada pelo servidor de autorização. + unsupported_response_type: O servidor de autorização não suporta este tipo de resposta. flash: applications: create: - notice: Aplicação criada. + notice: Aplicativo criado. destroy: - notice: Aplicação eliminada. + notice: Aplicativo deletado. update: - notice: Aplicação alterada. + notice: Aplicativo atualizado. authorized_applications: destroy: - notice: Aplicação revogada. + notice: Aplicativo revogado. layouts: admin: nav: - applications: Aplicações - oauth2_provider: OAuth2 Provider + applications: Aplicativo + oauth2_provider: Provedor de OAuth2 application: - title: Autorização OAuth necessária + title: Autorização OAuth obrigatória scopes: - follow: siga, bloqueie, desbloqueie, e deixe de seguir contas - read: tenha acesso aos dados da sua conta - write: públique por si + follow: seguir, bloquear, desbloquear e deixar de seguir outras contas + read: ler os dados da sua conta + write: postar em seu nome diff --git a/config/locales/pt-BR.yml b/config/locales/pt-BR.yml index 750120299..00941d215 100644 --- a/config/locales/pt-BR.yml +++ b/config/locales/pt-BR.yml @@ -1,52 +1,78 @@ --- pt-BR: about: - about_mastodon_html: Mastodon é um servidor de rede social grátis, e open-source. Uma alternativa descentralizada ás plataformas comerciais, que evita o risco de uma única empresa monopolizar a sua comunicação. Escolha um servidor que você confie — qualquer um que escolher, você poderá interagir com todo o resto. Qualquer um pode ter uma instância Mastodon e assim participar na rede social federada sem problemas. - about_this: Sobre essa instância - closed_registrations: Registros estão fechadas para essa instância. + about_mastodon_html: Mastodon é uma rede social baseada em protocolos abertos e software gratuito e de código aberto. É descentralizada como e-mail. + about_this: Sobre + closed_registrations: Cadastros estão atualmente fechados nesta instância. No entanto! Você pode procurar uma instância diferente na qual possa criar uma conta e acessar a mesma rede por lá. contact: Contato + contact_missing: Não definido + contact_unavailable: N/A description_headline: O que é %{domain}? domain_count_after: outras instâncias domain_count_before: Conectado a - other_instances: Outras instâncias - source_code: Source code - status_count_after: status - status_count_before: Quem autorizou + extended_description_html: +

Um bom lugar para as regras

+

A descrição extendida ainda não foi definida.

+ features: + humane_approach_body: Aprendendo com erros de outras redes, Mastodon tem como objetivo fazer decisões éticas de design para combater o desuso de redes sociais. + humane_approach_title: Uma abordagem mais humana + not_a_product_body: Mastodon não é uma rede comercial. Sem propagandas, coleta de dados, jardins fechados. Não há uma autoridade central. + not_a_product_title: Você é uma pessoa e não um produto + real_conversation_body: Com 500 caracteres à sua disposição e suporte para conteúdo granular e avisos de conteúdo, você pode se expressar da maneira que desejar. + real_conversation_title: Feito para conversas reais + within_reach_body: Vários apps para iOS, Android e outras plataformas graças a um ecossistema de API amigável para desenvolvedores proporcionam que você possa se manter atualizado sobre seus amigos de qualquer lugar. + within_reach_title: Sempre a seu alcance + find_another_instance: Encontre outra instância + generic_description: "%{domain} é um servidor na rede" + hosted_on: Mastodon hospedado em %{domain} + learn_more: Saiba mais + other_instances: Lista de instâncias + source_code: Código fonte + status_count_after: postagens + status_count_before: Autores de user_count_after: usuários - user_count_before: Lugar de + user_count_before: Casa de + what_is_mastodon: O que é Mastodon? accounts: follow: Seguir followers: Seguidores following: Seguindo + media: Mídia nothing_here: Não há nada aqui! - people_followed_by: Pessoas seguidas por %{name} + people_followed_by: Pessoas que %{name} segue people_who_follow: Pessoas que seguem %{name} - posts: Posts - remote_follow: Acesso remoto - unfollow: Unfollow + posts: Toots + posts_with_replies: Toots com respostas + remote_follow: Siga remotamente + reserved_username: Este usuário está reservado + roles: + admin: Administrador + unfollow: Deixar de seguir admin: accounts: are_you_sure: Você tem certeza? - confirm: Confirme + confirm: Confirmar confirmed: Confirmado - disable_two_factor_authentication: Desabilitar senha de 2 passos - display_name: Nome mostrado - domain: Domain + disable_two_factor_authentication: Desativar 2FA + display_name: Nome de exibição + domain: Domínio edit: Editar email: E-mail - feed_url: URL do Feed + feed_url: Feed URL followers: Seguidores - follows: Seguindo + follows: Segue + inbox_url: Inbox URL + ip: IP location: all: Todos local: Local remote: Remoto - title: Local - media_attachments: Mídia anexadas + title: Localização + media_attachments: Mídia(s) anexada(s) moderation: all: Todos - silenced: Silenciado - suspended: Supenso + silenced: Silenciados + suspended: Suspensos title: Moderação most_recent_activity: Atividade mais recente most_recent_ip: IP mais recente @@ -55,206 +81,281 @@ pt-BR: alphabetic: Alfabética most_recent: Mais recente title: Ordem - perform_full_suspension: Fazer suspensão completa + outbox_url: Outbox URL + perform_full_suspension: Efetue suspensão total profile_url: URL do perfil + protocol: Protocolo public: Público - push_subscription_expires: PuSH subscription expires - reset_password: Resetar senha + push_subscription_expires: Inscrição PuSH expira + redownload: Atualizar avatar + reset: Anular + reset_password: Modificar senha + resubscribe: Reinscrever-se salmon_url: Salmon URL + search: Pesquisar show: - created_reports: Reports criados por esta conta - report: report - targeted_reports: Reports feitos sobre esta conta + created_reports: Relatórios criados por esta conta + report: relatórios + targeted_reports: Relatórios feitos sobre esta conta silence: Silêncio - statuses: Status + statuses: Postagens + subscribe: Inscrever-se title: Contas - undo_silenced: Desfazer silenciar - undo_suspension: Desfazer supensão - username: Usuário + undo_silenced: Retirar silêncio + undo_suspension: Retirar suspensão + unsubscribe: Desinscrever-se + username: Nome de usuário web: Web domain_blocks: - add_new: Adicionar nova - created_msg: Bloqueio do domínio está sendo processado - destroyed_msg: Bloqueio de domínio está sendo desfeito + add_new: Adicionar novo + created_msg: Bloqueio de domínio está sendo processado + destroyed_msg: Bloqueio de domínio desfeito domain: Domínio new: create: Criar bloqueio - hint: O bloqueio de dominio não vai previnir a criação de entradas no banco de dados, mas irá, retroativamente e automaticamente aplicar métodos de moderação específica nessas contas. + hint: O bloqueio de domínio não prevenirá a criação de entradas de contas na base de dados, mas vai reatroativa e automaticamente aplicar métodos específicos de moderação nestas contas. severity: - desc_html: "Silenciar irá fazer com que os posts dessas contas sejam invisíveis para todos que não a seguem. Supender irá remover todos o conteúdo das contas, mídia e dados do perfil." - silence: Silenciar - suspend: Suspender + desc_html: "O Silêncio fará com que as postagens da conta fiquem invisíveis para qualquer um que não a esteja seguindo. A Suspensão removerá todo o conteúdo da conta, mídia e dados de perfil. Use Nenhum se você apenas deseja rejeitar arquivos de mídia." + noop: Nenhum + silence: Silêncio + suspend: Suspensão title: Novo bloqueio de domínio reject_media: Rejeitar arquivos de mídia - reject_media_hint: Remove localmente arquivos armazenados e rejeita fazer o download de novos no futuro. Irrelevante em suspensões. + reject_media_hint: Remove arquivos de mídia armazenados localmente e recusa quaisquer outros no futuro. Irrelevante para suspensões. severities: - silence: Silenciar - suspend: Suspender - severity: Severidade + noop: Nenhum + silence: Silêncio + suspend: Suspensão + severity: Rigidez show: affected_accounts: - one: Uma conta no banco de dados afetada - other: "%{count} contas no banco de dados afetada" + one: Uma conta no banco de dados foi afetada + other: "%{count} contas no banco de dados foram afetadas" retroactive: - silence: Desilenciar todas as contas existentes nesse domínio - suspend: Desuspender todas as contas existentes nesse domínio - title: Desfazer bloqueio de domínio para %{domain} - title: Bloqueio de domínio - undo: Desfazer + silence: Retirar silêncio de todas as contas existentes neste domínio + suspend: Retirar suspensão de todas as contas neste domínio + title: Retirar bloqueio de domínio de %{domain} + undo: Retirar + title: Bloqueios de domínio + undo: Retirar instances: account_count: Contas conhecidas domain_name: Domínio title: Instâncias conhecidas reports: + action_taken_by: Ação realizada por + are_you_sure: Você tem certeza? comment: - label: Commentário - none: None - delete: Deletar + label: Comentário + none: Nenhum + delete: Excluir id: ID - mark_as_resolved: Marque como resolvido - report: 'Report #%{id}' - report_contents: Conteúdo + mark_as_resolved: Marcar como resolvido + nsfw: + 'false': Mostrar mídias anexadas + 'true': Esconder mídias anexadas + report: 'Reportar #%{id}' + report_contents: Conteúdos reported_account: Conta reportada - reported_by: Reportado por + reported_by: Reportada por resolved: Resolvido - silence_account: Conta silenciada + silence_account: Silenciar conta status: Status - suspend_account: Conta suspensa - target: Target - title: Reports - unresolved: Unresolved - view: View + suspend_account: Suspender conta + target: Alvo + title: Denúncias + unresolved: Não resolvido + view: Visualizar settings: + bootstrap_timeline_accounts: + desc_html: Separe nomes de usuário através de vírgulas. Funciona apenas com contas locais e destrancadas. O padrão quando vazio são todos os administradores locais. + title: Usuários a serem seguidos por padrão por novas contas contact_information: - email: Entre um endereço de email público - username: Entre com usuário + email: E-mail + username: Contate usuário registrations: closed_message: - desc_html: Mostrar na página inicial quando registros estão fecados
Você pode usar tags HTML - title: Mensagem de registro fechados + desc_html: Exibido na página inicial quando cadastros estão fechados. Você pode usar tags HTML. + title: Mensagem de cadastros fechados + deletion: + desc_html: Permitir que qualquer um delete a sua conta + title: Exclusão aberta de contas open: - title: Aberto para registro + desc_html: Permitir que qualquer um crie uma conta + title: Cadastro aberto site_description: - desc_html: Mostrar como parágrafo e usado como meta tag.
Vôce pode usar tags HTML, em particular <a> e <em>. - title: Descrição do site + desc_html: Parágrafo introdutório na página inicial e em meta tags. Você pode usar tags HTML, em especial <a> e <em>. + title: Descrição da instância site_description_extended: - desc_html: Mostrar na página de informação extendiada
Você pode usar tags HTML - title: Descrição extendida do site - site_title: Título do site - title: Preferências do site + desc_html: Um ótimo lugar para seu código de conduta, regras, diretrizes e outras coisas para diferenciar a sua instância. Você pode usar tags HTML. + title: Informação estendida customizada + site_terms: + desc_html: Você pode escrever a sua própria política de privacidade, termos de serviço, entre outras coisas.Você pode usar tags HTML. + title: Termos de serviço customizados + site_title: Nome da instância + timeline_preview: + desc_html: Exibir a timeline pública na página inicial + title: Prévia da timeline + title: Configurações do site + statuses: + back_to_account: Voltar para página da conta + batch: + delete: Deletar + nsfw_off: NSFW OFF + nsfw_on: NSFW ON + execute: Executar + failed_to_execute: Falha em executar + media: + hide: Esconder mídia + show: Mostrar mídia + title: Mídia + no_media: Não há mídia + title: Postagens da conta + with_media: Com mídia subscriptions: - callback_url: URL de Callback + callback_url: Callback URL confirmed: Confirmado expires_in: Expira em last_delivery: Última entrega title: WebSub topic: Tópico title: Administração + admin_mailer: + new_report: + body: "%{reporter} reportou %{target}" + subject: Nova denúncia sobre %{instance} (#%{id}) application_mailer: - settings: 'Mudar preferências de email: %{link}' - signature: notificações Mastodon de %{instance} - view: 'View:' + salutation: "%{name}," + settings: 'Change e-mail preferences: %{link}' + signature: Notificações do Mastodon de %{instance} + view: 'Visualizar:' applications: - invalid_url: URL dada é inválida + created: Aplicação criada com sucesso + destroyed: Aplicação excluída com sucesso + invalid_url: A URL provida é inválida + regenerate_token: Regenerar token de acesso + token_regenerated: Token de acesso renegerado com sucesso + warning: Tenha cuidado com estes dados. Nunca compartilhe com alguém! + your_token: Seu token de acesso auth: - change_password: Mudar senha + agreement_html: Cadastrando-se você concorda com nossos termos de serviço e política de privacidade. + change_password: Segurança + delete_account: Excluir conta + delete_account_html: Se você deseja excluir a sua conta, você pode prosseguir para cá. Uma confirmação será requisitada. didnt_get_confirmation: Não recebeu instruções de confirmação? - forgot_password: Esqueceu a senha? + forgot_password: Esqueceu a sua senha? + invalid_reset_password_token: Token de modificação de senha é inválido ou expirou. Por favor, requisite um novo. login: Entrar logout: Sair - register: Registar + register: Cadastrar-se resend_confirmation: Reenviar instruções de confirmação - reset_password: Resetar senha - set_new_password: Editar password + reset_password: Modificar senha + set_new_password: Definir uma nova senha authorize_follow: - error: Infelizmente houve um erro olhando uma conta remota + error: Infelizmente, ocorreu um erro quando visualizando a conta remota. follow: Seguir + follow_request: 'Você mandou uma solicitação de seguidor para:' + following: 'Sucesso! Você agora está seguindo:' + post_follow: + close: Ou você pode simplesmente fechar esta janela. + return: Retornar ao perfil do usuário + web: Voltar para a página inicial title: Seguir %{acct} datetime: distance_in_words: about_x_hours: "%{count}h" - about_x_months: "%{count}mo" - about_x_years: "%{count}y" - almost_x_years: "%{count}y" + about_x_months: "%{count} meses" + about_x_years: "%{count} anos" + almost_x_years: "%{count} anos" half_a_minute: Agora - less_than_x_minutes: "%{count}m" + less_than_x_minutes: "%{count} meses" less_than_x_seconds: Agora - over_x_years: "%{count}y" - x_days: "%{count}d" - x_minutes: "%{count}m" - x_months: "%{count}mo" - x_seconds: "%{count}s" + over_x_years: "%{count} anos" + x_days: "%{count} dias" + x_minutes: "%{count} minutos" + x_months: "%{count} meses" + x_seconds: "%{count} segundos" + deletes: + bad_password_msg: Boa tentativa, hackers! Senha incorreta. + confirm_password: Insira a sua senha atual para verificar a sua identidade + description_html: Isto vai permanente e irreversivelmente remover conteúdo de sua conta e desativá-la. O seu nome de usuário permanecerá reservado para previnir futuros roubos de identidade. + proceed: Excluir conta + success_msg: A sua conta foi excluída com sucesso + warning_html: Apenas a exclusão de conteúdo desta instância em particular é garantida. Conteúdo que tenha sido largamente compartilhado muito provavelmente deixará traços. Servidores offline e servidores que se desinscreveram de suas atualizações não irão atualizar as suas bases de dados. + warning_title: Disponibilidade de conteúdo disseminado errors: - '403': Você não tem permissão para ver essa página. - '404': A página que você procura não existe. - '410': A página que você procura não existe mais. + '403': Você não tem permissão para ver esta página. + '404': A página pela qual você está procurando não existe. + '410': A página pela qual você está procurando não existe mais. '422': - content: Verificação de segurança falhou. Você está bloqueando cookies? - title: Verificação de segurança falhou + content: A verificação de segurança falhou. Você desativou o uso de cookies? + title: Falha na verificação de segurança + '429': Muitas requisições + noscript_html: Para usar o aplicativo web do Mastodon, por favor ative o JavaScript. Alternativamente, experimente um dos apps nativos para o Mastodon para a sua plataforma. exports: - blocks: Você bloqueia + blocks: Você bloqueou csv: CSV follows: Você segue - mutes: Você selencia - storage: Mídia de dados + mutes: Você silenciou + storage: Armazenamento de mídia followers: domain: Domínio - explanation_html: Se você quer garantir a privacidade doe seu status, você precisa saber quem te segue. Seu status privado é enviado a todas as instancias que você tem seguidores. Você pode querer reavaliar e remover os seguidores que você não confia que sua privacidade vai ser mantida pelos administradores ou softwares de outras instancias. - followers_count: Númbero de seguidores - lock_link: Bloquear sua conta - purge: Remove dos seguidores + explanation_html: Se você quer garantir a privacidade de suas postagens, você deve ficar atento a quem está te seguindo.Suas postagens privadas são enviadas para todas as instâncias em que você tem seguidores. Convém revisá-las e remover seguidores se você acredita que a sua privacidade não será respeitada pela equipe ou software destas instâncias. + followers_count: Número de seguidores + lock_link: Tranque a sua conta + purge: Remover de seus seguidores success: - one: Em processo de bloquear seguidores de um domínio... - other: Em processo de bloqueio-leve dos seguidores de %{count} domínios... - true_privacy_html: Saiba que privaicade de verdade só pode ser atingida com criptografia ponto-a-ponto. - unlocked_warning_html: Qualquer um que te seguir para ver seus status privado imediatamente. %{lock_link} para poder rever e rejeitar seguidores. - unlocked_warning_title: Sua conta não está bloqueada + one: No processo de bloqueio suave de seguidores de outro domínio... + other: No processo de bloqueio suave de seguidores de outros %{count} domínios... + true_privacy_html: Lembre-se de que a verdadeira privacidade só pode ser alcançada através de encriptação ponto-a-ponto. + unlocked_warning_html: Qualquer pessoa pode te seguir e ver as suas postagens privadas. %{lock_link} para ser capaz de revisar e rejeitar seguidores. + unlocked_warning_title: A sua conta não está trancada generic: - changes_saved_msg: Mudanças guardadas! + changes_saved_msg: Mudanças salvas com sucesso! powered_by: powered by %{link} - save_changes: Guardar alterações + save_changes: Salvar mudanças validation_errors: - one: Algo não está correto. Por favor reveja o erro abaixo - other: Algo não está correto. Por favor reveja os %{count} erros abaixo + one: Algo não está certo! Por favor, reveja o erro abaixo + other: Algo não está certo! Por favor, reveja os %{count} erros abaixo imports: - preface: Você pode importar certos dados, como as pessoas que você segue ou estão bloqueadas para sua conta nessa instancia, de arquivos com dados criados por outra instancia. - success: Seus dados foram carregados com sucesso and serão processados em algum tempo + preface: Você pode importar dados que você exportou de outra instância, como a lista de pessoas que você segue ou bloqueou. + success: Os seus dados foram enviados com sucesso e serão processados em instantes types: blocking: Lista de bloqueio - following: Lista de seguidos - muting: Lista de silenciados - upload: Carregar - landing_strip_html: "%{name} is a user on %{link_to_root_path}. You can follow them or interact with them if you have an account anywhere in the fediverse." - landing_strip_signup_html: If you don't, you can sign up here. + following: Pessoas que você segue + muting: Lista de silêncio + upload: Enviar + landing_strip_html: "%{name} é um usuário no %{link_to_root_path}. Você pode seguí-lo ou interagir com ele se você tiver uma conta em qualquer lugar no fediverso." + landing_strip_signup_html: Se não, você pode se cadastrar aqui. media_attachments: validations: - images_and_video: Cannot attach a video to a status that already contains images - too_many: Cannot attach more than 4 files + images_and_video: Não é possível anexar um vídeo a uma postagem que já contém imagens. + too_many: Não é possível anexar mais de quatro imagens. notification_mailer: digest: - body: 'Isto é um resumo do que você perdeu em %{instance} desde sua última visita %{since}:' - mention: "%{name} mencionou você em:" + body: 'Aqui está um resumo do que você perdeu no %{instance} desde o seu último acesso em %{since}:' + mention: "%{name} te mencionou em:" new_followers_summary: - one: Você tem um novo seguidor! - other: Você conseguiu %{count} novos seguidores! Incrível + one: Você tem um novo seguidor! Yay! + other: Você tem %{count} novos seguidores! Maravilha! subject: - one: "1 nova notificação desde sua última visita \U0001F418" - other: "%{count} novas notificações desde a última visita \U0001F418" + one: "Uma nova notificação desde o seu último acesso \U0001F418" + other: "%{count} novas notificações desde o seu último acesso \U0001F418" favourite: - body: 'O seu post foi favoritado por %{name}:' - subject: "%{name} favouritou o seu post" + body: 'Sua postagem foi favoritada por %{name}:' + subject: "%{name} favoritou a sua postagem" follow: - body: "%{name} seguiu você!" - subject: "%{name} segue você" + body: "%{name} está te seguindo!" + subject: "%{name} está te seguindo" follow_request: - body: "%{name} pediu para te seguir" - subject: 'Seguidor pendente: %{name}' + body: "%{name} requisitou autorização para te seguir" + subject: 'Pending follower: %{name}' mention: body: 'Você foi mencionado por %{name} em:' - subject: Foi mencionado por %{name} + subject: Você foi mencionado por %{name} reblog: - body: 'O seu post foi reblogado por %{name}:' - subject: "%{name} reblogou o seu post" + body: 'Sua postagem foi compartilhada por %{name}:' + subject: "%{name} compartilhou a sua postagem" number: human: decimal_units: @@ -267,56 +368,190 @@ pt-BR: trillion: T unit: '' pagination: - next: Next - prev: Prev + next: Próximo + prev: Anterior truncate: "…" + push_notifications: + favourite: + title: "%{name} favoritou a sua postagem" + follow: + title: "%{name} está te seguindo" + group: + title: "%{count} notificações" + mention: + action_boost: Compartilhar + action_expand: Mostrar mais + action_favourite: Favoritar + title: "%{name} mencionou você" + reblog: + title: "%{name} compartilhou a sua postagem" remote_follow: - acct: Entre seu usuário@domínio do qual quer seguir - missing_resource: Não foi possível achar a URL de redirecionamento para sua conta - proceed: Prossiga para seguir - prompt: 'Você vai seguir:' + acct: Insira o seu usuário@domínio do qual você quer seguir + missing_resource: Não foi possível encontrar a URL de direcionamento para a sua conta + proceed: Prosseguir para seguir + prompt: 'Você irá seguir:' + sessions: + activity: Última atividade + browser: Navegador + browsers: + alipay: Alipay + blackberry: Blackberry + chrome: Chrome + edge: Microsoft Edge + firefox: Firefox + generic: Unknown browser + ie: Internet Explorer + micro_messenger: MicroMessenger + nokia: Nokia S40 Ovi Browser + opera: Opera + phantom_js: PhantomJS + qq: QQ Browser + safari: Safari + uc_browser: UCBrowser + weibo: Weibo + current_session: Sessão atual + description: "%{browser} em %{platform}" + explanation: Estes são os navegadores que estão conectados com a sua conta do Mastodon. + ip: IP + platforms: + adobe_air: Adobe Air + android: Android + blackberry: Blackberry + chrome_os: ChromeOS + firefox_os: Firefox OS + ios: iOS + linux: Linux + mac: Mac + other: unknown platform + windows: Windows + windows_mobile: Windows Mobile + windows_phone: Windows Phone + revoke: Revogar + revoke_success: Sessão revogada com sucesso + title: Sessões settings: - authorized_apps: Aplicativos autorizados - back: Voltar ao Mastodon + authorized_apps: Apps autorizados + back: Voltar para o Mastodon + delete: Exclusão de conta + development: Desenvolvimento edit_profile: Editar perfil - export: Importar dados + export: Exportar dados followers: Seguidores autorizados import: Importar preferences: Preferências - settings: Settings - two_factor_authentication: Autenticação Two-factor + settings: Configurações + two_factor_authentication: Autenticação em dois passos + your_apps: Seus aplicativos statuses: - open_in_web: Abrir no browser - over_character_limit: limite de caracter excedeu %{max} + open_in_web: Abrir na web + over_character_limit: limite de caracteres de %{max} excedido + pin_errors: + ownership: Toots de outras pessoas não podem ser fixados + private: Toot não-público não pode ser fixado + reblog: Um compartilhamento não pode ser fixado show_more: Mostrar mais visibilities: - private: Seguidores-apenas + private: Apenas seguidores private_long: Mostrar apenas para seguidores public: Público - public_long: Qualquer um pode ver - unlisted: Público, mas não mostre no timeline público - unlisted_long: Todo mundo pode ver mas não será listado nas timeline públicas + public_long: Todos podem ver + unlisted: Não listado + unlisted_long: Todos podem ver, porém não será postado nas timelines públicas stream_entries: - click_to_show: Clique pra mostrar - reblogged: boosted + click_to_show: Clique para mostrar + pinned: Toot fixado + reblogged: compartilhado sensitive_content: Conteúdo sensível + terms: + body_html: | +

Política de privacidade

+ +

Que informações nós coletamos?

+ +

Coletamos informações quando você se cadastra em nosso site e capturamos dados quando você participa do fórum lendo, escrevendo e analisando o conteúdo aqui compartilhado.

+ +

Quando você se registrar em nosso site, será requisitado que você ceda seu nome e endereço de e-mail. Você pode, porém, visitar nosso site sem se cadastrar. Seu endereço de e-mail será verificado por uma mensagem contendo um link único. Se este link for visitado, saberemos que você controla este endereço de e-mail.

+ +

Quando registrado e postando, nós gravamos o endereço de IP de onde a postagem se originou. Nós também podemos reter logs de serviores que incluem o endereço de IP em cada requisição para o nosso servidor.

+ +

Para que usamos essas informações?

+ +

Quaisquer das informações que coletamos podem ser usadas das seguintes formas:

+ + + +

Como protegemos as suas informações?

+ +

Nós implementamos uma variedade de medidas de segurança para manter a segurança de suas informações pessoais quando você insere, submete ou acessa as suas informações pessoais.

+ +

Qual a sua política de retenção de dados?

+ +

Faremos esforços de boa fé para:

+ + + +

Nós usamos cookies?

+ +

Sim. Cookies são pequenos arquivos que um site ou o provedor de serviço transfere para o armazenamento interno de seu computador através de seu navegador (se você permitir). Estes cookies habilitam o site para reconhecer o seu navegador e, se você ter um cadastro, associá-lo a esta conta.

+ +

Nós usamos cookies para entender e salvar as suas preferências para futuras visitas e compilar dados agregados sobre o tráfego do site para que possamos oferecer melhores experiências e ferramentas no futuro. Nós podemos contratar serviços de terceiros para nos auxiliar a entender melhor nossos visitantes. Estes provedores de serviço não são autoriza usar as informações coletadas em nosso nome exceto para nos ajudar a conduzir e aprimorar nosso funcionamento.

+ +

Nós revelamos informações para terceiros?

+ +

Nós não vendemos, tocamos ou transferimos para terceiros informações pessoais que te identificam. Isso não inclui partes em que confiamos para nos ajudar a operar nosso site, conduzir nosso funcionamento ou servir você desde que estes terceiros concordem em manter essas informações em segredo. Nós também podemos prover as suas informações para obedecer ordens judiciais, reforçar nossas políticas ou proteger nossos direitos ou de outrem, propriedades ou segurança. Entretanto, informações pessoais não identificáveis podem ser enviadas para outras partes para marketing, propaganda e outros usos.

+ +

Links de terceiros

+ +

Ocasionalmente, à nossa discrição, podemos icluir ou oferecer produtos ou serviços de terceiros em nosso site. Estes terceiros têm políticas de privacidade separadas e independentes. Nós, portanto, não nos responsabilizamos pelo conteúdo e atividades destes sites de terceiros. Occasionally, at our discretion, we may include or offer third party products or services on our site. Não obstante, nós procuramos proteger a integridade de nosso site e todo feedback sobre estes sites de terceiros é bem-vindo.

+ +

Obediência ao Ato de Proteção da Privacidade Online de Crianças

+ +

Nosso site, produtos e serviços são todos direcionados a pessoas que têm pelo menos 13 anos de idade. Se este servidor estiver nos EUA, e você tiver menos de 13 anos, pelos requerimentos da COPPA (Children's Online Privacy Protection Act) não use este site.

+ +

Política de Apenas Privacidade Online

+ +

Esta política de privacidade online se aplica somente a informações coletadas por nosso site e não a informações coletadas offline.

+ + + +

Usando o nosso site, você concorda com a nossa política de privacidade.

+ +

Mudanças em nossa Política de Privacidade

+ +

Se decidirmos mudar a nossa política de privacidade, publicaremos as mudanças nesta página.

+ +

Este documento é CC-BY-SA. A sua última atualização aconteceu em 31 de maio de 2013.

+ +

Originalmente adaptado da política de privacidade do Discourse.

+ title: "%{instance} Termos de Serviço e Política de Privacidade" time: formats: - default: "%d %b, %Y, %H:%M" + default: "%b %d, %Y, %H:%M" two_factor_authentication: - code_hint: Entre o código gerado pelo seu aplicativo para confirmar - description_html: Se você habilitar autenticação two-factor , quando logar será necessário o seu telefone que vai gerar os tokens usado. - disable: Disabilitar - enable: Habilitar - enabled_success: Autenticador Two-factor habilitador com sucesso - generate_recovery_codes: Gerar códigos para recuperar conta - instructions_html: "Scaneie este código QR no seu Google Authenticator ou aplicativo similar no seu telefone. A partir de agora seu aplicativo irá gerar tokens que deverão ser digitados para você logar." - lost_recovery_codes: Códigos de recuperação permite que você recupere o acesso a sua conta se você perder seu telefone. Se você perder os códigos de recuperação, você pode regera-los aqui. Seus códigos antigos serão invalidados. - manual_instructions: 'Se você não puder scanear o código QR e precisa digita-los manualmente, aqui está o segredo em texto.:' - recovery_codes_regenerated: Códigos de recuperação foram gerados com sucesso - recovery_instructions_html: Se algum dia você perder o acesso ao seu telefone, você pode usar um dos códigos de abaixo para recupera o acesso a sua conta. Guarde os códigos de acesso em local seguro, por exemplo imprimindo ou guardados com documentos importantes. + code_hint: Insira o código gerado pelo seu aplicativo auteticador para confirmar + description_html: Se você ativar a autenticação em dois passos, o acesso à sua conta exigirá posse de seu celular, que irá gerar tokens para validação. + disable: Desativar + enable: Ativar + enabled: A autenticação em dois passos está ativada + enabled_success: Autenticação em dois passos ativada com sucesso + generate_recovery_codes: Gerar códigos de recuperação + instructions_html: "Escaneie este QR Code no Google Authenticator ou aplicativo TOTP similar com o seu celular. De agora em diante, este aplicativo irá gerar tokens que você terá que inserir quando desejar acessar a sua conta." + lost_recovery_codes: Códigos de recuperação permitem que você recupere acesso à sua conta caso perca o seu celular. Se você perdeu seus códigos de recuperação, você pode gerá-los novamente aqui. Seus códigos de recuperaçãp anteriores serão invalidados. + manual_instructions: 'Se você não pode escanear o QR code e precisa inserí-lo manualmente, aqui está o segredo em texto:' + recovery_codes: Códigos de recuperação de reserva + recovery_codes_regenerated: Códigos de recuperação regenerados com sucesso + recovery_instructions_html: Se você perder acesso ao seu celular, você pode usar um dos códigos de recuperação abaixo para reganhar acesso à sua conta. Mantenha os códigos de recuperação em um local seguro. Por exemplo, você pode imprimi-los e guardá-los com outros documentos importantes. setup: Configurar - wrong_code: O código digitado é inválido! Os relógios do servidor e do dispositivo estão corretos? + wrong_code: O código inserido é invalido! O horário do servidor e o horário do seu aparelho estão corretos? users: - invalid_email: Endereço e-mail inválido - invalid_otp_token: Código two-factor inválido + invalid_email: O endereço de e-mail é inválido + invalid_otp_token: Código de autenticação inválido + signed_in_as: 'Acesso como:' diff --git a/config/locales/simple_form.pt-BR.yml b/config/locales/simple_form.pt-BR.yml index 733e16892..bc6766689 100644 --- a/config/locales/simple_form.pt-BR.yml +++ b/config/locales/simple_form.pt-BR.yml @@ -1,51 +1,64 @@ --- pt-BR: simple_form: - labels: + hints: defaults: - avatar: PNG, GIF or JPG. Máximo 2MB. Será reduzido para 120x120px - display_name: '%{count} caracteres restantes' - header: PNG, GIF or JPG. Máximo 2MB. Será reduzido para 700x335px - locked: Requer você aprovação manualmente seguidores e posts padrão de privacidade para seguidores-apenas - note: '%{count} caracteres restantes' + avatar: PNG, GIF or JPG. Arquivos de até 2MB. Eles serão diminuídos para 120x120px + display_name: + one: 1 caracter restante + other: %{count} caracteres restantes + header: PNG, GIF or JPG. Arquivos de até 2MB. Eles serão diminuídos para 700x335px + locked: Requer aprovação manual de seguidores + note: + one: 1 caracter restante + other: %{count} caracteres restantes + setting_noindex: Afeta seu perfil público e as páginas de suas postagens imports: - data: Arquivo CSV exportado de outra instancia Mastodon + data: Arquivo CSV exportado de outra instância do Mastodon sessions: - otp: Entre com o código de 2 passos do seu telefone ou use os códiogos de recuperação. + otp: Insira o código de autenticação do seu celular ou use um dos códigos de recuperação. + user: + filtered_languages: Selecione os idiomas que devem ser removidos de suas timelines públicas. labels: defaults: avatar: Avatar - confirm_new_password: Confirme nova senha - confirm_password: Confirme a senha + confirm_new_password: Confirmar nova senha + confirm_password: Confirmar senha current_password: Senha atual data: Dados - display_name: Nome - email: Endereço de email - header: Header - locale: Linguagem - locked: Conta bloqueada + display_name: Nome de exibição + email: Endereço de e-mail + filtered_languages: Idiomas filtrados + header: Cabeçalho + locale: Idioma + locked: Trancar conta new_password: Nova senha - note: Biografia - otp_attempt: Autenticação 2 passos + note: Bio + otp_attempt: Código de autenticação em dois passos password: Senha - setting_auto_play_gif: Tocar GIFs animados automaticamente - setting_boost_modal: Mostrar dialogo de confirmação antes de fazer boost - setting_default_privacy: Postar privacidade - severity: Severidade - type: Importar tipo - username: Usuário + setting_auto_play_gif: Reproduzir GIFs automaticamente + setting_boost_modal: Mostrar diálogo de confirmação antes de compartilhar postagem + setting_default_privacy: Privacidade das postagens + setting_default_sensitive: Sempre marcar mídia como sensível + setting_delete_modal: Mostrar diálogo de confirmação antes de deletar uma postagem + setting_noindex: Não quero ser indexado por mecanismos de busca + setting_system_font_ui: Usar a fonte padrão de seu sistema + setting_unfollow_modal: Mostrar diálogo de confirmação antes de deixar de seguir alguém + severity: Gravidade + type: Tipo de importação + username: Nome de usuário interactions: must_be_follower: Bloquear notificações de não-seguidores - must_be_following: Bloquear notificações de pessoas que você + must_be_following: Bloquear notificações de pessoas que você não segue notification_emails: - digest: Enviar resumo de emails - favourite: Enviar email quando alguém favorita um post seu - follow: Enviar email quando alguém seguir você - follow_request: Enviar email quando alguém requisitar te seguir - mention: Enviar email quando alguém mencionar você - reblog: Enviar email quando alguém reblogar um post seu + digest: Mandar e-mails com relatórios + favourite: Mandar um e-mail quando alguém favoritar suas postagens + follow: Mandar um e-mail quando alguém te seguir + follow_request: Mandar um e-maill quando alguém solicitar ser seu seguidor + mention: Mandar um e-mail quando alguém te mencionar + reblog: Mandar um e-mail quando alguém compartilhar suas postagens 'no': 'Não' required: mark: "*" - text: necessário + text: obrigatório 'yes': 'Sim' -- cgit From 47d48fed8d398a1d1ebae01fcded0eb9f4f73c42 Mon Sep 17 00:00:00 2001 From: unarist Date: Mon, 11 Sep 2017 23:19:54 +0900 Subject: Reset preview image if avatar/header image selection was cancelled (#4893) --- app/javascript/packs/public.js | 4 ++-- app/views/settings/profiles/show.html.haml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'app/javascript') diff --git a/app/javascript/packs/public.js b/app/javascript/packs/public.js index 1a274c4cb..ca6f9eac6 100644 --- a/app/javascript/packs/public.js +++ b/app/javascript/packs/public.js @@ -124,7 +124,7 @@ function main() { delegate(document, '#account_avatar', 'change', ({ target }) => { const avatar = document.querySelector('.card.compact .avatar img'); const [file] = target.files || []; - const url = URL.createObjectURL(file); + const url = file ? URL.createObjectURL(file) : avatar.dataset.originalSrc; avatar.src = url; }); @@ -132,7 +132,7 @@ function main() { delegate(document, '#account_header', 'change', ({ target }) => { const header = document.querySelector('.card.compact'); const [file] = target.files || []; - const url = URL.createObjectURL(file); + const url = file ? URL.createObjectURL(file) : header.dataset.originalSrc; header.style.backgroundImage = `url(${url})`; }); diff --git a/app/views/settings/profiles/show.html.haml b/app/views/settings/profiles/show.html.haml index e0fb613f8..7a06cd014 100644 --- a/app/views/settings/profiles/show.html.haml +++ b/app/views/settings/profiles/show.html.haml @@ -8,8 +8,8 @@ = f.input :display_name, placeholder: t('simple_form.labels.defaults.display_name'), hint: t('simple_form.hints.defaults.display_name', count: 30 - @account.display_name.size).html_safe = f.input :note, placeholder: t('simple_form.labels.defaults.note'), hint: t('simple_form.hints.defaults.note', count: 160 - @account.note.size).html_safe - .card.compact{ style: "background-image: url(#{@account.header.url(:original)})" } - .avatar= image_tag @account.avatar.url(:original) + .card.compact{ style: "background-image: url(#{@account.header.url(:original)})", data: { original_src: @account.header.url(:original) } } + .avatar= image_tag @account.avatar.url(:original), data: { original_src: @account.avatar.url(:original) } .fields-group = f.input :avatar, wrapper: :with_label, input_html: { accept: AccountAvatar::IMAGE_MIME_TYPES.join(',') }, hint: t('simple_form.hints.defaults.avatar') -- cgit From af10c9fbfff237e45ff46355d118e6824ae05b79 Mon Sep 17 00:00:00 2001 From: unarist Date: Wed, 13 Sep 2017 06:06:10 +0900 Subject: Add section for protocol specific information on the admin page (#4910) This PR adds section for protocol specific information, then always show both of OStatus and ActivityPub. Specifically, this will help admins to check PuSH subscription status and unsubscribe manually, even `protocol` has been changed. This also includes below changes: * Add `overflow: hidden` to prevent float leaking * Add missing fields for ActivityPub --- app/javascript/styles/admin.scss | 8 +++ app/views/admin/accounts/show.html.haml | 109 +++++++++++++++++++------------- config/locales/en.yml | 2 + 3 files changed, 75 insertions(+), 44 deletions(-) (limited to 'app/javascript') diff --git a/app/javascript/styles/admin.scss b/app/javascript/styles/admin.scss index fa7859e38..87bc710af 100644 --- a/app/javascript/styles/admin.scss +++ b/app/javascript/styles/admin.scss @@ -97,6 +97,14 @@ margin-bottom: 40px; } + h3 { + color: $ui-secondary-color; + font-size: 20px; + line-height: 28px; + font-weight: 400; + margin-bottom: 30px; + } + h6 { font-size: 16px; color: $ui-secondary-color; diff --git a/app/views/admin/accounts/show.html.haml b/app/views/admin/accounts/show.html.haml index 89355281a..3775b6721 100644 --- a/app/views/admin/accounts/show.html.haml +++ b/app/views/admin/accounts/show.html.haml @@ -37,29 +37,6 @@ %th= t('admin.accounts.protocol') %td= @account.protocol.humanize - - if @account.ostatus? - %tr - %th= t('admin.accounts.feed_url') - %td= link_to @account.remote_url, @account.remote_url - %tr - %th= t('admin.accounts.push_subscription_expires') - %td - - if @account.subscribed? - %time.formatted{ datetime: @account.subscription_expires_at.iso8601, title: l(@account.subscription_expires_at) } - = l @account.subscription_expires_at - - else - = t('admin.accounts.not_subscribed') - %tr - %th= t('admin.accounts.salmon_url') - %td= link_to @account.salmon_url, @account.salmon_url - - elsif @account.activitypub? - %tr - %th= t('admin.accounts.inbox_url') - %td= link_to @account.inbox_url, @account.inbox_url - %tr - %th= t('admin.accounts.outbox_url') - %td= link_to @account.outbox_url, @account.outbox_url - %tr %th= t('admin.accounts.follows') %td= @account.following_count @@ -82,29 +59,73 @@ %th= t('.targeted_reports') %td= link_to pluralize(@account.targeted_reports.count, t('.report')), admin_reports_path(target_account_id: @account.id) -%div{ style: 'float: right' } - - if @account.local? - = link_to t('admin.accounts.reset_password'), admin_account_reset_path(@account.id), method: :create, class: 'button' - - if @account.user&.otp_required_for_login? - = link_to t('admin.accounts.disable_two_factor_authentication'), admin_user_two_factor_authentication_path(@account.user.id), method: :delete, class: 'button' - - else - - if @account.ostatus? +%div{ style: 'overflow: hidden' } + %div{ style: 'float: right' } + - if @account.local? + = link_to t('admin.accounts.reset_password'), admin_account_reset_path(@account.id), method: :create, class: 'button' + - if @account.user&.otp_required_for_login? + = link_to t('admin.accounts.disable_two_factor_authentication'), admin_user_two_factor_authentication_path(@account.user.id), method: :delete, class: 'button' + - else + = link_to t('admin.accounts.redownload'), redownload_admin_account_path(@account.id), method: :post, class: 'button' + + %div{ style: 'float: left' } + - if @account.silenced? + = link_to t('admin.accounts.undo_silenced'), admin_account_silence_path(@account.id), method: :delete, class: 'button' + - else + = link_to t('admin.accounts.silence'), admin_account_silence_path(@account.id), method: :post, class: 'button' + + - if @account.local? + - unless @account.user_confirmed? + = link_to t('admin.accounts.confirm'), admin_account_confirmation_path(@account.id), method: :post, class: 'button' + + - if @account.suspended? + = link_to t('admin.accounts.undo_suspension'), admin_account_suspension_path(@account.id), method: :delete, class: 'button' + - else + = link_to t('admin.accounts.perform_full_suspension'), admin_account_suspension_path(@account.id), method: :post, data: { confirm: t('admin.accounts.are_you_sure') }, class: 'button' + +- unless @account.local? + %hr + %h3 OStatus + + .table-wrapper + %table.table + %tbody + %tr + %th= t('admin.accounts.feed_url') + %td= link_to @account.remote_url, @account.remote_url + %tr + %th= t('admin.accounts.push_subscription_expires') + %td + - if @account.subscribed? + %time.formatted{ datetime: @account.subscription_expires_at.iso8601, title: l(@account.subscription_expires_at) } + = l @account.subscription_expires_at + - else + = t('admin.accounts.not_subscribed') + %tr + %th= t('admin.accounts.salmon_url') + %td= link_to @account.salmon_url, @account.salmon_url + + %div{ style: 'overflow: hidden' } + %div{ style: 'float: right' } = link_to @account.subscribed? ? t('admin.accounts.resubscribe') : t('admin.accounts.subscribe'), subscribe_admin_account_path(@account.id), method: :post, class: 'button' - if @account.subscribed? = link_to t('admin.accounts.unsubscribe'), unsubscribe_admin_account_path(@account.id), method: :post, class: 'button negative' - = link_to t('admin.accounts.redownload'), redownload_admin_account_path(@account.id), method: :post, class: 'button' - -%div{ style: 'float: left' } - - if @account.silenced? - = link_to t('admin.accounts.undo_silenced'), admin_account_silence_path(@account.id), method: :delete, class: 'button' - - else - = link_to t('admin.accounts.silence'), admin_account_silence_path(@account.id), method: :post, class: 'button' - - if @account.local? - - unless @account.user_confirmed? - = link_to t('admin.accounts.confirm'), admin_account_confirmation_path(@account.id), method: :post, class: 'button' + %hr + %h3 ActivityPub - - if @account.suspended? - = link_to t('admin.accounts.undo_suspension'), admin_account_suspension_path(@account.id), method: :delete, class: 'button' - - else - = link_to t('admin.accounts.perform_full_suspension'), admin_account_suspension_path(@account.id), method: :post, data: { confirm: t('admin.accounts.are_you_sure') }, class: 'button' + .table-wrapper + %table.table + %tbody + %tr + %th= t('admin.accounts.inbox_url') + %td= link_to @account.inbox_url, @account.inbox_url + %tr + %th= t('admin.accounts.outbox_url') + %td= link_to @account.outbox_url, @account.outbox_url + %tr + %th= t('admin.accounts.shared_inbox_url') + %td= link_to @account.shared_inbox_url, @account.shared_inbox_url + %tr + %th= t('admin.accounts.followers_url') + %td= link_to @account.followers_url, @account.followers_url diff --git a/config/locales/en.yml b/config/locales/en.yml index 64fc556f3..e31f883ac 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -60,6 +60,7 @@ en: email: E-mail feed_url: Feed URL followers: Followers + followers_url: Followers URL follows: Follows inbox_url: Inbox URL ip: IP @@ -93,6 +94,7 @@ en: resubscribe: Resubscribe salmon_url: Salmon URL search: Search + shared_inbox_url: Shared Inbox URL show: created_reports: Reports created by this account report: report -- cgit From 60944d5dca0f25c668db00c0d84910f1dddc2a12 Mon Sep 17 00:00:00 2001 From: abcang Date: Wed, 13 Sep 2017 17:24:33 +0900 Subject: Fix height cache (#4909) --- app/javascript/mastodon/actions/height_cache.js | 17 +++++++++++ app/javascript/mastodon/actions/statuses.js | 17 ----------- .../components/intersection_observer_article.js | 33 +++++++++++----------- .../mastodon/components/scrollable_list.js | 17 +++++++++-- .../intersection_observer_article_container.js | 17 +++++++++++ .../mastodon/containers/status_container.js | 6 +--- app/javascript/mastodon/features/ui/index.js | 4 +-- app/javascript/mastodon/reducers/height_cache.js | 23 +++++++++++++++ app/javascript/mastodon/reducers/index.js | 2 ++ app/javascript/mastodon/reducers/statuses.js | 18 ------------ 10 files changed, 93 insertions(+), 61 deletions(-) create mode 100644 app/javascript/mastodon/actions/height_cache.js create mode 100644 app/javascript/mastodon/containers/intersection_observer_article_container.js create mode 100644 app/javascript/mastodon/reducers/height_cache.js (limited to 'app/javascript') diff --git a/app/javascript/mastodon/actions/height_cache.js b/app/javascript/mastodon/actions/height_cache.js new file mode 100644 index 000000000..4c752993f --- /dev/null +++ b/app/javascript/mastodon/actions/height_cache.js @@ -0,0 +1,17 @@ +export const HEIGHT_CACHE_SET = 'HEIGHT_CACHE_SET'; +export const HEIGHT_CACHE_CLEAR = 'HEIGHT_CACHE_CLEAR'; + +export function setHeight (key, id, height) { + return { + type: HEIGHT_CACHE_SET, + key, + id, + height, + }; +}; + +export function clearHeight () { + return { + type: HEIGHT_CACHE_CLEAR, + }; +}; diff --git a/app/javascript/mastodon/actions/statuses.js b/app/javascript/mastodon/actions/statuses.js index 0b5e72c17..2204e0b14 100644 --- a/app/javascript/mastodon/actions/statuses.js +++ b/app/javascript/mastodon/actions/statuses.js @@ -23,9 +23,6 @@ export const STATUS_UNMUTE_REQUEST = 'STATUS_UNMUTE_REQUEST'; export const STATUS_UNMUTE_SUCCESS = 'STATUS_UNMUTE_SUCCESS'; export const STATUS_UNMUTE_FAIL = 'STATUS_UNMUTE_FAIL'; -export const STATUS_SET_HEIGHT = 'STATUS_SET_HEIGHT'; -export const STATUSES_CLEAR_HEIGHT = 'STATUSES_CLEAR_HEIGHT'; - export function fetchStatusRequest(id, skipLoading) { return { type: STATUS_FETCH_REQUEST, @@ -218,17 +215,3 @@ export function unmuteStatusFail(id, error) { error, }; }; - -export function setStatusHeight (id, height) { - return { - type: STATUS_SET_HEIGHT, - id, - height, - }; -}; - -export function clearStatusesHeight () { - return { - type: STATUSES_CLEAR_HEIGHT, - }; -}; diff --git a/app/javascript/mastodon/components/intersection_observer_article.js b/app/javascript/mastodon/components/intersection_observer_article.js index 347767818..bb83a4da0 100644 --- a/app/javascript/mastodon/components/intersection_observer_article.js +++ b/app/javascript/mastodon/components/intersection_observer_article.js @@ -7,10 +7,13 @@ import getRectFromEntry from '../features/ui/util/get_rect_from_entry'; export default class IntersectionObserverArticle extends ImmutablePureComponent { static propTypes = { - intersectionObserverWrapper: PropTypes.object, + intersectionObserverWrapper: PropTypes.object.isRequired, id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), index: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), listLength: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), + saveHeightKey: PropTypes.string, + cachedHeight: PropTypes.number, + onHeightChange: PropTypes.func, children: PropTypes.node, }; @@ -34,13 +37,10 @@ export default class IntersectionObserverArticle extends ImmutablePureComponent } componentDidMount () { - if (!this.props.intersectionObserverWrapper) { - // TODO: enable IntersectionObserver optimization for notification statuses. - // These are managed in notifications/index.js rather than status_list.js - return; - } - this.props.intersectionObserverWrapper.observe( - this.props.id, + const { intersectionObserverWrapper, id } = this.props; + + intersectionObserverWrapper.observe( + id, this.node, this.handleIntersection ); @@ -49,20 +49,21 @@ export default class IntersectionObserverArticle extends ImmutablePureComponent } componentWillUnmount () { - if (this.props.intersectionObserverWrapper) { - this.props.intersectionObserverWrapper.unobserve(this.props.id, this.node); - } + const { intersectionObserverWrapper, id } = this.props; + intersectionObserverWrapper.unobserve(id, this.node); this.componentMounted = false; } handleIntersection = (entry) => { + const { onHeightChange, saveHeightKey, id } = this.props; + if (this.node && this.node.children.length !== 0) { // save the height of the fully-rendered element this.height = getRectFromEntry(entry).height; - if (this.props.onHeightChange) { - this.props.onHeightChange(this.props.status, this.height); + if (onHeightChange && saveHeightKey) { + onHeightChange(saveHeightKey, id, this.height); } } @@ -94,16 +95,16 @@ export default class IntersectionObserverArticle extends ImmutablePureComponent } render () { - const { children, id, index, listLength } = this.props; + const { children, id, index, listLength, cachedHeight } = this.props; const { isIntersecting, isHidden } = this.state; - if (!isIntersecting && isHidden) { + if (!isIntersecting && (isHidden || cachedHeight)) { return (
diff --git a/app/javascript/mastodon/components/scrollable_list.js b/app/javascript/mastodon/components/scrollable_list.js index 723dd322b..3d78b3ffa 100644 --- a/app/javascript/mastodon/components/scrollable_list.js +++ b/app/javascript/mastodon/components/scrollable_list.js @@ -1,7 +1,7 @@ import React, { PureComponent } from 'react'; import { ScrollContainer } from 'react-router-scroll'; import PropTypes from 'prop-types'; -import IntersectionObserverArticle from './intersection_observer_article'; +import IntersectionObserverArticleContainer from '../containers/intersection_observer_article_container'; import LoadMore from './load_more'; import IntersectionObserverWrapper from '../features/ui/util/intersection_observer_wrapper'; import { throttle } from 'lodash'; @@ -9,6 +9,10 @@ import { List as ImmutableList } from 'immutable'; export default class ScrollableList extends PureComponent { + static contextTypes = { + router: PropTypes.object, + }; + static propTypes = { scrollKey: PropTypes.string.isRequired, onScrollToBottom: PropTypes.func, @@ -173,9 +177,16 @@ export default class ScrollableList extends PureComponent { {prepend} {React.Children.map(this.props.children, (child, index) => ( - + {child} - + ))} {loadMore} diff --git a/app/javascript/mastodon/containers/intersection_observer_article_container.js b/app/javascript/mastodon/containers/intersection_observer_article_container.js new file mode 100644 index 000000000..b6f162199 --- /dev/null +++ b/app/javascript/mastodon/containers/intersection_observer_article_container.js @@ -0,0 +1,17 @@ +import { connect } from 'react-redux'; +import IntersectionObserverArticle from '../components/intersection_observer_article'; +import { setHeight } from '../actions/height_cache'; + +const makeMapStateToProps = (state, props) => ({ + cachedHeight: state.getIn(['height_cache', props.saveHeightKey, props.id]), +}); + +const mapDispatchToProps = (dispatch) => ({ + + onHeightChange (key, id, height) { + dispatch(setHeight(key, id, height)); + }, + +}); + +export default connect(makeMapStateToProps, mapDispatchToProps)(IntersectionObserverArticle); diff --git a/app/javascript/mastodon/containers/status_container.js b/app/javascript/mastodon/containers/status_container.js index a727a87d1..c61b7d00d 100644 --- a/app/javascript/mastodon/containers/status_container.js +++ b/app/javascript/mastodon/containers/status_container.js @@ -18,7 +18,7 @@ import { blockAccount, muteAccount, } from '../actions/accounts'; -import { muteStatus, unmuteStatus, deleteStatus, setStatusHeight } from '../actions/statuses'; +import { muteStatus, unmuteStatus, deleteStatus } from '../actions/statuses'; import { initReport } from '../actions/reports'; import { openModal } from '../actions/modal'; import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; @@ -138,10 +138,6 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ } }, - onHeightChange (status, height) { - dispatch(setStatusHeight(status.get('id'), height)); - }, - }); export default injectIntl(connect(makeMapStateToProps, mapDispatchToProps)(Status)); diff --git a/app/javascript/mastodon/features/ui/index.js b/app/javascript/mastodon/features/ui/index.js index 41ce0f8b5..30a52a448 100644 --- a/app/javascript/mastodon/features/ui/index.js +++ b/app/javascript/mastodon/features/ui/index.js @@ -11,7 +11,7 @@ import { debounce } from 'lodash'; import { uploadCompose } from '../../actions/compose'; import { refreshHomeTimeline } from '../../actions/timelines'; import { refreshNotifications } from '../../actions/notifications'; -import { clearStatusesHeight } from '../../actions/statuses'; +import { clearHeight } from '../../actions/height_cache'; import { WrappedSwitch, WrappedRoute } from './util/react_router_helpers'; import UploadArea from './components/upload_area'; import ColumnsAreaContainer from './containers/columns_area_container'; @@ -68,7 +68,7 @@ export default class UI extends React.PureComponent { handleResize = debounce(() => { // The cached heights are no longer accurate, invalidate - this.props.dispatch(clearStatusesHeight()); + this.props.dispatch(clearHeight()); this.setState({ width: window.innerWidth }); }, 500, { diff --git a/app/javascript/mastodon/reducers/height_cache.js b/app/javascript/mastodon/reducers/height_cache.js new file mode 100644 index 000000000..2f5716fae --- /dev/null +++ b/app/javascript/mastodon/reducers/height_cache.js @@ -0,0 +1,23 @@ +import { Map as ImmutableMap } from 'immutable'; +import { HEIGHT_CACHE_SET, HEIGHT_CACHE_CLEAR } from '../actions/height_cache'; + +const initialState = ImmutableMap(); + +const setHeight = (state, key, id, height) => { + return state.update(key, ImmutableMap(), map => map.set(id, height)); +}; + +const clearHeights = () => { + return ImmutableMap(); +}; + +export default function statuses(state = initialState, action) { + switch(action.type) { + case HEIGHT_CACHE_SET: + return setHeight(state, action.key, action.id, action.height); + case HEIGHT_CACHE_CLEAR: + return clearHeights(); + default: + return state; + } +}; diff --git a/app/javascript/mastodon/reducers/index.js b/app/javascript/mastodon/reducers/index.js index 3aaf259c2..0a8c3ce6c 100644 --- a/app/javascript/mastodon/reducers/index.js +++ b/app/javascript/mastodon/reducers/index.js @@ -19,6 +19,7 @@ import compose from './compose'; import search from './search'; import media_attachments from './media_attachments'; import notifications from './notifications'; +import height_cache from './height_cache'; const reducers = { timelines, @@ -41,6 +42,7 @@ const reducers = { search, media_attachments, notifications, + height_cache, }; export default combineReducers(reducers); diff --git a/app/javascript/mastodon/reducers/statuses.js b/app/javascript/mastodon/reducers/statuses.js index eec2a5f16..7f906bef6 100644 --- a/app/javascript/mastodon/reducers/statuses.js +++ b/app/javascript/mastodon/reducers/statuses.js @@ -15,8 +15,6 @@ import { CONTEXT_FETCH_SUCCESS, STATUS_MUTE_SUCCESS, STATUS_UNMUTE_SUCCESS, - STATUS_SET_HEIGHT, - STATUSES_CLEAR_HEIGHT, } from '../actions/statuses'; import { TIMELINE_REFRESH_SUCCESS, @@ -95,18 +93,6 @@ const filterStatuses = (state, relationship) => { return state; }; -const setHeight = (state, id, height) => { - return state.update(id, ImmutableMap(), map => map.set('height', height)); -}; - -const clearHeights = (state) => { - state.forEach(status => { - state = state.deleteIn([status.get('id'), 'height']); - }); - - return state; -}; - const initialState = ImmutableMap(); export default function statuses(state = initialState, action) { @@ -148,10 +134,6 @@ export default function statuses(state = initialState, action) { return deleteStatus(state, action.id, action.references); case ACCOUNT_BLOCK_SUCCESS: return filterStatuses(state, action.relationship); - case STATUS_SET_HEIGHT: - return setHeight(state, action.id, action.height); - case STATUSES_CLEAR_HEIGHT: - return clearHeights(state); default: return state; } -- cgit From 283a5ec1a4b4c771e36e5ad50f6e7c425fcfc4f7 Mon Sep 17 00:00:00 2001 From: MitarashiDango Date: Wed, 13 Sep 2017 22:20:03 +0900 Subject: fix share intent. (#4926) --- app/javascript/mastodon/features/standalone/compose/index.js | 2 ++ 1 file changed, 2 insertions(+) (limited to 'app/javascript') diff --git a/app/javascript/mastodon/features/standalone/compose/index.js b/app/javascript/mastodon/features/standalone/compose/index.js index 96d07fefb..0d764575f 100644 --- a/app/javascript/mastodon/features/standalone/compose/index.js +++ b/app/javascript/mastodon/features/standalone/compose/index.js @@ -2,6 +2,7 @@ import React from 'react'; import ComposeFormContainer from '../../compose/containers/compose_form_container'; import NotificationsContainer from '../../ui/containers/notifications_container'; import LoadingBarContainer from '../../ui/containers/loading_bar_container'; +import ModalContainer from '../../ui/containers/modal_container'; export default class Compose extends React.PureComponent { @@ -10,6 +11,7 @@ export default class Compose extends React.PureComponent {
+
); -- cgit From 331263270bbc4b9536b3f15cdf93361493a60b97 Mon Sep 17 00:00:00 2001 From: Jeroen Date: Wed, 13 Sep 2017 16:12:29 +0200 Subject: Updating Dutch translation (#4927) * Update doorkeeper.nl.yml * Update nl.yml * Update simple_form.nl.yml * Update nl.json * Update en.json * Update en.json * Update nl.json --- app/javascript/mastodon/locales/nl.json | 17 +++++++----- config/locales/doorkeeper.nl.yml | 49 ++++++++++++++++++--------------- config/locales/nl.yml | 19 ++++++++++++- config/locales/simple_form.nl.yml | 14 ++++++++-- 4 files changed, 66 insertions(+), 33 deletions(-) (limited to 'app/javascript') diff --git a/app/javascript/mastodon/locales/nl.json b/app/javascript/mastodon/locales/nl.json index d6775e1e4..2cadc7ac2 100644 --- a/app/javascript/mastodon/locales/nl.json +++ b/app/javascript/mastodon/locales/nl.json @@ -12,7 +12,7 @@ "account.mute": "Negeer @{name}", "account.posts": "Toots", "account.report": "Rapporteer @{name}", - "account.requested": "Wacht op goedkeuring", + "account.requested": "Wacht op goedkeuring. Klik om volgverzoek te annuleren.", "account.share": "Profiel van @{name} delen", "account.unblock": "Deblokkeer @{name}", "account.unblock_domain": "{domain} niet meer negeren", @@ -34,10 +34,11 @@ "column.mutes": "Genegeerde gebruikers", "column.notifications": "Meldingen", "column.public": "Globale tijdlijn", + "column.pins": "Vastgezette toots", "column_back_button.label": "terug", "column_header.hide_settings": "Instellingen verbergen", - "column_header.moveLeft_settings": "Move column to the left", - "column_header.moveRight_settings": "Move column to the right", + "column_header.moveLeft_settings": "Kolom naar links verplaatsen", + "column_header.moveRight_settings": "Kolom naar rechts verplaatsen", "column_header.pin": "Vastmaken", "column_header.show_settings": "Instellingen tonen", "column_header.unpin": "Losmaken", @@ -63,8 +64,8 @@ "confirmations.mute.message": "Weet je het zeker dat je {name} wilt negeren?", "confirmations.unfollow.confirm": "Ontvolgen", "confirmations.unfollow.message": "Weet je het zeker dat je {name} wilt ontvolgen?", - "embed.instructions": "Embed this status on your website by copying the code below.", - "embed.preview": "Here is what it will look like:", + "embed.instructions": "Embed deze toot op jouw website, door de onderstaande code te kopiëren.", + "embed.preview": "Zo komt het eruit te zien:", "emoji_button.activity": "Activiteiten", "emoji_button.flags": "Vlaggen", "emoji_button.food": "Eten en drinken", @@ -85,6 +86,7 @@ "follow_request.authorize": "Goedkeuren", "follow_request.reject": "Afkeuren", "getting_started.appsshort": "Apps", + "getting_started.donate": "Doneren", "getting_started.faq": "FAQ", "getting_started.heading": "Beginnen", "getting_started.open_source_notice": "Mastodon is open-sourcesoftware. Je kunt bijdragen of problemen melden op GitHub via {github}.", @@ -111,6 +113,7 @@ "navigation_bar.mutes": "Genegeerde gebruikers", "navigation_bar.preferences": "Instellingen", "navigation_bar.public_timeline": "Globale tijdlijn", + "navigation_bar.pins": "Vastgezette toots", "notification.favourite": "{name} markeerde jouw toot als favoriet", "notification.follow": "{name} volgt jou nu", "notification.mention": "{name} vermeldde jou", @@ -171,7 +174,7 @@ "status.mention": "Vermeld @{name}", "status.mute_conversation": "Negeer conversatie", "status.open": "Toot volledig tonen", - "status.pin": "Pin on profile", + "status.pin": "Aan profielpagina vastmaken", "status.reblog": "Boost", "status.reblogged_by": "{name} boostte", "status.reply": "Reageren", @@ -183,7 +186,7 @@ "status.show_less": "Minder tonen", "status.show_more": "Meer tonen", "status.unmute_conversation": "Conversatie niet meer negeren", - "status.unpin": "Unpin from profile", + "status.unpin": "Van profielpagina losmaken", "tabs_bar.compose": "Schrijven", "tabs_bar.federated_timeline": "Globaal", "tabs_bar.home": "Start", diff --git a/config/locales/doorkeeper.nl.yml b/config/locales/doorkeeper.nl.yml index 77cf2503b..ae1f8bc52 100644 --- a/config/locales/doorkeeper.nl.yml +++ b/config/locales/doorkeeper.nl.yml @@ -3,9 +3,10 @@ nl: activerecord: attributes: doorkeeper/application: - name: Naam + name: Naam toepassing redirect_uri: Redirect-URI - scopes: Scopes + scopes: Toestemmingen + website: Website toepassing errors: models: doorkeeper/application: @@ -26,27 +27,31 @@ nl: confirmations: destroy: Weet je het zeker? edit: - title: Applicatie bewerken + title: Toepassing bewerken form: error: Oops! Controleer het formulier op fouten help: native_redirect_uri: Gebruik %{native_redirect_uri} voor lokale tests redirect_uri: 'Gebruik één regel per URI. ' - scopes: Scopes met spaties van elkaar scheiden. Laat leeg om de standaardscopes te gebruiken. + scopes: Toestemmingen met spaties van elkaar scheiden. Laat leeg om de standaardtoestemmingen te gebruiken. index: + application: Toepassing callback_url: Callback-URL + delete: Verwijderen name: Naam - new: Nieuwe applicatie - title: Jouw applicaties + new: Nieuwe toepassing + scopes: Toestemmingen + show: Tonen + title: Jouw toepassingen new: - title: Nieuwe applicatie + title: Nieuwe toepassing show: actions: Acties - application_id: Applicatie-ID + application_id: Client-key callback_urls: Callback-URL's - scopes: Scopes - secret: Secret - title: 'Applicatie: %{name}' + scopes: Toestemmingen + secret: Client-secret + title: 'Toepassing: %{name}' authorizations: buttons: authorize: Autoriseren @@ -54,7 +59,7 @@ nl: error: title: Er is een fout opgetreden new: - able_to: Deze applicatie zal in staat zijn om + able_to: Deze toepassing zal in staat zijn om prompt: "%{client_name} autoriseren om uw account te gebruiken?" title: Autorisatie vereist show: @@ -65,10 +70,10 @@ nl: confirmations: revoke: Weet je het zeker? index: - application: Applicatie + application: Toepassing created_at: Aangemaakt op date_format: "%d-%m-%Y %H:%M:%S" - title: Jouw geautoriseerde applicaties + title: Jouw geautoriseerde toepassingen errors: messages: access_denied: De resource-eigenaar of autorisatie-server weigerde het verzoek. @@ -92,23 +97,23 @@ nl: flash: applications: create: - notice: Applicatie aangemaakt. + notice: Toepassing aangemaakt. destroy: - notice: Applicatie verwijderd. + notice: Toepassing verwijderd. update: - notice: Applicatie bewerkt. + notice: Toepassing bewerkt. authorized_applications: destroy: - notice: Applicatie ingetrokken. + notice: Toepassing ingetrokken. layouts: admin: nav: - applications: Applicaties + applications: Toepassingen home: Home oauth2_provider: OAuth2-provider application: title: OAuth-autorisatie vereist scopes: - follow: accounts te volgen, te negeren en te blokkeren. - read: jouw accountgegevens te lezen - write: namens jou berichten te plaatsen + follow: accounts volgen, negeren en blokkeren + read: berichten lezen + write: berichten plaatsen diff --git a/config/locales/nl.yml b/config/locales/nl.yml index 2b7a1a511..c2b4b6da6 100644 --- a/config/locales/nl.yml +++ b/config/locales/nl.yml @@ -41,8 +41,11 @@ nl: people_followed_by: Mensen die %{name} volgt people_who_follow: Mensen die %{name} volgen posts: Toots + posts_with_replies: Toots met reacties remote_follow: Extern volgen reserved_username: Deze gebruikersnaam is gereserveerd + roles: + admin: Beheerder unfollow: Ontvolgen admin: accounts: @@ -56,7 +59,9 @@ nl: email: E-mail feed_url: Feed-URL followers: Volgers + followers_url: Volgers-URL follows: Volgt + inbox_url: Inbox-URL ip: IP location: all: Alles @@ -86,6 +91,7 @@ nl: resubscribe: Opnieuw abonneren salmon_url: Salmon-URL search: Zoeken + shared_inbox_url: Gedeelde inbox-URL show: created_reports: Toots door dit account gerapporteerd report: gerapporteerd @@ -160,6 +166,9 @@ nl: unresolved: Onopgelost view: Weergeven settings: + bootstrap_timeline_accounts: + desc_html: Meerdere gebruikersnamen met komma's scheiden. Alleen lokale en niet opgeschorte accounts werken. Laat leeg voor alle lokale beheerders. + title: Standaard te volgen accounts voor nieuwe gebruikers contact_information: email: Vul een openbaar gebruikt e-mailadres in username: Vul een gebruikersnaam in @@ -272,7 +281,7 @@ nl: content: Veiligheidsverificatie mislukt. Blokkeer je toevallig cookies? title: Veiligheidsverificatie mislukt '429': Te veel verbindingsaanvragen. - noscript_html: Schakel JavaScript in om de webapplicatie van Mastodon te gebruiken. Als alternatief kan je een Mastodon-app zoeken voor jouw platform. + noscript_html: Schakel JavaScript in om de webapp van Mastodon te kunnen gebruiken. Als alternatief kan je een Mastodon-app zoeken voor jouw platform. exports: blocks: Jij blokkeert csv: CSV @@ -412,6 +421,7 @@ nl: authorized_apps: Geautoriseerde apps back: Terug naar Mastodon delete: Account deletion + development: Ontwikkelaars edit_profile: Profiel bewerken export: Export followers: Geautoriseerde volgers @@ -419,9 +429,15 @@ nl: preferences: Voorkeuren settings: Instellingen two_factor_authentication: Tweestapsverificatie + your_apps: Jouw toepassingen statuses: open_in_web: In de webapp openen over_character_limit: Limiet van %{max} tekens overschreden + pin_errors: + limit: Te veel toots vastgezet + ownership: Een toot van iemand anders kan niet worden vastgezet + private: Alleen openbare toots kunnen worden vastgezet + reblog: Een boost kan niet worden vastgezet show_more: Meer tonen visibilities: private: Alleen volgers @@ -432,6 +448,7 @@ nl: unlisted_long: Aan iedereen tonen, maar niet op openbare tijdlijnen stream_entries: click_to_show: Klik om te tonen + pinned: Vastgemaakte toot reblogged: boostte sensitive_content: Gevoelige inhoud terms: diff --git a/config/locales/simple_form.nl.yml b/config/locales/simple_form.nl.yml index 351d1800c..82f6cd426 100644 --- a/config/locales/simple_form.nl.yml +++ b/config/locales/simple_form.nl.yml @@ -7,7 +7,10 @@ nl: display_name: Maximaal 30 tekens header: PNG, GIF of JPG. Maximaal 2MB. Wordt teruggeschaald naar 700x335px locked: Vereist dat je handmatig volgers moet accepteren en stelt de privacy van toots standaard in op alleen volgers - note: Maximaal 160 tekens + note: + one: 1 teken over + other: %{count} tekens over + setting_noindex: Heeft invloed op jouw openbare profiel en toots imports: data: CSV-bestand dat op een andere Mastodon-server werd geëxporteerd sessions: @@ -32,8 +35,13 @@ nl: otp_attempt: Tweestaps-aanmeldcode password: Wachtwoord setting_auto_play_gif: Speel geanimeerde GIF's automatisch af - setting_boost_modal: Vraag voor het boosten een bevestiging - setting_default_privacy: Tootprivacy + setting_boost_modal: Vraag voor het boosten van een toot een bevestiging + setting_default_privacy: Zichtbaarheid toots + setting_default_sensitive: Media altijd als gevoelig markeren + setting_delete_modal: Vraag voor het verwijderen van een toot een bevestiging + setting_noindex: Jouw toots niet door zoekmachines laten indexeren + setting_system_font_ui: Standaardlettertype van jouw systeem gebruiken + setting_unfollow_modal: Vraag voor het ontvolgen van iemand een bevestiging type: Importtype username: gebruikersnaam interactions: -- cgit From 9239e4ce4d4e958e62552d4a01183d0295c020f5 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Thu, 14 Sep 2017 00:04:30 +0200 Subject: Uploads for admin site settings (#4913) * Improve OpenGraph tags for about pages * Add thumbnail admin setting * Fix error * Fix up --- app/controllers/admin/settings_controller.rb | 14 ++++++-- app/javascript/images/mastodon_small.jpg | Bin 25199 -> 0 bytes app/javascript/images/preview.jpg | Bin 0 -> 292252 bytes app/models/site_upload.rb | 44 +++++++++++++++++++++++ app/presenters/instance_presenter.rb | 4 +++ app/serializers/rest/instance_serializer.rb | 8 ++++- app/views/about/_og.html.haml | 10 ++++++ app/views/about/more.html.haml | 11 +----- app/views/about/show.html.haml | 11 +----- app/views/admin/settings/edit.html.haml | 5 +++ config/locales/en.yml | 3 ++ db/migrate/20170913000752_create_site_uploads.rb | 10 ++++++ db/schema.rb | 14 +++++++- spec/fabricators/site_upload_fabricator.rb | 3 ++ spec/models/site_upload_spec.rb | 5 +++ spec/views/about/show.html.haml_spec.rb | 9 ++--- 16 files changed, 123 insertions(+), 28 deletions(-) delete mode 100644 app/javascript/images/mastodon_small.jpg create mode 100644 app/javascript/images/preview.jpg create mode 100644 app/models/site_upload.rb create mode 100644 app/views/about/_og.html.haml create mode 100644 db/migrate/20170913000752_create_site_uploads.rb create mode 100644 spec/fabricators/site_upload_fabricator.rb create mode 100644 spec/models/site_upload_spec.rb (limited to 'app/javascript') diff --git a/app/controllers/admin/settings_controller.rb b/app/controllers/admin/settings_controller.rb index c5e6fe4e5..a2f86b8a9 100644 --- a/app/controllers/admin/settings_controller.rb +++ b/app/controllers/admin/settings_controller.rb @@ -14,6 +14,7 @@ module Admin open_deletion timeline_preview bootstrap_timeline_accounts + thumbnail ).freeze BOOLEAN_SETTINGS = %w( @@ -22,14 +23,23 @@ module Admin timeline_preview ).freeze + UPLOAD_SETTINGS = %w( + thumbnail + ).freeze + def edit @admin_settings = Form::AdminSettings.new end def update settings_params.each do |key, value| - setting = Setting.where(var: key).first_or_initialize(var: key) - setting.update(value: value_for_update(key, value)) + if UPLOAD_SETTINGS.include?(key) + upload = SiteUpload.where(var: key).first_or_initialize(var: key) + upload.update(file: value) + else + setting = Setting.where(var: key).first_or_initialize(var: key) + setting.update(value: value_for_update(key, value)) + end end flash[:notice] = I18n.t('generic.changes_saved_msg') diff --git a/app/javascript/images/mastodon_small.jpg b/app/javascript/images/mastodon_small.jpg deleted file mode 100644 index 9c88ce3f7..000000000 Binary files a/app/javascript/images/mastodon_small.jpg and /dev/null differ diff --git a/app/javascript/images/preview.jpg b/app/javascript/images/preview.jpg new file mode 100644 index 000000000..ec2856748 Binary files /dev/null and b/app/javascript/images/preview.jpg differ diff --git a/app/models/site_upload.rb b/app/models/site_upload.rb new file mode 100644 index 000000000..8ffdc8313 --- /dev/null +++ b/app/models/site_upload.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true +# == Schema Information +# +# Table name: site_uploads +# +# id :integer not null, primary key +# var :string default(""), not null +# file_file_name :string +# file_content_type :string +# file_file_size :integer +# file_updated_at :datetime +# meta :json +# created_at :datetime not null +# updated_at :datetime not null +# + +class SiteUpload < ApplicationRecord + has_attached_file :file + + validates_attachment_content_type :file, content_type: /\Aimage\/.*\z/ + validates :var, presence: true, uniqueness: true + + before_save :set_meta + after_commit :clear_cache + + def cache_key + "site_uploads/#{var}" + end + + private + + def set_meta + tempfile = file.queued_for_write[:original] + + return if tempfile.nil? + + geometry = Paperclip::Geometry.from_file(tempfile) + self.meta = { width: geometry.width.to_i, height: geometry.height.to_i } + end + + def clear_cache + Rails.cache.delete(cache_key) + end +end diff --git a/app/presenters/instance_presenter.rb b/app/presenters/instance_presenter.rb index 8104b7531..c9e3c31a1 100644 --- a/app/presenters/instance_presenter.rb +++ b/app/presenters/instance_presenter.rb @@ -35,4 +35,8 @@ class InstancePresenter def source_url Mastodon::Version.source_url end + + def thumbnail + @thumbnail ||= Rails.cache.fetch('site_uploads/thumbnail') { SiteUpload.find_by(var: 'thumbnail') } + end end diff --git a/app/serializers/rest/instance_serializer.rb b/app/serializers/rest/instance_serializer.rb index a97137909..2898011fd 100644 --- a/app/serializers/rest/instance_serializer.rb +++ b/app/serializers/rest/instance_serializer.rb @@ -1,8 +1,10 @@ # frozen_string_literal: true class REST::InstanceSerializer < ActiveModel::Serializer + include RoutingHelper + attributes :uri, :title, :description, :email, - :version, :urls, :stats + :version, :urls, :stats, :thumbnail def uri Rails.configuration.x.local_domain @@ -24,6 +26,10 @@ class REST::InstanceSerializer < ActiveModel::Serializer Mastodon::Version.to_s end + def thumbnail + full_asset_url(instance_presenter.thumbnail.file.url) if instance_presenter.thumbnail + end + def stats { user_count: instance_presenter.user_count, diff --git a/app/views/about/_og.html.haml b/app/views/about/_og.html.haml new file mode 100644 index 000000000..dbd476915 --- /dev/null +++ b/app/views/about/_og.html.haml @@ -0,0 +1,10 @@ +- thumbnail = @instance_presenter.thumbnail += opengraph 'og:site_name', t('about.hosted_on', domain: site_hostname) += opengraph 'og:url', about_url += opengraph 'og:type', 'website' += opengraph 'og:title', @instance_presenter.site_title += opengraph 'og:description', strip_tags(@instance_presenter.site_description.presence || t('about.about_mastodon_html')) += opengraph 'og:image', full_asset_url(thumbnail&.file&.url || asset_pack_path('preview.jpg', protocol: :request)) += opengraph 'og:image:width', thumbnail ? thumbnail.meta['width'] : '1200' += opengraph 'og:image:height', thumbnail ? thumbnail.meta['height'] : '630' += opengraph 'twitter:card', 'summary_large_image' diff --git a/app/views/about/more.html.haml b/app/views/about/more.html.haml index 094188472..1a4e74643 100644 --- a/app/views/about/more.html.haml +++ b/app/views/about/more.html.haml @@ -3,16 +3,7 @@ - content_for :header_tags do = javascript_pack_tag 'public', integrity: true, crossorigin: 'anonymous' - - %meta{ property: 'og:site_name', content: site_title }/ - %meta{ property: 'og:url', content: about_url }/ - %meta{ property: 'og:type', content: 'website' }/ - %meta{ property: 'og:title', content: site_hostname }/ - %meta{ property: 'og:description', content: strip_tags(@instance_presenter.site_description.presence || t('about.about_mastodon_html')) }/ - %meta{ property: 'og:image', content: asset_pack_path('mastodon_small.jpg', protocol: :request) }/ - %meta{ property: 'og:image:width', content: '400' }/ - %meta{ property: 'og:image:height', content: '400' }/ - %meta{ property: 'twitter:card', content: 'summary' }/ + = render partial: 'og' .landing-page .header-wrapper.compact diff --git a/app/views/about/show.html.haml b/app/views/about/show.html.haml index 93270fe3d..0d311b895 100644 --- a/app/views/about/show.html.haml +++ b/app/views/about/show.html.haml @@ -4,16 +4,7 @@ - content_for :header_tags do %script#initial-state{ type: 'application/json' }!= json_escape(@initial_state_json) = javascript_pack_tag 'about', integrity: true, crossorigin: 'anonymous' - - %meta{ property: 'og:site_name', content: site_title }/ - %meta{ property: 'og:url', content: about_url }/ - %meta{ property: 'og:type', content: 'website' }/ - %meta{ property: 'og:title', content: site_hostname }/ - %meta{ property: 'og:description', content: strip_tags(@instance_presenter.site_description.presence || t('about.about_mastodon_html')) }/ - %meta{ property: 'og:image', content: asset_pack_path('mastodon_small.jpg', protocol: :request) }/ - %meta{ property: 'og:image:width', content: '400' }/ - %meta{ property: 'og:image:height', content: '400' }/ - %meta{ property: 'twitter:card', content: 'summary' }/ + = render partial: 'og' .landing-page .header-wrapper diff --git a/app/views/admin/settings/edit.html.haml b/app/views/admin/settings/edit.html.haml index 50d019ec4..468166035 100644 --- a/app/views/admin/settings/edit.html.haml +++ b/app/views/admin/settings/edit.html.haml @@ -10,6 +10,11 @@ %hr/ + .fields-group + = f.input :thumbnail, as: :file, wrapper: :with_block_label, label: t('admin.settings.thumbnail.title'), hint: t('admin.settings.thumbnail.desc_html') + + %hr/ + .fields-group = f.input :timeline_preview, as: :boolean, wrapper: :with_label, label: t('admin.settings.timeline_preview.title'), hint: t('admin.settings.timeline_preview.desc_html') diff --git a/config/locales/en.yml b/config/locales/en.yml index 0cd57a64f..8b5f52b02 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -195,6 +195,9 @@ en: desc_html: You can write your own privacy policy, terms of service or other legalese. You can use HTML tags title: Custom terms of service site_title: Instance name + thumbnail: + desc_html: Used for previews via OpenGraph and API. 1200x630px recommended + title: Instance thumbnail timeline_preview: desc_html: Display public timeline on landing page title: Timeline preview diff --git a/db/migrate/20170913000752_create_site_uploads.rb b/db/migrate/20170913000752_create_site_uploads.rb new file mode 100644 index 000000000..2246e48cd --- /dev/null +++ b/db/migrate/20170913000752_create_site_uploads.rb @@ -0,0 +1,10 @@ +class CreateSiteUploads < ActiveRecord::Migration[5.1] + def change + create_table :site_uploads do |t| + t.string :var, default: '', null: false, index: { unique: true } + t.attachment :file + t.json :meta + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index d8af0a1f8..f2ca2af69 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20170905165803) do +ActiveRecord::Schema.define(version: 20170913000752) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -288,6 +288,18 @@ ActiveRecord::Schema.define(version: 20170905165803) do t.index ["thing_type", "thing_id", "var"], name: "index_settings_on_thing_type_and_thing_id_and_var", unique: true end + create_table "site_uploads", force: :cascade do |t| + t.string "var", default: "", null: false + t.string "file_file_name" + t.string "file_content_type" + t.integer "file_file_size" + t.datetime "file_updated_at" + t.json "meta" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["var"], name: "index_site_uploads_on_var", unique: true + end + create_table "status_pins", force: :cascade do |t| t.bigint "account_id", null: false t.bigint "status_id", null: false diff --git a/spec/fabricators/site_upload_fabricator.rb b/spec/fabricators/site_upload_fabricator.rb new file mode 100644 index 000000000..8f4e43ac9 --- /dev/null +++ b/spec/fabricators/site_upload_fabricator.rb @@ -0,0 +1,3 @@ +Fabricator(:site_upload) do + +end diff --git a/spec/models/site_upload_spec.rb b/spec/models/site_upload_spec.rb new file mode 100644 index 000000000..8745d54b8 --- /dev/null +++ b/spec/models/site_upload_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe SiteUpload, type: :model do + +end diff --git a/spec/views/about/show.html.haml_spec.rb b/spec/views/about/show.html.haml_spec.rb index aa151dd27..724643cbc 100644 --- a/spec/views/about/show.html.haml_spec.rb +++ b/spec/views/about/show.html.haml_spec.rb @@ -15,15 +15,16 @@ describe 'about/show.html.haml', without_verify_partial_doubles: true do version_number: '1.0', source_url: 'https://github.com/tootsuite/mastodon', open_registrations: false, + thumbnail: nil, closed_registrations_message: 'yes') assign(:instance_presenter, instance_presenter) render header_tags = view.content_for(:header_tags) - expect(header_tags).to match(%r{}) - expect(header_tags).to match(%r{}) - expect(header_tags).to match(%r{}) - expect(header_tags).to match(%r{}) + expect(header_tags).to match(%r{}) + expect(header_tags).to match(%r{}) + expect(header_tags).to match(%r{}) + expect(header_tags).to match(%r{}) end end -- cgit From 2bbf987a0a352a36ef0cc7f06fe366b60593e89c Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Thu, 14 Sep 2017 03:39:10 +0200 Subject: Redesign video player (#4911) * Redesign video player * Use new video player on static public pages too * Use media gallery component on static public pages too * Pause video when hiding it * Full-screen sizing on WebKit * Add aria labels to video player buttons * Display link card on public status page * Fix fullscreen from modal sizing issue * Remove contain: strict property to fix fullscreen from columns --- app/javascript/mastodon/components/status.js | 19 +- .../mastodon/containers/card_container.js | 18 ++ .../mastodon/containers/media_gallery_container.js | 34 +++ .../mastodon/containers/video_container.js | 26 ++ .../mastodon/features/status/components/card.js | 10 +- .../features/status/components/detailed_status.js | 19 +- .../mastodon/features/ui/components/video_modal.js | 22 +- .../mastodon/features/ui/util/async-components.js | 4 + app/javascript/mastodon/features/video/index.js | 304 +++++++++++++++++++++ app/javascript/mastodon/locales/ar.json | 11 + app/javascript/mastodon/locales/bg.json | 11 + app/javascript/mastodon/locales/ca.json | 11 + app/javascript/mastodon/locales/de.json | 11 + .../mastodon/locales/defaultMessages.json | 62 +++++ app/javascript/mastodon/locales/en.json | 13 +- app/javascript/mastodon/locales/eo.json | 11 + app/javascript/mastodon/locales/es.json | 11 + app/javascript/mastodon/locales/fa.json | 13 +- app/javascript/mastodon/locales/fi.json | 11 + app/javascript/mastodon/locales/fr.json | 13 +- app/javascript/mastodon/locales/he.json | 11 + app/javascript/mastodon/locales/hr.json | 12 +- app/javascript/mastodon/locales/hu.json | 11 + app/javascript/mastodon/locales/id.json | 11 + app/javascript/mastodon/locales/io.json | 11 + app/javascript/mastodon/locales/it.json | 11 + app/javascript/mastodon/locales/ja.json | 13 +- app/javascript/mastodon/locales/ko.json | 13 +- app/javascript/mastodon/locales/nl.json | 11 + app/javascript/mastodon/locales/no.json | 11 + app/javascript/mastodon/locales/oc.json | 13 +- app/javascript/mastodon/locales/pl.json | 9 + app/javascript/mastodon/locales/pt-BR.json | 13 +- app/javascript/mastodon/locales/pt.json | 11 + app/javascript/mastodon/locales/ru.json | 11 + app/javascript/mastodon/locales/th.json | 11 + app/javascript/mastodon/locales/tr.json | 11 + app/javascript/mastodon/locales/uk.json | 11 + app/javascript/mastodon/locales/zh-CN.json | 11 + app/javascript/mastodon/locales/zh-HK.json | 11 + app/javascript/mastodon/locales/zh-TW.json | 11 + app/javascript/packs/public.js | 30 +- app/javascript/styles/components.scss | 197 ++++++++++++- app/javascript/styles/stream_entries.scss | 150 +--------- .../stream_entries/_detailed_status.html.haml | 15 +- app/views/stream_entries/_simple_status.html.haml | 17 +- 46 files changed, 1064 insertions(+), 217 deletions(-) create mode 100644 app/javascript/mastodon/containers/card_container.js create mode 100644 app/javascript/mastodon/containers/media_gallery_container.js create mode 100644 app/javascript/mastodon/containers/video_container.js create mode 100644 app/javascript/mastodon/features/video/index.js (limited to 'app/javascript') diff --git a/app/javascript/mastodon/components/status.js b/app/javascript/mastodon/components/status.js index 30a0c10cb..82359156d 100644 --- a/app/javascript/mastodon/components/status.js +++ b/app/javascript/mastodon/components/status.js @@ -9,7 +9,7 @@ import StatusContent from './status_content'; import StatusActionBar from './status_action_bar'; import { FormattedMessage } from 'react-intl'; import ImmutablePureComponent from 'react-immutable-pure-component'; -import { MediaGallery, VideoPlayer } from '../features/ui/util/async-components'; +import { MediaGallery, Video } from '../features/ui/util/async-components'; // We use the component (and not the container) since we do not want // to use the progress bar to show download progress @@ -88,6 +88,10 @@ export default class Status extends ImmutablePureComponent { return
; } + handleOpenVideo = startTime => { + this.props.onOpenVideo(this.props.status.getIn(['media_attachments', 0]), startTime); + } + render () { let media = null; let statusAvatar; @@ -127,9 +131,18 @@ export default class Status extends ImmutablePureComponent { if (status.get('media_attachments').some(item => item.get('type') === 'unknown')) { } else if (status.getIn(['media_attachments', 0, 'type']) === 'video') { + const video = status.getIn(['media_attachments', 0]); + media = ( - - {Component => } + + {Component => } ); } else { diff --git a/app/javascript/mastodon/containers/card_container.js b/app/javascript/mastodon/containers/card_container.js new file mode 100644 index 000000000..11b9f88d4 --- /dev/null +++ b/app/javascript/mastodon/containers/card_container.js @@ -0,0 +1,18 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import Card from '../features/status/components/card'; +import { fromJS } from 'immutable'; + +export default class CardContainer extends React.PureComponent { + + static propTypes = { + locale: PropTypes.string, + card: PropTypes.array.isRequired, + }; + + render () { + const { card, ...props } = this.props; + return ; + } + +} diff --git a/app/javascript/mastodon/containers/media_gallery_container.js b/app/javascript/mastodon/containers/media_gallery_container.js new file mode 100644 index 000000000..812c3d4e5 --- /dev/null +++ b/app/javascript/mastodon/containers/media_gallery_container.js @@ -0,0 +1,34 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { IntlProvider, addLocaleData } from 'react-intl'; +import { getLocale } from '../locales'; +import MediaGallery from '../components/media_gallery'; +import { fromJS } from 'immutable'; + +const { localeData, messages } = getLocale(); +addLocaleData(localeData); + +export default class MediaGalleryContainer extends React.PureComponent { + + static propTypes = { + locale: PropTypes.string.isRequired, + media: PropTypes.array.isRequired, + }; + + handleOpenMedia = () => {} + + render () { + const { locale, media, ...props } = this.props; + + return ( + + + + ); + } + +} diff --git a/app/javascript/mastodon/containers/video_container.js b/app/javascript/mastodon/containers/video_container.js new file mode 100644 index 000000000..2fd353096 --- /dev/null +++ b/app/javascript/mastodon/containers/video_container.js @@ -0,0 +1,26 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { IntlProvider, addLocaleData } from 'react-intl'; +import { getLocale } from '../locales'; +import Video from '../features/video'; + +const { localeData, messages } = getLocale(); +addLocaleData(localeData); + +export default class VideoContainer extends React.PureComponent { + + static propTypes = { + locale: PropTypes.string.isRequired, + }; + + render () { + const { locale, ...props } = this.props; + + return ( + + + ); + } + +} diff --git a/app/javascript/mastodon/features/status/components/card.js b/app/javascript/mastodon/features/status/components/card.js index 6b13e15cc..41c4300d3 100644 --- a/app/javascript/mastodon/features/status/components/card.js +++ b/app/javascript/mastodon/features/status/components/card.js @@ -1,4 +1,5 @@ import React from 'react'; +import PropTypes from 'prop-types'; import ImmutablePropTypes from 'react-immutable-proptypes'; import punycode from 'punycode'; import classnames from 'classnames'; @@ -22,10 +23,15 @@ export default class Card extends React.PureComponent { static propTypes = { card: ImmutablePropTypes.map, + maxDescription: PropTypes.number, + }; + + static defaultProps = { + maxDescription: 50, }; renderLink () { - const { card } = this.props; + const { card, maxDescription } = this.props; let image = ''; let provider = card.get('provider_name'); @@ -52,7 +58,7 @@ export default class Card extends React.PureComponent {
{card.get('title')} -

{(card.get('description') || '').substring(0, 50)}

+

{(card.get('description') || '').substring(0, maxDescription)}

{provider}
diff --git a/app/javascript/mastodon/features/status/components/detailed_status.js b/app/javascript/mastodon/features/status/components/detailed_status.js index 940a2699b..b11b41780 100644 --- a/app/javascript/mastodon/features/status/components/detailed_status.js +++ b/app/javascript/mastodon/features/status/components/detailed_status.js @@ -5,12 +5,12 @@ import Avatar from '../../../components/avatar'; import DisplayName from '../../../components/display_name'; import StatusContent from '../../../components/status_content'; import MediaGallery from '../../../components/media_gallery'; -import VideoPlayer from '../../../components/video_player'; import AttachmentList from '../../../components/attachment_list'; import Link from 'react-router-dom/Link'; import { FormattedDate, FormattedNumber } from 'react-intl'; import CardContainer from '../containers/card_container'; import ImmutablePureComponent from 'react-immutable-pure-component'; +import Video from '../../video'; export default class DetailedStatus extends ImmutablePureComponent { @@ -34,6 +34,10 @@ export default class DetailedStatus extends ImmutablePureComponent { e.stopPropagation(); } + handleOpenVideo = startTime => { + this.props.onOpenVideo(this.props.status.getIn(['media_attachments', 0]), startTime); + } + render () { const status = this.props.status.get('reblog') ? this.props.status.get('reblog') : this.props.status; @@ -44,7 +48,18 @@ export default class DetailedStatus extends ImmutablePureComponent { if (status.get('media_attachments').some(item => item.get('type') === 'unknown')) { media = ; } else if (status.getIn(['media_attachments', 0, 'type']) === 'video') { - media = ; + const video = status.getIn(['media_attachments', 0]); + + media = ( +