app/controllers & decorators i18n (#16126)

* app/controllers (& decorators) i18n etc

* tidy key names

* update keys

* delete ja.yml

* delete an involved ja.yml

* fix for PR review

* fix for spec

* delete ja.yml
This commit is contained in:
yheuhtozr 2022-02-04 03:35:56 +09:00 committed by GitHub
parent aa7b8d9f62
commit c4778d832e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
52 changed files with 424 additions and 157 deletions

View file

@ -9,7 +9,7 @@ class ApiSecretsController < ApplicationController
@secret.user_id = current_user.id
if @secret.save
flash[:notice] = "Your API Key has been generated: #{@secret.secret}"
flash[:notice] = I18n.t("api_secrets_controller.generated", secret: @secret.secret)
else
flash[:error] = @secret.errors_as_sentence
end
@ -21,10 +21,10 @@ class ApiSecretsController < ApplicationController
authorize @secret
if @secret.destroy
flash[:notice] = "Your API Key has been revoked."
flash[:notice] = I18n.t("api_secrets_controller.revoked")
else
flash[:error] =
"An error occurred. Please try again or send an email to: #{ForemInstance.email}"
I18n.t("errors.messages.try_again_email", email: ForemInstance.email)
end
redirect_back(fallback_location: root_path)

View file

@ -73,12 +73,12 @@ class ApplicationController < ActionController::Base
end
def not_authorized
render json: { error: "Error: not authorized" }, status: :unauthorized
render json: { error: I18n.t("application_controller.not_authorized") }, status: :unauthorized
raise NotAuthorizedError, "Unauthorized"
end
def bad_request
render json: { error: "Error: Bad Request" }, status: :bad_request
render json: { error: I18n.t("application_controller.bad_request") }, status: :bad_request
end
def error_too_many_requests(exc)
@ -94,7 +94,7 @@ class ApplicationController < ActionController::Base
respond_to do |format|
format.html { redirect_to sign_up_path }
format.json { render json: { error: "Please sign in" }, status: :unauthorized }
format.json { render json: { error: I18n.t("application_controller.please_sign_in") }, status: :unauthorized }
end
end

View file

@ -14,6 +14,6 @@ class ArticleApprovalsController < ApplicationController
end
end
@article.update(approved: params[:approved])
redirect_to "#{URI.parse(@article.path).path}/mod"
redirect_to "#{Addressable::URI.parse(@article.path).path}/mod"
end
end

View file

@ -129,7 +129,7 @@ class ArticlesController < ApplicationController
return
end
if params[:destination]
redirect_to(URI.parse(params[:destination]).path)
redirect_to(Addressable::URI.parse(params[:destination]).path)
return
end
if params[:article][:video_thumbnail_url]
@ -159,7 +159,7 @@ class ArticlesController < ApplicationController
authorize @article
Articles::Destroyer.call(@article)
respond_to do |format|
format.html { redirect_to "/dashboard", notice: "Article was successfully deleted." }
format.html { redirect_to "/dashboard", notice: I18n.t("articles_controller.deleted") }
format.json { head :no_content }
end
end

View file

@ -64,7 +64,7 @@ class CommentsController < ApplicationController
if @comment.invalid?
@comment.destroy
render json: { error: "comment already exists" }, status: :unprocessable_entity
render json: { error: I18n.t("comments_controller.create.failure") }, status: :unprocessable_entity
return
end
@ -77,7 +77,7 @@ class CommentsController < ApplicationController
)[1])
comment.destroy
render json: { error: "comment already exists" }, status: :unprocessable_entity
render json: { error: I18n.t("comments_controller.create.failure") }, status: :unprocessable_entity
else
message = @comment.errors_as_sentence
render json: { error: message }, status: :unprocessable_entity
@ -91,7 +91,7 @@ class CommentsController < ApplicationController
rescue StandardError => e
skip_authorization
message = "There was an error in your markdown: #{e}"
message = I18n.t("comments_controller.markdown", error: e)
render json: { error: message }, status: :unprocessable_entity
end
@ -106,26 +106,23 @@ class CommentsController < ApplicationController
@comment.user_id = moderator.id
@comment.body_markdown = response_template.content
authorize @comment
permit_commenter
if @comment.save
Notification.send_new_comment_notifications_without_delay(@comment)
Mention.create_all(@comment)
render json: { status: "created", path: @comment.path }
render json: { status: I18n.t("comments_controller.create.success"), path: @comment.path }
elsif (@comment = Comment.where(body_markdown: @comment.body_markdown,
commentable_id: @comment.commentable.id,
ancestry: @comment.ancestry)[0])
render json: { status: "comment already exists" }, status: :conflict
render json: { status: I18n.t("comments_controller.create.failure") }, status: :conflict
else
render json: { status: @comment&.errors&.full_messages&.to_sentence }, status: :unprocessable_entity
end
rescue ModerationUnauthorizedError => e
render json: { error: e.message }, status: :unprocessable_entity
rescue StandardError => e
skip_authorization
message = "There was an error in your markdown: #{e}"
message = I18n.t("comments_controller.markdown", error: e)
render json: { error: "error", status: message }, status: :unprocessable_entity
end
@ -169,7 +166,7 @@ class CommentsController < ApplicationController
end
rescue StandardError => e
@commentable = @comment.commentable
flash.now[:error] = "There was an error in your markdown: #{e}"
flash.now[:error] = I18n.t("comments_controller.markdown", error: e)
render :edit
end
@ -186,7 +183,7 @@ class CommentsController < ApplicationController
redirect = @comment.commentable&.path || user_path(current_user)
# NOTE: Brakeman doesn't like redirecting to a path, because of a "possible
# unprotected redirect". Using URI.parse().path is the recommended workaround.
redirect_to URI.parse(redirect).path, notice: "Comment was successfully deleted."
redirect_to Addressable::URI.parse(redirect).path, notice: I18n.t("comments_controller.delete.notice")
end
def delete_confirm
@ -202,7 +199,7 @@ class CommentsController < ApplicationController
parsed_markdown = MarkdownProcessor::Parser.new(fixed_body_markdown, source: Comment.new, user: current_user)
processed_html = parsed_markdown.finalize
rescue StandardError => e
processed_html = "<p>😔 There was an error in your markdown</p><hr><p>#{e}</p>"
processed_html = I18n.t("comments_controller.markdown_html", error: e)
end
respond_to do |format|
format.json { render json: { processed_html: processed_html }, status: :ok }
@ -262,8 +259,8 @@ class CommentsController < ApplicationController
if @comment.save
redirect_url = @comment.commentable&.path
if redirect_url
flash[:success] = "Comment was successfully deleted."
redirect_to URI.parse(redirect_url).path
flash[:success] = I18n.t("comments_controller.delete.notice")
redirect_to Addressable::URI.parse(redirect_url).path
else
redirect_to_comment_path
end
@ -300,7 +297,7 @@ class CommentsController < ApplicationController
end
def redirect_to_comment_path
flash[:error] = "Something went wrong; Comment NOT deleted."
flash[:error] = I18n.t("comments_controller.delete.error")
redirect_to "#{@comment.path}/mod"
end
@ -315,7 +312,7 @@ class CommentsController < ApplicationController
def permit_commenter
return unless user_blocked?
raise ModerationUnauthorizedError, "Not allowed due to moderation action"
raise ModerationUnauthorizedError, I18n.t("comments_controller.moderated")
end
def user_blocked?

View file

@ -3,8 +3,6 @@ module ImageUploads
extend ActiveSupport::Concern
MAX_FILENAME_LENGTH = 250
FILENAME_TOO_LONG_MESSAGE = "filename too long - the max is #{MAX_FILENAME_LENGTH} characters.".freeze
IS_NOT_FILE_MESSAGE = "invalid file type. Please upload a valid image.".freeze
def long_filename?(image)
image&.original_filename && image.original_filename.length > MAX_FILENAME_LENGTH
@ -13,4 +11,12 @@ module ImageUploads
def file?(image)
image.respond_to?(:original_filename)
end
def filename_too_long_message
I18n.t("concerns.image_uploads.too_long", max: MAX_FILENAME_LENGTH)
end
def is_not_file_message # rubocop:disable Naming/PredicateName
I18n.t("concerns.image_uploads.is_not_file")
end
end

View file

@ -1,7 +1,4 @@
class ConfirmationsController < Devise::ConfirmationsController
FLASH_MESSAGE = "Email sent! Please contact support at %<email>s if you are "\
"having trouble receiving your confirmation instructions.".freeze
# GET /resource/confirmation?confirmation_token=abcdef
def show
self.resource = resource_class.confirm_by_token(params[:confirmation_token])
@ -24,7 +21,7 @@ class ConfirmationsController < Devise::ConfirmationsController
self.resource = resource_class.send_confirmation_instructions(resource_params)
resource.errors.clear # Don't leak user information, like paranoid mode.
message = format(FLASH_MESSAGE, email: ForemInstance.email)
message = I18n.t("confirmations_controller.email_sent", email: ForemInstance.email)
flash.now[:global_notice] = message
render :new
end

View file

@ -33,7 +33,7 @@ class CreditsController < ApplicationController
if payment.success?
@purchaser = payment.purchaser
redirect_to credits_path, notice: "#{number_to_purchase} new credits purchased!"
redirect_to credits_path, notice: I18n.t("credits_controller.done", count: number_to_purchase)
else
flash[:error] = payment.error
redirect_to purchase_credits_path

View file

@ -23,7 +23,7 @@ class DevicesController < ApplicationController
def destroy
device = Device.find_by(unauthenticated_params)
unless device
render json: { error: "Not Found", status: 404 }, status: :not_found
render json: { error: I18n.t("devices_controller.not_found"), status: 404 }, status: :not_found
return
end

View file

@ -13,9 +13,9 @@ class DiscussionLocksController < ApplicationController
if @discussion_lock.save
bust_article_cache(article)
flash[:success] = "Discussion was successfully locked!"
flash[:success] = I18n.t("discussion_locks_controller.locked")
else
flash[:error] = "Error: #{@discussion_lock.errors_as_sentence}"
flash[:error] = I18n.t("errors.messages.general", errors: @discussion_lock.errors_as_sentence)
end
redirect_to "#{article.path}/manage"
@ -30,9 +30,9 @@ class DiscussionLocksController < ApplicationController
if discussion_lock.destroy
bust_article_cache(article)
flash[:success] = "Discussion was successfully unlocked!"
flash[:success] = I18n.t("discussion_locks_controller.unlocked")
else
flash[:error] = "Error: #{discussion_lock.errors_as_sentence}"
flash[:error] = I18n.t("errors.messages.general", errors: @discussion_lock.errors_as_sentence)
end
redirect_to "#{article.path}/manage"

View file

@ -5,7 +5,8 @@ class EmailSubscriptionsController < ApplicationController
if verified_params[:expires_at] > Time.current
user = User.find(verified_params[:user_id])
user.notification_setting.update(verified_params[:email_type] => false)
@email_type = preferred_email_name.fetch(verified_params[:email_type], "this list")
@email_type = preferred_email_name.fetch(verified_params[:email_type],
I18n.t("email_subscriptions_controller.this_list")).call
else
render "invalid_token"
end
@ -15,12 +16,15 @@ class EmailSubscriptionsController < ApplicationController
def preferred_email_name
{
email_digest_periodic: "#{Settings::Community.community_name} digest emails",
email_comment_notifications: "comment notifications",
email_follower_notifications: "follower notifications",
email_mention_notifications: "mention notifications",
email_unread_notifications: "unread notifications",
email_badge_notifications: "badge notifications"
email_digest_periodic: lambda {
I18n.t("email_subscriptions_controller.digest_emails",
community: Settings::Community.community_name)
},
email_comment_notifications: -> { I18n.t("email_subscriptions_controller.comment_notifications") },
email_follower_notifications: -> { I18n.t("email_subscriptions_controller.follower_notifications") },
email_mention_notifications: -> { I18n.t("email_subscriptions_controller.mention_notifications") },
email_unread_notifications: -> { I18n.t("email_subscriptions_controller.unread_notifications") },
email_badge_notifications: -> { I18n.t("email_subscriptions_controller.badge_notifications") }
}.freeze
end
end

View file

@ -1,8 +1,6 @@
class FeedbackMessagesController < ApplicationController
# No authorization required for entirely public controller
skip_before_action :verify_authenticity_token
FLASH_MESSAGE = "Make sure the forms are filled. 🤖 Other possible errors: "\
"%<errors>s".freeze
FEEDBACK_ALLOWED_PARAMS = %i[message feedback_type category reported_url offender_id].freeze
def create
@ -31,11 +29,15 @@ class FeedbackMessagesController < ApplicationController
respond_to do |format|
format.html { redirect_to feedback_messages_path }
format.json { render json: { success: true, message: "Your report is submitted" } }
format.json do
render json: { success: true, message: I18n.t("feedback_messages_controller.submitted") }
end
end
else
@previous_message = feedback_message_params[:message]
flash[:notice] = format(FLASH_MESSAGE, errors: @feedback_message.errors_as_sentence.presence || "N/A")
flash[:notice] =
I18n.t("feedback_messages_controller.error_fill",
errors: @feedback_message.errors_as_sentence.presence || I18n.t("feedback_messages_controller.n_a"))
respond_to do |format|
format.html { render "pages/report_abuse" }

View file

@ -68,7 +68,8 @@ class FollowsController < ApplicationController
unfollow(followable, params[:followable_type], need_notification: need_notification)
else
if rate_limiter.limit_by_action("follow_account")
render json: { error: "Daily account follow limit reached!" }, status: :too_many_requests
render json: { error: I18n.t("follows_controller.daily_limit") },
status: :too_many_requests
return
end
follow(followable, need_notification: need_notification)
@ -101,10 +102,10 @@ class FollowsController < ApplicationController
def follow(followable, need_notification: false)
user_follow = current_user.follow(followable)
Notification.send_new_follower_notification(user_follow) if need_notification
"followed"
I18n.t("follows_controller.followed")
rescue ActiveRecord::RecordInvalid
ForemStatsClient.increment("users.invalid_follow")
"already followed"
I18n.t("follows_controller.already_followed")
end
def unfollow(followable, followable_type, need_notification: false)
@ -113,6 +114,6 @@ class FollowsController < ApplicationController
Follows::DeleteCached.call(current_user, followable_type, followable.id)
"unfollowed"
I18n.t("follows_controller.unfollowed")
end
end

View file

@ -10,7 +10,8 @@ class GithubReposController < ApplicationController
# to fetch all of the user's repositories. This could eventually become slow
@repos = fetch_repositories_from_github(known_repositories)
rescue Github::Errors::Unauthorized => e
render json: { error: "GitHub Unauthorized: #{e.message}", status: 401 }, status: :unauthorized
render json: { error: I18n.t("github_repos_controller.github_unauthorized", e_message: e.message), status: 401 },
status: :unauthorized
end
def update_or_create
@ -20,7 +21,8 @@ class GithubReposController < ApplicationController
fetched_repo = fetch_repository_from_github(repo_params[:github_id_code])
unless fetched_repo
render json: { error: "GitHub repository not found", status: 404 }, status: :not_found
render json: { error: I18n.t("github_repos_controller.repo_not_found"), status: 404 },
status: :not_found
return
end

View file

@ -28,7 +28,8 @@ class ImageUploadsController < ApplicationController
rescue CarrierWave::ProcessingError # server error
respond_to do |format|
format.json do
render json: { error: "A server error has occurred!" }, status: :unprocessable_entity
render json: { error: I18n.t("image_uploads_controller.server_error") },
status: :unprocessable_entity
end
end
return
@ -49,8 +50,8 @@ class ImageUploadsController < ApplicationController
def validate_image
images = Array.wrap(params["image"])
return if images.blank?
return IS_NOT_FILE_MESSAGE unless valid_image_files?(images)
return FILENAME_TOO_LONG_MESSAGE unless valid_filenames?(images)
return is_not_file_message unless valid_image_files?(images)
return filename_too_long_message unless valid_filenames?(images)
nil
end

View file

@ -92,13 +92,13 @@ class ListingsController < ApplicationController
def destroy
authorize @listing
@listing.destroy!
redirect_to "/listings/dashboard", notice: "Listing was successfully deleted."
redirect_to "/listings/dashboard", notice: I18n.t("listings_controller.deleted")
end
private
def process_no_credit_left
redirect_to credits_path, notice: "Not enough available credits"
redirect_to credits_path, notice: I18n.t("listings_controller.no_credit")
end
def process_successful_draft

View file

@ -101,7 +101,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
rescue StandardError => e
Honeybadger.notify(e)
flash[:alert] = "Log in error: #{e}"
flash[:alert] = I18n.t("omniauth_callbacks_controller.log_in_error", e: e)
redirect_to new_user_registration_url
end
@ -110,7 +110,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
end
def user_persisted_but_username_taken?
@user.persisted? && @user.errors_as_sentence.include?("username has already been taken")
@user.persisted? && @user.errors_as_sentence.include?(I18n.t("omniauth_callbacks_controller.username_taken"))
end
# We only bypass CSRF checks on Apple callback path & Apple trusted ORIGIN

View file

@ -43,7 +43,7 @@ class OrganizationsController < ApplicationController
rate_limiter.track_limit_by_action(:organization_creation)
@organization_membership = OrganizationMembership.create!(organization_id: @organization.id,
user_id: current_user.id, type_of_user: "admin")
flash[:settings_notice] = "Your organization was successfully created and you are an admin."
flash[:settings_notice] = I18n.t("organizations_controller.created")
redirect_to "/settings/organization/#{@organization.id}"
else
render template: "users/edit"
@ -62,7 +62,7 @@ class OrganizationsController < ApplicationController
if @organization.update(organization_params.merge(profile_updated_at: Time.current))
@organization.users.touch_all(:organization_info_updated_at)
flash[:settings_notice] = "Your organization was successfully updated."
flash[:settings_notice] = I18n.t("organizations_controller.updated")
redirect_to "/settings/organization"
else
@org_organization_memberships = @organization.organization_memberships.includes(:user)
@ -79,12 +79,11 @@ class OrganizationsController < ApplicationController
Organizations::DeleteWorker.perform_async(organization.id, current_user.id)
flash[:settings_notice] =
"Your organization: \"#{organization.name}\" deletion is scheduled. You'll be notified when it's deleted."
I18n.t("organizations_controller.deletion_scheduled", organization_name: organization.name)
redirect_to user_settings_path(:organization)
rescue Pundit::NotAuthorizedError
flash[:error] = "Your organization was not deleted; you must be an admin, the only member in the organization, " \
"and have no articles connected to the organization."
flash[:error] = I18n.t("organizations_controller.not_deleted")
redirect_to user_settings_path(:organization, id: organization.id)
end
@ -92,7 +91,7 @@ class OrganizationsController < ApplicationController
set_organization
@organization.secret = @organization.generated_random_secret
@organization.save
flash[:settings_notice] = "Your org secret was updated"
flash[:settings_notice] = I18n.t("organizations_controller.secret_updated")
redirect_to user_settings_path(:organization)
end
@ -137,7 +136,7 @@ class OrganizationsController < ApplicationController
def valid_image_file?(image)
return true if file?(image)
@organization.errors.add(:profile_image, IS_NOT_FILE_MESSAGE)
@organization.errors.add(:profile_image, is_not_file_message)
false
end
@ -145,7 +144,7 @@ class OrganizationsController < ApplicationController
def valid_filename?(image)
return true unless long_filename?(image)
@organization.errors.add(:profile_image, FILENAME_TOO_LONG_MESSAGE)
@organization.errors.add(:profile_image, filename_too_long_message)
false
end

View file

@ -119,7 +119,7 @@ class PagesController < ApplicationController
def redirect_daily_thread_request(daily_thread)
if daily_thread
redirect_to(URI.parse(daily_thread.path).path)
redirect_to(Addressable::URI.parse(daily_thread.path).path)
else
redirect_to(notifications_path)
end

View file

@ -28,7 +28,7 @@ class PodcastsController < ApplicationController
if @podcast.save
current_user.add_role(:podcast_admin, @podcast) if added_by_owner?
flash[:global_notice] = "Podcast suggested"
flash[:global_notice] = I18n.t("podcasts_controller.podcast_suggested")
redirect_to pod_path
else
@ -74,10 +74,10 @@ class PodcastsController < ApplicationController
def valid_image_files_and_names?(images)
images.each do |field, image|
@podcast.errors.add(field, IS_NOT_FILE_MESSAGE) unless file?(image)
@podcast.errors.add(field, is_not_file_message) unless file?(image)
break if @podcast.errors.any?
@podcast.errors.add(field, FILENAME_TOO_LONG_MESSAGE) if long_filename?(image)
@podcast.errors.add(field, filename_too_long_message) if long_filename?(image)
end
@podcast.errors.blank?

View file

@ -8,9 +8,9 @@ class ProfilePinsController < ApplicationController
@profile_pin.pinnable_id = profile_pin_params[:pinnable_id].to_i
@profile_pin.pinnable_type = "Article"
if @profile_pin.save
flash[:success] = "📌 Pinned! (pinned posts display chronologically, 5 max)"
flash[:success] = I18n.t("views.pins.pinned")
else
flash[:error] = "You can only have five pins"
flash[:error] = I18n.t("views.pins.error")
end
redirect_back(fallback_location: "/dashboard")
bust_user_profile
@ -20,7 +20,7 @@ class ProfilePinsController < ApplicationController
# for removing pinnable
current_user.profile_pins.destroy_by(id: params[:id])
bust_user_profile
flash[:pins_success] = "🗑 Pin removed"
flash[:success] = I18n.t("views.pins.removed")
redirect_back(fallback_location: "/dashboard")
end

View file

@ -7,12 +7,12 @@ class ProfilesController < ApplicationController
def update
update_result = Users::Update.call(current_user, update_params)
if update_result.success?
flash[:settings_notice] = "Your profile has been updated"
flash[:settings_notice] = I18n.t("profiles_controller.updated")
redirect_to user_settings_path
else
@user = current_user
@tab = "profile"
flash[:error] = "Error: #{update_result.errors_as_sentence}"
flash[:error] = I18n.t("errors.messages.general", errors: update_result.errors_as_sentence)
render template: "users/edit", locals: {
user: update_params[:user],
profile: update_params[:profile],

View file

@ -22,7 +22,7 @@ class RatingVotesController < ApplicationController
format.json do
render json: { error: rating_vote.errors.full_messages.to_sentence }, status: :unprocessable_entity
end
format.html { render json: { result: "Not Upserted Successfully" } }
format.html { render json: { result: I18n.t("rating_votes_controller.not_upserted_successfully") } }
end
end
end

View file

@ -15,7 +15,7 @@ class RegistrationsController < Devise::RegistrationsController
authorize(params, policy_class: RegistrationPolicy)
unless recaptcha_verified?
flash[:notice] = "You must complete the recaptcha ✅"
flash[:notice] = I18n.t("registrations_controller.error.recaptcha")
return redirect_to new_user_registration_path(state: "email_signup")
end
@ -70,7 +70,7 @@ class RegistrationsController < Devise::RegistrationsController
# Alright, this error message isn't quite correct. Is the email
# from a blocked domain? Or an explicitly allowed domain. I
# think this is enough.
resource.errors.add(:email, "is not included in allowed domains.")
resource.errors.add(:email, I18n.t("registrations_controller.error.domain"))
end
def build_devise_resource

View file

@ -32,10 +32,12 @@ class ResponseTemplatesController < ApplicationController
response_template.type_of = "personal_comment"
if response_template.save
flash[:settings_notice] = "Your response template \"#{response_template.title}\" was created."
flash[:settings_notice] =
I18n.t("response_templates_controller.created", title: response_template.title)
redirect_to user_settings_path(tab: "response-templates", id: response_template.id)
else
flash[:error] = "Response template error: #{response_template.errors_as_sentence}"
flash[:error] =
I18n.t("response_templates_controller.response_template_error", errors: response_template.errors_as_sentence)
attributes = permitted_attributes(ResponseTemplate)
redirect_to user_settings_path(
tab: "response-templates",
@ -50,7 +52,8 @@ class ResponseTemplatesController < ApplicationController
authorize response_template
if response_template.destroy
flash[:settings_notice] = "Your response template \"#{response_template.title}\" was deleted."
flash[:settings_notice] =
I18n.t("response_templates_controller.deleted", title: response_template.title)
else
flash[:error] = response_template.errors_as_sentence # this will probably never fail
end
@ -63,10 +66,12 @@ class ResponseTemplatesController < ApplicationController
attributes = permitted_attributes(ResponseTemplate)
if response_template.update(attributes)
flash[:settings_notice] = "Your response template \"#{response_template.title}\" was updated."
flash[:settings_notice] =
I18n.t("response_templates_controller.updated", title: response_template.title)
redirect_to user_settings_path(tab: "response-templates", id: response_template.id)
else
flash[:error] = "Response template error: #{response_template.errors_as_sentence}"
flash[:error] =
I18n.t("response_templates_controller.response_template_error", errors: response_template.errors_as_sentence)
redirect_to user_settings_path(
tab: "response-templates",
id: response_template.id,

View file

@ -61,7 +61,7 @@ class SocialPreviewsController < ApplicationController
format.png do
html = render_to_string(template, formats: :html, layout: false)
redirect_to HtmlCssToImage.fetch_url(html: html, css: PNG_CSS,
google_fonts: "Roboto|Roboto+Condensed"), status: :found
google_fonts: I18n.t("social_previews_controller.fonts")), status: :found
end
end
end

View file

@ -3,7 +3,7 @@ module Stories
rescue_from ArgumentError, with: :bad_request
def index
@query = "...searching"
@query = I18n.t("stories_controller.searching")
@article_index = true
@current_ordering = current_search_results_ordering
set_surrogate_key_header "articles-page-with-query"

View file

@ -19,7 +19,7 @@ module Stories
pinned_at: PinnedArticle.updated_at.iso8601
}
else
render json: { error: "not found" }, status: :not_found
render json: { error: I18n.t("stories.pinned_articles_controller.not_found") }, status: :not_found
end
end

View file

@ -80,7 +80,7 @@ class StoriesController < ApplicationController
potential_username = params[:username].tr("@", "").downcase
@user = User.find_by("old_username = ? OR old_old_username = ?", potential_username, potential_username)
if @user&.articles&.find_by(slug: params[:slug])
redirect_permanently_to(URI.parse("/#{@user.username}/#{params[:slug]}").path)
redirect_permanently_to(Addressable::URI.parse("/#{@user.username}/#{params[:slug]}").path)
return
end
@ -401,7 +401,7 @@ class StoriesController < ApplicationController
url: URL.organization(@organization),
image: @organization.profile_image_url_for(length: 320),
name: @organization.name,
description: @organization.summary.presence || "404 bio not found"
description: @organization.summary.presence || I18n.t("stories_controller.404_bio_not_found")
}
end

View file

@ -13,12 +13,12 @@ class StripeActiveCardsController < ApplicationController
customer = find_or_create_customer
if Payments::Customer.create_source(customer.id, stripe_params[:stripe_token])
flash[:settings_notice] = "Your billing information has been updated"
flash[:settings_notice] = I18n.t("stripe_active_cards_controller.updated")
audit_log("add")
else
ForemStatsClient.increment("stripe.errors", tags: ["action:create_card", "user_id:#{current_user.id}"])
flash[:error] = "There was a problem updating your billing info."
flash[:error] = I18n.t("stripe_active_cards_controller.cannot_update")
end
redirect_to user_settings_path(:billing)
rescue Payments::CardError, Payments::InvalidRequestError => e
@ -35,11 +35,11 @@ class StripeActiveCardsController < ApplicationController
customer.default_source = card.id
if Payments::Customer.save(customer)
flash[:settings_notice] = "Your billing information has been updated"
flash[:settings_notice] = I18n.t("stripe_active_cards_controller.updated")
audit_log("update")
else
ForemStatsClient.increment("stripe.errors", tags: ["action:update_card", "user_id:#{current_user.id}"])
flash[:error] = "There was a problem updating your billing info."
flash[:error] = I18n.t("stripe_active_cards_controller.cannot_update")
end
redirect_to user_settings_path(:billing)
@ -55,13 +55,13 @@ class StripeActiveCardsController < ApplicationController
customer = find_customer
if customer.subscriptions.count.positive?
flash[:error] = "Can't remove card if you have an active membership. Please cancel your membership first."
flash[:error] = I18n.t("stripe_active_cards_controller.cannot_remove")
else
source = Payments::Customer.get_source(customer, params[:id])
Payments::Customer.detach_source(customer.id, source.id)
Payments::Customer.save(customer)
flash[:settings_notice] = "Your card has been successfully removed."
flash[:settings_notice] = I18n.t("stripe_active_cards_controller.removed")
audit_log("remove")
end

View file

@ -23,7 +23,7 @@ class TagAdjustmentsController < ApplicationController
render json: { status: "Success", result: tag_adjustment.adjustment_type,
colors: { bg: tag.bg_color_hex, text: tag.text_color_hex } }
end
format.html { redirect_to "#{URI.parse(article.path).path}/mod" }
format.html { redirect_to "#{Addressable::URI.parse(article.path).path}/mod" }
end
else
# TODO: remove this when we move over to full JSON endpoint
@ -35,7 +35,10 @@ class TagAdjustmentsController < ApplicationController
@already_adjusted_tags = @adjustments.map(&:tag_name).join(", ")
@allowed_to_adjust = @moderatable.instance_of?(Article) && (current_user.any_admin? || @tag_moderator_tags.any?)
respond_to do |format|
format.json { render json: { error: "Failure: #{tag_adjustment.errors.full_messages.to_sentence}" } }
format.json do
render json: { error: I18n.t("tag_adjustments_controller.failure",
errors: tag_adjustment.errors.full_messages.to_sentence) }
end
format.html { render template: "moderations/mod" }
end
end
@ -57,8 +60,8 @@ class TagAdjustmentsController < ApplicationController
respond_to do |format|
# TODO: add tag adjustment removal async route in actions panel
format.json { render json: { result: "Tag adjustment destroyed" } }
format.html { redirect_to "#{URI.parse(@article.path).path}/mod" }
format.json { render json: { result: I18n.t("tag_adjustments_controller.destroyed") } }
format.html { redirect_to "#{Addressable::URI.parse(@article.path).path}/mod" }
end
end
end

View file

@ -30,7 +30,7 @@ class TagsController < ApplicationController
@tag = Tag.find(params[:id])
authorize @tag
if @tag.errors.messages.blank? && @tag.update(tag_params)
flash[:success] = "Tag successfully updated! 👍 "
flash[:success] = I18n.t("tags_controller.tag_successfully_updated")
redirect_to "#{URL.tag_path(@tag)}/edit"
else
flash[:error] = @tag.errors.full_messages

View file

@ -31,7 +31,7 @@ module Users
cookies.permanent[:user_experience_level] = users_setting.experience_level.to_s
end
current_user.touch(:profile_updated_at)
flash[:settings_notice] = "Your config has been updated. Refresh to see all changes."
flash[:settings_notice] = I18n.t("users_controller.updated_config")
else
Honeycomb.add_field("error", users_setting.errors.messages.compact_blank)
Honeycomb.add_field("errored", true)

View file

@ -14,8 +14,6 @@ class UsersController < ApplicationController
ALLOWED_ONBOARDING_PARAMS = %i[checked_code_of_conduct checked_terms_and_conditions].freeze
INDEX_ATTRIBUTES_FOR_SERIALIZATION = %i[id name username summary profile_image].freeze
private_constant :INDEX_ATTRIBUTES_FOR_SERIALIZATION
REMOVE_IDENTITY_ERROR = "An error occurred. Please try again or send an email to: %<email>s".freeze
private_constant :REMOVE_IDENTITY_ERROR
def index
@users =
@ -51,9 +49,9 @@ class UsersController < ApplicationController
# explicitly requested "Feed fetch now" or simply updated any other field
import_articles_from_feed(@user)
notice = "Your profile was successfully updated."
notice = I18n.t("users_controller.updated_profile")
if @user.export_requested?
notice += " The export will be emailed to you shortly."
notice += I18n.t("users_controller.send_export")
ExportContentWorker.perform_async(@user.id, @user.email)
end
if @user.setting.experience_level.present?
@ -79,16 +77,16 @@ class UsersController < ApplicationController
set_current_tab("account")
if destroy_request_in_progress?
notice = "You have already requested account deletion. Please, check your email for further instructions."
notice = I18n.t("users_controller.deletion_in_progress")
flash[:settings_notice] = notice
redirect_to user_settings_path(@tab)
elsif @user.email?
Users::RequestDestroy.call(@user)
notice = "You have requested account deletion. Please, check your email for further instructions."
notice = I18n.t("users_controller.deletion_requested")
flash[:settings_notice] = notice
redirect_to user_settings_path(@tab)
else
flash[:settings_notice] = "Please, provide an email to delete your account."
flash[:settings_notice] = I18n.t("users_controller.provide_email")
redirect_to user_settings_path("account")
end
end
@ -99,15 +97,14 @@ class UsersController < ApplicationController
if @user
authorize @user
else
flash[:alert] = "You must be logged in to proceed with account deletion."
flash[:alert] = I18n.t("users_controller.log_in_to_delete")
redirect_to sign_up_path and return
end
destroy_token = Rails.cache.read("user-destroy-token-#{@user.id}")
# rubocop:disable Layout/LineLength
if destroy_token.blank?
flash[:settings_notice] = "Your token has expired, please request a new one. Tokens only last for 12 hours after account deletion is initiated."
flash[:settings_notice] = I18n.t("users_controller.token_expired")
redirect_to user_settings_path("account")
elsif destroy_token != params[:token]
Honeycomb.add_field("destroy_token", destroy_token)
@ -115,7 +112,6 @@ class UsersController < ApplicationController
raise ActionController::RoutingError, "Not Found"
end
# rubocop:enable Layout/LineLength
end
def full_delete
@ -123,10 +119,10 @@ class UsersController < ApplicationController
if @user.email?
Users::DeleteWorker.perform_async(@user.id)
sign_out @user
flash[:global_notice] = "Your account deletion is scheduled. You'll be notified when it's deleted."
flash[:global_notice] = I18n.t("users_controller.deletion_scheduled")
redirect_to new_user_registration_path
else
flash[:settings_notice] = "Please, provide an email to delete your account"
flash[:settings_notice] = I18n.t("users_controller.provide_email_delete")
redirect_to user_settings_path("account")
end
end
@ -134,7 +130,7 @@ class UsersController < ApplicationController
def remove_identity
set_current_tab("account")
error_message = format(REMOVE_IDENTITY_ERROR, email: ForemInstance.email)
error_message = I18n.t("errors.messages.try_again_email", email: ForemInstance.email)
unless Authentication::Providers.enabled?(params[:provider])
flash[:error] = error_message
redirect_to user_settings_path(@tab)
@ -158,7 +154,8 @@ class UsersController < ApplicationController
# We should delete them when a user unlinks their GitHub account.
@user.github_repos.destroy_all if provider.provider_name == :github
flash[:settings_notice] = "Your #{provider.official_name} account was successfully removed."
flash[:settings_notice] =
I18n.t("users_controller.removed_identity", provider: provider.official_name)
else
flash[:error] = error_message
end
@ -173,7 +170,7 @@ class UsersController < ApplicationController
if params[:user]
if params[:user].key?(:username) && params[:user][:username].blank?
return render_update_response(false, "Username cannot be blank")
return render_update_response(false, I18n.t("users_controller.username_blank"))
end
sanitize_user_params
@ -198,10 +195,11 @@ class UsersController < ApplicationController
authorize User
if (@organization = Organization.find_by(secret: params[:org_secret].strip))
OrganizationMembership.create(user_id: current_user.id, organization_id: @organization.id, type_of_user: "member")
flash[:settings_notice] = "You have joined the #{@organization.name} organization."
flash[:settings_notice] =
I18n.t("users_controller.joined_org", organization_name: @organization.name)
redirect_to "/settings/organization/#{@organization.id}"
else
flash[:error] = "The given organization secret was invalid."
flash[:error] = I18n.t("users_controller.invalid_secret")
redirect_to "/settings/organization/new"
end
end
@ -210,7 +208,7 @@ class UsersController < ApplicationController
org = Organization.find_by(id: params[:organization_id])
authorize org
OrganizationMembership.find_by(organization_id: org.id, user_id: current_user.id)&.delete
flash[:settings_notice] = "You have left your organization."
flash[:settings_notice] = I18n.t("users_controller.left_org")
redirect_to "/settings/organization/new"
end
@ -222,7 +220,7 @@ class UsersController < ApplicationController
organization: org)
OrganizationMembership.find_by(user_id: adminable.id, organization_id: org.id).update(type_of_user: "admin")
flash[:settings_notice] = "#{adminable.name} is now an admin."
flash[:settings_notice] = I18n.t("users_controller.added_admin", name: adminable.name)
redirect_to "/settings/organization/#{org.id}"
end
@ -233,7 +231,7 @@ class UsersController < ApplicationController
not_authorized unless current_user.org_admin?(org) && unadminable.org_admin?(org)
OrganizationMembership.find_by(user_id: unadminable.id, organization_id: org.id).update(type_of_user: "member")
flash[:settings_notice] = "#{unadminable.name} is no longer an admin."
flash[:settings_notice] = I18n.t("users_controller.removed_admin", name: unadminable.name)
redirect_to "/settings/organization/#{org.id}"
end
@ -245,7 +243,7 @@ class UsersController < ApplicationController
not_authorized unless current_user.org_admin?(org) && removable_org_membership
removable_org_membership.delete
flash[:settings_notice] = "#{removable.name} is no longer part of your organization."
flash[:settings_notice] = I18n.t("users_controller.removed_member", name: removable.name)
redirect_to "/settings/organization/#{org.id}"
end

View file

@ -21,9 +21,9 @@ class VideoStatesController < ApplicationController
NotifyMailer.with(article: @article).video_upload_complete_email.deliver_now
render json: { message: "Video state updated" }
render json: { message: I18n.t("video_states_controller.video_state_updated") }
else
render json: { message: "Related article not found" }, status: :not_found
render json: { message: I18n.t("video_states_controller.related_article_not_found") }, status: :not_found
end
end

View file

@ -67,7 +67,7 @@ class ArticleDecorator < ApplicationDecorator
modified_description += "." unless description.end_with?(".")
return modified_description if cached_tag_list.blank?
modified_description + " Tagged with #{cached_tag_list}."
modified_description + I18n.t("decorators.article_decorator.tagged_with", cached_tag_list: cached_tag_list)
end
def video_metadata
@ -102,8 +102,7 @@ class ArticleDecorator < ApplicationDecorator
# Used in determining when to bust additional routes for an Article's comments
def discussion?
cached_tag_list_array.include?("discuss") &&
featured_number.to_i > 35.hours.ago.to_i
cached_tag_list_array.include?("discuss") && featured_number.to_i > 35.hours.ago.to_i
end
def pinned?

View file

@ -23,9 +23,9 @@ class CommentDecorator < ApplicationDecorator
def readable_publish_date
if created_at.year == Time.current.year
created_at.strftime("%b %-e")
I18n.l(created_at, format: :short)
else
created_at.strftime("%b %-e '%y")
I18n.l(created_at, format: :short_with_yy)
end
end
end

View file

@ -14,9 +14,9 @@ class PodcastEpisodeDecorator < ApplicationDecorator
return "" unless published_at
if published_at.year == Time.current.year
published_at.strftime("%b %-e")
I18n.l(published_at, format: :short)
else
published_at.strftime("%b %-e '%y")
I18n.l(published_at, format: :short_with_yy)
end
end

View file

@ -18,7 +18,7 @@ class UserDecorator < ApplicationDecorator
},
].freeze
DEFAULT_PROFILE_SUMMARY = "404 bio not found".freeze
DEFAULT_PROFILE_SUMMARY = -> { I18n.t("stories_controller.404_bio_not_found") }
# The relevant attribute names for cached tags. These are the attributes that we'll make
# available in the front-end. The list comes from the two places (see below for that list).
@ -132,7 +132,7 @@ class UserDecorator < ApplicationDecorator
# Returns the users profile summary or a placeholder text
def profile_summary
profile.summary.presence || DEFAULT_PROFILE_SUMMARY
profile.summary.presence || DEFAULT_PROFILE_SUMMARY.call
end
delegate :display_sponsors, to: :setting

View file

@ -93,14 +93,14 @@ module Users
def valid_image_file?(image)
return true if file?(image)
errors.append(IS_NOT_FILE_MESSAGE)
errors.append(is_not_file_message)
false
end
def valid_filename?(image)
return true unless long_filename?(image)
errors.append(FILENAME_TOO_LONG_MESSAGE)
errors.append(filename_too_long_message)
false
end

View file

@ -82,7 +82,7 @@
<div id="page-content" class="wrapper <%= view_class %>" data-current-page="<%= current_page %>">
<% if flash[:global_notice] %>
<div class="crayons-banner" id="setup-banner" aria-live="polite">
<%= flash[:global_notice] %>
<%== flash[:global_notice] %>
</div>
<% end %>
<div id="page-content-inner">

View file

@ -0,0 +1,6 @@
---
en:
concerns:
image_uploads:
too_long: filename too long - the max is %{max} characters.
is_not_file: invalid file type. Please upload a valid image.

View file

@ -0,0 +1,6 @@
---
fr:
concerns:
image_uploads:
too_long: filename too long - the max is %{max} characters.
is_not_file: invalid file type. Please upload a valid image.

View file

@ -0,0 +1,121 @@
---
en:
api_secrets_controller:
generated: 'Your API Key has been generated: %{secret}'
revoked: Your API Key has been revoked.
application_controller:
bad_request: 'Error: Bad Request'
not_authorized: 'Error: not authorized'
please_sign_in: Please sign in
articles_controller:
deleted: Article was successfully deleted.
comments_controller:
create:
success: created
failure: comment already exists
delete:
error: Something went wrong; Comment NOT deleted.
notice: Comment was successfully deleted.
markdown: 'There was an error in your markdown: %{error}'
markdown_html: "<p>😔 There was an error in your markdown</p><hr><p>%{error}</p>"
moderated: Not allowed due to moderation action
confirmations_controller:
email_sent: Email sent! Please contact support at %{email} if you are having trouble receiving your confirmation instructions.
credits_controller:
done:
one: "%{count} new credits purchased!"
other: "%{count} new credits purchased!"
devices_controller:
not_found: Not Found
discussion_locks_controller:
locked: Discussion was successfully locked!
unlocked: Discussion was successfully unlocked!
email_subscriptions_controller:
badge_notifications: badge notifications
comment_notifications: comment notifications
digest_emails: "%{community} digest emails"
follower_notifications: follower notifications
mention_notifications: mention notifications
this_list: this list
unread_notifications: unread notifications
feedback_messages_controller:
error_fill: "Make sure the forms are filled. 🤖 Other possible errors: %{errors}"
n_a: N/A
submitted: Your report is submitted
follows_controller:
already_followed: already followed
daily_limit: Daily account follow limit reached!
followed: followed
unfollowed: unfollowed
github_repos_controller:
repo_not_found: GitHub repository not found
github_unauthorized: 'GitHub Unauthorized: %{e_message}'
image_uploads_controller:
server_error: A server error has occurred!
listings_controller:
deleted: Listing was successfully deleted.
no_credit: Not enough available credits
omniauth_callbacks_controller:
log_in_error: 'Log in error: %{e}'
username_taken: username has already been taken
organizations_controller:
secret_updated: Your org secret was updated
deletion_scheduled: 'Your organization: "%{organization_name}" deletion is scheduled. You''ll be notified when it''s deleted.'
not_deleted: Your organization was not deleted; you must be an admin, the only member in the organization, and have no articles connected to the organization.
created: Your organization was successfully created and you are an admin.
updated: Your organization was successfully updated.
podcasts_controller:
podcast_suggested: Podcast suggested
profiles_controller:
updated: Your profile has been updated
rating_votes_controller:
not_upserted_successfully: Not Upserted Successfully
registrations_controller:
error:
recaptcha: You must complete the recaptcha ✅
domain: is not included in allowed domains.
response_templates_controller:
response_template_error: 'Response template error: %{errors}'
created: Your response template "%{title}" was created.
deleted: Your response template "%{title}" was deleted.
updated: Your response template "%{title}" was updated.
social_previews_controller:
fonts: Roboto|Roboto+Condensed
stories:
pinned_articles_controller:
not_found: not found
stories_controller:
404_bio_not_found: 404 bio not found
searching: "...searching"
stripe_active_cards_controller:
cannot_remove: Can't remove card if you have an active membership. Please cancel your membership first.
cannot_update: There was a problem updating your billing info.
updated: Your billing information has been updated
removed: Your card has been successfully removed.
tag_adjustments_controller:
failure: 'Failure: %{errors}'
destroyed: Tag adjustment destroyed
tags_controller:
tag_successfully_updated: "Tag successfully updated! 👍 "
users_controller:
removed_admin: "%{name} is no longer an admin."
removed_member: "%{name} is no longer part of your organization."
added_admin: "%{name} is now an admin."
provide_email: Please, provide an email to delete your account.
provide_email_delete: Please, provide an email to delete your account
send_export: " The export will be emailed to you shortly."
invalid_secret: The given organization secret was invalid.
username_blank: Username cannot be blank
deletion_in_progress: You have already requested account deletion. Please, check your email for further instructions.
joined_org: You have joined the %{organization_name} organization.
left_org: You have left your organization.
deletion_requested: You have requested account deletion. Please, check your email for further instructions.
log_in_to_delete: You must be logged in to proceed with account deletion.
deletion_scheduled: Your account deletion is scheduled. You'll be notified when it's deleted.
removed_identity: Your %{provider} account was successfully removed.
updated_config: Your config has been updated. Refresh to see all changes.
updated_profile: Your profile was successfully updated.
token_expired: Your token has expired, please request a new one. Tokens only last for 12 hours after account deletion is initiated.
video_states_controller:
related_article_not_found: Related article not found
video_state_updated: Video state updated

View file

@ -0,0 +1,121 @@
---
fr:
api_secrets_controller:
generated: 'Your API Key has been generated: %{secret}'
revoked: Your API Key has been revoked.
application_controller:
bad_request: 'Error: Bad Request'
not_authorized: 'Error: not authorized'
please_sign_in: Please sign in
articles_controller:
deleted: Article was successfully deleted.
comments_controller:
create:
success: created
failure: comment already exists
delete:
error: Something went wrong; Comment NOT deleted.
notice: Comment was successfully deleted.
markdown: 'There was an error in your markdown: %{error}'
markdown_html: "<p>😔 There was an error in your markdown</p><hr><p>%{error}</p>"
moderated: Not allowed due to moderation action
confirmations_controller:
email_sent: Email sent! Please contact support at %{email} if you are having trouble receiving your confirmation instructions.
credits_controller:
done:
one: "%{count} new credits purchased!"
other: "%{count} new credits purchased!"
devices_controller:
not_found: Not Found
discussion_locks_controller:
locked: Discussion was successfully locked!
unlocked: Discussion was successfully unlocked!
email_subscriptions_controller:
badge_notifications: badge notifications
comment_notifications: comment notifications
digest_emails: "%{community} digest emails"
follower_notifications: follower notifications
mention_notifications: mention notifications
this_list: this list
unread_notifications: unread notifications
feedback_messages_controller:
error_fill: "Make sure the forms are filled. 🤖 Other possible errors: %{errors}"
n_a: N/A
submitted: Your report is submitted
follows_controller:
already_followed: already followed
daily_limit: Daily account follow limit reached!
followed: followed
unfollowed: unfollowed
github_repos_controller:
repo_not_found: GitHub repository not found
github_unauthorized: 'GitHub Unauthorized: %{e_message}'
image_uploads_controller:
server_error: A server error has occurred!
listings_controller:
deleted: Listing was successfully deleted.
no_credit: Not enough available credits
omniauth_callbacks_controller:
log_in_error: 'Log in error: %{e}'
username_taken: username has already been taken
organizations_controller:
secret_updated: Your org secret was updated
deletion_scheduled: 'Your organization: "%{organization_name}" deletion is scheduled. You''ll be notified when it''s deleted.'
not_deleted: Your organization was not deleted; you must be an admin, the only member in the organization, and have no articles connected to the organization.
created: Your organization was successfully created and you are an admin.
updated: Your organization was successfully updated.
podcasts_controller:
podcast_suggested: Podcast suggested
profiles_controller:
updated: Your profile has been updated
rating_votes_controller:
not_upserted_successfully: Not Upserted Successfully
registrations_controller:
error:
recaptcha: You must complete the recaptcha ✅
domain: is not included in allowed domains.
response_templates_controller:
response_template_error: 'Response template error: %{errors}'
created: Your response template "%{title}" was created.
deleted: Your response template "%{title}" was deleted.
updated: Your response template "%{title}" was updated.
social_previews_controller:
fonts: Roboto|Roboto+Condensed
stories:
pinned_articles_controller:
not_found: not found
stories_controller:
404_bio_not_found: 404 bio not found
searching: "...searching"
stripe_active_cards_controller:
cannot_remove: Can't remove card if you have an active membership. Please cancel your membership first.
cannot_update: There was a problem updating your billing info.
updated: Your billing information has been updated
removed: Your card has been successfully removed.
tag_adjustments_controller:
failure: 'Failure: %{errors}'
destroyed: Tag adjustment destroyed
tags_controller:
tag_successfully_updated: "Tag successfully updated! 👍 "
users_controller:
removed_admin: "%{name} is no longer an admin."
removed_member: "%{name} is no longer part of your organization."
added_admin: "%{name} is now an admin."
provide_email: Please, provide an email to delete your account.
provide_email_delete: Please, provide an email to delete your account
send_export: " The export will be emailed to you shortly."
invalid_secret: The given organization secret was invalid.
username_blank: Username cannot be blank
deletion_in_progress: You have already requested account deletion. Please, check your email for further instructions.
joined_org: You have joined the %{organization_name} organization.
left_org: You have left your organization.
deletion_requested: You have requested account deletion. Please, check your email for further instructions.
log_in_to_delete: You must be logged in to proceed with account deletion.
deletion_scheduled: Your account deletion is scheduled. You'll be notified when it's deleted.
removed_identity: Your %{provider} account was successfully removed.
updated_config: Your config has been updated. Refresh to see all changes.
updated_profile: Your profile was successfully updated.
token_expired: Your token has expired, please request a new one. Tokens only last for 12 hours after account deletion is initiated.
video_states_controller:
related_article_not_found: Related article not found
video_state_updated: Video state updated

View file

@ -0,0 +1,5 @@
---
en:
decorators:
article_decorator:
tagged_with: " Tagged with %{cached_tag_list}."

View file

@ -0,0 +1,5 @@
---
fr:
decorators:
article_decorator:
tagged_with: " Tagged with %{cached_tag_list}."

View file

@ -145,6 +145,7 @@ en:
equal_to: must be equal to %{count}
even: must be even
exclusion: is reserved
general: 'Error: %{errors}'
greater_than: must be greater than %{count}
greater_than_or_equal_to: must be greater than or equal to %{count}
inclusion: is not included in the list
@ -165,6 +166,7 @@ en:
too_short:
one: is too short (minimum is 1 character)
other: is too short (minimum is %{count} characters)
try_again_email: 'An error occurred. Please try again or send an email to: %{email}'
wrong_length:
one: is the wrong length (should be 1 character)
other: is the wrong length (should be %{count} characters)
@ -176,6 +178,7 @@ en:
medium: "%b %-d, %Y"
reddit: "%b %e '%y"
short: "%b %-e"
short_with_yy: "%b %-d '%y"
short_with_year: "%b %-e, %Y"
stackexchange: "%b %e '%y"
tweet: "%H:%M %p - %d %b %Y"

View file

@ -163,6 +163,7 @@ fr:
even: doit être pair
exclusion: est réservé
expired: a expiré, veuillez en demander un nouveau
general: 'Error: %{errors}'
greater_than: doit être supérieur à %{count}
greater_than_or_equal_to: doit être supérieur ou égal à %{count}
inclusion: n'est pas inclus dans la liste
@ -188,6 +189,7 @@ fr:
too_short:
one: est trop court (au moins 1 caractère)
other: est trop court (le minimum est de %{count} caractères)
try_again_email: 'An error occurred. Please try again or send an email to: %{email}'
wrong_length:
one: est la mauvaise longueur (devrait être 1 caractère)
other: est la mauvaise longueur (devrait être %{count} caractères)
@ -199,6 +201,7 @@ fr:
medium: "%b %-d, %Y"
reddit: "%b %e '%y"
short: "%-e %b"
short_with_yy: "%-e %b '%y"
short_with_year: "%-e %b, %Y"
stackexchange: "%b %e '%y"
tweet: "%H:%M %p - %d %b %Y"

View file

@ -10,12 +10,6 @@ en:
title_rel: "%{root} — %{site}"
title_root: "[Discussion] %{title} — %{site}"
description: "%{site} Comment"
messages:
create:
success: created
failure: comment already exists
markdown: 'There was an error in your markdown: %{error}'
markdown_html: "<p>😔 There was an error in your markdown</p><hr><p>%{error}</p>"
parent:
subtitle_html: "%{start}Discussion on: %{end}%{title}"
metadata_html: "%{name}%{on}"
@ -31,8 +25,6 @@ en:
heading: Are you sure you want to delete this comment?
desc_html: You cannot undo this action, perhaps you just want to %{action} instead?
action: Edit
error: Something went wrong; Comment NOT deleted.
notice: Comment was successfully deleted.
submit: Delete
edit: Edit
cancel: Dismiss

View file

@ -10,12 +10,6 @@ fr:
title_rel: "%{root} — %{site}"
title_root: "[Discussion] %{title} — %{site}"
description: "%{site} Comment"
messages:
create:
success: created
failure: comment already exists
markdown: 'There was an error in your markdown: %{error}'
markdown_html: "<p>😔 There was an error in your markdown</p><hr><p>%{error}</p>"
parent:
subtitle_html: "%{start}Discussion on: %{end}%{title}"
metadata_html: "%{name}%{on}"
@ -31,8 +25,6 @@ fr:
heading: Are you sure you want to delete this comment?
desc_html: You cannot undo this action, perhaps you just want to %{action} instead?
action: Edit
error: Something went wrong; Comment NOT deleted.
notice: Comment was successfully deleted.
submit: Delete
edit: Edit
cancel: Dismiss

View file

@ -7,8 +7,7 @@ RSpec.describe "/confirm-email", type: :system do
click_button "Resend"
expect(page).to have_current_path(user_confirmation_path)
expected_message = format(ConfirmationsController::FLASH_MESSAGE,
email: ForemInstance.email)
expected_message = I18n.t("confirmations_controller.email_sent", email: ForemInstance.email)
expect(page).to have_content(expected_message)
end
end