From 0ee34f8590df6e2fce3fecf5b484af6eaa6f8524 Mon Sep 17 00:00:00 2001 From: cmrd Senya Date: Mon, 11 Jul 2016 15:11:15 +0000 Subject: [PATCH 001/318] Remove the photo comment spec This functionality is not something we support and it doesn't look it will be reintroduced soon. see discussion https://github.com/diaspora/diaspora/pull/6818#discussion_r70227392 --- spec/models/photo_spec.rb | 6 ------ 1 file changed, 6 deletions(-) diff --git a/spec/models/photo_spec.rb b/spec/models/photo_spec.rb index 1d3ee559d..470f95a58 100644 --- a/spec/models/photo_spec.rb +++ b/spec/models/photo_spec.rb @@ -203,12 +203,6 @@ describe Photo, :type => :model do end end - context "commenting" do - it "accepts comments if there is no parent status message" do - expect{ @user.comment!(@photo, "big willy style") }.to change(@photo.comments, :count).by(1) - end - end - describe '#queue_processing_job' do it 'should queue a job to process the images' do expect(Workers::ProcessPhoto).to receive(:perform_async).with(@photo.id) From ef5751b808f7aa47b1ad10790e1c30894ae67b43 Mon Sep 17 00:00:00 2001 From: cmrd Senya Date: Wed, 14 Sep 2016 20:30:36 +0300 Subject: [PATCH 002/318] Refactor mail workers to use common base Introduce Workers::Mail::NotifierBase to be a base for all appropriate mail workers to reduce code duplication --- .../notification_mailers/started_sharing.rb | 4 +- app/mailers/notifier.rb | 40 ++----------------- app/workers/mail/also_commented.rb | 9 +---- app/workers/mail/comment_on_post.rb | 7 +--- app/workers/mail/confirm_email.rb | 7 +--- app/workers/mail/csrf_token_fail.rb | 7 +--- app/workers/mail/liked.rb | 8 ++-- app/workers/mail/mentioned.rb | 7 +--- app/workers/mail/notifier_base.rb | 11 +++++ app/workers/mail/private_message.rb | 7 +--- app/workers/mail/reshared.rb | 7 +--- app/workers/mail/started_sharing.rb | 7 +--- spec/mailers/notifier_spec.rb | 26 ++++++------ spec/workers/mail/csrf_token_fail_spec.rb | 4 +- spec/workers/mail/liked_spec.rb | 9 +++-- spec/workers/mail/mentioned_spec.rb | 6 +-- spec/workers/mail/private_message_spec.rb | 9 +++-- spec/workers/mail/reshared_spec.rb | 7 ++-- 18 files changed, 59 insertions(+), 123 deletions(-) create mode 100644 app/workers/mail/notifier_base.rb diff --git a/app/mailers/notification_mailers/started_sharing.rb b/app/mailers/notification_mailers/started_sharing.rb index e02c50e43..bc4a8dd44 100644 --- a/app/mailers/notification_mailers/started_sharing.rb +++ b/app/mailers/notification_mailers/started_sharing.rb @@ -1,7 +1,7 @@ module NotificationMailers class StartedSharing < NotificationMailers::Base - def set_headers - @headers[:subject] = I18n.t('notifier.started_sharing.subject', :name => @sender.name) + def set_headers(*_args) # rubocop:disable Style/AccessorMethodName + @headers[:subject] = I18n.t("notifier.started_sharing.subject", name: @sender.name) end end end diff --git a/app/mailers/notifier.rb b/app/mailers/notifier.rb index 80630ebe2..69fdfe11b 100644 --- a/app/mailers/notifier.rb +++ b/app/mailers/notifier.rb @@ -55,54 +55,20 @@ class Notifier < ActionMailer::Base end end - def started_sharing(recipient_id, sender_id) - send_notification(:started_sharing, recipient_id, sender_id) - end - - def liked(recipient_id, sender_id, like_id) - send_notification(:liked, recipient_id, sender_id, like_id) - end - - def reshared(recipient_id, sender_id, reshare_id) - send_notification(:reshared, recipient_id, sender_id, reshare_id) - end - - def mentioned(recipient_id, sender_id, target_id) - send_notification(:mentioned, recipient_id, sender_id, target_id) - end - - def comment_on_post(recipient_id, sender_id, comment_id) - send_notification(:comment_on_post, recipient_id, sender_id, comment_id) - end - - def also_commented(recipient_id, sender_id, comment_id) - send_notification(:also_commented, recipient_id, sender_id, comment_id) - end - - def private_message(recipient_id, sender_id, message_id) - send_notification(:private_message, recipient_id, sender_id, message_id) - end - - def confirm_email(recipient_id) - send_notification(:confirm_email, recipient_id) - end - - def csrf_token_fail(recipient_id) - send_notification(:csrf_token_fail, recipient_id) - end - - private def send_notification(type, *args) @notification = NotificationMailers.const_get(type.to_s.camelize).new(*args) with_recipient_locale do mail(@notification.headers) do |format| + self.action_name = type format.text format.html end end end + private + def with_recipient_locale(&block) I18n.with_locale(@notification.recipient.language, &block) end diff --git a/app/workers/mail/also_commented.rb b/app/workers/mail/also_commented.rb index 52026e737..05a1ef105 100644 --- a/app/workers/mail/also_commented.rb +++ b/app/workers/mail/also_commented.rb @@ -1,13 +1,6 @@ module Workers module Mail - class AlsoCommented < Base - sidekiq_options queue: :low - - def perform(recipient_id, sender_id, comment_id) - if email = Notifier.also_commented(recipient_id, sender_id, comment_id) - email.deliver_now - end - end + class AlsoCommented < NotifierBase end end end diff --git a/app/workers/mail/comment_on_post.rb b/app/workers/mail/comment_on_post.rb index 070eb8e33..168b75237 100644 --- a/app/workers/mail/comment_on_post.rb +++ b/app/workers/mail/comment_on_post.rb @@ -1,11 +1,6 @@ module Workers module Mail - class CommentOnPost < Base - sidekiq_options queue: :low - - def perform(recipient_id, sender_id, comment_id) - Notifier.comment_on_post(recipient_id, sender_id, comment_id).deliver_now - end + class CommentOnPost < NotifierBase end end end diff --git a/app/workers/mail/confirm_email.rb b/app/workers/mail/confirm_email.rb index 252f030c6..efa9fb64e 100644 --- a/app/workers/mail/confirm_email.rb +++ b/app/workers/mail/confirm_email.rb @@ -1,11 +1,6 @@ module Workers module Mail - class ConfirmEmail < Base - sidekiq_options queue: :low - - def perform(user_id) - Notifier.confirm_email(user_id).deliver_now - end + class ConfirmEmail < NotifierBase end end end diff --git a/app/workers/mail/csrf_token_fail.rb b/app/workers/mail/csrf_token_fail.rb index a3372b322..f9679b8c3 100644 --- a/app/workers/mail/csrf_token_fail.rb +++ b/app/workers/mail/csrf_token_fail.rb @@ -1,11 +1,6 @@ module Workers module Mail - class CsrfTokenFail < Base - sidekiq_options queue: :low - - def perform(user_id) - Notifier.csrf_token_fail(user_id).deliver_now - end + class CsrfTokenFail < NotifierBase end end end diff --git a/app/workers/mail/liked.rb b/app/workers/mail/liked.rb index 595af3e39..16471a542 100644 --- a/app/workers/mail/liked.rb +++ b/app/workers/mail/liked.rb @@ -1,10 +1,8 @@ module Workers module Mail - class Liked < Base - sidekiq_options queue: :low - - def perform(recipient_id, sender_id, like_id) - Notifier.liked(recipient_id, sender_id, like_id).deliver_now + class Liked < NotifierBase + def perform(*args) + super rescue ActiveRecord::RecordNotFound => e logger.warn("failed to send liked notification mail: #{e.message}") raise e unless e.message.start_with?("Couldn't find Like with") diff --git a/app/workers/mail/mentioned.rb b/app/workers/mail/mentioned.rb index a32f30f11..4ae477d54 100644 --- a/app/workers/mail/mentioned.rb +++ b/app/workers/mail/mentioned.rb @@ -5,12 +5,7 @@ module Workers module Mail - class Mentioned < Base - sidekiq_options queue: :low - - def perform(recipient_id, actor_id, target_id) - Notifier.mentioned( recipient_id, actor_id, target_id).deliver_now - end + class Mentioned < NotifierBase end end end diff --git a/app/workers/mail/notifier_base.rb b/app/workers/mail/notifier_base.rb new file mode 100644 index 000000000..72cb4acb8 --- /dev/null +++ b/app/workers/mail/notifier_base.rb @@ -0,0 +1,11 @@ +module Workers + module Mail + class NotifierBase < Base + sidekiq_options queue: :low + + def perform(*args) + Notifier.send_notification(self.class.name.gsub("Workers::Mail::", "").underscore, *args).deliver_now + end + end + end +end diff --git a/app/workers/mail/private_message.rb b/app/workers/mail/private_message.rb index d24ce0296..b851bfed0 100644 --- a/app/workers/mail/private_message.rb +++ b/app/workers/mail/private_message.rb @@ -5,12 +5,7 @@ module Workers module Mail - class PrivateMessage < Base - sidekiq_options queue: :low - - def perform(recipient_id, actor_id, target_id) - Notifier.private_message( recipient_id, actor_id, target_id).deliver_now - end + class PrivateMessage < NotifierBase end end end diff --git a/app/workers/mail/reshared.rb b/app/workers/mail/reshared.rb index 1144147ad..7e434788d 100644 --- a/app/workers/mail/reshared.rb +++ b/app/workers/mail/reshared.rb @@ -1,11 +1,6 @@ module Workers module Mail - class Reshared < Base - sidekiq_options queue: :low - - def perform(recipient_id, sender_id, reshare_id) - Notifier.reshared(recipient_id, sender_id, reshare_id).deliver_now - end + class Reshared < NotifierBase end end end diff --git a/app/workers/mail/started_sharing.rb b/app/workers/mail/started_sharing.rb index 3618d1527..ef101060c 100644 --- a/app/workers/mail/started_sharing.rb +++ b/app/workers/mail/started_sharing.rb @@ -5,12 +5,7 @@ module Workers module Mail - class StartedSharing < Base - sidekiq_options queue: :low - - def perform(recipient_id, sender_id, target_id) - Notifier.started_sharing(recipient_id, sender_id).deliver_now - end + class StartedSharing < NotifierBase end end end diff --git a/spec/mailers/notifier_spec.rb b/spec/mailers/notifier_spec.rb index 7593bba03..13a05a27e 100644 --- a/spec/mailers/notifier_spec.rb +++ b/spec/mailers/notifier_spec.rb @@ -64,7 +64,7 @@ describe Notifier, type: :mailer do end describe ".started_sharing" do - let!(:request_mail) { Notifier.started_sharing(bob.id, person.id) } + let!(:request_mail) { Notifier.send_notification("started_sharing", bob.id, person.id) } it "goes to the right person" do expect(request_mail.to).to eq([bob.email]) @@ -136,7 +136,7 @@ describe Notifier, type: :mailer do before do @post = FactoryGirl.create(:status_message, author: alice.person, public: true) @like = @post.likes.create!(author: bob.person) - @mail = Notifier.liked(alice.id, @like.author.id, @like.id) + @mail = Notifier.send_notification("liked", alice.id, @like.author.id, @like.id) end it "TO: goes to the right person" do @@ -158,7 +158,7 @@ describe Notifier, type: :mailer do it "can handle a reshare" do reshare = FactoryGirl.create(:reshare) like = reshare.likes.create!(author: bob.person) - Notifier.liked(alice.id, like.author.id, like.id) + Notifier.send_notification("liked", alice.id, like.author.id, like.id) end end @@ -166,7 +166,7 @@ describe Notifier, type: :mailer do before do @post = FactoryGirl.create(:status_message, author: alice.person, public: true) @reshare = FactoryGirl.create(:reshare, root: @post, author: bob.person) - @mail = Notifier.reshared(alice.id, @reshare.author.id, @reshare.id) + @mail = Notifier.send_notification("reshared", alice.id, @reshare.author.id, @reshare.id) end it "TO: goes to the right person" do @@ -205,7 +205,7 @@ describe Notifier, type: :mailer do @cnv = Conversation.create(@create_hash) - @mail = Notifier.private_message(bob.id, @cnv.author.id, @cnv.messages.first.id) + @mail = Notifier.send_notification("private_message", bob.id, @cnv.author.id, @cnv.messages.first.id) end it "TO: goes to the right person" do @@ -248,7 +248,7 @@ describe Notifier, type: :mailer do let(:comment) { eve.comment!(commented_post, "Totally is") } describe ".comment_on_post" do - let(:comment_mail) { Notifier.comment_on_post(bob.id, person.id, comment.id).deliver_now } + let(:comment_mail) { Notifier.send_notification("comment_on_post", bob.id, person.id, comment.id).deliver_now } it "TO: goes to the right person" do expect(comment_mail.to).to eq([bob.email]) @@ -289,7 +289,7 @@ describe Notifier, type: :mailer do end describe ".also_commented" do - let(:comment_mail) { Notifier.also_commented(bob.id, person.id, comment.id) } + let(:comment_mail) { Notifier.send_notification("also_commented", bob.id, person.id, comment.id) } it "TO: goes to the right person" do expect(comment_mail.to).to eq([bob.email]) @@ -344,7 +344,7 @@ describe Notifier, type: :mailer do let(:comment) { bob.comment!(limited_post, "Totally is") } describe ".also_commented" do - let(:mail) { Notifier.also_commented(alice.id, bob.person.id, comment.id) } + let(:mail) { Notifier.send_notification("also_commented", alice.id, bob.person.id, comment.id) } it "TO: goes to the right person" do expect(mail.to).to eq([alice.email]) @@ -369,7 +369,7 @@ describe Notifier, type: :mailer do describe ".comment_on_post" do let(:comment) { bob.comment!(limited_post, "Totally is") } - let(:mail) { Notifier.comment_on_post(alice.id, bob.person.id, comment.id) } + let(:mail) { Notifier.send_notification("comment_on_post", alice.id, bob.person.id, comment.id) } it "TO: goes to the right person" do expect(mail.to).to eq([alice.email]) @@ -400,7 +400,7 @@ describe Notifier, type: :mailer do describe ".liked" do let(:like) { bob.like!(limited_post) } - let(:mail) { Notifier.liked(alice.id, bob.person.id, like.id) } + let(:mail) { Notifier.send_notification("liked", alice.id, bob.person.id, like.id) } it "TO: goes to the right person" do expect(mail.to).to eq([alice.email]) @@ -436,7 +436,7 @@ describe Notifier, type: :mailer do describe ".confirm_email" do before do bob.update_attribute(:unconfirmed_email, "my@newemail.com") - @confirm_email = Notifier.confirm_email(bob.id) + @confirm_email = Notifier.send_notification("confirm_email", bob.id) end it "goes to the right person" do @@ -461,7 +461,7 @@ describe Notifier, type: :mailer do end describe ".csrf_token_fail" do - let(:email) { Notifier.csrf_token_fail(alice.id) } + let(:email) { Notifier.send_notification("csrf_token_fail", alice.id) } it "goes to the right person" do expect(email.to).to eq([alice.email]) @@ -495,7 +495,7 @@ describe Notifier, type: :mailer do it "handles idn addresses" do bob.update_attribute(:email, "ŧoo@ŧexample.com") expect { - Notifier.started_sharing(bob.id, person.id) + Notifier.send_notification("started_sharing", bob.id, person.id) }.to_not raise_error end end diff --git a/spec/workers/mail/csrf_token_fail_spec.rb b/spec/workers/mail/csrf_token_fail_spec.rb index e57292048..8c94f8663 100644 --- a/spec/workers/mail/csrf_token_fail_spec.rb +++ b/spec/workers/mail/csrf_token_fail_spec.rb @@ -3,12 +3,12 @@ # the COPYRIGHT file. describe Workers::Mail::CsrfTokenFail do - describe "#perfom" do + describe "#perform" do it "should call .deliver on the notifier object" do user = alice mail_double = double expect(mail_double).to receive(:deliver_now) - expect(Notifier).to receive(:csrf_token_fail).with(user.id).and_return(mail_double) + expect(Notifier).to receive(:send_notification).with("csrf_token_fail", user.id).and_return(mail_double) Workers::Mail::CsrfTokenFail.new.perform(user.id) end diff --git a/spec/workers/mail/liked_spec.rb b/spec/workers/mail/liked_spec.rb index 8bb31ef0d..7ab94586a 100644 --- a/spec/workers/mail/liked_spec.rb +++ b/spec/workers/mail/liked_spec.rb @@ -1,12 +1,13 @@ describe Workers::Mail::Liked do - describe "#perfom" do + describe "#perform" do it "should call .deliver_now on the notifier object" do sm = FactoryGirl.build(:status_message, author: bob.person, public: true) like = FactoryGirl.build(:like, author: alice.person, target: sm) mail_double = double expect(mail_double).to receive(:deliver_now) - expect(Notifier).to receive(:liked).with(bob.id, like.author.id, like.id).and_return(mail_double) + expect(Notifier).to receive(:send_notification) + .with("liked", bob.id, like.author.id, like.id).and_return(mail_double) Workers::Mail::Liked.new.perform(bob.id, like.author.id, like.id) end @@ -15,7 +16,7 @@ describe Workers::Mail::Liked do sm = FactoryGirl.build(:status_message, author: bob.person, public: true) like = FactoryGirl.build(:like, author: alice.person, target: sm) - expect(Notifier).to receive(:liked).with(bob.id, like.author.id, like.id) + expect(Notifier).to receive(:send_notification).with("liked", bob.id, like.author.id, like.id) .and_raise(ActiveRecord::RecordNotFound.new("Couldn't find Like with 'id'=42")) Workers::Mail::Liked.new.perform(bob.id, like.author.id, like.id) @@ -25,7 +26,7 @@ describe Workers::Mail::Liked do sm = FactoryGirl.build(:status_message, author: bob.person, public: true) like = FactoryGirl.build(:like, author: alice.person, target: sm) - expect(Notifier).to receive(:liked).with(bob.id, like.author.id, like.id) + expect(Notifier).to receive(:send_notification).with("liked", bob.id, like.author.id, like.id) .and_raise(ActiveRecord::RecordNotFound.new("Couldn't find Person with 'id'=42")) expect { diff --git a/spec/workers/mail/mentioned_spec.rb b/spec/workers/mail/mentioned_spec.rb index e63a9dfe5..5d8d76cd7 100644 --- a/spec/workers/mail/mentioned_spec.rb +++ b/spec/workers/mail/mentioned_spec.rb @@ -3,15 +3,15 @@ # the COPYRIGHT file. describe Workers::Mail::Mentioned do - describe '#perfom' do - it 'should call .deliver on the notifier object' do + describe "#perform" do + it "should call .deliver on the notifier object" do user = alice sm = FactoryGirl.build(:status_message) m = Mention.new(:person => user.person, :post=> sm) mail_double = double() expect(mail_double).to receive(:deliver_now) - expect(Notifier).to receive(:mentioned).with(user.id, sm.author.id, m.id).and_return(mail_double) + expect(Notifier).to receive(:send_notification).with("mentioned", user.id, sm.author.id, m.id).and_return(mail_double) Workers::Mail::Mentioned.new.perform(user.id, sm.author.id, m.id) end diff --git a/spec/workers/mail/private_message_spec.rb b/spec/workers/mail/private_message_spec.rb index 8722cd211..7b8401986 100644 --- a/spec/workers/mail/private_message_spec.rb +++ b/spec/workers/mail/private_message_spec.rb @@ -3,8 +3,8 @@ # the COPYRIGHT file. describe Workers::Mail::PrivateMessage do - describe '#perfom_delegate' do - it 'should call .deliver on the notifier object' do + describe "#perform" do + it "should call .deliver on the notifier object" do user1 = alice user2 = bob participant_ids = [user1.contacts.first.person.id, user1.person.id] @@ -17,9 +17,10 @@ describe Workers::Mail::PrivateMessage do mail_double = double() expect(mail_double).to receive(:deliver_now) - expect(Notifier).to receive(:mentioned).with(user2.id, user1.person.id, message.id).and_return(mail_double) + expect(Notifier).to receive(:send_notification) + .with("private_message", user2.id, user1.person.id, message.id).and_return(mail_double) - Workers::Mail::Mentioned.new.perform(user2.id, user1.person.id, message.id) + Workers::Mail::PrivateMessage.new.perform(user2.id, user1.person.id, message.id) end end end diff --git a/spec/workers/mail/reshared_spec.rb b/spec/workers/mail/reshared_spec.rb index fea1eb54d..d1ebd9908 100644 --- a/spec/workers/mail/reshared_spec.rb +++ b/spec/workers/mail/reshared_spec.rb @@ -3,14 +3,15 @@ # the COPYRIGHT file. describe Workers::Mail::Reshared do - describe '#perfom' do - it 'should call .deliver on the notifier object' do + describe "#perform" do + it "should call .deliver on the notifier object" do sm = FactoryGirl.build(:status_message, :author => bob.person, :public => true) reshare = FactoryGirl.build(:reshare, :author => alice.person, :root=> sm) mail_double = double() expect(mail_double).to receive(:deliver_now) - expect(Notifier).to receive(:reshared).with(bob.id, reshare.author.id, reshare.id).and_return(mail_double) + expect(Notifier).to receive(:send_notification) + .with("reshared", bob.id, reshare.author.id, reshare.id).and_return(mail_double) Workers::Mail::Reshared.new.perform(bob.id, reshare.author.id, reshare.id) end From 33ad411bbd0d48652d161a60627657f75d467292 Mon Sep 17 00:00:00 2001 From: cmrd Senya Date: Mon, 22 Aug 2016 15:12:35 +0300 Subject: [PATCH 003/318] Mentions in comments backend changes --- app/controllers/notifications_controller.rb | 21 +- app/controllers/status_messages_controller.rb | 5 +- app/controllers/users_controller.rb | 11 +- app/helpers/notifications_helper.rb | 56 +-- app/mailers/notification_mailers/mentioned.rb | 2 +- .../mentioned_in_comment.rb | 11 + app/models/comment.rb | 19 +- app/models/mention.rb | 8 +- app/models/notification.rb | 11 - app/models/notifications/also_commented.rb | 8 +- app/models/notifications/comment_on_post.rb | 7 +- app/models/notifications/commented.rb | 15 + app/models/notifications/mentioned.rb | 35 +- .../notifications/mentioned_in_comment.rb | 38 ++ app/models/notifications/mentioned_in_post.rb | 22 ++ app/models/post.rb | 6 +- app/models/status_message.rb | 49 +-- app/models/user.rb | 1 + app/models/user_preference.rb | 15 +- app/presenters/person_presenter.rb | 4 + app/services/notification_service.rb | 4 +- app/services/post_service.rb | 18 +- .../status_message_creation_service.rb | 12 +- app/views/notifications/_notification.haml | 4 +- .../notifications/_notification.mobile.haml | 3 +- app/views/notifications/index.html.haml | 2 +- app/views/notifier/mentioned.markerb | 2 +- .../notifier/mentioned_in_comment.markerb | 9 + app/views/users/_edit.haml | 5 + app/workers/mail/mentioned_in_comment.rb | 6 + config/locales/diaspora/en.yml | 15 +- .../20161107100840_polymorphic_mentions.rb | 38 ++ db/schema.rb | 11 +- features/desktop/change_settings.feature | 4 + features/desktop/notifications.feature | 20 + features/step_definitions/comment_steps.rb | 6 + features/step_definitions/custom_web_steps.rb | 2 +- .../step_definitions/notifications_steps.rb | 2 +- lib/diaspora/mentionable.rb | 34 +- lib/diaspora/mentions_container.rb | 38 ++ lib/diaspora/message_renderer.rb | 2 +- .../notifications_controller_spec.rb | 13 +- spec/controllers/users_controller_spec.rb | 30 +- spec/factories.rb | 38 +- spec/helper_methods.rb | 20 +- spec/helpers/notifications_helper_spec.rb | 31 ++ spec/integration/mentioning_spec.rb | 366 ++++++++++++++++-- spec/lib/diaspora/federation/receive_spec.rb | 20 +- spec/lib/diaspora/mentionable_spec.rb | 21 +- spec/mailers/notifier_spec.rb | 36 +- spec/models/comment_spec.rb | 51 +++ spec/models/mention_spec.rb | 4 +- .../notifications/mentioned_in_post_spec.rb | 72 ++++ spec/models/notifications/mentioned_spec.rb | 99 ++--- spec/models/status_message_spec.rb | 72 +--- spec/presenters/post_presenter_spec.rb | 4 +- spec/services/notification_service_spec.rb | 74 ++++ spec/services/post_service_spec.rb | 14 +- .../status_message_creation_service_spec.rb | 48 +-- spec/shared_behaviors/mentions_container.rb | 44 +++ spec/workers/mail/mentioned_spec.rb | 5 +- 61 files changed, 1192 insertions(+), 451 deletions(-) create mode 100644 app/mailers/notification_mailers/mentioned_in_comment.rb create mode 100644 app/models/notifications/commented.rb create mode 100644 app/models/notifications/mentioned_in_comment.rb create mode 100644 app/models/notifications/mentioned_in_post.rb create mode 100644 app/views/notifier/mentioned_in_comment.markerb create mode 100644 app/workers/mail/mentioned_in_comment.rb create mode 100644 db/migrate/20161107100840_polymorphic_mentions.rb create mode 100644 lib/diaspora/mentions_container.rb create mode 100644 spec/models/notifications/mentioned_in_post_spec.rb create mode 100644 spec/services/notification_service_spec.rb create mode 100644 spec/shared_behaviors/mentions_container.rb diff --git a/app/controllers/notifications_controller.rb b/app/controllers/notifications_controller.rb index aae218b69..0d1714ea0 100644 --- a/app/controllers/notifications_controller.rb +++ b/app/controllers/notifications_controller.rb @@ -23,8 +23,8 @@ class NotificationsController < ApplicationController def index conditions = {:recipient_id => current_user.id} - if params[:type] && Notification.types.has_key?(params[:type]) - conditions[:type] = Notification.types[params[:type]] + if params[:type] && types.has_key?(params[:type]) + conditions[:type] = types[params[:type]] end if params[:show] == "unread" then conditions[:unread] = true end page = params[:page] || 1 @@ -44,7 +44,7 @@ class NotificationsController < ApplicationController @grouped_unread_notification_counts = {} - Notification.types.each_with_object(current_user.unread_notifications.group_by(&:type)) {|(name, type), notifications| + types.each_with_object(current_user.unread_notifications.group_by(&:type)) {|(name, type), notifications| @grouped_unread_notification_counts[name] = notifications.has_key?(type) ? notifications[type].count : 0 } @@ -65,7 +65,7 @@ class NotificationsController < ApplicationController end def read_all - current_type = Notification.types[params[:type]] + current_type = types[params[:type]] notifications = Notification.where(recipient_id: current_user.id, unread: true) notifications = notifications.where(type: current_type) if params[:type] notifications.update_all(unread: false) @@ -93,4 +93,17 @@ class NotificationsController < ApplicationController } }.as_json end + + def types + { + "also_commented" => "Notifications::AlsoCommented", + "comment_on_post" => "Notifications::CommentOnPost", + "liked" => "Notifications::Liked", + "mentioned" => "Notifications::MentionedInPost", + "mentioned_in_comment" => "Notifications::MentionedInComment", + "reshared" => "Notifications::Reshared", + "started_sharing" => "Notifications::StartedSharing" + } + end + helper_method :types end diff --git a/app/controllers/status_messages_controller.rb b/app/controllers/status_messages_controller.rb index 87db1237f..93e3e6958 100644 --- a/app/controllers/status_messages_controller.rb +++ b/app/controllers/status_messages_controller.rb @@ -80,7 +80,10 @@ class StatusMessagesController < ApplicationController def handle_mention_feedback(status_message) return unless comes_from_others_profile_page? - flash[:notice] = t("status_messages.create.success", names: status_message.mentioned_people_names) + flash[:notice] = t( + "status_messages.create.success", + names: PersonPresenter.people_names(status_message.mentioned_people) + ) end def comes_from_others_profile_page? diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 958353e28..775f6f27e 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -150,16 +150,7 @@ class UsersController < ApplicationController :auto_follow_back_aspect_id, :getting_started, :post_default_public, - email_preferences: %i( - someone_reported - also_commented - mentioned - comment_on_post - private_message - started_sharing - liked - reshared - ) + email_preferences: UserPreference::VALID_EMAIL_TYPES.map(&:to_sym) ) end # rubocop:enable Metrics/MethodLength diff --git a/app/helpers/notifications_helper.rb b/app/helpers/notifications_helper.rb index a5bca4a24..a8c1a533f 100644 --- a/app/helpers/notifications_helper.rb +++ b/app/helpers/notifications_helper.rb @@ -2,42 +2,46 @@ module NotificationsHelper include PeopleHelper include PostsHelper - def object_link(note, actors) + def object_link(note, actors_html) target_type = note.popup_translation_key - actors_count = note.actors.size + opts = {actors: actors_html, count: note.actors.size} - if note.instance_of?(Notifications::Mentioned) - if post = note.linked_object - translation(target_type, - actors: actors, - count: actors_count, - post_link: link_to(post_page_title(post), post_path(post)).html_safe) - else - t(note.deleted_translation_key, :actors => actors, :count => actors_count).html_safe + if note.respond_to?(:linked_object) + if note.linked_object.nil? && note.respond_to?(:deleted_translation_key) + target_type = note.deleted_translation_key + elsif note.is_a?(Notifications::Mentioned) + opts.merge!(opts_for_mentioned(note.linked_object)) + elsif %w(Notifications::CommentOnPost Notifications::AlsoCommented Notifications::Reshared Notifications::Liked) + .include?(note.type) + opts.merge!(opts_for_post(note.linked_object)) end - elsif note.instance_of?(Notifications::CommentOnPost) || note.instance_of?(Notifications::AlsoCommented) || note.instance_of?(Notifications::Reshared) || note.instance_of?(Notifications::Liked) - if post = note.linked_object - translation(target_type, - actors: actors, - count: actors_count, - post_author: h(post.author_name), - post_link: link_to(post_page_title(post), - post_path(post), - data: {ref: post.id}, - class: "hard_object_link").html_safe) - else - t(note.deleted_translation_key, :actors => actors, :count => actors_count).html_safe - end - else #Notifications:StartedSharing, etc. - translation(target_type, :actors => actors, :count => actors_count) end + translation(target_type, opts) end def translation(target_type, opts = {}) - {:post_author => nil}.merge!(opts) t("#{target_type}", opts).html_safe end + def opts_for_post(post) + { + post_author: html_escape(post.author_name), + post_link: link_to(post_page_title(post), + post_path(post), + data: {ref: post.id}, + class: "hard_object_link").html_safe + } + end + + def opts_for_mentioned(mentioned) + post = mentioned.instance_of?(Comment) ? mentioned.parent : mentioned + { + post_link: link_to(post_page_title(post), post_path(post)).html_safe + }.tap {|opts| + opts[:comment_path] = post_path(post, anchor: mentioned.guid).html_safe if mentioned.instance_of?(Comment) + } + end + def notification_people_link(note, people=nil) actors =people || note.actors number_of_actors = actors.size diff --git a/app/mailers/notification_mailers/mentioned.rb b/app/mailers/notification_mailers/mentioned.rb index a06c82e75..e72c2074d 100644 --- a/app/mailers/notification_mailers/mentioned.rb +++ b/app/mailers/notification_mailers/mentioned.rb @@ -4,7 +4,7 @@ module NotificationMailers delegate :author_name, to: :post, prefix: true def set_headers(target_id) - @post = Mention.find_by_id(target_id).post + @post = Mention.find_by_id(target_id).mentions_container @headers[:subject] = I18n.t('notifier.mentioned.subject', :name => @sender.name) @headers[:in_reply_to] = @headers[:references] = "<#{@post.guid}@#{AppConfig.pod_uri.host}>" diff --git a/app/mailers/notification_mailers/mentioned_in_comment.rb b/app/mailers/notification_mailers/mentioned_in_comment.rb new file mode 100644 index 000000000..abb346ea8 --- /dev/null +++ b/app/mailers/notification_mailers/mentioned_in_comment.rb @@ -0,0 +1,11 @@ +module NotificationMailers + class MentionedInComment < NotificationMailers::Base + attr_reader :comment + + def set_headers(target_id) # rubocop:disable Style/AccessorMethodName + @comment = Mention.find_by_id(target_id).mentions_container + + @headers[:subject] = I18n.t("notifier.mentioned.subject", name: @sender.name) + end + end +end diff --git a/app/models/comment.rb b/app/models/comment.rb index 8d98e52ec..483215f03 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -11,6 +11,7 @@ class Comment < ActiveRecord::Base include Diaspora::Taggable include Diaspora::Likeable + include Diaspora::MentionsContainer acts_as_taggable_on :tags extract_tags_from :text @@ -49,14 +50,22 @@ class Comment < ActiveRecord::Base participation.unparticipate! if participation.present? end - def message - @message ||= Diaspora::MessageRenderer.new text - end - def text= text self[:text] = text.to_s.strip #to_s if for nil, for whatever reason end + def people_allowed_to_be_mentioned + if parent.public? + :all + else + [*parent.comments.pluck(:author_id), *parent.likes.pluck(:author_id), parent.author_id].uniq + end + end + + def add_mention_subscribers? + super && parent.author.local? + end + class Generator < Diaspora::Federated::Generator def self.federated_class Comment @@ -68,7 +77,7 @@ class Comment < ActiveRecord::Base end def relayable_options - {:post => @target, :text => @text} + {post: @target, text: @text} end end end diff --git a/app/models/mention.rb b/app/models/mention.rb index 9ddfd8dad..597cebe94 100644 --- a/app/models/mention.rb +++ b/app/models/mention.rb @@ -3,11 +3,15 @@ # the COPYRIGHT file. class Mention < ActiveRecord::Base - belongs_to :post + belongs_to :mentions_container, polymorphic: true belongs_to :person - validates :post, presence: true + validates :mentions_container, presence: true validates :person, presence: true + scope :local, -> { + joins(:person).where.not(people: {owner_id: nil}) + } + after_destroy :delete_notification def delete_notification diff --git a/app/models/notification.rb b/app/models/notification.rb index aaa56d53d..c4b557045 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -51,15 +51,4 @@ class Notification < ActiveRecord::Base private_class_method def self.suppress_notification?(recipient, actor) recipient.blocks.where(person: actor).exists? end - - def self.types - { - "also_commented" => "Notifications::AlsoCommented", - "comment_on_post" => "Notifications::CommentOnPost", - "liked" => "Notifications::Liked", - "mentioned" => "Notifications::Mentioned", - "reshared" => "Notifications::Reshared", - "started_sharing" => "Notifications::StartedSharing" - } - end end diff --git a/app/models/notifications/also_commented.rb b/app/models/notifications/also_commented.rb index a345566f3..cc28c047c 100644 --- a/app/models/notifications/also_commented.rb +++ b/app/models/notifications/also_commented.rb @@ -1,5 +1,7 @@ module Notifications class AlsoCommented < Notification + include Notifications::Commented + def mail_job Workers::Mail::AlsoCommented end @@ -8,17 +10,13 @@ module Notifications "notifications.also_commented" end - def deleted_translation_key - "notifications.also_commented_deleted" - end - def self.notify(comment, _recipient_user_ids) actor = comment.author commentable = comment.commentable recipient_ids = commentable.participants.local.where.not(id: [commentable.author_id, actor.id]).pluck(:owner_id) User.where(id: recipient_ids).find_each do |recipient| - next if recipient.is_shareable_hidden?(commentable) + next if recipient.is_shareable_hidden?(commentable) || mention_notification_exists?(comment, recipient.person) concatenate_or_create(recipient, commentable, actor).try(:email_the_user, comment, actor) end diff --git a/app/models/notifications/comment_on_post.rb b/app/models/notifications/comment_on_post.rb index df23b558e..ee3320e39 100644 --- a/app/models/notifications/comment_on_post.rb +++ b/app/models/notifications/comment_on_post.rb @@ -1,5 +1,7 @@ module Notifications class CommentOnPost < Notification + include Notifications::Commented + def mail_job Workers::Mail::CommentOnPost end @@ -8,15 +10,12 @@ module Notifications "notifications.comment_on_post" end - def deleted_translation_key - "notifications.also_commented_deleted" - end - def self.notify(comment, _recipient_user_ids) actor = comment.author commentable_author = comment.commentable.author return unless commentable_author.local? && actor != commentable_author + return if mention_notification_exists?(comment, commentable_author) concatenate_or_create(commentable_author.owner, comment.commentable, actor).email_the_user(comment, actor) end diff --git a/app/models/notifications/commented.rb b/app/models/notifications/commented.rb new file mode 100644 index 000000000..e5b1b7d48 --- /dev/null +++ b/app/models/notifications/commented.rb @@ -0,0 +1,15 @@ +module Notifications + module Commented + extend ActiveSupport::Concern + + def deleted_translation_key + "notifications.also_commented_deleted" + end + + module ClassMethods + def mention_notification_exists?(comment, recipient_person) + Notifications::MentionedInComment.exists?(target: comment.mentions.where(person: recipient_person)) + end + end + end +end diff --git a/app/models/notifications/mentioned.rb b/app/models/notifications/mentioned.rb index bede65ee4..b128791bb 100644 --- a/app/models/notifications/mentioned.rb +++ b/app/models/notifications/mentioned.rb @@ -1,30 +1,23 @@ module Notifications - class Mentioned < Notification - def mail_job - Workers::Mail::Mentioned - end - - def popup_translation_key - "notifications.mentioned" - end - - def deleted_translation_key - "notifications.mentioned_deleted" - end + module Mentioned + extend ActiveSupport::Concern def linked_object - target.post + target.mentions_container end - def self.notify(mentionable, recipient_user_ids) - actor = mentionable.author + module ClassMethods + def notify(mentionable, recipient_user_ids) + actor = mentionable.author + relevant_mentions = filter_mentions( + mentionable.mentions.local.where.not(person: actor), + mentionable, + recipient_user_ids + ) - mentionable.mentions.select {|mention| mention.person.local? }.each do |mention| - recipient = mention.person - - next if recipient == actor || !(mentionable.public || recipient_user_ids.include?(recipient.owner_id)) - - create_notification(recipient.owner, mention, actor).try(:email_the_user, mention, actor) + relevant_mentions.each do |mention| + create_notification(mention.person.owner, mention, actor).try(:email_the_user, mention, actor) + end end end end diff --git a/app/models/notifications/mentioned_in_comment.rb b/app/models/notifications/mentioned_in_comment.rb new file mode 100644 index 000000000..77038864a --- /dev/null +++ b/app/models/notifications/mentioned_in_comment.rb @@ -0,0 +1,38 @@ +module Notifications + class MentionedInComment < Notification + include Notifications::Mentioned + + def popup_translation_key + "notifications.mentioned_in_comment" + end + + def deleted_translation_key + "notifications.mentioned_in_comment_deleted" + end + + def self.filter_mentions(mentions, mentionable, _recipient_user_ids) + people = mentionable.people_allowed_to_be_mentioned + if people == :all + mentions + else + mentions.where(person_id: people) + end + end + + def mail_job + if !recipient.user_preferences.exists?(email_type: "mentioned_in_comment") + Workers::Mail::MentionedInComment + elsif shareable.author.owner_id == recipient_id + Workers::Mail::CommentOnPost + elsif shareable.participants.local.where(owner_id: recipient_id) + Workers::Mail::AlsoCommented + end + end + + private + + def shareable + linked_object.parent + end + end +end diff --git a/app/models/notifications/mentioned_in_post.rb b/app/models/notifications/mentioned_in_post.rb new file mode 100644 index 000000000..35ec36c45 --- /dev/null +++ b/app/models/notifications/mentioned_in_post.rb @@ -0,0 +1,22 @@ +module Notifications + class MentionedInPost < Notification + include Notifications::Mentioned + + def mail_job + Workers::Mail::Mentioned + end + + def popup_translation_key + "notifications.mentioned" + end + + def deleted_translation_key + "notifications.mentioned_deleted" + end + + def self.filter_mentions(mentions, mentionable, recipient_user_ids) + return mentions if mentionable.public + mentions.where(person: Person.where(owner_id: recipient_user_ids).ids) + end + end +end diff --git a/app/models/post.rb b/app/models/post.rb index 3ad235f0f..576717f79 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -12,16 +12,15 @@ class Post < ActiveRecord::Base include Diaspora::Likeable include Diaspora::Commentable include Diaspora::Shareable + include Diaspora::MentionsContainer has_many :participations, dependent: :delete_all, as: :target, inverse_of: :target - has_many :participants, class_name: "Person", through: :participations, source: :author + has_many :participants, through: :participations, source: :author attr_accessor :user_like has_many :reports, as: :item - has_many :mentions, dependent: :destroy - has_many :reshares, class_name: "Reshare", foreign_key: :root_guid, primary_key: :guid has_many :resharers, class_name: "Person", through: :reshares, source: :author @@ -60,7 +59,6 @@ class Post < ActiveRecord::Base end def root; end - def mentioned_people; []; end def photos; []; end #prevents error when trying to access @post.address in a post different than Reshare and StatusMessage types; diff --git a/app/models/status_message.rb b/app/models/status_message.rb index 6ee7d388e..28d838536 100644 --- a/app/models/status_message.rb +++ b/app/models/status_message.rb @@ -23,13 +23,12 @@ class StatusMessage < Post attr_accessor :oembed_url attr_accessor :open_graph_url - after_create :create_mentions after_commit :queue_gather_oembed_data, :on => :create, :if => :contains_oembed_url_in_text? after_commit :queue_gather_open_graph_data, :on => :create, :if => :contains_open_graph_url_in_text? #scopes scope :where_person_is_mentioned, ->(person) { - joins(:mentions).where(:mentions => {:person_id => person.id}) + owned_or_visible_by_user(person.owner).joins(:mentions).where(mentions: {person_id: person.id}) } def self.guids_for_author(person) @@ -52,36 +51,6 @@ class StatusMessage < Post text.try(:match, /#nsfw/i) || super end - def message - @message ||= Diaspora::MessageRenderer.new(text, mentioned_people: mentioned_people) - end - - def mentioned_people - if self.persisted? - self.mentions.includes(:person => :profile).map{ |mention| mention.person } - else - Diaspora::Mentionable.people_from_string(text) - end - end - - ## TODO ---- - # don't put presentation logic in the model! - def mentioned_people_names - self.mentioned_people.map(&:name).join(', ') - end - ## ---- ---- - - def create_mentions - ppl = Diaspora::Mentionable.people_from_string(text) - ppl.each do |person| - self.mentions.find_or_create_by(person_id: person.id) - end - end - - def mentions?(person) - mentioned_people.include? person - end - def comment_email_subject message.title end @@ -126,6 +95,22 @@ class StatusMessage < Post photos.each {|photo| photo.receive(recipient_user_ids) } end + # Only includes those people, to whom we're going to send a federation entity + # (and doesn't define exhaustive list of people who can receive it) + def people_allowed_to_be_mentioned + @aspects_ppl ||= + if public? + :all + else + Contact.joins(:aspect_memberships).where(aspect_memberships: {aspect: aspects}).distinct.pluck(:person_id) + end + end + + def filter_mentions + return if people_allowed_to_be_mentioned == :all + update(text: Diaspora::Mentionable.filter_people(text, people_allowed_to_be_mentioned)) + end + private def presence_of_content diff --git a/app/models/user.rb b/app/models/user.rb index e8a09a322..85ea59cb6 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -333,6 +333,7 @@ class User < ActiveRecord::Base ######### Mailer ####################### def mail(job, *args) + return unless job.present? pref = job.to_s.gsub('Workers::Mail::', '').underscore if(self.disable_mail == false && !self.user_preferences.exists?(:email_type => pref)) job.perform_async(*args) diff --git a/app/models/user_preference.rb b/app/models/user_preference.rb index 354a48400..ea4f92425 100644 --- a/app/models/user_preference.rb +++ b/app/models/user_preference.rb @@ -5,13 +5,14 @@ class UserPreference < ActiveRecord::Base VALID_EMAIL_TYPES = ["someone_reported", - "mentioned", - "comment_on_post", - "private_message", - "started_sharing", - "also_commented", - "liked", - "reshared"] + "mentioned", + "mentioned_in_comment", + "comment_on_post", + "private_message", + "started_sharing", + "also_commented", + "liked", + "reshared"] def must_be_valid_email_type unless VALID_EMAIL_TYPES.include?(self.email_type) diff --git a/app/presenters/person_presenter.rb b/app/presenters/person_presenter.rb index 63685cb51..8149acbc1 100644 --- a/app/presenters/person_presenter.rb +++ b/app/presenters/person_presenter.rb @@ -40,6 +40,10 @@ class PersonPresenter < BasePresenter } end + def self.people_names(people) + people.map(&:name).join(", ") + end + protected def own_profile? diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index d356a0211..b481f1b4c 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -1,8 +1,8 @@ class NotificationService NOTIFICATION_TYPES = { - Comment => [Notifications::CommentOnPost, Notifications::AlsoCommented], + Comment => [Notifications::MentionedInComment, Notifications::CommentOnPost, Notifications::AlsoCommented], Like => [Notifications::Liked], - StatusMessage => [Notifications::Mentioned], + StatusMessage => [Notifications::MentionedInPost], Conversation => [Notifications::PrivateMessage], Message => [Notifications::PrivateMessage], Reshare => [Notifications::Reshared], diff --git a/app/services/post_service.rb b/app/services/post_service.rb index 140c33a0d..99ce0d28e 100644 --- a/app/services/post_service.rb +++ b/app/services/post_service.rb @@ -59,8 +59,20 @@ class PostService end def mark_mention_notifications_read(post_id) - mention_id = Mention.where(post_id: post_id, person_id: user.person_id).pluck(:id) - Notification.where(recipient_id: user.id, target_type: "Mention", target_id: mention_id, unread: true) - .update_all(unread: false) if mention_id + mention_ids = Mention.where( + mentions_container_id: post_id, + mentions_container_type: "Post", + person_id: user.person_id + ).ids + mention_ids.concat(mentions_in_comments_for_post(post_id).pluck(:id)) + + Notification.where(recipient_id: user.id, target_type: "Mention", target_id: mention_ids, unread: true) + .update_all(unread: false) if mention_ids.any? + end + + def mentions_in_comments_for_post(post_id) + Mention + .joins("INNER JOIN comments ON mentions_container_id = comments.id AND mentions_container_type = 'Comment'") + .where(comments: {commentable_id: post_id, commentable_type: "Post"}) end end diff --git a/app/services/status_message_creation_service.rb b/app/services/status_message_creation_service.rb index b541d194d..94a16d795 100644 --- a/app/services/status_message_creation_service.rb +++ b/app/services/status_message_creation_service.rb @@ -19,20 +19,9 @@ class StatusMessageCreationService def build_status_message(params) public = params[:public] || false - filter_mentions params user.build_post(:status_message, params[:status_message].merge(public: public)) end - def filter_mentions(params) - unless params[:public] - params[:status_message][:text] = Diaspora::Mentionable.filter_for_aspects( - params[:status_message][:text], - user, - *params[:aspect_ids] - ) - end - end - def add_attachments(status_message, params) add_location(status_message, params[:location_address], params[:location_coords]) add_poll(status_message, params) @@ -75,6 +64,7 @@ class StatusMessageCreationService def dispatch(status_message, services) receiving_services = services ? Service.titles(services) : [] + status_message.filter_mentions # this is only required until changes from #6818 are deployed on every pod user.dispatch_post(status_message, url: short_post_url(status_message.guid, host: AppConfig.environment.url), service_types: receiving_services) diff --git a/app/views/notifications/_notification.haml b/app/views/notifications/_notification.haml index 8c537bdc0..23ff76fd3 100644 --- a/app/views/notifications/_notification.haml +++ b/app/views/notifications/_notification.haml @@ -1,5 +1,5 @@ -.media.stream-element{data: {guid: note.id, type: (Notification.types.key(note.type) || "")}, - class: (note.unread ? "unread" : "read")} +.media.stream-element{data: {guid: note.id, type: (types.key(note.type) || "")}, + class: (note.unread ? "unread" : "read")} .unread-toggle.pull-right %i.entypo-eye{title: (note.unread ? t("notifications.index.mark_read") : t("notifications.index.mark_unread"))} - if note.type == "Notifications::StartedSharing" && (!defined?(no_aspect_dropdown) || !no_aspect_dropdown) diff --git a/app/views/notifications/_notification.mobile.haml b/app/views/notifications/_notification.mobile.haml index 2b8825505..b38977152 100644 --- a/app/views/notifications/_notification.mobile.haml +++ b/app/views/notifications/_notification.mobile.haml @@ -1,4 +1,5 @@ -.notification_element{:data=>{:guid => note.id, :type => (Notification.types.key(note.type) || '')}, :class => (note.unread ? "unread" : "read")} +.notification_element{data: {guid: note.id, type: (types.key(note.type) || "")}, + class: (note.unread ? "unread" : "read")} .pull-right.unread-toggle %i.entypo-eye{title: (note.unread ? t("notifications.index.mark_read") : t("notifications.index.mark_unread"))} = person_image_tag note.actors.first, :thumb_small diff --git a/app/views/notifications/index.html.haml b/app/views/notifications/index.html.haml index 22e647c05..61a70fe14 100644 --- a/app/views/notifications/index.html.haml +++ b/app/views/notifications/index.html.haml @@ -23,7 +23,7 @@ %i.entypo-comment - when "liked" %i.entypo-heart - - when "mentioned" + - when "mentioned", "mentioned_in_comment" %span.mentionIcon @ - when "reshared" diff --git a/app/views/notifier/mentioned.markerb b/app/views/notifier/mentioned.markerb index a2469a0e5..414739665 100644 --- a/app/views/notifier/mentioned.markerb +++ b/app/views/notifier/mentioned.markerb @@ -4,6 +4,6 @@ <%= t('notifier.mentioned.limited_post') %> <% end %> -[<%= t('notifier.comment_on_post.reply', :name => @notification.post_author_name) %>][1] +[<%= t("notifier.comment_on_post.reply", name: @notification.post_author_name) %>][1] [1]: <%= post_url(@notification.post) %> diff --git a/app/views/notifier/mentioned_in_comment.markerb b/app/views/notifier/mentioned_in_comment.markerb new file mode 100644 index 000000000..3b86f409b --- /dev/null +++ b/app/views/notifier/mentioned_in_comment.markerb @@ -0,0 +1,9 @@ +<% if @notification.comment.public? %> +<%= @notification.comment.message.plain_text_without_markdown %> +<% else %> +<%= t("notifier.mentioned_in_comment.limited_post") %> +<% end %> + +[<%= t("notifier.mentioned_in_comment.reply") %>][1] + +[1]: <%= post_url(@notification.comment.parent, anchor: @notification.comment.guid) %> diff --git a/app/views/users/_edit.haml b/app/views/users/_edit.haml index 9a171a923..060778b95 100644 --- a/app/views/users/_edit.haml +++ b/app/views/users/_edit.haml @@ -142,6 +142,11 @@ = t(".mentioned") .small-horizontal-spacer + = type.label :mentioned_in_comment, class: "checkbox-inline" do + = type.check_box :mentioned_in_comment, {checked: @email_prefs["mentioned_in_comment"]}, false, true + = t(".mentioned_in_comment") + .small-horizontal-spacer + = type.label :liked, class: "checkbox-inline" do = type.check_box :liked, {checked: @email_prefs["liked"]}, false, true = t(".liked") diff --git a/app/workers/mail/mentioned_in_comment.rb b/app/workers/mail/mentioned_in_comment.rb new file mode 100644 index 000000000..5e8d7f91f --- /dev/null +++ b/app/workers/mail/mentioned_in_comment.rb @@ -0,0 +1,6 @@ +module Workers + module Mail + class MentionedInComment < NotifierBase + end + end +end diff --git a/config/locales/diaspora/en.yml b/config/locales/diaspora/en.yml index 62c2ccfff..65030b224 100644 --- a/config/locales/diaspora/en.yml +++ b/config/locales/diaspora/en.yml @@ -615,9 +615,11 @@ en: one: "%{actors} also commented on %{post_author}’s post %{post_link}." other: "%{actors} also commented on %{post_author}’s post %{post_link}." mentioned: - zero: "%{actors} have mentioned you in the post %{post_link}." one: "%{actors} has mentioned you in the post %{post_link}." other: "%{actors} have mentioned you in the post %{post_link}." + mentioned_in_comment: + one: "%{actors} has mentioned you in a comment to the post %{post_link}." + other: "%{actors} have mentioned you in a comment to the post %{post_link}." liked: zero: "%{actors} have liked your post %{post_link}." one: "%{actors} has liked your post %{post_link}." @@ -640,9 +642,11 @@ en: one: "%{actors} reshared your deleted post." other: "%{actors} reshared your deleted post." mentioned_deleted: - zero: "%{actors} mentioned you in a deleted post." one: "%{actors} mentioned you in a deleted post." other: "%{actors} mentioned you in a deleted post." + mentioned_in_comment_deleted: + one: "%{actors} mentioned you in a deleted comment." + other: "%{actors} mentioned you in a deleted comment." index: notifications: "Notifications" mark_all_as_read: "Mark all as read" @@ -655,7 +659,8 @@ en: also_commented: "Also commented" comment_on_post: "Comment on post" liked: "Liked" - mentioned: "Mentioned" + mentioned: "Mentioned in post" + mentioned_in_comment: "Mentioned in comment" reshared: "Reshared" started_sharing: "Started sharing" no_notifications: "You don't have any notifications yet." @@ -689,6 +694,9 @@ en: mentioned: subject: "%{name} has mentioned you on diaspora*" limited_post: "You were mentioned in a limited post." + mentioned_in_comment: + limited_post: "You were mentioned in a comment to a limited post." + reply: "Reply to or view this conversation >" private_message: subject: "There’s a new private message for you" reply_to_or_view: "Reply to or view this conversation >" @@ -1167,6 +1175,7 @@ en: started_sharing: "someone starts sharing with you" someone_reported: "someone sends a report" mentioned: "you are mentioned in a post" + mentioned_in_comment: "you are mentioned in a comment" liked: "someone likes your post" reshared: "someone reshares your post" comment_on_post: "someone comments on your post" diff --git a/db/migrate/20161107100840_polymorphic_mentions.rb b/db/migrate/20161107100840_polymorphic_mentions.rb new file mode 100644 index 000000000..07b096394 --- /dev/null +++ b/db/migrate/20161107100840_polymorphic_mentions.rb @@ -0,0 +1,38 @@ +class PolymorphicMentions < ActiveRecord::Migration + def change + remove_index :mentions, column: %i(post_id) + remove_index :mentions, column: %i(person_id post_id), unique: true + rename_column :mentions, :post_id, :mentions_container_id + add_column :mentions, :mentions_container_type, :string, null: false + add_index :mentions, + %i(mentions_container_id mentions_container_type), + name: "index_mentions_on_mc_id_and_mc_type", + length: {mentions_container_type: 191} + add_index :mentions, + %i(person_id mentions_container_id mentions_container_type), + name: "index_mentions_on_person_and_mc_id_and_mc_type", + length: {mentions_container_type: 191}, + unique: true + + reversible(&method(:up_down)) + end + + class Mention < ActiveRecord::Base + end + + class Notification < ActiveRecord::Base + end + + def up_down(change) + change.up do + Mention.update_all(mentions_container_type: "Post") + Notification.where(type: "Notifications::Mentioned").update_all(type: "Notifications::MentionedInPost") + end + + change.down do + Notification.where(type: "Notifications::MentionedInPost").update_all(type: "Notifications::Mentioned") + Mention.where(mentions_container_type: "Comment").destroy_all + Notification.where(type: "Notifications::MentionedInComment").destroy_all + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 402f53db2..7e0e55ec0 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20161024231443) do +ActiveRecord::Schema.define(version: 20161107100840) do create_table "account_deletions", force: :cascade do |t| t.string "diaspora_handle", limit: 255 @@ -204,13 +204,14 @@ ActiveRecord::Schema.define(version: 20161024231443) do end create_table "mentions", force: :cascade do |t| - t.integer "post_id", limit: 4, null: false - t.integer "person_id", limit: 4, null: false + t.integer "mentions_container_id", limit: 4, null: false + t.integer "person_id", limit: 4, null: false + t.string "mentions_container_type", limit: 255, null: false end - add_index "mentions", ["person_id", "post_id"], name: "index_mentions_on_person_id_and_post_id", unique: true, using: :btree + add_index "mentions", ["mentions_container_id", "mentions_container_type"], name: "index_mentions_on_mc_id_and_mc_type", length: {"mentions_container_id"=>nil, "mentions_container_type"=>191}, using: :btree + add_index "mentions", ["person_id", "mentions_container_id", "mentions_container_type"], name: "index_mentions_on_person_and_mc_id_and_mc_type", unique: true, length: {"person_id"=>nil, "mentions_container_id"=>nil, "mentions_container_type"=>191}, using: :btree add_index "mentions", ["person_id"], name: "index_mentions_on_person_id", using: :btree - add_index "mentions", ["post_id"], name: "index_mentions_on_post_id", using: :btree create_table "messages", force: :cascade do |t| t.integer "conversation_id", limit: 4, null: false diff --git a/features/desktop/change_settings.feature b/features/desktop/change_settings.feature index ba0543908..21c473930 100644 --- a/features/desktop/change_settings.feature +++ b/features/desktop/change_settings.feature @@ -22,6 +22,10 @@ Feature: Change settings And I press "change_email_preferences" Then I should see "Email notifications changed" And the "user_email_preferences_mentioned" checkbox should not be checked + When I uncheck "user_email_preferences_mentioned_in_comment" + And I press "change_email_preferences" + Then I should see "Email notifications changed" + And the "user_email_preferences_mentioned_in_comment" checkbox should not be checked Scenario: Change my preferred language When I select "polski" from "user_language" diff --git a/features/desktop/notifications.feature b/features/desktop/notifications.feature index 2dd5eaee4..13fc31a6b 100644 --- a/features/desktop/notifications.feature +++ b/features/desktop/notifications.feature @@ -101,6 +101,26 @@ Feature: Notifications Then I should see "mentioned you in the post" And I should have 1 email delivery + Scenario: someone mentioned me in a comment + Given "alice@alice.alice" has a public post with text "check this out!" + And "bob@bob.bob" has commented mentioning "alice@alice.alice" on "check this out!" + When I sign in as "alice@alice.alice" + And I follow "Notifications" in the header + Then the notification dropdown should be visible + And I should see "mentioned you in a comment" + And I should have 1 email delivery + + Scenario: I mark a notification as read + Given a user with email "bob@bob.bob" is connected with "alice@alice.alice" + And Alice has a post mentioning Bob + When I sign in as "bob@bob.bob" + And I follow "Notifications" in the header + Then the notification dropdown should be visible + And I wait for notifications to load + And I should see a ".unread .unread-toggle .entypo-eye" + When I click on selector ".unread .unread-toggle .entypo-eye" + Then I should see a ".read .unread-toggle" + Scenario: filter notifications Given a user with email "bob@bob.bob" is connected with "alice@alice.alice" And Alice has a post mentioning Bob diff --git a/features/step_definitions/comment_steps.rb b/features/step_definitions/comment_steps.rb index 0d669f1ac..74589dddb 100644 --- a/features/step_definitions/comment_steps.rb +++ b/features/step_definitions/comment_steps.rb @@ -21,6 +21,12 @@ Given /^"([^"]*)" has commented "([^"]*)" on "([^"]*)"$/ do |email, comment_text user.comment!(post, comment_text) end +Given /^"([^"]*)" has commented mentioning "([^"]*)" on "([^"]*)"$/ do |email, mentionee_email, post_text| + user = User.find_by(email: email) + post = StatusMessage.find_by(text: post_text) + user.comment!(post, text_mentioning(User.find_by(email: mentionee_email))) +end + Given /^"([^"]*)" has commented a lot on "([^"]*)"$/ do |email, post_text| user = User.find_by(email: email) post = StatusMessage.find_by(text: post_text) diff --git a/features/step_definitions/custom_web_steps.rb b/features/step_definitions/custom_web_steps.rb index a84f2d337..be4e29555 100644 --- a/features/step_definitions/custom_web_steps.rb +++ b/features/step_definitions/custom_web_steps.rb @@ -176,7 +176,7 @@ end Then /^(?:|I )should see a "([^\"]*)"(?: within "([^\"]*)")?$/ do |selector, scope_selector| with_scope(scope_selector) do - current_scope.should have_css selector + expect(current_scope).to have_css(selector) end end diff --git a/features/step_definitions/notifications_steps.rb b/features/step_definitions/notifications_steps.rb index 87c27ceff..65aa57ad0 100644 --- a/features/step_definitions/notifications_steps.rb +++ b/features/step_definitions/notifications_steps.rb @@ -3,7 +3,7 @@ When "I filter notifications by likes" do end When "I filter notifications by mentions" do - step %(I follow "Mentioned" within "#notifications_container .list-group") + step %(I follow "Mentioned in post" within "#notifications_container .list-group") end Then /^I should( not)? have activated notifications for the post( in the single post view)?$/ do |negate, spv| diff --git a/lib/diaspora/mentionable.rb b/lib/diaspora/mentionable.rb index 8645d9020..c922096af 100644 --- a/lib/diaspora/mentionable.rb +++ b/lib/diaspora/mentionable.rb @@ -54,25 +54,19 @@ module Diaspora::Mentionable end # takes a message text and converts mentions for people that are not in the - # given aspects to simple markdown links, leaving only mentions for people who + # given array to simple markdown links, leaving only mentions for people who # will actually be able to receive notifications for being mentioned. # # @param [String] message text - # @param [User] aspect owner - # @param [Mixed] array containing aspect ids or "all" + # @param [Array] allowed_people ids of people that are allowed to stay # @return [String] message text with filtered mentions - def self.filter_for_aspects(msg_text, user, *aspects) - aspect_ids = MentionsInternal.get_aspect_ids(user, *aspects) - + def self.filter_people(msg_text, allowed_people) mentioned_ppl = people_from_string(msg_text) - aspects_ppl = AspectMembership.where(aspect_id: aspect_ids) - .includes(:contact => :person) - .map(&:person) msg_text.to_s.gsub(REGEX) {|match_str| name, handle = mention_attrs(match_str) person = mentioned_ppl.find {|p| p.diaspora_handle == handle } - mention = MentionsInternal.profile_link(person, name) unless aspects_ppl.include?(person) + mention = MentionsInternal.profile_link(person, name) unless allowed_people.include?(person.id) mention || match_str } @@ -118,26 +112,6 @@ module Diaspora::Mentionable "[#{display_name.presence || person.name}](#{local_or_remote_person_path(person)})" end - - # takes a user and an array of aspect ids or an array containing "all" as - # the first element. will do some checking on ids and return them in an array - # in case of "all", returns an array with all the users aspect ids - # - # @param [User] owner of the aspects - # @param [Array] aspect ids or "all" - # @return [Array] aspect ids - def self.get_aspect_ids(user, *aspects) - return [] if aspects.empty? - - if (!aspects.first.is_a?(Integer)) && aspects.first.to_s == 'all' - return user.aspects.pluck(:id) - end - - ids = aspects.reject {|id| Integer(id) == nil } # only numeric - - #make sure they really belong to the user - user.aspects.where(id: ids).pluck(:id) - end end end diff --git a/lib/diaspora/mentions_container.rb b/lib/diaspora/mentions_container.rb new file mode 100644 index 000000000..5364aa5ae --- /dev/null +++ b/lib/diaspora/mentions_container.rb @@ -0,0 +1,38 @@ +module Diaspora + module MentionsContainer + extend ActiveSupport::Concern + + included do + after_create :create_mentions + has_many :mentions, as: :mentions_container, dependent: :destroy + end + + def mentioned_people + if persisted? + mentions.includes(person: :profile).map(&:person) + else + Diaspora::Mentionable.people_from_string(text) + end + end + + def add_mention_subscribers? + public? + end + + def subscribers + super.tap {|subscribers| + subscribers.concat(mentions.map(&:person).select(&:remote?)) if add_mention_subscribers? + } + end + + def create_mentions + Diaspora::Mentionable.people_from_string(text).each do |person| + mentions.find_or_create_by(person_id: person.id) + end + end + + def message + @message ||= Diaspora::MessageRenderer.new text, mentioned_people: mentioned_people + end + end +end diff --git a/lib/diaspora/message_renderer.rb b/lib/diaspora/message_renderer.rb index 7c39470fb..de616f3d9 100644 --- a/lib/diaspora/message_renderer.rb +++ b/lib/diaspora/message_renderer.rb @@ -72,7 +72,7 @@ module Diaspora end if options[:disable_hovercards] || options[:link_all_mentions] - @message = Diaspora::Mentionable.filter_for_aspects message, nil + @message = Diaspora::Mentionable.filter_people message, [] else make_mentions_plain_text end diff --git a/spec/controllers/notifications_controller_spec.rb b/spec/controllers/notifications_controller_spec.rb index e64b45bb4..d1f969e7a 100644 --- a/spec/controllers/notifications_controller_spec.rb +++ b/spec/controllers/notifications_controller_spec.rb @@ -77,12 +77,13 @@ describe NotificationsController, :type => :controller do timeago_content = note_html.css("time")[0]["data-time-ago"] expect(response_json["unread_count"]).to be(1) expect(response_json["unread_count_by_type"]).to eq( - "also_commented" => 1, - "comment_on_post" => 0, - "liked" => 0, - "mentioned" => 0, - "reshared" => 0, - "started_sharing" => 0 + "also_commented" => 1, + "comment_on_post" => 0, + "liked" => 0, + "mentioned" => 0, + "mentioned_in_comment" => 0, + "reshared" => 0, + "started_sharing" => 0 ) expect(timeago_content).to include(@notification.updated_at.iso8601) expect(response.body).to match(/note_html/) diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb index a80f9f37e..0ab83e120 100644 --- a/spec/controllers/users_controller_spec.rb +++ b/spec/controllers/users_controller_spec.rb @@ -184,20 +184,24 @@ describe UsersController, :type => :controller do end end - describe 'email settings' do - it 'lets the user turn off mail' do - par = {:id => @user.id, :user => {:email_preferences => {'mentioned' => 'true'}}} - expect{ - put :update, par - }.to change(@user.user_preferences, :count).by(1) - end + describe "email settings" do + UserPreference::VALID_EMAIL_TYPES.each do |email_type| + context "for #{email_type}" do + it "lets the user turn off mail" do + par = {id: @user.id, user: {email_preferences: {email_type => "true"}}} + expect { + put :update, par + }.to change(@user.user_preferences, :count).by(1) + end - it 'lets the user get mail again' do - @user.user_preferences.create(:email_type => 'mentioned') - par = {:id => @user.id, :user => {:email_preferences => {'mentioned' => 'false'}}} - expect{ - put :update, par - }.to change(@user.user_preferences, :count).by(-1) + it "lets the user get mail again" do + @user.user_preferences.create(email_type: email_type) + par = {id: @user.id, user: {email_preferences: {email_type => "false"}}} + expect { + put :update, par + }.to change(@user.user_preferences, :count).by(-1) + end + end end end diff --git a/spec/factories.rb b/spec/factories.rb index 2f8b37d30..ec8cec960 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -76,8 +76,17 @@ FactoryGirl.define do end end - factory :user_with_aspect, :parent => :user do - after(:create) { |u| FactoryGirl.create(:aspect, :user => u) } + factory :user_with_aspect, parent: :user do + transient do + friends [] + end + + after(:create) do |user, evaluator| + FactoryGirl.create(:aspect, user: user) + evaluator.friends.each do |friend| + connect_users_with_aspects(user, friend) + end + end end factory :aspect do @@ -116,8 +125,8 @@ FactoryGirl.define do factory(:status_message_in_aspect) do public false + author { FactoryGirl.create(:user_with_aspect).person } after(:build) do |sm| - sm.author = FactoryGirl.create(:user_with_aspect).person sm.aspects << sm.author.owner.aspects.first end end @@ -228,8 +237,8 @@ FactoryGirl.define do factory(:comment) do sequence(:text) {|n| "#{n} cats"} - association(:author, :factory => :person) - association(:post, :factory => :status_message) + association(:author, factory: :person) + association(:post, factory: :status_message) end factory(:notification) do @@ -242,6 +251,16 @@ FactoryGirl.define do end end + factory(:notification_mentioned_in_comment, class: Notification) do + association :recipient, factory: :user + type "Notifications::MentionedInComment" + + after(:build) do |note| + note.actors << FactoryGirl.build(:person) + note.target = FactoryGirl.create :mention_in_comment, person: note.recipient.person + end + end + factory(:tag, :class => ActsAsTaggableOn::Tag) do name "partytimeexcellent" end @@ -271,8 +290,13 @@ FactoryGirl.define do end factory(:mention) do - association(:person, :factory => :person) - association(:post, :factory => :status_message) + association(:person, factory: :person) + association(:mentions_container, factory: :status_message) + end + + factory(:mention_in_comment, class: Mention) do + association(:person, factory: :person) + association(:mentions_container, factory: :comment) end factory(:conversation) do diff --git a/spec/helper_methods.rb b/spec/helper_methods.rb index ad4371a34..177999a96 100644 --- a/spec/helper_methods.rb +++ b/spec/helper_methods.rb @@ -3,10 +3,12 @@ require Rails.root.join("spec", "support", "inlined_jobs") module HelperMethods def connect_users_with_aspects(u1, u2) - aspect1 = u1.aspects.length == 1 ? u1.aspects.first : u1.aspects.where(:name => "Besties").first - aspect2 = u2.aspects.length == 1 ? u2.aspects.first : u2.aspects.where(:name => "Besties").first + aspect1, aspect2 = [u1, u2].map do |user| + user.aspects.where(name: "Besties").first.presence || user.aspects.first + end connect_users(u1, aspect1, u2, aspect2) end + def connect_users(user1, aspect1, user2, aspect2) user1.contacts.create!(:person => user2.person, :aspects => [aspect1], @@ -42,4 +44,18 @@ module HelperMethods body.close if body.respond_to?(:close) # avoids deadlock after 3 tests ActionDispatch::TestResponse.new(status, headers, body) end + + def text_mentioning(*people) + people.map {|person| + "this is a text mentioning @{#{person.name}; #{person.diaspora_handle}} ... have fun testing!" + }.join(" ") + end + + def build_relayable_federation_entity(type, data={}, additional_xml_elements={}) + attributes = FactoryGirl.attributes_for("#{type}_entity".to_sym, data) + entity_class = "DiasporaFederation::Entities::#{type.capitalize}".constantize + signable_fields = attributes.keys - [:author_signature] + + entity_class.new(attributes, [*signable_fields, *additional_xml_elements.keys], additional_xml_elements) + end end diff --git a/spec/helpers/notifications_helper_spec.rb b/spec/helpers/notifications_helper_spec.rb index 7f5f2e601..1aa84d6a9 100644 --- a/spec/helpers/notifications_helper_spec.rb +++ b/spec/helpers/notifications_helper_spec.rb @@ -90,6 +90,37 @@ describe NotificationsHelper, type: :helper do end end end + + let(:status_message) { + FactoryGirl.create(:status_message_in_aspect, author: alice.person, text: text_mentioning(bob)) + } + + describe "when mentioned in status message" do + it "should include correct wording and post link" do + Notifications::MentionedInPost.notify(status_message, [bob.id]) + notification = Notifications::MentionedInPost.last + expect(notification).not_to be_nil + + link = object_link(notification, notification_people_link(notification)) + expect(link).to include("mentioned you in the post") + expect(link).to include(post_path(status_message)) + end + end + + describe "when mentioned in comment" do + it "should include correct wording, post link and comment link" do + comment = FactoryGirl.create(:comment, author: bob.person, text: text_mentioning(alice), post: status_message) + Notifications::MentionedInComment.notify(comment, [alice.id]) + notification = Notifications::MentionedInComment.last + expect(notification).not_to be_nil + + link = object_link(notification, notification_people_link(notification)) + expect(link).to include("mentioned you in a") + expect(link).to include(">comment") + expect(link).to include("href=\"#{post_path(status_message)}\"") + expect(link).to include("#{post_path(status_message)}##{comment.guid}") + end + end end describe '#display_year?' do diff --git a/spec/integration/mentioning_spec.rb b/spec/integration/mentioning_spec.rb index 8b8af8d0b..2e6b4292d 100644 --- a/spec/integration/mentioning_spec.rb +++ b/spec/integration/mentioning_spec.rb @@ -1,10 +1,39 @@ module MentioningSpecHelpers - def default_aspect - @user1.aspects.where(name: "generic").first + def notifications_about_mentioning(user, object) + table = object.class.table_name + + if object.is_a?(StatusMessage) + klass = Notifications::MentionedInPost + elsif object.is_a?(Comment) + klass = Notifications::MentionedInComment + end + + klass + .where(recipient_id: user.id) + .joins("LEFT OUTER JOIN mentions ON notifications.target_id = mentions.id AND "\ + "notifications.target_type = 'Mention'") + .joins("LEFT OUTER JOIN #{table} ON mentions_container_id = #{table}.id AND "\ + "mentions_container_type = '#{object.class.base_class}'").where(table.to_sym => {id: object.id}) end - def text_mentioning(user) - "this is a text mentioning @{#{user.name}; #{user.diaspora_handle}} ... have fun testing!" + def mention_container_path(object) + object.is_a?(Post) ? post_path(object) : post_path(object.parent, anchor: object.guid) + end + + def mentioning_mail_notification(user, object) + ActionMailer::Base.deliveries.select {|delivery| + delivery.to.include?(user.email) && + delivery.subject.include?(I18n.t("notifier.mentioned.subject", name: "")) && + delivery.body.parts[0].body.include?(mention_container_path(object)) + } + end + + def also_commented_mail_notification(user, post) + ActionMailer::Base.deliveries.select {|delivery| + delivery.to.include?(user.email) && + delivery.subject.include?(I18n.t("notifier.also_commented.limited_subject")) && + delivery.body.parts[0].body.include?(post_path(post)) + } end def stream_for(user) @@ -17,77 +46,336 @@ module MentioningSpecHelpers stream.posts end - def users_connected?(user1, user2) - user1.contacts.where(person_id: user2.person).count > 0 + def post_status_message(mentioned_user, aspects=nil) + aspects = user1.aspects.first.id.to_s if aspects.nil? + sign_in user1 + status_msg = nil + inlined_jobs do + post "/status_messages.json", status_message: {text: text_mentioning(mentioned_user)}, aspect_ids: aspects + status_msg = StatusMessage.find(JSON.parse(response.body)["id"]) + end + status_msg + end + + def receive_each(entity, recipients) + inlined_jobs do + recipients.each do |recipient| + DiasporaFederation.callbacks.trigger(:receive_entity, entity, entity.author, recipient.id) + end + end + end + + def find_private_message(guid) + StatusMessage.find_by(guid: guid).tap do |status_msg| + expect(status_msg).not_to be_nil + expect(status_msg.public?).to be false + end + end + + def receive_status_message_via_federation(text, *recipients) + entity = FactoryGirl.build( + :status_message_entity, + author: remote_raphael.diaspora_handle, + text: text, + public: false + ) + + expect { + receive_each(entity, recipients) + }.to change(Post, :count).by(1).and change(ShareVisibility, :count).by(recipients.count) + + find_private_message(entity.guid) + end + + def receive_comment_via_federation(text, parent) + entity = build_relayable_federation_entity( + :comment, + parent_guid: parent.guid, + author: remote_raphael.diaspora_handle, + parent: Diaspora::Federation::Entities.related_entity(parent), + text: text + ) + + receive_each(entity, [parent.author.owner]) + + Comment.find_by(guid: entity.guid) end end - describe "mentioning", type: :request do include MentioningSpecHelpers - before do - @user1 = FactoryGirl.create :user_with_aspect - @user2 = FactoryGirl.create :user - @user3 = FactoryGirl.create :user + RSpec::Matchers.define :be_mentioned_in do |object| + include Rails.application.routes.url_helpers - @user1.share_with(@user2.person, default_aspect) - sign_in @user1 + def user_notified?(user, object) + notifications_about_mentioning(user, object).any? && mentioning_mail_notification(user, object).any? + end + + match do |user| + object.message.markdownified.include?(person_path(id: user.person.guid)) && user_notified?(user, object) + end + + match_when_negated do |user| + !user_notified?(user, object) + end end - # see: https://github.com/diaspora/diaspora/issues/4160 - it "doesn't mention people that aren't in the target aspect" do - expect(users_connected?(@user1, @user3)).to be false + RSpec::Matchers.define :be_in_streams_of do |user| + match do |status_message| + stream_for(user).map(&:id).include?(status_message.id) && + mention_stream_for(user).map(&:id).include?(status_message.id) + end + match_when_negated do |status_message| + !stream_for(user).map(&:id).include?(status_message.id) && + !mention_stream_for(user).map(&:id).include?(status_message.id) + end + end + + let(:user1) { FactoryGirl.create(:user_with_aspect) } + let(:user2) { FactoryGirl.create(:user_with_aspect, friends: [user1, user3]) } + let(:user3) { FactoryGirl.create(:user_with_aspect) } + + # see: https://github.com/diaspora/diaspora/issues/4160 + it "only mentions people that are in the target aspect" do status_msg = nil expect { - post "/status_messages.json", status_message: {text: text_mentioning(@user3)}, aspect_ids: default_aspect.id.to_s - status_msg = StatusMessage.find(JSON.parse(response.body)["id"]) + status_msg = post_status_message(user3) }.to change(Post, :count).by(1).and change(AspectVisibility, :count).by(1) expect(status_msg).not_to be_nil expect(status_msg.public?).to be false - expect(status_msg.text).to include(@user3.name) - expect(status_msg.text).not_to include(@user3.diaspora_handle) - expect(status_msg.text).to include(user_profile_path(username: @user3.username)) + expect(status_msg.text).to include(user3.name) - expect(stream_for(@user3).map(&:id)).not_to include(status_msg.id) - expect(mention_stream_for(@user3).map(&:id)).not_to include(status_msg.id) + expect(user3).not_to be_mentioned_in(status_msg) + expect(status_msg).not_to be_in_streams_of(user3) + end + + context "in private post via federation" do + let(:status_msg) { + receive_status_message_via_federation(text_mentioning(user2, user3), user3) + } + + it "receiver is mentioned in status message" do + expect(user3).to be_mentioned_in(status_msg) + end + + it "receiver can see status message in streams" do + expect(status_msg).to be_in_streams_of(user3) + end + + it "non-receiver is not mentioned in status message" do + expect(user2).not_to be_mentioned_in(status_msg) + end + + it "non-receiver can't see status message in streams" do + expect(status_msg).not_to be_in_streams_of(user2) + end + end + + context "in private post via federation with multiple recipients" do + let(:status_msg) { + receive_status_message_via_federation(text_mentioning(user3, user2), user3, user2) + } + + it "mentions all recipients in the status message" do + [user2, user3].each do |user| + expect(user).to be_mentioned_in(status_msg) + end + end + + it "all recipients can see status message in streams" do + [user2, user3].each do |user| + expect(status_msg).to be_in_streams_of(user) + end + end end it "mentions people in public posts" do - expect(users_connected?(@user1, @user3)).to be false - status_msg = nil expect { - post "/status_messages.json", status_message: {text: text_mentioning(@user3)}, aspect_ids: "public" - status_msg = StatusMessage.find(JSON.parse(response.body)["id"]) + status_msg = post_status_message(user3, "public") }.to change(Post, :count).by(1) expect(status_msg).not_to be_nil expect(status_msg.public?).to be true - expect(status_msg.text).to include(@user3.name) - expect(status_msg.text).to include(@user3.diaspora_handle) + expect(status_msg.text).to include(user3.name) + expect(status_msg.text).to include(user3.diaspora_handle) - expect(stream_for(@user3).map(&:id)).to include(status_msg.id) - expect(mention_stream_for(@user3).map(&:id)).to include(status_msg.id) + expect(user3).to be_mentioned_in(status_msg) + expect(status_msg).to be_in_streams_of(user3) end it "mentions people that are in the target aspect" do - expect(users_connected?(@user1, @user2)).to be true - status_msg = nil expect { - post "/status_messages.json", status_message: {text: text_mentioning(@user2)}, aspect_ids: default_aspect.id.to_s - status_msg = StatusMessage.find(JSON.parse(response.body)["id"]) + status_msg = post_status_message(user2) }.to change(Post, :count).by(1).and change(AspectVisibility, :count).by(1) expect(status_msg).not_to be_nil expect(status_msg.public?).to be false - expect(status_msg.text).to include(@user2.name) - expect(status_msg.text).to include(@user2.diaspora_handle) + expect(status_msg.text).to include(user2.name) + expect(status_msg.text).to include(user2.diaspora_handle) - expect(stream_for(@user2).map(&:id)).to include(status_msg.id) - expect(mention_stream_for(@user2).map(&:id)).to include(status_msg.id) + expect(user2).to be_mentioned_in(status_msg) + expect(status_msg).to be_in_streams_of(user2) + end + + context "in comments" do + let(:author) { FactoryGirl.create(:user_with_aspect) } + + shared_context "commenter is author" do + let(:commenter) { author } + end + + shared_context "commenter is author's friend" do + let(:commenter) { FactoryGirl.create(:user_with_aspect, friends: [author]) } + end + + shared_context "commenter is not author's friend" do + let(:commenter) { FactoryGirl.create(:user) } + end + + shared_context "mentioned user is author" do + let(:mentioned_user) { author } + end + + shared_context "mentioned user is author's friend" do + let(:mentioned_user) { FactoryGirl.create(:user_with_aspect, friends: [author]) } + end + + shared_context "mentioned user is not author's friend" do + let(:mentioned_user) { FactoryGirl.create(:user) } + end + + context "with public post" do + let(:status_msg) { FactoryGirl.create(:status_message, author: author.person, public: true) } + + [ + ["commenter is author's friend", "mentioned user is not author's friend"], + ["commenter is author's friend", "mentioned user is author"], + ["commenter is not author's friend", "mentioned user is author's friend"], + ["commenter is not author's friend", "mentioned user is not author's friend"], + ["commenter is author", "mentioned user is author's friend"], + ["commenter is author", "mentioned user is not author's friend"] + ].each do |commenters_context, mentioned_context| + context "when #{commenters_context} and #{mentioned_context}" do + include_context commenters_context + include_context mentioned_context + + let(:comment) { + inlined_jobs do + commenter.comment!(status_msg, text_mentioning(mentioned_user)) + end + } + + subject { mentioned_user } + it { is_expected.to be_mentioned_in(comment) } + end + end + + context "when comment is received via federation" do + context "when mentioned user is remote" do + it "relays the comment to the mentioned user" do + mentioned_person = FactoryGirl.create(:person) + expect_any_instance_of(Diaspora::Federation::Dispatcher::Public) + .to receive(:deliver_to_remote).with([mentioned_person]) + + receive_comment_via_federation(text_mentioning(mentioned_person), status_msg) + end + end + end + end + + context "with private post" do + [ + ["commenter is author's friend", "mentioned user is author's friend"], + ["commenter is author", "mentioned user is author's friend"], + ["commenter is author's friend", "mentioned user is author"] + ].each do |commenters_context, mentioned_context| + context "when #{commenters_context} and #{mentioned_context}" do + include_context commenters_context + include_context mentioned_context + + let(:parent) { FactoryGirl.create(:status_message_in_aspect, author: author.person) } + let(:comment) { + inlined_jobs do + commenter.comment!(parent, text_mentioning(mentioned_user)) + end + } + + before do + mentioned_user.like!(parent) + end + + subject { mentioned_user } + it { is_expected.to be_mentioned_in(comment) } + end + end + + context "when comment is received via federation" do + let(:parent) { FactoryGirl.create(:status_message_in_aspect, author: user2.person) } + + before do + user3.like!(parent) + user1.like!(parent) + end + + let(:comment_text) { text_mentioning(user2, user3, user1) } + let(:comment) { receive_comment_via_federation(comment_text, parent) } + + it "mentions all the recepients" do + [user1, user2, user3].each do |user| + expect(user).to be_mentioned_in(comment) + end + end + + context "with only post author mentioned" do + let(:post_author) { parent.author.owner } + let(:comment_text) { text_mentioning(post_author) } + + it "makes only one notification for each recipient" do + expect { + comment + }.to change { Notifications::MentionedInComment.for(post_author).count }.by(1) + .and change { Notifications::AlsoCommented.for(user1).count }.by(1) + .and change { Notifications::AlsoCommented.for(user3).count }.by(1) + + expect(mentioning_mail_notification(post_author, comment).count).to eq(1) + + [user1, user3].each do |user| + expect(also_commented_mail_notification(user, parent).count).to eq(1) + end + end + end + end + + context "commenter can't mention a non-participant" do + let(:status_msg) { FactoryGirl.create(:status_message_in_aspect, author: author.person) } + + [ + ["commenter is author's friend", "mentioned user is not author's friend"], + ["commenter is not author's friend", "mentioned user is author's friend"], + ["commenter is not author's friend", "mentioned user is not author's friend"], + ["commenter is author", "mentioned user is author's friend"], + ["commenter is author", "mentioned user is not author's friend"] + ].each do |commenters_context, mentioned_context| + context "when #{commenters_context} and #{mentioned_context}" do + include_context commenters_context + include_context mentioned_context + + let(:comment) { + inlined_jobs do + commenter.comment!(status_msg, text_mentioning(mentioned_user)) + end + } + + subject { mentioned_user } + it { is_expected.not_to be_mentioned_in(comment) } + end + end + end + end end end diff --git a/spec/lib/diaspora/federation/receive_spec.rb b/spec/lib/diaspora/federation/receive_spec.rb index 7e55bb7b8..c31f6332d 100644 --- a/spec/lib/diaspora/federation/receive_spec.rb +++ b/spec/lib/diaspora/federation/receive_spec.rb @@ -15,17 +15,15 @@ describe Diaspora::Federation::Receive do end describe ".comment" do - let(:comment_data) { - FactoryGirl.attributes_for( - :comment_entity, - author: sender.diaspora_handle, - parent_guid: post.guid, - author_signature: "aa" - ) - } let(:comment_entity) { - DiasporaFederation::Entities::Comment.new( - comment_data, [:author, :guid, :parent_guid, :text, "new_property"], "new_property" => "data" + build_relayable_federation_entity( + :comment, + { + author: sender.diaspora_handle, + parent_guid: post.guid, + author_signature: "aa" + }, + "new_property" => "data" ) } @@ -57,7 +55,7 @@ describe Diaspora::Federation::Receive do expect(comment.signature).not_to be_nil expect(comment.signature.author_signature).to eq("aa") expect(comment.signature.additional_data).to eq("new_property" => "data") - expect(comment.signature.order).to eq(%w(author guid parent_guid text new_property)) + expect(comment.signature.order).to eq(comment_entity.xml_order.map(&:to_s)) end let(:entity) { comment_entity } diff --git a/spec/lib/diaspora/mentionable_spec.rb b/spec/lib/diaspora/mentionable_spec.rb index 365d2dd04..de8e2fcac 100644 --- a/spec/lib/diaspora/mentionable_spec.rb +++ b/spec/lib/diaspora/mentionable_spec.rb @@ -102,7 +102,7 @@ STR end end - describe "#filter_for_aspects" do + describe "#filter_people" do before do @user_a = FactoryGirl.create(:user_with_aspect, username: "user_a") @user_b = FactoryGirl.create(:user, username: "user_b") @@ -122,8 +122,10 @@ STR end it "filters mention, if contact is not in a given aspect" do - aspect_id = @user_a.aspects.where(name: "generic").first.id - txt = Diaspora::Mentionable.filter_for_aspects(@test_txt_c, @user_a, aspect_id) + txt = Diaspora::Mentionable.filter_people( + @test_txt_c, + @user_a.aspects.where(name: "generic").first.contacts.map(&:person_id) + ) expect(txt).to include("user C") expect(txt).to include(local_or_remote_person_path(@user_c.person)) @@ -132,18 +134,13 @@ STR end it "leaves mention, if contact is in a given aspect" do - aspect_id = @user_a.aspects.where(name: "generic").first.id - txt = Diaspora::Mentionable.filter_for_aspects(@test_txt_b, @user_a, aspect_id) + txt = Diaspora::Mentionable.filter_people( + @test_txt_b, + @user_a.aspects.where(name: "generic").first.contacts.map(&:person_id) + ) expect(txt).to include("user B") expect(txt).to include(@mention_b) end - - it "recognizes 'all' as keyword for aspects" do - txt = Diaspora::Mentionable.filter_for_aspects(@test_txt_bc, @user_a, "all") - - expect(txt).to include(@mention_b) - expect(txt).to include(@mention_c) - end end end diff --git a/spec/mailers/notifier_spec.rb b/spec/mailers/notifier_spec.rb index 13a05a27e..d0f545bc8 100644 --- a/spec/mailers/notifier_spec.rb +++ b/spec/mailers/notifier_spec.rb @@ -79,9 +79,9 @@ describe Notifier, type: :mailer do before do @user = alice @post = FactoryGirl.create(:status_message, public: true) - @mention = Mention.create(person: @user.person, post: @post) + @mention = Mention.create(person: @user.person, mentions_container: @post) - @mail = Notifier.mentioned(@user.id, @post.author.id, @mention.id) + @mail = Notifier.send_notification("mentioned", @user.id, @post.author.id, @mention.id) end it "TO: goes to the right person" do @@ -106,13 +106,41 @@ describe Notifier, type: :mailer do end end + describe ".mentioned_in_comment" do + let(:user) { alice } + let(:comment) { FactoryGirl.create(:comment) } + let(:mention) { Mention.create(person: user.person, mentions_container: comment) } + let(:mail) { Notifier.send_notification("mentioned_in_comment", user.id, comment.author.id, mention.id) } + + it "TO: goes to the right person" do + expect(mail.to).to eq([user.email]) + end + + it "SUBJECT: has the name of person mentioning in the subject" do + expect(mail.subject).to include(comment.author.name) + end + + it "has the comment link in the body" do + expect(mail.body.encoded).to include(post_url(comment.parent, anchor: comment.guid)) + end + + it "renders proper wording when limited" do + expect(mail.body.encoded).to include(I18n.translate("notifier.mentioned_in_comment.limited_post")) + end + + it "renders comment text when public" do + comment.parent.update(public: true) + expect(mail.body.encoded).to include(comment.message.plain_text_without_markdown) + end + end + describe ".mentioned limited" do before do @user = alice @post = FactoryGirl.create(:status_message, public: false) - @mention = Mention.create(person: @user.person, post: @post) + @mention = Mention.create(person: @user.person, mentions_container: @post) - @mail = Notifier.mentioned(@user.id, @post.author.id, @mention.id) + @mail = Notifier.send_notification("mentioned", @user.id, @post.author.id, @mention.id) end it "TO: goes to the right person" do diff --git a/spec/models/comment_spec.rb b/spec/models/comment_spec.rb index 4fe1d983b..05499dc39 100644 --- a/spec/models/comment_spec.rb +++ b/spec/models/comment_spec.rb @@ -7,6 +7,8 @@ describe Comment, type: :model do let(:status_bob) { bob.post(:status_message, text: "hello", to: bob.aspects.first.id) } let(:comment_alice) { alice.comment!(status_bob, "why so formal?") } + it_behaves_like "it is mentions container" + describe "#destroy" do it "should delete a participation" do comment_alice @@ -21,6 +23,55 @@ describe Comment, type: :model do end end + describe "#people_allowed_to_be_mentioned" do + let(:kate) { FactoryGirl.create(:user_with_aspect, friends: [bob]) } + let(:olga) { FactoryGirl.create(:user_with_aspect, friends: [bob]) } + + it "returns the author and people who have commented or liked the private post" do + eve.comment!(status_bob, "comment text") + kate.like!(status_bob) + olga.participate!(status_bob) + status_bob.reload + expect(comment_alice.people_allowed_to_be_mentioned).to match_array([alice, bob, eve, kate].map(&:person_id)) + end + + it "returns :all for public posts" do + # set parent public + status_bob.update(public: true) + expect(comment_alice.people_allowed_to_be_mentioned).to eq(:all) + end + end + + describe "#subscribers" do + let(:status_bob) { FactoryGirl.create(:status_message, public: true, author: bob.person) } + let(:comment_alice) { + FactoryGirl.create( + :comment, + text: text_mentioning(remote_raphael, local_luke), + post: status_bob, + author: alice.person + ) + } + + context "on the parent post pod" do + it "includes mentioned people to subscribers list" do + expect(comment_alice.subscribers).to include(remote_raphael) + end + + it "doesn't include local mentioned people if they aren't participant or contact" do + expect(comment_alice.subscribers).not_to include(local_luke) + end + end + + context "on a non parent post pod" do + let(:status_bob) { FactoryGirl.create(:status_message) } # make the message remote + + it "doesn't include mentioned people to subscribers list" do + expect(comment_alice.subscribers).not_to include(remote_raphael) + end + end + end + describe "User#comment" do it "should be able to comment on one's own status" do bob.comment!(status_bob, "sup dog") diff --git a/spec/models/mention_spec.rb b/spec/models/mention_spec.rb index e0e3a2a46..6fe5ecdb5 100644 --- a/spec/models/mention_spec.rb +++ b/spec/models/mention_spec.rb @@ -6,9 +6,9 @@ describe Mention, type: :model do describe "after destroy" do it "destroys a notification" do sm = alice.post(:status_message, text: "hi", to: alice.aspects.first) - mention = Mention.create!(person: bob.person, post: sm) + mention = Mention.create!(person: bob.person, mentions_container: sm) - Notifications::Mentioned.notify(sm, [bob.id]) + Notifications::MentionedInPost.notify(sm, [bob.id]) expect { mention.destroy diff --git a/spec/models/notifications/mentioned_in_post_spec.rb b/spec/models/notifications/mentioned_in_post_spec.rb new file mode 100644 index 000000000..90c5b007d --- /dev/null +++ b/spec/models/notifications/mentioned_in_post_spec.rb @@ -0,0 +1,72 @@ +describe Notifications::MentionedInPost, type: :model do + let(:sm) { + FactoryGirl.create(:status_message, author: alice.person, text: "hi @{bob; #{bob.diaspora_handle}}", public: true) + } + let(:mentioned_notification) { Notifications::MentionedInPost.new(recipient: bob) } + + describe ".notify" do + it "calls create_notification with mention" do + expect(Notifications::MentionedInPost).to receive(:create_notification).with( + bob, sm.mentions.first, sm.author + ).and_return(mentioned_notification) + + Notifications::MentionedInPost.notify(sm, []) + end + + it "sends an email to the mentioned person" do + allow(Notifications::MentionedInPost).to receive(:create_notification).and_return(mentioned_notification) + expect(bob).to receive(:mail).with(Workers::Mail::Mentioned, bob.id, sm.author.id, sm.mentions.first.id) + + Notifications::MentionedInPost.notify(sm, []) + end + + it "does nothing if the mentioned person is not local" do + sm = FactoryGirl.create( + :status_message, + author: alice.person, + text: "hi @{raphael; #{remote_raphael.diaspora_handle}}", + public: true + ) + expect(Notifications::MentionedInPost).not_to receive(:create_notification) + + Notifications::MentionedInPost.notify(sm, []) + end + + it "does not notify if the author of the post is ignored" do + bob.blocks.create(person: sm.author) + + expect_any_instance_of(Notifications::MentionedInPost).not_to receive(:email_the_user) + + Notifications::MentionedInPost.notify(sm, []) + + expect(Notifications::MentionedInPost.where(target: sm.mentions.first)).not_to exist + end + + context "with private post" do + let(:private_sm) { + FactoryGirl.create( + :status_message, + author: remote_raphael, + text: "hi @{bob; #{bob.diaspora_handle}}", + public: false + ).tap {|private_sm| + private_sm.receive([bob.id, alice.id]) + } + } + + it "calls create_notification if the mentioned person is a recipient of the post" do + expect(Notifications::MentionedInPost).to receive(:create_notification).with( + bob, private_sm.mentions.first, private_sm.author + ).and_return(mentioned_notification) + + Notifications::MentionedInPost.notify(private_sm, [bob.id]) + end + + it "does not call create_notification if the mentioned person is not a recipient of the post" do + expect(Notifications::MentionedInPost).not_to receive(:create_notification) + + Notifications::MentionedInPost.notify(private_sm, [alice.id]) + end + end + end +end diff --git a/spec/models/notifications/mentioned_spec.rb b/spec/models/notifications/mentioned_spec.rb index d9f05f30e..65ab03a49 100644 --- a/spec/models/notifications/mentioned_spec.rb +++ b/spec/models/notifications/mentioned_spec.rb @@ -1,70 +1,53 @@ -describe Notifications::Mentioned, type: :model do - let(:sm) { - FactoryGirl.create(:status_message, author: alice.person, text: "hi @{bob; #{bob.diaspora_handle}}", public: true) - } - let(:mentioned_notification) { Notifications::Mentioned.new(recipient: bob) } +describe Notifications::Mentioned do + class TestNotification < Notification + include Notifications::Mentioned + + def self.filter_mentions(mentions, *) + mentions + end + end describe ".notify" do - it "calls create_notification with mention" do - expect(Notifications::Mentioned).to receive(:create_notification).with( - bob, sm.mentions.first, sm.author - ).and_return(mentioned_notification) + let(:status_message) { + FactoryGirl.create(:status_message, text: text_mentioning(remote_raphael, alice, bob, eve), author: eve.person) + } - Notifications::Mentioned.notify(sm, []) + it "calls filter_mentions on self" do + expect(TestNotification).to receive(:filter_mentions).with( + Mention.where(mentions_container: status_message, person: [alice, bob].map(&:person)), + status_message, + [alice.id, bob.id] + ).and_return([]) + + TestNotification.notify(status_message, [alice.id, bob.id]) end - it "sends an email to the mentioned person" do - allow(Notifications::Mentioned).to receive(:create_notification).and_return(mentioned_notification) - expect(bob).to receive(:mail).with(Workers::Mail::Mentioned, bob.id, sm.author.id, sm.mentions.first.id) - - Notifications::Mentioned.notify(sm, []) - end - - it "does nothing if the mentioned person is not local" do - sm = FactoryGirl.create( - :status_message, - author: alice.person, - text: "hi @{raphael; #{remote_raphael.diaspora_handle}}", - public: true - ) - expect(Notifications::Mentioned).not_to receive(:create_notification) - - Notifications::Mentioned.notify(sm, []) - end - - it "does not notify if the author of the post is ignored" do - bob.blocks.create(person: sm.author) - - expect_any_instance_of(Notifications::Mentioned).not_to receive(:email_the_user) - - Notifications::Mentioned.notify(sm, []) - - expect(Notifications::Mentioned.where(target: sm.mentions.first)).not_to exist - end - - context "with private post" do - let(:private_sm) { - FactoryGirl.create( - :status_message, - author: remote_raphael, - text: "hi @{bob; #{bob.diaspora_handle}}", - public: false + it "creates notification for each mention" do + [alice, bob].each do |recipient| + expect(TestNotification).to receive(:create_notification).with( + recipient, + Mention.where(mentions_container: status_message, person: recipient.person_id).first, + status_message.author ) - } - - it "calls create_notification if the mentioned person is a recipient of the post" do - expect(Notifications::Mentioned).to receive(:create_notification).with( - bob, private_sm.mentions.first, private_sm.author - ).and_return(mentioned_notification) - - Notifications::Mentioned.notify(private_sm, [bob.id]) end - it "does not call create_notification if the mentioned person is not a recipient of the post" do - expect(Notifications::Mentioned).not_to receive(:create_notification) + TestNotification.notify(status_message, nil) + end - Notifications::Mentioned.notify(private_sm, [alice.id]) - end + it "creates email notification for mention" do + status_message = FactoryGirl.create(:status_message, text: text_mentioning(alice), author: eve.person) + expect_any_instance_of(TestNotification).to receive(:email_the_user).with( + Mention.where(mentions_container: status_message, person: alice.person_id).first, + status_message.author + ) + + TestNotification.notify(status_message, nil) + end + + it "doesn't create notification if it was filtered out by filter_mentions" do + expect(TestNotification).to receive(:filter_mentions).and_return([]) + expect(TestNotification).not_to receive(:create_notification) + TestNotification.notify(status_message, nil) end end end diff --git a/spec/models/status_message_spec.rb b/spec/models/status_message_spec.rb index 843305813..804a423b8 100644 --- a/spec/models/status_message_spec.rb +++ b/spec/models/status_message_spec.rb @@ -14,11 +14,12 @@ describe StatusMessage, type: :model do it "returns status messages where the given person is mentioned" do @bob = bob.person @test_string = "@{Daniel; #{@bob.diaspora_handle}} can mention people like Raph" + post1 = FactoryGirl.create(:status_message, text: @test_string, public: true) + post2 = FactoryGirl.create(:status_message, text: @test_string, public: true) FactoryGirl.create(:status_message, text: @test_string) - FactoryGirl.create(:status_message, text: @test_string) - FactoryGirl.create(:status_message) + FactoryGirl.create(:status_message, public: true) - expect(StatusMessage.where_person_is_mentioned(bob).count).to eq(2) + expect(StatusMessage.where_person_is_mentioned(@bob).ids).to match_array([post1.id, post2.id]) end end @@ -81,14 +82,6 @@ describe StatusMessage, type: :model do end end - describe ".after_create" do - it "calls create_mentions" do - status = FactoryGirl.build(:status_message, text: "text @{Test; #{alice.diaspora_handle}}") - expect(status).to receive(:create_mentions).and_call_original - status.save - end - end - context "emptiness" do it "needs either a message or at least one photo" do post = user.build_post(:status_message, text: nil) @@ -131,57 +124,20 @@ describe StatusMessage, type: :model do expect(status_message).not_to be_valid end - describe "mentions" do - let(:people) { [alice, bob, eve].map(&:person) } - let(:test_string) { - "@{Raphael; #{people[0].diaspora_handle}} can mention people like Raphael @{Ilya; #{people[1].diaspora_handle}} - can mention people like Raphaellike Raphael @{Daniel; #{people[2].diaspora_handle}} can mention people like Raph" - } - let(:status_message) { create(:status_message, text: test_string) } + it_behaves_like "it is mentions container" - describe "#create_mentions" do - it "creates a mention for everyone mentioned in the message" do - status_message - expect(Diaspora::Mentionable).to receive(:people_from_string).and_return(people) - status_message.mentions.delete_all - status_message.create_mentions - expect(status_message.mentions(true).map(&:person).to_set).to eq(people.to_set) - end + describe "#people_allowed_to_be_mentioned" do + it "returns only aspects members for private posts" do + sm = FactoryGirl.build(:status_message_in_aspect) + sm.author.owner.share_with(alice.person, sm.author.owner.aspects.first) + sm.author.owner.share_with(eve.person, sm.author.owner.aspects.first) + sm.save! - it "does not barf if it gets called twice" do - status_message.create_mentions - - expect { - status_message.create_mentions - }.to_not raise_error - end + expect(sm.people_allowed_to_be_mentioned).to match_array([alice.person_id, eve.person_id]) end - describe "#mentioned_people" do - it "does not call create_mentions if there are no mentions in the db" do - status_message.mentions.delete_all - expect(status_message).not_to receive(:create_mentions) - status_message.mentioned_people - end - - it "returns the mentioned people" do - expect(status_message.mentioned_people.to_set).to eq(people.to_set) - end - - it "does not call create_mentions if there are mentions in the db" do - expect(status_message).not_to receive(:create_mentions) - status_message.mentioned_people - end - end - - describe "#mentions?" do - it "returns true if the person was mentioned" do - expect(status_message.mentions?(people[0])).to be true - end - - it "returns false if the person was not mentioned" do - expect(status_message.mentions?(FactoryGirl.build(:person))).to be false - end + it "returns :all for public posts" do + expect(FactoryGirl.create(:status_message, public: true).people_allowed_to_be_mentioned).to eq(:all) end end diff --git a/spec/presenters/post_presenter_spec.rb b/spec/presenters/post_presenter_spec.rb index 0c2a5c993..952da0a2c 100644 --- a/spec/presenters/post_presenter_spec.rb +++ b/spec/presenters/post_presenter_spec.rb @@ -126,9 +126,9 @@ describe PostPresenter do it "does not raise if the root of a reshare does not exist anymore" do reshare = FactoryGirl.create(:reshare) - reshare.root = nil + reshare.update(root: nil) - expect(PostPresenter.new(reshare).send(:description)).to eq(nil) + expect(PostPresenter.new(Post.find(reshare.id)).send(:description)).to eq(nil) end end diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb new file mode 100644 index 000000000..8ef4bec5d --- /dev/null +++ b/spec/services/notification_service_spec.rb @@ -0,0 +1,74 @@ +describe NotificationService do + describe "notification interrelation" do + context "with mention in comment" do + let(:status_message) { + FactoryGirl.create(:status_message, public: true, author: alice.person).tap {|status_message| + eve.comment!(status_message, "whatever") + } + } + + let(:comment) { + FactoryGirl.create( + :comment, + author: bob.person, + text: text_mentioning(alice, eve), + post: status_message + ) + } + + it "sends only mention notification" do + [alice, eve].each do |user| + expect(Workers::Mail::MentionedInComment).to receive(:perform_async).with( + user.id, + bob.person.id, + *comment.mentions.where(person: user.person).ids + ) + end + + expect { + NotificationService.new.notify(comment, []) + }.to change { Notification.where(recipient_id: alice).count }.by(1) + .and change { Notification.where(recipient_id: eve).count }.by(1) + + [alice, eve].each do |user| + expect( + Notifications::MentionedInComment.where(target: comment.mentions, recipient_id: user.id) + ).to exist + + expect( + Notifications::CommentOnPost.where(target: comment.parent, recipient_id: user.id) + ).not_to exist + + expect( + Notifications::AlsoCommented.where(target: comment.parent, recipient_id: user.id) + ).not_to exist + end + end + + context "with \"mentioned in comment\" email turned off" do + before do + alice.user_preferences.create(email_type: "mentioned_in_comment") + eve.user_preferences.create(email_type: "mentioned_in_comment") + end + + it "calls appropriate mail worker instead" do + expect(Workers::Mail::MentionedInComment).not_to receive(:perform_async) + + expect(Workers::Mail::CommentOnPost).to receive(:perform_async).with( + alice.id, + bob.person.id, + *comment.mentions.where(person: alice.person).ids + ) + + expect(Workers::Mail::AlsoCommented).to receive(:perform_async).with( + eve.id, + bob.person.id, + *comment.mentions.where(person: eve.person).ids + ) + + NotificationService.new.notify(comment, []) + end + end + end + end +end diff --git a/spec/services/post_service_spec.rb b/spec/services/post_service_spec.rb index 3d6b96a48..b19a1638d 100644 --- a/spec/services/post_service_spec.rb +++ b/spec/services/post_service_spec.rb @@ -111,6 +111,8 @@ describe PostService do end describe "#mark_user_notifications" do + let(:status_text) { text_mentioning(alice) } + it "marks a corresponding notifications as read" do FactoryGirl.create(:notification, recipient: alice, target: post, unread: true) FactoryGirl.create(:notification, recipient: alice, target: post, unread: true) @@ -121,7 +123,6 @@ describe PostService do end it "marks a corresponding mention notification as read" do - status_text = "this is a text mentioning @{Mention User ; #{alice.diaspora_handle}} ... have fun testing!" mention_post = bob.post(:status_message, text: status_text, public: true) expect { @@ -129,6 +130,16 @@ describe PostService do }.to change(Notification.where(unread: true), :count).by(-1) end + it "marks a corresponding mention in comment notification as read" do + notification = FactoryGirl.create(:notification_mentioned_in_comment) + status_message = notification.target.mentions_container.parent + user = notification.recipient + + expect { + PostService.new(user).mark_user_notifications(status_message.id) + }.to change(Notification.where(unread: true), :count).by(-1) + end + it "does not change the update_at date/time for post notifications" do notification = Timecop.travel(1.minute.ago) do FactoryGirl.create(:notification, recipient: alice, target: post, unread: true) @@ -140,7 +151,6 @@ describe PostService do end it "does not change the update_at date/time for mention notifications" do - status_text = "this is a text mentioning @{Mention User ; #{alice.diaspora_handle}} ... have fun testing!" mention_post = Timecop.travel(1.minute.ago) do bob.post(:status_message, text: status_text, public: true) end diff --git a/spec/services/status_message_creation_service_spec.rb b/spec/services/status_message_creation_service_spec.rb index 80631f266..47838d172 100644 --- a/spec/services/status_message_creation_service_spec.rb +++ b/spec/services/status_message_creation_service_spec.rb @@ -151,44 +151,6 @@ describe StatusMessageCreationService do end end - context "with mentions" do - let(:mentioned_user) { FactoryGirl.create(:user) } - let(:text) { - "Hey @{#{bob.name}; #{bob.diaspora_handle}} and @{#{mentioned_user.name}; #{mentioned_user.diaspora_handle}}!" - } - - it "calls Diaspora::Mentionable#filter_for_aspects for private posts" do - expect(Diaspora::Mentionable).to receive(:filter_for_aspects).with(text, alice, aspect.id.to_s) - .and_call_original - StatusMessageCreationService.new(alice).create(params) - end - - it "keeps mentions for users in one of the aspects" do - status_message = StatusMessageCreationService.new(alice).create(params) - expect(status_message.text).to include bob.name - expect(status_message.text).to include bob.diaspora_handle - end - - it "removes mentions for users in other aspects" do - status_message = StatusMessageCreationService.new(alice).create(params) - expect(status_message.text).to include mentioned_user.name - expect(status_message.text).not_to include mentioned_user.diaspora_handle - end - - it "doesn't call Diaspora::Mentionable#filter_for_aspects for public posts" do - expect(Diaspora::Mentionable).not_to receive(:filter_for_aspects) - StatusMessageCreationService.new(alice).create(params.merge(public: true)) - end - - it "keeps all mentions in public posts" do - status_message = StatusMessageCreationService.new(alice).create(params.merge(public: true)) - expect(status_message.text).to include bob.name - expect(status_message.text).to include bob.diaspora_handle - expect(status_message.text).to include mentioned_user.name - expect(status_message.text).to include mentioned_user.diaspora_handle - end - end - context "dispatch" do it "dispatches the StatusMessage" do expect(alice).to receive(:dispatch_post).with(instance_of(StatusMessage), hash_including(service_types: [])) @@ -201,6 +163,16 @@ describe StatusMessageCreationService do hash_including(service_types: array_including(%w(Services::Facebook Services::Twitter)))) StatusMessageCreationService.new(alice).create(params.merge(services: %w(twitter facebook))) end + + context "with mention" do + let(:text) { text_mentioning(eve) } + + # this is only required until changes from #6818 are deployed on every pod + it "filters out mentions from text attribute" do + status_message = StatusMessageCreationService.new(alice).create(params) + expect(status_message.text).not_to include(eve.diaspora_handle) + end + end end end end diff --git a/spec/shared_behaviors/mentions_container.rb b/spec/shared_behaviors/mentions_container.rb new file mode 100644 index 000000000..87dedfef5 --- /dev/null +++ b/spec/shared_behaviors/mentions_container.rb @@ -0,0 +1,44 @@ +shared_examples_for "it is mentions container" do + let(:people) { [alice, bob, eve].map(&:person) } + let(:test_string) { + "@{Raphael; #{people[0].diaspora_handle}} can mention people like @{Ilya; #{people[1].diaspora_handle}}"\ + "can mention people like @{Daniel; #{people[2].diaspora_handle}}" + } + let(:target) { FactoryGirl.build(described_class.to_s.underscore.to_sym, text: test_string, author: alice.person) } + let(:target_persisted) { + target.save! + target + } + + describe ".after_create" do + it "calls create_mentions" do + expect(target).to receive(:create_mentions).and_call_original + target.save + end + end + + describe "#create_mentions" do + it "creates a mention for everyone mentioned in the message" do + people.each do |person| + expect(target.mentions).to receive(:find_or_create_by).with(person_id: person.id) + end + target.create_mentions + end + + it "does not barf if it gets called twice" do + expect { + target_persisted.create_mentions + }.to_not raise_error + end + end + + describe "#mentioned_people" do + it "returns the mentioned people if non-persisted" do + expect(target.mentioned_people).to match_array(people) + end + + it "returns the mentioned people if persisted" do + expect(target_persisted.mentioned_people).to match_array(people) + end + end +end diff --git a/spec/workers/mail/mentioned_spec.rb b/spec/workers/mail/mentioned_spec.rb index 5d8d76cd7..cc06f5d58 100644 --- a/spec/workers/mail/mentioned_spec.rb +++ b/spec/workers/mail/mentioned_spec.rb @@ -7,11 +7,12 @@ describe Workers::Mail::Mentioned do it "should call .deliver on the notifier object" do user = alice sm = FactoryGirl.build(:status_message) - m = Mention.new(:person => user.person, :post=> sm) + m = Mention.new(person: user.person, mentions_container: sm) mail_double = double() expect(mail_double).to receive(:deliver_now) - expect(Notifier).to receive(:send_notification).with("mentioned", user.id, sm.author.id, m.id).and_return(mail_double) + expect(Notifier).to receive(:send_notification) + .with("mentioned", user.id, sm.author.id, m.id).and_return(mail_double) Workers::Mail::Mentioned.new.perform(user.id, sm.author.id, m.id) end From 154ea6515af8483e634d6b46adc8d522543e682e Mon Sep 17 00:00:00 2001 From: Steffen van Bergerem Date: Tue, 29 Nov 2016 23:36:42 +0100 Subject: [PATCH 004/318] Fix mentions in comments migration on PostgreSQL --- db/migrate/20161107100840_polymorphic_mentions.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/db/migrate/20161107100840_polymorphic_mentions.rb b/db/migrate/20161107100840_polymorphic_mentions.rb index 07b096394..2f00e65fe 100644 --- a/db/migrate/20161107100840_polymorphic_mentions.rb +++ b/db/migrate/20161107100840_polymorphic_mentions.rb @@ -3,7 +3,7 @@ class PolymorphicMentions < ActiveRecord::Migration remove_index :mentions, column: %i(post_id) remove_index :mentions, column: %i(person_id post_id), unique: true rename_column :mentions, :post_id, :mentions_container_id - add_column :mentions, :mentions_container_type, :string, null: false + add_column :mentions, :mentions_container_type, :string add_index :mentions, %i(mentions_container_id mentions_container_type), name: "index_mentions_on_mc_id_and_mc_type", @@ -26,6 +26,7 @@ class PolymorphicMentions < ActiveRecord::Migration def up_down(change) change.up do Mention.update_all(mentions_container_type: "Post") + change_column :mentions, :mentions_container_type, :string, null: false Notification.where(type: "Notifications::Mentioned").update_all(type: "Notifications::MentionedInPost") end From 52b7d6ed9ebc6b5af9da4348925928f488b81248 Mon Sep 17 00:00:00 2001 From: Dennis Schubert Date: Tue, 13 Dec 2016 18:48:44 +0100 Subject: [PATCH 005/318] updated 121 locale files [ci skip] --- config/locales/devise/devise.hu.yml | 16 +- config/locales/devise/devise.ia.yml | 24 +- config/locales/devise/devise.ja.yml | 4 +- config/locales/devise/devise.nl.yml | 5 + config/locales/devise/devise.sv.yml | 29 +- config/locales/diaspora/ar.yml | 9 - config/locales/diaspora/bg.yml | 9 - config/locales/diaspora/br.yml | 10 - config/locales/diaspora/bs.yml | 10 - config/locales/diaspora/cs.yml | 11 - config/locales/diaspora/da.yml | 11 - config/locales/diaspora/de-CH.yml | 292 +++++++++--------- config/locales/diaspora/de.yml | 75 +++-- config/locales/diaspora/de_formal.yml | 76 +++-- config/locales/diaspora/el.yml | 10 - config/locales/diaspora/en_1337.yml | 9 - config/locales/diaspora/en_pirate.yml | 5 - config/locales/diaspora/en_shaw.yml | 6 - config/locales/diaspora/en_valspeak.yml | 10 - config/locales/diaspora/eo.yml | 10 - config/locales/diaspora/es-AR.yml | 67 +++- config/locales/diaspora/es-CL.yml | 10 - config/locales/diaspora/es-CO.yml | 9 - config/locales/diaspora/es-MX.yml | 10 - config/locales/diaspora/es.yml | 15 +- config/locales/diaspora/eu.yml | 9 - config/locales/diaspora/fi.yml | 10 - config/locales/diaspora/fr.yml | 71 ++++- config/locales/diaspora/fy.yml | 1 - config/locales/diaspora/ga.yml | 1 - config/locales/diaspora/he.yml | 10 - config/locales/diaspora/hu.yml | 170 +++++++--- config/locales/diaspora/hy.yml | 28 +- config/locales/diaspora/ia.yml | 290 +++++++++++------ config/locales/diaspora/id.yml | 9 - config/locales/diaspora/is.yml | 7 - config/locales/diaspora/it.yml | 10 - config/locales/diaspora/ja.yml | 120 +++---- config/locales/diaspora/ka.yml | 9 - config/locales/diaspora/ko.yml | 10 - config/locales/diaspora/lt.yml | 7 - config/locales/diaspora/mk.yml | 7 - config/locales/diaspora/ml.yml | 10 - config/locales/diaspora/nb.yml | 10 - config/locales/diaspora/nds.yml | 10 - config/locales/diaspora/ne.yml | 1 - config/locales/diaspora/nl.yml | 28 +- config/locales/diaspora/nn.yml | 10 - config/locales/diaspora/oc.yml | 37 ++- config/locales/diaspora/pl.yml | 10 - config/locales/diaspora/pt-BR.yml | 69 ++++- config/locales/diaspora/pt-PT.yml | 10 - config/locales/diaspora/ro.yml | 10 - config/locales/diaspora/ru.yml | 11 - config/locales/diaspora/si.yml | 1 - config/locales/diaspora/sk.yml | 10 - config/locales/diaspora/sl.yml | 10 - config/locales/diaspora/sr.yml | 5 - config/locales/diaspora/sv.yml | 63 ++-- config/locales/diaspora/te.yml | 10 - config/locales/diaspora/tr.yml | 32 +- config/locales/diaspora/uk.yml | 10 - config/locales/diaspora/vi.yml | 10 - config/locales/diaspora/wo.yml | 1 - config/locales/diaspora/zh-CN.yml | 9 - config/locales/diaspora/zh-TW.yml | 52 +++- config/locales/javascript/javascript.ar.yml | 4 - config/locales/javascript/javascript.bg.yml | 3 - config/locales/javascript/javascript.br.yml | 2 - config/locales/javascript/javascript.bs.yml | 2 - config/locales/javascript/javascript.cs.yml | 3 - config/locales/javascript/javascript.cy.yml | 3 - config/locales/javascript/javascript.da.yml | 4 - .../locales/javascript/javascript.de-CH.yml | 36 +++ config/locales/javascript/javascript.de.yml | 11 +- .../javascript/javascript.de_formal.yml | 12 +- config/locales/javascript/javascript.el.yml | 2 - .../locales/javascript/javascript.en_1337.yml | 3 - .../javascript/javascript.en_pirate.yml | 2 - .../locales/javascript/javascript.en_shaw.yml | 3 - .../javascript/javascript.en_valspeak.yml | 2 - config/locales/javascript/javascript.eo.yml | 2 - .../locales/javascript/javascript.es-AR.yml | 11 +- .../locales/javascript/javascript.es-CL.yml | 2 - .../locales/javascript/javascript.es-MX.yml | 2 - config/locales/javascript/javascript.es.yml | 4 - config/locales/javascript/javascript.eu.yml | 2 - config/locales/javascript/javascript.fi.yml | 3 - config/locales/javascript/javascript.fr.yml | 11 +- config/locales/javascript/javascript.he.yml | 2 - config/locales/javascript/javascript.hu.yml | 20 +- config/locales/javascript/javascript.hy.yml | 4 - config/locales/javascript/javascript.ia.yml | 46 ++- config/locales/javascript/javascript.id.yml | 3 - config/locales/javascript/javascript.is.yml | 2 - config/locales/javascript/javascript.it.yml | 2 - config/locales/javascript/javascript.ja.yml | 22 +- config/locales/javascript/javascript.ka.yml | 3 - config/locales/javascript/javascript.ko.yml | 2 - config/locales/javascript/javascript.lt.yml | 3 - config/locales/javascript/javascript.ml.yml | 2 - config/locales/javascript/javascript.ms.yml | 2 - config/locales/javascript/javascript.nb.yml | 3 - config/locales/javascript/javascript.nl.yml | 31 +- config/locales/javascript/javascript.nn.yml | 2 - config/locales/javascript/javascript.oc.yml | 4 - config/locales/javascript/javascript.pl.yml | 3 - .../locales/javascript/javascript.pt-BR.yml | 11 +- .../locales/javascript/javascript.pt-PT.yml | 2 - config/locales/javascript/javascript.ro.yml | 3 - config/locales/javascript/javascript.ru.yml | 3 - config/locales/javascript/javascript.sk.yml | 2 - config/locales/javascript/javascript.sl.yml | 2 - config/locales/javascript/javascript.sr.yml | 3 - config/locales/javascript/javascript.sv.yml | 37 ++- config/locales/javascript/javascript.te.yml | 4 - config/locales/javascript/javascript.tr.yml | 2 - config/locales/javascript/javascript.uk.yml | 3 - config/locales/javascript/javascript.vi.yml | 2 - .../locales/javascript/javascript.zh-CN.yml | 2 - .../locales/javascript/javascript.zh-TW.yml | 10 +- 121 files changed, 1202 insertions(+), 1109 deletions(-) create mode 100644 config/locales/javascript/javascript.de-CH.yml diff --git a/config/locales/devise/devise.hu.yml b/config/locales/devise/devise.hu.yml index c0e6aa96d..ebcbfea97 100644 --- a/config/locales/devise/devise.hu.yml +++ b/config/locales/devise/devise.hu.yml @@ -7,7 +7,7 @@ hu: devise: confirmations: - confirmed: "Fiókod megerősítve. Be vagy jelentkezve." + confirmed: "Az e-mail címedet sikeresen megerősítetted." new: resend_confirmation: "Megerősítési utasítások újraküldése" send_instructions: "Pár percen belül kapsz egy e-mailt, benne a megerősítéshez szükséges utasításokkal." @@ -18,12 +18,12 @@ hu: locked: "A fiókod zárolva van." not_found_in_database: "Érvénytelen e-mail cím vagy jelszó" timeout: "A munkamenet lejárt, kérjük jelentkezz be újra." - unauthenticated: "A továbblépéshez jelentkezz be vagy iratkozz fel." + unauthenticated: "A továbblépéshez bejelentkezés vagy regisztráció szükséges." unconfirmed: "Előbb meg kell erősítened fiókodat." invitations: invitation_token_invalid: "Sajnáljuk, de a meghívás nem érvényes." send_instructions: "A meghívód elküldve." - updated: "A jelszó módosítva. Be vagy jelentkezve." + updated: "A jelszó beállítva. Bejelentkeztél." mailer: confirmation_instructions: confirm: "Fiókom megerősítése" @@ -56,9 +56,9 @@ hu: forgot_password: "Elfelejtetted a jelszavad?" no_account: "Ehhez az e-mail címhez nem tartozik fiók." reset_password: "Jelszó visszaállítása" - send_password_instructions: "Küldd el nekem a jelszó alaphelyzetbe állításához szükséges utasításokat" + send_password_instructions: "Új jelszót igénylek" send_instructions: "Néhány perc múlva kapsz egy e-mailt arról, hogyan állíthatod alaphelyzetbe a jelszavadat." - updated: "A jelszavad megváltozott. Be vagy jelentkezve vele." + updated: "A jelszavad megváltozott. Sikeresen bejelentkeztél." registrations: destroyed: "Viszlát! A fiókod törölve. Reméljük hamarosan újra látunk. =)" signed_up: "Sikeresen feliratkoztál. Ha engedélyezve van, akkor egy megerősítő e-mailt küldünk." @@ -79,13 +79,13 @@ hu: receive_confirmation: "Nem kaptál megerősítési utasítást?" receive_unlock: "Nem kaptad meg feloldási utasítást?" sign_in: "Bejelentkezés" - sign_up: "Feliratkozás" - sign_up_closed: "Nincs nyílt feliratkozási lehetőség jelenleg." + sign_up: "Fiók létrehozása" + sign_up_closed: "A nyílt regisztrálás jelenleg nem hozzáférhető." unlocks: new: resend_unlock: "Feloldási utasítások újraküldése" send_instructions: "Pár percen belül kapsz egy e-mailt, benne a feloldáshoz szükséges utasításokkal." - unlocked: "A fiókod sikeresen feloldva. Be vagy jelentkezve." + unlocked: "A fiókod sikeresen feloldva. Jelentkezz be a folytatáshoz." errors: messages: already_confirmed: "már megerősítette" diff --git a/config/locales/devise/devise.ia.yml b/config/locales/devise/devise.ia.yml index 433159229..bde47d17f 100644 --- a/config/locales/devise/devise.ia.yml +++ b/config/locales/devise/devise.ia.yml @@ -11,10 +11,13 @@ ia: new: resend_confirmation: "Reinviar instructiones pro confirmar" send_instructions: "Tu recipera in pauc minutas un message de e-mail con instructiones pro confirmar tu conto." + send_paranoid_instructions: "Si tu adresse de e-mail existe in nostre base de datos, tu recipera in pauc minutas un e-mail con instructiones pro confirmar tu adresse de e-mail." failure: + already_authenticated: "Tu ha jam aperite session." inactive: "Tu conto non ha ancora essite activate." invalid: "Nomine de usator o contrasigno invalide." invalid_token: "Indicio de authentication invalide." + last_attempt: "Tu pote tentar solmente un altere vice ante que le conto es blocate." locked: "Tu conto es blocate." not_found_in_database: "E-mail o contrasigno invalide." timeout: "Le session ha expirate. Per favor aperi session de novo pro continuar." @@ -34,6 +37,8 @@ ia: accept_at: "a %{url}, tu pote acceptar lo per le ligamine sequente." has_invited_you: "%{name}" have_invited_you: "%{names} te ha invitate a unir te a diaspora*" + password_change: + subject: "Contrasigno cambiate" reset_password_instructions: change: "Cambiar mi contrasigno" ignore: "Si tu non ha demandate isto, per favor ignora iste message." @@ -46,6 +51,9 @@ ia: subject: "Instructiones pro disblocar" unlock: "Disblocar mi conto" welcome: "Benvenite, %{email}!" + omniauth_callbacks: + failure: "Impossibile authenticar te a partir de %{kind} perque \"%{reason}\"." + success: "Authentication a partir del conto %{kind} succedite." passwords: edit: change_password: "Cambiar mi contrasigno" @@ -57,13 +65,21 @@ ia: no_account: "Nulle conto con iste adresse de e-mail existe." reset_password: "Reinitialisar contrasigno" send_password_instructions: "Inviar instructiones pro reinitialisar contrasigno" + no_token: "Tu non pote acceder a iste pagina sin venir ab un e-mail pro reinitialisar contrasigno. Si tu de facto veni ab un e-mail pro reinitialisar contrasigno, per favor assecura te de usar le totalitate del URL fornite." send_instructions: "Tu recipera in pauc minutas un message de e-mail con instructiones pro reinitialisar le contrasigno." + send_paranoid_instructions: "Si tu adresse de e-mail existe in nostre base de datos, tu recipera in pauc minutas un e-mail con un ligamine pro recuperar le contrasigno." updated: "Le contrasigno ha essite cambiate con successo. Tu ha aperite session." + updated_not_active: "Tu contrasigno ha essite cambiate." registrations: destroyed: "Adeo! Le deletion de tu conto ha succedite. Nos spera revider te bentosto." signed_up: "Conto create con successo. Si applicabile, un confirmation ha essite inviate a tu adresse de e-mail." + signed_up_but_inactive: "Le creation de tu conto ha succedite. Totevia, nos non ha potite aperir tu session perque tu conto non es ancora activate." + signed_up_but_locked: "Le creation de tu conto ha succedite. Totevia, nos non ha potite aperir tu session perque tu conto es blocate." + signed_up_but_unconfirmed: "Un message con un ligamine de confirmation ha essite inviate a tu adresse de e-mail. Per favor, seque le ligamine pro activar tu conto." + update_needs_confirmation: "Tu ha actualisate tu conto, ma nos debe verificar tu nove adresse de e-mail. Per favor, lege tu e-mail e seque le ligamine de confirmation pro confirmar tu nove adresse de e-mail." updated: "Conto actualisate con successo." sessions: + already_signed_out: "Le session ha essite claudite." new: login: "Aperir session" modern_browsers: "supporta solmente le navigatores moderne." @@ -85,9 +101,15 @@ ia: new: resend_unlock: "Reinviar instructiones pro disblocar" send_instructions: "Tu recipera in pauc minutas un message de e-mail con instructiones pro disblocar tu conto." + send_paranoid_instructions: "Si tu conto existe, tu recipera in pauc minutas un e-mail con instructiones pro disblocar lo." unlocked: "Conto disblocate con successo. Tu ha aperite session." errors: messages: already_confirmed: "ha jam essite confirmate" + confirmation_period_expired: "debe esser confirmate intra %{period}, per favor requesta un altere" + expired: "ha expirate, per favor requesta un altere" not_found: "non trovate" - not_locked: "non ha essite blocate" \ No newline at end of file + not_locked: "non ha essite blocate" + not_saved: + one: "Un error ha impedite iste %{resource} de esser salveguardate:" + other: "%{count} errores ha impedite iste %{resource} de esser salveguardate:" \ No newline at end of file diff --git a/config/locales/devise/devise.ja.yml b/config/locales/devise/devise.ja.yml index 4f2f0a0fd..17bb41697 100644 --- a/config/locales/devise/devise.ja.yml +++ b/config/locales/devise/devise.ja.yml @@ -20,7 +20,7 @@ ja: last_attempt: "アカウントがロックされるまでに、まだ複数回試すことができます。" locked: "アカウントがロックされています。" not_found_in_database: "%{authentication_keys}またはパスワードが無効です。" - timeout: "セッション切れになりました。続くにはもう一度サインインしてください。" + timeout: "セッション切れになりました。もう一度サインインして続行してください。" unauthenticated: "進むにはサインインまたは新規登録する必要があります。" unconfirmed: "進にはアカウントを確認する必要があります。" invitations: @@ -62,7 +62,7 @@ ja: new: email: "メールアドレス" forgot_password: "パスワードを忘れましたか?" - no_account: "このメールアドレスに一致するアカウントは存在しません。招待待ちの方は、なるべく早く出せるように努力していますので、もう少々お待ちください。" + no_account: "このメールアドレスに一致するアカウントは存在しません" reset_password: "パスワードの再設定" send_password_instructions: "パスワード再発行の手続きメールを送ってください。" no_token: "パスワードリセットのメールからではないと、このページにアクセスすることはできません。パスワードリセットのメールから来た場合は、提供された完全なURLを使用していることを確認してください。" diff --git a/config/locales/devise/devise.nl.yml b/config/locales/devise/devise.nl.yml index 5737adb57..25d2f5c88 100644 --- a/config/locales/devise/devise.nl.yml +++ b/config/locales/devise/devise.nl.yml @@ -12,6 +12,7 @@ nl: resend_confirmation: "Stuur bevestigingsinstructies nogmaals" send_instructions: "Je ontvangt binnen enkele minuten een e-mail met instructies om je account te activeren." failure: + already_authenticated: "Je bent al ingelogd." inactive: "Je account is nog niet geactiveerd." invalid: "Gebruikersnaam of wachtwoord ongeldig." invalid_token: "Ongeldig authenticatietoken." @@ -34,6 +35,8 @@ nl: accept_at: "op %{url}, je kunt deze accepteren via onderstaande link." has_invited_you: "%{name}" have_invited_you: "%{names} heeft je uitgenodigd om lid te worden van diaspora*" + password_change: + subject: "Wachtwoord gewijzigd" reset_password_instructions: change: "Wijzig mijn wachtwoord" ignore: "Als je hier niet om hebt gevraagd kun je deze mail gewoon negeren." @@ -64,6 +67,7 @@ nl: signed_up: "Je bent succesvol geregistreerd. Indien aangevinkt is er een bevestiging naar je e-mail gestuurd." updated: "Je account is succesvol geüpdate." sessions: + already_signed_out: "Succesvol uitgelogd." new: login: "Inloggen" modern_browsers: "ondersteunt alleen moderne browsers." @@ -89,5 +93,6 @@ nl: errors: messages: already_confirmed: "is al geactiveerd" + expired: "is vervallen, vraag een nieuwe aan" not_found: "niet gevonden" not_locked: "is niet geblokkeerd" \ No newline at end of file diff --git a/config/locales/devise/devise.sv.yml b/config/locales/devise/devise.sv.yml index 765609003..1d61a9201 100644 --- a/config/locales/devise/devise.sv.yml +++ b/config/locales/devise/devise.sv.yml @@ -10,14 +10,17 @@ sv: confirmed: "Din e-postadress har verifierats." new: resend_confirmation: "Skicka instruktioner för att bekräfta kontot igen" - send_instructions: "Du kommer att få ett e-brev med instruktioner för att verifiera din e-postadress inom några minuter." + send_instructions: "Du kommer inom några minuter att få ett e-brev med instruktioner för att verifiera din e-postadress." + send_paranoid_instructions: "Om din e-postadress finns i vår databas, kommer du att få ett brev med instruktioner om hur du på några minuter bekräftar din adress." failure: + already_authenticated: "Du är redan inloggad." inactive: "Ditt konto är inte aktiverat ännu." invalid: "Fel %{authentication_keys} eller lösenord." invalid_token: "Ogiltig identifiering." + last_attempt: "Du har ett försök till innan du blir utelåst." locked: "Ditt konto är låst." not_found_in_database: "Ogiltig %{authentication_keys} eller ogiltigt lösenord." - timeout: "Din session är avslutad, var vänlig logga in igen för att fortsätta." + timeout: "Din session är avslutad. Vänligen logga in igen för att fortsätta." unauthenticated: "Du måste logga in innan du kan fortsätta." unconfirmed: "Du måste verifiera din e-postadress innan du kan fortsätta." invitations: @@ -34,6 +37,8 @@ sv: accept_at: "via %{url}. Du accepterar genom att klicka på länken nedan." has_invited_you: "%{name}" have_invited_you: "%{names} har bjudit in dig att gå med i Diaspora*" + password_change: + subject: "Lösenordet är bytt" reset_password_instructions: change: "Ändra mitt lösenord" ignore: "Om det inte är du som vill byta lösenord så kan du ignorera det här mailet." @@ -46,6 +51,9 @@ sv: subject: "Upplåsningsinstruktioner" unlock: "Lås upp mitt konto" welcome: "Välkommen %{email}!" + omniauth_callbacks: + failure: "Kunde inte autentisera dig från %{kind} på grund av: %{reason}" + success: "Lyckades autentisera från kontot %{kind}." passwords: edit: change_password: "Ändra mitt lösenord" @@ -57,13 +65,21 @@ sv: no_account: "Det finns inget konto med den här e-postadressen." reset_password: "Återställ lösenord" send_password_instructions: "Skicka information om hur jag återställer lösenordet" - send_instructions: "Du kommer att få ett e-brev med instruktioner för att återställa lösenordet inom några minuter." + no_token: "Du får inte tillgång till den här sidan utan en länk för att ställa in ett nytt lösenord via e-post. Om du kom hit genom en sådan, kontrollera att de använde hela URL:en som angavs." + send_instructions: "Du kommer inom några minuter att få ett e-brev med instruktioner för att återställa lösenordet." + send_paranoid_instructions: "Om din e-postadress finns i vår databas, kommer du inom några få minuter att få en länk skickad till dig för att kunna återställa ditt lösenord." updated: "Ditt lösenord har ändrats och du är nu inloggad." + updated_not_active: "Ditt lösenord är ändrat." registrations: destroyed: "Ditt konto är avslutat. På återseende!" signed_up: "Du har skapat ett konto. Beroende på dina inställningar kan en bekräftelse ha skickats till din e-postadress." + signed_up_but_inactive: "Du har nu registrerat dig, men du kommer inte kunna logga in förrän ditt konto är aktiverat." + signed_up_but_locked: "Du har nu registrerat dig, men du kan inte logga in medans ditt konto är låst." + signed_up_but_unconfirmed: "En bekräftelselänk är du skickad till dig via e-post. Följ den för att aktivera ditt konto." + update_needs_confirmation: "Ditt konto har uppdaterats, men vi måste bekräfta din nya e-postadress. Titta i din inkorg och följ länken från oss för att bekräfta din nya adress." updated: "Ditt konto har uppdateras." sessions: + already_signed_out: "Utloggningen lyckades." new: login: "Logga in" modern_browsers: "stöder endast moderna webbläsare." @@ -84,11 +100,14 @@ sv: unlocks: new: resend_unlock: "Skicka upplåsningsinstruktioner igen" - send_instructions: "Du kommer att få ett e-brev med instruktioner för att låsa upp ditt konto inom några minuter." - unlocked: "Ditt konto har är nu upplåst. Logga in för att fortsätta." + send_instructions: "Du kommer inom några minuter att få ett e-brev med instruktioner för att låsa upp ditt konto." + send_paranoid_instructions: "Om ditt konto finns, kommer du inom några minuter att få ett e-brev med instruktioner för hur du låser upp det." + unlocked: "Ditt konto har är nu upplåst. Vänligen logga in för att fortsätta." errors: messages: already_confirmed: "var redan bekräftad, prova att logga in" + confirmation_period_expired: "behöver bekräftas inom %{period}. Var vänlig ange en ny" + expired: "har löpt ut. Var vänlig ange en ny" not_found: "inte funnet" not_locked: "var ej låst" not_saved: diff --git a/config/locales/diaspora/ar.yml b/config/locales/diaspora/ar.yml index fea24a3d7..6ce6fd608 100644 --- a/config/locales/diaspora/ar.yml +++ b/config/locales/diaspora/ar.yml @@ -187,9 +187,6 @@ ar: posts_and_posting: character_limit_a: "65535 محرفًا. هذا أكبر بِـ 65395 محرفًا الذي تحصل عليها في تويتر! ؛)" invitations: - a_facebook_user: "مستخدم فايسبوك" - check_token: - not_found: "الدعوة الرمزية غير موجودة" create: no_more: "لم يتبقى لك أية دعوات" rejected: "واجه هذا البريد الإلكتروني مشاكلا: " @@ -395,14 +392,8 @@ ar: type_error: "فشل رفع الصورة، أواثقٌ أن صورة ما قد أُضيفَت؟" destroy: notice: "حُذِفَت الصورة." - new_photo: - empty: "{file} فارغ، رجاءًا أَعِد تحديد الملفات دونه." - invalid_ext: "{file} له صيغة غير صالحة. {extensions} هي الصيغ الوحيدة المسموح بها." - size_error: "{file} ذو حجم كبير جدا, {sizeLimit} هو الحجم الأقصى المسموح به." new_profile_photo: upload: "ارْفَع صورةً شخصيةً جديدة" - show: - show_original_post: "إِعرِضْ المشاركة الأصلية" posts: presenter: title: "مشاركة من %{name}" diff --git a/config/locales/diaspora/bg.yml b/config/locales/diaspora/bg.yml index 5b049ed14..c088e17fb 100644 --- a/config/locales/diaspora/bg.yml +++ b/config/locales/diaspora/bg.yml @@ -150,9 +150,6 @@ bg: fill_me_out: "Попълнете ме" find_people: "Намерете хора или #марки" invitations: - a_facebook_user: "Потребител на Facebook" - check_token: - not_found: "Данните за поканата не са намерени" create: no_more: "Не разполагате с повече покани." rejected: "Възникна проблем със следната ел. поща: " @@ -293,14 +290,8 @@ bg: type_error: "Снимката не бе качена. Сигурни ли сте, че е добавено изображение?" destroy: notice: "Снимката е изтрита." - new_photo: - empty: "{file} е празен. Моля, изберете наново файловете без празния." - invalid_ext: "{file} е с невалидно разширение. Позволени са само: {extensions}." - size_error: "{file} е твърде голям. Максималният разрешен размер е {sizeLimit}." new_profile_photo: upload: "Качете нова снимка за профила!" - show: - show_original_post: "Оригиналната публикация" posts: show: photos_by: diff --git a/config/locales/diaspora/br.yml b/config/locales/diaspora/br.yml index 2b515ef6e..ba230564e 100644 --- a/config/locales/diaspora/br.yml +++ b/config/locales/diaspora/br.yml @@ -201,7 +201,6 @@ br: conversations: create: fail: "kemennadenn direizh" - no_contact: "Alato, ezhomm ho peus ouzhpennañ an darempred da gentañ !" sent: "Kemennadenn bet kaset" index: conversations_inbox: "Kaozeadennoù – Boest degemer" @@ -314,9 +313,6 @@ br: tutorials: "kelennskridoù" wiki: "wiki" invitations: - a_facebook_user: "Un implijer eus Facebook" - check_token: - not_found: "N'eo ket bet kaset ar bilhed-pediñ" create: empty: "Merkit da nebeutañ ur chomlec'h postel." no_more: "N'ho 'peus pedadenn ebet ken." @@ -493,14 +489,8 @@ br: type_error: "C'hwitet war kargadenn ar skeudenn. Sur oc'h bezañ bet ouzhpennet ur skeudenn ?" destroy: notice: "Dilamet eo bet ar skeudenn" - new_photo: - empty: "{file} a zo goulo, diuzit ar restroù en-dro heptañ mar plij." - invalid_ext: "Ar restr {file} en deus ur astenn direizh. N'eus nemet {extensions} hag a zo asantet." - size_error: "Re vras eo {file}, {sizeLimit} eo ar ar vrasañ posupl." new_profile_photo: upload: "Kargit ur poltred nevez evit ho aelad !" - show: - show_original_post: "Diskouez an embannadenn orin" posts: presenter: title: "Un embannadenn a-berzh %{name}" diff --git a/config/locales/diaspora/bs.yml b/config/locales/diaspora/bs.yml index b61e05996..fa30b4d4a 100644 --- a/config/locales/diaspora/bs.yml +++ b/config/locales/diaspora/bs.yml @@ -201,7 +201,6 @@ bs: conversations: create: fail: "Nevažeća poruka" - no_contact: "Hej, morate prvo dodati kontakt!" sent: "Poruka poslata" index: inbox: "Pošta" @@ -285,9 +284,6 @@ bs: tutorials: "tutorijali" wiki: "wiki" invitations: - a_facebook_user: "Facebook korisnik" - check_token: - not_found: "Znakovi pozivnice nisu pronađeni" create: empty: "Molimo unesite najmanje jednu email adresu." no_more: "Nemate više pozivnica." @@ -477,14 +473,8 @@ bs: type_error: "Objavljivanje fotografije neuspješno. Jeste li sigurni da je slika dodana?" destroy: notice: "Fotografija izbrisana." - new_photo: - empty: "{file} je prazno, molimo izaberite datoteke ponovo bez toga." - invalid_ext: "{file} ima nevažeću ekstenziju. Samo {extensions} su dozvoljene." - size_error: "{file} je preveliko, maksimalna veličina datoteke je {sizeLimit}." new_profile_photo: upload: "Objavi novu fotografiju profila!" - show: - show_original_post: "Pokaži originalnu objavu" posts: presenter: title: "Objava od %{name}" diff --git a/config/locales/diaspora/cs.yml b/config/locales/diaspora/cs.yml index 70f712697..5165f2fd2 100644 --- a/config/locales/diaspora/cs.yml +++ b/config/locales/diaspora/cs.yml @@ -292,7 +292,6 @@ cs: conversations: create: fail: "Neplatná zpráva" - no_contact: "Hej, musíte kontakt nejdřív přidat!" sent: "Zpráva byla odeslána" destroy: delete_success: "Konverzace byla úspěšně smazána" @@ -556,7 +555,6 @@ cs: headline: "Vítejte v %{pod_name}" own_your_data: "Vlastni svá data" podmin: - admin_panel: "admin panel" contact_irc: "kontaktujte nás na IRC" contribute: "Pomoci" create_an_account: "Vytvořit účet" @@ -566,9 +564,6 @@ cs: invitation_codes: not_valid: "Kód této pozvánky již není platný." invitations: - a_facebook_user: "Uživatel Facebooku" - check_token: - not_found: "Pozvánka nebyla nalezena" create: empty: "Prosíme zadejte alespoň jednu emailovou adresu." no_more: "Nemáte žádné další pozvánky." @@ -844,14 +839,8 @@ cs: type_error: "Nahrání fotky selhalo. Jste si jist, že byl obrázek přidán?" destroy: notice: "Fotka smazána." - new_photo: - empty: "{file} je prázdný, prosím vyberte soubory znovu bez něho." - invalid_ext: "{file} má chybnou příponu. Jsou povoleny pouze {extensions}." - size_error: "{file} je přiliš veliký, maximální velikost je {sizeLimit}." new_profile_photo: upload: "Nahrajte novou profilovou fotku!" - show: - show_original_post: "Zobrazit původní příspěvek" polls: votes: few: "Zbývá %{count} hlasy" diff --git a/config/locales/diaspora/da.yml b/config/locales/diaspora/da.yml index 83c15bb60..65480bcbf 100644 --- a/config/locales/diaspora/da.yml +++ b/config/locales/diaspora/da.yml @@ -295,7 +295,6 @@ da: conversations: create: fail: "Ugyldig besked" - no_contact: "Hej, du kan tilføje din første kontaktperson!" sent: "Besked sendt" destroy: delete_success: "Konversationen er blevet slettet" @@ -561,7 +560,6 @@ da: own_your_data: "Vær i besiddelse af dine egne data" own_your_data_info: "Mange sociale netværk tjener penge på dine data ved at analysere din opførsel og derefter bruge informationen til at sælge reklamer. Diaspora bruger ikke dine data til noget, men står til rådighed så du kan kommunikere og dele med andre." podmin: - admin_panel: "admin panel" byline: "Du er i gang med at ændre internettet. Lad os komme i gang." configuration_info: "Åben %{database_path} og %{diaspora_path} i din favorit editor og gennemgå dem omhyggeligt. De er udførligt kommenteret." configure_your_pod: "Konfigurer din pod" @@ -583,9 +581,6 @@ da: invitation_codes: not_valid: "Invitationskoden er udløbet." invitations: - a_facebook_user: "En Facebook-bruger" - check_token: - not_found: "Invitation ikke fundet" create: empty: "Skriv mindst en e-mailadresse." no_more: "Du har ikke flere invitationer." @@ -880,14 +875,8 @@ da: type_error: "Billed-upload fejlede. Er du sikker på at et billede var tilføjet?" destroy: notice: "Billede slettet." - new_photo: - empty: "{file} er tom. Vælg venligst filer igen uden {file}." - invalid_ext: "{file} har en ugyldig filtype. Kun {udvidelser} er tilladt." - size_error: "{File} er for stor. Maksimal filstørrelse er {sizeLimit}." new_profile_photo: upload: "Upload et nyt profilbillede!" - show: - show_original_post: "Vis oprindeligt indlæg" polls: votes: one: "%{count} stemme indtil videre" diff --git a/config/locales/diaspora/de-CH.yml b/config/locales/diaspora/de-CH.yml index 4483360ad..6d0b3e86a 100644 --- a/config/locales/diaspora/de-CH.yml +++ b/config/locales/diaspora/de-CH.yml @@ -27,15 +27,15 @@ de-CH: reshare: attributes: root_guid: - taken: "Es isch guet, imfall - Du hesch de Post scho Wiitergseit!" + taken: "So guet, gäll? Du hesch de Biitrag scho wiitergseit!" user: attributes: email: - taken: "isch scho vergeh." + taken: "wird scho benutzt." person: - invalid: "isch ungültig" + invalid: "isch ungültig." username: - invalid: "isch ungültig, - Mer erlaubed nume Buechstabe, Nummere und Understrich." + invalid: "isch ungültig. Es sind nume Buechstabe, Nummere und Understrich erlaubt." taken: "isch scho vergeh." admins: admin_bar: @@ -45,8 +45,8 @@ de-CH: user_search: "Benutzer Suechi" weekly_user_stats: "Wöchentlichi Benutzerstatistik" stats: - 2weeks: "2 wuche" - 50_most: "50 meischt-benutzti täg's" + 2weeks: "2 Wuche" + 50_most: "50 meischt-benutzti Tags" current_segment: "S'aktuelle segment het durchschnittlich %{post_yest} biiträg pto Benutzer, sit em %{post_day}" daily: "Täglich" display_results: "Zeig d'ergäbnis usem %{segment} segment" @@ -62,22 +62,22 @@ de-CH: current_server: "S'Momentane Serverdatum isch %{date}" all_aspects: "Ali Aspekt" are_you_sure: "Bisch sicher?" - are_you_sure_delete_account: "Bisch sicher, dass din Account lösche willsch ? - da chasch nüm rückgängig mache!" + are_you_sure_delete_account: "Bisch sicher, dass din Account lösche willsch? - da chasch nüm rückgängig mache!" aspect_memberships: destroy: - failure: "Benutzer vom Aspekt entferne isch gschiiteret" - no_membership: "Han die uswählt Person i dem Aspekt nöd chönne finde." - success: "Benutzer erfolgriich vom Aspekt entfernt" + failure: "Person us em Aspekt entferne isch gschiiteret." + no_membership: "Die usgwählt Person isch i dem Aspekt nöd gfinde worde." + success: "Person erfolgriich us em Aspekt entfernt." aspects: add_to_aspect: failure: "De Kontakt zum Aspekt hinzuefüege isch fehlgschlage." - success: "Erfolgrich de Kontakt zum Aspekt hinzuegfüegt." + success: "Kontakt erfolgrich zum Aspekt hinzuegfüegt." aspect_listings: - add_an_aspect: "+ en Aspekt adde" + add_an_aspect: "+ en Aspekt hinzuefüege" aspect_stream: make_something: "Mach öppis" - stay_updated: "Bliib fresh" - stay_updated_explanation: "Din Haupt-Stream beinhaltet d'posts vo all dine Kontäkt, vo de täg's dene du folgsch und vo es paar kreative mit-diasporianerInne" + stay_updated: "Bliib uf em laufende" + stay_updated_explanation: "Din Haupt-Stream beinhaltet d'Biiträg vo all dine Kontäkt, vo de Tägs wo du folgsch und vo es paar kreative Mitglied vo de Community" destroy: failure: "%{name} het nöd chönne entfernt werde" success: "%{name} isch erfolgriich entfernt worde." @@ -87,45 +87,45 @@ de-CH: confirm_remove_aspect: "Bisch sicher, das de Aspekt lösche willsch?" rename: "Umbenenne" update: "Ändere" - updating: "am Ändere" + updating: "wird gänderet..." index: donate: "Spende" help: any_problem: "Git's es Problem?" contact_podmin: "Kontaktier de Admin vo dim Pod!" do_you: "Hesch du:" - feature_suggestion: "en vorschlag für e %{link}?" - find_a_bug: "en %{link} gfunde?" - have_a_question: "en %{link}" - here_to_help: "d'Diaspora* Komunity isch do!" + feature_suggestion: "... en Vorschlag für e %{link}?" + find_a_bug: "... en %{link} gfunde?" + have_a_question: "... en %{link}" + here_to_help: "d'diaspora* Community isch do für di!" mail_podmin: "Podmin email" need_help: "Bruchsch Hilf?" - tag_bug: "en bug" - tag_feature: "e Verbesserig" - tag_question: "e Frog" + tag_bug: "Fähler" + tag_feature: "Verbesserig" + tag_question: "Frog" introduce_yourself: "Das isch din Stream. Gump ine und stell dich vor." - keep_pod_running: "Hilf %{pod} schnell d'sii und finanzier mitere monatliche chliine spend de schuss kafi wo's defür bruuched" + keep_pod_running: "Hilf %{pod} schnell d'sii und finanzier mitere monatliche chliine spend de schuss kafi wo's defür bruuched!" new_here: - follow: "Folg %{link} und heiss neui Benutzer bi Diaspora* willkomme !" - learn_more: "meh info's" - title: "Tuen neui Benutzer Wilkomme heisse" + follow: "Folg %{link} und begrüess neui Benutzer bi diaspora*!" + learn_more: "Meh Infos" + title: "Begrüess neui Benutzer" services: - content: "Du chasch folgendi Dienst mit Diaspora* verbinde:" - heading: "Dienst verbinde" - welcome_to_diaspora: "Willkomme bi Diaspora*, %{name}!" + content: "Du chasch folgendi Dienscht mit diaspora* verbinde:" + heading: "Dienscht verbinde" + welcome_to_diaspora: "Willkomme bi diaspora*, %{name}!" no_contacts_message: - community_spotlight: "Kommunity Schiiwörferliecht" - or_spotlight: "Oder du chasch mit %{link} Teile" - try_adding_some_more_contacts: "Du chasch sueche oder meh Kontäkt %{invite_link}" - you_should_add_some_more_contacts: "Du söttsch es paar meh Kontäkt adde" + community_spotlight: "Intressanti Lüt" + or_spotlight: "Oder du chasch mit %{link} teile" + try_adding_some_more_contacts: "Du chasch meh Kontäkt sueche oder %{invite_link}." + you_should_add_some_more_contacts: "Du söttsch es paar meh Kontäkt hinzuefüege" seed: acquaintances: "Bekannti" family: "Familie" friends: "Fründe" work: "Arbet" update: - failure: "Din Aspekt %{name} het en z'lange name zum chönne gspeicheret werde" - success: "Din Aspekt %{name} het erfolgriich chönne gänderet werde" + failure: "%{name} isch en z'lange name zum chönne gspeicheret werde." + success: "Din Aspekt %{name} isch erfolgriich gänderet worde." blocks: create: failure: "Ignoriere vo dem benutzer fehlgschlage" @@ -134,43 +134,43 @@ de-CH: failure: "Han nöd chönne ufhöhre dä benutzer z'ignoriere." success: "Luegemer mol was die z'sägä hend! #sayhello" bookmarklet: - explanation: "Poste en biitrag bi Diaspora vo egal wo i dem du dä Link => %{link} zu dine Läsezeiche hinzuefüegsch" + explanation: "Erstell vo überall en Biitrag bi diaspora* i dem du %{link} zu dine Läsezeiche hinzuefüegsch" heading: "Läsezeichä" - post_something: "En biitrag in Diaspora* erstelle" + post_something: "Erstell en Biitrag bi diaspora*" cancel: "Abbreche" comments: new_comment: comment: "Kommentiere" - commenting: "Am Kommentiere..." + commenting: "Wird kommentiert..." contacts: index: add_a_new_aspect: "en neue Aspekt mache" all_contacts: "Ali Kontäkt" - community_spotlight: "Kommunity Schiiwörferliecht" + community_spotlight: "Intressanti Lüt" my_contacts: "Mini Kontäkt" - no_contacts: "Gseht uus als möstisch es paar Kontäkt adde" - no_contacts_message: "Lueg mal s'%{community_spotlight} aa" + no_contacts: "Gseht uus als möstisch es paar Kontäkt hinzuefüege!" + no_contacts_message: "Lueg mal di %{community_spotlight} aa" only_sharing_with_me: "Eisiitig mit mir teilendi" start_a_conversation: "Start es Gspröch" title: "Kontäkt" spotlight: - community_spotlight: "Kommunity Schiiwörferliecht" + community_spotlight: "Intressanti Lüt" suggest_member: "Mitglied vorschloh" conversations: create: fail: "Ungültigi Nochricht" - no_contact: "Hoppla, du muesch zersch de Kontakt adde." - sent: "Nochricht gsendet" + sent: "Nochricht verschickt" index: - inbox: "Igang" + inbox: "Poschtigang" no_messages: "Kei Nochrichte" new: - send: "Sende" - sending: "Sendend..." - subject: "worum gaht's ?" - to: "A" + send: "Abschicke" + sending: "Wird gschickt..." + subject: "Um was goht's?" + to: "Empfänger" show: delete: "Gspröch lösche" + last_message: "Letschti Nochricht empfange %{timeago}" reply: "Antworte" replying: "Am Antworte..." date: @@ -179,153 +179,147 @@ de-CH: birthday_with_year: "%d. %B %Y" fullmonth_day: "%d. %B" delete: "Lösche" - email: "Email" + email: "E-Mail" error_messages: helper: - correct_the_following_errors_and_try_again: "Korrigier folgendi Errör's und versuechs nomel." + correct_the_following_errors_and_try_again: "Korrigier folgendi Fähler und versuechs nomel." fill_me_out: "Füll mi uus" - find_people: "Find Mensche oder Tag's" + find_people: "Find Mensche oder #Tags" invitations: - a_facebook_user: "En Facebook benutzer" - check_token: - not_found: "Iilatigs-token isch nöd gfunde worde" create: empty: "Bitte mindestens ei email adresse iigä" - no_more: "Kei wiiteri Iilage." + no_more: "Du hesch kei Iilage meh." note_already_sent: "A %{emails} sind scho e iiladig gschickt worde." - rejected: "Bi folgende adresse het's Problem geh: " - sent: "Illadige sind a folgendi adresse gsendet worde: %{emails}" + rejected: "Bi folgende Adresse het's Problem geh: " + sent: "Illadige sind a folgendi Adresse gschickt worde: %{emails}" new: comma_separated_plz: "Du chasch mehreri email adresse iigeh, wenns dur es komma trennsch." - invite_someone_to_join: "Tuen öpper zu Diaspora* Iilade!" + invite_someone_to_join: "Lad öpper zu diaspora* ii!" language: "Sproch" - paste_link: "Teil de link mit dine fründe zum sie zu Diaspora* iizlade, oder schrick ene de link direkt." - send_an_invitation: "En Iiladig sende" + paste_link: "Teil de Link mit dine Fründe zum sie zu diaspora* iizlade, oder schick ene de link direkt per E-Mail." + send_an_invitation: "En Iiladig verschicke" layouts: application: back_to_top: "Zrugg zum Aafang" - powered_by: "Es lauft mir Diaspora*" - public_feed: "Öffentliche Diaspora* feed vo %{name}" + powered_by: "Es lauft mit diaspora*" + public_feed: "Öffentliche diaspora* Feed vo %{name}" source_package: "Lad S'Quellcode-packet abe" - toggle: "Mobiili aasicht ii/us-schalte" + toggle: "Mobiili Aasicht umschalte" whats_new: "Was git's neus?" header: logout: "Abmelde" profile: "Profil" - settings: "Iistelige" - limited: "Limitiert" + settings: "Iistellige" + limited: "Begrenzt" more: "Meh" - no_results: "Kei Resultat gfunde" + no_results: "Kei Ergebnis gfunde" notifications: comment_on_post: - one: "%{actors} het din biitrag %{post_link} kommentiert" - other: "%{actors} hend din biitrag %{post_link} kommentiert" - zero: "%{actors} het din biitrag %{post_link} kommentiert" + one: "%{actors} het din Biitrag %{post_link} kommentiert." + other: "%{actors} hend din Biitrag %{post_link} kommentiert." + zero: "Niemer het din Biitrag %{post_link} kommentiert." index: and: "und" mark_unread: "als gläsä markiere" liked: - one: "%{actors} het din post %{post_link} gern" - other: "%{actors} hend din post %{post_link} gern" - zero: "%{actors} het din post %{post_link} gern" + one: "%{actors} gfallt din Biitrag %{post_link}." + other: "%{actors} gfallt din Biitrag %{post_link}." + zero: "%{actors} gfallt din Biitrag %{post_link}." mentioned: - one: "%{actors} het dich im post %{post_link} erwähnt" - other: "%{actors} hend dich im post %{post_link} erwähnt" - zero: "%{actors} het dich im post %{post_link} erwähnt" + one: "%{actors} het di im Biitrag %{post_link} erwähnt." + other: "%{actors} hend di im Biitrag %{post_link} erwähnt." + zero: "%{actors} het di im Biitrag %{post_link} erwähnt." private_message: one: "%{actors} het dir e Nochricht gschickt." other: "%{actors} hend dir e Nochricht gschickt." zero: "%{actors} het dir e Nochricht gschickt." reshared: - one: "%{actors} het din post %{post_link} wiitergseit." - other: "%{actors} hend din post %{post_link} wiitergseit." + one: "%{actors} het din Biitrag %{post_link} wiitergseit." + other: "%{actors} hend din Biitrag %{post_link} wiitergseit." started_sharing: - one: "de %{actors} het agfange mit dir Teile." - other: "%{actors} hend agfange mit dir Teile." - zero: "%{actors} het agfange mit dir Teile." + one: "%{actors} het agfange mit dir z'teile." + other: "%{actors} hend agfange mit dir z'teile." + zero: "Niemer het agfange mit dir z'teile." notifier: - a_post_you_shared: "en post" + a_post_you_shared: "en Biitrag." click_here: "druck do" comment_on_post: - reply: "Gib antwort oder lueg der de post vo %{name} aa." + reply: "Schriib en Antwort oder lueg der de Biitrag vo %{name} aa >" confirm_email: - click_link: "Klick uf dä link zum dini neu email adresse %{unconfirmed_email} z'aktiviere" - subject: "Bitte aktivier dini neu email adresse %{unconfirmed_email}" - email_sent_by_diaspora: "Das e-mail isch vo %{pod_name} gsendet worde. Wenn du kei söttigi emails me willsch," - hello: "Hallo %{name}!" + click_link: "Klick uf dä Link zum dini neu E-Mail-Adresse %{unconfirmed_email} z'aktiviere:" + subject: "Bitte aktivier dini neu E-Mail-Adresse %{unconfirmed_email}" + email_sent_by_diaspora: "Das E-Mail isch vo %{pod_name} gschickt worde. Wenn du kei söttigi E-Mails me willsch," + hello: "Hoi %{name}!" invite: message: |- Hallo! - du bisch vo %{diaspora_id} iiglade worde Diaspora* biizträte. + du bisch vo %{diaspora_id} iiglade worde diaspora* biizträte. + Mit dem Link gohts los + [%{invite_url}][1] - Oder füeg %{diaspora_id} zu dine Aspekt hinzue. wennd scho en Account hesch. + Oder füeg %{diaspora_id} zu dine Aspekt hinzue, wennd scho es Konto hesch. - Liebi grüess - De Diaspora* email roboter + Liebi Grüess - Ps. Für de fall das do gar nonig weisch was Diaspora* isch:[do][2] git's meh info's. + De diaspora* E-Mail Roboter! + + PS: Für de Fall das do gar nonig weisch was diaspora* isch, [do][2] git's meh Info's. [1]: %{invite_url} [2]: %{diasporafoundation_url} - invited_you: "%{name} het dich zu Diaspora* iiglade" + invited_you: "%{name} het dich zu diaspora* iiglade" liked: - liked: "%{name} het din post gern" - view_post: "Post aaluege >" + liked: "%{name} gfallt din Biitrag" + view_post: "Biitrag aaluege >" mentioned: - subject: "%{name} het dich uf Diaspora* erwähnt" + subject: "%{name} het di uf diaspora* erwähnt" private_message: - reply_to_or_view: "Gib Antwort oder lueg die Underhaltig aa >" + reply_to_or_view: "Schrib en Antwort oder lueg s'Gspröch aa >" reshared: - reshared: "%{name} het din post wiitergseit" - view_post: "Post aaluege >" + reshared: "%{name} het din Biitrag wiitergseit" + view_post: "Biitrag aaluege >" single_admin: - admin: "Din Diaspora* administrator" - subject: "E Nochricht über din Diaspora* Account:" + admin: "Din diaspora* Administrator" + subject: "E Nochricht über dis diaspora* Konto:" started_sharing: - sharing: "het aagfange mit dir teile!" - subject: "%{name} het uf Diaspora* aagfange mit dir teile" - view_profile: "lueg s'profil vo %{name} aa" + sharing: "het aagfange mit dir z'teile!" + subject: "%{name} het uf diaspora* aagfange mit dir z'teile" + view_profile: "Lueg s'Profil vo %{name} aa" thanks: "Danke," - to_change_your_notification_settings: "zum dini benochrichtigungs-iistellige z'ändere" + to_change_your_notification_settings: "zum dini Benochrichtigungs-Iistellige z'ändere" nsfw: "NSFW" ok: "OK" people: add_contact: invited_by: "Du bisch iglade worde vo" index: - looking_for: "Bisch uf de suech noch mit %{tag_link} täggde biiträg?" - no_one_found: "...und niemer isch gunde worde." - no_results: "Hey, du muesch noch öppisem sueche." - results_for: "Benutzer zum Thema %{search_term}" + looking_for: "Bisch uf de Suech noch mit %{tag_link} täggde Biiträg?" + no_one_found: "...und niemer isch gfunde worde." + no_results: "Hey! Du muesch noch öppisem sueche." + results_for: "Suechergebnis für %{search_term}" searching: "Sueche, bitte bis geduldig..." person: thats_you: "Das bisch du!" profile_sidebar: - bio: "Biografie" + bio: "Beschriibig" born: "Geburi" gender: "Gschlächt" location: "Ort" show: - closed_account: "Dä Account isch gschlosse worde." + closed_account: "Dä Konto isch gschlosse worde." does_not_exist: "Die Person existiert nöd!" - has_not_shared_with_you_yet: "%{name} het bis etz no kei posts mit dir teilt.." + has_not_shared_with_you_yet: "%{name} het bis etz no kei Biiträg mit dir teilt!" photos: create: - integrity_error: "Fotiupload isch fehlgschlage... Sicher das da e bild gsi isch?" - runtime_error: "Fotiupload isch fehlgschlage... Sicher das ali tasse im chuchichäschtli sind?" - type_error: "Fotiupload isch fehlgschlage... lueg mal ob's bild dezuegfüegt worde isch.." + integrity_error: "Fotiupload isch fehlgschlage... Bisch sicher das da e Bild gsi isch?" + runtime_error: "Fotiupload isch fehlgschlage... Bisch sicher das ali Tasse im Chuchichäschtli sind?" + type_error: "Fotiupload isch fehlgschlage... Bisch sicher das e Bild iigfüegt worde isch?" destroy: notice: "Foti glöscht." - new_photo: - empty: "{file} isch läär, bitte wähl d'dateie nomol ohni das us." - invalid_ext: "{file} het e ungültigi Dateiendig. Nur folgendi ändige sind erlaubt : {extensions}" - size_error: "{file} isch z'gross.. - Uploads dörfed Maximal {sizeLimit} sii." new_profile_photo: upload: "Lad es neus Profilfoti ue!" - show: - show_original_post: "Orginal-Post aazeige" posts: presenter: title: "En post vo %{name}" @@ -335,50 +329,50 @@ de-CH: profile: "Profil" profiles: edit: - allow_search: "Andere lüüt innerhalb vo Diaspora* erlaube noch dir z'sueche" + allow_search: "Andere lüüt innerhalb vo diaspora* erlaube noch dir z'sueche" first_name: "Vorname" last_name: "Nochname" - update_profile: "Profil Update" - your_bio: "Dini beschriibig" + update_profile: "Profil aktualisierä" + your_bio: "Dini Beschriibig" your_birthday: "Din Geburtstag" your_gender: "Dis Gschlächt" - your_location: "Wo du bisch" - your_name: "Din name" - your_photo: "dis Foti" - your_tags: "Beschriib dich in 5 wörter" + your_location: "Din Ort" + your_name: "Din Name" + your_photo: "Dis Foti" + your_tags: "Beschriib dich i 5 Wörter" your_tags_placeholder: "Zum Biispiil: #diaspora #chuchichäschtli #kreativ #linux #musig" update: - failed: "Aktualisierä vom Profil isch fehlschlage" + failed: "Aktualisierä vom Profil isch fehlgschlage" updated: "Pofil aktualisiert" - public: "Öffentlich" + public: "Öffetlich" reactions: - one: "%{count} Reaktion" + one: "Ei Reaktion" other: "%{count} Reaktione" zero: "Kei Reaktion" registrations: - closed: "Uf dem pod isch Account erröffnig deaktiviert" + closed: "Uf dem pod isch d'Registrierig deaktiviert" create: - success: "Du bisch ez volle hahne bi Diaspora* debii !" + success: "Du bisch ez volle Hahne bi diaspora* debii!" invalid_invite: "De iiladigslink wo'd erstellt hesch isch nüme gültig!" new: - email: "Email" - enter_email: "Gib dini email adresse ii" + email: "E-Mail" + enter_email: "Gib dini E-Mail-Adresse ii" enter_password: "Passwort iigä (mindestens 6 zeiche)" enter_password_again: "Nomol s'gliich passwort wie vorher iigä" - enter_username: "Wähl en benutzername uus (bestehend usschliesslich us: zahle, nummere, und understrich)" + enter_username: "Wähl en Benutzername uus (bestehend usschliesslich us: Buechstabe, Nummere und Understrich)" password: "Passwort" password_confirmation: "Passwort bestätigung" sign_up: "Account mache" username: "Benutzername" reshares: reshare: - deleted: "Originalpost isch vom Verfasser glöscht worde" - reshare_confirmation: "%{author}'s post wiitersägä ?" - reshared_via: "wiitergseit vo" + deleted: "Originalbiitrag isch vom Verfasser glöscht worde." + reshare_confirmation: "%{author}'s Biitrag wiitersägä?" + reshared_via: "Wiitergseit vo" search: "Sueche" services: create: - already_authorized: "En benutzer mit de Diapsora id %{diaspora_id} het de Account mit name %{service_name} scho autorisiert." + already_authorized: "En Benutzer mit de diaspora* ID %{diaspora_id} het de %{service_name}-Account scho autorisiert." failure: "Authentifizierig fehlgschlage." success: "Authentifizierig erfolgriich." destroy: @@ -387,7 +381,7 @@ de-CH: error: "Bim verbinde zu dem Dienst het's en error geh.." index: disconnect: "Trenne" - edit_services: "Dienst bearbeite" + edit_services: "Dienscht bearbeite" logged_in_as: "Iigloggt als %{nickname}" really_disconnect: "%{service} trenne" settings: "Iistelige" @@ -403,7 +397,7 @@ de-CH: logged_in: "Igglogt in %{service}" manage: "Verbundeni dienst verwalte" new_user_welcome_message: "Mach #hashtags zum dini post's z'tägge und lüüt mit ähnliche intresse finde. Erwähn anderi mensche mit @mentions" - outside: "Öfentlichi biiträg sind für's gsamte internet sichtbar." + outside: "Öffentlichi Biiträg sind für's gsamte Internet sichtbar." share: "Teilä" title: "Verbundeni Dienst ufsetzä" visibility_dropdown: "Zum iistelle wär din post gseh dörf benutz s'dropdown menü. (Mer empfehled din erschtä post öffentlich z'mache (wellen susch nemert gseht ^^ ))" @@ -464,7 +458,7 @@ de-CH: email_not_confirmed: "Email het nöd chönne aktiviert werde. Falsche Link?" destroy: no_password: "Bitte dis aktuelle passwort iigäh zum de account schlüsse." - success: "Dis Konto isch gschperrt. Es chan ~ 20 Minute goh bevor din Account endgültig gschlosse isch. Danke das du dich uf Diaspora* versuecht hesch." + success: "Dis Konto isch gschperrt. Es chan ~ 20 Minute goh bis din Account endgültig gschlosse isch. Danke das du diaspora* uusprobiert hesch." wrong_password: "Das Passwort stimmt nöd mit dim aktuelle passwort überein." edit: also_commented: "öpper en post kommentiert wo du scho kommentiert häsch" @@ -479,10 +473,10 @@ de-CH: dont_go: "Hey, bitte hau nöd ab!" lock_username: "Din benutzername wird gsperrt. Niemer wird d'möglichkeit ha zum die gliich ID uf dem pod nomol z'registriere." locked_out: "Du wirsch us dim account abgmeldet und usgsperrt bis er glöscht worde isch." - make_diaspora_better: "Üs wär's sehr vill lieber du würsch bliibe und mithelfe Diaspora* besser z'mache anstatt z'goh. - Wenn aber würkli wotsch, das passiert als nöchschts:" + make_diaspora_better: "Üs wär's sehr vill lieber du würsch bliibe und mithelfe diaspora* besser z'mache anstatt z'goh. Wenn aber würkli wotsch, das passiert als nöchschts:" mr_wiggles: "Wenn du gosch wird de Mr.Wiggles ganz truurig" no_turning_back: "Es git keis zrugg! Wenn du dir würkli sicher bisch, gib dis passwort une ii." - what_we_delete: "Mer lösched all dini biiträg und profildate so bald als möglich. Dini kommentär wo du under de posts vo andere lüüt gmacht hesch werded immerno aazeigt aber mit dinere Diaspora* ID assoziiert anstatt dim name." + what_we_delete: "Mer lösched all dini Biiträg und Profildate so bald wie möglich. Dini Kommentär wo du under de Biiträg vo andere Lüüt gmacht hesch werdet immerno aazeigt aber si werdet mit dinere diaspora* ID anstatt dim Name verchnüpft." close_account_text: "Account schlüsse" comment_on_post: "öpper en post vo dir kommentiert" current_password: "aktuell's passwort" @@ -502,11 +496,11 @@ de-CH: started_sharing: "öpper mit dir aafangt teile" stream_preferences: "Stream Iistellige" your_email: "Dini Email Adresse" - your_handle: "Dini Diaspora* ID" + your_handle: "Dini diaspora* ID" getting_started: - awesome_take_me_to_diaspora: "Grossartig! bring mich zu Diaspora*" - community_welcome: "d'Diapora\"-Mensche sind froh dich an board zha!" - hashtag_explanation: "Mit hashtags chasch du über Sache rede und dini Intresse folge. Usserdem eignet si sich hervorragend zum neui lüüt uf Diaspora* z'finde." + awesome_take_me_to_diaspora: "Grossartig! Bring mi zu diaspora*" + community_welcome: "d'diapora*-Mensche sind froh di an Bord z'ha!" + hashtag_explanation: "Mit hashtags chasch du über Sache rede und dini Intresse folge. Usserdem eignet si sich hervorragend zum neui lüüt uf diaspora* z'finde." hashtag_suggestions: "Versuech's mal tags wie zb. #kunscht, #film, #chääs etc.." well_hello_there: "Halli Hallo !" what_are_you_in_to: "Was machsch so?" diff --git a/config/locales/diaspora/de.yml b/config/locales/diaspora/de.yml index 6e68d73b3..24d216e72 100644 --- a/config/locales/diaspora/de.yml +++ b/config/locales/diaspora/de.yml @@ -274,6 +274,8 @@ de: post_something: "Erstelle einen Beitrag in diaspora*" cancel: "Abbrechen" comments: + create: + error: "Konnte nicht kommentieren." new_comment: comment: "Kommentieren" commenting: "Kommentieren …" @@ -298,7 +300,6 @@ de: conversations: create: fail: "Ungültige Nachricht" - no_contact: "Hoppla, du musst den Kontakt erst hinzufügen!" sent: "Nachricht versendet" destroy: delete_success: "Das Gespräch wurde erfolgreich gelöscht." @@ -307,6 +308,7 @@ de: conversations_inbox: "Konversationen – Posteingang" inbox: "Eingang" new_conversation: "Neue Konversation" + no_contacts: "Du musst ein paar Kontakte schließen, bevor du eine Unterhaltung anfangen kannst" no_messages: "Keine Nachrichten" new: message: "Nachricht" @@ -331,6 +333,7 @@ de: delete: "Löschen" email: "E-Mail" error_messages: + csrf_token_fail: "Das CSRF-Token ist ungültig. Bitte melde dich an und versuche es noch einmal." helper: correct_the_following_errors_and_try_again: "Korrigiere die folgenden Fehler und versuche es erneut." need_javascript: "Diese Website benötigt Javascript, um richtig zu funktionieren. Falls du Javascript deaktiviert haben solltest, bitte aktiviere es und aktualisiere diese Seite." @@ -564,7 +567,6 @@ de: own_your_data: "Deine Daten, dein Eigentum" own_your_data_info: "Viele Netzwerke nutzen deine Daten, um Geld zu verdienen, indem Sie deine Interaktionen auswerten und diese Informationen verwenden, um dir Werbung zu zeigen. diaspora* nutzt deine Daten zu keinem anderen Zweck, als es dir zu ermöglichen, dich mit anderen zu verbinden und mit ihnen zu teilen." podmin: - admin_panel: "Administrationsbereich" byline: "Du bist drauf und dran, das Internet zu ändern. Lass uns gleich alles einrichten, okay?" configuration_info: "Öffne %{database_path} und %{diaspora_path} in deinem Lieblingstexteditor und sieh sie gründlich durch, sie sind ausführlich kommentiert." configure_your_pod: "Richte deinen Pod ein" @@ -578,22 +580,21 @@ de: getting_help_info: "Wir haben einige %{faq} aufgelistet, einschließlich einiger zusätzlicher Tipps und Tricks und Lösungen für die häufigsten Probleme. Kontaktiere uns gerne auch %{irc}." headline: "Willkommen, Freund." make_yourself_an_admin: "Mach dich zum Admin" - make_yourself_an_admin_info: "Du kannst Anweisungen im %{wiki} finden. Das sollte deinem Benutzermenü in der Kopfleiste einen Link „Admin“ hinzufügen, wenn du angemeldet bist. Er stellt dir Dinge wie Benutzersuche und Statistiken für deinen Pod zur Verfügung. Für ausführliche Angaben über die betriebsbezogenen Aspekte deines Pods, besuche den %{admin_panel}." + make_yourself_an_admin_info: "Du kannst Anweisungen im %{wiki} finden. Das sollte deinem Benutzermenü in der Kopfleiste einen Link „%{admin_dashboard}“ hinzufügen, wenn du angemeldet bist. Er stellt dir Dinge wie Benutzersuche und Statistiken für deinen Pod zur Verfügung." report_bugs: "melde sie" update_instructions: "Aktualisierungsanweisungen im diaspora*-Wiki" update_your_pod: "Aktualisiere deinen Pod" update_your_pod_info: "Du kannst %{update_instructions} finden." invitation_codes: + already_logged_in: "Du bist von %{inviter} eingeladen worden, diesem Pod beizutreten, allerdings bist du schon angemeldet." not_valid: "Dieser Einladungscode ist nicht mehr gültig" invitations: - a_facebook_user: "Ein Facebook-Nutzer" - check_token: - not_found: "Einladungstoken nicht gefunden" create: + closed: "Einladungen sind auf diesem diaspora*-Pod im Moment nicht verfügbar." empty: "Bitte mindestens eine E-Mail-Adresse eingeben." no_more: "Du hast keine Einladungen mehr." note_already_sent: "Es wurde bereits eine Einladung an %{emails} gesendet" - rejected: "Mit diesen E-Mail-Adressen gab es Probleme:" + rejected: "Mit diesen E-Mail-Adressen gab es Probleme: %{emails}" sent: "Einladungen wurden an %{emails} verschickt." new: codes_left: @@ -622,6 +623,9 @@ de: profile: "Profil" settings: "Einstellungen" toggle_navigation: "Navigation umschalten" + likes: + create: + error: "Gefällt mir ist fehlgeschlagen." limited: "Begrenzt" more: "Mehr" no_results: "Keine Ergebnisse gefunden" @@ -658,7 +662,8 @@ de: mark_all_shown_as_read: "Alle angezeigten als gelesen markieren" mark_read: "Als gelesen markieren" mark_unread: "als ungelesen markieren" - mentioned: "Erwähnt" + mentioned: "In Beitrag erwähnt" + mentioned_in_comment: "In Kommentar erwähnt" no_notifications: "Du hast noch keine Benachrichtigungen." notifications: "Benachrichtigungen" reshared: "Weitergesagt" @@ -677,8 +682,8 @@ de: two: "%{actors} gefällt dein gelöschter Beitrag." zero: "Niemandem gefällt dein gelöschter Beitrag." mentioned: - one: "%{actors} hat dich in dem Beitrag %{post_link} erwähnt." - other: "%{actors} haben dich in dem Beitrag %{post_link} erwähnt." + one: "%{actors} hat dich im Beitrag %{post_link} erwähnt." + other: "%{actors} haben dich im Beitrag %{post_link} erwähnt." zero: "%{actors} hat dich in dem Beitrag %{post_link} erwähnt." mentioned_deleted: few: "%{actors} haben dich in einem gelöschten Beitrag erwähnt." @@ -687,6 +692,12 @@ de: other: "%{actors} haben dich in einem gelöschten Beitrag erwähnt." two: "%{actors} hat dich in einem bereits gelöschten Beitrag erwähnt." zero: "Niemand hat dich in einem gelöschten Beitrag erwähnt." + mentioned_in_comment: + one: "%{actors} hat dich in einem Kommentar zum Beitrag %{post_link} erwähnt." + other: "%{actors} haben dich in einem Kommentar zum Beitrag %{post_link} erwähnt." + mentioned_in_comment_deleted: + one: "%{actors} hat dich in einem gelöschten Kommentar erwähnt." + other: "%{actors} haben dich in einem gelöschten Kommentar erwähnt." post: "Beitrag" private_message: few: "%{actors} haben dir eine Nachricht gesendet." @@ -726,6 +737,29 @@ de: confirm_email: click_link: "Um deine neue E-Mail-Adresse %{unconfirmed_email} zu aktivieren, klicke bitte auf diesen Link:" subject: "Bitte aktiviere deine neue E-Mail-Adresse %{unconfirmed_email}" + csrf_token_fail: + body: |- + Hallo %{name}, + + diaspora* hat einen Versuch, auf dein Konto zuzugreifen, erkannt, der eventuell unbefugt war. Um auszuschließen, dass deine Daten gefährdet werden, bist du abgemeldet worden. Mach dir keine Sorgen; Du kannst dich jetzt wieder sicher anmelden. + + Eine Anfrage ist mit ungültigem oder fehlendem CSRF-Token gesendet worden. Das könnte vollkommen harmlos sein, aber es könnte sich auch auch um einen Cross-Site-Request-Forgery-Angriff (CSRF-Angriff) handeln. + + Das könnte verursacht worden sein von: + + - Einem Add-on, das die Anfrage manipuliert oder Anfragen ohne das Token durchführt; + - Einem offen gelassenen Tab aus einer früheren Sitzung; + - Einer anderen Website, die mit oder ohne deine Genehmigung Anfragen durchführt; + - Verschiedenen anderen externen Werkzeugen; + - Schädlichen Code, der versucht, auf deine Daten zuzugreifen. + + Für mehr Informationen zu CSRF, siehe [%{link}](%{link}). + + Falls du diese Nachricht wiederholt siehst, prüfe bitte die oben stehenden Punkte, einschließlich aller Browser-Add-ons. + + Danke, + Der diaspora* E-Mail-Roboter! + subject: "Wir haben eine unbefugte Anfrage von deinem Konto empfangen, %{name}" email_sent_by_diaspora: "Diese E-Mail wurde von %{pod_name} verschickt. Falls du solche E-Mails nicht mehr erhalten willst," export_email: body: |- @@ -797,6 +831,9 @@ de: mentioned: limited_post: "Du wurdest in einem begrenzten Beitrag erwähnt." subject: "%{name} hat dich auf diaspora* erwähnt" + mentioned_in_comment: + limited_post: "Du wurdest in einem Kommentar zu einem begrenzten Beitrag erwähnt." + reply: "Auf diese Unterhaltung antworten oder sie ansehen >" private_message: reply_to_or_view: "Antworte oder sieh dir diese Unterhaltung an >" subject: "Es gibt eine neue private Nachricht für dich" @@ -882,14 +919,8 @@ de: type_error: "Hochladen des Fotos fehlgeschlagen. Bist du sicher, dass ein Bild hinzugefügt wurde?" destroy: notice: "Foto gelöscht." - new_photo: - empty: "{file} ist leer, bitte wähle erneut Dateien aus." - invalid_ext: "{file} hat keine gültige Erweiterung. Nur {extensions} sind erlaubt." - size_error: "{file} ist zu groß. Die maximale Dateigröße beträgt {sizeLimit}." new_profile_photo: upload: "Ein neues Profilfoto hochladen" - show: - show_original_post: "Zeige ursprünglichen Beitrag" polls: votes: one: "Bisher %{count} Stimme" @@ -960,7 +991,7 @@ de: enter_username: "Wähle einen Nutzernamen (nur Buchstaben, Nummern und Unterstriche)" password: "Kennwort" password_confirmation: "Kennwort bestätigen" - sign_up: "Konto ersellen" + sign_up: "Konto erstellen" submitting: "Absenden…" terms: "Indem du ein Konto erstellst, akzeptierst du die %{terms_link}." terms_link: "Nutzungsbedingungen" @@ -979,8 +1010,14 @@ de: destroyed: "Der Beitrag wurde gelöscht" failed: "Ein Fehler ist aufgetreten" title: "Meldungsübersicht" + unreviewed_reports: + one: "Es gibt eine ungeprüfte Meldung." + other: "Es gibt %{count} ungeprüfte Meldungen." + zero: "Es gibt keine ungeprüften Meldungen." reshares: comment_email_subject: "%{resharer}s Version von %{author}s Beitrag" + create: + error: "Fehler beim Weitersagen." reshare: deleted: "Originalbeitrag wurde vom Autor entfernt." reshare_confirmation: "%{author}s Beitrag weitersagen?" @@ -1022,7 +1059,7 @@ de: other: "In %{count} Aspekten" zero: "In keinem Aspekt" invitations: - by_email: "Per E-Mail" + by_email: "Lade Leute per E-Mail ein" invite_your_friends: "Lade deine Freunde ein" invites: "Einladungen" share_this: "Teile diesen Link per Email, Blog oder sozialen Netzwerken!" @@ -1156,6 +1193,7 @@ de: comment_on_post: "jemand deinen Beitrag kommentiert" current_password: "Derzeitiges Kennwort" current_password_expl: "das mit dem Du dich anmeldest..." + default_post_visibility: "Zum Teilen vorausgewählte Aspekte" download_export: "Mein Profil herunterladen" download_export_photos: "Meine Fotos herunterladen" edit_account: "Konto bearbeiten" @@ -1167,6 +1205,7 @@ de: last_exported_at: "(Zuletzt aktualisiert: %{timestamp})" liked: "jemandem dein Beitrag gefällt" mentioned: "du in einem Beitrag erwähnt wirst" + mentioned_in_comment: "du bist in einem Kommentar erwähnt" new_password: "Neues Kennwort" private_message: "du eine private Nachricht erhältst" receive_email_notifications: "E-Mail-Benachrichtigungen empfangen, wenn …" diff --git a/config/locales/diaspora/de_formal.yml b/config/locales/diaspora/de_formal.yml index 13f66162e..d1c305769 100644 --- a/config/locales/diaspora/de_formal.yml +++ b/config/locales/diaspora/de_formal.yml @@ -274,6 +274,8 @@ de_formal: post_something: "Erstellen Sie einen Beitrag in diaspora*" cancel: "Abbrechen" comments: + create: + error: "Konnte nicht kommentieren." new_comment: comment: "Kommentieren" commenting: "Kommentieren …" @@ -298,7 +300,6 @@ de_formal: conversations: create: fail: "Ungültige Nachricht" - no_contact: "Hoppla, Sie müssen den Kontakt erst hinzufügen!" sent: "Nachricht versendet" destroy: delete_success: "Unterhaltung erfolgreich gelöscht" @@ -307,6 +308,7 @@ de_formal: conversations_inbox: "Konversationen – Eingang" inbox: "Eingang" new_conversation: "Neue Konversation" + no_contacts: "Sie müssen einige Kontakte hinzufügen, bevor Sie eine Unterhaltung anfangen können" no_messages: "Keine Nachrichten" new: message: "Nachricht" @@ -331,6 +333,7 @@ de_formal: delete: "Löschen" email: "E-Mail-Adresse" error_messages: + csrf_token_fail: "Das CSRF-Token ist ungültig. Bitte melden Sie sich an und versuchen Sie es erneut." helper: correct_the_following_errors_and_try_again: "Korrigieren Sie die folgenden Fehler und versuchen Sie es erneut." need_javascript: "Diese Webseite benötigt JavaScript, um ordnungsgemäß zu funktionieren. Falls Sie JavaScript deaktiviert haben, aktivieren Sie es bitte und aktualisieren Sie diese Seite." @@ -564,7 +567,6 @@ de_formal: own_your_data: "Ihre Daten, Ihr Eigentum" own_your_data_info: "Viele Netzwerke nutzen Ihre Daten, um Geld zu verdienen, indem Sie Ihre Interaktionen auswerten und diese Informationen verwenden, um Ihnen Werbung zu zeigen. diaspora* nutzt Ihre Daten zu keinem anderen Zweck, als es Ihnen zu ermöglichen, sich mit anderen zu verbinden und mit ihnen zu teilen." podmin: - admin_panel: "Administrationsbereich" byline: "Sie sind im Begriff, das Internet zu ändern. Lassen Sie uns gleich alles einrichten, okay?" configuration_info: "Öffnen Sie %{database_path} und %{diaspora_path} in Ihrem Lieblingstexteditor und sehen Sie sie gründlich durch, sie sind ausführlich kommentiert." configure_your_pod: "Richten Sie Ihren Pod ein" @@ -578,22 +580,21 @@ de_formal: getting_help_info: "Wir haben einige %{faq} aufgelistet, einschließlich einiger zusätzlicher Tipps und Tricks und Lösungen für die häufigsten Probleme. Kontaktieren Sie uns gerne auch %{irc}." headline: "Willkommen, Freund." make_yourself_an_admin: "Machen Sie sich zum Admin" - make_yourself_an_admin_info: "Sie können Anweisungen im %{wiki} finden. Das sollte Ihrem Benutzermenü in der Kopfleiste einen Link „Admin“ hinzufügen, wenn Sie angemeldet sind. Er stellt Ihnen Dinge wie Benutzersuche und Statistiken für Ihren Pod zur Verfügung. Für ausführliche Angaben über die betriebsbezogenen Aspekte Ihres Pods, besuchen Sie den %{admin_panel}." + make_yourself_an_admin_info: "Sie können Anweisungen im %{wiki} finden. Das sollte Ihrem Benutzermenü in der Kopfleiste einen Link „%{admin_dashboard}“ hinzufügen, wenn Sie angemeldet sind. Er stellt Ihnen Dinge wie Benutzersuche und Statistiken für Ihren Pod zur Verfügung." report_bugs: "melden Sie sie" update_instructions: "Aktualisierungsanweisungen im diaspora*-Wiki" update_your_pod: "Aktualisieren Sie Ihren Pod" update_your_pod_info: "Sie können %{update_instructions} finden." invitation_codes: + already_logged_in: "Sie wurden von %{inviter} eingeladen, diesem Pod beizutreten, jedoch sind Sie bereits angemeldet." not_valid: "Dieser Einladungscode ist nicht mehr gültig" invitations: - a_facebook_user: "Ein Facebook Nutzer" - check_token: - not_found: "Einladungstoken nicht gefunden" create: + closed: "Einladungen sind auf diesem diaspora*-Pod derzeit nicht verfügbar." empty: "Bitte mindestens eine E-Mail-Adresse eingeben." no_more: "Sie haben keine Einladungen mehr." note_already_sent: "Es wurde bereits eine Einladung an %{emails} gesendet" - rejected: "Mit diesen E-Mail-Adressen gab es Probleme: " + rejected: "Mit den folgenden E-Mail-Adressen gab es Probleme: %{emails}" sent: "Einladungen wurden verschickt an: %{emails}" new: codes_left: @@ -622,6 +623,9 @@ de_formal: profile: "Profil" settings: "Einstellungen" toggle_navigation: "Navigation umschalten" + likes: + create: + error: "Gefällt mir ist fehlgeschlagen." limited: "Begrenzt" more: "Mehr" no_results: "Keine Ergebnisse gefunden" @@ -658,7 +662,8 @@ de_formal: mark_all_shown_as_read: "Alle angezeigten als gelesen markieren" mark_read: "Als gelesen markieren" mark_unread: "als ungelesen markieren" - mentioned: "Erwähnt" + mentioned: "In Beitrag erwähnt" + mentioned_in_comment: "In Kommentar erwähnt" no_notifications: "Sie haben noch keine Benachrichtigungen." notifications: "Benachrichtigungen" reshared: "Weitergesagt" @@ -687,6 +692,12 @@ de_formal: other: "%{actors} haben Sie in einem gelöschten Beitrag erwähnt." two: "%{actors} hat Sie in einem bereits gelöschten Beitrag erwähnt." zero: "Niemand hat Sie in einem gelöschten Beitrag erwähnt." + mentioned_in_comment: + one: "%{actors} hat Sie in einem Kommentar zum Beitrag %{post_link} erwähnt." + other: "%{actors} haben Sie in einem Kommentar zum Beitrag %{post_link} erwähnt." + mentioned_in_comment_deleted: + one: "%{actors} hat Sie in einem gelöschten Kommentar erwähnt." + other: "%{actors} haben Sie in einem gelöschten Beitrag erwähnt." post: "Beitrag" private_message: few: "%{actors} haben Ihnen eine Nachricht gesendet." @@ -700,11 +711,8 @@ de_formal: other: "%{actors} haben Ihren Beitrag %{post_link} weitergesagt." zero: "%{actors} haben Ihren Beitrag %{post_link} weitergesagt." reshared_post_deleted: - few: "%{actors} haben Ihren gelöschten Beitrag weitergesagt." - many: "%{actors} haben Ihren gelöschten Beitrag weitergesagt." one: "%{actors} hat Ihren gelöschten Beitrag weitergesagt." other: "%{actors} haben Ihren gelöschten Beitrag weitergesagt." - two: "%{actors} hat Ihren bereits gelöschten Beitrag weitergeleitet." zero: "%{actors} haben Ihren gelöschten Beitrag weitergesagt." started_sharing: few: "%{actors} haben angefangen mit Ihnen zu teilen." @@ -726,6 +734,29 @@ de_formal: confirm_email: click_link: "Um deine neue E-Mail-Adresse %{unconfirmed_email} zu aktivieren, klicken Sie bitte auf diesen Link:" subject: "Bitte aktivieren Sie Ihre neue E-Mail-Adresse %{unconfirmed_email}" + csrf_token_fail: + body: |- + Hallo %{name}, + + diaspora* hat einen Versuch, auf Ihr Konto zuzugreifen, erkannt, der möglicherweise unbefugt war. Um auszuschließen, dass Ihre Daten gefährdet werden, wurden Sie abgemeldet. Machen Sie sich keine Sorgen; Sie können sich nun wieder sicher anmelden. + + Es wurde eine Anfrage mit ungültigem oder fehlendem CSRF-Token gesendet. Dies könnte vollkommen harmlos sein, es könnte sich aber auch um einen Cross-Site-Request-Forgery-Angriff (CSRF-Angriff) handeln. + + Dies könnte verursacht worden sein durch: + + - Ein Add-on, das die Anfrage manipuliert oder Anfragen ohne das Token durchführt; + - Einen offen gelassenen Tab aus einer vorherigen Sitzung; + - Eine andere Website, die mit oder ohne Ihre Genehmigung Anfragen durchführt; + - Verschiedene andere externe Werkzeuge; + - Schädlichen Code, der auf Ihre Daten zuzugreifen versucht. + + Für weitere Informationen zu CSRF, siehe [%{link}](%{link}). + + Falls Sie diese Nachricht wiederholt sehen, prüfen Sie bitte die oben stehenden Punkte, einschließlich jeglicher Browser-Add-ons. + + Danke, + Der diaspora* E-Mail-Roboter! + subject: "Wir haben eine unbefugte Anfrage von Ihrem Konto erhalten, %{name}" email_sent_by_diaspora: "Diese E-Mail wurde von %{pod_name} verschickt. Falls Sie solche E-Mails nicht mehr erhalten wollen," export_email: body: |- @@ -797,6 +828,9 @@ de_formal: mentioned: limited_post: "Sie wurden in einem begrenzten Beitrag erwähnt." subject: "%{name} hat Sie auf diaspora* erwähnt" + mentioned_in_comment: + limited_post: "Sie wurden in einem Kommentar zu einem begrenzten Beitrag erwähnt." + reply: "Auf diese Unterhaltung antworten oder sie ansehen >" private_message: reply_to_or_view: "Antworten Sie oder sehen Sie sich diese Unterhaltung an >" subject: "Es gibt eine neue private Nachricht für Sie" @@ -881,14 +915,8 @@ de_formal: type_error: "Hochladen des Fotos fehlgeschlagen. Sind Sie sicher, dass ein Bild hinzugefügt wurde?" destroy: notice: "Foto gelöscht." - new_photo: - empty: "{file} ist leer, bitte wählen Sie erneut Dateien aus." - invalid_ext: "{file} hat keine gültige Erweiterung. Nur {extensions} sind erlaubt." - size_error: "{file} ist zu groß. Die maximale Dateigröße beträgt {sizeLimit}." new_profile_photo: upload: "Laden Sie ein neues Profilfoto hoch!" - show: - show_original_post: "Zeige ursprünglichen Beitrag" polls: votes: one: "Bisher eine Stimme." @@ -975,8 +1003,14 @@ de_formal: destroyed: "Der Beitrag wurde gelöscht" failed: "Ein Fehler ist aufgetreten" title: "Meldungsübersicht" + unreviewed_reports: + one: "Es besteht eine ungeprüfte Meldung." + other: "Es bestehen %{count} ungeprüfte Meldungen." + zero: "Es bestehen keine ungeprüften Meldungen." reshares: comment_email_subject: "%{resharer}s Version von %{author}s Beitrag" + create: + error: "Fehler beim Weitersagen." reshare: deleted: "Originalbeitrag wurde vom Autor gelöscht." reshare_confirmation: "%{author}'s Beitrag weitersagen?" @@ -1014,14 +1048,10 @@ de_formal: mobile_row_checked: "%{name} (entfernen)" mobile_row_unchecked: "%{name} (hinzufügen)" toggle: - few: "In %{count} Aspekten" - many: "In %{count} Aspekten" one: "In einem Aspekt" other: "In %{count} Aspekten" - two: "In %{count} Aspekten" - zero: "Kontakt hinzufügen" invitations: - by_email: "Per E-Mail" + by_email: "Lade Leute per E-Mail ein" invite_your_friends: "Laden Sie Ihre Freunde ein" invites: "Einladungen" share_this: "Teilen Sie diesen Link per E-Mail, Blog oder soziale Netzwerke!" @@ -1155,6 +1185,7 @@ de_formal: comment_on_post: "jemand Ihren Beitrag kommentiert" current_password: "Derzeitiges Passwort" current_password_expl: "das mit dem Sie sich anmelden..." + default_post_visibility: "Zum Teilen vorausgewählte Aspekte" download_export: "Mein Profil herunterladen" download_export_photos: "Meine Fotos herunterladen" edit_account: "Konto bearbeiten" @@ -1166,6 +1197,7 @@ de_formal: last_exported_at: "(Zuletzt aktualisiert um %{timestamp})" liked: "wenn jemandem Ihr Beitrag gefällt" mentioned: "Sie in einem Beitrag erwähnt werden" + mentioned_in_comment: "Sie sind in einem Kommentar erwähnt" new_password: "Neues Passwort" private_message: "Sie eine private Nachricht erhalten" receive_email_notifications: "E-Mail-Benachrichtigungen empfangen, wenn:" diff --git a/config/locales/diaspora/el.yml b/config/locales/diaspora/el.yml index 381ee15a4..9d69d7cd9 100644 --- a/config/locales/diaspora/el.yml +++ b/config/locales/diaspora/el.yml @@ -197,7 +197,6 @@ el: conversations: create: fail: "Μη έγκυρο μήνυμα" - no_contact: "Πρέπει πρώτα να προσθέσεις μια επαφή!" sent: "Μήνυμα εστάλη" index: inbox: "Εισερχόμενα" @@ -276,9 +275,6 @@ el: tutorials: "οδηγοί" wiki: "wiki" invitations: - a_facebook_user: "Ένας χρήστης του Facebook" - check_token: - not_found: "Το σύμβολο της πρόσκλησης δεν βρέθηκε" create: empty: "Παρακαλώ εισήγαγε τουλάχιστον μία διεύθυνση email." no_more: "Δεν έχεις άλλες προσκλήσεις." @@ -451,14 +447,8 @@ el: type_error: "Η μεταφόρτωση της φωτογραφίας απέτυχε. Σίγουρα προστέθηκε μια εικόνα;" destroy: notice: "Η φωτογραφία διαγράφηκε." - new_photo: - empty: "{file} είναι κενό, επιλέξτε και πάλι τα αρχεία χωρίς αυτό." - invalid_ext: "{file} δεν έχει έγκυρη τύπο αρχείου. Μόνο τύποι αρχείου {extensions} επιτρέπονται." - size_error: "{file} είναι πολύ μεγάλο, το μέγιστο μέγεθος αρχείου είναι {sizeLimit}." new_profile_photo: upload: "Ανέβασε μια νέα φωτογραφία προφίλ!" - show: - show_original_post: "Προβολή αρχικής ανάρτησης" posts: presenter: title: "Ένα άρθρο από τον/την %{name}" diff --git a/config/locales/diaspora/en_1337.yml b/config/locales/diaspora/en_1337.yml index 0d0abfc32..c2f4b71a8 100644 --- a/config/locales/diaspora/en_1337.yml +++ b/config/locales/diaspora/en_1337.yml @@ -129,9 +129,6 @@ en_1337: fill_me_out: "!npu7 73x7 h3r3" find_people: "Ctrl+F n0obz, #74g5" invitations: - a_facebook_user: "4 F4C3B00K N00B!" - check_token: - not_found: "1NV4L1D 1NV174710N 70K3N!" create: no_more: "U H4V3 N0 M0R3 1NV174710N5!" rejected: "7H3 F0LL0W1NG M41L5 H4D PR0BL3M5: " @@ -296,14 +293,8 @@ en_1337: type_error: "PR0N UPL04D F41L3D! 4R3 U 5UR3 4N 1M4G3 W45 4DD3D?" destroy: notice: "PR0N D3L373D!" - new_photo: - empty: "{file} 15 3MP7Y, PLZ 53L3C7 F1L35 4G41N W17H0U7 17!" - invalid_ext: "{file} H45 1NV4L1D 3X73N510N! 0NLY {extensions} 4R3 4LL0W3D!" - size_error: "{file} 15 2 L4RG3, M4X1MUM F1L3 51Z3 15 {sizeLimit}." new_profile_photo: upload: "UPL04D 4 N3W PR0F1L3 P1C!" - show: - show_original_post: "5H0W 0R1G1N4L 5P4M!" posts: show: photos_by: diff --git a/config/locales/diaspora/en_pirate.yml b/config/locales/diaspora/en_pirate.yml index 55e69a3ab..5801cdc3d 100644 --- a/config/locales/diaspora/en_pirate.yml +++ b/config/locales/diaspora/en_pirate.yml @@ -144,7 +144,6 @@ en_pirate: fill_me_out: "Fill me out arrr" find_people: "Scour fer mates or treasures" invitations: - a_facebook_user: "A Facebook scallywag" create: no_more: "Ye have no more invitations." rejected: "Yer pigeon can't deliver to the followin' addresses: " @@ -306,10 +305,6 @@ en_pirate: type_error: "Portrait hangin' failed. Are ye sure a portrait was added mate?" destroy: notice: "Portrait scuttled!" - new_photo: - empty: "{file} be empty, choose yer files again without it mate." - invalid_ext: "{file} not be valid ye scallywag. Only {extensions} be allowed." - size_error: "{file} be 't large mate, the biggest file size be {sizeLimit}." new_profile_photo: upload: "Hang a new portrait in ye ship!" posts: diff --git a/config/locales/diaspora/en_shaw.yml b/config/locales/diaspora/en_shaw.yml index 61c266774..4e834bdc3 100644 --- a/config/locales/diaspora/en_shaw.yml +++ b/config/locales/diaspora/en_shaw.yml @@ -119,8 +119,6 @@ en_shaw: fill_me_out: "𐑓𐑦𐑤 𐑥𐑰 𐑬𐑑" find_people: "𐑓𐑲𐑯𐑛 𐑐𐑰𐑐𐑩𐑤" invitations: - check_token: - not_found: "𐑦𐑯𐑝𐑦𐑑𐑱𐑖𐑩𐑯 𐑑𐑴𐑒𐑩𐑯 𐑯𐑪𐑑 𐑓𐑬𐑯𐑛" create: no_more: "𐑿 𐑣𐑨𐑝 𐑯𐑴 𐑥𐑹 𐑦𐑯𐑝𐑦𐑑𐑱𐑖𐑩𐑯𐑟." rejected: "𐑞 𐑓𐑪𐑤𐑴𐑦𐑙 𐑦-𐑥𐑱𐑤 𐑩𐑛𐑮𐑧𐑕 𐑣𐑨𐑛 𐑐𐑮𐑪𐑚𐑤𐑩𐑥𐑟: " @@ -282,10 +280,6 @@ en_shaw: type_error: "𐑓𐑴𐑑𐑴 𐑩𐑐𐑤𐑴𐑛 𐑓𐑱𐑤𐑛. 𐑸 𐑿 𐑖𐑻 𐑩𐑯 𐑦𐑥𐑩𐑡 𐑢𐑪𐑟 𐑨𐑛𐑩𐑛?" destroy: notice: "𐑓𐑴𐑑𐑴 𐑛𐑦𐑤𐑰𐑑𐑩𐑛." - new_photo: - empty: "{file} 𐑦𐑟 𐑧𐑥𐑐𐑑𐑦, 𐑐𐑤𐑰𐑟 𐑕𐑩𐑤𐑧𐑒𐑑 𐑓𐑲𐑤𐑟 𐑩𐑜𐑧𐑯 𐑢𐑦𐑞𐑬𐑑 𐑦𐑑." - invalid_ext: "{file} 𐑣𐑨𐑟 𐑦𐑯𐑝𐑨𐑤𐑦𐑛 𐑧𐑒𐑕𐑑𐑧𐑯𐑖𐑩𐑯. 𐑴𐑯𐑤𐑦 {extensions} 𐑸 𐑩𐑤𐑬𐑛." - size_error: "{file} 𐑦𐑟 𐑑𐑵 𐑤𐑸𐑡, 𐑥𐑨𐑒𐑕𐑦𐑥𐑩𐑥 𐑓𐑲𐑤 𐑕𐑲𐑟 𐑦𐑟 {sizeLimit}." new_profile_photo: upload: "𐑩𐑐𐑤𐑴𐑛 𐑩 𐑯𐑿 𐑐𐑮𐑴𐑓𐑲𐑤 𐑓𐑴𐑑𐑴!" posts: diff --git a/config/locales/diaspora/en_valspeak.yml b/config/locales/diaspora/en_valspeak.yml index bac0391f1..ec4f4a4bf 100644 --- a/config/locales/diaspora/en_valspeak.yml +++ b/config/locales/diaspora/en_valspeak.yml @@ -224,7 +224,6 @@ en_valspeak: conversations: create: fail: "bad txt" - no_contact: "Umm HELLO, u need 2 like, add them first! Duh!" sent: "txt sent" destroy: delete_success: "convo successfully deleted YAAAAY!((:" @@ -464,9 +463,6 @@ en_valspeak: tutorials: "tutorialz!!" wiki: "ZOMG D*'s OWN WIKIPEDIA!! :DDD" invitations: - a_facebook_user: "a like... fb usah" - check_token: - not_found: "invite token was like... not found :\\" create: empty: "Plz enter at least 1 email addy, thx<3" no_more: "u have like... no moar invites." @@ -703,14 +699,8 @@ en_valspeak: type_error: "So like... ur pic wasnt added. r u like... sure u actually like... added it?" destroy: notice: "Pic deleted :o" - new_photo: - empty: "{file} is like... empty, plz pick the filez again witout that 1. kthx" - invalid_ext: "{file} is like... not able2 b uploaded cuz like... its not the right kinda file.. only like... these {extensions} r allowed... sry bout tht :\\" - size_error: "OMG {file} is 2 big!! the biggest i can take is like... {sizeLimit}.(;" new_profile_photo: upload: "Upload a new selfie!!! OMG!!" - show: - show_original_post: "Show da original postie" posts: presenter: title: "A postie from %{name}" diff --git a/config/locales/diaspora/eo.yml b/config/locales/diaspora/eo.yml index d33a0419b..cd0b5b718 100644 --- a/config/locales/diaspora/eo.yml +++ b/config/locales/diaspora/eo.yml @@ -188,7 +188,6 @@ eo: conversations: create: fail: "Malĝusta mesaĝo" - no_contact: "Hej, unue devas vi aldoni la kontakton." sent: "Mesaĝo sendiĝis." index: inbox: "Poŝtujo" @@ -233,9 +232,6 @@ eo: tutorials: "enkondukoj" wiki: "vikio" invitations: - a_facebook_user: "Facebook-uzanto" - check_token: - not_found: "Ne povis trovi invitan ĵetonon" create: empty: "Bonvole tajpu almenaŭ unu retpoŝtadreson." no_more: "Vi ne plu havas invitojn." @@ -417,14 +413,8 @@ eo: type_error: "Alŝuti bildon malsukcesis. Ĉu vi certas, ke vi aldonis bildon?" destroy: notice: "Bildo forviŝiĝis." - new_photo: - empty: "{file} malplenas; bonvolu reelekti dosierojn sen ĝi." - invalid_ext: "{file} havas malvalidan sufikson. Nur {extensions} estas validaj." - size_error: "{file} estas tro granda; la maksimuma dosiergrandeco estas {sizeLimit}." new_profile_photo: upload: "Alŝutu novan profilbildon!" - show: - show_original_post: "Montri originan afiŝon." posts: presenter: title: "Mesaĝo de %{name}" diff --git a/config/locales/diaspora/es-AR.yml b/config/locales/diaspora/es-AR.yml index 1d5627a07..fc887d921 100644 --- a/config/locales/diaspora/es-AR.yml +++ b/config/locales/diaspora/es-AR.yml @@ -274,6 +274,8 @@ es-AR: post_something: "Publicar en diaspora*" cancel: "Cancelar" comments: + create: + error: "Hubo un error al comentar." new_comment: comment: "Comentar" commenting: "Comentando..." @@ -298,7 +300,6 @@ es-AR: conversations: create: fail: "Mensaje inválido" - no_contact: "¡Primero necesitas agregar al contacto!" sent: "Mensaje enviado" destroy: delete_success: "La conversación ha sido eliminada" @@ -307,6 +308,7 @@ es-AR: conversations_inbox: "Conversaciones - Bandeja de entrada" inbox: "Mensajes" new_conversation: "Nueva conversación" + no_contacts: "Necesitas añadir algunos contactos antes de empezar una conversación" no_messages: "No hay mensajes" new: message: "Mensaje" @@ -331,6 +333,7 @@ es-AR: delete: "Eliminar" email: "Correo electrónico" error_messages: + csrf_token_fail: "El token CSRF es invalido. Por favor volvé a iniciar sesión e intentalo nuevamente." helper: correct_the_following_errors_and_try_again: "Corregí los siguientes errores e intentá de nuevo." need_javascript: "Esta web necesita JavaScript para funcionar correctamente. Si lo desactivaste, por favor actívalo y actualiza la página." @@ -564,7 +567,6 @@ es-AR: own_your_data: "Sé el dueño de tus datos" own_your_data_info: "Muchas redes usan tus datos para hacer dinero analizando tus interacciones y usando esa información para mostrarte anuncios publicitarios. diaspora* no usa tus datos para ningún propósito más que permitirte estar en contacto con otras personas." podmin: - admin_panel: "panel de administración" byline: "Estás a punto de cambiar Internet. Vamos a configurarlo, ¿dale?" configuration_info: "Abre %{database_path} y %{diaspora_path} en tu editor de texto favorito y revísalos cuidadosamente, están comentados al detalle." configure_your_pod: "Configura tu pod" @@ -578,22 +580,21 @@ es-AR: getting_help_info: "Mostramos algunas %{faq} incluyendo consejos adicionales, trucos y soluciones para los problemas más comunes. También puedes probar el chat %{irc}." headline: "¡Bienvenido!" make_yourself_an_admin: "Conviértete en administrador" - make_yourself_an_admin_info: "Puedes encontrar instrucciones en la %{wiki}. Esto añadirá un enlace de \"Administrador\" a tu menú de usuario en el encabezado cuando inicies sesión. Asimismo, te dará funciones como búsqueda de usuarios y estadísticas de tu pod. Para detalles avanzados en el aspecto operacional, ve al %{admin_panel}." + make_yourself_an_admin_info: "Puedes encontrar instrucciones en la %{wiki}. Esto añadirá un enlace de \"Administrador\" a tu menú de usuario en el encabezado cuando inicies sesión. Asimismo, te dará funciones como búsqueda de usuarios y estadísticas de tu pod. Para detalles avanzados en el aspecto operacional, ve al “%{admin_dashboard}”." report_bugs: "repórtalos" update_instructions: "instrucciones de actualización en la wiki de diaspora*" update_your_pod: "Actualiza tu pod" update_your_pod_info: "Puedes encontrar %{update_instructions}" invitation_codes: + already_logged_in: "Fuiste invitado por %{inviter} para unirte a este pod pero ya tenes una sesión iniciada." not_valid: "El código de invitación ya no es válido" invitations: - a_facebook_user: "Un usuario de Facebook" - check_token: - not_found: "No se encontró la udentificación de invitación" create: + closed: "Las invitaciones están desactivadas en este pod de diaspora*." empty: "Por favor ingresa al menos una dirección de correo electrónico." no_more: "No tenés más invitaciones." note_already_sent: "Las invitaciones han sido enviadas a: %{emails}" - rejected: "Las siguientes direcciones tuvieron problemas: " + rejected: "Hubo problemas con las siguientes direcciones de correo electrónico: %{emails}" sent: "Las invitaciones se han enviado a: %{emails}" new: codes_left: @@ -622,6 +623,9 @@ es-AR: profile: "Perfil" settings: "Configuración" toggle_navigation: "Cambiar navegación" + likes: + create: + error: "¡Falló el 'Me gusta'!" limited: "Limitado" more: "Más" no_results: "No hay resultados" @@ -659,6 +663,7 @@ es-AR: mark_read: "Marcar como leído" mark_unread: "Marcar como no leído" mentioned: "Mencionados" + mentioned_in_comment: "Fuiste mencionado en un comentario" no_notifications: "Aún no tienes ninguna notificación." notifications: "Notificaciones" reshared: "Compartidos" @@ -687,6 +692,12 @@ es-AR: other: "%{actors} te mencionaron en una publicación eliminada." two: "%{actors} te mencionó en un mensaje eliminado." zero: "%{actors} te mencionó en una publicación eliminada." + mentioned_in_comment: + one: "%{actors} te mencionó en un comentario de la publicación %{post_link}" + other: "%{actors} te mencionarion en un comentario de la publicación %{post_link}" + mentioned_in_comment_deleted: + one: "%{actors} te mencionó en un comentario que fue eliminado." + other: "%{actors} te mencionaron en un comentario que fue eliminado." post: "publicación" private_message: few: "%{actors} te enviaron un mensaje." @@ -723,6 +734,29 @@ es-AR: confirm_email: click_link: "Para activar tu nueva dirección de correo %{unconfirmed_email}, por favor seguí este enlace::" subject: "Por favor, activá tu nueva dirección de correo %{unconfirmed_email}" + csrf_token_fail: + body: |- + Hola %{name}, + + diaspora* detecto un intento de acceso no autorizado a tu cuenta. Puede ser totalmente inocente, pero también podría  ser un ataque (CSRF). Para evitar cualquier posibilidad de que tus datos sean robados, cerramos tu sesión. + + Una solicitud hecha con token CSRF vacío o invalido, pude suceder por: + + -Un complemento del navegador que manipula la solicitud o que las hace sin el token; + -Una pestaña del navegador abierta con una sesión anterior a la actual; + -Otro sitio web haciendo peticiones, con o sin tu permiso; + -Varias aplicaciones externas; + -Algún código malicioso intentando acceder tus datos. + + Para más información sobre CSRF revisá [%{link}](%{link}). + + No te preocupes, ya mismo podés iniciar sesión de manera segura. + + Si ves este mensaje muy a menudo, por favor verifica los puntos nombrados anteriormente, incluyendo los complementos de tu navegador. + + Gracias, + El robot de correos de diaspora* + subject: "Recibimos una solicitud no autorizada desde tu cuenta, %{name}" email_sent_by_diaspora: "Este correo electrónico fue enviado por %{pod_name}. Si quieres dejar de recibir correos como este," export_email: body: |- @@ -794,6 +828,9 @@ es-AR: mentioned: limited_post: "Se te mencionó en una publicación privada." subject: "%{name} te mencionó en diaspora*" + mentioned_in_comment: + limited_post: "Fuiste mencionado en un comentario de una publicación limitada." + reply: "Contestar o ver esta conversación >" private_message: reply_to_or_view: "Responder o ver esta conversación >" subject: "Tienes un nuevo mensaje privado en diaspora*" @@ -880,14 +917,8 @@ es-AR: type_error: "Error subiendo la foto. ¿Estás seguro que agregaste una imagen?" destroy: notice: "La foto fue eliminada." - new_photo: - empty: "{file} está vacío, por favor seleccioná archivos sin él." - invalid_ext: "{file} tiene una extensión incorrecta. Sólo se permiten {extensions}." - size_error: "{file} es demasiado grande, el tamaño máximo de archivo es {sizeLimit}." new_profile_photo: upload: "¡Subir una nueva foto de perfil!" - show: - show_original_post: "Mostrar la publicación original" polls: votes: one: "%{count} voto hasta ahora" @@ -974,8 +1005,14 @@ es-AR: destroyed: "La publicación ha sido eliminada" failed: "Algo salió mal" title: "Resumen de reportes" + unreviewed_reports: + one: "Hay un reporte sin revisar." + other: "Hay %{count} reportes sin revisar." + zero: "No hay reportes sin revisar." reshares: comment_email_subject: "%{resharer} compartió una publicación de %{author}" + create: + error: "¡Error al compartir!" reshare: deleted: "La publicación original fue eliminada por su autor." reshare_confirmation: "¿Compartir la publicación de %{author}?" @@ -1017,7 +1054,7 @@ es-AR: other: "En %{count} aspectos" zero: "En %{count} aspectos" invitations: - by_email: "Vía correo electrónico" + by_email: "Invitar a más personas a través de correo electrónico" invite_your_friends: "Invitá a tus contactos" invites: "Invitaciones" share_this: "¡Comparte este enlace a través de correo electrónico, blog o tu red social favorita!" @@ -1151,6 +1188,7 @@ es-AR: comment_on_post: "...comentan en una publicación tuya?" current_password: "Contraseña actual" current_password_expl: "con la que inicias sesión…" + default_post_visibility: "Seleccionado el aspecto por defecto para la publicación" download_export: "Descargar mi perfil" download_export_photos: "Descargar mis fotos" edit_account: "Editar cuenta" @@ -1162,6 +1200,7 @@ es-AR: last_exported_at: "(Última actualización en %{timestamp})" liked: "...a alguien le gusta una publicación tuya?" mentioned: "...te mencionan en una publicación?" + mentioned_in_comment: "te han mencionado en un comentario" new_password: "Contraseña nueva" private_message: "...recibís un mensaje privado?" receive_email_notifications: "¿Recibir notificaciones por correo electrónico cuando..." diff --git a/config/locales/diaspora/es-CL.yml b/config/locales/diaspora/es-CL.yml index 5c69fb508..3cd96fdaa 100644 --- a/config/locales/diaspora/es-CL.yml +++ b/config/locales/diaspora/es-CL.yml @@ -190,7 +190,6 @@ es-CL: conversations: create: fail: "Mensaje invalido" - no_contact: "¡Tranquilo, primero tienes que añadir el contacto!" sent: "Mensaje enviado" index: inbox: "Buzón de Entrada" @@ -369,9 +368,6 @@ es-CL: tutorials: "tutoriales" wiki: "Wiki" invitations: - a_facebook_user: "Un usuario de Facebook" - check_token: - not_found: "Identificación de invitación no encontrada" create: empty: "Por favor ingresa al menos una dirección de correo electrónico." no_more: "No tienes más invitaciones." @@ -555,14 +551,8 @@ es-CL: type_error: "Error al subir la foto. ¿Estás seguro que agregaste una imagen?" destroy: notice: "Foto eliminada." - new_photo: - empty: "{file} está vacío, por favor, seleccione los archivos nuevamente sin éste último" - invalid_ext: "{file} tiene una extensión no válida. Solo están permitidas {extensions}." - size_error: "{file} es demasiado grande, el tamaño máximo por archivo es {sizeLimit}." new_profile_photo: upload: "¡Sube una nueva foto de perfil!" - show: - show_original_post: "Mostrar post original" posts: presenter: title: "Una publicación de %{name}" diff --git a/config/locales/diaspora/es-CO.yml b/config/locales/diaspora/es-CO.yml index a2e2c1126..3fb73f80d 100644 --- a/config/locales/diaspora/es-CO.yml +++ b/config/locales/diaspora/es-CO.yml @@ -149,9 +149,6 @@ es-CO: fill_me_out: "Complétame" find_people: "Encontrar personas o #tags" invitations: - a_facebook_user: "Un usuario de Facebook" - check_token: - not_found: "No se encontró la identificación de invitación" create: no_more: "No tienes más invitaciones." rejected: "Las siguientes direcciones tuvieron problemas: " @@ -259,14 +256,8 @@ es-CO: type_error: "Error al subir la foto. ¿Estás seguro de que agregaste una imagen?" destroy: notice: "La foto fue eliminada." - new_photo: - empty: "{file} está vacío, por favor omítelo y nuevamente selecciona archivos." - invalid_ext: "{file} tiene una extensión inválida. Solo se permiten {extensions}." - size_error: "{file} es demasiado grande, el tamaño máximo de archivo es {sizeLimit}." new_profile_photo: upload: "¡Subir una nueva foto de perfil!" - show: - show_original_post: "Mostrar publicación original" privacy: "Privacidad" profile: "Perfil" profiles: diff --git a/config/locales/diaspora/es-MX.yml b/config/locales/diaspora/es-MX.yml index 3277c4c34..781666478 100644 --- a/config/locales/diaspora/es-MX.yml +++ b/config/locales/diaspora/es-MX.yml @@ -189,7 +189,6 @@ es-MX: conversations: create: fail: "Mensaje inválido" - no_contact: "¡Eh, primero necesitas añadir al contacto!" sent: "Mensaje enviado" index: conversations_inbox: "Conversaciones – Bandeja de entrada" @@ -391,9 +390,6 @@ es-MX: tutorials: "tutoriales" wiki: "wiki" invitations: - a_facebook_user: "Un usuario de Facebook" - check_token: - not_found: "No se encontró la identificación de invitación" create: empty: "Por favor, introduce al menos una dirección de correo electrónico." no_more: "No tienes más invitaciones." @@ -557,14 +553,8 @@ es-MX: type_error: "Error al subir la foto. ¿Estás seguro de que agregaste una imagen?" destroy: notice: "La foto fue eliminada." - new_photo: - empty: "{file} está vacío, por favor selecciona archivos nuevamente sin este último." - invalid_ext: "{file} tiene una extensión inválida. Solo se permiten {extensions}." - size_error: "{file} es demasiado grande, el tamaño máximo de un archivo es de {sizeLimit}." new_profile_photo: upload: "¡Subir una nueva foto de perfil!" - show: - show_original_post: "Mostrar publicación original" posts: presenter: title: "Una publicación de %{name}" diff --git a/config/locales/diaspora/es.yml b/config/locales/diaspora/es.yml index 3409e71e2..b516e2efb 100644 --- a/config/locales/diaspora/es.yml +++ b/config/locales/diaspora/es.yml @@ -254,6 +254,8 @@ es: post_something: "Publica en Diaspora*" cancel: "Cancelar" comments: + create: + error: "Hubo un error al comentar." new_comment: comment: "Comentar" commenting: "Comentando..." @@ -278,7 +280,6 @@ es: conversations: create: fail: "Mensaje no válido" - no_contact: "¡Eh, primero tienes que añadir al contacto!" sent: "Mensaje enviado" destroy: delete_success: "Conversación correctamente borrada" @@ -287,6 +288,7 @@ es: conversations_inbox: "Conversaciones – Bandeja de entrada" inbox: "Bandeja de entrada" new_conversation: "Nueva conversación" + no_contacts: "Necesitas añadir algunos contactos antes de empezar una conversación" no_messages: "Ningún mensaje" new: message: "Mensaje" @@ -544,7 +546,6 @@ es: own_your_data: "Sé el dueño de tus datos" own_your_data_info: "Muchas redes usan tus datos para hacer dinero analizando tus interacciones y usando esa información para mostrarte anuncios. diaspora* no usa tus datos para ningún propósito distinto que permitirte estar en contacto con otros." podmin: - admin_panel: "panel de administración" byline: "Estas a punto de cambiar internet. Vamos a configurarlo, ¿de acuerdo?" configuration_info: "Abre %{database_path} y %{diaspora_path} en tu editor de texto favorito y revisalos cuidadosamente, están comentados al detalle." configure_your_pod: "Configura tu pod" @@ -566,10 +567,8 @@ es: invitation_codes: not_valid: "Ese código de invitación ya no es válido" invitations: - a_facebook_user: "Un usuario de Facebook" - check_token: - not_found: "Identificación de invitación no encontrada" create: + closed: "Las invitaciones están desactivadas en este pod de diaspora*." empty: "Por favor, introduce al menos una dirección de correo electrónico." no_more: "No tienes más invitaciones." note_already_sent: "Las invitaciones han sido enviadas a: %{emails}" @@ -841,14 +840,8 @@ es: type_error: "Error subiendo la foto. ¿Seguro que añadiste la imagen?" destroy: notice: "Foto eliminada." - new_photo: - empty: "{file} está vacío, por favor selecciona otros archivos." - invalid_ext: "{file} tiene una extensión inválida. Sólo {extensions} están permitidas." - size_error: "{file} es demasiado largo, el tamaño máximo por archivo es de {sizeLimit}." new_profile_photo: upload: "¡Sube una foto nueva de perfil!" - show: - show_original_post: "Mostrar la publicación original" polls: votes: one: "%{count} voto por ahora" diff --git a/config/locales/diaspora/eu.yml b/config/locales/diaspora/eu.yml index a86e80cb7..32f04555b 100644 --- a/config/locales/diaspora/eu.yml +++ b/config/locales/diaspora/eu.yml @@ -206,9 +206,6 @@ eu: fill_me_out: "Bete nazazu" find_people: "Jendea edo #etiketak aurkitu" invitations: - a_facebook_user: "Facebook erabiltzaile bat" - check_token: - not_found: "Gonbidapena ez da aurkitu" create: no_more: "Ez daukazu gonbidapen gehiago." rejected: "Hurrengo e-posta hauek arazoak sortu dituzte:" @@ -404,14 +401,8 @@ eu: type_error: "Argazki igoerak huts egin du. Ziur al zaude irudia gehitu duzunaz?" destroy: notice: "Argazkia ezabatu duzu." - new_photo: - empty: "{file} hutsik dago, mesedez aukera itzazu fitxategiak hura kenduta." - invalid_ext: "{file}(r)en luzapena ez da onartu. {extensions} dira onartuak soilik." - size_error: "{file} pisutsuegia da, fitxategi baten gehiengo pisua {sizeLimit} da." new_profile_photo: upload: "Igo ezazu profil argazki berri bat!" - show: - show_original_post: "Jatorrizko mezua erakutsi" posts: presenter: title: "" diff --git a/config/locales/diaspora/fi.yml b/config/locales/diaspora/fi.yml index 267982531..daf10767a 100644 --- a/config/locales/diaspora/fi.yml +++ b/config/locales/diaspora/fi.yml @@ -229,7 +229,6 @@ fi: conversations: create: fail: "Virheellinen viesti" - no_contact: "Hei, sinun on ensin lisättävä vastaanottaja!" sent: "Viesti lähetetty" destroy: delete_success: "Keskustelun poistaminen onnistui" @@ -483,9 +482,6 @@ fi: invitation_codes: not_valid: "Kutsukoodi ei ole enää voimassa" invitations: - a_facebook_user: "Facebook-käyttäjä" - check_token: - not_found: "Kutsun tunnusta ei löytynyt" create: empty: "Ole hyvä kirjoita vähintään yksi sähköpostiosoite." no_more: "Sinulla ei ole enempää kutsuja." @@ -756,14 +752,8 @@ fi: type_error: "Kuvan lataus epäonnistui. Lisäsitkö varmasti kuvan?" destroy: notice: "Kuva poistettu." - new_photo: - empty: "{file} on tyhjä, valitse tiedostot uudelleen ilman kyseistä tiedostoa." - invalid_ext: "{file} sisältää viallisen tiedostopäätteen. Tuetut muodot ovat {extensions}." - size_error: "{file} on liian suuri, suurin tiedostokoko on {sizeLimit}." new_profile_photo: upload: "Lisää uusi profiilikuva!" - show: - show_original_post: "Näytä alkuperäinen julkaisu" posts: presenter: title: "Julkaisu käyttäjältä %{name}" diff --git a/config/locales/diaspora/fr.yml b/config/locales/diaspora/fr.yml index 2d4634520..bcb816a69 100644 --- a/config/locales/diaspora/fr.yml +++ b/config/locales/diaspora/fr.yml @@ -270,6 +270,8 @@ fr: post_something: "Publiez sur diaspora*" cancel: "Annuler" comments: + create: + error: "Impossible de commenter." new_comment: comment: "Commenter" commenting: "Commentaire en cours d'envoi..." @@ -294,7 +296,6 @@ fr: conversations: create: fail: "Message invalide" - no_contact: "Hé, vous avez besoin d'ajouter le contact d'abord !" sent: "Message envoyé" destroy: delete_success: "Conversation effacée avec succès" @@ -303,6 +304,7 @@ fr: conversations_inbox: "Discussions - Boîte de réception" inbox: "Boîte de réception" new_conversation: "Nouvelle discussion" + no_contacts: "Vous devez ajouter des contacts avant de pouvoir démarrer une conversation." no_messages: "Aucun message" new: message: "Message" @@ -327,6 +329,7 @@ fr: delete: "Supprimer" email: "Courriel" error_messages: + csrf_token_fail: "Le jeton CSRF est invalide. Veuillez vous connecter et réessayer." helper: correct_the_following_errors_and_try_again: "Corrigez les erreurs suivantes, puis réessayez." need_javascript: "Ce site web nécessite JavaScript pour fonctionner correctement. Si vous avez désactivé JavaScript, veuillez le réactiver et actualiser cette page." @@ -562,7 +565,6 @@ fr: own_your_data: "Soyez propriétaire de vos données" own_your_data_info: "De nombreux réseaux utilisent vos données pour gagner de l'argent en analysant vos interactions et en utilisant ces informations pour vous proposer des publicités ciblées. Vos données sur diaspora* ne servent qu'à vous mettre en relation et à partager avec d'autres personnes." podmin: - admin_panel: "panneau d'administrateur" byline: "Vous êtes sur le point de changer la face d'Internet. Prêt à vous lancer ?" configuration_info: "Ouvrez %{database_path} et %{diaspora_path} dans votre éditeur de texte favori et relisez-les soigneusement, ils sont abondamment commentés." configure_your_pod: "Configurez votre pod" @@ -582,12 +584,11 @@ fr: update_your_pod: "Maintenez votre pod à jour" update_your_pod_info: "Vous trouverez %{update_instructions}." invitation_codes: + already_logged_in: "Vous avez été invité par %{inviter} pour rejoindre ce pod mais vous êtes déjà connecté." not_valid: "Ce code d'invitation n'est plus valide." invitations: - a_facebook_user: "Un utilisateur de Facebook" - check_token: - not_found: "Jeton d'invitation introuvable" create: + closed: "Les invitations sont fermées sur ce pod diaspora*." empty: "Veuillez fournir au moins une adresse de courrier électronique." no_more: "Vous n’avez plus d’invitation." note_already_sent: "Une invitation a déjà été envoyée aux e-mails %{emails}" @@ -620,6 +621,9 @@ fr: profile: "Profil" settings: "Paramètres" toggle_navigation: "Afficher/cacher le menu" + likes: + create: + error: "Impossible d'aimer." limited: "Limité" more: "Plus" no_results: "Aucun résultat trouvé" @@ -654,6 +658,7 @@ fr: mark_read: "Marquer comme lu" mark_unread: "Marquer comme non lu" mentioned: "Vous mentionnant" + mentioned_in_comment: "Vous mentionnant dans un commentaire" no_notifications: "Vous n'avez pas encore de notifications." notifications: "Notifications" reshared: "Repartagé" @@ -673,9 +678,15 @@ fr: other: "%{actors} vous ont mentionné(e) dans le message %{post_link}." zero: "%{actors} ne vous a mentionné(e) dans le message %{post_link}." mentioned_deleted: - one: "%{actors} vous a mentionné-e dans un message supprimé." - other: "%{actors} vous ont mentionné-e dans un message supprimé." - zero: "%{actors} a ont mentionné-e dans un message supprimé." + one: "%{actors} vous a mentionné dans un message supprimé." + other: "%{actors} vous ont mentionné dans un message supprimé." + zero: "Personne ne vous a mentionné dans un message supprimé." + mentioned_in_comment: + one: "%{actors} vous a mentionné dans un commentaire sur le message %{post_link}." + other: "%{actors} vous ont mentionné dans un commentaire sur le message %{post_link}." + mentioned_in_comment_deleted: + one: "%{actors} vous a mentionné sur un commentaire supprimé." + other: "%{actors} vous ont mentionné sur un commentaire supprimé." post: "message" private_message: one: "%{actors} vous a envoyé un message." @@ -706,6 +717,29 @@ fr: confirm_email: click_link: "Pour activer votre nouvelle adresse électronique %{unconfirmed_email}, merci de suivre ce lien :" subject: "Merci d'activer votre nouvelle adresse électronique %{unconfirmed_email}" + csrf_token_fail: + body: |- + Bonjour %{name}, + + diaspora* a détecté une tentative d'accès à votre session qui pourrait ne pas être autorisée. Cela est probablement tout à fait anodin, mais peut éventuellement être une attaque cross-site request forgery (CSRF). Pour éviter tout risque que vos données soient compromises, vous avez été déconnecté. + + Une requête faite en utilisant un jeton CSRF incorrect ou manquant peut être due à : + + - une extension manipulant la requête ou créant des requêtes sans le jeton + - un ancien onglet resté ouvert + - un autre site web faisant des requêtes avec ou sans votre permission + - divers autres outils externes + - du code malveillant essayant d'accéder à vos données + + Pour plus d'information sur le CSRF, voir [%{link}](%{link}). + + Ne vous inquiétez pas; vous pouvez vous reconnecter maintenant. + + Si vous voyez ce message à plusieurs reprises, merci de vérifier les points ci-dessus, y compris les extensions du navigateur. + + Merci. + Le messager automatique de diaspora* ! + subject: "Nous avons reçu une demande non autorisée de votre compte, %{name}" email_sent_by_diaspora: "Ce courriel a été envoyé par %{pod_name}. Si vous ne souhaitez plus recevoir des courriels de ce genre," export_email: body: |- @@ -778,6 +812,9 @@ fr: mentioned: limited_post: "Vous avez été mentionné dans une publication restreinte." subject: "%{name} vous a mentionné(e) sur diaspora*" + mentioned_in_comment: + limited_post: "Vous avez été mentionné dans un commentaire sur une publication restreinte." + reply: "Répondre ou voir cette conversation >" private_message: reply_to_or_view: "Répondre ou voir cette conversation >" subject: "Vous avez un nouveau message privé" @@ -862,14 +899,8 @@ fr: type_error: "L'envoi de la photo a échoué. Vérifiez qu'une photo a bien été ajoutée ?" destroy: notice: "La photo a été supprimée." - new_photo: - empty: "{file} est vide, merci de sélectionner d'autres fichiers." - invalid_ext: "{file} a une extension invalide. Seules {extensions} sont autorisées." - size_error: "{file} est trop grand, la taille maximum pour un fichier est {sizeLimit}." new_profile_photo: upload: "Mettre une nouvelle photo de profil !" - show: - show_original_post: "Montrer le message original" polls: votes: one: "%{count} vote pour l'instant" @@ -953,8 +984,14 @@ fr: destroyed: "Le message a été détruit" failed: "Il y a eu un problème." title: "Vue d'ensemble des signalements." + unreviewed_reports: + one: "Il y a %{count} signalement non vérifié." + other: "Il y a %{count} signalements non vérifiés." + zero: "Il n'y a aucun signalement non vérifié." reshares: comment_email_subject: "Partage par %{resharer} d'un message de %{author}" + create: + error: "Le repartage a échoué." reshare: deleted: "Le message original a été supprimé par l'auteur." reshare_confirmation: "Repartager le message de %{author} ?" @@ -1109,7 +1146,7 @@ fr: success: "Votre compte est verrouillé. Cela peut nous prendre jusqu'à vingt minutes pour finaliser sa fermeture. Merci d'avoir essayé diaspora*." wrong_password: "Le mot de passe saisi ne correspond pas à votre mot de passe actuel." edit: - also_commented: "quelqu'un commente un message que vous avez déjà commenté." + also_commented: "…quelqu'un commente un message que vous avez déjà commenté." auto_follow_aspect: "Aspect pour les utilisateurs que vous suivez automatiquement :" auto_follow_back: "Suivre automatiquement en retour ceux qui vous suivent" change: "Modifier" @@ -1130,6 +1167,7 @@ fr: comment_on_post: "…quelqu'un commente un de vos messages." current_password: "Mot de passe actuel" current_password_expl: "Celui avec lequel vous vous connectez ..." + default_post_visibility: "Aspects sélectionnés par défaut pour la publication" download_export: "Télécharger mon profil" download_export_photos: "Télécharger mes photos" edit_account: "Modifier le compte" @@ -1141,6 +1179,7 @@ fr: last_exported_at: "(Dernière mise à jour à %{timestamp})" liked: "…quelqu'un a aimé votre message." mentioned: "…l'on vous mentionne dans un message." + mentioned_in_comment: "…vous êtes mentionné dans un commentaire" new_password: "Nouveau mot de passe" private_message: "…vous recevez un message privé." receive_email_notifications: "Recevoir des notifications par courrier électronique lorsque…" @@ -1151,7 +1190,7 @@ fr: reshared: "…quelqu'un a repartagé votre message." show_community_spotlight: "Afficher les actualités de la communauté dans votre flux" show_getting_started: "Montrer les astuces de découverte" - someone_reported: "Quelqu'un a signalé un message" + someone_reported: "…quelqu'un a signalé un message" started_sharing: "…quelqu'un commence à partager avec vous." stream_preferences: "Préférences du flux" your_email: "Votre adresse électronique" diff --git a/config/locales/diaspora/fy.yml b/config/locales/diaspora/fy.yml index bd41dd905..d7fedb053 100644 --- a/config/locales/diaspora/fy.yml +++ b/config/locales/diaspora/fy.yml @@ -59,7 +59,6 @@ fy: email: "E-mail" find_people: "Minsken of #labels Sykje" invitations: - a_facebook_user: "In Facebook brûker" new: invite_someone_to_join: "Immen útnoadigje foar Diaspora!" language: "Taal" diff --git a/config/locales/diaspora/ga.yml b/config/locales/diaspora/ga.yml index 175a66f7d..9bee9613e 100644 --- a/config/locales/diaspora/ga.yml +++ b/config/locales/diaspora/ga.yml @@ -66,7 +66,6 @@ ga: email: "Ríomhphoist" fill_me_out: "Líon amach" invitations: - a_facebook_user: "Úsáideoir Facebook" new: language: "Teanga" layouts: diff --git a/config/locales/diaspora/he.yml b/config/locales/diaspora/he.yml index dbb57ea34..d8f40e64c 100644 --- a/config/locales/diaspora/he.yml +++ b/config/locales/diaspora/he.yml @@ -199,7 +199,6 @@ he: conversations: create: fail: "הודעה שגויה" - no_contact: "הי, יש להוסיף את איש הקשר קודם!" sent: "ההודעה נשלחה" index: conversations_inbox: "שיחות - דואר נכנס" @@ -264,9 +263,6 @@ he: tutorials: "מדריכים" wiki: "ויקי" invitations: - a_facebook_user: "משתמש פייסבוק" - check_token: - not_found: "אסימון ההזמנה לא נמצא" create: empty: "נא להזין לפחות כתובת דוא\"ל אחת." no_more: "אין לך עוד הזמנות." @@ -438,14 +434,8 @@ he: type_error: "העלאת התמונה נכשלה. האם תמונה אכן נוספה?" destroy: notice: "התמונה נמחקה." - new_photo: - empty: "הקובץ {file} ריק, נא לבחור קבצים בשנית בלעדיו" - invalid_ext: "לקובץ {file} יש סיומת לא חוקית. רק הסיומות הבאות מאופשרות: {extensions}." - size_error: "הקובץ {file} גדול מדי. הגודל המירבי הוא {sizeLimit}." new_profile_photo: upload: "העלאת תמונת פרופיל חדשה" - show: - show_original_post: "הצגת ההודעה המקורית" posts: presenter: title: "הודעה מאת %{name}" diff --git a/config/locales/diaspora/hu.yml b/config/locales/diaspora/hu.yml index 5d45caf8f..d782f3f88 100644 --- a/config/locales/diaspora/hu.yml +++ b/config/locales/diaspora/hu.yml @@ -9,6 +9,8 @@ hu: _contacts: "Ismerősök" _help: "Súgó" _services: "Szolgáltatások" + _statistics: "Statisztika" + _terms: "feltételek" account: "Felhasználói fiók" activerecord: errors: @@ -49,11 +51,16 @@ hu: admins: admin_bar: pages: "Oldalak" - pod_stats: "Kiszolgáló statisztika" + pod_network: "Pod hálózat" + pod_stats: "Pod statisztika" report: "Jelentések" sidekiq_monitor: "Sidekiq monitor" user_search: "Felhasználó keresés" - weekly_user_stats: "Heti statisztika" + weekly_user_stats: "Heti felhasználóstatisztika" + dashboard: + pod_status: "Pod állapot" + pods: + pod_network: "Pod hálózat" stats: 2weeks: "2 hét" 50_most: "50 legnépszerűbb címke" @@ -89,9 +96,13 @@ hu: account_closing_scheduled: "%{name} felhasználó fiókjának törlése időzítve. Feldolgozása néhány pillanat múlva megtörténik..." add_invites: "meghívók hozzáadása" are_you_sure: "Biztosan törölni szeretnéd ezt a fiókot?" + are_you_sure_lock_account: "Biztosan zárolni akarod ezt a fiókot?" + are_you_sure_unlock_account: "Biztosan fel akarod oldani a fiók zárolását?" close_account: "fiók törlése" email_to: "a meghívandó személy email címe" + lock_account: "Fiók zárolása" under_13: "13 éven aluli felhasználók mutatása (az USA COPPA szabályzata szerint)" + unlock_account: "Fiók zárolásának feloldása" users: other: "%{count} felhasználó található" zero: "nem található felhasználó" @@ -105,13 +116,23 @@ hu: zero: "az új felhasználók száma ezen a héten: %{count}" current_server: "A jelenlegi szerverdátum: %{date}" all_aspects: "Összes csoport" + api: + openid_connect: + authorizations: + new: + approve: "Elfogadás" + deny: "Megtagadás" + user_applications: + index: + edit_applications: "Alkalmazások" are_you_sure: "Biztos vagy benne?" are_you_sure_delete_account: "Biztos, hogy törölni akarod a fiókodat? A törlés nem vonható vissza!" aspect_memberships: destroy: - failure: "Személy törlése a csoportból sikertelen" - no_membership: "Nem található a személy ebben a csoportban" - success: "Sikeresen törölted a személyt a csoportból" + failure: "Személy törlése a csoportból sikertelen." + forbidden: "Ezt nincs jogosultságod megtenni." + no_membership: "Nem található a kiválasztott személy ebben a csoportban." + success: "Sikeresen törölted a személyt a csoportból." aspects: add_to_aspect: failure: "A kapcsolatot nem sikerült felvenni a csoportba." @@ -123,7 +144,7 @@ hu: stay_updated: "Légy naprakész!" stay_updated_explanation: "A Hírfolyamodban megjelennek az ismerőseid bejegyzései, követett címkéid és a Reflektorfényben szereplő személyek bejegyzései." destroy: - failure: "%{name} nem üres, így nem lehet törölni." + failure: "%{name} nem törölhető." success: "%{name} csoport sikeresen törölve." edit: aspect_list_is_not_visible: "csoportlista rejtett a csoporttagok számára" @@ -157,10 +178,11 @@ hu: title: "Sziasztok új felhasználók" services: content: "A következő szolgáltatásokhoz tudsz kapcsolódni:" - heading: "Szolgáltatások összekapcsolása" + heading: "Közösségi hálók összekapcsolása" welcome_to_diaspora: "Üdv a diaspora* közösségi oldalon, %{name}!" no_contacts_message: community_spotlight: "a figyelem középpontjában" + invite_link_text: "meghívás" or_spotlight: "Vagy körülnézhetsz a kiemelt tagok között is, lásd: %{link}" try_adding_some_more_contacts: "Ismerősöket kereshetsz vagy hívhatsz meg." you_should_add_some_more_contacts: "Adj hozzá még néhány ismerőst." @@ -207,22 +229,23 @@ hu: conversations: create: fail: "Érvénytelen üzenet" - no_contact: "Hé, először kapcsolatot kell hozzáadnod!" sent: "Üzenet elküldve" index: conversations_inbox: "Beszélgetések - levelesláda" inbox: "Bejövő" new_conversation: "Új beszélgetés" - no_messages: "nincs üzenet" + no_messages: "Nincs üzenet" new: + message: "Üzenet" send: "Küldés" sending: "Küldés ..." subject: "tárgy" + subject_default: "Nincs tárgy" to: "címzett" new_conversation: fail: "Érvénytelen üzenet" show: - delete: "beszélgetés törlése" + delete: "Beszélgetés törlése" reply: "válasz" replying: "Válaszolás..." date: @@ -257,27 +280,36 @@ hu: remove_notification_a: "Nem." remove_notification_q: "Ha valakit eltávolítok egy csoportból, vagy az összes csoportomból, kap róla értesítést?" rename_aspect_a: "Igen. A csoportjaid listáját a kezdőképernyő bal oldalán éred el. Mozgasd az egérmutatót az átnevezendő csoport fölé. Kattints az ekkor megjelenő ceruza (szerkesztés) ikonra. A felugró ablakban válaszd az átnevezés lehetőséget." - rename_aspect_q: "Átnevezhetem a csoportokat?" + rename_aspect_q: "Hogyan nevezek át egy csoportot?" restrict_posts_i_see_a: "Igen. Kattints a \"csoportjaim\" feliratra a bal oldalsávon és válaszd ki azokat a csoportokat, amelyeket megjeleníteni vagy elrejteni szeretnél. Csak a kijelölt csoportokhoz tartozó személyek bejegyzései fognak látszódni a hírfolyamodban." restrict_posts_i_see_q: "Korlátozhatom a megjelenítendő bejegyzéseket csak bizonyos csoportokból származóakra?" title: "Csoportok" what_is_an_aspect_a: "A csoport (vagy eredetileg \"aspektus\") az a mód, ahogy a kapcsolataidat rendszerezed a diaspora-n. Különböző arcaidat, oldalaidat különbözőképpen mutathatod meg például a munkatársaid, a családod, netán meghatározott közösséghez tartozó barátaid számára." what_is_an_aspect_q: "Mit jelent a \"csoport\"?" who_sees_post_q: "Amikor bejegyzést írok egy csoportba, ki láthatja azt?" - foundation_website: "a diaspora* alapítvány honlapja" + chat: + add_contact_roster_q: "Hogyan tudok csevegni valakivel a diasporán*?" + title: "Csevegés" + faq: "GYIK" + foundation_website: "diaspora* alapítvány" getting_help: + get_support_a_faq: "tekintsd meg %{faq} oldalunkat" get_support_a_hashtag: "kérdezz magyarul a közösségi hálón, nyilvános bejegyzésben a %{question} címke használatával" - get_support_a_irc: "Kapcsolódj %{irc}-en (élő csevegés)" - get_support_a_tutorials: "nézd meg az általunk készített %{tutorials}at" + get_support_a_irc: "kapcsolódj be %{irc}-en az élő csevegésbe" + get_support_a_tutorials: "nézd át az általunk készített %{tutorials}at" get_support_a_website: "látogasd meg a %{link} honlapját" get_support_a_wiki: "kutass a %{link} adattárunkban" get_support_q: "Mit tegyek, ha a kérdésemre itt nem találok választ? Hol kaphatok még felvilágosítást?" - getting_started_a: "Szerencséd van. Tekintsd át a %{tutorial_series} című angol nyelvű bemutató oldalunkat. Lépésről lépésre végigvezet a feliratkozási eljáráson és megtanítja mindazokat az alapvető dolgokat, amiket tudnod kell a Diaspora* használatához." + getting_started_a: "Szerencséd van. %{tutorial_series} nevű bemutató oldalunk lépésről lépésre végigvezet téged a regisztrációs eljáráson és megismerteti a diaspora* használatához szükséges alapvető tudnivalókat." getting_started_q: "Húha! A kezdéshez elkélne némi alapvető segítség!" title: "Források a tájékozódáshoz" getting_started_tutorial: "'Kezdő lépések'" here: "itt" irc: "IRC" + keyboard_shortcuts: + keyboard_shortcuts_a1: "A hírfolyam nézetben a következő billentyűparancsok állnak rendelkezésedre:" + keyboard_shortcuts_q: "Milyen billentyűparancsokat használhatok?" + title: "Billentyűparancsok" markdown: "markdown" mentions: how_to_mention_a: "Írj le egy \"@\" jelet és kezdd el gépelni az illető nevét. Egy legördülő menü fog megjelenni annak érdekében, hogy könnyebben választhass. Fontos, hogy csak azokat az embereket tudod megemlíteni, akiket hozzáadtál valamely csoporthoz." @@ -291,12 +323,15 @@ hu: miscellaneous: back_to_top_a: "Igen. Miután legörgeted az oldalt, kattints a böngészőablak jobb alsó sarkában megjelenő szürke nyílra." back_to_top_q: "Van gyors módja annak, hogy visszajussak az oldal elejére miután lejjebb görgettem?" - diaspora_app_a: "Számos Android alkalmazás van a korai fejlesztés állapotában. Ezek közül többen régóta magára hagyott projektek, így nem működnek jól a Diaspora legújabb változatával. Ne várj túl sokat ezektől az alkalmazásoktól jelenleg. Pillanatnyilag a Diaspora-hoz való hozzáférés legjobb módja, ha a mobil böngésződön keresztül próbálsz csatlakozni, mivel erre optimalizáltuk a rendszert. Aktuálisan nincs iOS alkalmazásunk. Röviden szólva: a Diaspora legjobban a böngésződön keresztül fog működni." + diaspora_app_a: "Számos Android alkalmazás van a korai fejlesztés állapotában. Ezek közül többen régóta magára hagyott projektek, így nem működnek jól a diaspora* legújabb változatával. Ne várj túl sokat ezektől az alkalmazásoktól. Pillanatnyilag a diaspora*-hoz való hozzáférés legjobb módja, ha a mobil böngésződön keresztül próbálsz csatlakozni, mivel erre optimalizáltuk a rendszert. Jelenleg nincs iOS alkalmazásunk. Egy szó mint száz: a diaspora* legjobban a böngésződön keresztül működik." diaspora_app_q: "Létezik Diaspora* alkalmazás Android vagy iOS rendszerre?" photo_albums_a: "Jelenleg nem. Mindazonáltal a feltöltött képek folyamát megtekintheted az adatlapok oldalsávjának fényképek részlegén." - photo_albums_q: "Támogatottak a kép- vagy videó gyűjtemények?" + photo_albums_q: "Támogatottak a kép- vagy videógyűjtemények?" subscribe_feed_q: "Feliratkozhatok valakinek a nyilvános bejegyzéseire hírfolyam (RSS) olvasóval?" title: "Egyebek" + pods: + title: "Podok" + what_is_a_pod_q: "Mit jelent a pod?" posts_and_posting: char_limit_services_a: "Ebben az esetben a bejegyzésed legfeljebb annyi leütésből állhat, ahányat az adott szolgáltató engedélyez (ami 140 a Twitter és 1000 a Tumblr esetében). A még felhasználható karakterek számát az adott szolgáltató ikonjánál láthatod. Küldhetsz ennél hosszabb bejegyzéseket is, de akkor a szöveg fennmaradó részét levágják az említett szolgáltatók." char_limit_services_q: "Legfeljebb hány leütésből állhat a bejegyzésem, ha olyan összekapcsolt szolgáltatáson keresztül küldöm el, ahol csak kevés karakter engedélyezett?" @@ -308,7 +343,7 @@ hu: image_text: "kép szövege" image_url: "kép url" insert_images_a: "Kattints a kis fényképezőgép jelére, ha képet szeretnél beszúrni a bejegyzésedbe. Nyomd meg az ikont ismételten, ha újabbat is szeretnél hozzáadni. Lehetőséged van több képet is egyszerre kiválasztani." - insert_images_comments_a1: "A következő markdown kód" + insert_images_comments_a1: "Nem tudsz képeket feltölteni hozzászólásokba, de a következő markdown kód" insert_images_comments_a2: "használható a világhálóról származó képek bejegyzésekbe és hozzászólásokba való beillesztéséhez" insert_images_comments_q: "Beilleszthetek képeket a hozzászólásaimba?" insert_images_q: "Hogyan helyezhetek el képeket a bejegyzésemben?" @@ -370,13 +405,19 @@ hu: title: "Címkék" what_are_tags_for_q: "Mire valók a címkék?" third_party_tools: "külsős fejlesztőeszközök" + title_header: "Súgó" tutorial: "útmutató" tutorials: "útmutatók" wiki: "wiki" + home: + default: + be_who_you_want_to_be: "Legyél, aki szeretnél lenni!" + be_who_you_want_to_be_info: "Sok közösségi hálózat ragaszkodik ahhoz, hogy a valódi identitásod használd. A diaspora* nem. Itt az lehetsz, aki csak akarsz, és te döntöd el, hogy mennyi információt osztasz meg magadról. Itt tényleg rajtad áll a döntés, hogyan lépsz kapcsolatba másokkal." + byline: "Az online közösség, ahol tiéd az irányítás." + choose_your_audience: "Válaszd meg közönséged" + invitation_codes: + not_valid: "Ez a meghívó kód már nem érvényes" invitations: - a_facebook_user: "Egy Facebook felhazsnáló" - check_token: - not_found: "Meghívó azonosító nem található" create: empty: "Kérlek adj meg legalább egy e-mail címet." no_more: "Nincs több felkérésed." @@ -390,17 +431,19 @@ hu: comma_separated_plz: "Megadhatsz több e-mail címet is vesszővel elválasztva." invite_someone_to_join: "Hívj meg valakit, hogy csatlakozzon a diaspora*-hoz!" language: "Nyelv" - paste_link: "Ha szeretnéd meghívni a barátaidat a Diaspora-ra, oszd meg velük ezt a hivatkozást vagy küldd el nekik közvetlenül levélben." + paste_link: "Ha szeretnéd meghívni a barátaidat a diaspora*-ra, oszd meg velük ezt a hivatkozást vagy küldd el nekik közvetlenül levélben." send_an_invitation: "Küldj egy meghívót" sending_invitation: "Meghívó küldése folyamatban..." layouts: application: back_to_top: "Vissza az elejére" + be_excellent: "Legyetek mindig jók egymáshoz! ♥" powered_by: "diaspora* - fordította adamex & danielwine" public_feed: "%{name} nyilvános diaspora* hírfolyama" source_package: "forráskódcsomag letöltése" + statistics_link: "pod statisztika" toggle: "mobil változat" - whats_new: "Mik az újdonságok?" + whats_new: "mik az újdonságok?" header: code: "kód" logout: "Kijelentkezés" @@ -408,7 +451,7 @@ hu: settings: "Beállítások" limited: "Korlátozott" more: "Bővebben" - no_results: "Nincs eredmény" + no_results: "Nincs találat" notifications: also_commented: few: "%{actors} is hozzászólt %{post_author} bejegyzéséhez: %{post_link}." @@ -588,7 +631,7 @@ hu: no_results: "Hé! Valamit keresned kell." results_for: "A keresési szűrőnek (%{search_term}) megfelelt felhasználók" search_handle: "Hogy biztosan megtaláld a barátaidat, használd a diaspora azonosítójukat (felhasználónév@pod.tld)." - searching: "keresés folyamatban, légy türelmes..." + searching: "Keresés folyamatban, türelem..." send_invite: "Még mindig semmi? Küldj meghívót!" person: thats_you: "Ez vagy Te!" @@ -608,18 +651,13 @@ hu: type_error: "Kép feltöltése nem sikerült. Biztos vagy benne, hogy jelöltél ki képet?" destroy: notice: "Kép törölve." - new_photo: - empty: "{file} egy üres fájl, válaszd ki újra a fájlokat {file} kivételéve!" - invalid_ext: "{file} érvénytelen kiterjesztés. Csak {extensions} kiterjesztések megengedettek." - size_error: "{file} túl nagy, maximum fájlméret {sizeLimit}." new_profile_photo: upload: "Tölts fel új önarcképet!" - show: - show_original_post: "Eredeti bejegyzés megtekintése" posts: presenter: title: "%{name} bejegyzése" show: + forbidden: "Ezt nincs jogosultságod megtenni" photos_by: few: "%{count} fénykép tőle: %{author}" many: "%{count} fénykép tőle: %{author}" @@ -633,11 +671,17 @@ hu: profiles: edit: allow_search: "megtalálható legyek a diaspora* keresőben" + basic: "Alapvető adatlapom" + extended: "Kibővített adatlapom" + extended_visibility_text: "Kibővített adatlapod láthatósága:" first_name: "Keresztnév" last_name: "Vezetéknév" + limited: "Korlátozott" nsfw_check: "Minden megosztásom megjelölése NSFW tartalomként" nsfw_explanation: "Az NSFW (munkahelyen nem illő tartalom) a diaspora* közösségének saját szabványa azokra a tartalmakra vonatkozólag, melyek nem illdomosak munkahelyen történő megtekintésre. Ha ilyen jellegű anyagot gyakran szeretnél küldeni, kérlek jelöld be ezt a lehetőséget, hogy csak azok a személyek láthassák, akik úgy döntöttek, szeretnék ha megjelenne a hírfolyamukban hasonló tartalom." nsfw_explanation2: "Ha nem választod ezt a lehetőséget, kérünk, hogy minden ilyen típusú tartalmadat bejegyzésenként külön jelöld meg az #nsfw címkével." + public: "Nyilvános" + settings: "Adatlap beállításai" update_profile: "Adatlap frissítése" your_bio: "Írj pár sort magadról" your_birthday: "Születésnapod" @@ -655,23 +699,23 @@ hu: other: "%{count} visszajelzés" zero: "nincs visszajelzés" registrations: - closed: "A feliratkozási lehetőség zárolva van ezen a diaspora* kiszolgálón." + closed: "A regisztrációs lehetőség zárolva van ezen a diaspora* kiszolgálón." create: success: "Csatlakoztál a diaspora* közösségi oldalra!" invalid_invite: "Ez a meghívó többé nem érvényes!" new: - email: "E-MAIL" - enter_email: "Írd be az e-mail címed" + email: "E-mail" + enter_email: "Add meg az e-mail címed" enter_password: "Adj meg egy jelszót (legalább hat karakterből álljon)" - enter_password_again: "Ugyanazt a jelszót írd amit az előbb" + enter_password_again: "Ugyanazt a jelszót add meg, amit a fenti mezőben" enter_username: "Válassz egy felhasználónevet (csak angol betű, szám és aláhúzás megengedett)" - password: "JELSZÓ" + password: "Jelszó" password_confirmation: "Jelszó megerősítése" - sign_up: "Feliratkozás" + sign_up: "Fiók létrehozása" submitting: "Feldolgozás folyamatban..." terms: "A fiók létrehozásával elfogadod a %{terms_link}." terms_link: "felhasználási feltételeket" - username: "AZONOSÍTÓ" + username: "Azonosító" report: comment_label: "Hozzászólás:
%{data}" confirm_deletion: "Biztosan törölni akarod ezt az elemet?" @@ -704,12 +748,17 @@ hu: error: "Hiba történt a szolgáltatáshoz való kapcsolódás során" index: connect: "Kapcsolódás" - disconnect: "megszakít" + disconnect: "Leválasztás" edit_services: "Szolgáltatások szerkesztése" logged_in_as: "- bejelentkeztél ezen a néven:" not_logged_in: "Jelenleg nem vagy bejelentkezve." - really_disconnect: "Megszakítod a kapcsolatot ezzel: %{service}?" + really_disconnect: "%{service} kapcsolat leválasztása?" services_explanation: "Ha kapcsolódsz más szolgáltatásokhoz, lehetőséged lesz bejegyzéseket küldeni a felületükre, amint azokat a diaspora* rendszerén belül megírod." + provider: + facebook: "Facebook" + tumblr: "Tumblr" + twitter: "Twitter" + wordpress: "WordPress" settings: "Beállítások" shared: aspect_dropdown: @@ -729,7 +778,7 @@ hu: atom_feed: "Atom hírfolyamod (feed)" control_your_audience: "Válassz célközönséget!" logged_in: "bejelentkezve ide: %{service}" - manage: "kapcsolódó szolgáltatások kezelése" + manage: "Kapcsolódó szolgáltatások kezelése" new_user_welcome_message: |- Használj kettőskeresztet(#), hogy felcímkézd a bejegyzésedet. Címkék alapján találhatsz veled azonos érdeklődésű embereket. A kukac(@) jellel pedig személyeket említhetsz meg a bejegyzésedben. @@ -763,6 +812,21 @@ hu: failed: "Ellenőrzés sikertelen" user: "A titkos kép és jel különbözőek voltak" placeholder: "Írd ide a látott számot" + statistics: + active_users_halfyear: "aktív felhasználók az elmúlt fél évben" + active_users_monthly: "aktív felhasználók havonta" + closed: "zárt" + disabled: "nem hozzáférhető" + enabled: "hozzáférhető" + local_comments: "helyi hozzászólások" + local_posts: "helyi bejegyzések" + name: "név" + network: "hálózat" + open: "nyílt" + registrations: "regisztráció" + services: "szolgáltatások" + total_users: "összes felhasználó" + version: "változat" status_messages: create: success: "Megemlítetted: %{names}" @@ -779,7 +843,7 @@ hu: title: "Csoportjaim" aspects_stream: "Csoportok" comment_stream: - title: "Hozzászólt bejegyzések" + title: "Kommentált bejegyzések" community_spotlight_stream: "A figyelem középpontjában" followed_tag: add_a_tag: "Címke hozzáadása" @@ -797,6 +861,10 @@ hu: title: "Nyilvános tevékenység" tags: title: "Bejegyzés megjelölve: %{tags}" + tag_followings: + manage: + no_tags: "Nem követsz egyetlen címkét sem." + title: "Követett címkék kezelése" tags: show: follow: "Címke követése" @@ -810,12 +878,13 @@ hu: destroy: no_password: "Add meg a jelszavad, hogy megszüntesd a fiókod." success: "A fiókodat lezártuk. Húsz percbe is beletelhet, mire befejezzük a fiókod törlését. Köszönjük, hogy kipróbáltad a diaspora* közösségi oldalt." - wrong_password: "A megadott jelszó nem felel meg." + wrong_password: "A megadott jelszó nem egyezik meg az érvényben lévővel." edit: - also_commented: "más is hozzászólt az ismerősöd bejegyzéséhez?" + also_commented: "más is hozzászólt egy általad kommentált bejegyzéshez?" auto_follow_aspect: "Csoport az automatikusan követett felhasználóknak:" auto_follow_back: "Automatikusan megosztod valakivel a tartalmaidat, ha a másik is elkezdett megosztani veled" change: "Módosítás" + change_color_theme: "Színséma megváltoztatása" change_email: "Email megváltoztatása" change_language: "Nyelv megváltoztatása" change_password: "Jelszó módosítása" @@ -824,7 +893,7 @@ hu: dont_go: "Hé, kérlek ne menj!" lock_username: "A felhasználóneved foglalt marad. Nem lesz lehetőséged ezen a kiszolgálón új fiókot létrehozni ugyanezzel a névvel." locked_out: "Ki fogunk léptetni és kizárunk a fiókodból, amíg végleg el nem távolítjuk." - make_diaspora_better: "Azt szeretnénk, ha segítenél, hogy jobbá tehessük a diaspora*-t. A távozásod helyett ezért szívesebben vennénk, ha közreműködnél. Ám ha úgy döntesz, hogy elhagyod az oldalt, a következő fog történni:" + make_diaspora_better: "Szeretnénk, ha segítenél jobbá tenni a diaspora*-t. Távozásod helyett ezért szívesebben vennénk, ha közreműködnél. Ám ha úgy döntesz, hogy elhagyod az oldalt, a következő fog történni:" mr_wiggles: "Vuk szomorú lesz, ha távozni lát." no_turning_back: "Nincs visszaút! Ha teljesen biztos vagy benne, add meg a jelszavadat a lenti mezőben." what_we_delete: "Töröljük az összes bejegyzésedet és adatodat amint tudjuk. A mások bejegyzéseihez írt hozzászólásaid megmaradnak, de a neved helyett csak a diaspora* azonosítód lesz látható mellettük." @@ -835,7 +904,8 @@ hu: download_export_photos: "Képeim letöltése" edit_account: "Fiók szerkesztése" email_awaiting_confirmation: "Aktivációs link elküldve ide: %{unconfirmed_email}. Amíg nem erősíted meg az új címed, addig a régit használjuk: %{email}." - export_data: "Adatok kivitele" + export_data: "Adatok letöltése" + export_in_progress: "Az adataid feldolgozása folyamatban van. Kérlek nézz vissza pár perc múlva." export_photos_in_progress: "Jelenleg folyamatban van a képeid feldolgozása. Kérlek nézz vissza később." following: "Követési beállítások" liked: "valakinek tetszik a bejegyzésed?" @@ -843,14 +913,18 @@ hu: new_password: "Új jelszó" private_message: "személyes üzenetet kaptál?" receive_email_notifications: "Szeretnél értesítést kapni levélben, ha:" + request_export: "Profiladataim igénylése" + request_export_photos: "Képeim igénylése" request_export_photos_update: "Képeim frissítése" + request_export_update: "Profiladataim frissítése" reshared: "valaki újraosztotta a bejegyzésedet?" show_community_spotlight: "A \"figyelem középpontjában\" lévő tartalmak megjelenítése a hírfolyamban" - show_getting_started: "\"Kezdő lépések\" újra engedélyezése" + show_getting_started: "\"Kezdő lépések\" újbóli megjelenítése" someone_reported: "valaki jelentést küldött" started_sharing: "valaki elkezd megosztani veled?" stream_preferences: "Hírfolyam tulajdonságai" your_email: "E-mail címed" + your_email_private: "Az emailedet sosem látja más" your_handle: "diaspora* azonosítód" getting_started: awesome_take_me_to_diaspora: "Remek! Irány a Diaspora*" @@ -870,6 +944,8 @@ hu: public: does_not_exist: "%{username} nem létezik!" update: + color_theme_changed: "Színséma sikeresen megváltozott." + color_theme_not_changed: "Hiba lépett fel a színséma megváltoztatása során." email_notifications_changed: "E-mail értesítések módosítva" follow_settings_changed: "Követési beállítások megváltoztak" follow_settings_not_changed: "Követési beállítások megváltoztatása sikertelen." diff --git a/config/locales/diaspora/hy.yml b/config/locales/diaspora/hy.yml index 81af4011d..d4b6400be 100644 --- a/config/locales/diaspora/hy.yml +++ b/config/locales/diaspora/hy.yml @@ -292,7 +292,6 @@ hy: conversations: create: fail: "Անվավեր հաղորդագրություն։" - no_contact: "Հեյ, բա հասցեատե՞րը։" sent: "Հաղորդագրությունն ուղարկված է։" destroy: delete_success: "Խոսակցությունը հաջողությամբ ջնջվեց։" @@ -564,7 +563,6 @@ hy: own_your_data: "Եղի՛ր քո տվյալների տերը" own_your_data_info: "Շատ ցանցեր օգտագործում են քո տվյալները գումար վաստակելու նպատակով՝ վերլուծելով քո փոխազդեծություններն ու այդ տեղեկատվության հիման վրա քեզ իրեր գովազդելով։ դիասպորա*ն չի օգտագործում քո տվյալները որեւէ նպատակի համար, բացի քեզ հնարավորություն տալուց՝ կապ հաստատել ու կիսվել ուրիշների հետ։" podmin: - admin_panel: "ադմինի վահանակ" byline: "Դու մոտ ես Համացանցը փոխելուն։ Արի, նախապատրաստենք քեզ, հը՞մ։" configuration_info: "Բացիր %{database_path} ու %{diaspora_path} քո նախընտրած տեքստային խմբագրիչի մեջ ու ուշադիր ուսումնասիրիր այն։ Դրանք մանրամասն մեկնաբանված են։" configure_your_pod: "Կարգավորի՛ր քո փոդը" @@ -578,7 +576,7 @@ hy: getting_help_info: "Մենք %{faq} ենք կազմել՝ ներառյալ որոշ լրացուցիչ խորհուրդներ, հնարքներ ու լուծումներ ամենահաճախակի հանդիպող խնդիրների համար։ Նաեւ քեզ ազատ զգա՝ %{irc}։" headline: "Բարի գալո՜ւստ, ընկեր։" make_yourself_an_admin: "Քեզ ադմի՛ն դարձրու" - make_yourself_an_admin_info: "Ցուցումները կարող ես գտնել %{wiki}ում։ Սրա արդյունքում «Ադմին» հղում կավելանա քո օգտատիրոջ մենյուում, երբ մուտք գործած լինես։ Դա քեզ մի շարք հնարավորություններ կտա, ինչպես օրինակ՝ օգտատերերի որոնում կամ քո փոդի վիճակագրությունը։ Քո փոդի գործման կողմերի վերաբերյալ առավել շատ մանրամասների համար անցիր %{admin_panel}։" + make_yourself_an_admin_info: "Ցուցումները կարող ես գտնել %{wiki}ում։ Սրա արդյունքում «%{admin_dashboard}» հղում կավելանա քո օգտատիրոջ մենյուում, երբ մուտք գործած լինես։ Դա քեզ մի շարք հնարավորություններ կտա, ինչպես օրինակ՝ օգտատերերի որոնում կամ քո փոդի վիճակագրությունը։" report_bugs: "տեղեկացրու դրանց մասին" update_instructions: "դիասպորա*յի վիքիում" update_your_pod: "Թարմացրո՛ւ քո փոդը" @@ -586,14 +584,11 @@ hy: invitation_codes: not_valid: "Հրավերի այս կոդն այլեւս անվավեր է" invitations: - a_facebook_user: "Ֆեյսբուքյան օգտատեր" - check_token: - not_found: "Հրավերի կոդանշանը չգտնվեց։" create: empty: "Պետք է առնվազն մեկ էլ․հասցե նշես։" no_more: "Այլևս հրավեր ուղարկելու իրավունք չունես։" note_already_sent: "Հրավերները արդեն ուղարկվել են հետևյալ հասցեներին՝ %{emails}" - rejected: "Հետևյալ էլ.հասցեների հետ կապված խնդիրներ կան՝ " + rejected: "Հետևյալ էլ.հասցեների հետ կապված խնդիրներ կան՝ %{emails}" sent: "Հրավերները ուղարկվեցին հետևյալ հասցեներով՝ %{emails}" new: codes_left: @@ -648,10 +643,11 @@ hy: comment_on_post: "Մեկնաբանել են գրառումը" liked: "Հավանել են" mark_all_as_read: "Նշել ամբողջը որպես ընթերցված" - mark_all_shown_as_read: "Նշել բոլոր ցուցադրվածները որպես կարդացված։" + mark_all_shown_as_read: "Նշել բոլոր ցուցադրվածները որպես կարդացված" mark_read: "Նշել որպես նայած" mark_unread: "Նշել որպես չկարդացված" - mentioned: "Նշել են" + mentioned: "Նշել են գրառման մեջ" + mentioned_in_comment: "Նշել են մեկնաբանության մեջ" no_notifications: "Դեռ ոչ մի ծանուցում չունես։" notifications: "Ծանուցումներ" reshared: "Տարածել են" @@ -674,6 +670,12 @@ hy: one: "%{actors} նշել է քեզ ջնջված գրառման մեջ։" other: "%{actors} նշել են քեզ ջնջված գրառման մեջ։" zero: "%{actors} նշել է քեզ ջնջված գրառման մեջ։" + mentioned_in_comment: + one: "%{actors} նշել է քեզ %{post_link} գրառման մեկնաբանության մեջ։" + other: "%{actors} նշել են քեզ %{post_link} գռարռման մեկնաբանության մեջ։" + mentioned_in_comment_deleted: + one: "%{actors} նշել է քեզ ջնջված մեկնաբանության մեջ։" + other: "%{actors} նշել են քեզ ջնջված մեկնաբանության մեջ։" post: "գրառում" private_message: one: "%{actors} քեզ հաղորդագրություն է ուղարկել։" @@ -855,14 +857,8 @@ hy: type_error: "Նկար վերբեռնելը տապալվեց։  Համոզված ե՞ս, որ հենց նկար էիր ավելացրել։" destroy: notice: "Նկարը ջնջված է։" - new_photo: - empty: "{file}-ը դատարկ է, կրկին ընտրիր ֆայլերը առանց դրա։" - invalid_ext: "{file}-ը անհամապատասխան ընդլայնման է։ Միայն {extensions} են թույլատրվում։" - size_error: "{file}-ը չափից դուրս մեծ է, առավելագույն չափն է՝ {sizeLimit}։" new_profile_photo: upload: "Նո՜րը վերբեռնել" - show: - show_original_post: "Ցույց տալ սկզբնական գրառումը" polls: votes: one: "առայժմ %{count} ձայն" @@ -990,7 +986,7 @@ hy: other: "%{count} խմբում" zero: "Ավելացնել " invitations: - by_email: "Էլ.հասցեով" + by_email: "Հրավիրիր մարդկանց էլ.հասցեով" invite_your_friends: "Կանչի՛ր ընկերներիդ" invites: "Հրավերներ" share_this: "Ուղարկիր այս հղումը էլ.փոստի, բլոգի կամ այլ սոցիալական ցանցերի միջոցով։" diff --git a/config/locales/diaspora/ia.yml b/config/locales/diaspora/ia.yml index fcc30506a..48fba4a45 100644 --- a/config/locales/diaspora/ia.yml +++ b/config/locales/diaspora/ia.yml @@ -53,7 +53,7 @@ ia: dashboard: "Pannello de instrumentos" pages: "Paginas" pod_network: "Rete de pods" - pod_stats: "Statisticas de pod" + pod_stats: "Statisticas del pod" report: "Reportos" sidekiq_monitor: "Monitor Sidekiq" user_search: "Recerca de usatores" @@ -64,12 +64,12 @@ ia: pods: pod_network: "Rete de pods" stats: - 2weeks: "2 Septimana" + 2weeks: "2 septimanas" 50_most: "Le 50 etiquettas le plus popular" current_segment: "Le segmento actual ha un media de %{post_yest} entratas per usator, a partir de %{post_day}" daily: "Quotidian" display_results: "Resultatos del segmento %{segment}" - go: "va" + go: "Va" month: "Mense" tag_name: "Nomine del etiquetta: %{name_tag} Occurrentias: %{count_tag}" usage_statistic: "Statisticas de uso" @@ -80,6 +80,7 @@ ia: email: "E-mail" guid: "GUID" id: "ID" + invite_token: "Indicio de invitation" last_seen: "ultime visita" ? "no" : "no" @@ -91,20 +92,21 @@ ia: account_closing_scheduled: "Le conto de %{name} es planate a esser claudite. Illo essera processate in alcun momentos…" account_locking_scheduled: "Le conto de %{name} es planate a esser blocate. Illo essera processate in alcun momentos…" account_unlocking_scheduled: "Le conto de %{name} es planate a esser disblocate. Illo essera processate in alcun momentos…" - add_invites: "adder invitationes" + add_invites: "Adder invitationes" are_you_sure: "Es tu secur de voler clauder iste conto?" are_you_sure_lock_account: "Es tu secur de voler blocar iste conto?" are_you_sure_unlock_account: "Es tu secur de voler disblocar iste conto?" close_account: "clauder conto" email_to: "Adresse de e-mail a invitar" + invite: "Invitar" lock_account: "Blocar conto" under_13: "Monstrar usatores con minus de 13 annos (COPPA)" unlock_account: "Disblocar conto" view_profile: "vider profilo" you_currently: - one: "il te resta un invitation %{link}" - other: "il te resta %{count} invitationes %{link}" - zero: "il non te resta invitationes %{link}" + one: "Il te resta un invitation %{link}" + other: "Il te resta %{count} invitationes %{link}" + zero: "Il non te resta invitationes %{link}" weekly_user_stats: amount_of: one: "Numero de nove usatores iste septimana: %{count}" @@ -131,12 +133,30 @@ ia: login_required: "Tu debe aperir session ante de poter autorisar iste application" title: "Un problema ha occurrite." scopes: + aud: + description: "Isto concede permissiones \"aud\" al application" + name: "aud" + name: + description: "Isto concede permissiones \"name\" al application" + name: "nomine" + nickname: + description: "Isto concede permissiones \"nickname\" al application" + name: "pseudonymo" openid: description: "Isto permitte que le application lege tu profilo basic" name: "profilo basic" + picture: + description: "Isto concede permissiones \"picture\" al application" + name: "imagine" + profile: + description: "Isto permitte que le application lege tu profilo extendite" + name: "profilo extendite" read: description: "Isto permitte que le application lege tu fluxo, tu conversationes e tu profilo complete" name: "leger profilo, fluxo e conversationes" + sub: + description: "Isto concede permissiones \"sub\" al application" + name: "sub" write: description: "Isto permitte que le application publica nove entratas, scribe conversationes e invia reactiones" name: "inviar entratas, conversationes e reactiones" @@ -154,11 +174,11 @@ ia: are_you_sure_delete_account: "Es tu secur de voler clauder tu conto? Isto non pote esser disfacite!" aspect_memberships: destroy: - failure: "Le remotion del persona del aspecto ha fallite" + failure: "Le remotion del persona del aspecto ha fallite." forbidden: "Tu non ha le permission de facer isto." invalid_statement: "Elemento duple rejectate." - no_membership: "Impossibile trovar le persona seligite in ille aspecto" - success: "Persona removite del aspecto con successo" + no_membership: "Le persona seligite non se trova in ille aspecto." + success: "Persona removite del aspecto con successo." aspects: add_to_aspect: failure: "Le addition del contacto al aspecto ha fallite." @@ -167,10 +187,10 @@ ia: add_an_aspect: "+ Adder un aspecto" aspect_stream: make_something: "Crea qualcosa" - stay_updated: "Tene te al currente" + stay_updated: "Mantene te al currente" stay_updated_explanation: "Le fluxo principal es plenate con tote le contactos tue, le etiquettas que tu seque, e messages de alcun membros creative del communitate." destroy: - failure: "%{name} non es vacue e non pote esser removite." + failure: "%{name} non pote esser removite." success: "%{name} ha essite removite con successo." success_auto_follow_back: "%{name} ha essite removite con successo. Tu ha usate iste aspecto pro automaticamente sequer le usatores que te seque. Verifica tu configuration de usator pro seliger un nove aspecto pro reciprocation automatic de sequimento." edit: @@ -196,7 +216,7 @@ ia: tag_feature: "functionalitate" tag_question: "question" tutorial_link_text: "Tutoriales" - tutorials_and_wiki: "%{faq}, %{tutorial} & %{wiki}: Adjuta pro le prime passos." + tutorials_and_wiki: "%{faq}, %{tutorial} & %{wiki}: adjuta pro le prime passos." introduce_yourself: "Iste fluxo es le tue. Non hesita… presenta te!" keep_pod_running: "Adjuta al mantenentia e melioration de %{pod} (e al caffeination de su gerentes) con un donation mensual!" new_here: @@ -223,10 +243,10 @@ ia: success: "Tu aspecto, %{name}, ha essite modificate con successo." blocks: create: - failure: "Io non poteva ignorar iste usator. #evasion" - success: "Ben, tu non plus videra iste usator in tu fluxo. #silentio!" + failure: "Un error ha impedite de ignorar iste usator. #evasion" + success: "In ordine, tu non plus videra iste usator in tu fluxo. #silentio!" destroy: - failure: "Io non poteva cessar de ignorar iste usator. #evasion" + failure: "Impossibile cessar de ignorar iste usator a causa de un error. #evasion" success: "Vamos vider lo que iste usator ha a dicer! #salutes" bookmarklet: explanation: "Invia cosas a diaspora* ab ubique con iste ligamine: %{link}" @@ -234,6 +254,8 @@ ia: post_something: "Inviar a diaspora*" cancel: "Cancellar" comments: + create: + error: "Commento fallite." new_comment: comment: "Commentar" commenting: "Commenta…" @@ -253,11 +275,11 @@ ia: user_search: "Recerca de usatores" spotlight: community_spotlight: "Usatores in evidentia" + no_members: "Il non ha ancora membros." suggest_member: "Suggerer un membro" conversations: create: fail: "Message non valide" - no_contact: "Tu debe adder le contacto primo." sent: "Message inviate" destroy: delete_success: "Le conversation ha essite delite" @@ -266,21 +288,22 @@ ia: conversations_inbox: "Conversationes – Cassa de entrata" inbox: "Cassa de entrata" new_conversation: "Nove conversation" - no_messages: "nulle message" + no_contacts: "Es necessari adder alcun contactos ante de poter initiar un conversation" + no_messages: "Nulle message" new: message: "Message" send: "Inviar" sending: "Invia…" - subject: "subjecto" + subject: "Subjecto" subject_default: "Sin subjecto" - to: "a" + to: "A" new_conversation: fail: "Message non valide" show: - delete: "deler e blocar conversation" + delete: "Deler conversation" hide: "celar e silentiar conversation" last_message: "Ultime message recipite %{timeago}" - reply: "responder" + reply: "Responder" replying: "Responde…" date: formats: @@ -290,6 +313,7 @@ ia: delete: "Deler" email: "E-mail" error_messages: + csrf_token_fail: "Le indicio CSRF non es valide. Per favor, aperi session e reproba." helper: correct_the_following_errors_and_try_again: "Corrige le sequente errores e proba de novo." need_javascript: "Iste sito web require JavaScript pro poter functionar. Si tu ha disactivate JavaScript, per favor reactiva lo e recarga iste pagina." @@ -297,13 +321,13 @@ ia: find_people: "Cercar personas o #etiquettas" help: account_and_data_management: - close_account_a: "Va al fin de tu pagina de configuration e clicca sur le button \"Clauder conto\"." + close_account_a: "Vade al fin de tu pagina de configuration e clicca sur le button \"Clauder conto\". Le systema te demandara de entrar tu contrasigno pro completar le processo. Non oblida que, si tu claude tu conto, tu nunquam potera re-inscriber tu nomine de usator in le mesme pod." close_account_q: "Como pote io deler mi conto?" - data_other_podmins_a: "Un vice que tu divide cosas con un persona in un altere pod, omne articulos que tu divide con illa e un copia del datos de tu profilo es immagazinate (in cache) in le pod de illa, e es accessibile al administrator del base de datos de iste pod. Quando tu dele un entrata o datos de profilo, illo es delite de tu pod e de omne altere pods ubi illo es immagazinate." + data_other_podmins_a: "Un vice que tu divide cosas con un persona in un altere pod, omne entratas que tu divide con illa e un copia del datos de tu profilo es immagazinate (in cache) in le pod de illa, e es accessibile al administrator del base de datos de iste pod. Quando tu dele un entrata o datos de profilo, illo es delite de tu pod e un requesta de deletion es inviate a omne altere pods ubi illo es immagazinate. Tu imagines nunquam es immagazinate in un altere pod que le tue; solmente ligamines a illos es transmittite a altere pods." data_other_podmins_q: "Esque le administratores de altere pods pote vider mi information?" - data_visible_to_podmin_a: "Le communication *inter* pods es sempre cryptate (con SSL e le cryptation de transporto proprie de diaspora*), ma le immagazinage de datos in pods non es cryptate. Le administrator del base de datos de tu pod (generalmente le persona qui gere le pod) pote acceder a tote le datos de tu profilo e tote lo que tu invia (isto es le caso pro le majoritate del sitos web que immagazina datos de usator). Gerer tu proprie pod fornirea un melior protection del vita private perque tu haberea le controlo super le accesso al base de datos." + data_visible_to_podmin_a: "In breve: toto. Le communication inter pods es sempre cryptate (con SSL e le cryptation de transporto proprie de diaspora*), ma le immagazinage de datos in pods non es cryptate. Si ille vole, le administrator del base de datos de tu pod (generalmente le persona qui gere le pod) poterea acceder a tote le datos de tu profilo e tote le entratas que tu invia (como es le caso pro le majoritate del sitos web que immagazina datos de usator). Es pro isto que tu ha le selection del pod in le qual crear tu conto, de maniera que tu pote seliger un pod gerite per un persona in que tu ha confidentia. Gerer tu proprie pod forni un melior protection del vita private perque tu controla alora le accesso al base de datos." data_visible_to_podmin_q: "Quante information mie pote le administrator de mi pod vider?" - download_data_a: "Si. Al fundo del scheda Conto in tu pagina de configuration il ha duo buttones pro discargar tu datos." + download_data_a: "Si. Al fundo del scheda Conto in tu pagina de configuration il ha duo buttones: un pro discargar tu datos e un pro discargar tu photos." download_data_q: "Pote io discargar un copia de tote le datos continite in mi conto?" move_pods_a: "In le futuro tu potera exportar tu conto de un pod e importar lo in un altere, ma pro le momento isto non es possibile. Tu pote sempre aperir un nove conto e adder tu contactos in aspectos in le nove conto, e demandar les de adder tu nove conto a lor aspectos." move_pods_q: "Como displaciar mi conto de un pod a un altere?" @@ -313,24 +337,24 @@ ia: change_aspect_of_post_q: "Un vice que io ha inviate qualcosa, pote io cambiar le aspecto(s) que pote vider le entrata?" contacts_know_aspect_a: "No. Ille non pote vider le nomine del aspecto in alcun maniera." contacts_know_aspect_q: "Esque mi contactos sapera in qual aspectos io les mitte?" - contacts_visible_a: "Si tu marca iste option, le contactos de ille aspecto potera vider le lista de altere personas includite in illo, a partir de tu pagina de profilo sub tu imagine. Es melior seliger iste option solmente si tote le contactos in iste aspecto se cognosce. Illes totevia non potera vider le nomine del aspecto." + contacts_visible_a: "Si tu marca iste option, le contactos de ille aspecto potera vider le lista de altere personas includite in illo, a partir del scheda \"Contactos\" in tu pagina de profilo. Es melior seliger iste option solmente si tote le personas in iste aspecto se cognosce, per exemplo si le aspecto es pro un club o societate de que tu es membro. Illes totevia non potera vider le nomine del aspecto." contacts_visible_q: "Que significa \"render le contactos in iste aspecto visibile le un al alteres\"?" - delete_aspect_a: "In tu lista de aspectos al latere sinistre del pagina, puncta le mouse verso le aspecto que tu vole deler. Clicca sur le micre stilo 'modificar' que appare al dextra. Clicca sur le button Deler in le quadro que appare." + delete_aspect_a: "Clicca sur \"Mi aspectos\" in le barra lateral a partir de un vista de fluxo e clicca sur le micre stilo de graphite presso le aspecto que tu vole deler, o vade a tu pagina Contactos e selige le aspecto in question. Postea clicca sur le icone de corbe a papiro in cyma al dextra del pagina." delete_aspect_q: "Como deler un aspecto?" - person_multiple_aspects_a: "Si. Vade a tu pagina de contactos e clicca sur Mi contactos. Pro cata contacto tu pote usar le menu al dextra pro adder la a omne aspectos que tu vole, o remover la de illos. O tu pote adder la a un nove aspecto (o remover la de un aspecto) per cliccar sur le button selector de aspectos in su pagina de profilo. O mesmo tu pote simplemente punctar le mouse verso su nomine quando tu lo vide in le fluxo, e un 'carta' de information apparera, in que tu pote cambiar le aspectos in que illa es." + person_multiple_aspects_a: "Si. Vade a tu pagina de contactos e clicca sur \"Mi contactos\". Pro cata contacto tu pote usar le menu al dextra pro adder la a omne aspectos que tu vole, o remover la de illos. O tu pote adder la a un nove aspecto (o remover la de un aspecto) per cliccar sur le button selector de aspectos in su pagina de profilo. O mesmo tu pote simplemente punctar le mouse verso su nomine quando tu lo vide in le fluxo, e un 'carta' de information apparera, in que tu pote cambiar le aspectos in que illa es." person_multiple_aspects_q: "Pote io adder un persona a plure aspectos?" - post_multiple_aspects_a: "Si. Quando tu scribe un entrata, usa le button selector de aspectos pro marcar o dismarcar aspectos. Le entrata essera visibile a tote le aspectos que tu marca. Tu pote anque seliger le aspectos al quales tu vole inviar lo in le barra lateral. Quando tu invia le entrata, le aspecto(s) que tu ha seligite in le lista al sinistra es memorate e essera seligite automaticamente quando tu comencia a facer un nove entrata." + post_multiple_aspects_a: "Si. Quando tu scribe un entrata, usa le button selector de aspectos pro marcar o dismarcar aspectos. \"Tote le aspectos\" es le option predefinite. Le entrata essera visibile a tote le aspectos que tu marca. Tu pote anque seliger le aspectos al quales tu vole inviar lo in le barra lateral. Quando tu invia le entrata, le aspecto(s) que tu ha seligite in le lista al sinistra es memorate e essera seligite automaticamente in le selector de aspectos quando tu comencia a facer un nove entrata." post_multiple_aspects_q: "Pote io inviar un entrata a plure aspectos insimul?" - remove_notification_a: "No." + remove_notification_a: "No. In ultra, illa non essera notificate si tu la adde a altere aspectos quando tu jam divide con illa." remove_notification_q: "Si io remove qualcuno de un aspecto, o de tote mi aspectos, esque ille recipera notification de isto?" - rename_aspect_a: "Si. In tu lista de aspectos al latere sinistre del pagina principal, puncta le mouse verso le aspecto que tu vole renominar. Clicca sur le micre stilo de graphite (con subtitulo 'modificar') que appare al dextra. Clicca sur 'renominar' in le quadro que appare." - rename_aspect_q: "Pote io renominar un aspecto?" + rename_aspect_a: "Clicca sur \"Mi aspectos\" in le barra lateral a partir de un vista de fluxo e clicca sur le micre stilo de graphite presso le aspecto que tu vole renominar, o vade a tu pagina Contactos e selige le aspecto in question. Postea clicca sur le icone de modification al latere del nomine del aspecto in cyma de iste pagina, cambia le nomine e clicca sur \"Actualisar\"." + rename_aspect_q: "Como renomina io un aspecto?" restrict_posts_i_see_a: "Si. Clicca sur \"Mi aspectos\" in le barra lateral e postea clicca sur individual aspectos in le lista pro marcar o dismarcar los. Solmente le entratas scribite per personas in le aspectos marcate apparera in tu fluxo." - restrict_posts_i_see_q: "Pote io limitar le entratas que io vide de sorta que solmente illos de certe aspectos es monstrate?" + restrict_posts_i_see_q: "Pote io limitar le entratas in mi fluxo solmente illos de certe aspectos?" title: "Aspectos" what_is_an_aspect_a: "Aspectos es le maniera de gruppar tu contactos in diaspora*. Cata aspecto es un del facies que tu monstra al mundo. Un aspecto poterea representar te a tu collegas, o a tu familia, o a tu amicos in un club de que tu es membro." what_is_an_aspect_q: "Que es un aspecto?" - who_sees_post_a: "Si tu scribe un entrata limitate, illo essera visibile solmente al personas que tu ha mittite in ille aspecto (o in ille aspectos, si tu lo ha inviate a plure aspectos). Tu contactos que non es in le aspecto non potera vider le entrata si tu non lo ha rendite public. Solmente le entratas public es visibile a personas que tu non ha includite in un de tu aspectos." + who_sees_post_a: "Si tu scribe un entrata limitate, illo essera visibile solmente pro le personas que tu ha mittite in ille aspecto (o in ille aspectos, si tu lo ha inviate a plure aspectos) ante de publicar le entrata. Tu contactos que non es in le aspecto non potera vider le entrata. Entratas limitate nunquam essera visibile pro alcun persona que tu non ha mittite in un de tu aspectos." who_sees_post_q: "Quando io invia qualcosa a un aspecto, qui lo videra?" chat: add_contact_roster_a: "Primo tu debe activar le chat pro un del aspectos in le quales iste persona es presente. Pro facer isto, va al %{contacts_page}, selige le aspecto que tu vole e clicca sur le icone de chat pro activar le chat pro ille aspecto. %{toggle_privilege} Alternativemente, tu pote crear un aspecto special nominate 'Chat' e adder a ille aspecto le personas con qui tu vole chattar. Un vice que tu ha facite isto, aperi le interfacie de chat e selige le persona con qui tu vole chattar." @@ -338,19 +362,19 @@ ia: contacts_page: "pagina de contactos" title: "Chat" faq: "FAQ" - foundation_website: "le sito web del fundation diaspora" + foundation_website: "le sito web del fundation diaspora*" getting_help: get_support_a_faq: "Lege nostre pagina de %{faq} sur le wiki" - get_support_a_hashtag: "pone le question in un entrata public de diaspora* adjungente le etiquetta %{question}" - get_support_a_irc: "veni a nos in %{irc} (conversation in directo)" - get_support_a_tutorials: "lege nostre %{tutorials}" - get_support_a_website: "visita nostre %{link}" - get_support_a_wiki: "cerca in le %{link}" + get_support_a_hashtag: "Pone le question in un entrata public de diaspora* adjungente le etiquetta %{question}" + get_support_a_irc: "Visita nos in %{irc} (conversation in directo)" + get_support_a_tutorials: "Lege nostre %{tutorials}" + get_support_a_website: "Visita nostre %{link}" + get_support_a_wiki: "Cerca in le %{link}" get_support_q: "E si le FAQ non ha un responsa a mi question, ubi pote io trovar adjuta?" getting_started_a: "Fortunatemente, le %{tutorial_series} in nostre sito es a tu disposition. Illo te guidara passo post passo per le processo de inscription e te inseniara le aspectos fundamental de usar diaspora*." getting_started_q: "Succurso! Io ha besonio de adjuta pro comenciar!" title: "Obtener adjuta" - getting_started_tutorial: "Serie de tutoriales 'Prime passos'" + getting_started_tutorial: "Serie de tutoriales \"Prime passos\"" here: "hic" irc: "IRC" keyboard_shortcuts: @@ -367,11 +391,11 @@ ia: title: "Claves accelerator" markdown: "Markdown" mentions: - how_to_mention_a: "Dactylographa le signo \"@\" e comencia a dactylographar su nomine. Un menu disrolante deberea apparer que permitte seliger le nomine plus facilemente. Nota ben que il es solmente possibile mentionar personas que tu ha addite a un aspecto." + how_to_mention_a: "Scribe le signo \"@\" e comencia a scriber su nomine. Un menu disrolante deberea apparer que permitte seliger le nomine plus facilemente. Nota ben que il es solmente possibile mentionar personas que tu ha addite a un aspecto." how_to_mention_q: "Como mentionar un persona quando io scribe un entrata?" mention_in_comment_a: "No, actualmente non." mention_in_comment_q: "Pote io mentionar qualcuno in un commento?" - see_mentions_a: "Si, clicca sur \"Mentiones\" in le columna sinistre in tu pagina principal." + see_mentions_a: "Si, clicca sur \"@Mentiones\" in le columna sinistre in tu pagina principal." see_mentions_q: "Existe un maniera de vider le entratas in que on me ha mentionate?" title: "Mentiones" what_is_a_mention_a: "Un mention es un ligamine al pagina de profilo de un persona que appare in un entrata. Quando un persona es mentionate, illa recipe un notification que dirige su attention verso le entrata." @@ -507,7 +531,7 @@ ia: title: "Etiquettas" what_are_tags_for_a: "Etiquettas servi a categorisar un entrata, normalmente per topico. Si tu cerca un etiquetta, es monstrate tote le entratas visibile pro te (public e private) con iste etiquetta. Isto permitte al personas interessate in un certe topico cercar le entratas public concernente lo." what_are_tags_for_q: "A que servi etiquettas?" - third_party_tools: "instrumentos de tertie personas" + third_party_tools: "Instrumentos de tertios" title_header: "Adjuta" tutorial: "tutorial" tutorials: "tutoriales" @@ -523,18 +547,34 @@ ia: own_your_data: "Possede tu proprie datos" own_your_data_info: "Multe retes usa tu datos pro ganiar moneta analysante tu interactiones e usante iste information pro diriger publicitate a te. diaspora* non usa tu datos pro alcun scopo, salvo illo de permitter te de connecter e divider cosas con altere personas." podmin: + byline: "Tu es sur le puncto de cambiar le facie de Internet. Preste a comenciar?" + configuration_info: "Aperi %{database_path} e %{diaspora_path} in tu editor de texto preferite e revide los meticulosemente; illos ha commentos extense." + configure_your_pod: "Configurar tu pod" + contact_irc: "contacta nos sur IRC" + contribute: "Contribuer" + contribute_info: "Adjuta a meliorar diaspora*! Si tu trova errores, per favor %{report_bugs}." + create_an_account: "Crear un conto" + create_an_account_info: "%{sign_up_link} pro un nove conto." + faq_for_podmins: "FAQ pro gestores de pod in nostre wiki" + getting_help: "Obtener adjuta" + getting_help_info: "Nos ha enumerate alcun %{faq} con avisos e consilios extra e solutiones de problemas commun. Alternativemente, %{irc}." headline: "Benvenite, amico." + make_yourself_an_admin: "Facer te administrator" + make_yourself_an_admin_info: "Instructiones se trova in le %{wiki}. Iste function insere un ligamine “%{admin_dashboard}” in tu menu personal in cyma del pagina durante que tu es in session aperte. Illo permitte cercar usatores e forni statisticas pro tu pod, inter altere cosas." + report_bugs: "reporta los" + update_instructions: "instructiones pro le actualisation in le wiki de diaspora*" + update_your_pod: "Actualisar tu pod" + update_your_pod_info: "Tu pote trovar %{update_instructions}." invitation_codes: + already_logged_in: "%{inviter} te ha invitate a unir te a iste pod, ma tu ha jam aperite session." not_valid: "Iste codice de invitation non plus es valide" invitations: - a_facebook_user: "Un usator de Facebook" - check_token: - not_found: "Indicio de invitation non trovate" create: + closed: "Le invitationes es claudite sur iste pod de diaspora*." empty: "Per favor, specifica al minus un adresse de e-mail." no_more: "Tu non ha altere invitationes." note_already_sent: "Invitationes ha jam essite inviate a: %{emails}" - rejected: "Le sequente adresses de e-mail habeva problemas: " + rejected: "Le sequente adresses de e-mail habeva problemas: %{emails}" sent: "Le sequente adresses ha recipite un invitation: %{emails}" new: comma_separated_plz: "Tu pote entrar plure adresses de e-mail separante los per commas." @@ -546,26 +586,30 @@ ia: layouts: application: back_to_top: "Retornar al cyma" + be_excellent: "Sia benevolente le un verso le altere! ♥" powered_by: "Actionate per diaspora*" public_feed: "Fluxo public de diaspora* pro %{name}" - source_package: "discargar le pacchetto con le codice-fonte" + source_package: "Discargar le pacchetto con le codice-fonte" statistics_link: "Statisticas del pod" - toggle: "(dis)activar mobile" - whats_new: "que es nove?" + toggle: "(Dis)activar mobile" + whats_new: "Que es nove?" header: - code: "codice" + code: "Codice" logout: "Clauder session" profile: "Profilo" settings: "Configuration" toggle_navigation: "Alternar navigation" + likes: + create: + error: "Appreciation fallite." limited: "Limitate" more: "Plus" no_results: "Nulle resultato trovate" notifications: also_commented: - one: "%{actors} anque commentava le entrata de %{post_author}, %{post_link}." - other: "%{actors} anque commentava le entrata de %{post_author}, %{post_link}." - zero: "%{actors} anque commentava le entrata de %{post_author}, %{post_link}." + one: "%{actors} etiam commentava le entrata %{post_link} de %{post_author}." + other: "%{actors} etiam commentava le entrata %{post_link} de %{post_author}." + zero: "Nemo altere commentava le entrata %{post_link} de %{post_author}." comment_on_post: one: "%{actors} commentava tu entrata %{post_link}." other: "%{actors} commentava tu entrata %{post_link}." @@ -581,6 +625,7 @@ ia: mark_read: "Marcar como legite" mark_unread: "Marcar como non legite" mentioned: "Mentionate" + mentioned_in_comment: "Mentionate in commento" no_notifications: "Tu non ha ancora notificationes." notifications: "Notificationes" reshared: "Repetite" @@ -595,6 +640,15 @@ ia: one: "%{actors} te ha mentionate in le entrata %{post_link}." other: "%{actors} te ha mentionate in le entrata %{post_link}." zero: "%{actors} te ha mentionate in le entrata %{post_link}." + mentioned_deleted: + one: "%{actors} te ha mentionate in un entrata delite." + other: "%{actors} te ha mentionate in un entrata delite." + mentioned_in_comment: + one: "%{actors} te ha mentionate in un commento sur le entrata %{post_link}." + other: "%{actors} te ha mentionate in un commento sur le entrata %{post_link}." + mentioned_in_comment_deleted: + one: "%{actors} te ha mentionate in un commento delite." + other: "%{actors} te ha mentionate in un commento delite." post: "entrata" private_message: one: "%{actors} te ha inviate un message." @@ -614,13 +668,36 @@ ia: a_private_message: "Il ha un nove message private pro te in diaspora*." also_commented: limited_subject: "Il ha un nove commento sur un entrata que tu ha commentate" - click_here: "clicca hic" + click_here: "Clicca hic" comment_on_post: limited_subject: "Il ha un nove commento sur un de tu entratas" - reply: "Responde o lege le message de %{name} >" + reply: "Responder o leger le message de %{name} >" confirm_email: click_link: "Pro activar tu nove adresse de e-mail %{unconfirmed_email}, seque iste ligamine:" subject: "Per favor activa tu nove adresse de e-mail %{unconfirmed_email}" + csrf_token_fail: + body: |- + Salute %{name}, + + diaspora* ha detegite un tentativa de acceder a tu session le qual pote esser non autorisate. Pro evitar omne possibilitate que tu datos sia compromittite, nos ha claudite tu session. Non te preoccupa; es secur reaperir session ora. + + Un requesta ha essite inviate con un indicio CSRF incorrecte o mancante. Isto poterea esser totalmente innocente, o poterea esser un attacco de requesta falsificate trans sitos (CSRF). + + Le causa poterea esser: + + - Un add-on manipulante le requesta o effectuante requestas sin indicio; + - Un scheda lassate aperte de un session passate; + - Un altere sito web faciente requestas, con o sin tu permission; + - Varie altere instrumentos externe; + - Codice malitiose tentante acceder a tu datos. + + Pro plus information sur CSRF, vide [%{link}](%{link}). + + Si tu vide iste message plure vices, per favor verifica le punctos precedente, incluse omne add-ons o extensiones del navigator. + + Gratias, + Le robot messagero de disapora*! + subject: "Nos ha recipite un requesta non autorisate de tu conto, %{name}" email_sent_by_diaspora: "Iste message ha essite inviate per %{pod_name}. Si tu non vole reciper altere e-mail como iste," export_email: body: |- @@ -667,20 +744,25 @@ ia: hello: "Salute %{name}!" invite: message: |- - Hallo, + Salute! - Tu ha essite invitate a unir te a diaspora*! + %{diaspora_id} te ha invitate a unir te a diaspora*! Clicca sur iste ligamine pro comenciar: [%{invite_url}][1] + O, si tu ha jam un conto, tu pote adder %{diaspora_id} a tu contactos. + Cordialmente, - Le messagero robotic de diaspora* + Le robot messagero de diaspora* + + P.S.: Si tu non sape (ancora) lo que es diaspora*, le responsa es [hic][2]! [1]: %{invite_url} + [2]: %{diasporafoundation_url} invited_you: "%{name} te ha invitate a diaspora*" liked: liked: "%{name} apprecia tu entrata" @@ -689,6 +771,9 @@ ia: mentioned: limited_post: "Tu ha essite mentionate in un entrata limitate." subject: "%{name} te ha mentionate in diaspora*" + mentioned_in_comment: + limited_post: "Tu ha essite mentionate in un commento sur un entrata limitate." + reply: "Responder o leger iste conversation >" private_message: reply_to_or_view: "Responde o lege iste conversation >" subject: "Il ha un nove message private pro te" @@ -744,7 +829,7 @@ ia: ok: "OK" people: add_contact: - invited_by: "tu ha essite inviate per" + invited_by: "Tu ha essite invitate per" index: couldnt_find_them: "Non trovate?" looking_for: "Cercar entratas con le etiquetta %{tag_link}?" @@ -752,7 +837,7 @@ ia: no_results: "Pro cercar, primo scribe alcun parolas." results_for: "Usatores correspondente a %{search_term}" search_handle: "Usa lor ID de diaspora* (p.ex. nominedeusator@pod.tld) pro cercar tu amicos." - searching: "recerca in curso, un momento per favor..." + searching: "Recerca in curso, un momento per favor..." send_invite: "Ancora nihil? Invia un invitation!" person: thats_you: "Es tu!" @@ -772,14 +857,13 @@ ia: type_error: "Le incargamento del photo ha fallite. Es tu secur que un imagine ha essite addite?" destroy: notice: "Photo delite." - new_photo: - empty: "{file} es vacue. Per favor re-selige le files sin iste." - invalid_ext: "{file} ha un extension inadmissibile. Solmente {extensions} es permittite." - size_error: "{file} es troppo grande. Le dimension maxime es {sizeLimit}." new_profile_photo: upload: "Incargar un nove photo de profilo!" - show: - show_original_post: "Monstrar entrata original" + polls: + votes: + one: "%{count} voto usque ora" + other: "%{count} votos usque ora" + zero: "%{count} votos usque ora" posts: presenter: title: "Un entrata de %{name}" @@ -813,29 +897,33 @@ ia: your_name: "Tu nomine" your_photo: "Tu photo" your_tags: "Describe te in 5 parolas" - your_tags_placeholder: "p.ex. #films #cattones #viages #docente #interlingua" + your_tags_placeholder: "P.ex. #films #cattones #viages #docente #interlingua" update: failed: "Le actualisation del profilo ha fallite" updated: "Profilo actualisate" public: "Public" + reactions: + one: "1 reaction" + other: "%{count} reactiones" + zero: "Nulle reaction" registrations: closed: "Le creation de contos es claudite in iste pod de diaspora*." create: success: "Tu ha adherite a diaspora*!" invalid_invite: "Le ligamine de invitation que tu ha fornite non plus es valide." new: - email: "E-MAIL" - enter_email: "Specifica adresse de e-mail" + email: "E-mail" + enter_email: "Scribe tu adresse de e-mail" enter_password: "Elige un contrasigno (de sex characteres al minimo)" enter_password_again: "Repete le contrasigno" enter_username: "Elige un nomine de usator (usa solmente litteras, numeros e tractos de sublineamento)" - password: "CONTRASIGNO" - password_confirmation: "CONFIRMA CONTRASIGNO" - sign_up: "CREAR CONTO" + password: "Contrasigno" + password_confirmation: "Confirma contrasigno" + sign_up: "Crear conto" submitting: "Submitte…" terms: "Per crear un conto tu accepta le %{terms_link}." terms_link: "conditiones de servicio" - username: "NOMINE DE USATOR" + username: "Nomine de usator" report: comment_label: "Commento:
%{data}" confirm_deletion: "Es tu secur de voler deler le elemento?" @@ -850,12 +938,18 @@ ia: destroyed: "Le entrata ha essite destruite" failed: "Qualcosa ha errate" title: "Summario de reportos" + unreviewed_reports: + one: "Il ha un reporto non revidite." + other: "Il ha %{count} reportos non revidite." + zero: "Il non ha reportos non revidite." reshares: comment_email_subject: "Repetition de %{resharer} del entrata de %{author}" + create: + error: "Repetition fallite." reshare: deleted: "Le entrata original ha essite delite per le autor." - reshare_confirmation: "Repeter iste entrata de %{author}?" - reshared_via: "repetite via" + reshare_confirmation: "Repeter le entrata de %{author}?" + reshared_via: "Repetite via" search: "Cercar" services: create: @@ -866,16 +960,17 @@ ia: destroy: success: "Authentication delite con successo." failure: - error: "un error occurreva durante le connexion a iste servicio" + error: "Un error occurreva durante le connexion a iste servicio" index: connect: "Connecter" - disconnect: "disconnecter" + disconnect: "Disconnecter" edit_services: "Modificar servicios" - logged_in_as: "identificate como" + logged_in_as: "In session como %{nickname}." no_services_available: "Il non ha servicios disponibile in iste pod." not_logged_in: "Nulle session aperte in iste momento." - really_disconnect: "disconnecter %{service}?" - services_explanation: "Le connexion a servicios da le possibilitate de publicar tu messages anque in illos si tu los scribe in diaspora*." + really_disconnect: "Disconnecter %{service}?" + services_explanation: "Le connexion a altere servicios da le possibilitate de publicar tu messages anque in illos quando tu los scribe in diaspora*." + share_to: "Divider sur %{provider}" title: "Gerer servicios connectite" provider: facebook: "Facebook" @@ -887,15 +982,18 @@ ia: aspect_dropdown: mobile_row_checked: "%{name} (remover)" mobile_row_unchecked: "%{name} (adder)" + toggle: + one: "In %{count} aspecto" + other: "In %{count} aspectos" invitations: - by_email: "Per e-mail" + by_email: "Invitar personas per e-mail" invite_your_friends: "Invitar tu amicos" invites: "Invitationes" share_this: "Divide iste ligamine per e-mail, blog o rete social!" public_explain: atom_feed: "Syndication Atom" control_your_audience: "Controlar tu audientia" - logged_in: "identificate in %{service}" + logged_in: "Session aperite in %{service}" manage: "Gerer servicios connectite" new_user_welcome_message: "Usa #etiquettas pro classificar tu messages e trovar personas con interesses in commun. Commenda personas extraordinari con @Mentiones." outside: "Le messages public essera visibile pro altere personas foras de diaspora*." @@ -919,8 +1017,8 @@ ia: upload_photos: "Incargar photos" whats_on_your_mind: "De que pensa tu?" stream_element: - via: "via %{link}" - via_mobile: "via mobile" + via: "Via %{link}" + via_mobile: "Per mobile" simple_captcha: label: "Scribe le codice in le quadro:" message: @@ -967,7 +1065,7 @@ ia: title: "#Etiquettas sequite" followed_tags_stream: "#Etiquettas sequite" like_stream: - title: "Fluxo de appreciationes" + title: "Fluxo de entratas appreciate" mentioned_stream: "@Mentiones" mentions: title: "@Mentiones" @@ -1002,7 +1100,7 @@ ia: wrong_password: "Le contrasigno entrate non corresponde a tu contrasigno actual." edit: also_commented: "un persona commenta un entrata que tu ha commentate" - auto_follow_aspect: "Aspecto pro contactos automaticamente addite:" + auto_follow_aspect: "Aspecto pro usatores con que tu divide automaticamente:" auto_follow_back: "Divider automaticamente con omne persona qui comencia a divider con te" change: "Cambiar" change_color_theme: "Cambiar thema de colores" @@ -1012,16 +1110,17 @@ ia: character_minimum_expl: "al minus 6 characteres" close_account: dont_go: "Per favor, non parti!" - lock_username: "Isto reserva tu nomine de usator in caso que tu decide de re-crear tu conto." - locked_out: "Tu session essera claudite e tu essera excludite de tu conto." - make_diaspora_better: "Nos ha besonio de adjuta pro meliorar diaspora*, dunque, per favor contribue in loco de quitar. Si tu vermente vole quitar, nos vole informar te de lo que evenira." + lock_username: "Tu nomine de usator essera blocate. Tu non potera crear un nove conto sur iste pod con le mesme ID." + locked_out: "Le session essera claudite e tu essera excludite del conto usque illo habera essite delite." + make_diaspora_better: "Nos amarea si tu remane e adjuta nos a meliorar diaspora* in vice de quitar. Nonobstante, si tu vermente vole quitar, ecce lo que evenira:" mr_wiggles: "Sr. Wiggles essera triste de vider te partir" - no_turning_back: "Tu ha arrivate al puncto de non retorno." + no_turning_back: "Tu ha arrivate al puncto de non retorno! Si tu es vermente secur, scribe hic infra tu contrasigno." what_we_delete: "Nos va deler, le plus tosto possibile, tote le entratas e datos de profilo pertinente a te. Tu commentos sur le entratas de altere personas remanera, ma essera associate con tu ID de diaspora* in loco de tu nomine." close_account_text: "Clauder conto" comment_on_post: "un persona commenta un entrata tue" current_password: "Contrasigno actual" current_password_expl: "illo con que tu aperi session..." + default_post_visibility: "Aspectos pre-seligite pro publicar entratas" download_export: "Discargar mi profilo" download_export_photos: "Discargar mi photos" edit_account: "Modificar conto" @@ -1033,6 +1132,7 @@ ia: last_exported_at: "(Ultime actualisation: %{timestamp})" liked: "un persona apprecia un entrata tue" mentioned: "un persona te mentiona in un entrata sue" + mentioned_in_comment: "tu es mentionate in un commento" new_password: "Contrasigno nove" private_message: "tu recipe un message private" receive_email_notifications: "Reciper notificationes per e-mail quando:" @@ -1053,7 +1153,7 @@ ia: awesome_take_me_to_diaspora: "Superbe! Conduce me a diaspora*" community_welcome: "Le communitate de diaspora* es felice de accolliger te!" connect_to_facebook: "Nos pote accelerar le cosas un poco per %{link} a diaspora*. Isto insere automaticamente tu nomine e photo, e permitte inviar entratas a ambe sitos." - connect_to_facebook_link: "connecter tu conto de Facebook" + connect_to_facebook_link: "Connecter tu conto de Facebook" hashtag_explanation: "Le #etiquettas permitte discuter e sequer tu interesses. Illos anque es un bon maniera de trovar nove personas in diaspora*." hashtag_suggestions: "Tenta sequer etiquettas como #arte, #films, #gif, etc." well_hello_there: "Salutationes a te!" @@ -1062,7 +1162,7 @@ ia: privacy_settings: ignored_users: "Usatores ignorate" no_user_ignored_message: "Tu non ignora usatores in iste momento." - stop_ignoring: "Cessar de ignorar" + stop_ignoring: "Non plus ignorar" strip_exif: "Remover le metadatos, p.ex. localitate, autor, modello de camera, de imagines incargate (recommendate)" title: "Configuration de confidentialitate" public: diff --git a/config/locales/diaspora/id.yml b/config/locales/diaspora/id.yml index 983e1daa1..3450de145 100644 --- a/config/locales/diaspora/id.yml +++ b/config/locales/diaspora/id.yml @@ -153,9 +153,6 @@ id: invitation_codes: not_valid: "Kode undangan sudah tidak valid." invitations: - a_facebook_user: "Seorang pengguna Facebook" - check_token: - not_found: "Token undangan tidak ditemukan" create: no_more: "Anda tidak dapat memberikan undangan lagi." rejected: "Alamat email berikut bermasalah dengan: " @@ -323,12 +320,6 @@ id: type_error: "Pengunggahan foto gagal. Kamu yakin sudah menambahkan gambar?" destroy: notice: "Foto dihapus." - new_photo: - empty: "{file} kosong, mohon pilih berkas lagi tanpanya." - invalid_ext: "ekstensi {file} tak valid. Hanya {extensions} yang diperbolehkan." - size_error: "{file} terlalu besar, ukuran maksimal berkas adalah {sizeLimit}" - show: - show_original_post: "Perlihatkan kiriman asli" posts: show: forbidden: "Kamu tidak boleh melakukannya" diff --git a/config/locales/diaspora/is.yml b/config/locales/diaspora/is.yml index 1944f1a7d..2fba0ed09 100644 --- a/config/locales/diaspora/is.yml +++ b/config/locales/diaspora/is.yml @@ -189,7 +189,6 @@ is: private_profiles: whats_in_profile_a: "Ferilskráin, staðsetning, kyn og fæðingardagur. Þetta eru allt hlutir sem eru neðst á Síðunni Þinni. Þú ræður hvort þú setur upplýsingar þar inn. Eingöngu einstaklingar sem þú hefur bætt í eina af þínum sýnum, og eru skráðir inn, geta séð þessar upplýsingar. Þegar þeir fara á síðuna þína geta þeir séð þau skeyti sem þú hefur deilt með öllum, sem og þau skeyti sem þú hefur valið að deila með sýnum sem þeir eru í." invitations: - a_facebook_user: "Facebook-notandi" create: no_more: "Ekki eru til fleiri boðsmiðar." rejected: "Eftirfarandi netföng ollu vandræðum: " @@ -360,14 +359,8 @@ is: type_error: "Innsending á mynd mistókst. Ertu viss um að mynd hafi verið bætt við?" destroy: notice: "Mynd var eytt." - new_photo: - empty: "{file} skráin er tóm, veldu skrárnar aftur en slepptu þessari skrá." - invalid_ext: "{file} er með ógilda skráarendingu. Aðeins {extensions} eru leyfðar." - size_error: "{file} skráin er of stór, hámarksstærð er {sizeLimit}." new_profile_photo: upload: "Senda inn nýja forsíðumynd!" - show: - show_original_post: "Birta upprunalega færslu" posts: show: photos_by: diff --git a/config/locales/diaspora/it.yml b/config/locales/diaspora/it.yml index afe098311..dd8c14359 100644 --- a/config/locales/diaspora/it.yml +++ b/config/locales/diaspora/it.yml @@ -197,7 +197,6 @@ it: conversations: create: fail: "Messaggio non valido" - no_contact: "Hey, devi prima aggiungere un contatto!" sent: "Messaggio inviato" index: inbox: "In arrivo" @@ -412,9 +411,6 @@ it: tutorials: "Guide" wiki: "wiki" invitations: - a_facebook_user: "Un utente Facebook" - check_token: - not_found: "Token di invito non trovato" create: empty: "Perfavore inserire almeno un indirizzo email." no_more: "Non hai più inviti a disposizione" @@ -607,14 +603,8 @@ it: type_error: "Il caricamento della foto non è riuscito. Sei sicuro che fosse un'immagine?" destroy: notice: "Foto eliminata." - new_photo: - empty: "{file} è vuoto, per favore seleziona di nuovo i file senza includerlo." - invalid_ext: "{file} ha un'estensione non valida. Sono permesse soltanto {extensions}." - size_error: "{file} è troppo grande, la dimensione massima è {sizeLimit}." new_profile_photo: upload: "Carica una nuova foto nel profilo!" - show: - show_original_post: "Mostra il post originale" posts: presenter: title: "Un post di %{name}" diff --git a/config/locales/diaspora/ja.yml b/config/locales/diaspora/ja.yml index c5d689077..83dcb3aaf 100644 --- a/config/locales/diaspora/ja.yml +++ b/config/locales/diaspora/ja.yml @@ -267,6 +267,8 @@ ja: post_something: "ダイアスポラに投稿" cancel: "取消" comments: + create: + error: "コメントに失敗しました。" new_comment: comment: "コメント" commenting: "コメント投稿中…" @@ -291,7 +293,6 @@ ja: conversations: create: fail: "無効なメッセージです。" - no_contact: "最初に連絡先を追加する必要があります!" sent: "メッセージを送信しました" destroy: delete_success: "会話を正常に削除しました" @@ -300,6 +301,7 @@ ja: conversations_inbox: "会話 – 受信トレイ" inbox: "受信トレイ" new_conversation: "新しい会話" + no_contacts: "会話を開始する前に、連絡先を追加する必要があります" no_messages: "メッセージがありません" new: message: "メッセージ" @@ -324,6 +326,7 @@ ja: delete: "削除" email: "メール" error_messages: + csrf_token_fail: "CSRFトークンが無効です。 サインインしてもう一度やり直してください。" helper: correct_the_following_errors_and_try_again: "次の問題を解決してからやり直してください。" need_javascript: "このウェブサイトは正常に機能するためにJavaScriptが必要です。 JavaScriptを無効にした場合は、有効にしてこのページを更新してください。" @@ -557,7 +560,6 @@ ja: own_your_data: "あなた自身のデータを所有する" own_your_data_info: "多くのネットワークはあなたのデータを使用して、あなたのやり取りを分析することでお金を稼ぎます。そして、この情報を使用して、物を宣伝します。ダイアスポラ*は、あなたが他のユーザーと接続して、シェアすることを可能にする以外の目的のために、あなたのデータを使用しません。" podmin: - admin_panel: "管理者用パネル" byline: "インターネットを変更しようとしています。セットアップを始めますか?" configuration_info: "お好みのテキストエディタで %{database_path} と %{diaspora_path} を開いて、慎重にレビューしてください。広範囲にコメントしています。" configure_your_pod: "あなたのポッドを設定" @@ -577,12 +579,11 @@ ja: update_your_pod: "ポッドを更新" update_your_pod_info: "%{update_instructions}を見つけることができます。" invitation_codes: + already_logged_in: "あなたは%{inviter}によってこのポッドに参加するように招待されましたが、すでにログインしています。" not_valid: "その招待コードは、もはや有効ではありません" invitations: - a_facebook_user: "Facebookユーザー" - check_token: - not_found: "招待トークンが見つかりません。" create: + closed: "このダイアスポラ* ポッドへの招待を締め切らせて頂いています。" empty: "少なくとも1つのEメールアドレスを入力してください。" no_more: "招待権がもう残っていません。" note_already_sent: "招待状はすでにに送信しました: %{emails}" @@ -614,41 +615,28 @@ ja: profile: "プロフィール" settings: "設定" toggle_navigation: "ナビゲーションの切り替え" + likes: + create: + error: "いいね!に失敗しました。" limited: "限定公開" more: "続き" no_results: "結果が見つかりません" notifications: also_commented: - few: "%{actors} also commented on %{post_author}'s %{post_link}." - many: "%{actors} also commented on %{post_author}'s %{post_link}." - one: "%{actors} also commented on %{post_author}'s %{post_link}." other: "%{actors}さんは%{post_author}さんの投稿%{post_link}もコメントしました。" - two: "%{actors} also commented on %{post_author}'s %{post_link}." zero: "%{actors}さんは%{post_author}さんの投稿%{post_link}もコメントしました。" also_commented_deleted: - few: "%{actors} commented on a deleted post." - many: "%{actors} commented on a deleted post." - one: "%{actors} commented on a deleted post." other: "%{actors}さんが削除された投稿にコメントしました。" - two: "%{actors} commented on a deleted post." zero: "%{actors}さんが削除された投稿にコメントしました。" comment_on_post: - few: "%{actors} commented on your %{post_link}." - many: "%{actors} commented on your %{post_link}." - one: "%{actors} commented on your %{post_link}." other: "%{actors}さんが投稿%{post_link}にコメントしました。" - two: "%{actors} commented on your %{post_link}." zero: "%{actors}さんが投稿%{post_link}にコメントしました。" index: all_notifications: "すべての通知" also_commented: "コメントも" and: "および" and_others: - few: "and %{count} others" - many: "and %{count} others" - one: "and one more" other: "そして他に %{count} 人" - two: "and %{count} others" zero: "そして他にはいません" comment_on_post: "投稿にコメント" liked: "いいね!しました" @@ -657,6 +645,7 @@ ja: mark_read: "既読にする" mark_unread: "未読にする" mentioned: "メンションされました" + mentioned_in_comment: "コメントでメンションしました" no_notifications: "まだ通知は何もありません" notifications: "通知" reshared: "リシェアしました" @@ -664,61 +653,33 @@ ja: show_unread: "未開封メッセージを表示" started_sharing: "シェアを開始しました" liked: - few: "%{actors} has just liked your %{post_link}." - many: "%{actors} has just liked your %{post_link}." - one: "%{actors} has just liked your %{post_link}." other: "%{actors}さんが投稿%{post_link}にいいね!しました。" - two: "%{actors} has just liked your %{post_link}." zero: "%{actors}さんが投稿%{post_link}にいいね!しました。" liked_post_deleted: - few: "%{actors} liked your deleted post." - many: "%{actors} liked your deleted post." - one: "%{actors} liked your deleted post." other: "%{actors}さんが削除された投稿にいいね!しました。" - two: "%{actors} liked your deleted post." zero: "%{actors}さんが削除された投稿にいいね!しました。" mentioned: - few: "%{actors} has mentioned you in a %{post_link}." - many: "%{actors} has mentioned you in a %{post_link}." - one: "%{actors} has mentioned you in a %{post_link}." other: "%{actors}さんが%{post_link}であなたにメンションしました。" - two: "%{actors} has mentioned you in a %{post_link}." zero: "%{actors}さんが%{post_link}であなたにメンションしました。" mentioned_deleted: - few: "%{actors} mentioned you in a deleted post." - many: "%{actors} mentioned you in a deleted post." - one: "%{actors} mentioned you in a deleted post." other: "%{actors}さんが削除された投稿であなたにメンションしました。" - two: "%{actors} mentioned you in a deleted post." zero: "%{actors}さんが削除された投稿であなたにメンションしました。" + mentioned_in_comment: + other: "%{actors} が、投稿 %{post_link} に コメント でメンションしました。" + mentioned_in_comment_deleted: + other: "%{actors} が、削除したコメントでメンションしました。" post: "(投稿で)" private_message: - few: "%{actors} sent you a message." - many: "%{actors} sent you a message." - one: "%{actors} sent you a message." other: "%{actors}さんが、あなたにメッセージを送信しました。" - two: "%{actors} sent you a message." zero: "%{actors}さんが、あなたにメッセージを送信しました。" reshared: - few: "%{actors} has reshared your %{post_link}." - many: "%{actors} has reshared your %{post_link}." - one: "%{actors} has reshared your %{post_link}." other: "%{actors}さんが投稿%{post_link}をリシェアしました。" - two: "%{actors} has reshared your %{post_link}." zero: "%{actors}さんが投稿%{post_link}をリシェアしました。" reshared_post_deleted: - few: "%{actors} reshared your deleted post." - many: "%{actors} reshared your deleted post." - one: "%{actors} reshared your deleted post." other: "%{actors}さんが削除された投稿をリシェアしました。" - two: "%{actors} reshared your deleted post." zero: "%{actors}さんが削除された投稿をリシェアしました。" started_sharing: - few: "%{actors} started sharing with you." - many: "%{actors} started sharing with you." - one: "%{actors} started sharing with you." other: "%{actors}さんが、あなたとシェアを始めました。" - two: "%{actors} started sharing with you." zero: "%{actors}さんが、あなたとシェアを始めました。" notifier: a_limited_post_comment: "あなたが確認する、ダイアスポラ*の制限公開の投稿に新しいコメントがあります。" @@ -733,6 +694,29 @@ ja: confirm_email: click_link: "新しいメールアドレス %{unconfirmed_email} を有効にするために、このリンクをクリックしてください:" subject: "新しいメールアドレス %{unconfirmed_email} を有効にしてください" + csrf_token_fail: + body: |- + %{name} さん、こんにちは + + ダイアスポラ* が、あなたのセッションへのアクセスを検知しましたが、これは不正な可能性があります。 これは完全に無実かもしれませんが、クロスサイトリクエストフォージェリ (CSRF) の可能性があります。 データが侵害される可能性を避けるために、あなたはログアウトしています。 + + 不適切または欠落しているCSRFトークンを使用して行われたリクエストは、以下のような原因が考えられます: + + - リクエストを操作するか、トークンなしでリクエストを行うアドオン。 + - 過去のセッションで開いたタブ。 + - あなたの許可の有無にかかわらず、リクエストを行う別のウェブサイト。 + - さまざまな他の外部ツール。 + - あなたのデータにアクセスしようとしている悪質なコード。 + + CSRFの詳細については、 [%{link}](%{link}) を参照してください。 + + 心配しないでください。 今すぐもう一度安全にサインインすることができます。 + + このメッセージが繰り返し表示される場合は、ブラウザのアドオンを含め、上記の点を確認してください。 + + ありがとうございました、 + ダイアスポラ* メールロボット! + subject: "あなたのアカウント %{name} から、不正なリクエストを受け取りました。" email_sent_by_diaspora: "このEメールは%{pod_name}から送信されました。もしこのようなEメールの受信を拒否したい場合は、" export_email: body: |- @@ -804,6 +788,9 @@ ja: mentioned: limited_post: "あなたは限定公開の投稿でメンションされました。" subject: "%{name}さんはダイアスポラ*であなたをメンションしました。" + mentioned_in_comment: + limited_post: "限定公開の投稿にコメントでメンションされました。" + reply: "この会話に返信、または表示 >" private_message: reply_to_or_view: "この会話に返信、または表示 >" subject: "あなたに新しい非公開メッセージがあります" @@ -889,14 +876,8 @@ ja: type_error: "写真のアップロードに失敗しました。確かに画像ファイルを添付しましたか。" destroy: notice: "写真を削除しました。" - new_photo: - empty: "{file}は空です。取り除いてファイルを選択しなおしてください。" - invalid_ext: "{file}のファイル名は不正です。{extensions}以外の拡張子は使えません。" - size_error: "{file}は大きすぎます。ファイルサイズの上限は{sizeLimit}です。" new_profile_photo: upload: "新しいプロフィール写真をアップロードしてください!" - show: - show_original_post: "元の投稿を表示する" polls: votes: other: "これまで %{count} の投票" @@ -908,11 +889,7 @@ ja: forbidden: "この操作は許可されていません" location: "%{location} から投稿" photos_by: - few: "%{count} photos by %{author}" - many: "%{count} photos by %{author}" - one: "One photo by %{author}" other: "%{author}さんの写真%{count}枚" - two: "Two photos by %{author}" zero: "%{author}さんの写真はありません" reshare_by: "%{author}さんがリシェア" privacy: "プライバシー" @@ -947,11 +924,7 @@ ja: updated: "プロフィールを更新しました" public: "公開" reactions: - few: "%{count} reactions" - many: "%{count} reactions" - one: "1 reaction" other: "%{count} リアクション" - two: "%{count} reactions" zero: "0 リアクション" registrations: closed: "このダイアスポラ*ポッドでは新規登録を受け付けていません。" @@ -985,8 +958,13 @@ ja: destroyed: "投稿が破壊されました" failed: "何か問題があります" title: "報告の概要" + unreviewed_reports: + other: "%{count} 件の未確認の報告があります。" + zero: "未確認の報告はありません。" reshares: comment_email_subject: "%{author}の投稿の%{resharer}のリシェア" + create: + error: "リシェアに失敗しました。" reshare: deleted: "元の投稿は作者によって削除されました。" reshare_confirmation: "%{author}さんの投稿をリシェアしますか?" @@ -1009,7 +987,7 @@ ja: logged_in_as: "%{nickname}としてログインしています。" no_services_available: "このポッドで利用可能なサービスはありません。" not_logged_in: "現在ログインしていません。" - really_disconnect: "%{service}から切断しますか。" + really_disconnect: "%{service}から切断しますか?" services_explanation: "サードパーティのシェアサービスに接続すると、ダイアスポラ*に書きながらそれらに投稿を公開することができます。" share_to: "%{provider}にシェア" title: "提携サービスを管理する" @@ -1024,11 +1002,7 @@ ja: mobile_row_checked: "%{name} (削除)" mobile_row_unchecked: "%{name} (追加)" toggle: - few: "In %{count} aspects" - many: "In %{count} aspects" - one: "In %{count} aspect" other: "%{count} のアスペクトで" - two: "In %{count} aspects" zero: "%{count} のアスペクトで" invitations: by_email: "メールで" @@ -1166,6 +1140,7 @@ ja: comment_on_post: "自分の投稿にコメントがあったとき" current_password: "現在のパスワード" current_password_expl: "サインインしているもの..." + default_post_visibility: "投稿のために選択されるデフォルトのアスペクト" download_export: "マイ プロフィールをダウンロード" download_export_photos: "写真をダウンロードする" edit_account: "アカウント編集" @@ -1177,6 +1152,7 @@ ja: last_exported_at: "(最終更新 %{timestamp})" liked: "あなたの投稿をいいね!したとき" mentioned: "投稿に自分がメンションされたとき" + mentioned_in_comment: "コメントでメンションされました" new_password: "新しいパスワード" private_message: "非公開メッセージが届いたとき" receive_email_notifications: "通知メールの送信設定" diff --git a/config/locales/diaspora/ka.yml b/config/locales/diaspora/ka.yml index ad0f02224..d1caa470a 100644 --- a/config/locales/diaspora/ka.yml +++ b/config/locales/diaspora/ka.yml @@ -156,9 +156,6 @@ ka: fill_me_out: "შევსება" find_people: "იპოვეთ ადამიანები ან #ტეგები" invitations: - a_facebook_user: "Facebook-ის მომხმარებელი" - check_token: - not_found: "მოწვევა არ არის ნაპოვნი" create: no_more: "თქვენ ამოგეწურათ მოსაწვევები." rejected: "შემდეგ ელ-ფოსტებს აქვთ პრობლემა: " @@ -327,14 +324,8 @@ ka: type_error: "ფოტოს ატვირთვა ვერ მოხერხდა. დარწმუნებული ხარ რომ სურათი დაამატე?" destroy: notice: "სურათი წაშლილია." - new_photo: - empty: "{file} არის ცარიელი, გთხოვთ აირჩიოთ ფაილები მის გარეშე" - invalid_ext: "{file} აქვს არასწორი გაფართოება. მხოლოდ {extensions} გაფართოებები არის დაშვებული." - size_error: "{file} ზომაზე დიდია, მაქსიმალური ზომა არის {sizeLimit}." new_profile_photo: upload: "ახალი პროფილის ფოტოს ატვირთვა!" - show: - show_original_post: "ორიგინალი პოსტის ჩვენება" posts: show: photos_by: diff --git a/config/locales/diaspora/ko.yml b/config/locales/diaspora/ko.yml index b39326bef..759972cad 100644 --- a/config/locales/diaspora/ko.yml +++ b/config/locales/diaspora/ko.yml @@ -182,7 +182,6 @@ ko: conversations: create: fail: "유효하지 않은 쪽지" - no_contact: "컨택부터 추가하세요!" sent: "쪽지를 보냈습니다" index: conversations_inbox: "대화 - 수신함" @@ -241,9 +240,6 @@ ko: tutorials: "간단 설명서" wiki: "위키" invitations: - a_facebook_user: "페이스북 사욤자" - check_token: - not_found: "초대장 토큰을 찾을 수 없습니다" create: empty: "이메일 주소를 한 개 이상 입력해주세요." no_more: "가진 초대장이 없습니다." @@ -422,14 +418,8 @@ ko: type_error: "사진 업로드 실패. 이미지를 추가하지 않았습니다." destroy: notice: "사진을 지웠습니다." - new_photo: - empty: "{file} 파일은 빈 파일입니다. 이 파일만 빼고 다시 시도하세요." - invalid_ext: "{file} 파일은 유효하지 않은 형식입니다. {extensions} 형식의 파일을 올려주세요." - size_error: "{file} 파일이 {sizeLimit} 보다 큽니다" new_profile_photo: upload: "새 프로필 사진 업로드하기!" - show: - show_original_post: "원래 게시물 보기" posts: presenter: title: "%{name}님의 게시물" diff --git a/config/locales/diaspora/lt.yml b/config/locales/diaspora/lt.yml index 8d56031ce..2a26ff209 100644 --- a/config/locales/diaspora/lt.yml +++ b/config/locales/diaspora/lt.yml @@ -148,9 +148,6 @@ lt: fill_me_out: "Užpildykite" find_people: "Rasti žmones arba žymes" invitations: - a_facebook_user: "Facebook vartotojas" - check_token: - not_found: "Pakvietimo raktas nerastas" create: no_more: "Daugiau pakvietimų neturi." rejected: "Šie el. pašto adresai neveikė: " @@ -287,10 +284,6 @@ lt: photos: destroy: notice: "Nuotrauka pašalinta." - new_photo: - empty: "{file} yra tuščias, pasirink failus iš naujo." - invalid_ext: "{file} turi neteisingą galūnę. Yra leidžiamos tik {extensions}." - size_error: "{file} yra per didelis, maksimalus failo dydis yra {sizeLimit}." posts: show: photos_by: diff --git a/config/locales/diaspora/mk.yml b/config/locales/diaspora/mk.yml index 7dfd8096d..06cf1ce6e 100644 --- a/config/locales/diaspora/mk.yml +++ b/config/locales/diaspora/mk.yml @@ -101,9 +101,6 @@ mk: fill_me_out: "Пополни ме" find_people: "Пронајди пријатели или #тагови" invitations: - a_facebook_user: "Facebook корисник" - check_token: - not_found: "Токенот за поканата не е пронајден" create: no_more: "Немате повеќе покани." rejected: "Следните е-маил адреси имаа проблем:" @@ -238,10 +235,6 @@ mk: photos: destroy: notice: "Сликата е избришана." - new_photo: - empty: "{file} е празен, изберете датотеки без него." - invalid_ext: "{file} има невалидна екстензија. Само овие {extensions} се дозволени." - size_error: "{file} е премногу голема, максимална големина на датотека е {sizeLimit}." posts: show: photos_by: diff --git a/config/locales/diaspora/ml.yml b/config/locales/diaspora/ml.yml index fa2cfae70..16ee66b36 100644 --- a/config/locales/diaspora/ml.yml +++ b/config/locales/diaspora/ml.yml @@ -189,7 +189,6 @@ ml: conversations: create: fail: "സാധുവല്ലാത്ത സന്ദേശം" - no_contact: "നമസ്കാരം, താങ്കൾ ആദ്യം ഒരു ബന്ധം ചേർക്കണം!" sent: "സന്ദേശം അയച്ചു." index: inbox: "ഇന്‍ബോക്സ്" @@ -348,9 +347,6 @@ ml: tutorials: "പഠനോപകരണങ്ങള്‍" wiki: "വിക്കി" invitations: - a_facebook_user: "ഒരു ഫേസ്ബുക്ക് ഉപയോക്താവ്" - check_token: - not_found: "ക്ഷണത്തിന്റെ ടോക്കണ്‍ കാണുന്നില്ല" create: empty: "ദയവായി കുറഞ്ഞത് ഒരു ഈമെയിൽ വിലാസമെങ്കിലും നൽകുക" no_more: "താങ്കള്‍ക്ക് ഇനി ക്ഷണങ്ങളൊന്നും ബാക്കിയില്ല." @@ -530,14 +526,8 @@ ml: type_error: "ചിത്രം അപ്‌ലോഡ് പരാജയപ്പെട്ടു.. താങ്കള്‍ ഒരു ചിത്രം അപ്‌ലോഡ് ചെയ്യാന്‍ തിരഞ്ഞെടുത്തിരുന്നോ?" destroy: notice: "ചിത്രം നീക്കം ചെയ്തു." - new_photo: - empty: "{file} ശൂന്യമാണ്, അതല്ലാത്ത ഫയലുകള്‍ ദയവായി വീണ്ടും തെരഞ്ഞെടുക്കുക." - invalid_ext: "{file} ന് തെറ്റായ extension ആണ്. {extensions} മാത്രം അനുവദിച്ചിരിക്കുന്നു." - size_error: "{file} വളരെ വലുതാണ്, കൂടിയ ഫയല്‍ വലിപ്പം {sizeLimit} ആകുന്നു." new_profile_photo: upload: "പുതിയ പ്രൊഫൈല്‍ ചിത്രം ചേര്‍ക്കുക!" - show: - show_original_post: "Show original post" posts: presenter: title: "%{name}ല്‍ നിന്നുള്ള കുറിപ്പ്" diff --git a/config/locales/diaspora/nb.yml b/config/locales/diaspora/nb.yml index 9c84061f6..9b100a47f 100644 --- a/config/locales/diaspora/nb.yml +++ b/config/locales/diaspora/nb.yml @@ -229,7 +229,6 @@ nb: conversations: create: fail: "Ugyldig melding" - no_contact: "Heisann, du må legge til kontakten først." sent: "Melding sendt" destroy: delete_success: "Samtalen ble slettet suksessfullt" @@ -484,9 +483,6 @@ nb: invitation_codes: not_valid: "Den invitasjonskoden er ikke lenger gyldig" invitations: - a_facebook_user: "En Facebook-bruker" - check_token: - not_found: "Invitasjonsnøkkelen finnes ikke" create: empty: "Vennligst angi i hvertfall en e-post adresse" no_more: "Du har ikke flere invitasjoner." @@ -774,14 +770,8 @@ nb: type_error: "Bildeopplastning mislyktes. ER du sikker på at et bilde ble lagt til?" destroy: notice: "Bildet er sletta." - new_photo: - empty: "{file} er tom, vennligst velg filer igjen uten den" - invalid_ext: "{file} er en ugyldig filtype. Bare {extensions} er tillatt." - size_error: "{file} er for stor, maks filstørrelse er {sizeLimit}." new_profile_photo: upload: "Last opp et nytt profilbilde!" - show: - show_original_post: "Vis originalpost" posts: presenter: title: "En post fra %{name}" diff --git a/config/locales/diaspora/nds.yml b/config/locales/diaspora/nds.yml index fdd8336c6..937f04a3f 100644 --- a/config/locales/diaspora/nds.yml +++ b/config/locales/diaspora/nds.yml @@ -216,7 +216,6 @@ nds: conversations: create: fail: "Ungültige Noricht" - no_contact: "He, du muss erst Kontakt schluten!" sent: "Noricht afschickt" destroy: delete_success: "Schnack erfolgriek löscht" @@ -389,9 +388,6 @@ nds: tutorials: "Anleidungen" wiki: "Wiki" invitations: - a_facebook_user: "Een Facebook-Bruker" - check_token: - not_found: "Inlodungstoken nich funnen" create: empty: "Bidde geev minstens eene E-Mail-Adress in." no_more: "Du kannst keene Inlodungen mehr schicken." @@ -580,14 +576,8 @@ nds: type_error: "Hoochloden von dat Bild fehlschloon. Bist du di sicher, dat du een Bild dortaudoon hest?" destroy: notice: "Bild löscht." - new_photo: - empty: "{file} is leer, bidde wähl de Dateien noch mol ohne er ut." - invalid_ext: "{file} het een ungültiges Enn. Nur {extensions} sind erlaubt." - size_error: "{file} is to groot, Dateien dröfft höchstens {sizeLimit} groot ween." new_profile_photo: upload: "Nee’es Profilbild hoochloden!" - show: - show_original_post: "Originalbidrag anzeigen" posts: presenter: title: "Een Bidrag von %{name}" diff --git a/config/locales/diaspora/ne.yml b/config/locales/diaspora/ne.yml index 93d9f1203..dfdd3b822 100644 --- a/config/locales/diaspora/ne.yml +++ b/config/locales/diaspora/ne.yml @@ -23,7 +23,6 @@ ne: delete: "मेट्नुहोस्" email: "ईमेल" invitations: - a_facebook_user: "फेसबुक प्रयोगकर्ता" new: language: "भाषा" notifications: diff --git a/config/locales/diaspora/nl.yml b/config/locales/diaspora/nl.yml index af552a81d..e1f585c73 100644 --- a/config/locales/diaspora/nl.yml +++ b/config/locales/diaspora/nl.yml @@ -274,6 +274,8 @@ nl: post_something: "Publiceer op diaspora*" cancel: "Annuleren" comments: + create: + error: "Reageren mislukt." new_comment: comment: "Reactie" commenting: "Reageren..." @@ -293,11 +295,11 @@ nl: user_search: "Zoek gebruiker" spotlight: community_spotlight: "Community aanrader" + no_members: "Er zijn nog geen leden" suggest_member: "Suggereer een lid" conversations: create: fail: "Ongeldig bericht" - no_contact: "Hallo, je moet wel eerst een contactpersoon toevoegen!" sent: "Privébericht verzonden" destroy: delete_success: "De conversatie is verwijderd" @@ -306,6 +308,7 @@ nl: conversations_inbox: "Conversaties - inbakje" inbox: "Postvak In" new_conversation: "Nieuwe conversatie" + no_contacts: "Je moet een paar contactpersonen toevoegen om een conversatie te starten" no_messages: "Geen privéberichten" new: message: "Bericht" @@ -330,6 +333,7 @@ nl: delete: "Verwijderen" email: "E-mail" error_messages: + csrf_token_fail: "Het CSRF token is ongeldig. Log opnieuw in en probeer het nog eens." helper: correct_the_following_errors_and_try_again: "Corrigeer de volgende fouten en probeer opnieuw." need_javascript: "Deze website vereist JavaScript om goed te kunnen werken. Als je JavaScript hebt uitgeschakeld, adviseren we om het te activeren en deze pagina te herladen." @@ -567,7 +571,6 @@ nl: own_your_data: "Beschik over je eigen gegevens" own_your_data_info: "Veel netwerken verdienen hun geld door jouw gedrag en interacties vanuit jouw gegevens te analyseren om 'op maat gesneden' advertenties te serveren. diaspora* gebruikt je data alleen om je in de gelegenheid te stellen te communiceren en te delen met anderen." podmin: - admin_panel: "beheerscherm" byline: "Je staat op het punt om het internet te veranderen. Zullen we daar maar eens mee beginnen?" configuration_info: "Open %{database_path} en %{diaspora_path} in je voorkeurs teksteditor en bestudeer ze grondig. Ze zijn rijkelijk voorzien van commentaar." configure_your_pod: "Configureer je pod" @@ -587,12 +590,11 @@ nl: update_your_pod: "Update je pod" update_your_pod_info: "Je vind %{update_instructions}" invitation_codes: + already_logged_in: "Je bent door %{inviter} uitgenodigd om lid te worden van deze pod, maar je bent al ingelogd." not_valid: "Deze uitnodigingscode is niet langer geldig" invitations: - a_facebook_user: "Een Facebook gebruiker" - check_token: - not_found: "Uitnodigingstoken niet gevonden" create: + closed: "Uitnodigingen zijn gesloten op deze diaspora* pod" empty: "Gelieve minstens 1 e-mailadres toe te voegen." no_more: "Je hebt geen uitnodigingen meer." note_already_sent: "Er zijn al uitnodigingen verstuurd naar: %{emails}" @@ -612,6 +614,7 @@ nl: layouts: application: back_to_top: "Terug naar top" + be_excellent: "Wees uitmuntend voor elkaar! ♥" powered_by: "Powered by diaspora*" public_feed: "Publieke diaspora* kanaal van %{name}" source_package: "Download het broncode pakket" @@ -624,6 +627,9 @@ nl: profile: "Profiel" settings: "Instellingen" toggle_navigation: "Switchen navigatie" + likes: + create: + error: "Leuk vinden mislukt" limited: "Beperkt" more: "Meer" no_results: "Geen resultaten gevonden" @@ -874,14 +880,8 @@ nl: type_error: "Foto uploaden mislukt. Weet je zeker dat je een afbeelding toegevoegd hebt?" destroy: notice: "Foto verwijderd." - new_photo: - empty: "{file} is leeg, selecteer de bestanden opnieuw zonder deze." - invalid_ext: "{file} heeft een ongeldige extensie. Alleen {extensions} zijn toegestaan." - size_error: "{file} is te groot, de maximale bestandsgrootte is {sizeLimit}." new_profile_photo: upload: "Upload een nieuwe profielfoto!" - show: - show_original_post: "Toon origineel bericht" polls: votes: one: "%{count} stem tot nu" @@ -968,8 +968,14 @@ nl: destroyed: "Het bericht is vernietigd" failed: "Er ging iets verkeerd" title: "Meldingenoverzicht" + unreviewed_reports: + one: "Er is %{count} onbeoordeelde melding." + other: "Er zijn %{count} onbeoordeelde meldingen." + zero: "Er zijn geen onbeoordeelde meldingen." reshares: comment_email_subject: "%{resharer}'s doorgifte van %{author}'s post" + create: + error: "Doordelen mislukt." reshare: deleted: "Het originele bericht is verwijderd door de auteur." reshare_confirmation: "%{author}'s bericht doorgeven?" diff --git a/config/locales/diaspora/nn.yml b/config/locales/diaspora/nn.yml index 2a6b074df..0184b8224 100644 --- a/config/locales/diaspora/nn.yml +++ b/config/locales/diaspora/nn.yml @@ -189,7 +189,6 @@ nn: conversations: create: fail: "Ugyldig melding" - no_contact: "Hei, du må leggje til kontakten først!" sent: "Meldinga er sendt" index: inbox: "Innkorg" @@ -228,9 +227,6 @@ nn: tutorials: "innføringar" wiki: "wiki" invitations: - a_facebook_user: "Ein Facebook-brukar" - check_token: - not_found: "Fann ikkje invitasjonskoda" create: empty: "Skriv inn minst ei e-post-adresse." no_more: "Du har ingen fleire invitasjonar." @@ -420,14 +416,8 @@ nn: type_error: "Klarte ikkje å lasta opp biletet. Er du sikker på at du la til eit bilete?" destroy: notice: "Biletet er sletta." - new_photo: - empty: "{file} er tom, vel filer utan å ta ho med." - invalid_ext: "{file} har ein ugyldig filtype. Berre {extensions} er tillatne." - size_error: "{file} er for stor, kan ikkje vera større enn {sizeLimit}." new_profile_photo: upload: "Last opp eit nytt profilbilete." - show: - show_original_post: "Syn den opphavlege meldinga" posts: presenter: title: "Eit innlegg av %{name}" diff --git a/config/locales/diaspora/oc.yml b/config/locales/diaspora/oc.yml index 54f2c1098..1396b96ae 100644 --- a/config/locales/diaspora/oc.yml +++ b/config/locales/diaspora/oc.yml @@ -291,7 +291,6 @@ oc: conversations: create: fail: "Messatge invalid" - no_contact: "Ei, vos cal ajustar lo contacte en primièr !" sent: "Messatge mandat" destroy: delete_success: "Conversacion escafada amb succès" @@ -330,19 +329,26 @@ oc: find_people: "Recercar de personas o de #tags" help: account_and_data_management: + close_account_a: "Rensètz-vos en bas de la pagina e clicatz sul boton \"Clausurar lo compte\". Vòstre senhal vos serà demandat per acabar lo processus. Vos rapelam que se tampatz vòstre compte, ne poiretz pas mai tornar crear sus aqueste pod amb aqueste nom d'utilizaire." close_account_q: "Cossí pòdi suprimir mon compte ?" data_other_podmins_q: "Los administrators dels autres pods pòdon veire mas informacions ?" data_visible_to_podmin_q: "Quina quantitat de mas informacions l'administrator del pod pòt veire ?" + download_data_a: "Òc. En dejòs de los paramètres de Compte trobaretz dos botons : un per telecargar vòstras donadas e un per telecargar vòstras fotos." download_data_q: "Pòdi telecargar una còpia de totas las donadas contengudas dins mon compte ?" + move_pods_a: "Dins lo futur poiretz exportar vòstra grana - seed - dempuèi un pod e l'importar dins un autre, mai pel moment es pas possible. Podètz totjorn dubrir un nòu compte e ajustar vòstres contactes sus aquela nòva grana, e lor demandar de vos ajustar sus lors aspèctes amb vòstra nòva grana." move_pods_q: "Cossí desplaçar mon compte d'un pod a un autre ?" title: "Gestion del compte e de las donadas" aspects: + change_aspect_of_post_a: "Non, mas podètz totjorn crear una nòva publicacion amb lo meteis contengut e o publicar sus un autre aspècte." + change_aspect_of_post_q: "Un còp qu'ai publiat quicòm, pòdi cambiar los aspècte(s) qu'o pòdon veire ?" contacts_know_aspect_a: "Non pas. Pòdon pas veire lo nom de l'aspècte qualqu'arribe." contacts_know_aspect_q: "Mos contactes pòdon saber sus quin aspècte los ai mes ?" contacts_visible_q: "Qué significa « rendre los contactes dins aqueste aspècte visibles entre eles » ?" delete_aspect_q: "Cossí pòdi suprimir un aspècte ?" person_multiple_aspects_q: "Pòdi apondre una persona a mantun aspècte ?" + post_multiple_aspects_a: "Òc. Quand publicatz una publicacion, utilizatz lo boton per causir los aspèctes. \"Totes los aspèctes\" es la causida per defaut dins los paramaètres. Podètz tanben causir los aspèctes dins la barra de menú. Quand publicactz, lo(s) aspèctes qu'avètz causits dins la lista a man esquèrra seràn automaticament seleccionats per las publicacions venentas." post_multiple_aspects_q: "Pòdi mandar un messatge a mantun aspècte a l'encòp ?" + remove_notification_a: "Non. Tanpauc seràn pas avisat se los ajustatz dins mai aspèctes, del moment que ja partejatz amb eles." remove_notification_q: "Se suprimissi qualqu'un d'un de mos aspèctes, o totas las personas d'un aspècte, son prevengudas ?" rename_aspect_a: "Clicatz \"Mos aspèctes\" sul costat esquèrra de la pagina de flux e clicatz sul gredonèl \"editar\" sus la dreita de l'aspècte de renomenar. Podètz tanben anar sus la pagina \"Contactes\" e seleccionar l'aspècte concernit. Clicatz alara sus l'icòna \"editar\" al costat del nom amont de la pagina, cambiatz lo nom e clicatz \"Metre a jorn\"." rename_aspect_q: "Pòdi tornar nommar un aspècte ?" @@ -364,6 +370,7 @@ oc: get_support_a_website: "Visitatz nòstre %{link}" get_support_a_wiki: "Recercatz dins lo %{link}" get_support_q: "De qué far se ma question a pas de responsa dins la FAQ ? A quines autres endreits pòdi obténer de documentcion ?" + getting_started_a: "Sètz astruc. Ensajatz las %{tutorial_series} sul site de nòstre projècte. Vos ajudarà pas a pas dempuèi l'inscripcion cap a las causas basicas que vos cal saber per utilizar diaspora*." getting_started_q: "Ajudatz-me ! Ai besonh d'ajuda per debutar !" title: "Obténer d'ajuda" getting_started_tutorial: "Seria de tutorials \"Mos primièrs passes\"" @@ -405,6 +412,7 @@ oc: char_limit_services_q: "Quin es lo limit de caractèrs pels messatges partejats amb un servici qu'a un limit de caractèrs mai pichon ?" character_limit_a: "65 535 caractèrs. Son 65 395 caractèrs de mai que Twitter ! :)" character_limit_q: "Qual es lo limit de caractèrs per las publicacions ?" + embed_multimedia_q: "Cossí pòdi inserir un contengut vidèo, àudio, o multimèdia dins una publicacion ?" format_text_q: "Cossí pòdi formatar lo tèxte dins as publicacions (gras, italic, etc.) ?" hide_posts_q: "Cossí escondi una publicacion ?" image_text: "tèxte de l'imatge" @@ -438,6 +446,7 @@ oc: can_comment_reshare_like_a: "Quin utilizaire connectat a diaspora* que siá, pòt comentar, repartejar vòstre messatge public o marcar que li agrada." can_comment_reshare_like_q: "Qual pòt comentar, repartejar, o marcar que li agrada mon messatge public ?" find_public_post_q: "Cossí las autras personas pòdon trobar mos messatges publics ?" + see_comment_reshare_like_q: "Quand comenti, tòrni partejar, o aimi una publicacion publica, qual pòt o veire ?" title: "Publicacions publicas" who_sees_post_q: "Quand publiqui quicòm publicament, qual pòt veire ?" public_profiles: @@ -480,7 +489,6 @@ oc: headline: "Benvenguda sus %{pod_name}" own_your_data: "Siatz proprietari de vòstras donadas" podmin: - admin_panel: "panèl d'administrator" byline: "Sètz a mand de cambiar la fàcia d'internet. Prèst a vos lançar ?" configuration_info: "Dobrissètz %{database_path} e %{diaspora_path} dins vòstre editor de tèxte favorit e relegissètz-los menimosament, son comentats abondament." configure_your_pod: "Configuratz vòstre pod" @@ -500,9 +508,6 @@ oc: invitation_codes: not_valid: "Aqueste còdi es pas pus valid." invitations: - a_facebook_user: "Un utilizaire de Facebook" - check_token: - not_found: "Geton de convit pas trobat" create: empty: "Mercés de picar almens una adreça de corrièl." no_more: "Avètz pas mai de convits." @@ -536,6 +541,9 @@ oc: profile: "Perfil" settings: "Paramètres" toggle_navigation: "Afichar/amagar lo menú" + likes: + create: + error: "Fracàs al moment d'aimar." limited: "Limitat" more: "Mai" no_results: "Cap de resultat pas trobat" @@ -567,6 +575,7 @@ oc: mark_read: "Marcar coma legit" mark_unread: "Marcar coma pas legit" mentioned: "Mencionat" + mentioned_in_comment: "Mencionat dins un comentari" no_notifications: "Avètz pas encara cap de notificacion." notifications: "Notificacions" reshared: "Repartejat" @@ -618,6 +627,8 @@ oc: confirm_email: click_link: "Per activar vòstre novèla adreça de corrièl %{unconfirmed_email}, seguissètz aqueste ligam :" subject: "Mercés d'activar vòstre novèl corrièl %{unconfirmed_email}" + csrf_token_fail: + subject: "Avèm recebut una demanda sens autorizacion dempuèi vòstre compte, %{name}" email_sent_by_diaspora: "Aqueste corrièl es estat mandaat per %{pod_name}. Se volètz pas mai de corrièls atal," export_email: body: |- @@ -690,6 +701,9 @@ oc: mentioned: limited_post: "Sètz estat mencionat dins una publicacion restenta." subject: "%{name} vos a mencionat sus diaspora*" + mentioned_in_comment: + limited_post: "Sètz mencionat dins un comentari al accès limitat." + reply: "Respondre o veire la conversacion >" private_message: reply_to_or_view: "Respondre o afichar aquela conversacion >" subject: "Avètz un novèl messatge privat" @@ -773,14 +787,8 @@ oc: type_error: "Fracàs al moment de mandar l'imatge.  Sètz segur qu'un imatge es estat apondut ?" destroy: notice: "Fòto suprimida" - new_photo: - empty: "{file} es voida, mercé de tornar seleccionar de fichièrs sens aquel d'aquí." - invalid_ext: "L'extension de {file} es pas valida. Sonque {extensions} son autorizadas." - size_error: "{file} es tròp granda, la talha maximala es {sizeLimit}." new_profile_photo: upload: "Mandatz una novèla fòto de perfil !" - show: - show_original_post: "Mostrar la publicacion originala" polls: votes: one: "%{count} vòte pel moment" @@ -862,6 +870,8 @@ oc: title: "Vista d'ensemble dels senhalaments" reshares: comment_email_subject: "Partiment per %{resharer} d'un messatge de %{author}" + create: + error: "Fracàs al moment de tornar partejar." reshare: deleted: "La publicacion originala foguèt suprimida per son autor." reshare_confirmation: "Volètz tornar partejar la publicacion de %{author} ?" @@ -916,6 +926,7 @@ oc: outside: "Los messatges publics poiràn èsser vistes per totes, quitament en defòra de diaspora*." share: "Partejatz" title: "Metre en plaça de servicis connectats" + visibility_dropdown: "Utilizatz aqueste menú per cambiar la visibilitat de vòstra publicacion  (Vos recomandam de marcar la primièra coma publica)" publisher: discard_post: "Suprimir la publicacion" formatWithMarkdown: "Utilizatz la sintaxi %{markdown_link} per metre en forma vòstre messatge" @@ -1031,10 +1042,12 @@ oc: make_diaspora_better: "Nos agradariá fòrça que demorèssetz e nos ajudèssetz a far un melhor diaspora* puslèu que de nos daissar. Se volètz vertadièrament partir, pasmens, vaquí çò que se va passar :" mr_wiggles: "Mossur Wiggles serà triste de vos veire partir." no_turning_back: "Es pas possible de tornar en arrièr ! Se sètz segur de vos, sasissètz vòstre senhal çaijós." + what_we_delete: "Suprimirem totas vòstras publicacions e informacions de perfil tre que possible. Vòstres comentaris sus la publicacion del mond desapareisseràn, mai seràn associats a vòstre ID diaspora* al lòc de vòstre nom." close_account_text: "Tampar lo compte" comment_on_post: "qualqu'un comenta vòstra publicacion" current_password: "Senhal actual" current_password_expl: "Lo senhal que causissètz..." + default_post_visibility: "Aspèctes per defaut seleccionats per las publicacions" download_export: "Telecargar mon perfil" download_export_photos: "Telecargar mas fòtos" edit_account: "Modificar lo compte" @@ -1046,6 +1059,7 @@ oc: last_exported_at: "(Darrièra mesa a jorn a %{timestamp})" liked: "a qualqu'un li a agradat vòstra publicacion" mentioned: "...se vos menciona dins un messatge." + mentioned_in_comment: "sètz mencionat dins un comentari" new_password: "Senhal novèl" private_message: "Avètz recebut un messatge privat." receive_email_notifications: "Recebre una notificacion per corrièl quand :" @@ -1065,6 +1079,7 @@ oc: getting_started: awesome_take_me_to_diaspora: "Òsca ! Mena-me cap a diaspora*" community_welcome: "La comunautat diaspora* es contenta de vos aver a bòrd." + connect_to_facebook: "Podèm accelerar un pauc las causas de %{link} sus diaspora*. Aquò botarà vòstre nom e foto, e activar la publicacion multiplataforma." connect_to_facebook_link: "Connexion amb vòtre compte Facebook en cors" hashtag_explanation: "Las etiquetas vos permeton de charrar e seguir vòstres interèsses. Son tanben una bona manièra de trobar de mond novèl sus diaspora*." hashtag_suggestions: "Ensejatz etiquetas coma aquestas #art #filmes #gif, etc." diff --git a/config/locales/diaspora/pl.yml b/config/locales/diaspora/pl.yml index c664c3714..248dbd440 100644 --- a/config/locales/diaspora/pl.yml +++ b/config/locales/diaspora/pl.yml @@ -276,7 +276,6 @@ pl: conversations: create: fail: "Nieprawidłowa wiadomość" - no_contact: "Hej! Najpierw należy dodać kontakt!" sent: "Wiadomość została wysłana" destroy: delete_success: "Rozmowa usunięta" @@ -531,9 +530,6 @@ pl: tutorials: "samouczki" wiki: "wiki" invitations: - a_facebook_user: "Użytkownik Facebooka" - check_token: - not_found: "Nie odnaleziono identyfikatora zaproszenia" create: empty: "Podaj przynajmniej jeden adres e-mail." no_more: "Nie masz więcej zaproszeń." @@ -826,14 +822,8 @@ pl: type_error: "Nie udało się przesłać zdjęcia. Czy na pewno doda@{m:łeś|f:łaś|n:no} obraz?" destroy: notice: "Usunięto zdjęcie." - new_photo: - empty: "Plik {file} jest pusty. Wybierz proszę jeszcze raz odpowiednie pliki, pomijając ten." - invalid_ext: "Plik {file} ma niewłaściwe rozszerzenie. Akceptowane rozszerzenia: {extensions}" - size_error: "Plik {file} jest zbyt duży, maksymalny rozmiar to {sizeLimit}." new_profile_photo: upload: "Prześlij nowe zdjęcie profilowe!" - show: - show_original_post: "Wyświetl oryginalny wpis" posts: presenter: title: "Wpis od %{name}" diff --git a/config/locales/diaspora/pt-BR.yml b/config/locales/diaspora/pt-BR.yml index 6aa04fa4b..7e2d70bee 100644 --- a/config/locales/diaspora/pt-BR.yml +++ b/config/locales/diaspora/pt-BR.yml @@ -268,6 +268,8 @@ pt-BR: post_something: "Publicar em diaspora*" cancel: "Cancelar" comments: + create: + error: "Falha ao comentar." new_comment: comment: "Comentar" commenting: "Comentando..." @@ -292,7 +294,6 @@ pt-BR: conversations: create: fail: "Mensagem inválida" - no_contact: "Cuidado, você precisa adicionar o contato primeiro!" sent: "Mensagem enviada" destroy: delete_success: "Conversa excluída com sucesso" @@ -301,6 +302,7 @@ pt-BR: conversations_inbox: "Conversas – Caixa de Entrada" inbox: "Entrada" new_conversation: "Nova conversa" + no_contacts: "Você precisa adicionar contatos antes de começar uma conversa." no_messages: "Não há mensagens" new: message: "Mensagem" @@ -325,6 +327,7 @@ pt-BR: delete: "Apagar" email: "E-mail" error_messages: + csrf_token_fail: "O código CSRF é inválido. Por favor, entre no sistema e tente de novo." helper: correct_the_following_errors_and_try_again: "Corrija os erros a seguir e tente novamente." need_javascript: "Este site precisa de JavaScript para funcionar corretamente. Se você desabilitou o Javascript, habilite-o e atualize esta página." @@ -558,7 +561,6 @@ pt-BR: own_your_data: "Os seus dados são seus" own_your_data_info: "Várias redes lucram com seus dados, analisando as suas interações e usando as informações obtidas para fazer publicidade. A diaspora* não usa seus dados para nada além de possibilitar que você se conecte e compartilhe com outras pessoas." podmin: - admin_panel: "painel de administração" byline: "Você está prestes a revolucionar a internet. Vamos começar?" configuration_info: "Abra %{database_path} e %{diaspora_path} no seu editor de texto favorito e revise-os cuidadosamente, estão minuciosamente comentados." configure_your_pod: "Configure seu servidor" @@ -572,22 +574,21 @@ pt-BR: getting_help_info: "Nós listamos %{faq}, inclusive dicas, macetes e soluções para os problemas mais comuns. Sinta-se livre, também, para %{irc}." headline: "Olá, colega." make_yourself_an_admin: "Assuma a administração" - make_yourself_an_admin_info: "Você pode encontrar instruções na %{wiki}. Quando você entrar no sistema, haverá um link \"Admin\" no seu menu de usuário, no cabeçalho. Você poderá buscar usuários e ver as estatísticas do seu servidor. Para detalhes sobre os aspectos operacionais do seu servidor, vá para o %{admin_panel}." + make_yourself_an_admin_info: "Você pode encontrar instruções na %{wiki}. Isso vai adicionar um link \"%{admin_dashboard}\", visível quando você entrar no sistema, ao seu menu de usuário, no cabeçalho. Você poderá buscar usuários e ver as estatísticas do seu servidor." report_bugs: "reporte-o" update_instructions: "instruções para atualizar na wiki da diaspora*" update_your_pod: "Atualize seu servidor" update_your_pod_info: "Você pode encontrar %{update_instructions}." invitation_codes: + already_logged_in: "%{inviter} te convidou para se juntar a este servidor, mas você já fez login." not_valid: "Esse código de convite expirou" invitations: - a_facebook_user: "Um usuário do Facebook" - check_token: - not_found: "Convite não encontrado." create: + closed: "Convites estão desativados neste servidor diaspora*." empty: "Por favor, insira ao menos um endereço de email." no_more: "Você não possui mais convites." note_already_sent: "Convites já foram enviados para: %{emails}" - rejected: "Houve problemas com os seguintes endereços de e-mail: " + rejected: "Os seguintes endereços de e-mail tiveram problemas: %{emails}" sent: "Convites enviados para: %{emails}" new: codes_left: @@ -616,6 +617,9 @@ pt-BR: profile: "Perfil" settings: "Configurações" toggle_navigation: "Alternar navegação" + likes: + create: + error: "Falha ao curtir." limited: "Limitado" more: "Mais" no_results: "Nenhum resultado encontrado" @@ -669,9 +673,15 @@ pt-BR: other: "%{actors} mencionaram você na publicação %{post_link}." zero: "%{actors} mencionou você na publicação %{post_link}." mentioned_deleted: - one: "%{actors} mencionou você em uma publicação apagada." - other: "%{actors} mencionaram você em uma publicação apagada." + one: "%{actors} mencionou você em uma publicação deletada." + other: "%{actors} mencionaram você em uma publicação deletada." zero: "%{actors} mencionou você em uma publicação apagada." + mentioned_in_comment: + one: "%{actors} mencionou você em um à publicação %{post_link}." + other: "%{actors} mencionaram você em um à publicação %{post_link}." + mentioned_in_comment_deleted: + one: "%{actors} mencionou você em um comentário deletado." + other: "%{actors} mencionaram você em um comentário deletado." post: "publicação" private_message: one: "%{actors} te enviou uma mensagem." @@ -702,6 +712,29 @@ pt-BR: confirm_email: click_link: "Para confirmar o seu novo endereço de email %{unconfirmed_email}, por favor clique neste link:" subject: "Por favor, ative o seu novo endereço de email %{unconfirmed_email}" + csrf_token_fail: + body: |- + Olá, %{name}, + + A diaspora* detectou uma tentativa de acessar a sua sessão que talvez não tenha sido autorizada. Para não arriscar comprometer os seus dados, encerramos sua sessão no sistema. Não se preocupe, você pode entrar com segurança agora. + + Uma solicitação foi feita usando um código CSRF incorreto ou inexistente. Pode não ser nada, mas também pode ser uma tentativa de falsificação de solicitação entre sites (CSRF, do inglês _cross-site request forgery_). + + Isso pode ter sido causado por: + +   - Um complemento manipulando o pedido ou fazendo pedidos sem o código; +   - Uma aba com uma sessão anterior deixada aberta; + - Outro site fazendo pedidos, com ou sem a sua permissão; + - Várias outras ferramentas externas; + - Código malicioso tentando acessar os seus dados. + + Para saber mais sobre falsificação de solicitação entre sites, veja [%{link}](%{link}). + + Se você receber essa mensagem várias vezes, por favor, verifique os itens acima, inclusive os complementos do navegador. + + Nossa equipe agradece. + diaspora* + subject: "Recebemos um pedido não autorizado da sua conta, %{name}" email_sent_by_diaspora: "Este email foi enviado por %{pod_name}. Se você deseja parar de receber emails como este," export_email: body: |- @@ -771,6 +804,9 @@ pt-BR: mentioned: limited_post: "Você foi mencionado em uma publicação privada." subject: "%{name} mencionou você em Diaspora*" + mentioned_in_comment: + limited_post: "Mencionaram você em um comentário a uma publicação limitada." + reply: "Responder ou ver esta conversa >" private_message: reply_to_or_view: "Responder ou visualizar esta conversa >" subject: "Há uma nova mensagem privada para você" @@ -856,14 +892,8 @@ pt-BR: type_error: "O envio da foto falhou. Tem certeza que a imagem é válida?" destroy: notice: "Foto apagada." - new_photo: - empty: "{file} está vazio, por favor, selecione os arquivos novamente." - invalid_ext: "{file} possui uma extensão inválida. Somente {extensions} são permitidos." - size_error: "{file} é muito grande, o tamanho máximo para arquivos é {sizeLimit}." new_profile_photo: upload: "Envie uma foto nova para o perfil!" - show: - show_original_post: "Ver publicação original" polls: votes: one: "Um voto até agora" @@ -947,8 +977,14 @@ pt-BR: destroyed: "A publicação foi destruída" failed: "Alguma coisa deu errado" title: "Visão Geral de Relatos" + unreviewed_reports: + one: "Há um relatório sem revisar." + other: "Há %{count} relatórios sem revisar." + zero: "Não há relatórios sem revisar." reshares: comment_email_subject: "publicação de %{author} recompartilhada por %{resharer}" + create: + error: "Falha ao recompartilhar." reshare: deleted: "A publicação original foi apagada pelo autor." reshare_confirmation: "Recompartilhar publicação de %{author}?" @@ -989,7 +1025,7 @@ pt-BR: one: "Em %{count} aspecto" other: "Em %{count} aspectos" invitations: - by_email: "Por email" + by_email: "Convidar pessoas por e-mail" invite_your_friends: "Convide seus Amigos" invites: "Convites" share_this: "Compartilhe este link via email, blog, ou redes sociais!" @@ -1123,6 +1159,7 @@ pt-BR: comment_on_post: "alguém comentar uma publicação sua" current_password: "Senha atual" current_password_expl: "o que você usa atualmente..." + default_post_visibility: "Aspectos selecionados para publicar por padrão" download_export: "Baixar o meu perfil" download_export_photos: "Baixar minhas fotos" edit_account: "Editar Conta" diff --git a/config/locales/diaspora/pt-PT.yml b/config/locales/diaspora/pt-PT.yml index da2cfbc4e..a0b2699cc 100644 --- a/config/locales/diaspora/pt-PT.yml +++ b/config/locales/diaspora/pt-PT.yml @@ -191,7 +191,6 @@ pt-PT: conversations: create: fail: "Mensagem inválida" - no_contact: "Cuidado, tem de adicionar primeiro um contacto!" sent: "A mensagem foi enviada" index: inbox: "Caixa de entrada" @@ -367,9 +366,6 @@ pt-PT: tutorials: "tutoriais" wiki: "wiki" invitations: - a_facebook_user: "Um utilizador do Facebook" - check_token: - not_found: "Código de convite não encontrado" create: empty: "Por favor insira pelo menos um endereço de email." no_more: "Não tem mais convites." @@ -546,14 +542,8 @@ pt-PT: type_error: "O envio da fotografia falhou. Tem a certeza que uma imagem foi adicionada?" destroy: notice: "Fotografia apagada." - new_photo: - empty: "{file} está vazio, por favor seleccione de novo os ficheiros sem este último." - invalid_ext: "{file} tem uma extensão inválida. Apenas são permitidas as extensões {extensions}." - size_error: "{file} é demasiado grande, o tamanho máximo é {sizeLimit}." new_profile_photo: upload: "Envie uma fotografia de perfil nova!" - show: - show_original_post: "Mostrar publicação original" posts: presenter: title: "Uma publicação de %{name}" diff --git a/config/locales/diaspora/ro.yml b/config/locales/diaspora/ro.yml index 06eedbab0..77303dc02 100644 --- a/config/locales/diaspora/ro.yml +++ b/config/locales/diaspora/ro.yml @@ -173,16 +173,12 @@ ro: be_who_you_want_to_be: "Fii cine vrei să fii" own_your_data: "Fii tu însăşi proprietarul datelor tale" podmin: - admin_panel: "panoul de administrator" contact_irc: "contactează-ne pe IRC" contribute: "Contribuie" create_an_account: "Crează-ţi contul." headline: "Bine ai venit, prietene." make_yourself_an_admin: "Devino administrator" invitations: - a_facebook_user: "Un utilizator Facebook" - check_token: - not_found: "Invitaţia nu a fost găsită" create: no_more: "Nu mai dispui de invitaţii." rejected: "Urmatoarele adrese de email au prezentat probleme:" @@ -346,14 +342,8 @@ ro: type_error: "Imaginea nu s-a incarcat cu succes. Sunteti sigur ca era o imagine?" destroy: notice: "Fotografie eliminată." - new_photo: - empty: "{file} este gol, incearcă să selectezi fişiere din nou fără acest fişier." - invalid_ext: "{file} are o extensie invalidă. Doar extensiile {extensions} sunt permise." - size_error: "{file} este prea mare, mărimea maximă a unui fişier este {sizeLimit}." new_profile_photo: upload: "Încarcă o fotografie de profil nouă!" - show: - show_original_post: "Afişează publicaţia originală" posts: presenter: title: "Un articol de la %{name}" diff --git a/config/locales/diaspora/ru.yml b/config/locales/diaspora/ru.yml index a6c2a5758..35403ac23 100644 --- a/config/locales/diaspora/ru.yml +++ b/config/locales/diaspora/ru.yml @@ -260,7 +260,6 @@ ru: conversations: create: fail: "Неверное сообщение" - no_contact: "Эй, вам нужно сначала добавить контакт!" sent: "Сообщение отправлено" destroy: delete_success: "Диалог успешно удален" @@ -526,7 +525,6 @@ ru: own_your_data: "Владелец ваших данных - вы" own_your_data_info: "Многие социальные сети используют ваши данные, чтобы делать деньги, анализируя ваши интересы и используя их для рекламирования вам вещей. диаспора* использует ваши данные только в той мере, в которой это необходимо для организации подключения и общения с другими людьми." podmin: - admin_panel: "административной панелью" byline: "Ты скоро изменишь Интернет. Давай подготовим тебя?" configuration_info: "Откройте %{database_path} и %{diaspora_path} в любимом текстовом редакторе и внимательно изучите. Они подробно прокомментированы." configure_your_pod: "Настроить ваш под" @@ -542,9 +540,6 @@ ru: invitation_codes: not_valid: "Код для приглашения уже не активен" invitations: - a_facebook_user: "Пользователь Facebook" - check_token: - not_found: "Код приглашения не найден" create: empty: "Пожалуйста введите хотя бы один адрес электронной почты." no_more: "У вас закончились приглашения." @@ -833,14 +828,8 @@ ru: type_error: "Сбой при загрузке фототрафии. Вы уверены, что добавили фотографию?" destroy: notice: "Фотография удалена." - new_photo: - empty: "{file} пуст, выберите пожалуйста файлы без него." - invalid_ext: "{file} имеет недопустимое расширение. Разрешены только {extensions}." - size_error: "{file} слишком большой, максимальный размер файла {sizeLimit}." new_profile_photo: upload: "Загрузить новое фото для профиля!" - show: - show_original_post: "Показать исходную запись" posts: presenter: title: "Запись %{name}" diff --git a/config/locales/diaspora/si.yml b/config/locales/diaspora/si.yml index 398ff4552..ea94d53e7 100644 --- a/config/locales/diaspora/si.yml +++ b/config/locales/diaspora/si.yml @@ -91,7 +91,6 @@ si: email: "විද්‍යුත් තැපෑල" find_people: "පුද්ගයින් සෙවීම හෝ #tags" invitations: - a_facebook_user: "Facebook පරිශීලකයෙක්" create: no_more: "ඔබ සතුව තවත් අරාධනාවන් නැත." new: diff --git a/config/locales/diaspora/sk.yml b/config/locales/diaspora/sk.yml index 9394322d1..aaceadb94 100644 --- a/config/locales/diaspora/sk.yml +++ b/config/locales/diaspora/sk.yml @@ -198,7 +198,6 @@ sk: conversations: create: fail: "Neplatná správa" - no_contact: "Pozor, najprv treba pridať kontakt!" sent: "Správa odoslaná" index: conversations_inbox: "Rozhovory – Poštová schránka" @@ -318,9 +317,6 @@ sk: tutorials: "návody" wiki: "wiki" invitations: - a_facebook_user: "Používateľ(ka) Facebooku" - check_token: - not_found: "Číslo pozvánky sa nenašlo" create: empty: "Zadajte, prosím, aspoň jednu e-mailovú adresu." no_more: "Nemáš žiadne nové pozvánky." @@ -505,14 +501,8 @@ sk: type_error: "Nepodarilo sa nahrať fotku. Určite si pridal(a) obrázok?" destroy: notice: "Fotka zmazaná." - new_photo: - empty: "Súbor {file} je prázdny; vyber, prosím, znova všetky súbory okrem tohto." - invalid_ext: "Súbor {file} má neplatnú príponu. Povolené sú len prípony {extensions}." - size_error: "Súbor {file} je príliš veľký, maximálna povolená veľkosť je {sizeLimit}." new_profile_photo: upload: "Nahrať novú profilovú fotku!" - show: - show_original_post: "Zobraziť pôvodný príspevok" posts: presenter: title: "Príspevok, ktorý napísal(a) %{name}" diff --git a/config/locales/diaspora/sl.yml b/config/locales/diaspora/sl.yml index 9f3de5e90..037411fdf 100644 --- a/config/locales/diaspora/sl.yml +++ b/config/locales/diaspora/sl.yml @@ -200,7 +200,6 @@ sl: conversations: create: fail: "Neveljavno sporočilo" - no_contact: "Hej, najprej moraš dodati stike!" sent: "Sporočilo poslano" index: inbox: "Prejeto" @@ -227,9 +226,6 @@ sl: fill_me_out: "Izpolni me" find_people: "Poišči ljudi ali #zaznamke" invitations: - a_facebook_user: "Facebook uporabnik" - check_token: - not_found: "Povabilo ni bilo najdeno" create: empty: "Prosim vnesite vsaj en elektronski poštni naslov." no_more: "Nimate več povabil." @@ -420,14 +416,8 @@ sl: type_error: "Nalaganje slike ni uspelo. Ste prepričani, da je bila dodana slika?" destroy: notice: "Slika izbrisana." - new_photo: - empty: "Datoteka {file} je prazna, prosimo ponovno izberite datoteke brez nje." - invalid_ext: "Datoteka {file} ni veljavna. Dovoljene so samo naslednje vrste datotek {extensions}." - size_error: "Datoteka {file} je prevelika, največja dovoljena velikost je {sizeLimit}." new_profile_photo: upload: "Naloži novo sliko profila!" - show: - show_original_post: "Prikaži originalno objavo" posts: presenter: title: "Objava osebe %{name}" diff --git a/config/locales/diaspora/sr.yml b/config/locales/diaspora/sr.yml index 685fb44a5..c1d622a8b 100644 --- a/config/locales/diaspora/sr.yml +++ b/config/locales/diaspora/sr.yml @@ -139,9 +139,6 @@ sr: fill_me_out: "Испуни ме" find_people: "Тражи људе или #тагове" invitations: - a_facebook_user: "Фејсбук корисник" - check_token: - not_found: "Токен позивнице није пронађен" create: no_more: "Немате више позивница." rejected: "Ове email адресе имају проблеме: " @@ -210,8 +207,6 @@ sr: notice: "Слика обрисана" new_profile_photo: upload: "Додајте нову профилну слику!" - show: - show_original_post: "Прикажи оригиналну објаву" privacy: "Приватност" profile: "Профил" profiles: diff --git a/config/locales/diaspora/sv.yml b/config/locales/diaspora/sv.yml index da01b223e..6d4e4c3a4 100644 --- a/config/locales/diaspora/sv.yml +++ b/config/locales/diaspora/sv.yml @@ -274,6 +274,8 @@ sv: post_something: "Dela på Diaspora*" cancel: "Avbryt" comments: + create: + error: "Lyckades inte kommentera." new_comment: comment: "Kommentera" commenting: "Kommenterar..." @@ -293,11 +295,11 @@ sv: user_search: "Användarsökning" spotlight: community_spotlight: "Gemenskapens rampljus" + no_members: "Det finns inga medlemmar än." suggest_member: "Föreslå en medlem" conversations: create: fail: "Ogiltigt meddelande" - no_contact: "Hallå där! Du måste först lägga till kontakten." sent: "Meddelandet har skickats" destroy: delete_success: "Konversationen har tagits bort" @@ -306,6 +308,7 @@ sv: conversations_inbox: "Konversationer – Inkorg" inbox: "Inkorg" new_conversation: "Ny konversation" + no_contacts: "Du behöver lägga till några kontakter innan du kan konversera." no_messages: "Inga meddelanden" new: message: "Meddelande" @@ -330,6 +333,7 @@ sv: delete: "Ta bort" email: "E-post" error_messages: + csrf_token_fail: "Ogiltigt CSRF-insegel. Vanligen logga in och försök igen." helper: correct_the_following_errors_and_try_again: "Rätta till följande fel och försök igen." need_javascript: "Denna webbplats behöver JavaScript för att fungera ordentligt. Har du inaktiverat JavaScript, får du vara så snäll att aktivera det och ladda om sidan." @@ -563,7 +567,6 @@ sv: own_your_data: "Du äger din data" own_your_data_info: "Många nätverk använder din data för att tjäna pengar genom att analysera dig och använda din data för att sälja reklam riktad mot dig. Diaspora* använder inte din data för något annat än att låta dig kommunicera med andra." podmin: - admin_panel: "administratörspanel" byline: "Du är just på väg att förändra Internet. Är du redo för att komma igång?" configuration_info: "Öppna %{database_path} och %{diaspora_path} i en textredigerare och gå igenom dem noggrant. De är fyllda med kommentarer." configure_your_pod: "Konfigurera din pod" @@ -577,22 +580,21 @@ sv: getting_help_info: "Vi har listat några %{faq} med ytterligare råd och problemlösningar för de främsta problemen. Du är även välkommen på %{irc}." headline: "Välkommen, vän." make_yourself_an_admin: "Gör dig till administratör" - make_yourself_an_admin_info: "Du hittar instruktioner på %{wiki}. Detta skapar en administratörslänk i din användarmeny när du har loggat in. Där ges du verktyg för att söka och finna statistik för din pod. För fler detaljer om driftaspekterna för din pod, gå till %{admin_panel}." + make_yourself_an_admin_info: "Du hittar instruktioner på %{wiki}. Detta ger en %{admin_dashboard}-länk i din användarmeny efter att du har loggat in. Via den kommer du till verktyg för att söka och finna statistik för din pod." report_bugs: "rapportera dem" update_instructions: "uppdateringsinstruktioner från Diasporawikin." update_your_pod: "Uppdatera din pod" update_your_pod_info: "Du finner %{update_instructions}" invitation_codes: + already_logged_in: "Du är inbjuden att gå med denna pod av %{inviter}, men det tycks som att du redan är inloggad." not_valid: "Inbjudningskoden är inte längre giltig." invitations: - a_facebook_user: "En Facebookanvändare" - check_token: - not_found: "Inbjudan kan inte hittas" create: + closed: "Inbjudningar är inte längre möjliga till denna Diaspora*-pod." empty: "Var snäll och ange minst en e-postadress." no_more: "Du har inga fler inbjudningar." note_already_sent: "Inbjudningar har redan skickats till: %{emails}" - rejected: "Det är problem med följande e-postadresser: " + rejected: "Det är problem med följande e-postadresser: %{emails}" sent: "Inbjudningarna har skickats till: %{emails}" new: codes_left: @@ -621,6 +623,9 @@ sv: profile: "Profil" settings: "Inställningar" toggle_navigation: "Skifta navigation" + likes: + create: + error: "Lyckades inte gilla." limited: "Begränsad" more: "Mer" no_results: "Inga sökresultat" @@ -654,7 +659,7 @@ sv: mark_all_shown_as_read: "Märk allt som läst" mark_read: "Lästmärk" mark_unread: "Markera som oläst" - mentioned: "Omnämnd" + mentioned: "Omnämnd i inlägg" no_notifications: "Du har inga notifikationer än." notifications: "Notiser" reshared: "Återdelad" @@ -676,7 +681,7 @@ sv: mentioned_deleted: one: "%{actors} har nämnt dig i ett raderat inlägg." other: "%{actors} har nämnt dig i ett raderat inlägg." - zero: "Ingen inlägg där du är nämnd har raderats." + zero: "inga inlägg där du är nämnd har raderats." post: "inlägg" private_message: one: "%{actors} har skickat dig ett meddelande." @@ -707,6 +712,27 @@ sv: confirm_email: click_link: "För att aktivera din nya e-postadress %{unconfirmed_email}, klicka här:" subject: "Var vänlig och aktivera din nya e-postadress %{unconfirmed_email}" + csrf_token_fail: + body: |- + Hej, %{name}. + + Diaspora* har märkt av ett potentiellt oauktoriserat försökt tilla tt komma åt din session. För att undkomma att din data själs, har du loggats ut. Räds icke; du kan nu logga in säkert igen. + + En förfrågan med ogiltigt eller helt saknar CSRF-insegel. Det skulle kunna vara helt oskyldigt, men det skulle kunna vara ett försökt av en sida att låtsas vara en annan sida (s.k. "cross-site request forgery", CSRF). En sådan kan vara orsakat av: + + - Ett tillägg som manipulerar förfrågningar eller gör förfrågningar utan insegel; + - En flik från tidigare session finns kvar i webbläsaren; + - En annan hemsida gör en förfrågan, med eller utan din tillåtelse; + - Diverse externa verktyg; + - Försmädlig kod som vill komma åt din data. + + För mer information om CSRF: [%{link}](%{link}). + + Om du får detta meddelande fler gånger, får du se över om det kan vara orsakat av någon av punkterna ovanför. + + Tack ska du ha! + Med vänlig hälsning, Diasporas e-postrobot. + subject: "Vi har fått en oauktoriserad förfrågan från ditt konto, %{name}." email_sent_by_diaspora: "Detta e-brev har skickats av %{pod_name}. Vill du inte få några fler liknade e-brev," export_email: body: |- @@ -864,14 +890,8 @@ sv: type_error: "Fotouppladdning misslyckades. Är du säker på att en bild blev tillagd?" destroy: notice: "Fotot är borttaget." - new_photo: - empty: "{file} är tom, välj om filerna utan att välja denna." - invalid_ext: "{file} har en ogiltig filändelse. Endast {extensions} är tillåtna." - size_error: "{file} är för stor, maximal tillåten filstorlek är {sizeLimit}." new_profile_photo: upload: "Ladda upp en ny profilbild!" - show: - show_original_post: "Visa det ursprungliga inlägget" polls: votes: one: "En röst än så länge." @@ -958,8 +978,14 @@ sv: destroyed: "Inlägget har förintats" failed: "Någonting gick snett" title: "Översikt av anmälningar" + unreviewed_reports: + one: "Det finns en rapport att gå igenom." + other: "Det finns %{count} rapporter att gå igenom." + zero: "Det finns inga rapporter att gå igenom." reshares: comment_email_subject: "%{resharer} har delat vidare ett inlägg av %{author}" + create: + error: "Lyckades inte dela vidare." reshare: deleted: "Det ursprungliga inlägget är raderat." reshare_confirmation: "Vill du dela vidare %{author}s inlägg?" @@ -997,14 +1023,10 @@ sv: mobile_row_checked: "%{name} (ta bort)" mobile_row_unchecked: "%{name} (lägg till)" toggle: - few: "I %{count} aspekter" - many: "I %{count} aspekter" one: "I %{count} aspekt" other: "I %{count} aspekter" - two: "I %{count} aspekter" - zero: "Lägg till kontakt" invitations: - by_email: "Via e-post" + by_email: "Bjud in personer via e-post" invite_your_friends: "Bjud in dina vänner" invites: "Inbjudningar" share_this: "Dela med dig av länken via e-post, din blog eller de sociala nätverken!" @@ -1138,6 +1160,7 @@ sv: comment_on_post: "någon kommenterar dina inlägg" current_password: "Nuvarande lösenord" current_password_expl: "den som du loggar in med..." + default_post_visibility: "Standardaspekt vald för inlägg." download_export: "Ladda ned min profil" download_export_photos: "Ladda ned mina bilder" edit_account: "Ändra konto" diff --git a/config/locales/diaspora/te.yml b/config/locales/diaspora/te.yml index f4deec27b..b937a69ce 100644 --- a/config/locales/diaspora/te.yml +++ b/config/locales/diaspora/te.yml @@ -208,7 +208,6 @@ te: conversations: create: fail: "చెల్లని సందేశం" - no_contact: "ఓయ్, ముందుగా మీరు పరిచయాన్ని జతచేసుకోవాలి!" sent: "సందేశం పంపబడింది" destroy: delete_success: "సంభాషణ విజయవంతంగా తొలగించబడింది" @@ -339,9 +338,6 @@ te: tutorials: "ఉపశిక్షణ" wiki: "వికీ" invitations: - a_facebook_user: "ఫేస్‌బుక్ వాడుకరి" - check_token: - not_found: "ఆహ్వాన టోకెన్ కనపడలేదు" create: empty: "దయచేసి ఒక్క ఈమెయిలు చిరునామానైనా ఇవ్వండి." no_more: "మీకు ఆహ్వానాలేమీ లేవు." @@ -554,14 +550,8 @@ te: type_error: "ఛాయాచిత్ర ఎక్కింపు విఫలమైంది. మీరు ఖచ్ఛితంగా బొమ్మనే జోడించారా?" destroy: notice: "ఛాయాచిత్రం తొలగించబడింది" - new_photo: - empty: "{file} ఖాళీగావుంది, దయచేసి అదికాకుండా వేరే దస్త్రాలను ఎంచుకోండి." - invalid_ext: "{file} చెల్లని పొడిగింతను కలిగివుంది. కేవలం {extensions} మాత్రమే అనుమతించబడును." - size_error: "{file} చాలా పెద్దగావుంది, గరిష్ట దస్త్ర పరిమాణం {sizeLimit}." new_profile_photo: upload: "ఒక కొత్త ప్రవర ఛాయాచిత్రాన్ని ఎక్కించండి!" - show: - show_original_post: "అసలు టపాని చూపించు" posts: presenter: title: "%{name} నుండి ఒక టపా" diff --git a/config/locales/diaspora/tr.yml b/config/locales/diaspora/tr.yml index bcb9ef223..eb469b976 100644 --- a/config/locales/diaspora/tr.yml +++ b/config/locales/diaspora/tr.yml @@ -195,7 +195,6 @@ tr: conversations: create: fail: "Geçersiz mesaj" - no_contact: "Hey, önce bir bağlantı ekleyin!" sent: "Mesaj gönderildi" index: conversations_inbox: "Yazışmalar — Gelen kutusu" @@ -288,6 +287,8 @@ tr: title: "Anılmalar" what_is_a_mention_q: "\"Birisini anmak\" nedir?" miscellaneous: + diaspora_app_a: "Toplıluk üyelerince çeşitli Android uygulamaları geliştirilmektedir. Bazıları çoktan terk edlimiş ve mevcut diaspora* yazılımına uygun değildir. Bunlardan çok bir şey beklemeyin. Şu an için bir iOS uygulaması yok. diaspora*ya mobilden erişmenin en iyi yolu bir tarayıcı, çünkü mobil siteyi tüm cihazlarda, işlevselliği henüz tam olmamakla birlikte, düzgün çalışacak şekilde tasarladık." + diaspora_app_q: "Android ve iOS için diaspora* uygulamaları var mı?" title: "Çeşitli" pods: find_people_a: "Kenar çubuğundaki e-mektup bağlantısına tıklayın. İlgi alanlarınızı paylaşan kişileri #etiketler ile takip edin, ve onlardan ilgilendiğiniz şeyler gönderenleri bir bakışa ekleyin. Genel bir gönderide #buradayeniyim diye bağırın." @@ -327,6 +328,8 @@ tr: private_profiles: title: "Özel profiller" whats_in_profile_q: "Ne benim özel profil var?" + who_sees_profile_a: "Paylaşımda bulunduğunuz (bakışlarınızdan birinde olan) her hangi kullanıcı, adıyla girdiğinde görebilir. Ancak sizin takip etmediğiniz takipçiler, ancak herkese açık bilgilerinizi görür." + who_sees_profile_q: "Özel profilimi kimler görür?" who_sees_updates_a: "Bakışlarınızdaki herkes özel profilinizdeki değişiklikleri görebilir. " who_sees_updates_q: "Özel profilimin güncelllemelerini kim görebilir?" public_posts: @@ -348,13 +351,11 @@ tr: what_are_tags_for_a: "Etiketler gönderileri, genellikle konularına göre, sınıflandırmanın bir yoludur. Bir etiketi aratarak onu içeren tüm görebileceğiniz gönderileri (genel ve özel) bulabilirsiniz. Bu belli bir konu ile ilgilenenlerin onunla ilgili genel gönderileri bulabilmesini sağlar." what_are_tags_for_q: "Etiketler ne işe yarar?" third_party_tools: "üçüncü taraf araçları" + title_header: "Yardım" tutorial: "öğretici" tutorials: "öğreticiler" wiki: "wiki" invitations: - a_facebook_user: "Bir Facebook kullanıcısı" - check_token: - not_found: "Davetiye bulunamadı." create: empty: "En az bir e-posta adresi girin." no_more: "Başka davetiyeniz yok." @@ -402,6 +403,8 @@ tr: other: "%{actors} %{post_link} gönderinizi yorumladı." zero: "%{actors} %{post_link} gönderinizi yorumladı." index: + all_notifications: "Tüm bildirimler" + also_commented: "Bunlar da yorumladı" and: "ve" and_others: other: "ve %{count} diğer kişi" @@ -411,6 +414,8 @@ tr: mark_read: "Okundu" mark_unread: "Okunmadı olarak işaretle" notifications: "Bildirimler" + show_all: "Tümünü göster" + show_unread: "Okunmamışları göster" liked: other: "%{actors} senin %{post_link} gönderini beğendi." zero: "%{actors} senin %{post_link} gönderini beğendi." @@ -491,6 +496,10 @@ tr: diaspora* elektronik mektup robotu [1]: %{url} + subject: "Yeni %{type} ağır dil olarak işaretlendi" + type: + comment: "yorum" + post: "gönderi" reshared: reshared: "%{name} gönderini tekrar paylaştı" view_post: "Gönderiyi görüntüle>" @@ -509,6 +518,7 @@ tr: add_contact: invited_by: "tarafından davet edildin" index: + couldnt_find_them: "Aradığını bulamadın mı?" looking_for: "%{tag_link} ile etiketlenmiş gönderileri mi arıyorsun?" no_one_found: "...ve hiç kimse bulunamadı." no_results: "Hey! Bir şeyi araman lazım." @@ -534,14 +544,8 @@ tr: type_error: "Fotoğraf yüklemesi başarısız oldu. Bir görüntünün eklendiğinden emin misin?" destroy: notice: "Fotoğraf silindi." - new_photo: - empty: "{file} boş bir dosya, bu olmadan dosyaları tekrar seçin." - invalid_ext: "{file} geçersiz uzantıya sahip. sadece {extensions} uzantılarına izin verilir." - size_error: "{file} çok büyük, en büyük dosya boyutu {sizeLimit}." new_profile_photo: upload: "Yeni bir profil fotoğrafı yükle!" - show: - show_original_post: "Orijinal gönderiyi göster" posts: presenter: title: "%{name} 'den bir gönderi" @@ -594,6 +598,12 @@ tr: terms: "Bir hesap oluşturarak %{terms_link}'teki koşulları kabul etmiş sayılırsınız." terms_link: "hizmet koşulları" username: "KULLANICI ADI" + report: + comment_label: "Yorum:
%{data}" + post_label: "Gönderi: %{title}" + reason_label: "Sebep: %{text}" + reported_label: "%{person} raporladı" + title: "Raporlara bakış" reshares: comment_email_subject: "%{resharer}, %{author} kişisinin gönderisini tekrar paylaştı" reshare: @@ -647,6 +657,8 @@ tr: i_like: "İlgimi çeken şunlardır: %{tags}." invited_by: "Davet için teşekkürler, " newhere: "YeniyimBurada" + poll: + add_a_poll: "Oylama ekle" posting: "Gönderiliyor..." share: "Paylaş" upload_photos: "Fotoğraf yükle" diff --git a/config/locales/diaspora/uk.yml b/config/locales/diaspora/uk.yml index 980cbd7e7..a4c8562b2 100644 --- a/config/locales/diaspora/uk.yml +++ b/config/locales/diaspora/uk.yml @@ -240,7 +240,6 @@ uk: conversations: create: fail: "Неправильне повідомлення" - no_contact: "Ей, вам потрібно спочатку додати контакт!" sent: "Повідомлення відправлене" destroy: delete_success: "Діалог успішно видалений" @@ -481,9 +480,6 @@ uk: tutorials: "настанови" wiki: "вікі" invitations: - a_facebook_user: "Користувач Facebook" - check_token: - not_found: "Код запрошення не знайдений" create: empty: "Будь-ласка, введіть хоча б одну електронну пошту." no_more: "У вас закінчилися запрошення." @@ -760,14 +756,8 @@ uk: type_error: "Збій при завантаженні світлини. Ви впевнені, що додали графічний файл?" destroy: notice: "Фотографію вилучено." - new_photo: - empty: "{file} порожній, будь ласка, виберіть файли ще раз, але без нього." - invalid_ext: "{file} має неприпустиме розширення. Дозволені тільки {extensions}." - size_error: "{file} занадто великий, максимальний розмір файлу: {sizeLimit}." new_profile_photo: upload: "Завантажити нове фото для профілю!" - show: - show_original_post: "Показати початковий запис" posts: presenter: title: "Запис %{name}" diff --git a/config/locales/diaspora/vi.yml b/config/locales/diaspora/vi.yml index 610d783f5..ebb1e2a7b 100644 --- a/config/locales/diaspora/vi.yml +++ b/config/locales/diaspora/vi.yml @@ -176,7 +176,6 @@ vi: conversations: create: fail: "Tin nhắn không hợp lệ" - no_contact: "Bạn cần phải thêm liên lạc trước đã!" sent: "Đã gửi tin nhắn" index: inbox: "Hộp thư đến" @@ -211,9 +210,6 @@ vi: tutorials: "hướng dẫn" wiki: "wiki" invitations: - a_facebook_user: "Người dùng Facebook" - check_token: - not_found: "Không tìm thấy khoá mời" create: empty: "Nhập ít nhất một địa chỉ thư điện tử." no_more: "Bạn đã hết thư mời." @@ -371,14 +367,8 @@ vi: type_error: "Tải ảnh lên thất bại, Bạn có chắc ảnh đã được thêm?" destroy: notice: "Đã xóa ảnh." - new_photo: - empty: "{file} rỗng, chọn lại tập tin." - invalid_ext: "{file} có phần mở rộng không hợp lệ. Chỉ chấp nhận phần mở rộng {extensions}." - size_error: "{file} quá to, dung lượng tối đa cho phép là {sizeLimit}." new_profile_photo: upload: "Tải lên ảnh mới" - show: - show_original_post: "Xem bài đăng gốc" posts: presenter: title: "Một bài đăng từ %{name}" diff --git a/config/locales/diaspora/wo.yml b/config/locales/diaspora/wo.yml index 20f4ee371..c5733f30d 100644 --- a/config/locales/diaspora/wo.yml +++ b/config/locales/diaspora/wo.yml @@ -44,7 +44,6 @@ wo: to: "ci" email: "Email" invitations: - a_facebook_user: "Facebooku jëfandikukat" new: language: "Làkk" layouts: diff --git a/config/locales/diaspora/zh-CN.yml b/config/locales/diaspora/zh-CN.yml index 00266f409..de8ef9955 100644 --- a/config/locales/diaspora/zh-CN.yml +++ b/config/locales/diaspora/zh-CN.yml @@ -200,9 +200,6 @@ zh-CN: fill_me_out: "补全信息" find_people: "找人或#标签" invitations: - a_facebook_user: "Facebook 用户" - check_token: - not_found: "找不到该邀请码" create: empty: "请至少填写一个邮箱" no_more: "您暂无邀请函。" @@ -350,14 +347,8 @@ zh-CN: type_error: "照片上传失败。您确定有选择任何图片吗?" destroy: notice: "照片删除成功。" - new_photo: - empty: "文件 {file} 是空的,请重新选择文件,并且不要选中它。" - invalid_ext: "不支持文件 {file} 的格式。只接受 {extensions}。" - size_error: "文件 {file} 太大了,上限是 {sizeLimit}。" new_profile_photo: upload: "上传新的头像!" - show: - show_original_post: "显示原文" posts: presenter: title: "来自 %{name} 的内容" diff --git a/config/locales/diaspora/zh-TW.yml b/config/locales/diaspora/zh-TW.yml index 292a4ca6c..949386af9 100644 --- a/config/locales/diaspora/zh-TW.yml +++ b/config/locales/diaspora/zh-TW.yml @@ -267,6 +267,8 @@ zh-TW: post_something: "貼到 diaspora*" cancel: "取消" comments: + create: + error: "發表意見失敗。" new_comment: comment: "留言" commenting: "發表留言中..." @@ -291,7 +293,6 @@ zh-TW: conversations: create: fail: "無效的訊息" - no_contact: "喂,你要先加聯絡人才行!" sent: "訊息送出去了" destroy: delete_success: "對話成功刪掉了" @@ -300,6 +301,7 @@ zh-TW: conversations_inbox: "對話 - 收訊匣" inbox: "收訊匣" new_conversation: "開始對話" + no_contacts: "開始對話前必須先加一些聯絡人" no_messages: "沒有訊息" new: message: "訊息" @@ -324,6 +326,7 @@ zh-TW: delete: "刪除" email: "電子信箱" error_messages: + csrf_token_fail: "CSRF 信物不正確。請重新登入後再重試一次。" helper: correct_the_following_errors_and_try_again: "請修正以下錯誤後再試一次。" need_javascript: "這個網站需要 JavaScript 功能才能正常運作。如果你關掉了 JavaScript 的話,請打開它後重新載入網頁來使用。" @@ -557,7 +560,6 @@ zh-TW: own_your_data: "控制自己的資料" own_your_data_info: "很多社群網路用你的資料來賺錢,像是分析使用行為,然後用這些資訊來對你做廣告推銷。diaspora* 只會用你的資料來讓你和別人聯繫和分享,不會拿來做其他用途。" podmin: - admin_panel: "管理面板" byline: "準備來改變網際網路了。我們來幫你準備就緒,好嗎?" configuration_info: "請用你慣用的編輯器,打開設定檔 %{database_path} 以及 %{diaspora_path},仔細檢查並修改它們,裡面有很詳細的註解。" configure_your_pod: "設定豆莢" @@ -571,22 +573,21 @@ zh-TW: getting_help_info: "我們在維基上整理了%{faq},包含一些訣竅、花招、以及常見問題的解法。同時也歡迎%{irc}。" headline: "歡迎你來,朋友。" make_yourself_an_admin: "成為管理員" - make_yourself_an_admin_info: "%{wiki}裡面有步驟說明。做完之後,在你登入時頂部的使用者功能表應該就會多一個「管理」項目。這個功能可以讓你搜尋豆莢裡的使用者、檢視統計資料等等。更深度的豆莢維運項目請用%{admin_panel}。" + make_yourself_an_admin_info: "%{wiki}裡面有步驟說明。設定完成之後,在你登入時頂部的使用者功能表應該就會多一個「%{admin_dashboard}」項目。這個功能可以讓你搜尋豆莢裡的使用者、檢視統計資料等等。" report_bugs: "回報" update_instructions: "在 diaspora* 維基上的更新步驟說明" update_your_pod: "更新豆莢" update_your_pod_info: "這是%{update_instructions}。" invitation_codes: + already_logged_in: "%{inviter}邀請你加入這個豆莢,不過其實你已經加入且登入了。" not_valid: "邀請碼已經失效了" invitations: - a_facebook_user: "Facebook 使用者" - check_token: - not_found: "找不到該邀請信物" create: + closed: "這個 diaspora* 豆莢目前不開放邀請。" empty: "請輸入至少一個電子信箱" no_more: "你沒有邀請卡了。" note_already_sent: "邀請卡已經寄到這些信箱了:%{emails}" - rejected: "以下的電子信箱有問題:" + rejected: "以下的電子信箱有問題:%{emails}" sent: "邀請卡已經寄到這些信箱了:%{emails}" new: codes_left: @@ -614,6 +615,9 @@ zh-TW: profile: "個人檔案" settings: "設定" toggle_navigation: "瀏覽模式切換" + likes: + create: + error: "按讚失敗。" limited: "受限" more: "更多" no_results: "搜尋沒有結果" @@ -689,6 +693,26 @@ zh-TW: confirm_email: click_link: "請點以下連結,來開通你新的電子信箱 %{unconfirmed_email}:" subject: "請開通你新的電子信箱 %{unconfirmed_email}" + csrf_token_fail: + body: |- + %{name}你好, + + diaspora* 偵測到可能是未經授權而試圖存取你的登入狀態的行為。雖然這有可能無害,但也有可能是跨網站的偽造請求(cross-site request forgery; CSRF)。為了防止你的資料可能會外洩,我們就將你登出了。 + + 造成資料請求中沒有 CSRF 信物,或是該信物不正確的情形可能有: + - 有瀏覽器附加元件修改了資料請求,或是發出了沒有該信物的請求; + - 有之前登入的分頁或是視窗沒有關閉; + - 有其他網站發出了資料請求,不論是否經過你的同意; + - 其他外部工具造成; + - 有惡意程式試圖要存取你的資料; + 有關 CSRF 的更多資訊請見[%{link}](%{link})。 + + 不用擔心,現在你還是可以安全地重新登入。 + 但是如果你持續收到這個訊息,請檢查以上因素,包含你所使用的瀏覽器附加元件。 + + 謝謝。 + diaspora* 電郵機器人 + subject: "%{name},我們偵測到你的帳號有未授權的請求" email_sent_by_diaspora: "這封電子郵件是從 %{pod_name} 寄出。如果你不想再收到這類的信件," export_email: body: |- @@ -830,14 +854,8 @@ zh-TW: type_error: "相片上傳失敗。你確定有加入任何圖片嗎?" destroy: notice: "相片刪掉了。" - new_photo: - empty: "檔案 {file} 是空的,請重新挑選檔案,且不要再選它。" - invalid_ext: "檔案 {file} 的副檔名不合格。只接受{extensions}。" - size_error: "檔案 {file} 太大了,上限是{sizeLimit}。" new_profile_photo: upload: "上傳新的個人照!" - show: - show_original_post: "顯示原文" polls: votes: other: "目前為止有%{count}個人投票" @@ -918,8 +936,13 @@ zh-TW: destroyed: "貼文已經被銷毀了" failed: "發生問題了" title: "回報總覽" + unreviewed_reports: + other: "有%{count}份還沒看過的回報。" + zero: "沒有還沒看過的回報。" reshares: comment_email_subject: "%{resharer} 轉貼了 %{author} 的貼文" + create: + error: "轉貼失敗。" reshare: deleted: "原貼文已經被作者刪除了。" reshare_confirmation: "要轉貼 %{author} 的貼文嗎?" @@ -960,7 +983,7 @@ zh-TW: other: "在%{count}個社交面中" zero: "加聯絡人" invitations: - by_email: "用電子郵件" + by_email: "寄電子郵件邀請" invite_your_friends: "邀請你的朋友" invites: "邀請" share_this: "將這個連結透過電子郵件、部落格,或其他社交網站分享出去!" @@ -1093,6 +1116,7 @@ zh-TW: comment_on_post: "有人留言在你的貼文" current_password: "目前密碼" current_password_expl: "登入時那一個..." + default_post_visibility: "預設貼文發表的社交面" download_export: "下載個人檔案" download_export_photos: "下載相片" edit_account: "編輯帳號" diff --git a/config/locales/javascript/javascript.ar.yml b/config/locales/javascript/javascript.ar.yml index e332f0387..df5fe3c59 100644 --- a/config/locales/javascript/javascript.ar.yml +++ b/config/locales/javascript/javascript.ar.yml @@ -32,9 +32,7 @@ ar: contacts: search_no_results: "لم يُعثر على متراسلين" delete: "احذف" - failed_to_like: "فشل في [أعجبني]" failed_to_post_message: "فشل في نشر رسالة!" - failed_to_reshare: "فشلت إعادة المشاركة!" getting_started: alright_ill_wait: "حسناً ، سأنتظر." hey: "انتبه <%= name %>" @@ -63,8 +61,6 @@ ar: limited: "محدودة - مشاركتك ستكون متاحة لجهات إتصالك فقط" public: "عام - مشاركتك ستكون متاحة للجميع ومفهرسة في محركات البحث" remove_post: "أأزيل هذه التدوينة؟" - reshares: - duplicate: "رائع، أليس كذلك؟ أعدت نشر هذه المشاركة مسبقا" show_more: "المزيد" stream: comment: "تعليق" diff --git a/config/locales/javascript/javascript.bg.yml b/config/locales/javascript/javascript.bg.yml index 53d1e1c8c..eacbf1d02 100644 --- a/config/locales/javascript/javascript.bg.yml +++ b/config/locales/javascript/javascript.bg.yml @@ -26,7 +26,6 @@ bg: show: "показване на коментарите" confirm_dialog: "Сигурни ли сте?" delete: "Изтриване" - failed_to_like: "Публикацията не бе харесана!" failed_to_post_message: "Съобщението не бе публикувано!" getting_started: alright_ill_wait: "Добре, ще изчакам." @@ -52,8 +51,6 @@ bg: publisher: limited: "Ограничено - публикацията ще бъде видима само за хората, с които я споделите" public: "Публично - публикацията ще бъде видима за всеки, а съдържанието ѝ ще бъде налично за търсещите машини" - reshares: - duplicate: "Вече сте споделили публикацията!" show_more: "покажи още" stream: comment: "Коментиране" diff --git a/config/locales/javascript/javascript.br.yml b/config/locales/javascript/javascript.br.yml index 1cee93040..304b3b67a 100644 --- a/config/locales/javascript/javascript.br.yml +++ b/config/locales/javascript/javascript.br.yml @@ -32,7 +32,6 @@ br: confirm_dialog: "Ha sur oc'h ?" delete: "Diverkañ" edit: "Kemmañ" - failed_to_like: "C'hwitet merkañ plijus !" failed_to_post_message: "N'eus ket bet gallet embann ar gemennadenn !" failed_to_remove: "N'eus ket bet gallet lemel en enmont kuit !" getting_started: @@ -97,7 +96,6 @@ br: option: "Dibarzh <%= nr %>" question: "Goulenn" reshares: - duplicate: "Kaset eo bet an destenn-mañ pelloc'h ganeoc'h c'hoazh !" post: "Rannañ pelloc'h embannadenn <%= name %> ?" successful: "Rannet pelloc'h eo bet an embannadenn ervat !" show_more: "Gwelet muioc'h" diff --git a/config/locales/javascript/javascript.bs.yml b/config/locales/javascript/javascript.bs.yml index 543188d27..00545875f 100644 --- a/config/locales/javascript/javascript.bs.yml +++ b/config/locales/javascript/javascript.bs.yml @@ -34,7 +34,6 @@ bs: confirm_dialog: "Jeste sigurni?" delete: "Izbriši" edit: "Uredi" - failed_to_like: "Neuspješno sviđanje" failed_to_post_message: "Neuspješno objavljivanje poruke!" getting_started: alright_ill_wait: "Dobro, čekat ću." @@ -72,7 +71,6 @@ bs: near_from: "Objavljeno sa: <%= location %>" public: "Javno - vaša objava će biti vidljiva svima i može biti pronađena od pretraživača" reshares: - duplicate: "Tako dobro, ha? Već ste ponovo dijelili tu objavu!" post: "Ponovo dijeli objavu od <%= name %>?" successful: "Objava je uspješno ponovo dijeljenja!" show_more: "pokaži više" diff --git a/config/locales/javascript/javascript.cs.yml b/config/locales/javascript/javascript.cs.yml index a80f67c44..03849bf46 100644 --- a/config/locales/javascript/javascript.cs.yml +++ b/config/locales/javascript/javascript.cs.yml @@ -102,10 +102,8 @@ cs: create: "Vytvořit" delete: "Odstranit" edit: "Upravit" - failed_to_like: "Oblíbení se nezdařilo!" failed_to_post_message: "Odeslání příspěvku se nezdařilo!" failed_to_remove: "Odstranění záznamu selhalo!" - failed_to_reshare: "Znovusdílení selhalo" getting_started: alright_ill_wait: "Dobrá, počkám." hey: "Ahoj, <%= name %>!" @@ -228,7 +226,6 @@ cs: created: "Zpráva byla úspěšně založena" exists: "Zpráva již existuje" reshares: - duplicate: "Tento příspěvek už sdílíte!" post: "Sdílet příspěvek uživatele <%= name %>?" successful: "Příspěvek je sdílen!" show_more: "zobrazit více" diff --git a/config/locales/javascript/javascript.cy.yml b/config/locales/javascript/javascript.cy.yml index 4481192eb..a680b3f73 100644 --- a/config/locales/javascript/javascript.cy.yml +++ b/config/locales/javascript/javascript.cy.yml @@ -27,7 +27,6 @@ cy: hide: "cuddio sylwadau" show: "ddangos sylwadau i gŷd" confirm_dialog: "Chi'n siwr?" - failed_to_like: "Wedi methu i hoffi!" failed_to_post_message: "Methwyd i bostio neges!" getting_started: alright_ill_wait: "O'r gorau - 'dwi'n aros..." @@ -38,8 +37,6 @@ cy: search: "Find people or #tags" photo_uploader: looking_good: "OMG, rydych chi'n ymddangos yn neis iawn!" - reshares: - duplicate: "Mae hynny'n dda, eh? Rydych chi wedi rhannu'r bost eisoes!" show_more: "dangos mwy" stream: likes: diff --git a/config/locales/javascript/javascript.da.yml b/config/locales/javascript/javascript.da.yml index 173731002..d33d27aa4 100644 --- a/config/locales/javascript/javascript.da.yml +++ b/config/locales/javascript/javascript.da.yml @@ -110,11 +110,8 @@ da: create: "Opret" delete: "Slet" edit: "Rediger" - failed_to_comment: "Din kommentar blev ikke lagt op. Måske ignorerer indlæggets ophavsmand dig?" - failed_to_like: "Kunne ikke synes om! Måske ignorere ophavsmanden dig?" failed_to_post_message: "Kunne ikke indsende besked!" failed_to_remove: "Det lykkedes ikke at fjerne indlægget!" - failed_to_reshare: "Kunne ikke dele indlægget!" getting_started: alright_ill_wait: "Okay, jeg venter." hey: "Hej <%= name %>!" @@ -235,7 +232,6 @@ da: created: "Der blev lavet en rapport" exists: "Der eksisterer allerede en rapport" reshares: - duplicate: "Du har allerede delt indlægget!" post: "Videredel <%= name %>s indlæg?" successful: "Indlægget er blevet videredelt!" show_more: "Vis mere" diff --git a/config/locales/javascript/javascript.de-CH.yml b/config/locales/javascript/javascript.de-CH.yml new file mode 100644 index 000000000..829a7a4ec --- /dev/null +++ b/config/locales/javascript/javascript.de-CH.yml @@ -0,0 +1,36 @@ +# Copyright (c) 2010-2013, Diaspora Inc. This file is +# licensed under the Affero General Public License version 3 or later. See +# the COPYRIGHT file. + + + +de-CH: + javascripts: + timeago: + day: "eim Tag" + days: + one: "eim Tag" + other: "%d Täg" + hour: "öpe einere Stund" + hours: + one: "öpe einere Stund" + other: "öpe %d Stunde" + inPast: "jede Moment" + minute: "öpe einere Minute" + minutes: + one: "einere Minute" + other: "%d Minute" + month: "öpe eim Monet" + months: + one: "eim Monet" + other: "%d Mönet" + prefixAgo: "vor" + prefixFromNow: "i" + seconds: "weniger als einere Minute" + suffixAgo: "" + suffixFromNow: "ab jetzt" + wordSeparator: " " + year: "öpe eim Johr" + years: + one: "eim Johr" + other: "%d Johr" \ No newline at end of file diff --git a/config/locales/javascript/javascript.de.yml b/config/locales/javascript/javascript.de.yml index f37afc57a..2629178ae 100644 --- a/config/locales/javascript/javascript.de.yml +++ b/config/locales/javascript/javascript.de.yml @@ -106,16 +106,17 @@ de: remove_contact: "Kontakt entfernen" search_no_results: "Keine Kontakte gefunden" conversation: + create: + no_recipient: "Hey, du musst erst einen Empfänger hinzufügen!" new: no_contacts: "Du musst einige Kontakte hinzufügen, bevor du eine Konversation anfangen kannst." create: "Erstellen" delete: "Löschen" edit: "Bearbeiten" - failed_to_comment: "Konnte nicht kommentieren. Vielleicht ignoriert dich der Autor?" - failed_to_like: "Gefällt mir ist fehlgeschlagen. Vielleicht ignoriert dich der Autor?" + errors: + connection: "Konnte keine Verbindung mit dem Server aufbauen." failed_to_post_message: "Konnte Beitrag nicht senden!" failed_to_remove: "Fehler beim Entfernen des Beitrags!" - failed_to_reshare: "Fehler beim Weitersagen!" getting_started: alright_ill_wait: "Alles klar, ich warte." hey: "Hey, <%= name %>!" @@ -151,6 +152,9 @@ de: notifications: mark_read: "Als gelesen markieren" mark_unread: "Als ungelesen markieren" + new_notifications: + one: "Du hast <%= count %> ungelesene Benachrichtigung" + other: "Du hast <%= count %> ungelesene Benachrichtigungen" people: edit_my_profile: "Mein Profil bearbeiten" helper: @@ -236,7 +240,6 @@ de: created: "Die Meldung wurde erfolgreich erstellt" exists: "Die Meldung existiert bereits" reshares: - duplicate: "Du hast diesen Beitrag bereits weitergesagt!" post: "<%= name %>s Beitrag weitersagen?" successful: "Der Beitrag wurde erfolgreich weitergesagt!" show_more: "Mehr zeigen" diff --git a/config/locales/javascript/javascript.de_formal.yml b/config/locales/javascript/javascript.de_formal.yml index ab64ce0f5..5fb62d5ef 100644 --- a/config/locales/javascript/javascript.de_formal.yml +++ b/config/locales/javascript/javascript.de_formal.yml @@ -69,7 +69,6 @@ de_formal: toggle: one: "In <%= count %> Aspekt" other: "In <%= count %> Aspekten" - zero: "Aspekt auswählen" updating: "aktualisiere..." aspect_navigation: add_an_aspect: "+ Aspekt hinzufügen" @@ -106,16 +105,17 @@ de_formal: remove_contact: "Kontakt entfernen" search_no_results: "Keine Kontakte gefunden" conversation: + create: + no_recipient: "Hey, Sie müssen erst einen Empfänger angeben!" new: no_contacts: "Sie müssen einige Kontakte hinzufügen, bevor Sie eine Konversation anfangen können." create: "Erstellen" delete: "Löschen" edit: "Bearbeiten" - failed_to_comment: "Konnte nicht kommentieren. Vielleicht ignoriert Sie der Autor?" - failed_to_like: "Gefällt mir ist fehlgeschlagen. Vielleicht ignoriert Sie der Autor?" + errors: + connection: "Konnte keine Verbindung mit dem Server aufbauen." failed_to_post_message: "Konnte Beitrag nicht senden!" failed_to_remove: "Fehler beim Entfernen des Beitrags!" - failed_to_reshare: "Fehler beim Weitersagen!" getting_started: alright_ill_wait: "Alles klar, ich warte." hey: "Hey, <%= name %>!" @@ -151,6 +151,9 @@ de_formal: notifications: mark_read: "Als gelesen markieren" mark_unread: "Als ungelesen markieren" + new_notifications: + one: "Sie haben <%= count %> ungelesene Benachrichtigung" + other: "Sie haben <%= count %> ungelesene Benachrichtigungen" people: edit_my_profile: "Mein Profil bearbeiten" helper: @@ -236,7 +239,6 @@ de_formal: created: "Die Meldung ist erfolgreich erstellt worden" exists: "Die Meldung existiert bereits" reshares: - duplicate: "Sie haben diesen Beitrag bereits weitergesagt!" post: "<%= name %>s Beitrag weitersagen?" successful: "Der Beitrag wurde erfolgreich weitergesagt!" show_more: "Mehr zeigen" diff --git a/config/locales/javascript/javascript.el.yml b/config/locales/javascript/javascript.el.yml index 36675af68..ec682cfac 100644 --- a/config/locales/javascript/javascript.el.yml +++ b/config/locales/javascript/javascript.el.yml @@ -35,7 +35,6 @@ el: remove_contact: "Διαγραφή επαφής" delete: "Διαγραφή" edit: "Επεξεργασία" - failed_to_like: "Αποτυχία!" failed_to_post_message: "Αποτυχία δημοσίευσης μηνύματος!" getting_started: alright_ill_wait: "Εντάξει, θα περιμένω." @@ -92,7 +91,6 @@ el: report: name: "Αναφορά" reshares: - duplicate: "Αυτό είναι τόσο καλό ε; Έχετε ήδη κοινοποιήσει αυτή τη δημοσίευση!" post: "Κοινοποίηση της ανάρτησης του <%= name %>;" successful: "Η ανάρτηση κοινοποιήθηκε επιτυχώς!" show_more: "Προβολή περισσότερων" diff --git a/config/locales/javascript/javascript.en_1337.yml b/config/locales/javascript/javascript.en_1337.yml index 8d3382c01..81e7f3397 100644 --- a/config/locales/javascript/javascript.en_1337.yml +++ b/config/locales/javascript/javascript.en_1337.yml @@ -24,7 +24,6 @@ en_1337: hide: "H1D3 5P4M5!" show: "5H0W 4LL 5P4M5!" confirm_dialog: "5UR3?" - failed_to_like: "F41L3D 2 <3!" failed_to_post_message: "F41L3D 2 53ND 5P4M!" getting_started: hey: "H3Y, <%= name %>!" @@ -34,8 +33,6 @@ en_1337: publisher: limited: "L1M173D - Y0UR 5P4M W1LL 0NLY B3 533N BY N00B5 U 4R3 5H4R1NG W17H!" public: "PUBL1C - Y0UR 5P4M W1LL B3 V151BL3 2 3V3RY0N3 4ND F0UND BY S34RCH 3NG1N35!" - reshares: - duplicate: "U H4V3 4LR34DY R35P4MM3D 7HI5!" show_more: "5H0W M0R3!" stream: likes: diff --git a/config/locales/javascript/javascript.en_pirate.yml b/config/locales/javascript/javascript.en_pirate.yml index c0573f0cd..6afef4962 100644 --- a/config/locales/javascript/javascript.en_pirate.yml +++ b/config/locales/javascript/javascript.en_pirate.yml @@ -20,8 +20,6 @@ en_pirate: preparing_your_stream: "Preparing your personialized stream..." header: search: "Find people or #tags" - reshares: - duplicate: "You've already reshared that post!" stream: likes: few: "<%= count %> Likes" diff --git a/config/locales/javascript/javascript.en_shaw.yml b/config/locales/javascript/javascript.en_shaw.yml index 27259dbc2..e10137b24 100644 --- a/config/locales/javascript/javascript.en_shaw.yml +++ b/config/locales/javascript/javascript.en_shaw.yml @@ -19,15 +19,12 @@ en_shaw: hide: "𐑣𐑲𐑛 𐑒𐑪𐑥𐑩𐑯𐑑𐑕" show: "𐑖𐑴 𐑷𐑤 𐑒𐑪𐑥𐑩𐑯𐑑𐑕" confirm_dialog: "𐑸 𐑿 𐑖𐑻?" - failed_to_like: "𐑓𐑱𐑤𐑛 𐑑 𐑤𐑲𐑒!" failed_to_post_message: "𐑓𐑱𐑤𐑛 𐑑 𐑐𐑴𐑕𐑑 𐑥𐑧𐑕𐑩𐑡!" getting_started: hey: "Hey, <%= name %>!" preparing_your_stream: "Preparing your personialized stream..." header: search: "Find people or #tags" - reshares: - duplicate: "𐑿𐑝 𐑷𐑤𐑮𐑧𐑛𐑦 𐑮𐑦𐑖𐑺𐑛 𐑞𐑨𐑑 𐑐𐑴𐑕𐑑!" show_more: "𐑖𐑴 𐑥𐑹" stream: likes: diff --git a/config/locales/javascript/javascript.en_valspeak.yml b/config/locales/javascript/javascript.en_valspeak.yml index b8fc63771..a8c663acd 100644 --- a/config/locales/javascript/javascript.en_valspeak.yml +++ b/config/locales/javascript/javascript.en_valspeak.yml @@ -51,7 +51,6 @@ en_valspeak: no_contacts: "So like, u got to add some ppl before u can start a convo..." delete: "Trash" edit: "Edit!" - failed_to_like: "Ur <3 didnt work :(" failed_to_post_message: "so like, i couldnt post txt... sry bout tht... :\\" failed_to_remove: "So like, there was an issue when removin the entry... sry bout that :\\" getting_started: @@ -138,7 +137,6 @@ en_valspeak: created: "The report was like, created. Yay." exists: "The report like, already existz..." reshares: - duplicate: "OMG that gr8t eh? uve like, already reshared tht postie!! :P" post: "do u wanna like, reshare <%= name %>'s postie?" successful: "The postie was reshared!!! :D" show_more: "show moar" diff --git a/config/locales/javascript/javascript.eo.yml b/config/locales/javascript/javascript.eo.yml index 439f2c33f..cf0061d19 100644 --- a/config/locales/javascript/javascript.eo.yml +++ b/config/locales/javascript/javascript.eo.yml @@ -35,7 +35,6 @@ eo: confirm_dialog: "Ĉu vi certas?" delete: "Forviŝi" edit: "Redakti" - failed_to_like: "Ne povis ŝati!" failed_to_post_message: "Ne povis afiŝi mesaĝon!" getting_started: alright_ill_wait: "En ordo, mi atendos." @@ -68,7 +67,6 @@ eo: limited: "Malpublika - via afiŝo nur videblos de homoj, al kiuj vi konigas aferojn" public: "Publika - via afiŝo videblos al ĉiuj kaj troveblos de retserĉprogramoj." reshares: - duplicate: "Nu, ĉu tiel bone? Vi jam rekonigis tiun afiŝon!" post: "Ĉu vi deziras rekonigi la mesaĝon de <%= name %>?" successful: "La afiŝo estis sukcese rekonigita!" show_more: "vidi plu" diff --git a/config/locales/javascript/javascript.es-AR.yml b/config/locales/javascript/javascript.es-AR.yml index 1f9a13293..bcb038f0c 100644 --- a/config/locales/javascript/javascript.es-AR.yml +++ b/config/locales/javascript/javascript.es-AR.yml @@ -106,16 +106,17 @@ es-AR: remove_contact: "Eliminar contacto" search_no_results: "No se han encontrado contactos con ese nombre." conversation: + create: + no_recipient: "¡Hey! primero tenes que agregar un destinatario" new: no_contacts: "Necesitas agregar algunos contactos antes de iniciar una conversación." create: "Crear" delete: "Borrar" edit: "Editar" - failed_to_comment: "Error al comentar. ¿Puede ser que el autor te esté ignorando?" - failed_to_like: "¡No pudo marcarse como \"Me gusta\"! ¿Tal vez el autor de la publicación te está ignorando?" + errors: + connection: "No es posible conectarse al servidor." failed_to_post_message: "¡No pudo publicarse el mensaje!" failed_to_remove: "Fallo al eliminar la entrada!" - failed_to_reshare: "Error al volver a compartir" getting_started: alright_ill_wait: "Todo bien, voy a esperar." hey: "¡Hola, <%= name %>!" @@ -151,6 +152,9 @@ es-AR: notifications: mark_read: "Marcar como leído" mark_unread: "Marcar como no leído" + new_notifications: + one: "Tenés una notificación sin leer" + other: "Tenés <%= count %> notificaciones sin leer" people: edit_my_profile: "Editar mi perfil" helper: @@ -236,7 +240,6 @@ es-AR: created: "El reporte se ha creado exitosamente" exists: "El reporte ya existe" reshares: - duplicate: "¿Te gustó eh? ¡Ya habías compartido esa publicación!" post: "¿Compartir la publicación de <%= name %>?" successful: "¡La publicación se compartió correctamente!" show_more: "Mostrar más" diff --git a/config/locales/javascript/javascript.es-CL.yml b/config/locales/javascript/javascript.es-CL.yml index ab15420fa..1c04a3676 100644 --- a/config/locales/javascript/javascript.es-CL.yml +++ b/config/locales/javascript/javascript.es-CL.yml @@ -26,7 +26,6 @@ es-CL: show: "mostrar todos los comentarios" confirm_dialog: "¿Estás seguro/a?" delete: "Eliminar" - failed_to_like: "¡Falló el 'Me gusta'!" failed_to_post_message: "¡Falló la publicación del mensaje!" getting_started: alright_ill_wait: "Está bien, esperaré." @@ -57,7 +56,6 @@ es-CL: limited: "Limitada - tu publicación sólo será visto por gente con la que compartes" public: "Público - tu post será visible para todos y encontrado por mecanismos de búsqueda" reshares: - duplicate: "¿Es genial, cierto?  ¡Ya has compartido esa publicación!" successful: "¡La publicación se compartió correctamente!" show_more: "mostrar más" stream: diff --git a/config/locales/javascript/javascript.es-MX.yml b/config/locales/javascript/javascript.es-MX.yml index a840ed04c..dddbdef48 100644 --- a/config/locales/javascript/javascript.es-MX.yml +++ b/config/locales/javascript/javascript.es-MX.yml @@ -32,7 +32,6 @@ es-MX: confirm_dialog: "¿Estás seguro?" delete: "Borrar" edit: "Editar" - failed_to_like: "¡No se pudo marcar como «Me gusta»!" failed_to_post_message: "¡No se pudo publicar el mensaje!" failed_to_remove: "¡Se produjo un error al eliminar la entrada!" getting_started: @@ -73,7 +72,6 @@ es-MX: near_from: "Publicado desde: <%= location %>" public: "Público – tu publicación será visible para todos, y encontrada por buscadores" reshares: - duplicate: "Qué bien, ¿eh? ¡Ya has compartido esa publicación!" post: "¿Compartir la publicación de <%= name %>?" successful: "¡La publicación se compartió exitosamente!" show_more: "mostrar más" diff --git a/config/locales/javascript/javascript.es.yml b/config/locales/javascript/javascript.es.yml index 3e037b986..ef7cd6d7a 100644 --- a/config/locales/javascript/javascript.es.yml +++ b/config/locales/javascript/javascript.es.yml @@ -109,11 +109,8 @@ es: create: "Crear" delete: "Eliminar" edit: "Editar" - failed_to_comment: "Error al comentar. ¿Puede ser que el autor te esté ignorando?" - failed_to_like: "\"Me gusta\" no ha funcionado." failed_to_post_message: "¡Error al publicar el mensaje!" failed_to_remove: "¡Se produjo un error al eliminar la entrada!" - failed_to_reshare: "¡Error al compartir!" getting_started: alright_ill_wait: "Está bien, esperaré." hey: "¡Hola, <%= name %>!" @@ -234,7 +231,6 @@ es: created: "El informe fue creado correctamente" exists: "El informe ya existe" reshares: - duplicate: "¿Verdad que te ha gustado? Pero ya has esa publicación." post: "¿Compartir la publicación de <%= name %>?" successful: "¡Publicación compartida con éxito!" show_more: "mostrar más" diff --git a/config/locales/javascript/javascript.eu.yml b/config/locales/javascript/javascript.eu.yml index bf98ebbd9..00f348ada 100644 --- a/config/locales/javascript/javascript.eu.yml +++ b/config/locales/javascript/javascript.eu.yml @@ -26,7 +26,6 @@ eu: show: "iruzkin guztiak erakutsi" confirm_dialog: "Ziur al zaude?" delete: "Ezabatu" - failed_to_like: "Huts gustoko egitean!" failed_to_post_message: "Huts egin du mezuaren bidalketak!" getting_started: alright_ill_wait: "Beno, itxarongo dut." @@ -57,7 +56,6 @@ eu: limited: "Mugatua - zure mezua aukeratu duzun jendeak bakarrik ikusiko du" public: "Publikoa - zure mezua edonork ikusi ahalko du, bai eta bilaketa zerbitzuetan agertu ere" reshares: - duplicate: "Oso ona, e? Dagoeneko birpartekatu duzu mezu hori!" post: "Birpartekatu nahi al duzu <%= name %>(r)en mezua?" successful: "Mezua arrakastaz birpartekatu da!" show_more: "erakutsi gehiago" diff --git a/config/locales/javascript/javascript.fi.yml b/config/locales/javascript/javascript.fi.yml index 3720953e3..c8a0bac34 100644 --- a/config/locales/javascript/javascript.fi.yml +++ b/config/locales/javascript/javascript.fi.yml @@ -63,10 +63,8 @@ fi: create: "Luo" delete: "Poista" edit: "Muokkaa" - failed_to_like: "Tykkääminen epäonnistui!" failed_to_post_message: "Viestin lähetys epäonnistui!" failed_to_remove: "Lisäyksen poistaminen epäonnistui!" - failed_to_reshare: "Uudelleen jakaminen epäonnistui!" getting_started: alright_ill_wait: "Okei, minä odotan." hey: "Hei <%= name %>!" @@ -153,7 +151,6 @@ fi: created: "Ilmoitus luotiin onnistuneesti" exists: "Ilmoitus on jo olemassa" reshares: - duplicate: "Olet jo uudelleenjakanut tämän julkaisun!" post: "Jaa käyttäjän <%= name %> julkaisu?" successful: "Julkaisu jaettiin onnistuneesti!" show_more: "Näytä lisää" diff --git a/config/locales/javascript/javascript.fr.yml b/config/locales/javascript/javascript.fr.yml index a9aba7533..e3ccd91ac 100644 --- a/config/locales/javascript/javascript.fr.yml +++ b/config/locales/javascript/javascript.fr.yml @@ -106,16 +106,17 @@ fr: remove_contact: "Retirer ce contact" search_no_results: "Aucun contact trouvé" conversation: + create: + no_recipient: "Vous avez d'abord besoin d'ajouter un destinataire." new: no_contacts: "Vous devez ajouter des contacts avant de pouvoir démarrer une conversation." create: "Créer" delete: "Effacer" edit: "Éditer" - failed_to_comment: "Impossible de commenter. Peut-être que l'auteur vous ignore ?" - failed_to_like: "Impossible d'aimer !" + errors: + connection: "Impossible de se connecter au serveur." failed_to_post_message: "Impossible de partager le message !" failed_to_remove: "L'entrée n'a pu être supprimée" - failed_to_reshare: "Échec du repartage" getting_started: alright_ill_wait: "Bon, je vais attendre." hey: "Hey, <%= name %> !" @@ -151,6 +152,9 @@ fr: notifications: mark_read: "Marquer comme lu" mark_unread: "Marquer comme non lu" + new_notifications: + one: "Vous avez une notification non lue." + other: "Vous avez <%= count %> notifications non lues." people: edit_my_profile: "Modifier mon profil" helper: @@ -237,7 +241,6 @@ fr: created: "Le signalement a été crée avec succès." exists: "Le signalement existe déjà" reshares: - duplicate: "C'est si bien que ça ? Vous avez déjà repartagé ce message !" post: "Repartager le message de <%= name %> ?" successful: "Le message a été repartagé !" show_more: "Voir plus" diff --git a/config/locales/javascript/javascript.he.yml b/config/locales/javascript/javascript.he.yml index 5f5a8d4d5..379e2f447 100644 --- a/config/locales/javascript/javascript.he.yml +++ b/config/locales/javascript/javascript.he.yml @@ -32,7 +32,6 @@ he: confirm_dialog: "האם אתם בטוחים?" delete: "מחיקה" edit: "עריכה" - failed_to_like: "הסימון ב'אהבתי' נכשל!" failed_to_post_message: "פרסום ההודעה נכשל!" failed_to_remove: "הנסיון להסיר את הערך נכשל!" getting_started: @@ -88,7 +87,6 @@ he: public: "ציבורי - הודעתך תהיה גלויה לכולם וניתן יהיה למצוא אותה במנועי חיפוש" question: "שאלה" reshares: - duplicate: "כבר שיתפת מחדש את ההודעה הזו." post: "האם לשתף מחדש את ההודעה של <%= name %>?" successful: "ההודעה שותפה מחדש בהצלחה!" show_more: "הצגת עוד" diff --git a/config/locales/javascript/javascript.hu.yml b/config/locales/javascript/javascript.hu.yml index d868bc858..b998dd286 100644 --- a/config/locales/javascript/javascript.hu.yml +++ b/config/locales/javascript/javascript.hu.yml @@ -22,6 +22,7 @@ hu: other: "<%= count %> csoportban" two: "<%= count %> csoportban" zero: "Csoportok kiválasztása" + updating: "frissítés..." aspect_navigation: add_an_aspect: "+ Új csoport" deselect_all: "Összes kijelölés megszüntetése" @@ -31,6 +32,7 @@ hu: post_something: "Hozz létre bejegyzést" post_submit: "Bejegyzés közzététele..." post_success: "Közzétéve! A felugró ablak bezáródik..." + cancel: "Mégsem" comma: "," comments: hide: "hozzászólások elrejtése" @@ -42,9 +44,10 @@ hu: aspect_list_is_not_visible: "A csoport tagjai nem láthatják egymást." aspect_list_is_visible: "A csoport tagjai láthatják egymást." remove_contact: "Ismerős eltávolítása" + search_no_results: "Nincsenek kapcsolatok" + create: "Létrehozás" delete: "Töröl" edit: "Szerkesztés" - failed_to_like: "Hiba" failed_to_post_message: "Üzenet elküldése sikertelen!" failed_to_remove: "Nem sikerült eltávolítani az elemet!" getting_started: @@ -67,6 +70,8 @@ hu: search: "Keresés" settings: "Beállítások" view_all: "Összes" + hide_post: "Bejegyzés elrejetése?" + hide_post_failed: "Bejegyzés elrejtése nem lehetséges" ignore: "Mellőzés" ignore_failed: "Nem sikerült mellőzni ezt a felhasználót" ignore_user: "Felhasználó mellőzése?" @@ -94,6 +99,7 @@ hu: close_result: "Eredmény rejtése" count: other: "<%=count%> szavazat eddig" + original_post: "eredeti bejegyzés" result: "Eredmény" show_result: "Eredmény mutatása" vote: "Szavazás" @@ -110,11 +116,18 @@ hu: you_have_no_tags: "nincsenek címkéid!" publisher: add_option: "Válasz hozzáadása" - limited: "Korlátozott - csak az ismerőseid láthatják ezt a bejegyzést" + limited: "Korlátozott: csak azok láthatják, akikkel megosztasz tartalmakat" + markdown_editor: + preview: "Előnézet" + tooltips: + insert_image: "Kép beillesztése" + insert_link: "Hivatkozás beillesztése" + write: "Szöveg" near_from: "<%= location %> közelében" option: "Válasz" - public: "Nyilvános - ezt a bejegyzést bárki láthatja az interneten." + public: "Nyilvános: bárki láthatja és keresőrobotok is megtalálhatják" question: "Kérdés" + remove_post: "Bejegyzés törlése?" report: name: "Jelentés" prompt: "Kérünk adj meg egy indokot:" @@ -123,7 +136,6 @@ hu: created: "A jelentés sikeresen létrehozva" exists: "A jelentés már létezik" reshares: - duplicate: "Jó mi? De már egyszer megosztottad ezt a bejegyzést!" post: "Szeretnéd újra megosztani <%= name %> bejegyzését?" successful: "A bejegyzés újraosztása sikeres!" show_more: "tovább" diff --git a/config/locales/javascript/javascript.hy.yml b/config/locales/javascript/javascript.hy.yml index 7bb2194bd..df61d6df7 100644 --- a/config/locales/javascript/javascript.hy.yml +++ b/config/locales/javascript/javascript.hy.yml @@ -107,11 +107,8 @@ hy: create: "Ստեղծել" delete: "Ջնջել" edit: "Փոփոխել" - failed_to_comment: "Չստացվեց մեկնաբանել։ Գուցե հեղինակն արհամարհո՞ւմ է քեզ։" - failed_to_like: "Չհաջողվեց հավանել։ Գուցե հեղինակն արհամարհո՞ւմ է քեզ։" failed_to_post_message: "Չհաջողվեց գրառում կատարել։" failed_to_remove: "Չստացվեց ջնջել մուտքագրածը։" - failed_to_reshare: "Չստացվեց տարածել։" getting_started: alright_ill_wait: "Դե լավ, ես կսպասեմ։" hey: "Հե՜յ, <%= name %>։" @@ -230,7 +227,6 @@ hy: created: "Բողոքը հաջողությամբ ստեղծվեց" exists: "Բողոքը արդեն ստեղծված է" reshares: - duplicate: "Էդքան լա՞վն ա։ Արդեն տարածել ես այս գրառումը։" post: "Տարածե՞լ <%= name %>-ի գրառումը։" successful: "Գրառումը հաջողությամբ տարածվեց։" show_more: "Ցույց տալ ավելին" diff --git a/config/locales/javascript/javascript.ia.yml b/config/locales/javascript/javascript.ia.yml index 783f19b22..bcfda0267 100644 --- a/config/locales/javascript/javascript.ia.yml +++ b/config/locales/javascript/javascript.ia.yml @@ -46,6 +46,9 @@ ia: one: "Il ha ancora un pod non verificate." other: "Il ha ancora <%= count %> pods non verificate." unknown: "incognite" + version_failed: + one: "Il ha un pod que non ha version (pod ancian sin NodeInfo)." + other: "Il ha <%= count %> pods que non ha version (pods ancian sin NodeInfo)." admins: dashboard: compare_versions: "Le ultime version de diaspora* es <%= latestVersion %>; iste pod executa <%= podVersion %>." @@ -90,6 +93,8 @@ ia: confirm_unload: "Per favor, confirma que tu vole quitar iste pagina. Le datos que tu ha inserite non essera salveguardate." contacts: add_contact: "Adder contacto" + aspect_chat_is_enabled: "Le contactos in iste aspecto pote chattar con te." + aspect_chat_is_not_enabled: "Le contactos in iste aspecto non pote chattar con te." aspect_list_is_not_visible: "Le contactos in iste aspecto non pote vider le un le altere." aspect_list_is_visible: "Le contactos in iste aspecto pote vider le un le altere." error_add: "Non poteva adder <%= name %> al aspecto." @@ -97,16 +102,17 @@ ia: remove_contact: "Remover contacto" search_no_results: "Nulle contacto trovate" conversation: + create: + no_recipient: "Es necessari adder un destinatario primo." new: no_contacts: "Es necessari adder alcun contactos ante de poter initiar un conversation." create: "Crear" delete: "Deler" edit: "Modificar" - failed_to_comment: "Commento fallite. Es possibile que le autor te ignora." - failed_to_like: "Appreciation fallite!" + errors: + connection: "Impossibile connecter al servitor." failed_to_post_message: "Publication del entrata fallite!" failed_to_remove: "Le remotion del entrata ha fallite." - failed_to_reshare: "Repetition fallite!" getting_started: alright_ill_wait: "Ben, io attendera." hey: "Hallo, <%= name %>!" @@ -142,6 +148,9 @@ ia: notifications: mark_read: "Marcar como legite" mark_unread: "Marcar como non legite" + new_notifications: + one: "Tu ha <%= count %> notification non legite" + other: "Tu ha <%= count %> notificationes non legite" people: edit_my_profile: "Modificar mi profilo" helper: @@ -186,6 +195,34 @@ ia: publisher: add_option: "Adder un responsa" limited: "Limitate: le message es visibile solmente pro le personas con qui tu lo divide" + markdown_editor: + preview: "Previsualisar" + texts: + code: "scribe hic le codice" + heading: "texto de titulo" + insert_image_description_text: "describe hic le imagine" + insert_image_help_text: "Inserer hic un ligamine a un imagine" + insert_image_title: "scribe hic le titulo del imagine" + insert_link_description_text: "describe hic le ligamine" + insert_link_help_text: "Inserer ligamine hic" + italic: "texto italic" + list: "scribe hic le texto del lista" + quote: "scribe hic le texto del citation" + strong: "texto forte" + tooltips: + bold: "Grasse" + cancel: "Cancellar message" + code: "Inserer codice" + heading: "Titulo" + insert_image: "Inserer imagine" + insert_link: "Inserer ligamine" + insert_ordered_list: "Inserer lista ordinate" + insert_unordered_list: "Inserer lista non ordinate" + italic: "Italic" + preview: "Previsualisar message" + quote: "Inserer citation" + write: "Modificar message" + write: "Scriber" near_from: "Inviate ab: <%= location %>" option: "Responsa" public: "Public: le message es visibile pro tote le mundo e trovabile pro motores de recerca" @@ -199,7 +236,6 @@ ia: created: "Le creation del reporto ha succedite" exists: "Le reporto jam existe" reshares: - duplicate: "Tu ha jam repetite iste entrata." post: "Repeter le entrata de <%= name %>?" successful: "Le entrata ha essite repetite con successo." show_more: "monstrar plus" @@ -216,6 +252,7 @@ ia: hide_nsfw_posts: "Celar entratas #nsfw (improprie pro le travalio)" like: "Appreciar" limited: "Limitate" + no_posts_yet: "Il non ha ancora entratas a monstrar hic." original_post_deleted: "Le entrata original ha essite delite per le autor." permalink: "Permaligamine" public: "Public" @@ -245,6 +282,7 @@ ia: hour: "circa un hora" hours: other: "circa %d horas" + inPast: "a qualcunque momento" minute: "circa un minuta" minutes: other: "%d minutas" diff --git a/config/locales/javascript/javascript.id.yml b/config/locales/javascript/javascript.id.yml index 73326f6da..a803cf236 100644 --- a/config/locales/javascript/javascript.id.yml +++ b/config/locales/javascript/javascript.id.yml @@ -25,7 +25,6 @@ id: show: "tampilkan semua komentar" confirm_dialog: "Anda yakin ?" delete: "Menghapus" - failed_to_like: "Gagal untuk 'like'!" failed_to_post_message: "Gagal memposting pesan!" getting_started: alright_ill_wait: "Baiklah, Saya akan menunggu" @@ -42,8 +41,6 @@ id: publisher: limited: "Di Limitasi - Apa yang anda publikasi hanya dapat di lihat oleh orang-orang yang berbagi dengan anda." public: "Publik - Apa yang anda publikasi dapat di lihat oleh siapa saja dan dapat di temukan oleh mesin pencari." - reshares: - duplicate: "Menarik ? Anda telah membagikan ulang posting tersebut!" show_more: "Tampilkan lebih banyak lagi" stream: comment: "Komentar" diff --git a/config/locales/javascript/javascript.is.yml b/config/locales/javascript/javascript.is.yml index 74f241949..5dca7fb38 100644 --- a/config/locales/javascript/javascript.is.yml +++ b/config/locales/javascript/javascript.is.yml @@ -32,7 +32,6 @@ is: confirm_dialog: "Ertu viss?" delete: "Eyða" edit: "Breyta" - failed_to_like: "Tókst ekki að líka við. Ætli höfundurinn sé að hunsa þig?" failed_to_post_message: "Tókst ekki að senda skeytið!" getting_started: alright_ill_wait: "Ekkert mál, ég get beðið." @@ -75,7 +74,6 @@ is: near_from: "Sennt inn nálægt: <%= location %>" public: "Opinbert - skeytið verður sýnilegt öllum, leitarvélar geta einnig fundið póstinn" reshares: - duplicate: "Þetta gott, ha? Þú ert þegar búinn að endurdeila þessari færslu!" post: "Deila áfram færslu frá <%= name %>?" successful: "Tókst að deila þessu skeyti áfram!" show_more: "Sýna meira" diff --git a/config/locales/javascript/javascript.it.yml b/config/locales/javascript/javascript.it.yml index 8fdec11a9..706cde2c0 100644 --- a/config/locales/javascript/javascript.it.yml +++ b/config/locales/javascript/javascript.it.yml @@ -35,7 +35,6 @@ it: confirm_dialog: "Sei sicuro?" delete: "Elimina" edit: "Modifica" - failed_to_like: "Errore, il \"mi piace\" non è stato inviato!" failed_to_post_message: "Invio messaggio fallito!" getting_started: alright_ill_wait: "Perfetto, aspetterò." @@ -75,7 +74,6 @@ it: near_from: "Vicino a: <%= location %>" public: "Pubblico - il tuo post sarà visibile a tutti, inclusi i motori di ricerca" reshares: - duplicate: "Bello eh? Ma hai già condiviso quel post!" post: "Vuoi condividere il post di <%= name %>?" successful: "Il post è stato condiviso!" show_more: "continua..." diff --git a/config/locales/javascript/javascript.ja.yml b/config/locales/javascript/javascript.ja.yml index b02294947..cba79d345 100644 --- a/config/locales/javascript/javascript.ja.yml +++ b/config/locales/javascript/javascript.ja.yml @@ -101,16 +101,17 @@ ja: remove_contact: "連絡先を削除" search_no_results: "連絡先が見つかりません" conversation: + create: + no_recipient: "最初に受信者を追加する必要があります!" new: no_contacts: "会話を開始する前に、連絡先を追加する必要があります。" create: "作成" delete: "削除" edit: "編集" - failed_to_comment: "コメントに失敗しました。おそらく作者があなたを無視していませんか?" - failed_to_like: "いいね!に失敗しました。おそらく作者があなたを無視していませんか?" + errors: + connection: "サーバーに接続できません。" failed_to_post_message: "メッセージの投稿に失敗しました!" failed_to_remove: "エントリーの削除に失敗しました!" - failed_to_reshare: "リシェアに失敗しました!" getting_started: alright_ill_wait: "OK、私は待ちます。" hey: "Hey, <%= name %>!" @@ -146,6 +147,8 @@ ja: notifications: mark_read: "既読にする" mark_unread: "未読にする" + new_notifications: + other: "<%= count %> 件、未読の通知があります" people: edit_my_profile: "マイ プロフィールを編集する" helper: @@ -228,7 +231,6 @@ ja: created: "報告を正常に作成しました" exists: "報告はすでに存在します" reshares: - duplicate: "えっ?すでにこの投稿をリシェアしています!" post: "<%= name %>さんの投稿をリシェアしますか?" successful: "投稿は正常にリシェアされました!" show_more: "さらに表示する" @@ -245,19 +247,11 @@ ja: hide_nsfw_posts: "#nsfwの投稿を隠す" like: "いいね!" likes: - few: "<%= count %> Likes" - many: "<%= count %> Likes" - one: "<%= count %> Like" other: "<%= count %> いいね!" - two: "<%= count %> Likes" zero: "<%= count %> いいね!" limited: "限定公開" more_comments: - few: "Show <%= count %> more comments" - many: "Show <%= count %> more comments" - one: "Show <%= count %> more comment" other: "さらに <%= count %> のコメントを表示" - two: "Show <%= count %> more comments" zero: "さらに <%= count %> のコメントを表示" no_posts_yet: "まだここに表示する投稿はありません。" original_post_deleted: "元の投稿は作者によって削除されました" @@ -268,11 +262,7 @@ ja: zero: "<%= count%> リアクション" reshare: "リシェア" reshares: - few: "<%= count %> Reshares" - many: "<%= count %> Reshares" - one: "<%= count %> Reshare" other: "<%= count %> リシェア" - two: "<%= count %> Reshares" zero: "<%= count %> リシェア" show_nsfw_post: "投稿を表示する" show_nsfw_posts: "全て表示" diff --git a/config/locales/javascript/javascript.ka.yml b/config/locales/javascript/javascript.ka.yml index 79e4f018d..0460662bd 100644 --- a/config/locales/javascript/javascript.ka.yml +++ b/config/locales/javascript/javascript.ka.yml @@ -25,7 +25,6 @@ ka: show: "ყველა კომენტარის ჩვენება" confirm_dialog: "დარწმუნებული ხართ?" delete: "წაშლა" - failed_to_like: "მოწონება ვერ მოხერხდა!" failed_to_post_message: "შეტყობინების გამოქვეყნება ვერ მოხერხდა!" getting_started: alright_ill_wait: "კარგი, მოვიცდი." @@ -52,8 +51,6 @@ ka: publisher: limited: "შეზღუდული - თქვენს პოსტს დაინახავს მხოლოდ ის ხალხი რომელთაც გაუზიარებთ" public: "საჯარო - თქვენს პოსტს დაინახავს ყველა და ის გამოჩნდება საძიებო სისტემაში" - reshares: - duplicate: "ასეთი მაგარია? თქვენ უკვე გააზიარეთ ეს პოსტი!" show_more: "მეტის ჩვენება" stream: comment: "კომენტარი" diff --git a/config/locales/javascript/javascript.ko.yml b/config/locales/javascript/javascript.ko.yml index 8f9378a59..73abde04a 100644 --- a/config/locales/javascript/javascript.ko.yml +++ b/config/locales/javascript/javascript.ko.yml @@ -33,7 +33,6 @@ ko: confirm_dialog: "확실합니까?" delete: "지우기" edit: "고치기" - failed_to_like: "좋아요를 실패했습니다!" failed_to_post_message: "메시지 게시를 실패하였습니다!" getting_started: alright_ill_wait: "기다릴게요." @@ -78,7 +77,6 @@ ko: public: "공개 - 내 게시물을 누구나 볼 수 있고 검색 엔진으로 찾을 수 있습니다" question: "질문" reshares: - duplicate: "이미 재공유된 게시물입니다!" post: "<%= name %>님의 게시물을 재공유할까요?" successful: "해당 게시물이 성공적으로 재공유되었습니다!" show_more: "더 보기" diff --git a/config/locales/javascript/javascript.lt.yml b/config/locales/javascript/javascript.lt.yml index 33a7d0366..3e211df37 100644 --- a/config/locales/javascript/javascript.lt.yml +++ b/config/locales/javascript/javascript.lt.yml @@ -27,7 +27,6 @@ lt: show: "Rodyti visus komentarus" confirm_dialog: "Ar Jūs tuo įsitikinęs?" delete: "Ištrinti" - failed_to_like: "Nepavyko pamėgti!" failed_to_post_message: "Nepavyko išsiųsti žinutės!" getting_started: alright_ill_wait: "Suprantama, aš galiu palaukti!" @@ -54,8 +53,6 @@ lt: publisher: limited: "Ribotas - Jūsų įrašą galės peržiūrėti tik žmonės, su kuriais Jūs dalijatės" public: "Viešas - Jūsų įrašus galės peržiūrėti visi, taip pat jie bus randami paieškos sistemose." - reshares: - duplicate: "Šitas geras, ne? Jūs jau dalijotės šiuo įrašu!" show_more: "Rodyti daugiau" stream: comment: "Komentuoti" diff --git a/config/locales/javascript/javascript.ml.yml b/config/locales/javascript/javascript.ml.yml index 4110513dd..37c9d4762 100644 --- a/config/locales/javascript/javascript.ml.yml +++ b/config/locales/javascript/javascript.ml.yml @@ -32,7 +32,6 @@ ml: confirm_dialog: "താങ്കള്‍ക്ക് ഉറപ്പാണോ?" delete: "മായ്ക്കുക" edit: "തിരുത്തുക" - failed_to_like: "ഇഷ്ടപെടാൻ സാധിച്ചില്ല" failed_to_post_message: "സന്ദേശം ഇടാൻ സാധിച്ചില്ല" getting_started: alright_ill_wait: "ശരി, ഞാൻ കാത്തിരിക്കാം" @@ -71,7 +70,6 @@ ml: near_from: "<%= location %>ല്‍ നിന്നും അയച്ചത്" public: "പൊതുവായത് - താങ്കളുടെ കുറിപ്പ് എല്ലാവർക്കും കാണാൻ സാധിക്കും. കൂടാതെ തിരച്ചിൽ യന്ത്രങ്ങളാൽ കണ്ടുപിടിക്കപ്പെടുകയും ചെയ്യും" reshares: - duplicate: "അത്ര നല്ലതാണോ? താങ്കൾ ആ കുറിപ്പ് മുൻപേ തന്നെ വീണ്ടും പങ്കിട്ടിട്ടുണ്ട്" post: "<%= name %>ന്റെ കുറിപ്പ് വീണ്ടും പങ്കിടണോ?" successful: "ഈ കുറിപ്പ് വിജയകരമായി വീണ്ടും പങ്കുവെയ്ക്കപ്പെട്ടു!" show_more: "കൂടുതല്‍ കാണിക്കുക" diff --git a/config/locales/javascript/javascript.ms.yml b/config/locales/javascript/javascript.ms.yml index 08538a490..fc0fb6290 100644 --- a/config/locales/javascript/javascript.ms.yml +++ b/config/locales/javascript/javascript.ms.yml @@ -42,7 +42,6 @@ ms: error_remove: "Tidak dapat membuang <%= name %> dari aspek :(" remove_contact: "Buang kenalan" edit: "Edit" - failed_to_like: "Gagal untuk suka!" failed_to_post_message: "Gagal untuk pos mesej!" failed_to_remove: "Gagal membuang catatan!" getting_started: @@ -112,7 +111,6 @@ ms: created: "Laporan itu sudah wujud" exists: "Laporan itu sudah wujud" reshares: - duplicate: "Yang baik, kan? Anda telah berkongsi semula pos itu!" post: "Kongsi semula catatan <%= name %>?" successful: "Catatan berjaya dikongsi semula!" show_more: "tunjuk lagi" diff --git a/config/locales/javascript/javascript.nb.yml b/config/locales/javascript/javascript.nb.yml index ec8a4bae1..a31618ca0 100644 --- a/config/locales/javascript/javascript.nb.yml +++ b/config/locales/javascript/javascript.nb.yml @@ -60,10 +60,8 @@ nb: create: "Lag" delete: "Slett" edit: "Rediger" - failed_to_like: "Klarte ikke å like!" failed_to_post_message: "Klarte ikke å publisere post!" failed_to_remove: "Noe gikk galt i forsøket på å fjerne innlegget!" - failed_to_reshare: "Kunne ikke videredele" getting_started: alright_ill_wait: "Greit, jeg venter." hey: "Hei, <%= name %>!" @@ -178,7 +176,6 @@ nb: created: "Rapporten er opprettet" exists: "Rapporten eksisterer allerede" reshares: - duplicate: "du har allerede delt denne posten!" post: "Videredel <%= name %> sitt innhold?" successful: "Dette innholdet ble videredelt" show_more: "vis mer" diff --git a/config/locales/javascript/javascript.nl.yml b/config/locales/javascript/javascript.nl.yml index b0c929669..168bfc232 100644 --- a/config/locales/javascript/javascript.nl.yml +++ b/config/locales/javascript/javascript.nl.yml @@ -114,11 +114,8 @@ nl: create: "Creëren" delete: "Verwijder" edit: "Bewerken" - failed_to_comment: "Reageren mislukt. Misschien negeert de schrijver jou?" - failed_to_like: "Leuk vinden mislukt. Misschien negeert de auteur jou?" failed_to_post_message: "Bericht plaatsen mislukt!" failed_to_remove: "Kon het bericht niet verwijderen!" - failed_to_reshare: "Doorgeven mislukt!" getting_started: alright_ill_wait: "Prima, ik wacht wel." hey: "Hallo, <%= name %>!" @@ -154,6 +151,9 @@ nl: notifications: mark_read: "Markeren als gelezen" mark_unread: "Markeren als ongelezen" + new_notifications: + one: "Je hebt <%= count %> ongelezen melding" + other: "Je hebt <%= count %> ongelezen meldingen" people: edit_my_profile: "Bewerk mijn profiel" helper: @@ -198,6 +198,30 @@ nl: publisher: add_option: "Keuzemogelijkheid toevoegen" limited: "Gelimiteerd - je bericht is alleen zichtbaar voor de mensen waarmee je hem deelt" + markdown_editor: + preview: "Voorbeeld" + texts: + code: "code hier" + heading: "Koptekst" + insert_image_title: "voeg hier afbeeldingstekst in" + italic: "Cursieve tekst" + list: "lijst tekst hier" + quote: "quote hier" + strong: "Benadrukte tekst" + tooltips: + bold: "Vet" + cancel: "Annuleren bericht" + code: "Invoegen code" + heading: "Koptekst" + insert_image: "Invoegen afbeelding" + insert_link: "Invoegen link" + insert_ordered_list: "Invoegen genummerde lijst" + insert_unordered_list: "Invoegen ongenummerde lijst" + italic: "Cursief" + preview: "Voorbeeld bericht" + quote: "Invoegen quote" + write: "Bewerk bericht" + write: "Schrijven" near_from: "Geplaatst vanaf: <%= location %>" option: "Keuze <%= nr %>" public: "Openbaar - je bericht is zichtbaar voor iedereen en kan gevonden worden door zoekmachines" @@ -211,7 +235,6 @@ nl: created: "Het is succesvol gemeld" exists: "De melding bestaat al" reshares: - duplicate: "Je hebt dit bericht al doorgegeven! Is het echt zo goed?" post: "Doorgeven <%= name %>'s bericht?" successful: "Het bericht is gedeeld!" show_more: "Laat meer zien" diff --git a/config/locales/javascript/javascript.nn.yml b/config/locales/javascript/javascript.nn.yml index 708e558b0..4e042f80f 100644 --- a/config/locales/javascript/javascript.nn.yml +++ b/config/locales/javascript/javascript.nn.yml @@ -31,7 +31,6 @@ nn: confirm_dialog: "Er du sikker?" delete: "Slett" edit: "Endra" - failed_to_like: "Like-funksjonen feila." failed_to_post_message: "Klarte ikkje å senda meldinga." getting_started: alright_ill_wait: "Greitt, eg ventar." @@ -65,7 +64,6 @@ nn: limited: "Avgrensa - berre personar du deler med vil kunna sjå meldinga" public: "Offentleg - alle kan sjå meldinga di og ho kan bli funnen av søkjemotorar" reshares: - duplicate: "Så bra, altså? Men du har allereie delt meldinga :-)" post: "Vil du dele <%= name %> sin post?" successful: "Hurra, posten vart delt!" show_more: "syn meir" diff --git a/config/locales/javascript/javascript.oc.yml b/config/locales/javascript/javascript.oc.yml index fc7dde386..c5dc05786 100644 --- a/config/locales/javascript/javascript.oc.yml +++ b/config/locales/javascript/javascript.oc.yml @@ -111,11 +111,8 @@ oc: create: "Crear" delete: "Suprimir" edit: "Editar" - failed_to_comment: "Impossible de comentar. Benlèu que l'autor vos ignòra ?" - failed_to_like: "Impossible de marcar que m'agrada !" failed_to_post_message: "Impossible de partejar lo messatge !" failed_to_remove: "L'entrada a pas pogut èsser suprimida" - failed_to_reshare: "Fracàs del partiment" getting_started: alright_ill_wait: "Bon, vau esperar." hey: "Adiu, <%= name %>" @@ -236,7 +233,6 @@ oc: created: "Lo senhalament es estat creat amb succès." exists: "Lo senhalament existís ja" reshares: - duplicate: "Es tan plan coma aquò ? Avètz ja repartejat aqueste messatge !" post: "Repartejar lo messatge de <%= name %> ?" successful: "Lo messatge es estat repartejat !" show_more: "N'afichar mai" diff --git a/config/locales/javascript/javascript.pl.yml b/config/locales/javascript/javascript.pl.yml index 1f746a939..77e8edbe2 100644 --- a/config/locales/javascript/javascript.pl.yml +++ b/config/locales/javascript/javascript.pl.yml @@ -63,10 +63,8 @@ pl: create: "Utwórz" delete: "Usuń" edit: "Edycja" - failed_to_like: "Nie udało się pulubić!" failed_to_post_message: "Nie można wysłać wiadomości!" failed_to_remove: "Nie udało się usunąć wartości!" - failed_to_reshare: "Nie udało się przekazać dalej!" getting_started: alright_ill_wait: "Dobrze, poczekam." hey: "Hej, <%= name %>!" @@ -155,7 +153,6 @@ pl: created: "Zgłoszenie zostało pomyślnie utworzone" exists: "Zgłoszenie już istnieje" reshares: - duplicate: "Już przekaza@{m:łeś|f:łaś|n:no} dalej ten wpis!" post: "Przesłać dalej wpis użytkownika <%= name %>?" successful: "Wpis został pomyślnie przesłany dalej!" show_more: "wyświetl więcej" diff --git a/config/locales/javascript/javascript.pt-BR.yml b/config/locales/javascript/javascript.pt-BR.yml index 824bfd304..0c6a840ec 100644 --- a/config/locales/javascript/javascript.pt-BR.yml +++ b/config/locales/javascript/javascript.pt-BR.yml @@ -107,16 +107,17 @@ pt-BR: remove_contact: "Remover contato" search_no_results: "Nenhum contato encontrado" conversation: + create: + no_recipient: "Ei, primeiro você precisa adicionar um destinatário!" new: no_contacts: "Você precisa adicionar contatos antes de começar uma conversa." create: "Criar" delete: "Apagar" edit: "Editar" - failed_to_comment: "Falha ao comentar. Será que estão ignorando você?" - failed_to_like: "Falha ao curtir. Será que o autor está ignorando você?" + errors: + connection: "Não foi possível conectar ao servidor." failed_to_post_message: "Falha na publicação da mensagem!" failed_to_remove: "Falha ao remover a entrada!" - failed_to_reshare: "Falha ao recompartilhar!" getting_started: alright_ill_wait: "Tudo bem, vou esperar." hey: "Ei, <%= name %>!" @@ -152,6 +153,9 @@ pt-BR: notifications: mark_read: "Marcar como lida" mark_unread: "Marcar como não lida" + new_notifications: + one: "Você tem <%= count %> notificação não lida" + other: "Você tem <%= count %> notificações não lidas" people: edit_my_profile: "Editar meu perfil" helper: @@ -237,7 +241,6 @@ pt-BR: created: "O relato foi criado com sucesso" exists: "O relato já existe" reshares: - duplicate: "Que bom, hein? Você já recompartilhou essa publicação!" post: "Recompartilhar a publicação de <%= name %>?" successful: "A publicação foi recompartilhada com sucesso!" show_more: "Mostrar mais" diff --git a/config/locales/javascript/javascript.pt-PT.yml b/config/locales/javascript/javascript.pt-PT.yml index cf25549dc..61fa78fcb 100644 --- a/config/locales/javascript/javascript.pt-PT.yml +++ b/config/locales/javascript/javascript.pt-PT.yml @@ -31,7 +31,6 @@ pt-PT: confirm_dialog: "Tem a certeza?" delete: "Eliminar" edit: "Editar" - failed_to_like: "Falhou em gostar!" failed_to_post_message: "Falhou ao publicar a mensagem!" getting_started: alright_ill_wait: "Tudo bem, eu esperarei." @@ -69,7 +68,6 @@ pt-PT: near_from: "Publicado em: <%= location %>" public: "Público - A sua publicação será visível para todos e encontrada por motores de busca" reshares: - duplicate: "Que bom, hein? Você já republicou essa mensagem!" post: "Repartilhar a publicação de <%= name %>?" successful: "A publicação foi repartilhada com sucesso!" show_more: "mostrar mais" diff --git a/config/locales/javascript/javascript.ro.yml b/config/locales/javascript/javascript.ro.yml index 5737916c4..97357603b 100644 --- a/config/locales/javascript/javascript.ro.yml +++ b/config/locales/javascript/javascript.ro.yml @@ -31,7 +31,6 @@ ro: confirm_dialog: "Sunteţi sigur?" delete: "Şterge" edit: "Modifică" - failed_to_like: "Nu sa reusit operatia de \"imi place\"!" failed_to_post_message: "Nu sa reusit trimiterea mesajului!" getting_started: alright_ill_wait: "In regulă, o să aștept." @@ -65,8 +64,6 @@ ro: limited: "Limitat - publicatia va fi vazuta doar de catre persoanele cu care imparti publicatii" near_from: "Publicat din <%= location %>" public: "Public - articolul tău va fi vizibil tuturor şi va fi accesibilă prin motoarele de căutare" - reshares: - duplicate: "E chiar asa de tare, hmm? Ati mai raspandit o data aceasta publicatie!" show_more: "arată mai mult" stream: comment: "Comentariu" diff --git a/config/locales/javascript/javascript.ru.yml b/config/locales/javascript/javascript.ru.yml index 2fd45487a..af924673b 100644 --- a/config/locales/javascript/javascript.ru.yml +++ b/config/locales/javascript/javascript.ru.yml @@ -73,10 +73,8 @@ ru: create: "Создать" delete: "Удалить" edit: "Изменить" - failed_to_like: "Не удалось!" failed_to_post_message: "Не удалось отправить сообщение!" failed_to_remove: "Удаление не завершено!" - failed_to_reshare: "Не удалось поделиться!" getting_started: alright_ill_wait: "Хорошо, я подожду." hey: "Привет, <%= name %>!" @@ -193,7 +191,6 @@ ru: created: "Донос успешно отправлен" exists: "Донос уже отправлен" reshares: - duplicate: "Здорово, да? Вы уже поделились этой записью!" post: "Поделиться записью пользователя <%= name %>?" successful: "Вы успешно поделились записью!" show_more: "показать больше" diff --git a/config/locales/javascript/javascript.sk.yml b/config/locales/javascript/javascript.sk.yml index 1bf7feea8..cb66d1313 100644 --- a/config/locales/javascript/javascript.sk.yml +++ b/config/locales/javascript/javascript.sk.yml @@ -37,7 +37,6 @@ sk: confirm_dialog: "Určite?" delete: "Odstrániť" edit: "Upraviť" - failed_to_like: "Nepodarilo sa označiť, že sa ti to páči!" failed_to_post_message: "Správu sa nepodarilo poslať!" getting_started: alright_ill_wait: "V poriadku, počkám." @@ -99,7 +98,6 @@ sk: created: "Úspešne si vytvoril(a) správu" exists: "Správa už existuje" reshares: - duplicate: "Je to dobré, čo? O tento príspevok si sa už raz znova podelil(a)!" post: "Znova ukázať priateľom príspevok, ktorý napísal(a) <%= name %>?" successful: "Tento príspevok si úspešne znova ukázal(a) priateľom!" show_more: "Zobraziť viac" diff --git a/config/locales/javascript/javascript.sl.yml b/config/locales/javascript/javascript.sl.yml index 00e783156..74ede6004 100644 --- a/config/locales/javascript/javascript.sl.yml +++ b/config/locales/javascript/javascript.sl.yml @@ -28,7 +28,6 @@ sl: show: "prikaži vse komentarje" confirm_dialog: "Ste prepričani" delete: "Izbriši" - failed_to_like: "Označevanje ni uspelo!" failed_to_post_message: "Objava ni uspela!" getting_started: alright_ill_wait: "V redu, bom počakal." @@ -59,7 +58,6 @@ sl: limited: "Omejeno - Vaša objava bo vidna le ljudem, s katerimi delite" public: "Javno - Vaša objava bo vidna vsem, prikazana bo tudi v spletnih iskalnikih" reshares: - duplicate: "To objavo ste že ponovno delili" post: "Ponovno deli objavo osebe <%= name %>?" successful: "Objavo ste uspešno ponovno delili!" show_more: "pokaži več" diff --git a/config/locales/javascript/javascript.sr.yml b/config/locales/javascript/javascript.sr.yml index d4ff3fb71..f6a9aa96c 100644 --- a/config/locales/javascript/javascript.sr.yml +++ b/config/locales/javascript/javascript.sr.yml @@ -28,7 +28,6 @@ sr: show: "прикажи све коментаре" confirm_dialog: "Јесте ли сигурни?" delete: "Уклони" - failed_to_like: "Свиђање није успело!" failed_to_post_message: "Слање поруке није успело!" getting_started: alright_ill_wait: "Важи, сачекаћу." @@ -55,8 +54,6 @@ sr: publisher: limited: "Ограничено - твоју објаву ће видети само људи са којима је делиш" public: "Јавно - твоју објаву ће видети сви и биће је могуће тражити путем претраживача" - reshares: - duplicate: "Добро је, а? Већ сте објавили ово!" show_more: "прикажи још" stream: comment: "Коментариши" diff --git a/config/locales/javascript/javascript.sv.yml b/config/locales/javascript/javascript.sv.yml index 3424d104f..ea420eeae 100644 --- a/config/locales/javascript/javascript.sv.yml +++ b/config/locales/javascript/javascript.sv.yml @@ -68,12 +68,8 @@ sv: started_sharing_with: "Du har börjat dela med <%= name %>!" stopped_sharing_with: "Du har slutat dela med <%= name %>." toggle: - few: "I <%= count %> aspekter" - many: "I <%= count %> aspekter" one: "I <%= count %> aspekt" other: "I <%= count %> aspekter" - two: "I <%= count %> aspekter" - zero: "Välj aspekter" updating: "uppdaterar..." aspect_navigation: add_an_aspect: "+ Lägg till en aspekt" @@ -110,16 +106,17 @@ sv: remove_contact: "Ta bort kontakt" search_no_results: "Inga kontakter hittade" conversation: + create: + no_recipient: "Hörru! Du måste lägga till en mottagare först." new: no_contacts: "Du behöver några kontakter innan du kan påbörja konversationer." create: "Skapa" delete: "Radera" edit: "Ändra" - failed_to_comment: "Lyckades inte kommentera. Författaren kanske ignorerar dig." - failed_to_like: "Misslyckades att gilla. Kanske är du inte önskvärd av författaren." + errors: + connection: "Kunde inte ansluta till servern." failed_to_post_message: "Misslyckades att posta meddelande!" failed_to_remove: "Misslyckades med att borttaga inlägget!" - failed_to_reshare: "Kunde inte dela vidare!" getting_started: alright_ill_wait: "Okej, jag väntar." hey: "Hej, <%= name %>!" @@ -155,6 +152,10 @@ sv: notifications: mark_read: "Lästmärk" mark_unread: "Olästmarkera" + new_notifications: + one: "Du har en oläst notifikation" + other: "Du har <%= count %> olästa notifikationer" + zero: "Du har inga olästa notifikationer" people: edit_my_profile: "Ändra min profil" helper: @@ -200,12 +201,32 @@ sv: add_option: "Lägg till alternativ" limited: "Begränsat: ditt inlägg visas endast för personer som du delar med" markdown_editor: + preview: "Förhandsgranska" + texts: + code: "kod här" + heading: "rubriktext" + insert_image_description_text: "fyll i bildbeskrivning här" + insert_image_help_text: "Fyll i bildlänk här" + insert_image_title: "fyll i bildrubrik här" + insert_link_description_text: "fyll i länkbeskrivning här" + insert_link_help_text: "Fyll i länk här" + italic: "kursiv text" + list: "lista text här" + quote: "citerad text här" + strong: "fet text" tooltips: bold: "Fet" + cancel: "Avbryt meddelande" + code: "Infoga kod" heading: "Rubrik" insert_image: "Infoga bild" insert_link: "Infoga länk" + insert_ordered_list: "Lägg till sorterad lista" + insert_unordered_list: "Lägg till osorterad lista" italic: "Kursiv" + preview: "Förhandsgranska meddelande" + quote: "Infoga citat" + write: "Ändra meddelande" write: "Skriv" near_from: "Sänt från: <%= location %>" option: "Alternativ" @@ -220,7 +241,6 @@ sv: created: "Anmälan skapad" exists: "Anmälan finns redan" reshares: - duplicate: "Du gillar detta va? Du har nämligen redan delat vidare detta inlägg!" post: "Vill du dela vidare inlägget av <%= name %>?" successful: "Lyckades med att dela vidare inlägget." show_more: "Visa mer" @@ -245,6 +265,7 @@ sv: one: "Visa en kommentar till" other: "Visa <%= count %> kommentarer till" zero: "Visa inga fler kommentarer" + no_posts_yet: "Det finns inga inlägg än." original_post_deleted: "Det ursprungliga inlägget har blivit borttaget av författaren." permalink: "Permanent länk" public: "Publik" diff --git a/config/locales/javascript/javascript.te.yml b/config/locales/javascript/javascript.te.yml index 092cd9622..fe23b3881 100644 --- a/config/locales/javascript/javascript.te.yml +++ b/config/locales/javascript/javascript.te.yml @@ -50,10 +50,8 @@ te: create: "సృష్టించు" delete: "తొలగించు" edit: "సవరించు" - failed_to_like: "ఇష్టపడుటలో విఫలమైంది! బహుశా రచయిత మిమ్మల్ని విస్మరిస్తున్నారా?" failed_to_post_message: "సందేశాన్ని పోస్టుచేయుటలో విఫలమైంది!" failed_to_remove: "ప్రవేశాన్ని తొలగించుటలో విఫలమైంది!" - failed_to_reshare: "మళ్ళీ పంచుకోవడంలో విఫలమైంది!" getting_started: alright_ill_wait: "పరవాలేదు, నేను వేచివుంటాను." hey: "ఓయ్, <%= name %>!" @@ -130,8 +128,6 @@ te: status: created: "ఫిర్యాదు విజయవంతంగా సృష్టించబడింది" exists: "ఫిర్యాదు ఇదివరకే ఉంది" - reshares: - duplicate: "అంత బాగుందా? ఆ టపాని మీరు ఇప్పటికే పంచుకున్నారు!" show_more: "ఇంకా చూపించు" stream: comment: "వ్యాఖ్య" diff --git a/config/locales/javascript/javascript.tr.yml b/config/locales/javascript/javascript.tr.yml index a0756bd68..097c138a2 100644 --- a/config/locales/javascript/javascript.tr.yml +++ b/config/locales/javascript/javascript.tr.yml @@ -25,7 +25,6 @@ tr: show: "tüm yorumları görüntüle" confirm_dialog: "Emin misiniz?" delete: "Sil" - failed_to_like: "Beğenme başarısız oldu!" failed_to_post_message: "Gönderi başarısız oldu!" getting_started: alright_ill_wait: "Tamam, ben bekleyeceğim." @@ -85,7 +84,6 @@ tr: write: "yazma" public: "Genel - gönderi herkes tarafından görünür ve arama motorları tarafından bulunur olacak" reshares: - duplicate: "Bu iyi, değil mi? Zaten bu gönderiyi tekrar paylaştın!" post: "<%= name %> kişisinin gönderisini yeniden paylaşamak istiyor musun?" successful: "Gönderi başarıyla yeniden paylaşıldı!" show_more: "daha fazlasını göster" diff --git a/config/locales/javascript/javascript.uk.yml b/config/locales/javascript/javascript.uk.yml index 93ddca011..98f72502e 100644 --- a/config/locales/javascript/javascript.uk.yml +++ b/config/locales/javascript/javascript.uk.yml @@ -53,10 +53,8 @@ uk: no_contacts: "Перш ніж розпочати розмову, треба мати хоча б один контакт." delete: "Вилучити" edit: "Змінити" - failed_to_like: "Не вдалося!" failed_to_post_message: "Не вдалося надіслати повідомлення!" failed_to_remove: "Видалення не завершено!" - failed_to_reshare: "Не вдалося поділитись!" getting_started: alright_ill_wait: "Добре, я почекаю." hey: "Привіт, <%= name %>!" @@ -143,7 +141,6 @@ uk: created: "Донос успішно відправлений" exists: "Донос вже відправлений" reshares: - duplicate: "Настільки круто, так? Ви вже поділилися цим записом!" post: "Поширити допис <%= name %>?" successful: "Ви успішно поділилися записом!" show_more: "показати більше" diff --git a/config/locales/javascript/javascript.vi.yml b/config/locales/javascript/javascript.vi.yml index 3ce23e061..3813bf02c 100644 --- a/config/locales/javascript/javascript.vi.yml +++ b/config/locales/javascript/javascript.vi.yml @@ -30,7 +30,6 @@ vi: confirm_dialog: "Bạn có chắc không?" delete: "Xoá" edit: "Chỉnh sửa" - failed_to_like: "Không thích được!" failed_to_post_message: "Đăng tin thất bại!" getting_started: alright_ill_wait: "Được rồi, tôi sẽ chờ." @@ -68,7 +67,6 @@ vi: near_from: "Gửi từ: <%= location %>" public: "Công khai - bài đăng của bạn được mọi người và máy tìm kiếm nhìn thấy" reshares: - duplicate: "Bạn đã chia sẻ lại tin đó!" post: "Chia sẻ lại bài đăng của <%= name %>?" successful: "Đã chia sẻ lại bài đăng!" show_more: "hiện thêm" diff --git a/config/locales/javascript/javascript.zh-CN.yml b/config/locales/javascript/javascript.zh-CN.yml index 46bca1ae5..47ff47727 100644 --- a/config/locales/javascript/javascript.zh-CN.yml +++ b/config/locales/javascript/javascript.zh-CN.yml @@ -25,7 +25,6 @@ zh-CN: show: "显示所有评论" confirm_dialog: "您确定吗?" delete: "删除" - failed_to_like: "赞失败" failed_to_post_message: "发布消息失败!" getting_started: alright_ill_wait: "以后再说" @@ -57,7 +56,6 @@ zh-CN: limited: "限制 - 只有您想分享的人才看得到您的内容" public: "公开 - 所有人都能看到您的内容,包括搜索引擎" reshares: - duplicate: "您已经转发过了。" post: "要转发 <%= name %> 的内容吗?" successful: "转发成功" show_more: "查看更多" diff --git a/config/locales/javascript/javascript.zh-TW.yml b/config/locales/javascript/javascript.zh-TW.yml index a5665a620..6df1cfe44 100644 --- a/config/locales/javascript/javascript.zh-TW.yml +++ b/config/locales/javascript/javascript.zh-TW.yml @@ -101,16 +101,17 @@ zh-TW: remove_contact: "刪聯絡人" search_no_results: "沒找到聯絡人" conversation: + create: + no_recipient: "欸,必須要有收訊人 !" new: no_contacts: "\x1f開始對話前你必須先加一些聯絡人" create: "建立" delete: "刪除" edit: "編輯" - failed_to_comment: "發表意見失敗。作者可能正在忽視你。" - failed_to_like: "說讚失敗。也許是因為作者正在忽視你。" + errors: + connection: "沒辦法跟伺服器連線。" failed_to_post_message: "貼文失敗!" failed_to_remove: "刪掉這個項目的動作失敗了!" - failed_to_reshare: "轉貼失敗!" getting_started: alright_ill_wait: "好,再說吧。" hey: "嗨,<%= name %>!" @@ -146,6 +147,8 @@ zh-TW: notifications: mark_read: "標示為看過了" mark_unread: "標示為沒看過" + new_notifications: + other: "有<%= count %>則還沒看過的通知" people: edit_my_profile: "編輯自己的個人檔案" helper: @@ -229,7 +232,6 @@ zh-TW: created: "成功產生回報了" exists: "已經有這筆回報了" reshares: - duplicate: "很棒對吧?你已經轉貼過該篇貼文了!" post: "要轉貼 <%= name %> 的貼文嗎?" successful: "貼文轉貼成功!" show_more: "顯示更多" From 1fb6040344d159d3a4b1dfc867d7d661bd2215dd Mon Sep 17 00:00:00 2001 From: cmrd Senya Date: Wed, 7 Dec 2016 20:36:14 +0200 Subject: [PATCH 006/318] new PostController#mentionable_in_comment action --- app/controllers/posts_controller.rb | 17 +- app/models/comment.rb | 8 - .../notifications/mentioned_in_comment.rb | 7 +- app/models/person.rb | 89 +++++++- app/models/status_message.rb | 2 + app/services/post_service.rb | 11 + config/routes.rb | 1 + spec/controllers/posts_controller_spec.rb | 43 ++++ spec/factories.rb | 7 +- spec/models/comment_spec.rb | 19 -- spec/models/person_spec.rb | 83 +++++++ spec/services/post_service_spec.rb | 216 ++++++++++++++++++ 12 files changed, 458 insertions(+), 45 deletions(-) diff --git a/app/controllers/posts_controller.rb b/app/controllers/posts_controller.rb index e88af7a77..2441173bc 100644 --- a/app/controllers/posts_controller.rb +++ b/app/controllers/posts_controller.rb @@ -3,7 +3,7 @@ # the COPYRIGHT file. class PostsController < ApplicationController - before_action :authenticate_user!, only: :destroy + before_action :authenticate_user!, only: %i(destroy mentionable) before_action :set_format_if_malformed_from_status_net, only: :show respond_to :html, :mobile, :json, :xml @@ -50,6 +50,21 @@ class PostsController < ApplicationController end end + def mentionable + respond_to do |format| + format.json { + if params[:id].present? && params[:q].present? + render json: post_service.mentionable_in_comment(params[:id], params[:q]) + else + render nothing: true, status: 204 + end + } + format.any { render nothing: true, status: 406 } + end + rescue ActiveRecord::RecordNotFound + render nothing: true, status: 404 + end + def destroy post_service.destroy(params[:id]) respond_to do |format| diff --git a/app/models/comment.rb b/app/models/comment.rb index 483215f03..fb5446173 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -54,14 +54,6 @@ class Comment < ActiveRecord::Base self[:text] = text.to_s.strip #to_s if for nil, for whatever reason end - def people_allowed_to_be_mentioned - if parent.public? - :all - else - [*parent.comments.pluck(:author_id), *parent.likes.pluck(:author_id), parent.author_id].uniq - end - end - def add_mention_subscribers? super && parent.author.local? end diff --git a/app/models/notifications/mentioned_in_comment.rb b/app/models/notifications/mentioned_in_comment.rb index 77038864a..5e5466b68 100644 --- a/app/models/notifications/mentioned_in_comment.rb +++ b/app/models/notifications/mentioned_in_comment.rb @@ -11,12 +11,7 @@ module Notifications end def self.filter_mentions(mentions, mentionable, _recipient_user_ids) - people = mentionable.people_allowed_to_be_mentioned - if people == :all - mentions - else - mentions.where(person_id: people) - end + mentions.joins(:person).merge(Person.allowed_to_be_mentioned_in_a_comment_to(mentionable.parent)) end def mail_job diff --git a/app/models/person.rb b/app/models/person.rb index 8e0d5b6e2..e9eefc6ec 100644 --- a/app/models/person.rb +++ b/app/models/person.rb @@ -62,7 +62,8 @@ class Person < ActiveRecord::Base scope :remote, -> { where('people.owner_id IS NULL') } scope :local, -> { where('people.owner_id IS NOT NULL') } scope :for_json, -> { - select('DISTINCT people.id, people.guid, people.diaspora_handle') + select("people.id, people.guid, people.diaspora_handle") + .distinct .includes(:profile) } @@ -94,6 +95,78 @@ class Person < ActiveRecord::Base .where(:posts => {:root_guid => StatusMessage.guids_for_author(user.person), :type => 'Reshare'} ) } + # This scope selects people where the full name contains the search_str or diaspora ID + # starts with the search_str. + # However, if the search_str doesn't have more than 1 non-whitespace character, it'll return an empty set. + # @param [String] search substring + # @return [Person::ActiveRecord_Relation] + scope :find_by_substring, ->(search_str) { + search_str.strip! + return none if search_str.blank? || search_str.size < 2 + + sql, tokens = search_query_string(search_str) + joins(:profile).where(sql, *tokens) + } + + # Left joins likes and comments to a specific post where people are authors of these comments and likes + # @param [String, Integer] post ID for which comments and likes should be joined + # @return [Person::ActiveRecord_Relation] + scope :left_join_visible_post_interactions_on_authorship, ->(post_id) { + comments_sql = <<-SQL + LEFT OUTER JOIN comments ON + comments.author_id = people.id AND comments.commentable_type = 'Post' AND comments.commentable_id = #{post_id} + SQL + + likes_sql = <<-SQL + LEFT OUTER JOIN likes ON + likes.author_id = people.id AND likes.target_type = 'Post' AND likes.target_id = #{post_id} + SQL + + joins(comments_sql).joins(likes_sql) + } + + # Selects people who can be mentioned in a comment to a specific post. For public posts all people + # are allowed, so no additional constraints are added. For private posts selection is limited to + # people who have posted comments or likes for this post. + # @param [Post] the post for which we query mentionable in comments people + # @return [Person::ActiveRecord_Relation] + scope :allowed_to_be_mentioned_in_a_comment_to, ->(post) { + if post.public? + all + else + left_join_visible_post_interactions_on_authorship(post.id) + .where("comments.id IS NOT NULL OR likes.id IS NOT NULL OR people.id = #{post.author_id}") + end + } + + # This scope adds sorting of people in the order, appropriate for suggesting to a user (current user) who + # has requested a list of the people mentionable in a comment for a specific post. + # Sorts people in the following priority: post author > commenters > likers > contacts > non-contacts + # @param [Post] post for which the mentionable in comment people list is requested + # @param [User] user who requests the people list + # @return [Person::ActiveRecord_Relation] + scope :sort_for_mention_suggestion, ->(post, user) { + left_join_visible_post_interactions_on_authorship(post.id) + .joins("LEFT OUTER JOIN contacts ON people.id = contacts.person_id AND contacts.user_id = #{user.id}") + .joins(:profile) + .select(<<-SQL + people.id = #{unscoped { post.author_id }} AS is_author, + comments.id IS NOT NULL AS is_commenter, + likes.id IS NOT NULL AS is_liker, + contacts.id IS NOT NULL AS is_contact + SQL + ) + .order(<<-SQL + is_author DESC, + is_commenter DESC, + is_liker DESC, + is_contact DESC, + profiles.full_name, + people.diaspora_handle + SQL + ) + } + def self.community_spotlight Person.joins(:roles).where(:roles => {:name => 'spotlight'}) end @@ -128,7 +201,7 @@ class Person < ActiveRecord::Base self.guid end - def self.search_query_string(query) + private_class_method def self.search_query_string(query) query = query.downcase like_operator = AppConfig.postgres? ? "ILIKE" : "LIKE" @@ -146,15 +219,13 @@ class Person < ActiveRecord::Base end def self.search(search_str, user, only_contacts: false, mutual: false) - search_str.strip! - return none if search_str.blank? || search_str.size < 2 - - sql, tokens = search_query_string(search_str) + query = find_by_substring(search_str) + return query if query.is_a?(ActiveRecord::NullRelation) query = if only_contacts - joins(:contacts).where(contacts: {user_id: user.id}) + query.joins(:contacts).where(contacts: {user_id: user.id}) else - joins( + query.joins( "LEFT OUTER JOIN contacts ON contacts.user_id = #{user.id} AND contacts.person_id = people.id" ).searchable(user) end @@ -162,8 +233,6 @@ class Person < ActiveRecord::Base query = query.where(contacts: {sharing: true, receiving: true}) if mutual query.where(closed_account: false) - .where(sql, *tokens) - .includes(:profile) .order(["contacts.user_id IS NULL", "profiles.last_name ASC", "profiles.first_name ASC"]) end diff --git a/app/models/status_message.rb b/app/models/status_message.rb index 28d838536..423ea01fc 100644 --- a/app/models/status_message.rb +++ b/app/models/status_message.rb @@ -95,6 +95,8 @@ class StatusMessage < Post photos.each {|photo| photo.receive(recipient_user_ids) } end + # Note: the next two methods can be safely removed once changes from #6818 are deployed on every pod + # see StatusMessageCreationService#dispatch # Only includes those people, to whom we're going to send a federation entity # (and doesn't define exhaustive list of people who can receive it) def people_allowed_to_be_mentioned diff --git a/app/services/post_service.rb b/app/services/post_service.rb index 99ce0d28e..6d35a385d 100644 --- a/app/services/post_service.rb +++ b/app/services/post_service.rb @@ -31,6 +31,17 @@ class PostService user.retract(post) end + def mentionable_in_comment(post_id, query) + post = find!(post_id) + Person + .allowed_to_be_mentioned_in_a_comment_to(post) + .where.not(id: user.person_id) + .find_by_substring(query) + .sort_for_mention_suggestion(post, user) + .for_json + .limit(15) + end + private attr_reader :user diff --git a/config/routes.rb b/config/routes.rb index 288733244..f71fe120a 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -32,6 +32,7 @@ Diaspora::Application.routes.draw do resources :posts, only: %i(show destroy) do member do get :interactions + get :mentionable end resource :participation, only: %i(create destroy) diff --git a/spec/controllers/posts_controller_spec.rb b/spec/controllers/posts_controller_spec.rb index 7f2d9c9fb..2ce6b677c 100644 --- a/spec/controllers/posts_controller_spec.rb +++ b/spec/controllers/posts_controller_spec.rb @@ -4,6 +4,7 @@ describe PostsController, type: :controller do let(:post) { alice.post(:status_message, text: "ohai", to: alice.aspects.first) } + let(:post_service) { controller.send(:post_service) } describe "#show" do context "user signed in" do @@ -166,6 +167,48 @@ describe PostsController, type: :controller do end end + describe "#mentionable" do + context "with a user signed in" do + before do + sign_in alice + end + + it "returns status 204 without a :q parameter" do + get :mentionable, id: post.id, format: :json + expect(response.status).to eq(204) + end + + it "responses status 406 (not acceptable) on html request" do + get :mentionable, id: post.id, q: "whatever", format: :html + expect(response.status).to eq(406) + end + + it "responses status 404 when the post can't be found" do + expect(post_service).to receive(:find!) do + raise ActiveRecord::RecordNotFound + end + get :mentionable, id: post.id, q: "whatever", format: :json + expect(response.status).to eq(404) + end + + it "calls PostService#mentionable_in_comment and passes the result as a response" do + expect(post_service).to receive(:mentionable_in_comment).with(post.id.to_s, "whatever").and_return([bob.person]) + get :mentionable, id: post.id, q: "whatever", format: :json + expect(response.status).to eq(200) + expect(response.body).to eq([bob.person].to_json) + end + end + + context "without a user signed in" do + it "returns 401" do + allow(post_service).to receive(:mentionable_in_comment).and_return([]) + get :mentionable, id: post.id, q: "whatever", format: :json + expect(response.status).to eq(401) + expect(JSON.parse(response.body)["error"]).to eq(I18n.t("devise.failure.unauthenticated")) + end + end + end + describe "#destroy" do context "own post" do before do diff --git a/spec/factories.rb b/spec/factories.rb index ec8cec960..d89eb7d95 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -32,12 +32,17 @@ FactoryGirl.define do end factory(:person, aliases: %i(author)) do + transient do + first_name nil + end + sequence(:diaspora_handle) {|n| "bob-person-#{n}#{r_str}@example.net" } pod { Pod.find_or_create_by(url: "http://example.net") } serialized_public_key OpenSSL::PKey::RSA.generate(1024).public_key.export - after(:build) do |person| + after(:build) do |person, evaluator| unless person.profile.first_name.present? person.profile = FactoryGirl.build(:profile, person: person) + person.profile.first_name = evaluator.first_name if evaluator.first_name end end after(:create) do |person| diff --git a/spec/models/comment_spec.rb b/spec/models/comment_spec.rb index 05499dc39..82d46566c 100644 --- a/spec/models/comment_spec.rb +++ b/spec/models/comment_spec.rb @@ -23,25 +23,6 @@ describe Comment, type: :model do end end - describe "#people_allowed_to_be_mentioned" do - let(:kate) { FactoryGirl.create(:user_with_aspect, friends: [bob]) } - let(:olga) { FactoryGirl.create(:user_with_aspect, friends: [bob]) } - - it "returns the author and people who have commented or liked the private post" do - eve.comment!(status_bob, "comment text") - kate.like!(status_bob) - olga.participate!(status_bob) - status_bob.reload - expect(comment_alice.people_allowed_to_be_mentioned).to match_array([alice, bob, eve, kate].map(&:person_id)) - end - - it "returns :all for public posts" do - # set parent public - status_bob.update(public: true) - expect(comment_alice.people_allowed_to_be_mentioned).to eq(:all) - end - end - describe "#subscribers" do let(:status_bob) { FactoryGirl.create(:status_message, public: true, author: bob.person) } let(:comment_alice) { diff --git a/spec/models/person_spec.rb b/spec/models/person_spec.rb index bb2bb7d6b..4e65c6ccc 100644 --- a/spec/models/person_spec.rb +++ b/spec/models/person_spec.rb @@ -94,6 +94,89 @@ describe Person, :type => :model do expect(Person.who_have_reshared_a_users_posts(alice)).to eq([reshare.author]) end end + + describe ".find_by_substring" do + it "returns \"none\" when the substring is less than 1 non-space character" do + expect(Person.find_by_substring("R")).to eq(Person.none) + expect(Person.find_by_substring("R ")).to eq(Person.none) + expect(Person.find_by_substring("")).to eq(Person.none) + expect(Person.find_by_substring(" ")).to eq(Person.none) + end + + it "finds a person with a profile name containing the substring" do + substring = r_str + person = FactoryGirl.create(:person, first_name: "A#{substring}A") + expect(Person.find_by_substring(substring)).to include(person) + end + + it "finds a person with a diaspora ID starting with the substring" do + substring = r_str + person = FactoryGirl.create(:person, diaspora_handle: "#{substring}A@pod.tld") + expect(Person.find_by_substring(substring)).to include(person) + end + end + + describe ".allowed_to_be_mentioned_in_a_comment_to" do + let(:status_bob) { bob.post(:status_message, text: "hello", to: bob.aspects.first.id) } + + it "returns the author and people who have commented or liked the private post" do + kate = FactoryGirl.create(:user_with_aspect, friends: [bob]) + olga = FactoryGirl.create(:user_with_aspect, friends: [bob]) + alice.comment!(status_bob, "why so formal?") + eve.comment!(status_bob, "comment text") + kate.like!(status_bob) + olga.participate!(status_bob) + expect( + Person.allowed_to_be_mentioned_in_a_comment_to(status_bob).ids + ).to match_array([alice, bob, eve, kate].map(&:person_id)) + end + + it "returns all for public posts" do + status_bob.update(public: true) # set parent public + expect(Person.allowed_to_be_mentioned_in_a_comment_to(status_bob)).to eq(Person.all) + end + end + + describe ".sort_for_mention_suggestion" do + let(:status_message) { FactoryGirl.create(:status_message) } + + it "returns people sorted in the order: post author > commenters > likers > contacts" do + like = FactoryGirl.create(:like, target: status_message) + comment = FactoryGirl.create(:comment, post: status_message) + current_user = FactoryGirl.create(:user_with_aspect, friends: [alice]) + result = Person.select(:id, :guid).sort_for_mention_suggestion(status_message, current_user) + expect(result[0]).to eq(status_message.author) + expect(result[1]).to eq(comment.author) + expect(result[2]).to eq(like.author) + expect(result[3]).to eq(alice.person) # a contact of the current user + end + + it "sorts people of the same priority by profile name" do + current_user = FactoryGirl.create(:user_with_aspect) + person1 = FactoryGirl.create(:person, first_name: "x2") + person2 = FactoryGirl.create(:person, first_name: "x1") + result = Person + .select(:id, :guid) + .where(id: [person1.id, person2.id]) + .sort_for_mention_suggestion(status_message, current_user) + expect(result[0].id).to eq(person2.id) + expect(result[1].id).to eq(person1.id) + end + + it "sorts people of the same priority and same names by diaspora ID" do + current_user = FactoryGirl.create(:user_with_aspect) + person1 = FactoryGirl.create(:person, diaspora_handle: "x2@pod.tld") + person1.profile.update(first_name: "John", last_name: "Doe") + person2 = FactoryGirl.create(:person, diaspora_handle: "x1@pod.tld") + person2.profile.update(first_name: "John", last_name: "Doe") + result = Person + .select(:id, :guid) + .where(id: [person1.id, person2.id]) + .sort_for_mention_suggestion(status_message, current_user) + expect(result[0].id).to eq(person2.id) + expect(result[1].id).to eq(person1.id) + end + end end describe "delegating" do diff --git a/spec/services/post_service_spec.rb b/spec/services/post_service_spec.rb index b19a1638d..28dfae6c1 100644 --- a/spec/services/post_service_spec.rb +++ b/spec/services/post_service_spec.rb @@ -193,4 +193,220 @@ describe PostService do expect(StatusMessage.find_by_id(post.id)).not_to be_nil end end + + describe "#mentionable_in_comment" do + describe "semi-integration test" do + let(:post_author_attributes) { {first_name: "Ro#{r_str}"} } + let(:post_author) { FactoryGirl.create(:person, post_author_attributes) } + let(:current_user) { FactoryGirl.create(:user_with_aspect) } + let(:post_service) { PostService.new(current_user) } + + shared_context "with commenters and likers" do + # randomize ids of the created people so that the test doesn't pass just because of + # the id sequence matched against the expected ordering + let(:ids) { (1..4).map {|i| Person.maximum(:id) + i }.shuffle } + + before do + # in case when post_author has't been instantiated before this context, specify id + # in order to avoid id conflict with the people generated here + post_author_attributes.merge!(id: ids.max + 1) + end + + let!(:commenter1) { + FactoryGirl.create(:person, id: ids.shift, first_name: "Ro1#{r_str}").tap {|person| + FactoryGirl.create(:comment, author: person, post: post) + } + } + + let!(:commenter2) { + FactoryGirl.create(:person, id: ids.shift, first_name: "Ro2#{r_str}").tap {|person| + FactoryGirl.create(:comment, author: person, post: post) + } + } + + let!(:liker1) { + FactoryGirl.create(:person, id: ids.shift, first_name: "Ro1#{r_str}").tap {|person| + FactoryGirl.create(:like, author: person, target: post) + } + } + + let!(:liker2) { + FactoryGirl.create(:person, id: ids.shift, first_name: "Ro2#{r_str}").tap {|person| + FactoryGirl.create(:like, author: person, target: post) + } + } + end + + shared_context "with a current user's friend" do + let!(:current_users_friend) { + FactoryGirl.create(:person).tap {|friend| + current_user.contacts.create!( + person: friend, + aspects: [current_user.aspects.first], + sharing: true, + receiving: true + ) + } + } + end + + context "with private post" do + let(:post) { FactoryGirl.create(:status_message, text: "ohai", author: post_author) } + + context "when the post doesn't have a visibility for the current user" do + it "doesn't find a post and raises an exception" do + expect { + post_service.mentionable_in_comment(post.id, "Ro") + }.to raise_error(ActiveRecord::RecordNotFound) + end + end + + context "when the post has a visibility for the current user" do + before do + ShareVisibility.batch_import([current_user.id], post) + end + + context "with commenters and likers" do + include_context "with commenters and likers" + + it "returns mention suggestions in the correct order" do + expected_suggestions = [ + post_author, commenter1, commenter2, liker1, liker2 + ] + expect(post_service.mentionable_in_comment(post.id, "Ro")).to eq(expected_suggestions) + end + end + + context "with a current user's friend" do + include_context "with a current user's friend" + + it "doesn't include a contact" do + expect(post_service.mentionable_in_comment(post.id, current_users_friend.first_name)).to be_empty + end + end + + it "doesn't include a non contact" do + expect(post_service.mentionable_in_comment(post.id, eve.person.first_name)).to be_empty + end + end + end + + context "with public post" do + let(:post) { FactoryGirl.create(:status_message, text: "ohai", public: true, author: post_author) } + + context "with commenters and likers and with a current user's friend" do + include_context "with commenters and likers" + include_context "with a current user's friend" + + it "returns mention suggestions in the correct order" do + result = post_service.mentionable_in_comment(post.id, "Ro") + expect(result.size).to be > 7 + # participants: post author, comments, likers + expect(result[0..4]).to eq([post_author, commenter1, commenter2, liker1, liker2]) + # contacts + expect(result[5]).to eq(current_users_friend) + # non-contacts + result[6..-1].each {|person| + expect(person.contacts.where(user_id: current_user.id)).to be_empty + expect(person.profile.first_name).to include("Ro") + } + end + + it "doesn't include people with non-matching names" do + commenter = FactoryGirl.create(:person, first_name: "RRR#{r_str}") + FactoryGirl.create(:comment, author: commenter) + liker = FactoryGirl.create(:person, first_name: "RRR#{r_str}") + FactoryGirl.create(:like, author: liker) + friend = FactoryGirl.create(:person, first_name: "RRR#{r_str}") + current_user.contacts.create!( + person: friend, + aspects: [current_user.aspects.first], + sharing: true, + receiving: true + ) + + result = post_service.mentionable_in_comment(post.id, "Ro") + expect(result).not_to include(commenter) + expect(result).not_to include(liker) + expect(result).not_to include(friend) + end + end + + shared_examples "current user can't mention himself" do + before do + current_user.profile.update(first_name: "Ro#{r_str}") + end + + it "doesn't include current user" do + expect(post_service.mentionable_in_comment(post.id, "Ro")).not_to include(current_user.person) + end + end + + context "when current user is a post author" do + let(:post_author) { current_user.person } + + include_examples "current user can't mention himself" + end + + context "current user is a participant" do + before do + current_user.like!(post) + current_user.comment!(post, "hello") + end + + include_examples "current user can't mention himself" + end + + context "current user is a stranger matching a search pattern" do + include_examples "current user can't mention himself" + end + + it "doesn't fail when the post author doesn't match the requested pattern" do + expect(post_service.mentionable_in_comment(post.id, "#{r_str}#{r_str}#{r_str}")).to be_empty + end + + it "renders a commenter with multiple comments only once" do + person = FactoryGirl.create(:person, first_name: "Ro2#{r_str}") + 2.times { FactoryGirl.create(:comment, author: person, post: post) } + expect(post_service.mentionable_in_comment(post.id, person.first_name).length).to eq(1) + end + end + end + + describe "unit test" do + let(:post_service) { PostService.new(alice) } + + before do + expect(post_service).to receive(:find!).and_return(post) + end + + it "calls Person.allowed_to_be_mentioned_in_a_comment_to" do + expect(Person).to receive(:allowed_to_be_mentioned_in_a_comment_to).with(post).and_call_original + post_service.mentionable_in_comment(post.id, "whatever") + end + + it "calls Person.find_by_substring" do + expect(Person).to receive(:find_by_substring).with("whatever").and_call_original + post_service.mentionable_in_comment(post.id, "whatever") + end + + it "calls Person.sort_for_mention_suggestion" do + expect(Person).to receive(:sort_for_mention_suggestion).with(post, alice).and_call_original + post_service.mentionable_in_comment(post.id, "whatever") + end + + it "calls Person.limit" do + expect_any_instance_of(Person::ActiveRecord_Relation).to receive(:limit).with(15).and_call_original + post_service.mentionable_in_comment(post.id, "whatever") + end + + it "contains a constraint on a current user" do + expect(Person).to receive(:allowed_to_be_mentioned_in_a_comment_to) { Person.all } + expect(Person).to receive(:find_by_substring) { Person.all } + expect(Person).to receive(:sort_for_mention_suggestion) { Person.all } + expect(post_service.mentionable_in_comment(post.id, alice.person.first_name)) + .not_to include(alice.person) + end + end + end end From bd0210a18124a0d74ab9e3e2c55f51259a604255 Mon Sep 17 00:00:00 2001 From: Steffen van Bergerem Date: Sun, 15 Jan 2017 13:30:54 +0100 Subject: [PATCH 007/318] Remove chartbeat and mixpanel support --- app/assets/javascripts/app/app.js | 6 -- .../app/models/post/interactions.js | 8 --- app/helpers/analytics_helper.rb | 69 ------------------- app/views/application/_head.haml | 2 - app/views/layouts/application.html.haml | 3 - app/views/layouts/application.mobile.haml | 3 - config/defaults.yml | 2 - config/diaspora.yml.example | 6 -- config/initializers/secure_headers.rb | 6 -- 9 files changed, 105 deletions(-) delete mode 100644 app/helpers/analytics_helper.rb diff --git a/app/assets/javascripts/app/app.js b/app/assets/javascripts/app/app.js index d95852882..ab45ee73a 100644 --- a/app/assets/javascripts/app/app.js +++ b/app/assets/javascripts/app/app.js @@ -126,12 +126,6 @@ var app = { app.flashMessages = new app.views.FlashMessages({el: $("#flash-container")}); }, - /* mixpanel wrapper function */ - instrument : function(type, name, object, callback) { - if(!window.mixpanel) { return; } - window.mixpanel[type](name, object, callback); - }, - setupDisabledLinks: function() { $("a.disabled").click(function(event) { event.preventDefault(); diff --git a/app/assets/javascripts/app/models/post/interactions.js b/app/assets/javascripts/app/models/post/interactions.js index 3615387e2..b3700b97d 100644 --- a/app/assets/javascripts/app/models/post/interactions.js +++ b/app/assets/javascripts/app/models/post/interactions.js @@ -76,8 +76,6 @@ app.models.Post.Interactions = Backbone.Model.extend({ app.flashMessages.handleAjaxError(response); } }); - - app.instrument("track", "Like"); }, unlike : function() { @@ -87,8 +85,6 @@ app.models.Post.Interactions = Backbone.Model.extend({ self.set({"likes_count" : self.get("likes_count") - 1}); self.likes.trigger("change"); }}); - - app.instrument("track", "Unlike"); }, comment: function(text, options) { @@ -104,8 +100,6 @@ app.models.Post.Interactions = Backbone.Model.extend({ self.trigger('change'); //updates after sync if (options.success) { options.success(); } }); - - app.instrument("track", "Comment"); }, reshare : function(){ @@ -126,8 +120,6 @@ app.models.Post.Interactions = Backbone.Model.extend({ .fail(function(response) { app.flashMessages.handleAjaxError(response); }); - - app.instrument("track", "Reshare"); }, userCanReshare : function(){ diff --git a/app/helpers/analytics_helper.rb b/app/helpers/analytics_helper.rb deleted file mode 100644 index df7f69c6e..000000000 --- a/app/helpers/analytics_helper.rb +++ /dev/null @@ -1,69 +0,0 @@ -# Copyright (c) 2010-2012, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - -module AnalyticsHelper - def include_mixpanel - include_analytics "mixpanel" do - nonced_javascript_tag do - <<-JS.html_safe - (function(d,c){var a,b,g,e;a=d.createElement('script');a.type='text/javascript';a.async=!0;a.src=('https:'===d.location.protocol?'https:':'http:')+'//api.mixpanel.com/site_media/js/api/mixpanel.2.js';b=d.getElementsByTagName('script')[0];b.parentNode.insertBefore(a,b);c._i=[];c.init=function(a,d,f){var b=c;'undefined'!==typeof f?b=c[f]=[]:f='mixpanel';g='disable track track_pageview track_links track_forms register register_once unregister identify name_tag set_config'.split(' '); - for(e=0;e Date: Fri, 27 Jan 2017 23:44:35 +0100 Subject: [PATCH 008/318] Update regex for new mention syntax See #7276 --- lib/diaspora/mentionable.rb | 20 +++++--------- spec/lib/diaspora/mentionable_spec.rb | 38 ++++++++++++++++++++++++--- 2 files changed, 42 insertions(+), 16 deletions(-) diff --git a/lib/diaspora/mentionable.rb b/lib/diaspora/mentionable.rb index c922096af..4029054d3 100644 --- a/lib/diaspora/mentionable.rb +++ b/lib/diaspora/mentionable.rb @@ -1,23 +1,20 @@ module Diaspora::Mentionable - # regex for finding mention markup in plain text - # ex. + # regex for finding mention markup in plain text: + # "message @{user@pod.net} text" + # it can also contain a name, which gets used as the link text: # "message @{User Name; user@pod.net} text" # will yield "User Name" and "user@pod.net" - REGEX = /(@\{(.+?; [^\}]+)\})/ + REGEX = /@\{(?:([^\}]+?); )?([^\} ]+)\}/ # class attribute that will be added to all mention html links PERSON_HREF_CLASS = "mention hovercardable" def self.mention_attrs(mention_str) - mention = mention_str.match(REGEX)[2] - del_pos = mention.rindex(/;/) + name, diaspora_id = mention_str.match(REGEX).captures - name = mention[0..(del_pos - 1)].strip - handle = mention[(del_pos + 1)..-1].strip - - [name, handle] + [name.try(:strip), diaspora_id.strip] end # takes a message text and returns the text with mentions in (html escaped) @@ -46,7 +43,7 @@ module Diaspora::Mentionable # @return [Array] array of people def self.people_from_string(msg_text) identifiers = msg_text.to_s.scan(REGEX).map do |match_str| - _, identifier = mention_attrs(match_str.first) + identifier = match_str.second.strip identifier if Validation::Rule::DiasporaId.new.valid_value?(identifier) end @@ -72,8 +69,6 @@ module Diaspora::Mentionable } end - private - private_class_method def self.find_or_fetch_person_by_identifier(identifier) Person.find_or_fetch_by_identifier(identifier) rescue DiasporaFederation::Discovery::DiscoveryError @@ -113,5 +108,4 @@ module Diaspora::Mentionable "[#{display_name.presence || person.name}](#{local_or_remote_person_path(person)})" end end - end diff --git a/spec/lib/diaspora/mentionable_spec.rb b/spec/lib/diaspora/mentionable_spec.rb index de8e2fcac..6a6274ad6 100644 --- a/spec/lib/diaspora/mentionable_spec.rb +++ b/spec/lib/diaspora/mentionable_spec.rb @@ -18,7 +18,27 @@ three "Eve> E. STR end - describe "#format" do + describe ".mention_attrs" do + it "returns name and diaspora ID" do + name, diaspora_id = Diaspora::Mentionable.mention_attrs("@{#{@names[0]}; #{@people[0].diaspora_handle}}") + expect(name).to eq(@names[0]) + expect(diaspora_id).to eq(@people[0].diaspora_handle) + end + + it "returns only diaspora-ID when no name is included" do + name, diaspora_id = Diaspora::Mentionable.mention_attrs("@{#{@people[0].diaspora_handle}}") + expect(diaspora_id).to eq(@people[0].diaspora_handle) + expect(name).to be_nil + end + + it "trims the name if available" do + name, diaspora_id = Diaspora::Mentionable.mention_attrs("@{#{@names[0]} ; #{@people[0].diaspora_handle}}") + expect(name).to eq(@names[0]) + expect(diaspora_id).to eq(@people[0].diaspora_handle) + end + end + + describe ".format" do context "html output" do it "adds the links to the formatted message" do fmt_msg = Diaspora::Mentionable.format(@test_txt, @people) @@ -64,12 +84,24 @@ STR end end - describe "#people_from_string" do + describe ".people_from_string" do it "extracts the mentioned people from the text" do ppl = Diaspora::Mentionable.people_from_string(@test_txt) expect(ppl).to match_array(@people) end + it "extracts the mentioned people from the text without name" do + text = "test @{#{@people[0].diaspora_handle}} test" + ppl = Diaspora::Mentionable.people_from_string(text) + expect(ppl).to match_array([@people[0]]) + end + + it "extracts the mentioned people from the text mixed mentions (with and without name)" do + text = "@{#{@people[0].diaspora_handle}} and @{#{@names[1]}; #{@people[1].diaspora_handle}}" + ppl = Diaspora::Mentionable.people_from_string(text) + expect(ppl).to match_array([@people[0], @people[1]]) + end + describe "returns an empty array if nobody was found" do it "gets a post without mentions" do ppl = Diaspora::Mentionable.people_from_string("post w/o mentions") @@ -102,7 +134,7 @@ STR end end - describe "#filter_people" do + describe ".filter_people" do before do @user_a = FactoryGirl.create(:user_with_aspect, username: "user_a") @user_b = FactoryGirl.create(:user, username: "user_b") From 322f92110a44f9c0cd77592b71f53b4f41b78174 Mon Sep 17 00:00:00 2001 From: Benjamin Neff Date: Sat, 28 Jan 2017 23:54:06 +0100 Subject: [PATCH 009/318] Backport new mention syntax to old syntax for backward compatibility See #7276 --- lib/diaspora/mentionable.rb | 29 ++++++++++++++------- lib/diaspora/mentions_container.rb | 5 ++++ spec/lib/diaspora/mentionable_spec.rb | 25 ++++++++++++++++++ spec/shared_behaviors/mentions_container.rb | 10 +++++++ 4 files changed, 60 insertions(+), 9 deletions(-) diff --git a/lib/diaspora/mentionable.rb b/lib/diaspora/mentionable.rb index 4029054d3..f1b8cc918 100644 --- a/lib/diaspora/mentionable.rb +++ b/lib/diaspora/mentionable.rb @@ -29,8 +29,8 @@ module Diaspora::Mentionable people = [*people] msg_text.to_s.gsub(REGEX) {|match_str| - name, handle = mention_attrs(match_str) - person = people.find {|p| p.diaspora_handle == handle } + name, diaspora_id = mention_attrs(match_str) + person = people.find {|p| p.diaspora_handle == diaspora_id } ERB::Util.h(MentionsInternal.mention_link(person, name, opts)) } @@ -42,10 +42,7 @@ module Diaspora::Mentionable # @param [String] text containing mentions # @return [Array] array of people def self.people_from_string(msg_text) - identifiers = msg_text.to_s.scan(REGEX).map do |match_str| - identifier = match_str.second.strip - identifier if Validation::Rule::DiasporaId.new.valid_value?(identifier) - end + identifiers = msg_text.to_s.scan(REGEX).map {|match_str| match_str.second.strip } identifiers.compact.uniq.map {|identifier| find_or_fetch_person_by_identifier(identifier) }.compact end @@ -61,16 +58,30 @@ module Diaspora::Mentionable mentioned_ppl = people_from_string(msg_text) msg_text.to_s.gsub(REGEX) {|match_str| - name, handle = mention_attrs(match_str) - person = mentioned_ppl.find {|p| p.diaspora_handle == handle } + name, diaspora_id = mention_attrs(match_str) + person = mentioned_ppl.find {|p| p.diaspora_handle == diaspora_id } mention = MentionsInternal.profile_link(person, name) unless allowed_people.include?(person.id) mention || match_str } end + # Regex to find mentions with new syntax, only used for backporting to old syntax + NEW_SYNTAX_REGEX = /@\{[^ ]+\}/ + + # replaces new syntax with old syntax, to be compatible with old pods + # @deprecated remove when most of the posts can handle the new syntax + def self.backport_mention_syntax(text) + text.to_s.gsub(NEW_SYNTAX_REGEX) do |match_str| + _, diaspora_id = mention_attrs(match_str) + person = find_or_fetch_person_by_identifier(diaspora_id) + old_syntax = "@{#{person.name}; #{diaspora_id}}" if person + old_syntax || match_str + end + end + private_class_method def self.find_or_fetch_person_by_identifier(identifier) - Person.find_or_fetch_by_identifier(identifier) + Person.find_or_fetch_by_identifier(identifier) if Validation::Rule::DiasporaId.new.valid_value?(identifier) rescue DiasporaFederation::Discovery::DiscoveryError nil end diff --git a/lib/diaspora/mentions_container.rb b/lib/diaspora/mentions_container.rb index 5364aa5ae..6aea4acf5 100644 --- a/lib/diaspora/mentions_container.rb +++ b/lib/diaspora/mentions_container.rb @@ -3,6 +3,11 @@ module Diaspora extend ActiveSupport::Concern included do + before_create do + # TODO: remove when most of the posts can handle the new syntax + self.text = Diaspora::Mentionable.backport_mention_syntax(text) if text + end + after_create :create_mentions has_many :mentions, as: :mentions_container, dependent: :destroy end diff --git a/spec/lib/diaspora/mentionable_spec.rb b/spec/lib/diaspora/mentionable_spec.rb index 6a6274ad6..b01161a82 100644 --- a/spec/lib/diaspora/mentionable_spec.rb +++ b/spec/lib/diaspora/mentionable_spec.rb @@ -175,4 +175,29 @@ STR expect(txt).to include(@mention_b) end end + + describe ".backport_mention_syntax" do + it "replaces the new syntax with the old syntax" do + text = "mention @{#{@people[0].diaspora_handle}} text" + expected_text = "mention @{#{@people[0].name}; #{@people[0].diaspora_handle}} text" + expect(Diaspora::Mentionable.backport_mention_syntax(text)).to eq(expected_text) + end + + it "does not change the text, when the mention includes a name" do + text = "mention @{#{@names[0]}; #{@people[0].diaspora_handle}} text" + expect(Diaspora::Mentionable.backport_mention_syntax(text)).to eq(text) + end + + it "does not change the text, when the person is not found" do + text = "mention @{non_existing_user@example.org} text" + expect(Person).to receive(:find_or_fetch_by_identifier).with("non_existing_user@example.org").and_return(nil) + expect(Diaspora::Mentionable.backport_mention_syntax(text)).to eq(text) + end + + it "does not change the text, when the diaspora ID is invalid" do + text = "mention @{invalid_diaspora_id} text" + expect(Person).not_to receive(:find_or_fetch_by_identifier) + expect(Diaspora::Mentionable.backport_mention_syntax(text)).to eq(text) + end + end end diff --git a/spec/shared_behaviors/mentions_container.rb b/spec/shared_behaviors/mentions_container.rb index 87dedfef5..42633e6e9 100644 --- a/spec/shared_behaviors/mentions_container.rb +++ b/spec/shared_behaviors/mentions_container.rb @@ -10,6 +10,16 @@ shared_examples_for "it is mentions container" do target } + describe ".before_create" do + it "backports mention syntax to old syntax" do + text = "mention @{#{people[0].diaspora_handle}} text" + expected_text = "mention @{#{people[0].name}; #{people[0].diaspora_handle}} text" + obj = FactoryGirl.build(described_class.to_s.underscore.to_sym, text: text, author: alice.person) + obj.save + expect(obj.text).to eq(expected_text) + end + end + describe ".after_create" do it "calls create_mentions" do expect(target).to receive(:create_mentions).and_call_original From 0e89d601178a339851c81c4a1b2d53ce347aab62 Mon Sep 17 00:00:00 2001 From: Benjamin Neff Date: Sun, 29 Jan 2017 01:45:32 +0100 Subject: [PATCH 010/318] Use name of mentioned person in plain text --- lib/diaspora/message_renderer.rb | 2 +- spec/lib/diaspora/message_renderer_spec.rb | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/diaspora/message_renderer.rb b/lib/diaspora/message_renderer.rb index de616f3d9..9540db631 100644 --- a/lib/diaspora/message_renderer.rb +++ b/lib/diaspora/message_renderer.rb @@ -79,7 +79,7 @@ module Diaspora end def make_mentions_plain_text - @message = Diaspora::Mentionable.format message, [], plain_text: true + @message = Diaspora::Mentionable.format message, options[:mentioned_people], plain_text: true end def render_tags diff --git a/spec/lib/diaspora/message_renderer_spec.rb b/spec/lib/diaspora/message_renderer_spec.rb index fa0aa3b3b..539edec2b 100644 --- a/spec/lib/diaspora/message_renderer_spec.rb +++ b/spec/lib/diaspora/message_renderer_spec.rb @@ -191,6 +191,18 @@ describe Diaspora::MessageRenderer do text = "#hashtag message" expect(message(text).plain_text_without_markdown).to eq text end + + context "with mention" do + it "contains the name of the mentioned person" do + msg = message("@{#{alice.diaspora_handle}} is cool", mentioned_people: alice.person) + expect(msg.plain_text_without_markdown).to eq "#{alice.name} is cool" + end + + it "uses the name from mention when the mention contains a name" do + msg = message("@{Alice; #{alice.diaspora_handle}} is cool", mentioned_people: alice.person) + expect(msg.plain_text_without_markdown).to eq "Alice is cool" + end + end end describe "#urls" do From 84e2a131cfecff8587e87e401bd52523b21b3e3a Mon Sep 17 00:00:00 2001 From: Benjamin Neff Date: Mon, 30 Jan 2017 23:46:09 +0100 Subject: [PATCH 011/318] Remove { and } from the name when backporting mentions Because } is not compatible with the regex. --- lib/diaspora/mentionable.rb | 2 +- spec/lib/diaspora/mentionable_spec.rb | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/diaspora/mentionable.rb b/lib/diaspora/mentionable.rb index f1b8cc918..de9cfb5f3 100644 --- a/lib/diaspora/mentionable.rb +++ b/lib/diaspora/mentionable.rb @@ -75,7 +75,7 @@ module Diaspora::Mentionable text.to_s.gsub(NEW_SYNTAX_REGEX) do |match_str| _, diaspora_id = mention_attrs(match_str) person = find_or_fetch_person_by_identifier(diaspora_id) - old_syntax = "@{#{person.name}; #{diaspora_id}}" if person + old_syntax = "@{#{person.name.delete('{}')}; #{diaspora_id}}" if person old_syntax || match_str end end diff --git a/spec/lib/diaspora/mentionable_spec.rb b/spec/lib/diaspora/mentionable_spec.rb index b01161a82..f48e495fa 100644 --- a/spec/lib/diaspora/mentionable_spec.rb +++ b/spec/lib/diaspora/mentionable_spec.rb @@ -183,6 +183,14 @@ STR expect(Diaspora::Mentionable.backport_mention_syntax(text)).to eq(expected_text) end + it "removes curly braces from name of the mentioned person when adding it" do + profile = FactoryGirl.build(:profile, first_name: "{Alice}", last_name: "(Smith) [123]") + person = FactoryGirl.create(:person, profile: profile) + text = "mention @{#{person.diaspora_handle}} text" + expected_text = "mention @{Alice (Smith) [123]; #{person.diaspora_handle}} text" + expect(Diaspora::Mentionable.backport_mention_syntax(text)).to eq(expected_text) + end + it "does not change the text, when the mention includes a name" do text = "mention @{#{@names[0]}; #{@people[0].diaspora_handle}} text" expect(Diaspora::Mentionable.backport_mention_syntax(text)).to eq(text) From 2d8d0255dd9f1aadb567eff0fb27c2454bb0428c Mon Sep 17 00:00:00 2001 From: Benjamin Neff Date: Tue, 31 Jan 2017 00:49:28 +0100 Subject: [PATCH 012/318] Improve handling with new mention syntax without name * fallback to diaspora ID when person is not found * fix filter_people when the person is not found * write some more tests --- lib/diaspora/mentionable.rb | 23 ++-- spec/lib/diaspora/mentionable_spec.rb | 153 +++++++++++++-------- spec/lib/diaspora/message_renderer_spec.rb | 5 + 3 files changed, 110 insertions(+), 71 deletions(-) diff --git a/lib/diaspora/mentionable.rb b/lib/diaspora/mentionable.rb index de9cfb5f3..72a0ffcf5 100644 --- a/lib/diaspora/mentionable.rb +++ b/lib/diaspora/mentionable.rb @@ -14,7 +14,7 @@ module Diaspora::Mentionable def self.mention_attrs(mention_str) name, diaspora_id = mention_str.match(REGEX).captures - [name.try(:strip), diaspora_id.strip] + [name.try(:strip).presence, diaspora_id.strip] end # takes a message text and returns the text with mentions in (html escaped) @@ -32,7 +32,7 @@ module Diaspora::Mentionable name, diaspora_id = mention_attrs(match_str) person = people.find {|p| p.diaspora_handle == diaspora_id } - ERB::Util.h(MentionsInternal.mention_link(person, name, opts)) + ERB::Util.h(MentionsInternal.mention_link(person, name, diaspora_id, opts)) } end @@ -60,9 +60,12 @@ module Diaspora::Mentionable msg_text.to_s.gsub(REGEX) {|match_str| name, diaspora_id = mention_attrs(match_str) person = mentioned_ppl.find {|p| p.diaspora_handle == diaspora_id } - mention = MentionsInternal.profile_link(person, name) unless allowed_people.include?(person.id) - mention || match_str + if person && allowed_people.include?(person.id) + match_str + else + MentionsInternal.profile_link(person, name, diaspora_id) + end } end @@ -97,11 +100,11 @@ module Diaspora::Mentionable # @param [Person] AR Person # @param [String] display name # @param [Hash] formatting options - def self.mention_link(person, display_name, opts) - return display_name unless person.present? + def self.mention_link(person, display_name, diaspora_id, opts) + return display_name || diaspora_id unless person.present? if opts[:plain_text] - display_name.presence || person.name + display_name || person.name else person_link(person, class: PERSON_HREF_CLASS, display_name: display_name) end @@ -113,10 +116,10 @@ module Diaspora::Mentionable # @param [Person] AR Person # @param [String] display name # @return [String] markdown person link - def self.profile_link(person, display_name) - return display_name unless person.present? + def self.profile_link(person, display_name, diaspora_id) + return display_name || diaspora_id unless person.present? - "[#{display_name.presence || person.name}](#{local_or_remote_person_path(person)})" + "[#{display_name || person.name}](#{local_or_remote_person_path(person)})" end end end diff --git a/spec/lib/diaspora/mentionable_spec.rb b/spec/lib/diaspora/mentionable_spec.rb index f48e495fa..58b453c17 100644 --- a/spec/lib/diaspora/mentionable_spec.rb +++ b/spec/lib/diaspora/mentionable_spec.rb @@ -1,66 +1,74 @@ describe Diaspora::Mentionable do include PeopleHelper - before do - @people = [alice, bob, eve].map(&:person) - @names = %w(Alice\ A Bob\ B "Eve>\ E) - @test_txt = <<-STR + let(:people) { [alice, bob, eve].map(&:person) } + let(:names) { %w(Alice\ A Bob\ B "Eve>\ E) } + + let(:test_text_with_names) { <<-STR } This post contains a lot of mentions -one @{#{@names[0]}; #{@people[0].diaspora_handle}}, -two @{#{@names[1]}; #{@people[1].diaspora_handle}} and finally -three @{#{@names[2]}; #{@people[2].diaspora_handle}}. +one @{#{names[0]}; #{people[0].diaspora_handle}}, +two @{#{names[1]}; #{people[1].diaspora_handle}} and finally +three @{#{names[2]}; #{people[2].diaspora_handle}}. STR - @test_txt_plain = <<-STR + + let(:test_text_without_names) { <<-STR } This post contains a lot of mentions -one Alice A, -two Bob B and finally -three "Eve> E. +one @{#{people[0].diaspora_handle}}, +two @{#{people[1].diaspora_handle}} and finally +three @{#{people[2].diaspora_handle}}. STR - end describe ".mention_attrs" do it "returns name and diaspora ID" do - name, diaspora_id = Diaspora::Mentionable.mention_attrs("@{#{@names[0]}; #{@people[0].diaspora_handle}}") - expect(name).to eq(@names[0]) - expect(diaspora_id).to eq(@people[0].diaspora_handle) + name, diaspora_id = Diaspora::Mentionable.mention_attrs("@{#{names[0]}; #{people[0].diaspora_handle}}") + expect(name).to eq(names[0]) + expect(diaspora_id).to eq(people[0].diaspora_handle) end it "returns only diaspora-ID when no name is included" do - name, diaspora_id = Diaspora::Mentionable.mention_attrs("@{#{@people[0].diaspora_handle}}") - expect(diaspora_id).to eq(@people[0].diaspora_handle) + name, diaspora_id = Diaspora::Mentionable.mention_attrs("@{#{people[0].diaspora_handle}}") + expect(diaspora_id).to eq(people[0].diaspora_handle) expect(name).to be_nil end it "trims the name if available" do - name, diaspora_id = Diaspora::Mentionable.mention_attrs("@{#{@names[0]} ; #{@people[0].diaspora_handle}}") - expect(name).to eq(@names[0]) - expect(diaspora_id).to eq(@people[0].diaspora_handle) + name, diaspora_id = Diaspora::Mentionable.mention_attrs("@{#{names[0]} ; #{people[0].diaspora_handle}}") + expect(name).to eq(names[0]) + expect(diaspora_id).to eq(people[0].diaspora_handle) end end describe ".format" do context "html output" do it "adds the links to the formatted message" do - fmt_msg = Diaspora::Mentionable.format(@test_txt, @people) + fmt_msg = Diaspora::Mentionable.format(test_text_with_names, people) - [@people, @names].transpose.each do |person, name| + [people, names].transpose.each do |person, name| expect(fmt_msg).to include person_link(person, class: "mention hovercardable", display_name: name) end end - it "should work correct when message is escaped html" do - fmt_msg = Diaspora::Mentionable.format(CGI.escapeHTML(@test_txt), @people) + it "adds the links to the formatted message and uses the names from the people" do + fmt_msg = Diaspora::Mentionable.format(test_text_without_names, people) - [@people, @names].transpose.each do |person, name| + people.each do |person| + expect(fmt_msg).to include person_link(person, class: "mention hovercardable", display_name: person.name) + end + end + + it "should work correct when message is escaped html" do + fmt_msg = Diaspora::Mentionable.format(CGI.escapeHTML(test_text_with_names), people) + + [people, names].transpose.each do |person, name| expect(fmt_msg).to include person_link(person, class: "mention hovercardable", display_name: name) end end it "escapes the link title (name)" do name = "
" - test_txt = "two @{#{name}; #{@people[0].diaspora_handle}} and finally" + test_txt = "two @{#{name}; #{people[0].diaspora_handle}} and finally" - fmt_msg = Diaspora::Mentionable.format(test_txt, @people) + fmt_msg = Diaspora::Mentionable.format(test_txt, people) expect(fmt_msg).not_to include(name) expect(fmt_msg).to include(">", "<", "'") # ">", "<", "'" @@ -69,9 +77,9 @@ STR context "plain text output" do it "removes mention markup and displays unformatted name" do - fmt_msg = Diaspora::Mentionable.format(@test_txt, @people, plain_text: true) + fmt_msg = Diaspora::Mentionable.format(test_text_with_names, people, plain_text: true) - @names.each do |name| + names.each do |name| expect(fmt_msg).to include CGI.escapeHTML(name) end expect(fmt_msg).not_to include "", "hovercardable" @@ -79,27 +87,46 @@ STR end it "leaves the names of people that cannot be found" do - fmt_msg = Diaspora::Mentionable.format(@test_txt, []) - expect(fmt_msg).to eql @test_txt_plain + test_txt_plain = <<-STR +This post contains a lot of mentions +one Alice A, +two Bob B and finally +three "Eve> E. +STR + + fmt_msg = Diaspora::Mentionable.format(test_text_with_names, []) + expect(fmt_msg).to eql test_txt_plain + end + + it "uses the diaspora ID when the person cannot be found" do + test_txt_plain = <<-STR +This post contains a lot of mentions +one #{people[0].diaspora_handle}, +two #{people[1].diaspora_handle} and finally +three #{people[2].diaspora_handle}. +STR + + fmt_msg = Diaspora::Mentionable.format(test_text_without_names, []) + expect(fmt_msg).to eql test_txt_plain end end describe ".people_from_string" do it "extracts the mentioned people from the text" do - ppl = Diaspora::Mentionable.people_from_string(@test_txt) - expect(ppl).to match_array(@people) + ppl = Diaspora::Mentionable.people_from_string(test_text_with_names) + expect(ppl).to match_array(people) end it "extracts the mentioned people from the text without name" do - text = "test @{#{@people[0].diaspora_handle}} test" + text = "test @{#{people[0].diaspora_handle}} test" ppl = Diaspora::Mentionable.people_from_string(text) - expect(ppl).to match_array([@people[0]]) + expect(ppl).to match_array([people[0]]) end it "extracts the mentioned people from the text mixed mentions (with and without name)" do - text = "@{#{@people[0].diaspora_handle}} and @{#{@names[1]}; #{@people[1].diaspora_handle}}" + text = "@{#{people[0].diaspora_handle}} and @{#{names[1]}; #{people[1].diaspora_handle}}" ppl = Diaspora::Mentionable.people_from_string(text) - expect(ppl).to match_array([@people[0], @people[1]]) + expect(ppl).to match_array([people[0], people[1]]) end describe "returns an empty array if nobody was found" do @@ -135,51 +162,55 @@ STR end describe ".filter_people" do + let(:user_a) { FactoryGirl.create(:user_with_aspect, username: "user_a") } + let(:user_b) { FactoryGirl.create(:user, username: "user_b") } + let(:user_c) { FactoryGirl.create(:user, username: "user_c") } + before do - @user_a = FactoryGirl.create(:user_with_aspect, username: "user_a") - @user_b = FactoryGirl.create(:user, username: "user_b") - @user_c = FactoryGirl.create(:user, username: "user_c") + user_a.aspects.create!(name: "second") - @user_a.aspects.create!(name: "second") - - @mention_b = "@{user B; #{@user_b.diaspora_handle}}" - @mention_c = "@{user C; #{@user_c.diaspora_handle}}" - - @user_a.share_with(@user_b.person, @user_a.aspects.where(name: "generic")) - @user_a.share_with(@user_c.person, @user_a.aspects.where(name: "second")) - - @test_txt_b = "mentioning #{@mention_b}" - @test_txt_c = "mentioning #{@mention_c}" - @test_txt_bc = "mentioning #{@mention_b}} and #{@mention_c}" + user_a.share_with(user_b.person, user_a.aspects.where(name: "generic")) + user_a.share_with(user_c.person, user_a.aspects.where(name: "second")) end it "filters mention, if contact is not in a given aspect" do + mention = "@{user C; #{user_c.diaspora_handle}}" txt = Diaspora::Mentionable.filter_people( - @test_txt_c, - @user_a.aspects.where(name: "generic").first.contacts.map(&:person_id) + "mentioning #{mention}", + user_a.aspects.where(name: "generic").first.contacts.map(&:person_id) ) expect(txt).to include("user C") - expect(txt).to include(local_or_remote_person_path(@user_c.person)) + expect(txt).to include(local_or_remote_person_path(user_c.person)) expect(txt).not_to include("href") - expect(txt).not_to include(@mention_c) + expect(txt).not_to include(mention) end it "leaves mention, if contact is in a given aspect" do + mention = "@{user B; #{user_b.diaspora_handle}}" txt = Diaspora::Mentionable.filter_people( - @test_txt_b, - @user_a.aspects.where(name: "generic").first.contacts.map(&:person_id) + "mentioning #{mention}", + user_a.aspects.where(name: "generic").first.contacts.map(&:person_id) ) expect(txt).to include("user B") - expect(txt).to include(@mention_b) + expect(txt).to include(mention) + end + + it "works if the person cannot be found" do + expect(Person).to receive(:find_or_fetch_by_identifier).with("non_existing_user@example.org").and_return(nil) + + mention = "@{non_existing_user@example.org}" + txt = Diaspora::Mentionable.filter_people("mentioning #{mention}", []) + + expect(txt).to eq "mentioning non_existing_user@example.org" end end describe ".backport_mention_syntax" do it "replaces the new syntax with the old syntax" do - text = "mention @{#{@people[0].diaspora_handle}} text" - expected_text = "mention @{#{@people[0].name}; #{@people[0].diaspora_handle}} text" + text = "mention @{#{people[0].diaspora_handle}} text" + expected_text = "mention @{#{people[0].name}; #{people[0].diaspora_handle}} text" expect(Diaspora::Mentionable.backport_mention_syntax(text)).to eq(expected_text) end @@ -192,7 +223,7 @@ STR end it "does not change the text, when the mention includes a name" do - text = "mention @{#{@names[0]}; #{@people[0].diaspora_handle}} text" + text = "mention @{#{names[0]}; #{people[0].diaspora_handle}} text" expect(Diaspora::Mentionable.backport_mention_syntax(text)).to eq(text) end diff --git a/spec/lib/diaspora/message_renderer_spec.rb b/spec/lib/diaspora/message_renderer_spec.rb index 539edec2b..78611a324 100644 --- a/spec/lib/diaspora/message_renderer_spec.rb +++ b/spec/lib/diaspora/message_renderer_spec.rb @@ -202,6 +202,11 @@ describe Diaspora::MessageRenderer do msg = message("@{Alice; #{alice.diaspora_handle}} is cool", mentioned_people: alice.person) expect(msg.plain_text_without_markdown).to eq "Alice is cool" end + + it "uses the diaspora ID when the person cannot be found" do + msg = message("@{#{alice.diaspora_handle}} is cool", mentioned_people: []) + expect(msg.plain_text_without_markdown).to eq "#{alice.diaspora_handle} is cool" + end end end From 408645cccc03201c2a1504e9e1211a0fc0469447 Mon Sep 17 00:00:00 2001 From: Steffen van Bergerem Date: Mon, 30 Jan 2017 12:14:25 +0100 Subject: [PATCH 013/318] Use new mention syntax in the publisher --- app/assets/javascripts/app/views/publisher/mention_view.js | 2 +- spec/javascripts/app/views/publisher_mention_view_spec.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/assets/javascripts/app/views/publisher/mention_view.js b/app/assets/javascripts/app/views/publisher/mention_view.js index 86b3b07aa..f732c0247 100644 --- a/app/assets/javascripts/app/views/publisher/mention_view.js +++ b/app/assets/javascripts/app/views/publisher/mention_view.js @@ -6,7 +6,7 @@ app.views.PublisherMention = app.views.SearchBase.extend({ mentionRegex: /@([^@\s]+)$/, templates: { - mentionItemSyntax: _.template("@{<%= name %> ; <%= handle %>}"), + mentionItemSyntax: _.template("@{<%= handle %>}"), mentionItemHighlight: _.template("<%= name %>") }, diff --git a/spec/javascripts/app/views/publisher_mention_view_spec.js b/spec/javascripts/app/views/publisher_mention_view_spec.js index d4e9417e3..c95a3247a 100644 --- a/spec/javascripts/app/views/publisher_mention_view_spec.js +++ b/spec/javascripts/app/views/publisher_mention_view_spec.js @@ -189,7 +189,7 @@ describe("app.views.PublisherMention", function() { it("sets the correct messageText", function() { this.view.updateMessageTexts(); - expect(this.view.inputBox.data("messageText")).toBe("@user1 Text before @{user1 ; user1@pod.tld}\ntext after"); + expect(this.view.inputBox.data("messageText")).toBe("@user1 Text before @{user1@pod.tld}\ntext after"); }); it("formats overlay text to HTML", function() { @@ -468,7 +468,7 @@ describe("app.views.PublisherMention", function() { this.view.typeaheadInput.typeahead("val", "user"); this.view.typeaheadInput.typeahead("open"); this.view.$(".tt-suggestion").first().click(); - expect(this.view.getTextForSubmit()).toBe("@{user1 ; user1@pod.tld}"); + expect(this.view.getTextForSubmit()).toBe("@{user1@pod.tld}"); }); it("returns normal text if nobody has been mentioned", function() { From b3c412d38f106891b66fd0d1fc09ea1cb6467280 Mon Sep 17 00:00:00 2001 From: Steffen van Bergerem Date: Mon, 30 Jan 2017 12:50:03 +0100 Subject: [PATCH 014/318] Display mention syntax in publisher instead of username --- .../app/views/publisher/mention_view.js | 42 ++++------------ .../app/views/publisher_mention_view_spec.js | 48 +++++++++++-------- 2 files changed, 39 insertions(+), 51 deletions(-) diff --git a/app/assets/javascripts/app/views/publisher/mention_view.js b/app/assets/javascripts/app/views/publisher/mention_view.js index f732c0247..0641e2fcc 100644 --- a/app/assets/javascripts/app/views/publisher/mention_view.js +++ b/app/assets/javascripts/app/views/publisher/mention_view.js @@ -2,13 +2,8 @@ app.views.PublisherMention = app.views.SearchBase.extend({ triggerChar: "@", - invisibleChar: "\u200B", // zero width space mentionRegex: /@([^@\s]+)$/, - - templates: { - mentionItemSyntax: _.template("@{<%= handle %>}"), - mentionItemHighlight: _.template("<%= name %>") - }, + mentionSyntaxTemplate: function(person) { return "@{" + person.handle + "}"; }, events: { "keydown #status_message_fake_text": "onInputBoxKeyDown", @@ -55,8 +50,8 @@ app.views.PublisherMention = app.views.SearchBase.extend({ cleanMentionedPeople: function() { var inputText = this.inputBox.val(); this.mentionedPeople = this.mentionedPeople.filter(function(person) { - return person.name && inputText.indexOf(person.name) > -1; - }); + return person.handle && inputText.indexOf(this.mentionSyntaxTemplate(person)) > -1; + }.bind(this)); this.ignoreDiasporaIds = this.mentionedPeople.map(function(person) { return person.handle; }); }, @@ -70,39 +65,22 @@ app.views.PublisherMention = app.views.SearchBase.extend({ this.addPersonToMentions(person); this.closeSuggestions(); - messageText = messageText.substring(0, triggerCharPosition) + - this.invisibleChar + person.name + messageText.substring(caretPosition); + var mentionText = this.mentionSyntaxTemplate(person); + + messageText = messageText.substring(0, triggerCharPosition) + mentionText + messageText.substring(caretPosition); this.inputBox.val(messageText); this.updateMessageTexts(); this.inputBox.focus(); - var newCaretPosition = triggerCharPosition + person.name.length + 1; + var newCaretPosition = triggerCharPosition + mentionText.length; this.inputBox[0].setSelectionRange(newCaretPosition, newCaretPosition); }, - /** - * Replaces every combination of this.invisibleChar + mention.name by the - * correct syntax for both hidden text and visible one. - * - * For instance, the text "Hello \u200Buser1" will be tranformed to - * "Hello @{user1 ; user1@pod.tld}" in the hidden element and - * "Hello user1" in the element visible to the user. - */ updateMessageTexts: function() { - var fakeMessageText = this.inputBox.val(), - mentionBoxText = _.escape(fakeMessageText), - messageText = fakeMessageText; - - this.mentionedPeople.forEach(function(person) { - var mentionName = this.invisibleChar + person.name; - messageText = messageText.replace(mentionName, this.templates.mentionItemSyntax(person)); - var textHighlight = this.templates.mentionItemHighlight({name: _.escape(person.name)}); - mentionBoxText = mentionBoxText.replace(mentionName, textHighlight); - }, this); - + var messageText = this.inputBox.val(); this.inputBox.data("messageText", messageText); - this.mentionsBox.find(".mentions").html(mentionBoxText); + this.mentionsBox.find(".mentions").html(_.escape(messageText)); }, updateTypeaheadInput: function() { @@ -128,7 +106,7 @@ app.views.PublisherMention = app.views.SearchBase.extend({ prefillMention: function(persons) { persons.forEach(function(person) { this.addPersonToMentions(person); - var text = this.invisibleChar + person.name; + var text = this.mentionSyntaxTemplate(person); if(this.inputBox.val().length !== 0) { text = this.inputBox.val() + " " + text; } diff --git a/spec/javascripts/app/views/publisher_mention_view_spec.js b/spec/javascripts/app/views/publisher_mention_view_spec.js index c95a3247a..54e72ad90 100644 --- a/spec/javascripts/app/views/publisher_mention_view_spec.js +++ b/spec/javascripts/app/views/publisher_mention_view_spec.js @@ -7,7 +7,6 @@ describe("app.views.PublisherMention", function() { it("initializes object properties", function() { this.view = new app.views.PublisherMention({ el: "#publisher" }); expect(this.view.mentionedPeople).toEqual([]); - expect(this.view.invisibleChar).toBe("\u200B"); expect(this.view.triggerChar).toBe("@"); }); @@ -29,6 +28,17 @@ describe("app.views.PublisherMention", function() { }); }); + describe("mentionSyntaxTemplate", function() { + beforeEach(function() { + this.view = new app.views.PublisherMention({el: "#publisher"}); + this.person = {handle: "alice@pod.tld", name: "Alice Awesome"}; + }); + + it("returns the correct mention syntax", function() { + expect(this.view.mentionSyntaxTemplate(this.person)).toBe("@{alice@pod.tld}"); + }); + }); + describe("bindTypeaheadEvents", function() { beforeEach(function() { this.view = new app.views.PublisherMention({ el: "#publisher" }); @@ -92,30 +102,30 @@ describe("app.views.PublisherMention", function() { }); it("removes person from mentioned people if not mentioned anymore", function() { - this.view.addPersonToMentions({name: "user1", handle: "user1@pod.tld"}); + this.view.addPersonToMentions({name: "User Name", handle: "user1@pod.tld"}); expect(this.view.mentionedPeople.length).toBe(1); this.view.cleanMentionedPeople(); expect(this.view.mentionedPeople.length).toBe(0); }); it("removes person from ignored people if not mentioned anymore", function() { - this.view.addPersonToMentions({name: "user1", handle: "user1@pod.tld"}); + this.view.addPersonToMentions({name: "User Name", handle: "user1@pod.tld"}); expect(this.view.ignoreDiasporaIds.length).toBe(1); this.view.cleanMentionedPeople(); expect(this.view.ignoreDiasporaIds.length).toBe(0); }); it("keeps mentioned persons", function() { - this.view.addPersonToMentions({name: "user1", handle: "user1@pod.tld"}); - this.view.inputBox.val("user1"); + this.view.addPersonToMentions({name: "User Name", handle: "user1@pod.tld"}); + this.view.inputBox.val("@{user1@pod.tld}"); expect(this.view.mentionedPeople.length).toBe(1); this.view.cleanMentionedPeople(); expect(this.view.mentionedPeople.length).toBe(1); }); it("keeps mentioned persons for ignored diaspora ids", function() { - this.view.addPersonToMentions({name: "user1", handle: "user1@pod.tld"}); - this.view.inputBox.val("user1"); + this.view.addPersonToMentions({name: "User Name", handle: "user1@pod.tld"}); + this.view.inputBox.val("@{user1@pod.tld}"); expect(this.view.ignoreDiasporaIds.length).toBe(1); this.view.cleanMentionedPeople(); expect(this.view.ignoreDiasporaIds.length).toBe(1); @@ -151,20 +161,20 @@ describe("app.views.PublisherMention", function() { it("correctly formats the text", function() { this.view.onSuggestionSelection({name: "user1337", handle: "user1@pod.tld"}); - expect(this.view.inputBox.val()).toBe("@user1337 Text before \u200Buser1337 text after"); + expect(this.view.inputBox.val()).toBe("@user1337 Text before @{user1@pod.tld} text after"); }); it("replaces the correct mention", function() { this.view.inputBox.val("@user1337 123 user2 @user2 456 @user3 789"); this.view.inputBox[0].setSelectionRange(26, 26); this.view.onSuggestionSelection({name: "user23", handle: "user2@pod.tld"}); - expect(this.view.inputBox.val()).toBe("@user1337 123 user2 \u200Buser23 456 @user3 789"); + expect(this.view.inputBox.val()).toBe("@user1337 123 user2 @{user2@pod.tld} 456 @user3 789"); this.view.inputBox[0].setSelectionRange(9, 9); this.view.onSuggestionSelection({name: "user1337", handle: "user1@pod.tld"}); - expect(this.view.inputBox.val()).toBe("\u200Buser1337 123 user2 \u200Buser23 456 @user3 789"); - this.view.inputBox[0].setSelectionRange(38, 38); + expect(this.view.inputBox.val()).toBe("@{user1@pod.tld} 123 user2 @{user2@pod.tld} 456 @user3 789"); + this.view.inputBox[0].setSelectionRange(54, 54); this.view.onSuggestionSelection({name: "user32", handle: "user3@pod.tld"}); - expect(this.view.inputBox.val()).toBe("\u200Buser1337 123 user2 \u200Buser23 456 \u200Buser32 789"); + expect(this.view.inputBox.val()).toBe("@{user1@pod.tld} 123 user2 @{user2@pod.tld} 456 @{user3@pod.tld} 789"); }); it("calls updateMessageTexts", function() { @@ -175,7 +185,7 @@ describe("app.views.PublisherMention", function() { it("places the caret at the right position", function() { this.view.onSuggestionSelection({"name": "user1WithLongName", "handle": "user1@pod.tld"}); - var expectedCaretPosition = ("@user1337 Text before \u200Buser1WithLongName").length; + var expectedCaretPosition = ("@user1337 Text before @{user1@pod.tld}").length; expect(this.view.inputBox[0].selectionStart).toBe(expectedCaretPosition); }); }); @@ -183,7 +193,7 @@ describe("app.views.PublisherMention", function() { describe("updateMessageTexts", function() { beforeEach(function() { this.view = new app.views.PublisherMention({ el: "#publisher" }); - this.view.inputBox.val("@user1 Text before \u200Buser1\ntext after"); + this.view.inputBox.val("@user1 Text before @{user1@pod.tld}\ntext after"); this.view.mentionedPeople.push({"name": "user1", "handle": "user1@pod.tld"}); }); @@ -195,14 +205,14 @@ describe("app.views.PublisherMention", function() { it("formats overlay text to HTML", function() { this.view.updateMessageTexts(); expect(this.view.mentionsBox.find(".mentions").html()) - .toBe("@user1 Text before user1\ntext after"); + .toBe("@user1 Text before @{user1@pod.tld}\ntext after"); }); it("properly escapes the user input", function() { - this.view.inputBox.val(" @user1 Text before \u200Buser1\ntext after"); + this.view.inputBox.val(" @user1 Text before @{user1@pod.tld}\ntext after"); this.view.updateMessageTexts(); expect(this.view.mentionsBox.find(".mentions").html()) - .toBe("<img src=\"/default.png\"> @user1 Text before user1\ntext after"); + .toBe("<img src=\"/default.png\"> @user1 Text before @{user1@pod.tld}\ntext after"); }); }); @@ -264,7 +274,7 @@ describe("app.views.PublisherMention", function() { this.view.prefillMention([{"name": "user1", "handle": "user1@pod.tld"}]); expect(this.view.addPersonToMentions).toHaveBeenCalledWith({"name": "user1", "handle": "user1@pod.tld"}); expect(this.view.updateMessageTexts).toHaveBeenCalled(); - expect(this.view.inputBox.val()).toBe("\u200Buser1"); + expect(this.view.inputBox.val()).toBe("@{user1@pod.tld}"); }); it("prefills multiple mentions", function() { @@ -276,7 +286,7 @@ describe("app.views.PublisherMention", function() { expect(this.view.addPersonToMentions).toHaveBeenCalledWith({"name": "user1", "handle": "user1@pod.tld"}); expect(this.view.addPersonToMentions).toHaveBeenCalledWith({"name": "user2", "handle": "user2@pod.tld"}); expect(this.view.updateMessageTexts).toHaveBeenCalled(); - expect(this.view.inputBox.val()).toBe("\u200Buser1 \u200Buser2"); + expect(this.view.inputBox.val()).toBe("@{user1@pod.tld} @{user2@pod.tld}"); }); }); From a04f32adcecfa004433bc54cdb37f919f8dae3c6 Mon Sep 17 00:00:00 2001 From: Steffen van Bergerem Date: Mon, 30 Jan 2017 13:00:15 +0100 Subject: [PATCH 015/318] Drop mentions box in the publisher --- .../app/views/publisher/mention_view.js | 3 --- app/assets/stylesheets/mentions.scss | 24 ------------------- app/assets/stylesheets/publisher.scss | 11 --------- app/views/publisher/_publisher.html.haml | 2 -- features/desktop/follows_tags.feature | 2 +- features/step_definitions/posts_steps.rb | 4 ++++ .../app/views/publisher_mention_view_spec.js | 13 ---------- 7 files changed, 5 insertions(+), 54 deletions(-) diff --git a/app/assets/javascripts/app/views/publisher/mention_view.js b/app/assets/javascripts/app/views/publisher/mention_view.js index 0641e2fcc..d678a6bf5 100644 --- a/app/assets/javascripts/app/views/publisher/mention_view.js +++ b/app/assets/javascripts/app/views/publisher/mention_view.js @@ -18,8 +18,6 @@ app.views.PublisherMention = app.views.SearchBase.extend({ // contains the 'fake text' displayed to the user // also has a data-messageText attribute with the original text this.inputBox = this.$("#status_message_fake_text"); - // contains the mentions displayed to the user - this.mentionsBox = this.$(".mentions-box"); this.typeaheadInput = this.$(".typeahead-mention-box"); this.bindTypeaheadEvents(); @@ -80,7 +78,6 @@ app.views.PublisherMention = app.views.SearchBase.extend({ updateMessageTexts: function() { var messageText = this.inputBox.val(); this.inputBox.data("messageText", messageText); - this.mentionsBox.find(".mentions").html(_.escape(messageText)); }, updateTypeaheadInput: function() { diff --git a/app/assets/stylesheets/mentions.scss b/app/assets/stylesheets/mentions.scss index a6920e7b3..c9af7be45 100644 --- a/app/assets/stylesheets/mentions.scss +++ b/app/assets/stylesheets/mentions.scss @@ -64,28 +64,4 @@ } } } - - .mentions-box { - position: absolute; - right: 0px; - bottom: 0px; - left: 0px; - top: 0px; - padding: $padding-base-vertical $padding-base-horizontal; - } - - .mentions { - color: transparent; - font-size: $font-size-base; - font-family: Arial, Helvetica, sans-serif; - overflow: hidden; - width: 100%; - white-space: pre-wrap; - word-wrap: break-word; - - > strong { - background: $background-blue; - font-weight: normal; - } - } } diff --git a/app/assets/stylesheets/publisher.scss b/app/assets/stylesheets/publisher.scss index 51c4a494f..a08f67955 100644 --- a/app/assets/stylesheets/publisher.scss +++ b/app/assets/stylesheets/publisher.scss @@ -14,10 +14,6 @@ display: none !important; } - .mentions-box { - margin-top: 0; - } - #publisher_textarea_wrapper { border: 1px solid $border-grey !important; } } @@ -248,8 +244,6 @@ .locator { display: none; } } - &.submitting .mentions-box { display: none; } - .twitter-typeahead { left: -1px; // Override inline rule of Typeahead @@ -257,11 +251,6 @@ position: absolute !important; // scss-lint:enable ImportantRule } - - .mentions-box { - // Leave space for markdown editor header - margin-top: 42px; - } } .publisher-buttonbar { diff --git a/app/views/publisher/_publisher.html.haml b/app/views/publisher/_publisher.html.haml index 1304283a4..6fc8669cc 100644 --- a/app/views/publisher/_publisher.html.haml +++ b/app/views/publisher/_publisher.html.haml @@ -5,8 +5,6 @@ %params .publisher-textarea-wrapper#publisher_textarea_wrapper .mentions-input-box - .mentions-box - .mentions - if current_user.getting_started? = status.text_area :fake_text, :rows => 2, :value => h(publisher_formatted_text), :tabindex => 1, :placeholder => "#{t('contacts.index.start_a_conversation')}...", diff --git a/features/desktop/follows_tags.feature b/features/desktop/follows_tags.feature index 78692e71c..fcdfbf3a5 100644 --- a/features/desktop/follows_tags.feature +++ b/features/desktop/follows_tags.feature @@ -16,7 +16,7 @@ Feature: posting Then I should see a ".tag-following-action .followed" Scenario: can post a message from the tag page - Then I should see "#boss" within "#publisher" + Then I should see "#boss " in the publisher When I click the publisher and post "#boss from the tag page" And I go to the tag page for "boss" Then I should see "#boss from the tag page" diff --git a/features/step_definitions/posts_steps.rb b/features/step_definitions/posts_steps.rb index b0b8e62b1..34df49e49 100644 --- a/features/step_definitions/posts_steps.rb +++ b/features/step_definitions/posts_steps.rb @@ -32,6 +32,10 @@ Then /^I should not be able to submit the publisher$/ do expect(publisher_submittable?).to be false end +Then /^I should see "([^"]*)" in the publisher$/ do |text| + expect(page).to have_field("status_message[fake_text]", with: text) +end + Given /^I have a limited post with text "([^\"]*)" in the aspect "([^"]*)"$/ do |text, aspect_name| @me.post :status_message, text: text, to: @me.aspects.where(name: aspect_name).first.id end diff --git a/spec/javascripts/app/views/publisher_mention_view_spec.js b/spec/javascripts/app/views/publisher_mention_view_spec.js index 54e72ad90..7ab98fe78 100644 --- a/spec/javascripts/app/views/publisher_mention_view_spec.js +++ b/spec/javascripts/app/views/publisher_mention_view_spec.js @@ -201,19 +201,6 @@ describe("app.views.PublisherMention", function() { this.view.updateMessageTexts(); expect(this.view.inputBox.data("messageText")).toBe("@user1 Text before @{user1@pod.tld}\ntext after"); }); - - it("formats overlay text to HTML", function() { - this.view.updateMessageTexts(); - expect(this.view.mentionsBox.find(".mentions").html()) - .toBe("@user1 Text before @{user1@pod.tld}\ntext after"); - }); - - it("properly escapes the user input", function() { - this.view.inputBox.val(" @user1 Text before @{user1@pod.tld}\ntext after"); - this.view.updateMessageTexts(); - expect(this.view.mentionsBox.find(".mentions").html()) - .toBe("<img src=\"/default.png\"> @user1 Text before @{user1@pod.tld}\ntext after"); - }); }); describe("updateTypeaheadInput", function() { From c4b6b9534c2e07109c9b9777e46a6f4f350964f5 Mon Sep 17 00:00:00 2001 From: Steffen van Bergerem Date: Mon, 30 Jan 2017 13:19:50 +0100 Subject: [PATCH 016/318] No more fake text in the publisher --- .../app/views/publisher/mention_view.js | 13 +++++----- .../javascripts/app/views/publisher_view.js | 25 ++++--------------- .../interim_stream_hackiness_helper.rb | 10 -------- app/views/publisher/_publisher.html.haml | 5 ++-- features/desktop/post_preview.feature | 16 ++++++------ features/desktop/post_with_a_poll.feature | 16 ++++++------ features/mobile/posts_from_main_page.feature | 4 +-- .../keyboard_navigation_steps.rb | 2 +- features/step_definitions/posts_steps.rb | 6 +---- features/support/publishing_cuke_helpers.rb | 23 ++++++----------- .../app/views/bookmarklet_view_spec.js | 7 +----- .../app/views/publisher_view_spec.js | 7 ++---- 12 files changed, 43 insertions(+), 91 deletions(-) diff --git a/app/assets/javascripts/app/views/publisher/mention_view.js b/app/assets/javascripts/app/views/publisher/mention_view.js index d678a6bf5..55efafbe2 100644 --- a/app/assets/javascripts/app/views/publisher/mention_view.js +++ b/app/assets/javascripts/app/views/publisher/mention_view.js @@ -6,18 +6,17 @@ app.views.PublisherMention = app.views.SearchBase.extend({ mentionSyntaxTemplate: function(person) { return "@{" + person.handle + "}"; }, events: { - "keydown #status_message_fake_text": "onInputBoxKeyDown", - "input #status_message_fake_text": "onInputBoxInput", - "click #status_message_fake_text": "onInputBoxClick", - "blur #status_message_fake_text": "onInputBoxBlur" + "keydown #status_message_text": "onInputBoxKeyDown", + "input #status_message_text": "onInputBoxInput", + "click #status_message_text": "onInputBoxClick", + "blur #status_message_text": "onInputBoxBlur" }, initialize: function() { this.mentionedPeople = []; - // contains the 'fake text' displayed to the user - // also has a data-messageText attribute with the original text - this.inputBox = this.$("#status_message_fake_text"); + // has a data-messageText attribute with the original text + this.inputBox = this.$("#status_message_text"); this.typeaheadInput = this.$(".typeahead-mention-box"); this.bindTypeaheadEvents(); diff --git a/app/assets/javascripts/app/views/publisher_view.js b/app/assets/javascripts/app/views/publisher_view.js index de9245027..7d789f998 100644 --- a/app/assets/javascripts/app/views/publisher_view.js +++ b/app/assets/javascripts/app/views/publisher_view.js @@ -18,11 +18,11 @@ app.views.Publisher = Backbone.View.extend({ el : "#publisher", events : { - "keydown #status_message_fake_text" : "keyDown", + "keydown #status_message_text": "keyDown", "focus textarea" : "open", "submit form" : "createStatusMessage", "click #submit" : "createStatusMessage", - "textchange #status_message_fake_text": "handleTextchange", + "textchange #status_message_text": "handleTextchange", "click #locator" : "showLocation", "click #poll_creator" : "togglePollCreator", "click #hide_location" : "destroyLocation", @@ -35,8 +35,7 @@ app.views.Publisher = Backbone.View.extend({ this.disabled = false; // init shortcut references to the various elements - this.inputEl = this.$("#status_message_fake_text"); - this.hiddenInputEl = this.$("#status_message_text"); + this.inputEl = this.$("#status_message_text"); this.wrapperEl = this.$("#publisher_textarea_wrapper"); this.submitEl = this.$("input[type=submit], button#submit"); this.photozoneEl = this.$("#photodropzone"); @@ -46,14 +45,6 @@ app.views.Publisher = Backbone.View.extend({ $(window).on("beforeunload", _.bind(this._beforeUnload, this)); $(window).unload(this.clear.bind(this)); - // sync textarea content - if( this.hiddenInputEl.val() === "" ) { - this.hiddenInputEl.val( this.inputEl.val() ); - } - if( this.inputEl.val() === "" ) { - this.inputEl.val( this.hiddenInputEl.val() ); - } - // hide close and preview buttons and manage services link // in case publisher is standalone // (e.g. bookmarklet, mentions popup) @@ -175,7 +166,6 @@ app.views.Publisher = Backbone.View.extend({ // inject content into the publisher textarea setText: function(txt) { this.inputEl.val(txt); - this.hiddenInputEl.val(txt); this.prefillText = txt; this.inputEl.trigger("input"); @@ -381,11 +371,10 @@ app.views.Publisher = Backbone.View.extend({ // remove mentions this.mention.reset(); - // clear text(s) + // clear text this.inputEl.val(""); - this.hiddenInputEl.val(""); this.inputEl.trigger("keyup") - .trigger("keydown"); + .trigger("keydown"); autosize.update(this.inputEl); // remove photos @@ -421,7 +410,6 @@ app.views.Publisher = Backbone.View.extend({ // force textchange plugin to update lastValue this.inputEl.data("lastValue", ""); - this.hiddenInputEl.data("lastValue", ""); return this; }, @@ -487,10 +475,8 @@ app.views.Publisher = Backbone.View.extend({ setInputEnabled: function(bool) { if (bool) { this.inputEl.removeAttr("disabled"); - this.hiddenInputEl.removeAttr("disabled"); } else { this.inputEl.prop("disabled", true); - this.hiddenInputEl.prop("disabled", true); } }, @@ -505,7 +491,6 @@ app.views.Publisher = Backbone.View.extend({ handleTextchange: function() { this.checkSubmitAvailability(); - this.hiddenInputEl.val(this.mention.getTextForSubmit()); }, _beforeUnload: function(e) { diff --git a/app/helpers/interim_stream_hackiness_helper.rb b/app/helpers/interim_stream_hackiness_helper.rb index b531871f2..4283a8126 100644 --- a/app/helpers/interim_stream_hackiness_helper.rb +++ b/app/helpers/interim_stream_hackiness_helper.rb @@ -21,16 +21,6 @@ module InterimStreamHackinessHelper end end - def publisher_hidden_text - if params[:prefill].present? - params[:prefill] - elsif defined?(@stream) - @stream.publisher.prefill - else - nil - end - end - def from_group(post) if defined?(@stream) && params[:controller] == 'multis' @stream.post_from_group(post) diff --git a/app/views/publisher/_publisher.html.haml b/app/views/publisher/_publisher.html.haml index 6fc8669cc..9ed2ae2ee 100644 --- a/app/views/publisher/_publisher.html.haml +++ b/app/views/publisher/_publisher.html.haml @@ -6,17 +6,16 @@ .publisher-textarea-wrapper#publisher_textarea_wrapper .mentions-input-box - if current_user.getting_started? - = status.text_area :fake_text, :rows => 2, :value => h(publisher_formatted_text), + = status.text_area :text, :rows => 2, :value => h(publisher_formatted_text), :tabindex => 1, :placeholder => "#{t('contacts.index.start_a_conversation')}...", "data-title" => popover_with_close_html("1. " + t("shared.public_explain.share")), "data-content" => t("shared.public_explain.new_user_welcome_message"), "class" => "form-control" - else - = status.text_area :fake_text, :rows => 2, :value => h(publisher_formatted_text), + = status.text_area :text, :rows => 2, :value => h(publisher_formatted_text), :tabindex => 1, :placeholder => "#{t('contacts.index.start_a_conversation')}...", "class" => "form-control" %input.typeahead-mention-box.hidden{type: "text"} - = status.hidden_field :text, value: h(publisher_hidden_text), class: "clear_on_submit" .container-fluid.photodropzone-container#photodropzone_container %ul#photodropzone diff --git a/features/desktop/post_preview.feature b/features/desktop/post_preview.feature index 827b36d36..d2a69b687 100644 --- a/features/desktop/post_preview.feature +++ b/features/desktop/post_preview.feature @@ -44,7 +44,7 @@ Feature: preview posts in the stream Given I expand the publisher And I attach "spec/fixtures/button.png" to the publisher When I fill in the following: - | status_message_fake_text | Look at this dog | + | status_message_text | Look at this dog | And I preview the post Then I should see a "img" within ".md-preview .stream-element .photo_attachments" And I should see "Look at this dog" within ".md-preview .stream-element" @@ -63,7 +63,7 @@ Feature: preview posts in the stream Then I should see "Samuel Beckett" When I expand the publisher And I fill in the following: - | status_message_fake_text | This preview rocks | + | status_message_text | This preview rocks | And I preview the post Then I should see "This preview rocks" in the preview And I close the publisher @@ -71,11 +71,11 @@ Feature: preview posts in the stream Scenario: preview a post with the poll Given I expand the publisher When I fill in the following: - | status_message_fake_text | I am eating yogurt | + | status_message_text | I am eating yogurt | And I click on selector "#poll_creator" When I fill in the following: - | status_message_fake_text | I am eating yogurt | - | poll_question | What kind of yogurt do you like? | + | status_message_text | I am eating yogurt | + | poll_question | What kind of yogurt do you like? | And I fill in the following for the options: | normal | | not normal | @@ -87,12 +87,12 @@ Feature: preview posts in the stream Scenario: preview a post with location Given I expand the publisher When I fill in the following: - | status_message_fake_text | I am eating yogurt | + | status_message_text | I am eating yogurt | And I allow geolocation And I click on selector "#locator" When I fill in the following: - | status_message_fake_text | I am eating yogurt | - | location_address | Some cool place | + | status_message_text | I am eating yogurt | + | location_address | Some cool place | And I preview the post Then I should see a ".near-from" within ".md-preview .stream-element" And I should see "Some cool place" within ".md-preview .stream-element .near-from" diff --git a/features/desktop/post_with_a_poll.feature b/features/desktop/post_with_a_poll.feature index b5b3a0ff8..5a27fc7ee 100644 --- a/features/desktop/post_with_a_poll.feature +++ b/features/desktop/post_with_a_poll.feature @@ -40,8 +40,8 @@ Feature: posting with a poll Given I expand the publisher And I click on selector "#poll_creator" When I fill in the following: - | status_message_fake_text | I am eating yogurt | - | poll_question | What kind of yogurt do you like? | + | status_message_text | I am eating yogurt | + | poll_question | What kind of yogurt do you like? | And I fill in the following for the options: | normal | | not normal | @@ -53,8 +53,8 @@ Feature: posting with a poll Given I expand the publisher And I click on selector "#poll_creator" When I fill in the following: - | status_message_fake_text | I am eating yogurt | - | poll_question | What kind of yogurt do you like? | + | status_message_text | I am eating yogurt | + | poll_question | What kind of yogurt do you like? | And I fill in the following for the options: | normal | | not normal | @@ -70,8 +70,8 @@ Feature: posting with a poll Given I expand the publisher And I click on selector "#poll_creator" When I fill in the following: - | status_message_fake_text | I am eating yogurt | - | poll_question | What kind of yogurt do you like? | + | status_message_text | I am eating yogurt | + | poll_question | What kind of yogurt do you like? | And I fill in the following for the options: | normal | | not normal | @@ -83,8 +83,8 @@ Feature: posting with a poll Given I expand the publisher And I click on selector "#poll_creator" When I fill in the following: - | status_message_fake_text | I am eating yogurt | - | poll_question | What kind of yogurt do you like? | + | status_message_text | I am eating yogurt | + | poll_question | What kind of yogurt do you like? | And I fill in the following for the options: | normal | | | diff --git a/features/mobile/posts_from_main_page.feature b/features/mobile/posts_from_main_page.feature index 22fb6195a..9afee520d 100644 --- a/features/mobile/posts_from_main_page.feature +++ b/features/mobile/posts_from_main_page.feature @@ -20,7 +20,7 @@ Feature: posting from the mobile main page Scenario: post and delete some text Given I visit the mobile publisher page - And I append "I am eating yogurt" to the mobile publisher + And I append "I am eating yogurt" to the publisher And I select "Unicorns" from "aspect_ids_" And I press "Share" When I go to the stream page @@ -52,7 +52,7 @@ Feature: posting from the mobile main page Scenario: back out of uploading a picture when another has been attached Given I visit the mobile publisher page - And I append "I am eating yogurt" to the mobile publisher + And I append "I am eating yogurt" to the publisher And I attach the file "spec/fixtures/button.gif" to hidden "qqfile" within "#file-upload-publisher" And I attach the file "spec/fixtures/button.png" to hidden "qqfile" within "#file-upload-publisher" And I click to delete the first uploaded photo diff --git a/features/step_definitions/keyboard_navigation_steps.rb b/features/step_definitions/keyboard_navigation_steps.rb index e0109902d..32188aff3 100644 --- a/features/step_definitions/keyboard_navigation_steps.rb +++ b/features/step_definitions/keyboard_navigation_steps.rb @@ -5,7 +5,7 @@ When /^I press the "([^\"]*)" key somewhere$/ do |key| end When /^I press the "([^\"]*)" key in the publisher$/ do |key| - find("#status_message_fake_text").native.send_key(key) + find("#status_message_text").native.send_key(key) end Then /^post (\d+) should be highlighted$/ do |position| diff --git a/features/step_definitions/posts_steps.rb b/features/step_definitions/posts_steps.rb index 34df49e49..a13779a2c 100644 --- a/features/step_definitions/posts_steps.rb +++ b/features/step_definitions/posts_steps.rb @@ -33,7 +33,7 @@ Then /^I should not be able to submit the publisher$/ do end Then /^I should see "([^"]*)" in the publisher$/ do |text| - expect(page).to have_field("status_message[fake_text]", with: text) + expect(page).to have_field("status_message[text]", with: text) end Given /^I have a limited post with text "([^\"]*)" in the aspect "([^"]*)"$/ do |text, aspect_name| @@ -118,10 +118,6 @@ When /^I append "([^"]*)" to the publisher$/ do |text| append_to_publisher(text) end -When /^I append "([^"]*)" to the mobile publisher$/ do |text| - append_to_publisher(text, '#status_message_text') -end - When /^I attach "([^"]*)" to the publisher$/ do |path| upload_file_with_publisher(path) end diff --git a/features/support/publishing_cuke_helpers.rb b/features/support/publishing_cuke_helpers.rb index 046f8e332..ff5f91d43 100644 --- a/features/support/publishing_cuke_helpers.rb +++ b/features/support/publishing_cuke_helpers.rb @@ -1,21 +1,12 @@ module PublishingCukeHelpers def write_in_publisher(txt) - fill_in 'status_message_fake_text', with: txt + fill_in "status_message_text", with: txt end - def append_to_publisher(txt, input_selector='#status_message_fake_text') - status_message_text = find("#status_message_text", visible: false).value - find(input_selector).native.send_key(" #{txt}") - - # make sure the other text field got the new contents - if input_selector == "#status_message_fake_text" - begin - expect(page).to have_selector("#status_message_text[value='#{status_message_text} #{txt}']", visible: false) - rescue RSpec::Expectations::ExpectationNotMetError - puts "Value was instead: #{find('#status_message_text', visible: false).value.inspect}" - raise - end - end + def append_to_publisher(txt) + status_message_text = find("#status_message_text").value + find("#status_message_text").native.send_key(" #{txt}") + expect(page).to have_field("status_message[text]", with: "#{status_message_text} #{txt}") end def upload_file_with_publisher(path) @@ -33,7 +24,7 @@ module PublishingCukeHelpers end def submit_publisher - txt = find("#publisher #status_message_fake_text").value + txt = find("#publisher #status_message_text").value find("#publisher .btn-primary").click # wait for the content to appear expect(find("#main_stream")).to have_content(txt) @@ -45,7 +36,7 @@ module PublishingCukeHelpers end def click_publisher - find("#status_message_fake_text").click + find("#status_message_text").click expect(find("#publisher")).to have_css(".publisher-textarea-wrapper.active") end diff --git a/spec/javascripts/app/views/bookmarklet_view_spec.js b/spec/javascripts/app/views/bookmarklet_view_spec.js index d5de57466..9d12f998c 100644 --- a/spec/javascripts/app/views/bookmarklet_view_spec.js +++ b/spec/javascripts/app/views/bookmarklet_view_spec.js @@ -29,23 +29,18 @@ describe("app.views.Bookmarklet", function() { it("prefills the publisher", function() { init_bookmarklet(test_data); - expect($.trim(app.publisher.inputEl.val())).not.toEqual(""); - expect($.trim(app.publisher.hiddenInputEl.val())).not.toEqual(""); }); it("handles dirty input well", function() { init_bookmarklet(evil_test_data); - expect($.trim(app.publisher.inputEl.val())).not.toEqual(""); - expect($.trim(app.publisher.hiddenInputEl.val())).not.toEqual(""); }); it("allows changing a prefilled publisher", function() { init_bookmarklet(test_data); app.publisher.setText(app.publisher.inputEl.val()+"A"); - - expect(app.publisher.hiddenInputEl.val()).toMatch(/.+A$/); + expect(app.publisher.inputEl.val()).toMatch(/.+A$/); }); it("keeps the publisher disabled after successful post creation", function() { diff --git a/spec/javascripts/app/views/publisher_view_spec.js b/spec/javascripts/app/views/publisher_view_spec.js index c672b33fa..a0bd9c292 100644 --- a/spec/javascripts/app/views/publisher_view_spec.js +++ b/spec/javascripts/app/views/publisher_view_spec.js @@ -82,9 +82,9 @@ describe("app.views.Publisher", function() { }); it("resets the element's height", function() { - $(this.view.el).find("#status_message_fake_text").height(100); + $(this.view.el).find("#status_message_text").height(100); this.view.close($.Event()); - expect($(this.view.el).find("#status_message_fake_text").attr("style")).not.toContain("height"); + expect($(this.view.el).find("#status_message_text").attr("style")).not.toContain("height"); }); it("calls autosize.update", function() { @@ -235,9 +235,7 @@ describe("app.views.Publisher", function() { describe('#setText', function() { it("sets the content text", function() { this.view.setText("FOO bar"); - expect(this.view.inputEl.val()).toEqual("FOO bar"); - expect(this.view.hiddenInputEl.val()).toEqual("FOO bar"); }); }); @@ -248,7 +246,6 @@ describe("app.views.Publisher", function() { expect(this.view.disabled).toBeTruthy(); expect(this.view.inputEl.prop("disabled")).toBeTruthy(); - expect(this.view.hiddenInputEl.prop("disabled")).toBeTruthy(); }); it("disables submitting", function() { From 90b379b110a9abbfe5416deffb78c2c65d49e427 Mon Sep 17 00:00:00 2001 From: Steffen van Bergerem Date: Mon, 30 Jan 2017 13:31:16 +0100 Subject: [PATCH 017/318] Drop useless data attribute for message text in publisher --- .../app/views/publisher/mention_view.js | 15 ------ .../javascripts/app/views/publisher_view.js | 2 +- .../app/views/publisher_mention_view_spec.js | 52 ------------------- 3 files changed, 1 insertion(+), 68 deletions(-) diff --git a/app/assets/javascripts/app/views/publisher/mention_view.js b/app/assets/javascripts/app/views/publisher/mention_view.js index 55efafbe2..d1c98b829 100644 --- a/app/assets/javascripts/app/views/publisher/mention_view.js +++ b/app/assets/javascripts/app/views/publisher/mention_view.js @@ -14,8 +14,6 @@ app.views.PublisherMention = app.views.SearchBase.extend({ initialize: function() { this.mentionedPeople = []; - - // has a data-messageText attribute with the original text this.inputBox = this.$("#status_message_text"); this.typeaheadInput = this.$(".typeahead-mention-box"); this.bindTypeaheadEvents(); @@ -67,18 +65,11 @@ app.views.PublisherMention = app.views.SearchBase.extend({ messageText = messageText.substring(0, triggerCharPosition) + mentionText + messageText.substring(caretPosition); this.inputBox.val(messageText); - this.updateMessageTexts(); - this.inputBox.focus(); var newCaretPosition = triggerCharPosition + mentionText.length; this.inputBox[0].setSelectionRange(newCaretPosition, newCaretPosition); }, - updateMessageTexts: function() { - var messageText = this.inputBox.val(); - this.inputBox.data("messageText", messageText); - }, - updateTypeaheadInput: function() { var messageText = this.inputBox.val(); var caretPosition = this.inputBox[0].selectionStart; @@ -107,7 +98,6 @@ app.views.PublisherMention = app.views.SearchBase.extend({ text = this.inputBox.val() + " " + text; } this.inputBox.val(text); - this.updateMessageTexts(); }, this); }, @@ -133,7 +123,6 @@ app.views.PublisherMention = app.views.SearchBase.extend({ */ onInputBoxInput: function() { this.cleanMentionedPeople(); - this.updateMessageTexts(); this.updateTypeaheadInput(); }, @@ -189,9 +178,5 @@ app.views.PublisherMention = app.views.SearchBase.extend({ isVisible: function() { return this.$(".tt-menu").is(":visible"); - }, - - getTextForSubmit: function() { - return this.mentionedPeople.length ? this.inputBox.data("messageText") : this.inputBox.val(); } }); diff --git a/app/assets/javascripts/app/views/publisher_view.js b/app/assets/javascripts/app/views/publisher_view.js index 7d789f998..a06ac3387 100644 --- a/app/assets/javascripts/app/views/publisher_view.js +++ b/app/assets/javascripts/app/views/publisher_view.js @@ -324,7 +324,7 @@ app.views.Publisher = Backbone.View.extend({ this.handleTextchange(); var serializedForm = $("#new_status_message").serializeObject(); - var text = this.mention.getTextForSubmit(); + var text = serializedForm["status_message[text]"]; var photos = this.getUploadedPhotos(); var mentionedPeople = this.mention.mentionedPeople; var poll = this.getPollData(serializedForm); diff --git a/spec/javascripts/app/views/publisher_mention_view_spec.js b/spec/javascripts/app/views/publisher_mention_view_spec.js index 7ab98fe78..4cd9e5ae6 100644 --- a/spec/javascripts/app/views/publisher_mention_view_spec.js +++ b/spec/javascripts/app/views/publisher_mention_view_spec.js @@ -177,12 +177,6 @@ describe("app.views.PublisherMention", function() { expect(this.view.inputBox.val()).toBe("@{user1@pod.tld} 123 user2 @{user2@pod.tld} 456 @{user3@pod.tld} 789"); }); - it("calls updateMessageTexts", function() { - spyOn(this.view, "updateMessageTexts"); - this.view.onSuggestionSelection({name: "user1337", handle: "user1@pod.tld"}); - expect(this.view.updateMessageTexts).toHaveBeenCalled(); - }); - it("places the caret at the right position", function() { this.view.onSuggestionSelection({"name": "user1WithLongName", "handle": "user1@pod.tld"}); var expectedCaretPosition = ("@user1337 Text before @{user1@pod.tld}").length; @@ -190,19 +184,6 @@ describe("app.views.PublisherMention", function() { }); }); - describe("updateMessageTexts", function() { - beforeEach(function() { - this.view = new app.views.PublisherMention({ el: "#publisher" }); - this.view.inputBox.val("@user1 Text before @{user1@pod.tld}\ntext after"); - this.view.mentionedPeople.push({"name": "user1", "handle": "user1@pod.tld"}); - }); - - it("sets the correct messageText", function() { - this.view.updateMessageTexts(); - expect(this.view.inputBox.data("messageText")).toBe("@user1 Text before @{user1@pod.tld}\ntext after"); - }); - }); - describe("updateTypeaheadInput", function() { beforeEach(function() { this.view = new app.views.PublisherMention({ el: "#publisher" }); @@ -254,13 +235,11 @@ describe("app.views.PublisherMention", function() { beforeEach(function() { this.view = new app.views.PublisherMention({ el: "#publisher" }); spyOn(this.view, "addPersonToMentions"); - spyOn(this.view, "updateMessageTexts"); }); it("prefills one mention", function() { this.view.prefillMention([{"name": "user1", "handle": "user1@pod.tld"}]); expect(this.view.addPersonToMentions).toHaveBeenCalledWith({"name": "user1", "handle": "user1@pod.tld"}); - expect(this.view.updateMessageTexts).toHaveBeenCalled(); expect(this.view.inputBox.val()).toBe("@{user1@pod.tld}"); }); @@ -272,7 +251,6 @@ describe("app.views.PublisherMention", function() { expect(this.view.addPersonToMentions).toHaveBeenCalledWith({"name": "user1", "handle": "user1@pod.tld"}); expect(this.view.addPersonToMentions).toHaveBeenCalledWith({"name": "user2", "handle": "user2@pod.tld"}); - expect(this.view.updateMessageTexts).toHaveBeenCalled(); expect(this.view.inputBox.val()).toBe("@{user1@pod.tld} @{user2@pod.tld}"); }); }); @@ -380,12 +358,6 @@ describe("app.views.PublisherMention", function() { expect(this.view.cleanMentionedPeople).toHaveBeenCalled(); }); - it("calls 'updateMessageTexts'", function() { - spyOn(this.view, "updateMessageTexts"); - this.view.onInputBoxInput(); - expect(this.view.updateMessageTexts).toHaveBeenCalled(); - }); - it("calls 'updateTypeaheadInput'", function() { spyOn(this.view, "updateTypeaheadInput"); this.view.onInputBoxInput(); @@ -450,28 +422,4 @@ describe("app.views.PublisherMention", function() { expect(this.view.typeaheadInput.val()).toBe(""); }); }); - - describe("getTextForSubmit", function() { - beforeEach(function() { - this.view = new app.views.PublisherMention({ el: "#publisher" }); - this.view.bloodhound.add([ - {person: true, name: "user1", handle: "user1@pod.tld"} - ]); - }); - - it("returns text with mention if someone has been mentioned", function() { - this.view.inputBox.val("@user"); - this.view.inputBox[0].setSelectionRange(5, 5); - this.view.typeaheadInput.typeahead("val", "user"); - this.view.typeaheadInput.typeahead("open"); - this.view.$(".tt-suggestion").first().click(); - expect(this.view.getTextForSubmit()).toBe("@{user1@pod.tld}"); - }); - - it("returns normal text if nobody has been mentioned", function() { - this.view.inputBox.data("messageText", "Bad text"); - this.view.inputBox.val("Good text"); - expect(this.view.getTextForSubmit()).toBe("Good text"); - }); - }); }); From 9217df43cdc1374ed13ec5429896e23eb74a9a67 Mon Sep 17 00:00:00 2001 From: Steffen van Bergerem Date: Mon, 30 Jan 2017 13:52:39 +0100 Subject: [PATCH 018/318] Only update mentions in publisher before opening suggestions or preview --- .../app/views/publisher/mention_view.js | 8 +++- .../javascripts/app/views/publisher_view.js | 8 +--- .../app/views/publisher_mention_view_spec.js | 40 ++++++++++++++++--- .../app/views/publisher_view_spec.js | 14 ------- 4 files changed, 42 insertions(+), 28 deletions(-) diff --git a/app/assets/javascripts/app/views/publisher/mention_view.js b/app/assets/javascripts/app/views/publisher/mention_view.js index d1c98b829..36ab541cf 100644 --- a/app/assets/javascripts/app/views/publisher/mention_view.js +++ b/app/assets/javascripts/app/views/publisher/mention_view.js @@ -80,6 +80,8 @@ app.views.PublisherMention = app.views.SearchBase.extend({ return; } + this.cleanMentionedPeople(); + // result[1] is the string between the last '@' and the current caret position this.typeaheadInput.typeahead("val", result[1]); this.typeaheadInput.typeahead("open"); @@ -122,7 +124,6 @@ app.views.PublisherMention = app.views.SearchBase.extend({ * Listens for user input and opens results dropdown when input contains the trigger char */ onInputBoxInput: function() { - this.cleanMentionedPeople(); this.updateTypeaheadInput(); }, @@ -178,5 +179,10 @@ app.views.PublisherMention = app.views.SearchBase.extend({ isVisible: function() { return this.$(".tt-menu").is(":visible"); + }, + + getMentionedPeople: function() { + this.cleanMentionedPeople(); + return this.mentionedPeople; } }); diff --git a/app/assets/javascripts/app/views/publisher_view.js b/app/assets/javascripts/app/views/publisher_view.js index a06ac3387..c19ff863e 100644 --- a/app/assets/javascripts/app/views/publisher_view.js +++ b/app/assets/javascripts/app/views/publisher_view.js @@ -192,9 +192,6 @@ app.views.Publisher = Backbone.View.extend({ // empty poll answer and failing validation. this.viewPollCreator.removeLastAnswer(); - //add missing mentions at end of post: - this.handleTextchange(); - var serializedForm = $(evt.target).closest("form").serializeObject(); // disable input while posting, must be after the form is serialized this.setInputEnabled(false); @@ -320,13 +317,10 @@ app.views.Publisher = Backbone.View.extend({ }, createPostPreview: function() { - //add missing mentions at end of post: - this.handleTextchange(); - var serializedForm = $("#new_status_message").serializeObject(); var text = serializedForm["status_message[text]"]; var photos = this.getUploadedPhotos(); - var mentionedPeople = this.mention.mentionedPeople; + var mentionedPeople = this.mention.getMentionedPeople(); var poll = this.getPollData(serializedForm); var locationCoords = serializedForm["location[coords]"]; if(!locationCoords || locationCoords === "") { diff --git a/spec/javascripts/app/views/publisher_mention_view_spec.js b/spec/javascripts/app/views/publisher_mention_view_spec.js index 4cd9e5ae6..666a62d96 100644 --- a/spec/javascripts/app/views/publisher_mention_view_spec.js +++ b/spec/javascripts/app/views/publisher_mention_view_spec.js @@ -229,6 +229,22 @@ describe("app.views.PublisherMention", function() { expect(this.view.closeSuggestions).not.toHaveBeenCalled(); expect(this.view.typeaheadInput.val()).toBe("user"); }); + + it("doesn't call 'cleanMentionedPeople' if there is no '@' in front of the caret", function() { + spyOn(this.view, "cleanMentionedPeople"); + this.view.inputBox.val("user1337 Text before @user1 text after"); + this.view.inputBox[0].setSelectionRange(9, 9); + this.view.updateTypeaheadInput(); + expect(this.view.cleanMentionedPeople).not.toHaveBeenCalled(); + }); + + it("calls 'cleanMentionedPeople' if there is an '@' in front of the caret", function() { + spyOn(this.view, "cleanMentionedPeople"); + this.view.inputBox.val("@user1337 Text before @user1 text after"); + this.view.inputBox[0].setSelectionRange(9, 9); + this.view.updateTypeaheadInput(); + expect(this.view.cleanMentionedPeople).toHaveBeenCalled(); + }); }); describe("prefillMention", function() { @@ -352,12 +368,6 @@ describe("app.views.PublisherMention", function() { this.view = new app.views.PublisherMention({ el: "#publisher" }); }); - it("calls 'cleanMentionedPeople'", function() { - spyOn(this.view, "cleanMentionedPeople"); - this.view.onInputBoxInput(); - expect(this.view.cleanMentionedPeople).toHaveBeenCalled(); - }); - it("calls 'updateTypeaheadInput'", function() { spyOn(this.view, "updateTypeaheadInput"); this.view.onInputBoxInput(); @@ -422,4 +432,22 @@ describe("app.views.PublisherMention", function() { expect(this.view.typeaheadInput.val()).toBe(""); }); }); + + describe("getMentionedPeople", function() { + beforeEach(function() { + this.view = new app.views.PublisherMention({el: "#publisher"}); + }); + + it("calls 'cleanMentionedPeople'", function() { + spyOn(this.view, "cleanMentionedPeople"); + this.view.getMentionedPeople(); + expect(this.view.cleanMentionedPeople).toHaveBeenCalled(); + }); + + it("returns the cleaned mentionedPeople", function() { + this.view.inputBox.val("@{user1@pod.tld} user2@pod.tld"); + this.view.mentionedPeople = [{name: "user1", handle: "user1@pod.tld"}, {name: "user2", handle: "user2@pod.tld"}]; + expect(this.view.getMentionedPeople()).toEqual([{name: "user1", handle: "user1@pod.tld"}]); + }); + }); }); diff --git a/spec/javascripts/app/views/publisher_view_spec.js b/spec/javascripts/app/views/publisher_view_spec.js index a0bd9c292..0b3bc8993 100644 --- a/spec/javascripts/app/views/publisher_view_spec.js +++ b/spec/javascripts/app/views/publisher_view_spec.js @@ -203,12 +203,6 @@ describe("app.views.Publisher", function() { }); describe("createStatusMessage", function(){ - it("calls handleTextchange to complete missing mentions", function(){ - spyOn(this.view, "handleTextchange"); - this.view.createStatusMessage($.Event()); - expect(this.view.handleTextchange).toHaveBeenCalled(); - }); - it("adds the status message to the stream", function() { app.stream = { addNow: $.noop }; spyOn(app.stream, "addNow"); @@ -224,14 +218,6 @@ describe("app.views.Publisher", function() { }); }); - describe("createPostPreview", function(){ - it("calls handleTextchange to complete missing mentions", function(){ - spyOn(this.view, "handleTextchange"); - this.view.createPostPreview(); - expect(this.view.handleTextchange).toHaveBeenCalled(); - }); - }); - describe('#setText', function() { it("sets the content text", function() { this.view.setText("FOO bar"); From b23debf0b61c5881a53ac1f3c63c77d6c6a8bb4c Mon Sep 17 00:00:00 2001 From: Steffen van Bergerem Date: Mon, 30 Jan 2017 14:06:01 +0100 Subject: [PATCH 019/318] Refactor publisher backbone view --- .../javascripts/app/views/publisher_view.js | 21 +++++++------------ .../app/views/publisher_view_spec.js | 12 +++-------- 2 files changed, 10 insertions(+), 23 deletions(-) diff --git a/app/assets/javascripts/app/views/publisher_view.js b/app/assets/javascripts/app/views/publisher_view.js index c19ff863e..97bda7e12 100644 --- a/app/assets/javascripts/app/views/publisher_view.js +++ b/app/assets/javascripts/app/views/publisher_view.js @@ -22,7 +22,7 @@ app.views.Publisher = Backbone.View.extend({ "focus textarea" : "open", "submit form" : "createStatusMessage", "click #submit" : "createStatusMessage", - "textchange #status_message_text": "handleTextchange", + "textchange #status_message_text": "checkSubmitAvailability", "click #locator" : "showLocation", "click #poll_creator" : "togglePollCreator", "click #hide_location" : "destroyLocation", @@ -154,7 +154,7 @@ app.views.Publisher = Backbone.View.extend({ this.viewPollCreator.render(); if (this.prefillMention) { - this.handleTextchange(); + this.checkSubmitAvailability(); } }, @@ -170,7 +170,7 @@ app.views.Publisher = Backbone.View.extend({ this.inputEl.trigger("input"); autosize.update(this.inputEl); - this.handleTextchange(); + this.checkSubmitAvailability(); }, // show the "getting started" popups around the publisher @@ -242,7 +242,7 @@ app.views.Publisher = Backbone.View.extend({ self.setButtonsEnabled(true); self.setInputEnabled(true); self.wrapperEl.removeClass("submitting"); - self.handleTextchange(); + self.checkSubmitAvailability(); autosize.update(self.inputEl); } }); @@ -318,9 +318,7 @@ app.views.Publisher = Backbone.View.extend({ createPostPreview: function() { var serializedForm = $("#new_status_message").serializeObject(); - var text = serializedForm["status_message[text]"]; var photos = this.getUploadedPhotos(); - var mentionedPeople = this.mention.getMentionedPeople(); var poll = this.getPollData(serializedForm); var locationCoords = serializedForm["location[coords]"]; if(!locationCoords || locationCoords === "") { @@ -336,12 +334,12 @@ app.views.Publisher = Backbone.View.extend({ var previewMessage = { "id": 0, - "text": text, + "text": serializedForm["status_message[text]"], "public": serializedForm["aspect_ids[]"] === "public", "created_at": new Date().toISOString(), "interacted_at": new Date().toISOString(), "author": app.currentUser ? app.currentUser.attributes : {}, - "mentioned_people": mentionedPeople, + "mentioned_people": this.mention.getMentionedPeople(), "photos": photos, "title": serializedForm["status_message[text]"], "location": location, @@ -454,8 +452,7 @@ app.views.Publisher = Backbone.View.extend({ setEnabled: function(bool) { this.setInputEnabled(bool); this.disabled = !bool; - - this.handleTextchange(); + this.checkSubmitAvailability(); }, setButtonsEnabled: function(bool) { @@ -483,10 +480,6 @@ app.views.Publisher = Backbone.View.extend({ return (!onlyWhitespaces || isPhotoAttached) && isValidPoll && !this.disabled; }, - handleTextchange: function() { - this.checkSubmitAvailability(); - }, - _beforeUnload: function(e) { if(this._submittable() && this.inputEl.val() !== this.prefillText){ var confirmationMessage = Diaspora.I18n.t("confirm_unload"); diff --git a/spec/javascripts/app/views/publisher_view_spec.js b/spec/javascripts/app/views/publisher_view_spec.js index 0b3bc8993..e540669b6 100644 --- a/spec/javascripts/app/views/publisher_view_spec.js +++ b/spec/javascripts/app/views/publisher_view_spec.js @@ -43,17 +43,11 @@ describe("app.views.Publisher", function() { }); describe("#initSubviews", function() { - it("calls handleTextchange if the publisher is prefilled with mentions", function() { - spyOn(this.view, "handleTextchange"); + it("calls checkSubmitAvailability if the publisher is prefilled with mentions", function() { + spyOn(this.view, "checkSubmitAvailability"); this.view.prefillMention = "user@example.org"; this.view.initSubviews(); - expect(this.view.handleTextchange).toHaveBeenCalled(); - }); - - it("doesn't call handleTextchange if there are no prefilled mentions", function() { - spyOn(this.view, "handleTextchange"); - this.view.initSubviews(); - expect(this.view.handleTextchange).not.toHaveBeenCalled(); + expect(this.view.checkSubmitAvailability).toHaveBeenCalled(); }); }); From a6e6e6de9125755251e05e15a931cab6a350c117 Mon Sep 17 00:00:00 2001 From: Steffen van Bergerem Date: Mon, 30 Jan 2017 14:09:55 +0100 Subject: [PATCH 020/318] Refactor publisher mentions backbone view --- .../app/views/publisher/mention_view.js | 11 ++--------- .../app/views/publisher_mention_view_spec.js | 16 ++-------------- 2 files changed, 4 insertions(+), 23 deletions(-) diff --git a/app/assets/javascripts/app/views/publisher/mention_view.js b/app/assets/javascripts/app/views/publisher/mention_view.js index 36ab541cf..f30779c70 100644 --- a/app/assets/javascripts/app/views/publisher/mention_view.js +++ b/app/assets/javascripts/app/views/publisher/mention_view.js @@ -7,7 +7,7 @@ app.views.PublisherMention = app.views.SearchBase.extend({ events: { "keydown #status_message_text": "onInputBoxKeyDown", - "input #status_message_text": "onInputBoxInput", + "input #status_message_text": "updateTypeaheadInput", "click #status_message_text": "onInputBoxClick", "blur #status_message_text": "onInputBoxBlur" }, @@ -120,13 +120,6 @@ app.views.PublisherMention = app.views.SearchBase.extend({ this.typeaheadInput.trigger($.Event("keydown", {keyCode: e.keyCode, which: e.which})); }, - /** - * Listens for user input and opens results dropdown when input contains the trigger char - */ - onInputBoxInput: function() { - this.updateTypeaheadInput(); - }, - onInputBoxKeyDown: function(e) { // This also matches HOME/END on OSX which is CMD+LEFT, CMD+RIGHT if(e.which === Keycodes.LEFT || e.which === Keycodes.RIGHT || @@ -169,7 +162,7 @@ app.views.PublisherMention = app.views.SearchBase.extend({ reset: function() { this.inputBox.val(""); - this.onInputBoxInput(); + this.updateTypeaheadInput(); }, closeSuggestions: function() { diff --git a/spec/javascripts/app/views/publisher_mention_view_spec.js b/spec/javascripts/app/views/publisher_mention_view_spec.js index 666a62d96..5f53c110f 100644 --- a/spec/javascripts/app/views/publisher_mention_view_spec.js +++ b/spec/javascripts/app/views/publisher_mention_view_spec.js @@ -363,18 +363,6 @@ describe("app.views.PublisherMention", function() { }); }); - describe("onInputBoxInput", function() { - beforeEach(function() { - this.view = new app.views.PublisherMention({ el: "#publisher" }); - }); - - it("calls 'updateTypeaheadInput'", function() { - spyOn(this.view, "updateTypeaheadInput"); - this.view.onInputBoxInput(); - expect(this.view.updateTypeaheadInput).toHaveBeenCalled(); - }); - }); - describe("onInputBoxClick", function() { beforeEach(function() { this.view = new app.views.PublisherMention({ el: "#publisher" }); @@ -402,13 +390,13 @@ describe("app.views.PublisherMention", function() { describe("reset", function() { beforeEach(function() { this.view = new app.views.PublisherMention({ el: "#publisher" }); - spyOn(this.view, "onInputBoxInput"); + spyOn(this.view, "updateTypeaheadInput"); }); it("resets the mention box", function() { this.view.reset(); expect(this.view.inputBox.val()).toBe(""); - expect(this.view.onInputBoxInput).toHaveBeenCalled(); + expect(this.view.updateTypeaheadInput).toHaveBeenCalled(); }); }); From c312ff00f3e6ae0e751d0e308e9e6ea6f19ab74a Mon Sep 17 00:00:00 2001 From: Benjamin Neff Date: Sun, 12 Feb 2017 19:30:43 +0100 Subject: [PATCH 021/318] Bump markdown-it-diaspora-mention --- Gemfile | 2 +- Gemfile.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index 83b143f10..785e8bfb7 100644 --- a/Gemfile +++ b/Gemfile @@ -96,7 +96,7 @@ source "https://rails-assets.org" do gem "rails-assets-markdown-it", "8.2.2" gem "rails-assets-markdown-it-hashtag", "0.4.0" - gem "rails-assets-markdown-it-diaspora-mention", "1.1.1" + gem "rails-assets-markdown-it-diaspora-mention", "1.2.0" gem "rails-assets-markdown-it-sanitizer", "0.4.3" gem "rails-assets-markdown-it--markdown-it-for-inline", "0.1.1" gem "rails-assets-markdown-it-sub", "1.0.0" diff --git a/Gemfile.lock b/Gemfile.lock index 8f53fd2ad..af0893dd9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -551,7 +551,7 @@ GEM rails-assets-jquery (>= 1.6) rails-assets-markdown-it--markdown-it-for-inline (0.1.1) rails-assets-markdown-it (8.2.2) - rails-assets-markdown-it-diaspora-mention (1.1.1) + rails-assets-markdown-it-diaspora-mention (1.2.0) rails-assets-markdown-it-hashtag (0.4.0) rails-assets-markdown-it-sanitizer (0.4.3) rails-assets-markdown-it-sub (1.0.0) @@ -881,7 +881,7 @@ DEPENDENCIES rails-assets-jquery-textchange (= 0.2.3)! rails-assets-markdown-it (= 8.2.2)! rails-assets-markdown-it--markdown-it-for-inline (= 0.1.1)! - rails-assets-markdown-it-diaspora-mention (= 1.1.1)! + rails-assets-markdown-it-diaspora-mention (= 1.2.0)! rails-assets-markdown-it-hashtag (= 0.4.0)! rails-assets-markdown-it-sanitizer (= 0.4.3)! rails-assets-markdown-it-sub (= 1.0.0)! From 5c444e62bef5a8f2c1211828e9fce561ee450ef9 Mon Sep 17 00:00:00 2001 From: Benjamin Neff Date: Sun, 12 Feb 2017 19:54:16 +0100 Subject: [PATCH 022/318] Add @ before mentions for mobile and notifications fixes #7269 --- lib/diaspora/mentionable.rb | 4 ++-- spec/lib/diaspora/mentionable_spec.rb | 25 +++++++++++----------- spec/lib/diaspora/message_renderer_spec.rb | 6 +++--- spec/lib/publisher_spec.rb | 2 +- 4 files changed, 19 insertions(+), 18 deletions(-) diff --git a/lib/diaspora/mentionable.rb b/lib/diaspora/mentionable.rb index 72a0ffcf5..fb6117a45 100644 --- a/lib/diaspora/mentionable.rb +++ b/lib/diaspora/mentionable.rb @@ -32,7 +32,7 @@ module Diaspora::Mentionable name, diaspora_id = mention_attrs(match_str) person = people.find {|p| p.diaspora_handle == diaspora_id } - ERB::Util.h(MentionsInternal.mention_link(person, name, diaspora_id, opts)) + "@#{ERB::Util.h(MentionsInternal.mention_link(person, name, diaspora_id, opts))}" } end @@ -64,7 +64,7 @@ module Diaspora::Mentionable if person && allowed_people.include?(person.id) match_str else - MentionsInternal.profile_link(person, name, diaspora_id) + "@#{MentionsInternal.profile_link(person, name, diaspora_id)}" end } end diff --git a/spec/lib/diaspora/mentionable_spec.rb b/spec/lib/diaspora/mentionable_spec.rb index 58b453c17..477e6837b 100644 --- a/spec/lib/diaspora/mentionable_spec.rb +++ b/spec/lib/diaspora/mentionable_spec.rb @@ -44,7 +44,8 @@ STR fmt_msg = Diaspora::Mentionable.format(test_text_with_names, people) [people, names].transpose.each do |person, name| - expect(fmt_msg).to include person_link(person, class: "mention hovercardable", display_name: name) + link = person_link(person, class: "mention hovercardable", display_name: name) + expect(fmt_msg).to include "@#{link}" end end @@ -52,7 +53,8 @@ STR fmt_msg = Diaspora::Mentionable.format(test_text_without_names, people) people.each do |person| - expect(fmt_msg).to include person_link(person, class: "mention hovercardable", display_name: person.name) + link = person_link(person, class: "mention hovercardable", display_name: person.name) + expect(fmt_msg).to include "@#{link}" end end @@ -80,7 +82,7 @@ STR fmt_msg = Diaspora::Mentionable.format(test_text_with_names, people, plain_text: true) names.each do |name| - expect(fmt_msg).to include CGI.escapeHTML(name) + expect(fmt_msg).to include "@#{CGI.escapeHTML(name)}" end expect(fmt_msg).not_to include "", "hovercardable" end @@ -89,9 +91,9 @@ STR it "leaves the names of people that cannot be found" do test_txt_plain = <<-STR This post contains a lot of mentions -one Alice A, -two Bob B and finally -three "Eve> E. +one @Alice A, +two @Bob B and finally +three @"Eve> E. STR fmt_msg = Diaspora::Mentionable.format(test_text_with_names, []) @@ -101,9 +103,9 @@ STR it "uses the diaspora ID when the person cannot be found" do test_txt_plain = <<-STR This post contains a lot of mentions -one #{people[0].diaspora_handle}, -two #{people[1].diaspora_handle} and finally -three #{people[2].diaspora_handle}. +one @#{people[0].diaspora_handle}, +two @#{people[1].diaspora_handle} and finally +three @#{people[2].diaspora_handle}. STR fmt_msg = Diaspora::Mentionable.format(test_text_without_names, []) @@ -180,8 +182,7 @@ STR user_a.aspects.where(name: "generic").first.contacts.map(&:person_id) ) - expect(txt).to include("user C") - expect(txt).to include(local_or_remote_person_path(user_c.person)) + expect(txt).to include("@[user C](#{local_or_remote_person_path(user_c.person)}") expect(txt).not_to include("href") expect(txt).not_to include(mention) end @@ -203,7 +204,7 @@ STR mention = "@{non_existing_user@example.org}" txt = Diaspora::Mentionable.filter_people("mentioning #{mention}", []) - expect(txt).to eq "mentioning non_existing_user@example.org" + expect(txt).to eq "mentioning @non_existing_user@example.org" end end diff --git a/spec/lib/diaspora/message_renderer_spec.rb b/spec/lib/diaspora/message_renderer_spec.rb index 78611a324..f72adc240 100644 --- a/spec/lib/diaspora/message_renderer_spec.rb +++ b/spec/lib/diaspora/message_renderer_spec.rb @@ -195,17 +195,17 @@ describe Diaspora::MessageRenderer do context "with mention" do it "contains the name of the mentioned person" do msg = message("@{#{alice.diaspora_handle}} is cool", mentioned_people: alice.person) - expect(msg.plain_text_without_markdown).to eq "#{alice.name} is cool" + expect(msg.plain_text_without_markdown).to eq "@#{alice.name} is cool" end it "uses the name from mention when the mention contains a name" do msg = message("@{Alice; #{alice.diaspora_handle}} is cool", mentioned_people: alice.person) - expect(msg.plain_text_without_markdown).to eq "Alice is cool" + expect(msg.plain_text_without_markdown).to eq "@Alice is cool" end it "uses the diaspora ID when the person cannot be found" do msg = message("@{#{alice.diaspora_handle}} is cool", mentioned_people: []) - expect(msg.plain_text_without_markdown).to eq "#{alice.diaspora_handle} is cool" + expect(msg.plain_text_without_markdown).to eq "@#{alice.diaspora_handle} is cool" end end end diff --git a/spec/lib/publisher_spec.rb b/spec/lib/publisher_spec.rb index 8eeb76d24..f8479d884 100644 --- a/spec/lib/publisher_spec.rb +++ b/spec/lib/publisher_spec.rb @@ -16,7 +16,7 @@ describe Publisher do describe '#text' do it 'is a formatted version of the prefill' do p = Publisher.new(alice, prefill: "@{alice; #{alice.diaspora_handle}}") - expect(p.text).to eq("alice") + expect(p.text).to eq("@alice") end end From ef3faff8f1d9988b4d4b42e3b1e9e43bbab1899e Mon Sep 17 00:00:00 2001 From: Steffen van Bergerem Date: Mon, 13 Feb 2017 21:47:14 +0100 Subject: [PATCH 023/318] Render mentions as links in comments --- app/assets/javascripts/app/views/comment_view.js | 2 +- app/presenters/comment_presenter.rb | 11 ++++++----- features/desktop/mentions.feature | 12 ++++++++++++ 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/app/assets/javascripts/app/views/comment_view.js b/app/assets/javascripts/app/views/comment_view.js index 7f74d1146..6ca7a4355 100644 --- a/app/assets/javascripts/app/views/comment_view.js +++ b/app/assets/javascripts/app/views/comment_view.js @@ -20,7 +20,7 @@ app.views.Comment = app.views.Content.extend({ presenter : function() { return _.extend(this.defaultPresenter(), { canRemove: this.canRemove(), - text : app.helpers.textFormatter(this.model.get("text")) + text: app.helpers.textFormatter(this.model.get("text"), this.model.get("mentioned_people")) }); }, diff --git a/app/presenters/comment_presenter.rb b/app/presenters/comment_presenter.rb index 95eef095c..f687ba7b8 100644 --- a/app/presenters/comment_presenter.rb +++ b/app/presenters/comment_presenter.rb @@ -5,11 +5,12 @@ class CommentPresenter < BasePresenter def as_json(opts={}) { - :id => @comment.id, - :guid => @comment.guid, - :text => @comment.message.plain_text_for_json, - :author => @comment.author.as_api_response(:backbone), - :created_at => @comment.created_at + id: @comment.id, + guid: @comment.guid, + text: @comment.message.plain_text_for_json, + author: @comment.author.as_api_response(:backbone), + created_at: @comment.created_at, + mentioned_people: @comment.mentioned_people.as_api_response(:backbone) } end end diff --git a/features/desktop/mentions.feature b/features/desktop/mentions.feature index 01791180f..000e1f963 100644 --- a/features/desktop/mentions.feature +++ b/features/desktop/mentions.feature @@ -54,3 +54,15 @@ Feature: Mentions Then I should see "Bob Jones" within ".stream-element" When I follow "Bob Jones" Then I should see "Bob Jones" + + Scenario: A user mentions another user in a comment and it displays correctly + Given following users exist: + | username | email | + | Bob Jones | bob@bob.bob | + | Alice Smith | alice@alice.alice | + And a user with email "bob@bob.bob" is connected with "alice@alice.alice" + And "alice@alice.alice" has a public post with text "check this out!" + And "alice@alice.alice" has commented mentioning "bob@bob.bob" on "check this out!" + When I sign in as "alice@alice.alice" + And I follow "Bob Jones" + Then I should see "Bob Jones" From ab0a4606e2fe29956f22c4c8db13092d858b5877 Mon Sep 17 00:00:00 2001 From: Steffen van Bergerem Date: Mon, 13 Feb 2017 21:56:05 +0100 Subject: [PATCH 024/318] Use new mention syntax in specs --- spec/helper_methods.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/helper_methods.rb b/spec/helper_methods.rb index 177999a96..c1992dc82 100644 --- a/spec/helper_methods.rb +++ b/spec/helper_methods.rb @@ -47,7 +47,7 @@ module HelperMethods def text_mentioning(*people) people.map {|person| - "this is a text mentioning @{#{person.name}; #{person.diaspora_handle}} ... have fun testing!" + "this is a text mentioning @{#{person.diaspora_handle}} ... have fun testing!" }.join(" ") end From 97c351c7b4e312b6eae647e86a7fe8f84f1ad267 Mon Sep 17 00:00:00 2001 From: Benjamin Neff Date: Thu, 16 Feb 2017 01:45:13 +0100 Subject: [PATCH 025/318] Add In-Reply-To and References header to mentioned in comment mail --- app/mailers/notification_mailers/mentioned_in_comment.rb | 1 + spec/mailers/notifier_spec.rb | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/app/mailers/notification_mailers/mentioned_in_comment.rb b/app/mailers/notification_mailers/mentioned_in_comment.rb index abb346ea8..0e9a51bba 100644 --- a/app/mailers/notification_mailers/mentioned_in_comment.rb +++ b/app/mailers/notification_mailers/mentioned_in_comment.rb @@ -5,6 +5,7 @@ module NotificationMailers def set_headers(target_id) # rubocop:disable Style/AccessorMethodName @comment = Mention.find_by_id(target_id).mentions_container + @headers[:in_reply_to] = @headers[:references] = "<#{@comment.parent.guid}@#{AppConfig.pod_uri.host}>" @headers[:subject] = I18n.t("notifier.mentioned.subject", name: @sender.name) end end diff --git a/spec/mailers/notifier_spec.rb b/spec/mailers/notifier_spec.rb index 2ded0d80f..eb871f7cd 100644 --- a/spec/mailers/notifier_spec.rb +++ b/spec/mailers/notifier_spec.rb @@ -120,6 +120,11 @@ describe Notifier, type: :mailer do expect(mail.subject).to include(comment.author.name) end + it "IN-REPLY-TO and REFERENCES: references the commented post" do + expect(mail.in_reply_to).to eq("#{comment.parent.guid}@#{AppConfig.pod_uri.host}") + expect(mail.references).to eq("#{comment.parent.guid}@#{AppConfig.pod_uri.host}") + end + it "has the comment link in the body" do expect(mail.body.encoded).to include(post_url(comment.parent, anchor: comment.guid)) end From eac8c7572ca63813d7397ef95e3bc0fc7c3fee7b Mon Sep 17 00:00:00 2001 From: Benjamin Neff Date: Thu, 16 Feb 2017 01:58:19 +0100 Subject: [PATCH 026/318] Remove unused From headers It is already added in the default_headers --- app/mailers/notification_mailers/also_commented.rb | 1 - app/mailers/notification_mailers/comment_on_post.rb | 1 - app/mailers/notification_mailers/private_message.rb | 3 +-- spec/mailers/notifier_spec.rb | 6 ++++-- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/app/mailers/notification_mailers/also_commented.rb b/app/mailers/notification_mailers/also_commented.rb index aa063cfa8..c6c4da8de 100644 --- a/app/mailers/notification_mailers/also_commented.rb +++ b/app/mailers/notification_mailers/also_commented.rb @@ -7,7 +7,6 @@ module NotificationMailers @comment = Comment.find_by_id(comment_id) if mail? - @headers[:from] = "\"#{@comment.author_name} (diaspora*)\" <#{AppConfig.mail.sender_address}>" @headers[:in_reply_to] = @headers[:references] = "<#{@comment.parent.guid}@#{AppConfig.pod_uri.host}>" if @comment.public? @headers[:subject] = "Re: #{@comment.comment_email_subject}" diff --git a/app/mailers/notification_mailers/comment_on_post.rb b/app/mailers/notification_mailers/comment_on_post.rb index 4782f52b2..c9957e86f 100644 --- a/app/mailers/notification_mailers/comment_on_post.rb +++ b/app/mailers/notification_mailers/comment_on_post.rb @@ -5,7 +5,6 @@ module NotificationMailers def set_headers(comment_id) @comment = Comment.find(comment_id) - @headers[:from] = "\"#{@comment.author_name} (diaspora*)\" <#{AppConfig.mail.sender_address}>" @headers[:in_reply_to] = @headers[:references] = "<#{@comment.parent.guid}@#{AppConfig.pod_uri.host}>" if @comment.public? @headers[:subject] = "Re: #{@comment.comment_email_subject}" diff --git a/app/mailers/notification_mailers/private_message.rb b/app/mailers/notification_mailers/private_message.rb index 9cbe71dc3..60a5013e8 100644 --- a/app/mailers/notification_mailers/private_message.rb +++ b/app/mailers/notification_mailers/private_message.rb @@ -3,11 +3,10 @@ module NotificationMailers attr_accessor :message, :conversation, :participants def set_headers(message_id) - @message = Message.find_by_id(message_id) + @message = Message.find_by_id(message_id) @conversation = @message.conversation @participants = @conversation.participants - @headers[:from] = "\"#{@message.author_name} (diaspora*)\" <#{AppConfig.mail.sender_address}>" @headers[:subject] = I18n.t("notifier.private_message.subject") @headers[:in_reply_to] = @headers[:references] = "<#{@conversation.guid}@#{AppConfig.pod_uri.host}>" end diff --git a/spec/mailers/notifier_spec.rb b/spec/mailers/notifier_spec.rb index eb871f7cd..3adaca132 100644 --- a/spec/mailers/notifier_spec.rb +++ b/spec/mailers/notifier_spec.rb @@ -281,7 +281,9 @@ describe Notifier, type: :mailer do let(:comment) { eve.comment!(commented_post, "Totally is") } describe ".comment_on_post" do - let(:comment_mail) { Notifier.send_notification("comment_on_post", bob.id, person.id, comment.id).deliver_now } + let(:comment_mail) { + Notifier.send_notification("comment_on_post", bob.id, eve.person.id, comment.id).deliver_now + } it "TO: goes to the right person" do expect(comment_mail.to).to eq([bob.email]) @@ -322,7 +324,7 @@ describe Notifier, type: :mailer do end describe ".also_commented" do - let(:comment_mail) { Notifier.send_notification("also_commented", bob.id, person.id, comment.id) } + let(:comment_mail) { Notifier.send_notification("also_commented", bob.id, eve.person.id, comment.id) } it "TO: goes to the right person" do expect(comment_mail.to).to eq([bob.email]) From 3d95642aca30c3dddc665c6d2379e7545227aaa4 Mon Sep 17 00:00:00 2001 From: Benjamin Neff Date: Thu, 16 Feb 2017 03:02:38 +0100 Subject: [PATCH 027/318] Fix receiving multiple mentioned-in-comment notifications When somebody commented multiple times and is mentioned in another comment afterwards, the person received multiple notifications. --- app/models/notifications/mentioned_in_comment.rb | 2 +- spec/integration/mentioning_spec.rb | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/app/models/notifications/mentioned_in_comment.rb b/app/models/notifications/mentioned_in_comment.rb index 5e5466b68..5b57f395b 100644 --- a/app/models/notifications/mentioned_in_comment.rb +++ b/app/models/notifications/mentioned_in_comment.rb @@ -11,7 +11,7 @@ module Notifications end def self.filter_mentions(mentions, mentionable, _recipient_user_ids) - mentions.joins(:person).merge(Person.allowed_to_be_mentioned_in_a_comment_to(mentionable.parent)) + mentions.includes(:person).merge(Person.allowed_to_be_mentioned_in_a_comment_to(mentionable.parent)).distinct end def mail_job diff --git a/spec/integration/mentioning_spec.rb b/spec/integration/mentioning_spec.rb index 2e6b4292d..367758bf8 100644 --- a/spec/integration/mentioning_spec.rb +++ b/spec/integration/mentioning_spec.rb @@ -376,6 +376,18 @@ describe "mentioning", type: :request do end end end + + it "only creates one notification for the mentioned person, when mentioned person commented twice before" do + parent = FactoryGirl.create(:status_message_in_aspect, author: author.person) + mentioned_user = FactoryGirl.create(:user_with_aspect, friends: [author]) + mentioned_user.comment!(parent, "test comment 1") + mentioned_user.comment!(parent, "test comment 2") + comment = inlined_jobs do + author.comment!(parent, text_mentioning(mentioned_user)) + end + + expect(notifications_about_mentioning(mentioned_user, comment).count).to eq(1) + end end end end From 509f429cc8b5bd530545dd3dc189f54105d4d409 Mon Sep 17 00:00:00 2001 From: Benjamin Neff Date: Sun, 5 Mar 2017 17:41:12 +0100 Subject: [PATCH 028/318] Move 'distinct' to 'allowed_to_be_mentioned_in_a_comment_to' --- .../notifications/mentioned_in_comment.rb | 2 +- app/models/person.rb | 19 ++++++++---------- spec/models/person_spec.rb | 20 +++++++++---------- 3 files changed, 18 insertions(+), 23 deletions(-) diff --git a/app/models/notifications/mentioned_in_comment.rb b/app/models/notifications/mentioned_in_comment.rb index 5b57f395b..35ef9b61a 100644 --- a/app/models/notifications/mentioned_in_comment.rb +++ b/app/models/notifications/mentioned_in_comment.rb @@ -11,7 +11,7 @@ module Notifications end def self.filter_mentions(mentions, mentionable, _recipient_user_ids) - mentions.includes(:person).merge(Person.allowed_to_be_mentioned_in_a_comment_to(mentionable.parent)).distinct + mentions.includes(:person).merge(Person.allowed_to_be_mentioned_in_a_comment_to(mentionable.parent)) end def mail_job diff --git a/app/models/person.rb b/app/models/person.rb index e9eefc6ec..3da18333b 100644 --- a/app/models/person.rb +++ b/app/models/person.rb @@ -61,11 +61,7 @@ class Person < ActiveRecord::Base } scope :remote, -> { where('people.owner_id IS NULL') } scope :local, -> { where('people.owner_id IS NOT NULL') } - scope :for_json, -> { - select("people.id, people.guid, people.diaspora_handle") - .distinct - .includes(:profile) - } + scope :for_json, -> { select("people.id, people.guid, people.diaspora_handle").includes(:profile) } # @note user is passed in here defensively scope :all_from_aspects, ->(aspect_ids, user) { @@ -131,12 +127,13 @@ class Person < ActiveRecord::Base # @param [Post] the post for which we query mentionable in comments people # @return [Person::ActiveRecord_Relation] scope :allowed_to_be_mentioned_in_a_comment_to, ->(post) { - if post.public? - all - else - left_join_visible_post_interactions_on_authorship(post.id) - .where("comments.id IS NOT NULL OR likes.id IS NOT NULL OR people.id = #{post.author_id}") - end + allowed = if post.public? + all + else + left_join_visible_post_interactions_on_authorship(post.id) + .where("comments.id IS NOT NULL OR likes.id IS NOT NULL OR people.id = #{post.author_id}") + end + allowed.distinct } # This scope adds sorting of people in the order, appropriate for suggesting to a user (current user) who diff --git a/spec/models/person_spec.rb b/spec/models/person_spec.rb index 4e65c6ccc..9c54e98ee 100644 --- a/spec/models/person_spec.rb +++ b/spec/models/person_spec.rb @@ -24,16 +24,6 @@ describe Person, :type => :model do Person.for_json.first.serialized_public_key }.to raise_error ActiveModel::MissingAttributeError end - - it 'selects distinct people' do - aspect = bob.aspects.create(:name => 'hilarious people') - aspect.contacts << bob.contact_for(eve.person) - person_ids = Person.for_json.joins(:contacts => :aspect_memberships). - where(:contacts => {:user_id => bob.id}, - :aspect_memberships => {:aspect_id => bob.aspect_ids}).map{|p| p.id} - - expect(person_ids.uniq).to eq(person_ids) - end end describe '.local' do @@ -131,9 +121,17 @@ describe Person, :type => :model do ).to match_array([alice, bob, eve, kate].map(&:person_id)) end + it "selects distinct people" do + alice.comment!(status_bob, "hyi") + alice.comment!(status_bob, "how are you?") + expect( + Person.allowed_to_be_mentioned_in_a_comment_to(status_bob).ids + ).to match_array([alice, bob].map(&:person_id)) + end + it "returns all for public posts" do status_bob.update(public: true) # set parent public - expect(Person.allowed_to_be_mentioned_in_a_comment_to(status_bob)).to eq(Person.all) + expect(Person.allowed_to_be_mentioned_in_a_comment_to(status_bob).ids).to match_array(Person.ids) end end From 6657fd51fa4655bd776a80240ce07010b7f133a9 Mon Sep 17 00:00:00 2001 From: goobertron Date: Tue, 16 Aug 2016 20:46:10 +0100 Subject: [PATCH 029/318] Capitalisation of colour themes --- config/color_themes.yml | 8 ++++---- config/initializers/color_themes.rb | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/config/color_themes.yml b/config/color_themes.yml index 896658841..9f33b152f 100644 --- a/config/color_themes.yml +++ b/config/color_themes.yml @@ -1,7 +1,7 @@ available: - original: "Original Gray" - original_white: "Original White Background" - dark_green: "Dark Green" + original: "Original gray" + original_white: "Original white background" + dark_green: "Dark green" magenta: "Magenta" - egyptian_blue: "Egyptian Blue" + egyptian_blue: "Egyptian blue" dark: "Dark" diff --git a/config/initializers/color_themes.rb b/config/initializers/color_themes.rb index 6f76ee51c..4d172789c 100644 --- a/config/initializers/color_themes.rb +++ b/config/initializers/color_themes.rb @@ -10,10 +10,10 @@ if color_themes_file.exist? if color_themes["available"].length > 0 color_themes["available"] else - {"original" => "Original Gray"} + {"original" => "Original gray"} end else - AVAILABLE_COLOR_THEMES = {"original" => "Original Gray"}.freeze + AVAILABLE_COLOR_THEMES = {"original" => "Original gray"}.freeze end # Get all codes from available themes into a separate variable, so that they can be called easier. AVAILABLE_COLOR_THEME_CODES = AVAILABLE_COLOR_THEMES.keys From 7eb3dabb444d99cf51e672e065284f9aa23628e9 Mon Sep 17 00:00:00 2001 From: Steffen van Bergerem Date: Thu, 16 Mar 2017 12:25:41 +0100 Subject: [PATCH 030/318] i18n for color themes --- app/helpers/users_helper.rb | 8 ++++---- app/models/user.rb | 2 +- config/color_themes.yml | 12 ++++++------ config/initializers/color_themes.rb | 8 +++----- config/locales/diaspora/en.yml | 8 ++++++++ 5 files changed, 22 insertions(+), 16 deletions(-) diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb index d79b6b059..5d181ea9c 100644 --- a/app/helpers/users_helper.rb +++ b/app/helpers/users_helper.rb @@ -31,13 +31,13 @@ module UsersHelper # specified from AVAILABLE_COLOR_THEMES in # config/initializers/color_themes.rb. # - # @example if AVAILABLE_COLOR_THEMES = {"original"=>"Original dark", "dark_green" => "Dark green"} + # @example if AVAILABLE_COLOR_THEMES = ["original", "dark_green"] # available_color_themes - # #=> [["Original dark", "original"], ["Dark green", "dark_green"]] + # #=> [["Original gray", "original"], ["Dark green", "dark_green"]] def available_color_themes opts = [] - AVAILABLE_COLOR_THEMES.map do |theme_code, theme_name| - opts << [theme_name, theme_code] + AVAILABLE_COLOR_THEMES.map do |theme_code| + opts << [I18n.t("color_themes.#{theme_code}"), theme_code] end opts end diff --git a/app/models/user.rb b/app/models/user.rb index 85ea59cb6..9969203ba 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -30,7 +30,7 @@ class User < ActiveRecord::Base validates_length_of :username, :maximum => 32 validates_exclusion_of :username, :in => AppConfig.settings.username_blacklist validates_inclusion_of :language, :in => AVAILABLE_LANGUAGE_CODES - validates :color_theme, inclusion: {in: AVAILABLE_COLOR_THEME_CODES}, allow_blank: true + validates :color_theme, inclusion: {in: AVAILABLE_COLOR_THEMES}, allow_blank: true validates_format_of :unconfirmed_email, :with => Devise.email_regexp, :allow_blank => true validate :unconfirmed_email_quasiuniqueness diff --git a/config/color_themes.yml b/config/color_themes.yml index 9f33b152f..45dfd5106 100644 --- a/config/color_themes.yml +++ b/config/color_themes.yml @@ -1,7 +1,7 @@ available: - original: "Original gray" - original_white: "Original white background" - dark_green: "Dark green" - magenta: "Magenta" - egyptian_blue: "Egyptian blue" - dark: "Dark" + - original + - original_white + - dark_green + - magenta + - egyptian_blue + - dark diff --git a/config/initializers/color_themes.rb b/config/initializers/color_themes.rb index 4d172789c..ae4757610 100644 --- a/config/initializers/color_themes.rb +++ b/config/initializers/color_themes.rb @@ -8,12 +8,10 @@ if color_themes_file.exist? # else include the original theme. AVAILABLE_COLOR_THEMES = if color_themes["available"].length > 0 - color_themes["available"] + color_themes["available"].freeze else - {"original" => "Original gray"} + ["original"].freeze end else - AVAILABLE_COLOR_THEMES = {"original" => "Original gray"}.freeze + AVAILABLE_COLOR_THEMES = ["original"].freeze end -# Get all codes from available themes into a separate variable, so that they can be called easier. -AVAILABLE_COLOR_THEME_CODES = AVAILABLE_COLOR_THEMES.keys diff --git a/config/locales/diaspora/en.yml b/config/locales/diaspora/en.yml index f280e4c69..b90dd4950 100644 --- a/config/locales/diaspora/en.yml +++ b/config/locales/diaspora/en.yml @@ -240,6 +240,14 @@ en: post_something: "Post to diaspora*" explanation: "Post to diaspora* from anywhere by bookmarking this link => %{link}." + color_themes: + dark: "Dark" + dark_green: "Dark green" + egyptian_blue: "Egyptian blue" + magenta: "Magenta" + original: "Original gray" + original_white: "Original white background" + comments: create: error: "Failed to comment." From c90cb3328ef1ac121177cb2bb52920c683fe229c Mon Sep 17 00:00:00 2001 From: cmrd Senya Date: Thu, 10 Nov 2016 17:46:31 +0200 Subject: [PATCH 031/318] jQuery 3 integration --- Gemfile | 4 ++-- Gemfile.lock | 10 +++++----- app/assets/javascripts/jasmine-load-all.js | 2 +- app/helpers/application_helper.rb | 8 +++++--- config/application.rb | 2 +- spec/helpers/application_helper_spec.rb | 2 +- 6 files changed, 15 insertions(+), 13 deletions(-) diff --git a/Gemfile b/Gemfile index 84e2256a2..997615e35 100644 --- a/Gemfile +++ b/Gemfile @@ -86,13 +86,13 @@ gem "entypo-rails", "3.0.0" # JavaScript gem "handlebars_assets", "0.23.1" -gem "jquery-rails", "4.2.1" +gem "jquery-rails", "4.2.2" gem "jquery-ui-rails", "5.0.5" gem "js-routes", "1.3.3" gem "js_image_paths", "0.1.0" source "https://rails-assets.org" do - gem "rails-assets-jquery", "2.2.4" # Should be kept in sync with jquery-rails + gem "rails-assets-jquery", "3.1.1" # Should be kept in sync with jquery-rails gem "rails-assets-highlightjs", "9.9.0" gem "rails-assets-markdown-it", "8.3.0" diff --git a/Gemfile.lock b/Gemfile.lock index 9b35f6791..17ef3130e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -324,7 +324,7 @@ GEM rake jasmine-core (2.5.2) jasmine-jquery-rails (2.0.3) - jquery-rails (4.2.1) + jquery-rails (4.2.2) rails-dom-testing (>= 1, < 3) railties (>= 4.2.0) thor (>= 0.14, < 2.0) @@ -540,7 +540,7 @@ GEM rails-assets-jasmine (2.5.2) rails-assets-jasmine-ajax (3.3.1) rails-assets-jasmine (~> 2) - rails-assets-jquery (2.2.4) + rails-assets-jquery (3.1.1) rails-assets-jquery-colorbox (1.6.4) rails-assets-jquery (>= 1.3.2) rails-assets-jquery-fullscreen-plugin (0.5.0) @@ -831,7 +831,7 @@ DEPENDENCIES i18n-inflector-rails (= 1.0.7) jasmine (= 2.5.2) jasmine-jquery-rails (= 2.0.3) - jquery-rails (= 4.2.1) + jquery-rails (= 4.2.2) jquery-ui-rails (= 5.0.5) js-routes (= 1.3.3) js_image_paths (= 0.1.0) @@ -878,7 +878,7 @@ DEPENDENCIES rails-assets-fine-uploader (= 5.13.0)! rails-assets-highlightjs (= 9.9.0)! rails-assets-jasmine-ajax (= 3.3.1)! - rails-assets-jquery (= 2.2.4)! + rails-assets-jquery (= 3.1.1)! rails-assets-jquery-placeholder (= 2.3.1)! rails-assets-jquery-textchange (= 0.2.3)! rails-assets-markdown-it (= 8.3.0)! @@ -928,4 +928,4 @@ DEPENDENCIES will_paginate (= 3.1.5) BUNDLED WITH - 1.14.5 + 1.14.6 diff --git a/app/assets/javascripts/jasmine-load-all.js b/app/assets/javascripts/jasmine-load-all.js index be83acdec..b465abdad 100644 --- a/app/assets/javascripts/jasmine-load-all.js +++ b/app/assets/javascripts/jasmine-load-all.js @@ -1,4 +1,4 @@ -//= require jquery2 +//= require jquery3 //= require handlebars.runtime //= require templates //= require main diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 3a89c597d..b46b27203 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -52,11 +52,13 @@ module ApplicationHelper def jquery_include_tag buf = [] if AppConfig.privacy.jquery_cdn? - version = Jquery::Rails::JQUERY_2_VERSION + version = Jquery::Rails::JQUERY_3_VERSION buf << [javascript_include_tag("//code.jquery.com/jquery-#{version}.min.js")] - buf << [nonced_javascript_tag("!window.jQuery && document.write(unescape('#{j javascript_include_tag('jquery2')}'));")] + buf << [ + nonced_javascript_tag("!window.jQuery && document.write(unescape('#{j javascript_include_tag('jquery3')}'));") + ] else - buf << [javascript_include_tag("jquery2")] + buf << [javascript_include_tag("jquery3")] end buf << [javascript_include_tag("jquery_ujs")] buf << [nonced_javascript_tag("jQuery.ajaxSetup({'cache': false});")] diff --git a/config/application.rb b/config/application.rb index 98bf0609f..dd9ca5adf 100644 --- a/config/application.rb +++ b/config/application.rb @@ -68,7 +68,7 @@ module Diaspora config.assets.precompile += %w( contact-list.js ie.js - jquery2.js + jquery3.js jquery_ujs.js main.js jsxc.js diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb index 8a277d41a..1109c2a4c 100644 --- a/spec/helpers/application_helper_spec.rb +++ b/spec/helpers/application_helper_spec.rb @@ -54,7 +54,7 @@ describe ApplicationHelper, :type => :helper do end it 'includes jquery.js from asset pipeline' do - expect(helper.jquery_include_tag).to match(/jquery2\.js/) + expect(helper.jquery_include_tag).to match(/jquery3\.js/) expect(helper.jquery_include_tag).not_to match(/jquery\.com/) end end From 71e0bdc411a99414d85b18b571a20aa779896da7 Mon Sep 17 00:00:00 2001 From: cmrd Senya Date: Tue, 13 Dec 2016 20:20:06 +0200 Subject: [PATCH 032/318] app_spec fixes --- spec/javascripts/app/app_spec.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/spec/javascripts/app/app_spec.js b/spec/javascripts/app/app_spec.js index 1ade3b556..01e49e5f3 100644 --- a/spec/javascripts/app/app_spec.js +++ b/spec/javascripts/app/app_spec.js @@ -62,6 +62,10 @@ describe("app", function() { }); describe("setupAjaxErrorRedirect", function() { + beforeEach(function() { + app.setupAjaxErrorRedirect(); + }); + it("redirects to /users/sign_in on 401 ajax responses", function() { spyOn(app, "_changeLocation"); $.ajax("/test"); @@ -115,7 +119,6 @@ describe("app", function() { beforeEach(function() { app.stream = {basePath: function() { return "/stream"; }}; app.notificationsCollection = {fetch: $.noop}; - spyOn(Backbone.history, "start"); this.link = $(""); spec.content().append(this.link); app.setupBackboneLinks(); @@ -123,6 +126,7 @@ describe("app", function() { afterEach(function() { app.stream = undefined; + Backbone.history.stop(); }); it("calls Backbone.history.navigate", function() { From c2f352d8371c3b7a87cec907cc501f3ea22061d2 Mon Sep 17 00:00:00 2001 From: cmrd Senya Date: Fri, 24 Mar 2017 00:40:24 +0200 Subject: [PATCH 033/318] Comment mentions front-end --- .../app/views/comment_mention_view.js | 10 ++++++++++ .../app/views/comment_stream_view.js | 1 + .../app/views/publisher/mention_view.js | 15 ++++++++------- app/assets/stylesheets/comments.scss | 4 ++-- app/assets/stylesheets/mentions.scss | 18 ++++++++++++++++++ app/assets/stylesheets/publisher.scss | 7 ------- .../templates/comment-stream_tpl.jst.hbs | 10 ++++++++-- app/views/publisher/_publisher.html.haml | 7 ++++--- features/desktop/mentions.feature | 19 +++++++++++++++++++ features/step_definitions/comment_steps.rb | 4 ++++ .../app/views/comment_mention_view_spec.js | 10 ++++++++++ .../app/views/comment_stream_view_spec.js | 7 +++++++ 12 files changed, 91 insertions(+), 21 deletions(-) create mode 100644 app/assets/javascripts/app/views/comment_mention_view.js create mode 100644 spec/javascripts/app/views/comment_mention_view_spec.js diff --git a/app/assets/javascripts/app/views/comment_mention_view.js b/app/assets/javascripts/app/views/comment_mention_view.js new file mode 100644 index 000000000..52b125774 --- /dev/null +++ b/app/assets/javascripts/app/views/comment_mention_view.js @@ -0,0 +1,10 @@ +// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later +//= require ./publisher/mention_view + +app.views.CommentMention = app.views.PublisherMention.extend({ + initialize: function(opts) { + opts.url = Routes.mentionablePost(opts.postId); + app.views.PublisherMention.prototype.initialize.call(this, opts); + } +}); +// @license-end diff --git a/app/assets/javascripts/app/views/comment_stream_view.js b/app/assets/javascripts/app/views/comment_stream_view.js index 05ba192db..c6374a301 100644 --- a/app/assets/javascripts/app/views/comment_stream_view.js +++ b/app/assets/javascripts/app/views/comment_stream_view.js @@ -27,6 +27,7 @@ app.views.CommentStream = app.views.Base.extend({ this.model.comments.each(this.appendComment, this); this.commentBox = this.$(".comment_box"); this.commentSubmitButton = this.$("input[name='commit']"); + new app.views.CommentMention({el: this.$el, postId: this.model.get("id")}); }, presenter: function(){ diff --git a/app/assets/javascripts/app/views/publisher/mention_view.js b/app/assets/javascripts/app/views/publisher/mention_view.js index f30779c70..bf15dc85e 100644 --- a/app/assets/javascripts/app/views/publisher/mention_view.js +++ b/app/assets/javascripts/app/views/publisher/mention_view.js @@ -6,15 +6,16 @@ app.views.PublisherMention = app.views.SearchBase.extend({ mentionSyntaxTemplate: function(person) { return "@{" + person.handle + "}"; }, events: { - "keydown #status_message_text": "onInputBoxKeyDown", - "input #status_message_text": "updateTypeaheadInput", - "click #status_message_text": "onInputBoxClick", - "blur #status_message_text": "onInputBoxBlur" + "keydown .mention-textarea": "onInputBoxKeyDown", + "input .mention-textarea": "updateTypeaheadInput", + "click .mention-textarea": "onInputBoxClick", + "blur .mention-textarea": "onInputBoxBlur" }, - initialize: function() { + initialize: function(opts) { this.mentionedPeople = []; - this.inputBox = this.$("#status_message_text"); + var url = (opts && opts.url) || "/contacts"; + this.inputBox = this.$(".mention-textarea"); this.typeaheadInput = this.$(".typeahead-mention-box"); this.bindTypeaheadEvents(); @@ -22,7 +23,7 @@ app.views.PublisherMention = app.views.SearchBase.extend({ typeaheadInput: this.typeaheadInput, customSearch: true, autoselect: true, - remoteRoute: {url: "/contacts"} + remoteRoute: {url: url} }); }, diff --git a/app/assets/stylesheets/comments.scss b/app/assets/stylesheets/comments.scss index 533c9cffb..54d5f1973 100644 --- a/app/assets/stylesheets/comments.scss +++ b/app/assets/stylesheets/comments.scss @@ -46,7 +46,7 @@ .comment.new-comment-form-wrapper { padding-bottom: 0; } - .submit_button { + .submit-button { margin-top: 10px; input { float: right; @@ -60,7 +60,7 @@ } textarea.comment_box:focus, textarea.comment_box:valid, textarea.comment_box:active { border-color: $border-dark-grey; - & + .submit_button { display: block; } + ~ .submit-button { display: block; } min-height: 35px; box-shadow: none; } diff --git a/app/assets/stylesheets/mentions.scss b/app/assets/stylesheets/mentions.scss index c9af7be45..97cd758ed 100644 --- a/app/assets/stylesheets/mentions.scss +++ b/app/assets/stylesheets/mentions.scss @@ -65,3 +65,21 @@ } } } + +.typeahead-mention-box-wrap .twitter-typeahead { + left: -1px; + width: calc(100% + 2px); + + .tt-menu { + // Override inline rule of Typeahead + // If this is not overridden (`position: absolute` by default in Typeahead) then + // the box is cut when opened because of the `overflow: hidden` from parent classes of comment form styles. By + // having `position: relative` here we make it visible by inserting it in the flow. + // This has a side effect of "Comment" button move down when box is open, but it feels like the least evil. + // scss-lint:disable ImportantRule + position: relative !important; + // scss-lint:enable ImportantRule + + width: 100%; + } +} diff --git a/app/assets/stylesheets/publisher.scss b/app/assets/stylesheets/publisher.scss index 94510aed7..f95480c94 100644 --- a/app/assets/stylesheets/publisher.scss +++ b/app/assets/stylesheets/publisher.scss @@ -19,12 +19,6 @@ .container-fluid{ padding: 0; } - .twitter-typeahead { - width: calc(100% + 2px); - - .tt-menu { width: 100%; } - } - form { margin: 0; #fileInfo { display: none !important; } @@ -245,7 +239,6 @@ } .twitter-typeahead { - left: -1px; // Override inline rule of Typeahead // scss-lint:disable ImportantRule position: absolute !important; diff --git a/app/assets/templates/comment-stream_tpl.jst.hbs b/app/assets/templates/comment-stream_tpl.jst.hbs index e7343507d..cf3bb4652 100644 --- a/app/assets/templates/comment-stream_tpl.jst.hbs +++ b/app/assets/templates/comment-stream_tpl.jst.hbs @@ -26,8 +26,14 @@
-