diff --git a/app/helpers/mailer_helper.rb b/app/helpers/mailer_helper.rb index 8917a84ed6..f29b2ff59a 100644 --- a/app/helpers/mailer_helper.rb +++ b/app/helpers/mailer_helper.rb @@ -127,4 +127,56 @@ def creator_text(work) work.pseuds.map { |p| text_pseud(p) }.to_sentence.html_safe end end + + def work_metadata_label(text) + text.html_safe + t("mailer.general.metadata_label_indicator") + end + + # Spacing is dealt with in locale files, e.g. " : " for French. + def work_tag_metadata(tags) + return if tags.empty? + + "#{work_tag_metadata_label(tags)}#{work_tag_metadata_list(tags)}" + end + + def style_work_metadata_label(text) + style_bold(work_metadata_label(text)) + end + + # Spacing is dealt with in locale files, e.g. " : " for French. + def style_work_tag_metadata(tags) + return if tags.empty? + + label = style_bold(work_tag_metadata_label(tags)) + "#{label}#{style_work_tag_metadata_list(tags)}".html_safe + end + + private + + def work_tag_metadata_label(tags) + return if tags.empty? + + type = tags.first.type + t("activerecord.models.#{type.underscore}", count: tags.count) + t("mailer.general.metadata_label_indicator") + end + + # We don't use .to_sentence because these aren't links and we risk making any + # connector word (e.g., "and") look like part of the final tag. + def work_tag_metadata_list(tags) + return if tags.empty? + + tags.pluck(:name).join(t("support.array.words_connector")) + end + + def style_work_tag_metadata_list(tags) + return if tags.empty? + + type = tags.first.type + # Fandom tags are linked and to_sentence'd. + if type == "Fandom" + tags.map { |f| style_link(f.name, fandom_url(f)) }.to_sentence.html_safe + else + work_tag_metadata_list(tags) + end + end end # end of MailerHelper diff --git a/app/helpers/translation_helper.rb b/app/helpers/translation_helper.rb index ea3fe70c79..f86f4936e3 100644 --- a/app/helpers/translation_helper.rb +++ b/app/helpers/translation_helper.rb @@ -60,4 +60,10 @@ def time_ago_in_words(from_time, include_seconds = false) alias distance_of_time_in_words_to_now time_ago_in_words + # Take some text and add whatever punctuation, symbols, and/or spacing + # we use to separate a metadata property from its value, e.g., "Property: ", + # "Propriété : ". + def metadata_property(text) + text.html_safe + t("mailer.general.metadata_label_indicator") + end end diff --git a/app/mailers/user_mailer.rb b/app/mailers/user_mailer.rb index 9168cbd0b1..f86762aa77 100644 --- a/app/mailers/user_mailer.rb +++ b/app/mailers/user_mailer.rb @@ -311,15 +311,15 @@ def recipient_notification(user_id, work_id, collection_id = nil) @user = User.find(user_id) @work = Work.find(work_id) @collection = Collection.find(collection_id) if collection_id - subject = if @collection - t("user_mailer.recipient_notification.subject.collection", - app_name: ArchiveConfig.APP_SHORT_NAME, - collection_title: @collection.title) - else - t("user_mailer.recipient_notification.subject.no_collection", - app_name: ArchiveConfig.APP_SHORT_NAME) - end I18n.with_locale(Locale.find(@user.preference.preferred_locale).iso) do + subject = if @collection + t("user_mailer.recipient_notification.subject.collection", + app_name: ArchiveConfig.APP_SHORT_NAME, + collection_title: @collection.title) + else + t("user_mailer.recipient_notification.subject.no_collection", + app_name: ArchiveConfig.APP_SHORT_NAME) + end mail( to: @user.email, subject: subject diff --git a/app/views/user_mailer/_work_info.html.erb b/app/views/user_mailer/_work_info.html.erb new file mode 100644 index 0000000000..877faa3421 --- /dev/null +++ b/app/views/user_mailer/_work_info.html.erb @@ -0,0 +1,24 @@ +<% # expects work %> +

+ <%= style_work_metadata_label(Work.human_attribute_name("chapter_total_display")) %><%= work.chapter_total_display %> +
<%= style_work_tag_metadata(work.fandoms) %> +
<%= style_work_tag_metadata(work.ratings) %> +
<%= style_work_tag_metadata(work.archive_warnings) %> + <% unless work.relationship_string.blank? %> +
<%= style_work_tag_metadata(work.relationships) %> + <% end %> + <% unless work.character_string.blank? %> +
<%= style_work_tag_metadata(work.characters) %> + <% end %> + <% unless work.freeform_string.blank? %> +
<%= style_work_tag_metadata(work.freeforms) %> + <% end %> + <% unless work.series.count.zero? %> +
<%= style_work_metadata_label(Series.model_name.human(count: work.series.count)) %><%= series_list_for_feeds(work).html_safe %> + <% end %> +

+ +<% unless work.summary.blank? %> +

<%= style_work_metadata_label(Work.human_attribute_name("summary")) %>

+ <%= style_quote(raw sanitize_field(work, :summary)) %> +<% end %> diff --git a/app/views/user_mailer/_work_info.text.erb b/app/views/user_mailer/_work_info.text.erb new file mode 100644 index 0000000000..a50823cd0b --- /dev/null +++ b/app/views/user_mailer/_work_info.text.erb @@ -0,0 +1,22 @@ +<% # expects work %> +<%= work_metadata_label(Work.human_attribute_name("chapter_total_display"))%><%= work.chapter_total_display %> +<%= work_tag_metadata(work.fandoms) %> +<%= work_tag_metadata(work.ratings) %> +<%= work_tag_metadata(work.archive_warnings) %> +<% unless work.relationship_string.blank? %> +<%= work_tag_metadata(work.relationships) %> +<% end %> +<% unless work.character_string.blank? %> +<%= work_tag_metadata(work.characters) %> +<% end %> +<% unless work.freeform_string.blank? %> +<%= work_tag_metadata(work.freeforms) %> +<% end %> +<% unless work.series.count.zero? %> +<%= Series.model_name.human(count: work.series.count) %><%= raw to_plain_text(series_list_for_feeds(work)) %> +<% end %> +<% unless work.summary.blank? %> + +<%= work_metadata_label(Work.human_attribute_name("summary")) %> + <%= raw to_plain_text(sanitize_field(work, :summary)) %> +<% end %> diff --git a/app/views/user_mailer/recipient_notification.html.erb b/app/views/user_mailer/recipient_notification.html.erb index dd85d467e6..bd4cecf817 100644 --- a/app/views/user_mailer/recipient_notification.html.erb +++ b/app/views/user_mailer/recipient_notification.html.erb @@ -7,23 +7,13 @@

- <% if @collection.nil? %> - <%= style_creation_link(@work.title, work_url(@work)) %> <%= "(#{@work.word_count} words)" %> - <% else %> - <%= style_creation_link(@work.title, collection_work_url(@collection, @work)) %> <%= "(#{@work.word_count} words)" %> - <% end %> + <% url = @collection ? collection_work_url(@collection, @work) : work_url(@work) %> + <%= style_creation_link(@work.title, url) %> <%= "(#{@work.word_count} words)" %>
- by <%= @work.anonymous? ? "an anonymous responder" : (@work.pseuds.map{|p| style_pseud_link(p)}.to_sentence.html_safe) %> -
- <% unless @work.fandom_string.blank? %> - <%= style_bold("Fandom:") %> <%= @work.fandom_string %> - <% end %> + by <%= creator_links(@work) %>

- <% unless @work.summary.blank? %> - <%= style_bold("Summary:") %> - <%= style_quote(raw sanitize_field(@work, :summary)) %> - <% end %> + <%= render "work_info", work: @work %> <% if @collection && !@collection.gift_notification.blank? %>

<%= @collection.gift_notification %>

diff --git a/app/views/user_mailer/recipient_notification.text.erb b/app/views/user_mailer/recipient_notification.text.erb index a4b3bc7c3f..3a92e0ee85 100644 --- a/app/views/user_mailer/recipient_notification.text.erb +++ b/app/views/user_mailer/recipient_notification.text.erb @@ -6,11 +6,8 @@ A gift work has been posted for you<% if @collection %> in the "<%= @collection. "<%= @work.title.html_safe %>" (<%= @work.word_count %> words) <%= @collection ? collection_work_url(@collection, @work) : work_url(@work) %> -by <%= @work.anonymous? ? "an anonymous responder" : (@work.pseuds.map{|p| text_pseud(p)}.to_sentence) %> +by <%= creator_text(@work) %> -<% unless @work.fandom_string.blank? %>Fandom: <%= @work.fandom_string %><% end %> - -<% unless @work.summary.blank? %>Summary: -<%= to_plain_text(raw sanitize_field(@work, :summary)) %><% end %> +<%= render "work_info", work: @work %> <% if @collection && !@collection.gift_notification.blank? %><%= @collection.gift_notification %><% end %><% end %> diff --git a/config/locales/mailers/en.yml b/config/locales/mailers/en.yml index d5b17623de..39f012a488 100644 --- a/config/locales/mailers/en.yml +++ b/config/locales/mailers/en.yml @@ -10,6 +10,7 @@ en: addressed: "Hi, %{name}!" unaddressed: "Hi!" introductory: "Hello from the Archive of Our Own!" + metadata_label_indicator: ": " signature: app_short_name: AO3 open_doors: The Open Doors team diff --git a/config/locales/models/en.yml b/config/locales/models/en.yml index 11649342f1..21fd44a1f3 100644 --- a/config/locales/models/en.yml +++ b/config/locales/models/en.yml @@ -23,12 +23,14 @@ en: models: archive_warning: one: "Warning" - other: "Warnings" + other: "Warnings" bookmark: "Bookmark" category: one: "Category" other: "Categories" - chapter: "Chapter" + chapter: + one: "Chapter" + other: "Chapters" character: one: "Character" other: "Characters" @@ -40,10 +42,15 @@ en: one: "Additional Tag" other: "Additional Tags" pseud: "Pseud" - rating: "Rating" + rating: + one: "Rating" + other: "Ratings" relationship: one: "Relationship" other: "Relationships" + series: + one: "Series" + other: "Series" tag: one: "Tag" other: "Tags" @@ -108,4 +115,7 @@ en: external_work: user_defined_tags_count: "Fandom, relationship, and character tags" work: + chapter_total_display: "Chapters" + summary: "Summary" user_defined_tags_count: "Fandom, relationship, character, and additional tags" + diff --git a/features/gift_exchanges/challenge_yuletide.feature b/features/gift_exchanges/challenge_yuletide.feature index 364f97daea..1d60b5c17e 100644 --- a/features/gift_exchanges/challenge_yuletide.feature +++ b/features/gift_exchanges/challenge_yuletide.feature @@ -574,7 +574,7 @@ Feature: Collection And the email should contain "A gift work has been posted for you in the" And the email should contain "Yuletide" And the email should contain "at the Archive of Our Own" - And the email should contain "by an anonymous responder" + And the email should contain "by Anonymous" And the email should not contain "by myname1" And the email should not contain "by myname2" And the email should not contain "by myname3" diff --git a/spec/helpers/mailer_helper_spec.rb b/spec/helpers/mailer_helper_spec.rb index 9bbe2e0dc8..02a5b9ca5e 100644 --- a/spec/helpers/mailer_helper_spec.rb +++ b/spec/helpers/mailer_helper_spec.rb @@ -7,4 +7,97 @@ expect(style_creation_link(work.title, work_url(work))).to eq("#{work.title}") end end + + describe "#work_metadata_label" do + it "appends the metadata indicator to a string" do + expect(work_metadata_label("Text")).to eq("Text: ") + end + end + + describe "#work_tag_metadata" do + { + "Fandom" => ["Fandom: ", "Fandoms: "], + "Rating" => ["Rating: ", "Ratings: "], + "ArchiveWarning" => ["Warning: ", "Warnings: "], + "Relationship" => ["Relationship: ", "Relationships: "], + "Character" => ["Character: ", "Characters: "], + "Freeform" => ["Additional Tag: ", "Additional Tags: "] + }.each_pair do |klass, labels| + context "when given one #{klass.underscore.humanize.downcase.singularize}" do + let(:tag) { create(:tag, type: klass) } + let(:tags) { [tag] } + + it "returns \"#{labels[0]}\" followed by the tag name" do + expect(work_tag_metadata(tags)).to eq("#{labels[0]}#{tag.name}") + end + end + + context "when given multiple #{klass.underscore.humanize.downcase.pluralize}" do + let(:tag1) { create(:tag, type: klass) } + let(:tag2) { create(:tag, type: klass) } + let(:tags) { [tag1, tag2] } + + it "returns \"#{labels[1]}\" followed by a comma-separated list of tag names" do + expect(work_tag_metadata(tags)).to eq("#{labels[1]}#{tag1.name}, #{tag2.name}") + end + end + end + end + + describe "#style_work_tag_metadata" do + context "when given one fandom" do + let(:fandom) { create(:fandom) } + let(:fandoms) { [fandom] } + + it "returns \"Fandom: \" styled bold and red followed by a link to the fandom" do + label = "Fandom: " + link = link_to(fandom.name, fandom_url(fandom), style: "color:#990000") + expect(style_work_tag_metadata(fandoms)).to eq("#{label}#{link}") + end + end + + context "when given multiple fandoms" do + let(:fandom1) { create(:fandom) } + let(:fandom2) { create(:fandom) } + let(:fandoms) { [fandom1, fandom2] } + + it "returns \"Fandoms: \" styled bold and red followed by links to the fandoms combined using to_sentence" do + label = "Fandoms: " + link1 = link_to(fandom1.name, fandom_url(fandom1), style: "color:#990000") + link2 = link_to(fandom2.name, fandom_url(fandom2), style: "color:#990000") + list = "#{link1} and #{link2}" + expect(style_work_tag_metadata(fandoms)).to eq("#{label}#{list}") + end + end + + { + "Rating" => ["Rating:", "Ratings:"], + "ArchiveWarning" => ["Warning:", "Warnings:"], + "Relationship" => ["Relationship:", "Relationships:"], + "Character" => ["Character:", "Characters:"], + "Freeform" => ["Additional Tag:", "Additional Tags:"] + }.each_pair do |klass, labels| + context "when given one #{klass.underscore.humanize.downcase.singularize}" do + let(:tag) { create(:tag, type: klass) } + let(:tags) { [tag] } + + it "returns \"#{labels[0]} \" styled bold and red followed by the tag name" do + label = "#{labels[0]} " + expect(style_work_tag_metadata(tags)).to eq("#{label}#{tag.name}") + end + end + + context "when given multiple #{klass.underscore.humanize.downcase.pluralize}" do + let(:tag1) { create(:tag, type: klass) } + let(:tag2) { create(:tag, type: klass) } + let(:tags) { [tag1, tag2] } + + it "returns \"#{labels[1]} \" styled bold and red followed by a comma-separated list of tag names" do + label = "#{labels[1]} " + list = "#{tag1.name}, #{tag2.name}" + expect(style_work_tag_metadata(tags)).to eq("#{label}#{list}") + end + end + end + end end diff --git a/spec/mailers/user_mailer_spec.rb b/spec/mailers/user_mailer_spec.rb index 9d32baffa6..96dc2f130b 100644 --- a/spec/mailers/user_mailer_spec.rb +++ b/spec/mailers/user_mailer_spec.rb @@ -783,7 +783,7 @@ subject(:email) { UserMailer.recipient_notification(user.id, work.id, collection.id) } let(:user) { create(:user) } - let(:work) { create(:work) } + let(:work) { create(:work, fandom_string: "Fandom 1, Fandom 2", character_string: "A, B") } let(:collection) { create(:collection) } # Test the headers @@ -797,6 +797,8 @@ # Test both body contents it_behaves_like "a multipart email" + it_behaves_like "a translated email" + describe "HTML version" do it "has the correct content" do expect(email).to have_html_part_content("Hi,