diff --git a/app/controllers/admin/tags_controller.rb b/app/controllers/admin/tags_controller.rb
index 0e9dda30221070dc5d5ac998519a74c51cf785b7..ed271aedcb0d304c7cf9b79c4e224e691c1dc5e6 100644
--- a/app/controllers/admin/tags_controller.rb
+++ b/app/controllers/admin/tags_controller.rb
@@ -17,7 +17,7 @@ module Admin
       authorize @tag, :update?
 
       if @tag.update(tag_params.merge(reviewed_at: Time.now.utc))
-        redirect_to admin_tag_path(@tag.id)
+        redirect_to admin_tag_path(@tag.id), notice: I18n.t('admin.tags.updated_msg')
       else
         render :show
       end
diff --git a/app/controllers/directories_controller.rb b/app/controllers/directories_controller.rb
index d2ef76f0691936794cb959902e34cbde35d20e88..a5c47b515c63e24b2f05235aa3c43c6f8c9c9094 100644
--- a/app/controllers/directories_controller.rb
+++ b/app/controllers/directories_controller.rb
@@ -25,7 +25,7 @@ class DirectoriesController < ApplicationController
   end
 
   def set_tag
-    @tag = Tag.discoverable.find_by!(name: params[:id].downcase)
+    @tag = Tag.discoverable.find_normalized!(params[:id])
   end
 
   def set_tags
diff --git a/app/controllers/tags_controller.rb b/app/controllers/tags_controller.rb
index 3cd2d9e204730f5458b2423947d547432b41e07b..5a6fcc8fdd834f6da956ad08691f8c5afb9a4507 100644
--- a/app/controllers/tags_controller.rb
+++ b/app/controllers/tags_controller.rb
@@ -47,7 +47,7 @@ class TagsController < ApplicationController
   private
 
   def set_tag
-    @tag = Tag.find_normalized!(params[:id])
+    @tag = Tag.usable.find_normalized!(params[:id])
   end
 
   def set_body_classes
diff --git a/app/models/account.rb b/app/models/account.rb
index ccd116d6e2e3656007c574c1b644a749364272fc..b205c8c9e7ddeb92e48af91f7ef8d9afc784d928 100644
--- a/app/models/account.rb
+++ b/app/models/account.rb
@@ -227,17 +227,7 @@ class Account < ApplicationRecord
   end
 
   def tags_as_strings=(tag_names)
-    tag_names.map! { |name| name.mb_chars.downcase.to_s }
-    tag_names.uniq!
-
-    # Existing hashtags
-    hashtags_map = Tag.where(name: tag_names).each_with_object({}) { |tag, h| h[tag.name] = tag }
-
-    # Initialize not yet existing hashtags
-    tag_names.each do |name|
-      next if hashtags_map.key?(name)
-      hashtags_map[name] = Tag.new(name: name)
-    end
+    hashtags_map = Tag.find_or_create_by_names(tag_names).each_with_object({}) { |tag, h| h[tag.name] = tag }
 
     # Remove hashtags that are to be deleted
     tags.each do |tag|
diff --git a/app/models/tag.rb b/app/models/tag.rb
index 6a02581fad32e02795c4222701cbcbbac646f4f5..e2fe91da1b4a10cbef536e2ce19cb4b29c16ce82 100644
--- a/app/models/tag.rb
+++ b/app/models/tag.rb
@@ -31,7 +31,8 @@ class Tag < ApplicationRecord
 
   scope :reviewed, -> { where.not(reviewed_at: nil) }
   scope :pending_review, -> { where(reviewed_at: nil).where.not(requested_review_at: nil) }
-  scope :discoverable, -> { where.not(listable: false).joins(:account_tag_stat).where(AccountTagStat.arel_table[:accounts_count].gt(0)).order(Arel.sql('account_tag_stats.accounts_count desc')) }
+  scope :usable, -> { where(usable: [true, nil]) }
+  scope :discoverable, -> { where(listable: [true, nil]).joins(:account_tag_stat).where(AccountTagStat.arel_table[:accounts_count].gt(0)).order(Arel.sql('account_tag_stats.accounts_count desc')) }
   scope :most_used, ->(account) { joins(:statuses).where(statuses: { account: account }).group(:id).order(Arel.sql('count(*) desc')) }
 
   delegate :accounts_count,
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 333d4f17209f124e4573a21a6e22c1c7bef8f717..20baf634e66af80696b020661fb00d0608cabb0c 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -496,6 +496,7 @@ en:
       title: Hashtags
       trending_right_now: Trending right now
       unique_uses_today: "%{count} posting today"
+      updated_msg: Hashtag settings updated successfully
     title: Administration
     warning_presets:
       add_new: Add new