about summary refs log tree commit diff
path: root/app
diff options
context:
space:
mode:
authorClaire <claire.github-309c@sitedethib.com>2022-10-02 17:33:37 +0200
committerClaire <claire.github-309c@sitedethib.com>2022-10-02 18:46:22 +0200
commit221580a3afb62b8da047b4feddbb58261ca07fbc (patch)
treebb070ba3e04a4cea5a7f55257ebe3cf71b2df280 /app
parent9d7c323abdda66423751f3a25faf960674af8a49 (diff)
parentc55219efa811b3c6347774bec1b174d325e5f300 (diff)
Merge branch 'main' into glitch-soc/merge-upstream
Conflicts:
- `app/controllers/home_controller.rb`:
  Upstream made it so `/web` is available to non-logged-in users
  and `/` redirects to `/web` instead of `/about`.
  Kept our version since glitch-soc's WebUI doesn't have what's
  needed yet and I think /about is still a much better landing
  page anyway.
- `app/models/form/admin_settings.rb`:
  Upstream added new settings, and glitch-soc had an extra setting.
  Not really a conflict.
  Added upstream's new settings.
- `app/serializers/initial_state_serializer.rb`:
  Upstream added a new `server` initial state object.
  Not really a conflict.
  Merged upstream's changes.
- `app/views/admin/settings/edit.html.haml`:
  Upstream added new settings.
  Not really a conflict.
  Merged upstream's changes.
- `app/workers/scheduler/feed_cleanup_scheduler.rb`:
  Upstream refactored that part and removed the file.
  Ported our relevant changes into `app/lib/vacuum/feeds_vacuum.rb`
- `config/settings.yml`:
  Upstream added new settings.
  Not a real conflict.
  Added upstream's new settings.
Diffstat (limited to 'app')
-rw-r--r--app/controllers/about_controller.rb6
-rw-r--r--app/controllers/accounts_controller.rb2
-rw-r--r--app/controllers/activitypub/claims_controller.rb2
-rw-r--r--app/controllers/activitypub/collections_controller.rb2
-rw-r--r--app/controllers/activitypub/followers_synchronizations_controller.rb2
-rw-r--r--app/controllers/activitypub/inboxes_controller.rb10
-rw-r--r--app/controllers/activitypub/outboxes_controller.rb2
-rw-r--r--app/controllers/activitypub/replies_controller.rb2
-rw-r--r--app/controllers/api/base_controller.rb6
-rw-r--r--app/controllers/api/v1/accounts/follower_accounts_controller.rb2
-rw-r--r--app/controllers/api/v1/accounts/following_accounts_controller.rb2
-rw-r--r--app/controllers/api/v1/accounts_controller.rb6
-rw-r--r--app/controllers/api/v1/statuses/translations_controller.rb29
-rw-r--r--app/controllers/api/v2/search_controller.rb5
-rw-r--r--app/controllers/concerns/signature_verification.rb88
-rw-r--r--app/controllers/follower_accounts_controller.rb2
-rw-r--r--app/controllers/following_accounts_controller.rb2
-rw-r--r--app/controllers/privacy_controller.rb22
-rw-r--r--app/controllers/statuses_controller.rb2
-rw-r--r--app/controllers/tags_controller.rb2
-rw-r--r--app/javascript/mastodon/actions/accounts.js6
-rw-r--r--app/javascript/mastodon/actions/markers.js10
-rw-r--r--app/javascript/mastodon/actions/statuses.js39
-rw-r--r--app/javascript/mastodon/components/__tests__/__snapshots__/avatar-test.js.snap4
-rw-r--r--app/javascript/mastodon/components/__tests__/__snapshots__/avatar_overlay-test.js.snap4
-rw-r--r--app/javascript/mastodon/components/__tests__/__snapshots__/display_name-test.js.snap2
-rw-r--r--app/javascript/mastodon/components/column_header.js3
-rw-r--r--app/javascript/mastodon/components/hashtag.js15
-rw-r--r--app/javascript/mastodon/components/logo.js4
-rw-r--r--app/javascript/mastodon/components/poll.js6
-rw-r--r--app/javascript/mastodon/components/status.js16
-rw-r--r--app/javascript/mastodon/components/status_content.js35
-rw-r--r--app/javascript/mastodon/containers/mastodon.js2
-rw-r--r--app/javascript/mastodon/containers/status_container.js10
-rw-r--r--app/javascript/mastodon/features/account/components/header.js35
-rw-r--r--app/javascript/mastodon/features/account_timeline/components/header.js6
-rw-r--r--app/javascript/mastodon/features/account_timeline/containers/header_container.js8
-rw-r--r--app/javascript/mastodon/features/community_timeline/index.js6
-rw-r--r--app/javascript/mastodon/features/directory/index.js6
-rw-r--r--app/javascript/mastodon/features/explore/index.js6
-rw-r--r--app/javascript/mastodon/features/explore/links.js11
-rw-r--r--app/javascript/mastodon/features/explore/results.js18
-rw-r--r--app/javascript/mastodon/features/explore/suggestions.js11
-rw-r--r--app/javascript/mastodon/features/explore/tags.js11
-rw-r--r--app/javascript/mastodon/features/follow_recommendations/index.js6
-rw-r--r--app/javascript/mastodon/features/hashtag_timeline/index.js18
-rw-r--r--app/javascript/mastodon/features/public_timeline/index.js6
-rw-r--r--app/javascript/mastodon/features/report/components/status_check_box.js26
-rw-r--r--app/javascript/mastodon/features/status/components/detailed_status.js13
-rw-r--r--app/javascript/mastodon/features/status/index.js37
-rw-r--r--app/javascript/mastodon/features/subscribed_languages_modal/index.js121
-rw-r--r--app/javascript/mastodon/features/ui/components/columns_area.js4
-rw-r--r--app/javascript/mastodon/features/ui/components/compose_panel.js22
-rw-r--r--app/javascript/mastodon/features/ui/components/document_title.js41
-rw-r--r--app/javascript/mastodon/features/ui/components/link_footer.js46
-rw-r--r--app/javascript/mastodon/features/ui/components/modal_root.js2
-rw-r--r--app/javascript/mastodon/features/ui/components/navigation_panel.js83
-rw-r--r--app/javascript/mastodon/features/ui/components/sign_in_banner.js13
-rw-r--r--app/javascript/mastodon/features/ui/index.js43
-rw-r--r--app/javascript/mastodon/initial_state.js3
-rw-r--r--app/javascript/mastodon/locales/af.json13
-rw-r--r--app/javascript/mastodon/locales/ar.json27
-rw-r--r--app/javascript/mastodon/locales/ast.json21
-rw-r--r--app/javascript/mastodon/locales/bg.json163
-rw-r--r--app/javascript/mastodon/locales/bn.json13
-rw-r--r--app/javascript/mastodon/locales/br.json13
-rw-r--r--app/javascript/mastodon/locales/ca.json51
-rw-r--r--app/javascript/mastodon/locales/ckb.json13
-rw-r--r--app/javascript/mastodon/locales/co.json13
-rw-r--r--app/javascript/mastodon/locales/cs.json53
-rw-r--r--app/javascript/mastodon/locales/cy.json13
-rw-r--r--app/javascript/mastodon/locales/da.json47
-rw-r--r--app/javascript/mastodon/locales/de.json73
-rw-r--r--app/javascript/mastodon/locales/defaultMessages.json110
-rw-r--r--app/javascript/mastodon/locales/el.json13
-rw-r--r--app/javascript/mastodon/locales/en-GB.json13
-rw-r--r--app/javascript/mastodon/locales/en.json13
-rw-r--r--app/javascript/mastodon/locales/eo.json29
-rw-r--r--app/javascript/mastodon/locales/es-AR.json47
-rw-r--r--app/javascript/mastodon/locales/es-MX.json49
-rw-r--r--app/javascript/mastodon/locales/es.json47
-rw-r--r--app/javascript/mastodon/locales/et.json13
-rw-r--r--app/javascript/mastodon/locales/eu.json13
-rw-r--r--app/javascript/mastodon/locales/fa.json13
-rw-r--r--app/javascript/mastodon/locales/fi.json47
-rw-r--r--app/javascript/mastodon/locales/fr.json23
-rw-r--r--app/javascript/mastodon/locales/fy.json13
-rw-r--r--app/javascript/mastodon/locales/ga.json13
-rw-r--r--app/javascript/mastodon/locales/gd.json15
-rw-r--r--app/javascript/mastodon/locales/gl.json47
-rw-r--r--app/javascript/mastodon/locales/he.json63
-rw-r--r--app/javascript/mastodon/locales/hi.json13
-rw-r--r--app/javascript/mastodon/locales/hr.json13
-rw-r--r--app/javascript/mastodon/locales/hu.json47
-rw-r--r--app/javascript/mastodon/locales/hy.json13
-rw-r--r--app/javascript/mastodon/locales/id.json17
-rw-r--r--app/javascript/mastodon/locales/io.json47
-rw-r--r--app/javascript/mastodon/locales/is.json49
-rw-r--r--app/javascript/mastodon/locales/it.json47
-rw-r--r--app/javascript/mastodon/locales/ja.json35
-rw-r--r--app/javascript/mastodon/locales/ka.json13
-rw-r--r--app/javascript/mastodon/locales/kab.json13
-rw-r--r--app/javascript/mastodon/locales/kk.json13
-rw-r--r--app/javascript/mastodon/locales/kn.json13
-rw-r--r--app/javascript/mastodon/locales/ko.json47
-rw-r--r--app/javascript/mastodon/locales/ku.json49
-rw-r--r--app/javascript/mastodon/locales/kw.json13
-rw-r--r--app/javascript/mastodon/locales/lt.json13
-rw-r--r--app/javascript/mastodon/locales/lv.json47
-rw-r--r--app/javascript/mastodon/locales/mk.json13
-rw-r--r--app/javascript/mastodon/locales/ml.json13
-rw-r--r--app/javascript/mastodon/locales/mr.json13
-rw-r--r--app/javascript/mastodon/locales/ms.json13
-rw-r--r--app/javascript/mastodon/locales/nl.json43
-rw-r--r--app/javascript/mastodon/locales/nn.json13
-rw-r--r--app/javascript/mastodon/locales/no.json13
-rw-r--r--app/javascript/mastodon/locales/oc.json13
-rw-r--r--app/javascript/mastodon/locales/pa.json13
-rw-r--r--app/javascript/mastodon/locales/pl.json47
-rw-r--r--app/javascript/mastodon/locales/pt-BR.json13
-rw-r--r--app/javascript/mastodon/locales/pt-PT.json47
-rw-r--r--app/javascript/mastodon/locales/ro.json13
-rw-r--r--app/javascript/mastodon/locales/ru.json63
-rw-r--r--app/javascript/mastodon/locales/sa.json13
-rw-r--r--app/javascript/mastodon/locales/sc.json13
-rw-r--r--app/javascript/mastodon/locales/si.json321
-rw-r--r--app/javascript/mastodon/locales/sk.json23
-rw-r--r--app/javascript/mastodon/locales/sl.json47
-rw-r--r--app/javascript/mastodon/locales/sq.json47
-rw-r--r--app/javascript/mastodon/locales/sr-Latn.json13
-rw-r--r--app/javascript/mastodon/locales/sr.json13
-rw-r--r--app/javascript/mastodon/locales/sv.json13
-rw-r--r--app/javascript/mastodon/locales/szl.json13
-rw-r--r--app/javascript/mastodon/locales/ta.json61
-rw-r--r--app/javascript/mastodon/locales/tai.json13
-rw-r--r--app/javascript/mastodon/locales/te.json13
-rw-r--r--app/javascript/mastodon/locales/th.json45
-rw-r--r--app/javascript/mastodon/locales/tr.json47
-rw-r--r--app/javascript/mastodon/locales/tt.json13
-rw-r--r--app/javascript/mastodon/locales/ug.json13
-rw-r--r--app/javascript/mastodon/locales/uk.json47
-rw-r--r--app/javascript/mastodon/locales/ur.json13
-rw-r--r--app/javascript/mastodon/locales/vi.json49
-rw-r--r--app/javascript/mastodon/locales/zgh.json13
-rw-r--r--app/javascript/mastodon/locales/zh-CN.json47
-rw-r--r--app/javascript/mastodon/locales/zh-HK.json13
-rw-r--r--app/javascript/mastodon/locales/zh-TW.json47
-rw-r--r--app/javascript/mastodon/reducers/statuses.js6
-rw-r--r--app/javascript/mastodon/utils/icons.js2
-rw-r--r--app/javascript/styles/mastodon/_mixins.scss1
-rw-r--r--app/javascript/styles/mastodon/accounts.scss9
-rw-r--r--app/javascript/styles/mastodon/components.scss85
-rw-r--r--app/javascript/styles/mastodon/forms.scss3
-rw-r--r--app/lib/activitypub/activity.rb10
-rw-r--r--app/lib/activitypub/dereferencer.rb6
-rw-r--r--app/lib/activitypub/linked_data_signature.rb6
-rw-r--r--app/lib/activitypub/tag_manager.rb8
-rw-r--r--app/lib/feed_manager.rb2
-rw-r--r--app/lib/permalink_redirector.rb4
-rw-r--r--app/lib/redis_configuration.rb6
-rw-r--r--app/lib/request.rb24
-rw-r--r--app/lib/translation_service.rb23
-rw-r--r--app/lib/translation_service/deepl.rb53
-rw-r--r--app/lib/translation_service/libre_translate.rb44
-rw-r--r--app/lib/translation_service/translation.rb5
-rw-r--r--app/lib/vacuum.rb3
-rw-r--r--app/lib/vacuum/access_tokens_vacuum.rb (renamed from app/workers/scheduler/doorkeeper_cleanup_scheduler.rb)15
-rw-r--r--app/lib/vacuum/backups_vacuum.rb25
-rw-r--r--app/lib/vacuum/feeds_vacuum.rb41
-rw-r--r--app/lib/vacuum/media_attachments_vacuum.rb40
-rw-r--r--app/lib/vacuum/preview_cards_vacuum.rb39
-rw-r--r--app/lib/vacuum/statuses_vacuum.rb54
-rw-r--r--app/lib/vacuum/system_keys_vacuum.rb13
-rw-r--r--app/lib/webfinger.rb2
-rw-r--r--app/models/account.rb4
-rw-r--r--app/models/concerns/account_interactions.rb23
-rw-r--r--app/models/content_retention_policy.rb25
-rw-r--r--app/models/export.rb4
-rw-r--r--app/models/follow.rb4
-rw-r--r--app/models/follow_request.rb4
-rw-r--r--app/models/form/admin_settings.rb4
-rw-r--r--app/models/user.rb2
-rw-r--r--app/serializers/activitypub/public_key_serializer.rb2
-rw-r--r--app/serializers/initial_state_serializer.rb12
-rw-r--r--app/serializers/rest/admin/account_serializer.rb2
-rw-r--r--app/serializers/rest/relationship_serializer.rb7
-rw-r--r--app/serializers/rest/translation_serializer.rb9
-rw-r--r--app/services/activitypub/fetch_remote_account_service.rb66
-rw-r--r--app/services/activitypub/fetch_remote_actor_service.rb80
-rw-r--r--app/services/activitypub/fetch_remote_key_service.rb48
-rw-r--r--app/services/activitypub/process_account_service.rb2
-rw-r--r--app/services/activitypub/process_collection_service.rb11
-rw-r--r--app/services/fetch_resource_service.rb2
-rw-r--r--app/services/follow_service.rb13
-rw-r--r--app/services/import_service.rb2
-rw-r--r--app/services/keys/claim_service.rb2
-rw-r--r--app/services/process_mentions_service.rb2
-rw-r--r--app/services/resolve_account_service.rb12
-rw-r--r--app/services/resolve_url_service.rb4
-rw-r--r--app/services/translate_status_service.rb27
-rw-r--r--app/validators/language_validator.rb21
-rw-r--r--app/views/admin/settings/edit.html.haml9
-rw-r--r--app/views/home/index.html.haml12
-rw-r--r--app/views/layouts/public.html.haml5
-rw-r--r--app/views/privacy/show.html.haml (renamed from app/views/about/terms.html.haml)0
-rw-r--r--app/views/settings/deletes/show.html.haml2
-rw-r--r--app/views/user_mailer/confirmation_instructions.html.haml2
-rw-r--r--app/views/user_mailer/confirmation_instructions.text.erb4
-rw-r--r--app/workers/activitypub/delivery_worker.rb2
-rw-r--r--app/workers/activitypub/processing_worker.rb12
-rw-r--r--app/workers/refollow_worker.rb7
-rw-r--r--app/workers/scheduler/backup_cleanup_scheduler.rb17
-rw-r--r--app/workers/scheduler/feed_cleanup_scheduler.rb40
-rw-r--r--app/workers/scheduler/media_cleanup_scheduler.rb17
-rw-r--r--app/workers/scheduler/vacuum_scheduler.rb56
-rw-r--r--app/workers/unfollow_follow_worker.rb9
216 files changed, 3576 insertions, 1371 deletions
diff --git a/app/controllers/about_controller.rb b/app/controllers/about_controller.rb
index 620c0ff78..654f2d92c 100644
--- a/app/controllers/about_controller.rb
+++ b/app/controllers/about_controller.rb
@@ -10,10 +10,10 @@ class AboutController < ApplicationController
   before_action :require_open_federation!, only: [:show, :more]
   before_action :set_body_classes, only: :show
   before_action :set_instance_presenter
-  before_action :set_expires_in, only: [:more, :terms]
+  before_action :set_expires_in, only: [:more]
   before_action :set_registration_form_time, only: :show
 
-  skip_before_action :require_functional!, only: [:more, :terms]
+  skip_before_action :require_functional!, only: [:more]
 
   def show; end
 
@@ -28,8 +28,6 @@ class AboutController < ApplicationController
     @blocks            = DomainBlock.with_user_facing_limitations.by_severity if display_blocks?
   end
 
-  def terms; end
-
   helper_method :display_blocks?
   helper_method :display_blocks_rationale?
   helper_method :public_fetch_mode?
diff --git a/app/controllers/accounts_controller.rb b/app/controllers/accounts_controller.rb
index 9949206cb..02f3c3dd7 100644
--- a/app/controllers/accounts_controller.rb
+++ b/app/controllers/accounts_controller.rb
@@ -7,7 +7,7 @@ class AccountsController < ApplicationController
   include AccountControllerConcern
   include SignatureAuthentication
 
-  before_action :require_signature!, if: -> { request.format == :json && authorized_fetch_mode? }
+  before_action :require_account_signature!, if: -> { request.format == :json && authorized_fetch_mode? }
   before_action :set_cache_headers
   before_action :set_body_classes
 
diff --git a/app/controllers/activitypub/claims_controller.rb b/app/controllers/activitypub/claims_controller.rb
index 08ad952df..339333e46 100644
--- a/app/controllers/activitypub/claims_controller.rb
+++ b/app/controllers/activitypub/claims_controller.rb
@@ -6,7 +6,7 @@ class ActivityPub::ClaimsController < ActivityPub::BaseController
 
   skip_before_action :authenticate_user!
 
-  before_action :require_signature!
+  before_action :require_account_signature!
   before_action :set_claim_result
 
   def create
diff --git a/app/controllers/activitypub/collections_controller.rb b/app/controllers/activitypub/collections_controller.rb
index ac7ab8a0b..23d874071 100644
--- a/app/controllers/activitypub/collections_controller.rb
+++ b/app/controllers/activitypub/collections_controller.rb
@@ -4,7 +4,7 @@ class ActivityPub::CollectionsController < ActivityPub::BaseController
   include SignatureVerification
   include AccountOwnedConcern
 
-  before_action :require_signature!, if: :authorized_fetch_mode?
+  before_action :require_account_signature!, if: :authorized_fetch_mode?
   before_action :set_items
   before_action :set_size
   before_action :set_type
diff --git a/app/controllers/activitypub/followers_synchronizations_controller.rb b/app/controllers/activitypub/followers_synchronizations_controller.rb
index 940b77cf0..4e445bcb1 100644
--- a/app/controllers/activitypub/followers_synchronizations_controller.rb
+++ b/app/controllers/activitypub/followers_synchronizations_controller.rb
@@ -4,7 +4,7 @@ class ActivityPub::FollowersSynchronizationsController < ActivityPub::BaseContro
   include SignatureVerification
   include AccountOwnedConcern
 
-  before_action :require_signature!
+  before_action :require_account_signature!
   before_action :set_items
   before_action :set_cache_headers
 
diff --git a/app/controllers/activitypub/inboxes_controller.rb b/app/controllers/activitypub/inboxes_controller.rb
index 92dcb5ac7..5ee85474e 100644
--- a/app/controllers/activitypub/inboxes_controller.rb
+++ b/app/controllers/activitypub/inboxes_controller.rb
@@ -6,7 +6,7 @@ class ActivityPub::InboxesController < ActivityPub::BaseController
   include AccountOwnedConcern
 
   before_action :skip_unknown_actor_activity
-  before_action :require_signature!
+  before_action :require_actor_signature!
   skip_before_action :authenticate_user!
 
   def create
@@ -49,17 +49,17 @@ class ActivityPub::InboxesController < ActivityPub::BaseController
   end
 
   def upgrade_account
-    if signed_request_account.ostatus?
+    if signed_request_account&.ostatus?
       signed_request_account.update(last_webfingered_at: nil)
       ResolveAccountWorker.perform_async(signed_request_account.acct)
     end
 
-    DeliveryFailureTracker.reset!(signed_request_account.inbox_url)
+    DeliveryFailureTracker.reset!(signed_request_actor.inbox_url)
   end
 
   def process_collection_synchronization
     raw_params = request.headers['Collection-Synchronization']
-    return if raw_params.blank? || ENV['DISABLE_FOLLOWERS_SYNCHRONIZATION'] == 'true'
+    return if raw_params.blank? || ENV['DISABLE_FOLLOWERS_SYNCHRONIZATION'] == 'true' || signed_request_account.nil?
 
     # Re-using the syntax for signature parameters
     tree   = SignatureParamsParser.new.parse(raw_params)
@@ -71,6 +71,6 @@ class ActivityPub::InboxesController < ActivityPub::BaseController
   end
 
   def process_payload
-    ActivityPub::ProcessingWorker.perform_async(signed_request_account.id, body, @account&.id)
+    ActivityPub::ProcessingWorker.perform_async(signed_request_actor.id, body, @account&.id, signed_request_actor.class.name)
   end
 end
diff --git a/app/controllers/activitypub/outboxes_controller.rb b/app/controllers/activitypub/outboxes_controller.rb
index cd3992502..60d201f76 100644
--- a/app/controllers/activitypub/outboxes_controller.rb
+++ b/app/controllers/activitypub/outboxes_controller.rb
@@ -6,7 +6,7 @@ class ActivityPub::OutboxesController < ActivityPub::BaseController
   include SignatureVerification
   include AccountOwnedConcern
 
-  before_action :require_signature!, if: :authorized_fetch_mode?
+  before_action :require_account_signature!, if: :authorized_fetch_mode?
   before_action :set_statuses
   before_action :set_cache_headers
 
diff --git a/app/controllers/activitypub/replies_controller.rb b/app/controllers/activitypub/replies_controller.rb
index 4ff7cfa08..8e0f9de2e 100644
--- a/app/controllers/activitypub/replies_controller.rb
+++ b/app/controllers/activitypub/replies_controller.rb
@@ -7,7 +7,7 @@ class ActivityPub::RepliesController < ActivityPub::BaseController
 
   DESCENDANTS_LIMIT = 60
 
-  before_action :require_signature!, if: :authorized_fetch_mode?
+  before_action :require_account_signature!, if: :authorized_fetch_mode?
   before_action :set_status
   before_action :set_cache_headers
   before_action :set_replies
diff --git a/app/controllers/api/base_controller.rb b/app/controllers/api/base_controller.rb
index 2e393fbb6..7ce6599c5 100644
--- a/app/controllers/api/base_controller.rb
+++ b/app/controllers/api/base_controller.rb
@@ -131,4 +131,10 @@ class Api::BaseController < ApplicationController
   def disallow_unauthenticated_api_access?
     authorized_fetch_mode?
   end
+
+  private
+
+  def respond_with_error(code)
+    render json: { error: Rack::Utils::HTTP_STATUS_CODES[code] }, status: code
+  end
 end
diff --git a/app/controllers/api/v1/accounts/follower_accounts_controller.rb b/app/controllers/api/v1/accounts/follower_accounts_controller.rb
index a665863eb..b61de13b9 100644
--- a/app/controllers/api/v1/accounts/follower_accounts_controller.rb
+++ b/app/controllers/api/v1/accounts/follower_accounts_controller.rb
@@ -1,7 +1,7 @@
 # frozen_string_literal: true
 
 class Api::V1::Accounts::FollowerAccountsController < Api::BaseController
-  before_action -> { doorkeeper_authorize! :read, :'read:accounts' }
+  before_action -> { authorize_if_got_token! :read, :'read:accounts' }
   before_action :set_account
   after_action :insert_pagination_headers
 
diff --git a/app/controllers/api/v1/accounts/following_accounts_controller.rb b/app/controllers/api/v1/accounts/following_accounts_controller.rb
index 7d885a212..37d3c2d78 100644
--- a/app/controllers/api/v1/accounts/following_accounts_controller.rb
+++ b/app/controllers/api/v1/accounts/following_accounts_controller.rb
@@ -1,7 +1,7 @@
 # frozen_string_literal: true
 
 class Api::V1::Accounts::FollowingAccountsController < Api::BaseController
-  before_action -> { doorkeeper_authorize! :read, :'read:accounts' }
+  before_action -> { authorize_if_got_token! :read, :'read:accounts' }
   before_action :set_account
   after_action :insert_pagination_headers
 
diff --git a/app/controllers/api/v1/accounts_controller.rb b/app/controllers/api/v1/accounts_controller.rb
index 5537cc9b0..be84720aa 100644
--- a/app/controllers/api/v1/accounts_controller.rb
+++ b/app/controllers/api/v1/accounts_controller.rb
@@ -30,12 +30,12 @@ class Api::V1::AccountsController < Api::BaseController
     self.response_body = Oj.dump(response.body)
     self.status        = response.status
   rescue ActiveRecord::RecordInvalid => e
-    render json: ValidationErrorFormatter.new(e, :'account.username' => :username, :'invite_request.text' => :reason).as_json, status: :unprocessable_entity
+    render json: ValidationErrorFormatter.new(e, 'account.username': :username, 'invite_request.text': :reason).as_json, status: :unprocessable_entity
   end
 
   def follow
-    follow  = FollowService.new.call(current_user.account, @account, reblogs: params.key?(:reblogs) ? truthy_param?(:reblogs) : nil, notify: params.key?(:notify) ? truthy_param?(:notify) : nil, with_rate_limit: true)
-    options = @account.locked? || current_user.account.silenced? ? {} : { following_map: { @account.id => { reblogs: follow.show_reblogs?, notify: follow.notify? } }, requested_map: { @account.id => false } }
+    follow  = FollowService.new.call(current_user.account, @account, reblogs: params.key?(:reblogs) ? truthy_param?(:reblogs) : nil, notify: params.key?(:notify) ? truthy_param?(:notify) : nil, languages: params.key?(:languages) ? params[:languages] : nil, with_rate_limit: true)
+    options = @account.locked? || current_user.account.silenced? ? {} : { following_map: { @account.id => { reblogs: follow.show_reblogs?, notify: follow.notify?, languages: follow.languages } }, requested_map: { @account.id => false } }
 
     render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships(**options)
   end
diff --git a/app/controllers/api/v1/statuses/translations_controller.rb b/app/controllers/api/v1/statuses/translations_controller.rb
new file mode 100644
index 000000000..540b17d00
--- /dev/null
+++ b/app/controllers/api/v1/statuses/translations_controller.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+class Api::V1::Statuses::TranslationsController < Api::BaseController
+  include Authorization
+
+  before_action -> { doorkeeper_authorize! :read, :'read:statuses' }
+  before_action :set_status
+  before_action :set_translation
+
+  rescue_from TranslationService::NotConfiguredError, with: :not_found
+  rescue_from TranslationService::UnexpectedResponseError, TranslationService::QuotaExceededError, TranslationService::TooManyRequestsError, with: :service_unavailable
+
+  def create
+    render json: @translation, serializer: REST::TranslationSerializer
+  end
+
+  private
+
+  def set_status
+    @status = Status.find(params[:status_id])
+    authorize @status, :show?
+  rescue Mastodon::NotPermittedError
+    not_found
+  end
+
+  def set_translation
+    @translation = TranslateStatusService.new.call(@status, content_locale)
+  end
+end
diff --git a/app/controllers/api/v2/search_controller.rb b/app/controllers/api/v2/search_controller.rb
index 77eeab5b0..d14cd5627 100644
--- a/app/controllers/api/v2/search_controller.rb
+++ b/app/controllers/api/v2/search_controller.rb
@@ -5,8 +5,7 @@ class Api::V2::SearchController < Api::BaseController
 
   RESULTS_LIMIT = (ENV['MAX_SEARCH_RESULTS'] || 20).to_i
 
-  before_action -> { doorkeeper_authorize! :read, :'read:search' }
-  before_action :require_user!
+  before_action -> { authorize_if_got_token! :read, :'read:search' }
 
   def index
     @search = Search.new(search_results)
@@ -24,7 +23,7 @@ class Api::V2::SearchController < Api::BaseController
       params[:q],
       current_account,
       limit_param(RESULTS_LIMIT),
-      search_params.merge(resolve: truthy_param?(:resolve), exclude_unreviewed: truthy_param?(:exclude_unreviewed))
+      search_params.merge(resolve: user_signed_in? ? truthy_param?(:resolve) : false, exclude_unreviewed: truthy_param?(:exclude_unreviewed))
     )
   end
 
diff --git a/app/controllers/concerns/signature_verification.rb b/app/controllers/concerns/signature_verification.rb
index 4dd0cac55..2394574b3 100644
--- a/app/controllers/concerns/signature_verification.rb
+++ b/app/controllers/concerns/signature_verification.rb
@@ -45,10 +45,14 @@ module SignatureVerification
     end
   end
 
-  def require_signature!
+  def require_account_signature!
     render plain: signature_verification_failure_reason, status: signature_verification_failure_code unless signed_request_account
   end
 
+  def require_actor_signature!
+    render plain: signature_verification_failure_reason, status: signature_verification_failure_code unless signed_request_actor
+  end
+
   def signed_request?
     request.headers['Signature'].present?
   end
@@ -68,7 +72,11 @@ module SignatureVerification
   end
 
   def signed_request_account
-    return @signed_request_account if defined?(@signed_request_account)
+    signed_request_actor.is_a?(Account) ? signed_request_actor : nil
+  end
+
+  def signed_request_actor
+    return @signed_request_actor if defined?(@signed_request_actor)
 
     raise SignatureVerificationError, 'Request not signed' unless signed_request?
     raise SignatureVerificationError, 'Incompatible request signature. keyId and signature are required' if missing_required_signature_parameters?
@@ -78,26 +86,30 @@ module SignatureVerification
     verify_signature_strength!
     verify_body_digest!
 
-    account = account_from_key_id(signature_params['keyId'])
+    actor = actor_from_key_id(signature_params['keyId'])
 
-    raise SignatureVerificationError, "Public key not found for key #{signature_params['keyId']}" if account.nil?
+    raise SignatureVerificationError, "Public key not found for key #{signature_params['keyId']}" if actor.nil?
 
     signature             = Base64.decode64(signature_params['signature'])
     compare_signed_string = build_signed_string
 
-    return account unless verify_signature(account, signature, compare_signed_string).nil?
+    return actor unless verify_signature(actor, signature, compare_signed_string).nil?
 
-    account = stoplight_wrap_request { account.possibly_stale? ? account.refresh! : account_refresh_key(account) }
+    actor = stoplight_wrap_request { actor_refresh_key!(actor) }
 
-    raise SignatureVerificationError, "Public key not found for key #{signature_params['keyId']}" if account.nil?
+    raise SignatureVerificationError, "Public key not found for key #{signature_params['keyId']}" if actor.nil?
 
-    return account unless verify_signature(account, signature, compare_signed_string).nil?
+    return actor unless verify_signature(actor, signature, compare_signed_string).nil?
 
-    @signature_verification_failure_reason = "Verification failed for #{account.username}@#{account.domain} #{account.uri} using rsa-sha256 (RSASSA-PKCS1-v1_5 with SHA-256)"
-    @signed_request_account = nil
+    fail_with! "Verification failed for #{actor.to_log_human_identifier} #{actor.uri} using rsa-sha256 (RSASSA-PKCS1-v1_5 with SHA-256)"
   rescue SignatureVerificationError => e
-    @signature_verification_failure_reason = e.message
-    @signed_request_account = nil
+    fail_with! e.message
+  rescue HTTP::Error, OpenSSL::SSL::SSLError => e
+    fail_with! "Failed to fetch remote data: #{e.message}"
+  rescue Mastodon::UnexpectedResponseError
+    fail_with! 'Failed to fetch remote data (got unexpected reply from server)'
+  rescue Stoplight::Error::RedLight
+    fail_with! 'Fetching attempt skipped because of recent connection failure'
   end
 
   def request_body
@@ -106,6 +118,11 @@ module SignatureVerification
 
   private
 
+  def fail_with!(message)
+    @signature_verification_failure_reason = message
+    @signed_request_actor = nil
+  end
+
   def signature_params
     @signature_params ||= begin
       raw_signature = request.headers['Signature']
@@ -138,13 +155,23 @@ module SignatureVerification
     digests = request.headers['Digest'].split(',').map { |digest| digest.split('=', 2) }.map { |key, value| [key.downcase, value] }
     sha256  = digests.assoc('sha-256')
     raise SignatureVerificationError, "Mastodon only supports SHA-256 in Digest header. Offered algorithms: #{digests.map(&:first).join(', ')}" if sha256.nil?
-    raise SignatureVerificationError, "Invalid Digest value. Computed SHA-256 digest: #{body_digest}; given: #{sha256[1]}" if body_digest != sha256[1]
+
+    return if body_digest == sha256[1]
+
+    digest_size = begin
+      Base64.strict_decode64(sha256[1].strip).length
+    rescue ArgumentError
+      raise SignatureVerificationError, "Invalid Digest value. The provided Digest value is not a valid base64 string. Given digest: #{sha256[1]}"
+    end
+
+    raise SignatureVerificationError, "Invalid Digest value. The provided Digest value is not a SHA-256 digest. Given digest: #{sha256[1]}" if digest_size != 32
+    raise SignatureVerificationError, "Invalid Digest value. Computed SHA-256 digest: #{body_digest}; given: #{sha256[1]}"
   end
 
-  def verify_signature(account, signature, compare_signed_string)
-    if account.keypair.public_key.verify(OpenSSL::Digest.new('SHA256'), signature, compare_signed_string)
-      @signed_request_account = account
-      @signed_request_account
+  def verify_signature(actor, signature, compare_signed_string)
+    if actor.keypair.public_key.verify(OpenSSL::Digest.new('SHA256'), signature, compare_signed_string)
+      @signed_request_actor = actor
+      @signed_request_actor
     end
   rescue OpenSSL::PKey::RSAError
     nil
@@ -207,7 +234,7 @@ module SignatureVerification
     signature_params['keyId'].blank? || signature_params['signature'].blank?
   end
 
-  def account_from_key_id(key_id)
+  def actor_from_key_id(key_id)
     domain = key_id.start_with?('acct:') ? key_id.split('@').last : key_id
 
     if domain_not_allowed?(domain)
@@ -216,27 +243,34 @@ module SignatureVerification
     end
 
     if key_id.start_with?('acct:')
-      stoplight_wrap_request { ResolveAccountService.new.call(key_id.gsub(/\Aacct:/, '')) }
+      stoplight_wrap_request { ResolveAccountService.new.call(key_id.gsub(/\Aacct:/, ''), suppress_errors: false) }
     elsif !ActivityPub::TagManager.instance.local_uri?(key_id)
-      account   = ActivityPub::TagManager.instance.uri_to_resource(key_id, Account)
-      account ||= stoplight_wrap_request { ActivityPub::FetchRemoteKeyService.new.call(key_id, id: false) }
+      account   = ActivityPub::TagManager.instance.uri_to_actor(key_id)
+      account ||= stoplight_wrap_request { ActivityPub::FetchRemoteKeyService.new.call(key_id, id: false, suppress_errors: false) }
       account
     end
-  rescue Mastodon::HostValidationError
-    nil
+  rescue Mastodon::PrivateNetworkAddressError => e
+    raise SignatureVerificationError, "Requests to private network addresses are disallowed (tried to query #{e.host})"
+  rescue Mastodon::HostValidationError, ActivityPub::FetchRemoteActorService::Error, ActivityPub::FetchRemoteKeyService::Error, Webfinger::Error => e
+    raise SignatureVerificationError, e.message
   end
 
   def stoplight_wrap_request(&block)
     Stoplight("source:#{request.remote_ip}", &block)
-      .with_fallback { nil }
       .with_threshold(1)
       .with_cool_off_time(5.minutes.seconds)
       .with_error_handler { |error, handle| error.is_a?(HTTP::Error) || error.is_a?(OpenSSL::SSL::SSLError) ? handle.call(error) : raise(error) }
       .run
   end
 
-  def account_refresh_key(account)
-    return if account.local? || !account.activitypub?
-    ActivityPub::FetchRemoteAccountService.new.call(account.uri, only_key: true)
+  def actor_refresh_key!(actor)
+    return if actor.local? || !actor.activitypub?
+    return actor.refresh! if actor.respond_to?(:refresh!) && actor.possibly_stale?
+
+    ActivityPub::FetchRemoteActorService.new.call(actor.uri, only_key: true, suppress_errors: false)
+  rescue Mastodon::PrivateNetworkAddressError => e
+    raise SignatureVerificationError, "Requests to private network addresses are disallowed (tried to query #{e.host})"
+  rescue Mastodon::HostValidationError, ActivityPub::FetchRemoteActorService::Error, Webfinger::Error => e
+    raise SignatureVerificationError, e.message
   end
 end
diff --git a/app/controllers/follower_accounts_controller.rb b/app/controllers/follower_accounts_controller.rb
index f898994ac..0d9e624ef 100644
--- a/app/controllers/follower_accounts_controller.rb
+++ b/app/controllers/follower_accounts_controller.rb
@@ -4,7 +4,7 @@ class FollowerAccountsController < ApplicationController
   include AccountControllerConcern
   include SignatureVerification
 
-  before_action :require_signature!, if: -> { request.format == :json && authorized_fetch_mode? }
+  before_action :require_account_signature!, if: -> { request.format == :json && authorized_fetch_mode? }
   before_action :set_cache_headers
 
   skip_around_action :set_locale, if: -> { request.format == :json }
diff --git a/app/controllers/following_accounts_controller.rb b/app/controllers/following_accounts_controller.rb
index 11c6b6d50..68e1a79be 100644
--- a/app/controllers/following_accounts_controller.rb
+++ b/app/controllers/following_accounts_controller.rb
@@ -4,7 +4,7 @@ class FollowingAccountsController < ApplicationController
   include AccountControllerConcern
   include SignatureVerification
 
-  before_action :require_signature!, if: -> { request.format == :json && authorized_fetch_mode? }
+  before_action :require_account_signature!, if: -> { request.format == :json && authorized_fetch_mode? }
   before_action :set_cache_headers
 
   skip_around_action :set_locale, if: -> { request.format == :json }
diff --git a/app/controllers/privacy_controller.rb b/app/controllers/privacy_controller.rb
new file mode 100644
index 000000000..ced84dbe5
--- /dev/null
+++ b/app/controllers/privacy_controller.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+class PrivacyController < ApplicationController
+  layout 'public'
+
+  before_action :set_instance_presenter
+  before_action :set_expires_in
+
+  skip_before_action :require_functional!
+
+  def show; end
+
+  private
+
+  def set_instance_presenter
+    @instance_presenter = InstancePresenter.new
+  end
+
+  def set_expires_in
+    expires_in 0, public: true
+  end
+end
diff --git a/app/controllers/statuses_controller.rb b/app/controllers/statuses_controller.rb
index 3812f541e..55cc3790f 100644
--- a/app/controllers/statuses_controller.rb
+++ b/app/controllers/statuses_controller.rb
@@ -8,7 +8,7 @@ class StatusesController < ApplicationController
 
   layout 'public'
 
-  before_action :require_signature!, only: [:show, :activity], if: -> { request.format == :json && authorized_fetch_mode? }
+  before_action :require_account_signature!, only: [:show, :activity], if: -> { request.format == :json && authorized_fetch_mode? }
   before_action :set_status
   before_action :set_instance_presenter
   before_action :set_link_headers
diff --git a/app/controllers/tags_controller.rb b/app/controllers/tags_controller.rb
index 46821a200..315eabb3d 100644
--- a/app/controllers/tags_controller.rb
+++ b/app/controllers/tags_controller.rb
@@ -8,7 +8,7 @@ class TagsController < ApplicationController
 
   layout 'public'
 
-  before_action :require_signature!, if: -> { request.format == :json && authorized_fetch_mode? }
+  before_action :require_account_signature!, if: -> { request.format == :json && authorized_fetch_mode? }
   before_action :authenticate_user!, if: :whitelist_mode?
   before_action :set_local
   before_action :set_tag
diff --git a/app/javascript/mastodon/actions/accounts.js b/app/javascript/mastodon/actions/accounts.js
index eedf61dc9..f61f06e40 100644
--- a/app/javascript/mastodon/actions/accounts.js
+++ b/app/javascript/mastodon/actions/accounts.js
@@ -536,10 +536,12 @@ export function expandFollowingFail(id, error) {
 
 export function fetchRelationships(accountIds) {
   return (dispatch, getState) => {
-    const loadedRelationships = getState().get('relationships');
+    const state = getState();
+    const loadedRelationships = state.get('relationships');
     const newAccountIds = accountIds.filter(id => loadedRelationships.get(id, null) === null);
+    const signedIn = !!state.getIn(['meta', 'me']);
 
-    if (newAccountIds.length === 0) {
+    if (!signedIn || newAccountIds.length === 0) {
       return;
     }
 
diff --git a/app/javascript/mastodon/actions/markers.js b/app/javascript/mastodon/actions/markers.js
index 16a3df8f6..b7f406cb8 100644
--- a/app/javascript/mastodon/actions/markers.js
+++ b/app/javascript/mastodon/actions/markers.js
@@ -1,6 +1,7 @@
 import api from '../api';
 import { debounce } from 'lodash';
 import compareId from '../compare_id';
+import { List as ImmutableList } from 'immutable';
 
 export const MARKERS_FETCH_REQUEST = 'MARKERS_FETCH_REQUEST';
 export const MARKERS_FETCH_SUCCESS = 'MARKERS_FETCH_SUCCESS';
@@ -11,7 +12,7 @@ export const synchronouslySubmitMarkers = () => (dispatch, getState) => {
   const accessToken = getState().getIn(['meta', 'access_token'], '');
   const params      = _buildParams(getState());
 
-  if (Object.keys(params).length === 0) {
+  if (Object.keys(params).length === 0 || accessToken === '') {
     return;
   }
 
@@ -63,7 +64,7 @@ export const synchronouslySubmitMarkers = () => (dispatch, getState) => {
 const _buildParams = (state) => {
   const params = {};
 
-  const lastHomeId         = state.getIn(['timelines', 'home', 'items']).find(item => item !== null);
+  const lastHomeId         = state.getIn(['timelines', 'home', 'items'], ImmutableList()).find(item => item !== null);
   const lastNotificationId = state.getIn(['notifications', 'lastReadId']);
 
   if (lastHomeId && compareId(lastHomeId, state.getIn(['markers', 'home'])) > 0) {
@@ -82,9 +83,10 @@ const _buildParams = (state) => {
 };
 
 const debouncedSubmitMarkers = debounce((dispatch, getState) => {
-  const params = _buildParams(getState());
+  const accessToken = getState().getIn(['meta', 'access_token'], '');
+  const params      = _buildParams(getState());
 
-  if (Object.keys(params).length === 0) {
+  if (Object.keys(params).length === 0 || accessToken === '') {
     return;
   }
 
diff --git a/app/javascript/mastodon/actions/statuses.js b/app/javascript/mastodon/actions/statuses.js
index 32a4f1f85..4ae1b21e0 100644
--- a/app/javascript/mastodon/actions/statuses.js
+++ b/app/javascript/mastodon/actions/statuses.js
@@ -34,6 +34,11 @@ export const STATUS_FETCH_SOURCE_REQUEST = 'STATUS_FETCH_SOURCE_REQUEST';
 export const STATUS_FETCH_SOURCE_SUCCESS = 'STATUS_FETCH_SOURCE_SUCCESS';
 export const STATUS_FETCH_SOURCE_FAIL    = 'STATUS_FETCH_SOURCE_FAIL';
 
+export const STATUS_TRANSLATE_REQUEST = 'STATUS_TRANSLATE_REQUEST';
+export const STATUS_TRANSLATE_SUCCESS = 'STATUS_TRANSLATE_SUCCESS';
+export const STATUS_TRANSLATE_FAIL    = 'STATUS_TRANSLATE_FAIL';
+export const STATUS_TRANSLATE_UNDO    = 'STATUS_TRANSLATE_UNDO';
+
 export function fetchStatusRequest(id, skipLoading) {
   return {
     type: STATUS_FETCH_REQUEST,
@@ -309,4 +314,36 @@ export function toggleStatusCollapse(id, isCollapsed) {
     id,
     isCollapsed,
   };
-}
+};
+
+export const translateStatus = id => (dispatch, getState) => {
+  dispatch(translateStatusRequest(id));
+
+  api(getState).post(`/api/v1/statuses/${id}/translate`).then(response => {
+    dispatch(translateStatusSuccess(id, response.data));
+  }).catch(error => {
+    dispatch(translateStatusFail(id, error));
+  });
+};
+
+export const translateStatusRequest = id => ({
+  type: STATUS_TRANSLATE_REQUEST,
+  id,
+});
+
+export const translateStatusSuccess = (id, translation) => ({
+  type: STATUS_TRANSLATE_SUCCESS,
+  id,
+  translation,
+});
+
+export const translateStatusFail = (id, error) => ({
+  type: STATUS_TRANSLATE_FAIL,
+  id,
+  error,
+});
+
+export const undoStatusTranslation = id => ({
+  type: STATUS_TRANSLATE_UNDO,
+  id,
+});
diff --git a/app/javascript/mastodon/components/__tests__/__snapshots__/avatar-test.js.snap b/app/javascript/mastodon/components/__tests__/__snapshots__/avatar-test.js.snap
index 76ab3374a..1c200b184 100644
--- a/app/javascript/mastodon/components/__tests__/__snapshots__/avatar-test.js.snap
+++ b/app/javascript/mastodon/components/__tests__/__snapshots__/avatar-test.js.snap
@@ -6,7 +6,7 @@ exports[`<Avatar /> Autoplay renders a animated avatar 1`] = `
   onMouseEnter={[Function]}
   onMouseLeave={[Function]}
   style={
-    Object {
+    {
       "backgroundImage": "url(/animated/alice.gif)",
       "backgroundSize": "100px 100px",
       "height": "100px",
@@ -22,7 +22,7 @@ exports[`<Avatar /> Still renders a still avatar 1`] = `
   onMouseEnter={[Function]}
   onMouseLeave={[Function]}
   style={
-    Object {
+    {
       "backgroundImage": "url(/static/alice.jpg)",
       "backgroundSize": "100px 100px",
       "height": "100px",
diff --git a/app/javascript/mastodon/components/__tests__/__snapshots__/avatar_overlay-test.js.snap b/app/javascript/mastodon/components/__tests__/__snapshots__/avatar_overlay-test.js.snap
index d59fee42f..58f27a321 100644
--- a/app/javascript/mastodon/components/__tests__/__snapshots__/avatar_overlay-test.js.snap
+++ b/app/javascript/mastodon/components/__tests__/__snapshots__/avatar_overlay-test.js.snap
@@ -7,7 +7,7 @@ exports[`<AvatarOverlay renders a overlay avatar 1`] = `
   <div
     className="account__avatar-overlay-base"
     style={
-      Object {
+      {
         "backgroundImage": "url(/static/alice.jpg)",
       }
     }
@@ -15,7 +15,7 @@ exports[`<AvatarOverlay renders a overlay avatar 1`] = `
   <div
     className="account__avatar-overlay-overlay"
     style={
-      Object {
+      {
         "backgroundImage": "url(/static/eve.jpg)",
       }
     }
diff --git a/app/javascript/mastodon/components/__tests__/__snapshots__/display_name-test.js.snap b/app/javascript/mastodon/components/__tests__/__snapshots__/display_name-test.js.snap
index 0f27473af..9c37580d7 100644
--- a/app/javascript/mastodon/components/__tests__/__snapshots__/display_name-test.js.snap
+++ b/app/javascript/mastodon/components/__tests__/__snapshots__/display_name-test.js.snap
@@ -10,7 +10,7 @@ exports[`<DisplayName /> renders display name + account name 1`] = `
     <strong
       className="display-name__html"
       dangerouslySetInnerHTML={
-        Object {
+        {
           "__html": "<p>Foo</p>",
         }
       }
diff --git a/app/javascript/mastodon/components/column_header.js b/app/javascript/mastodon/components/column_header.js
index cbbc490a8..5b2e16627 100644
--- a/app/javascript/mastodon/components/column_header.js
+++ b/app/javascript/mastodon/components/column_header.js
@@ -17,6 +17,7 @@ class ColumnHeader extends React.PureComponent {
 
   static contextTypes = {
     router: PropTypes.object,
+    identity: PropTypes.object,
   };
 
   static propTypes = {
@@ -145,7 +146,7 @@ class ColumnHeader extends React.PureComponent {
       collapsedContent.push(moveButtons);
     }
 
-    if (children || (multiColumn && this.props.onPin)) {
+    if (this.context.identity.signedIn && (children || (multiColumn && this.props.onPin))) {
       collapseButton = (
         <button
           className={collapsibleButtonClassName}
diff --git a/app/javascript/mastodon/components/hashtag.js b/app/javascript/mastodon/components/hashtag.js
index 4e9cd3569..4a5a4bb57 100644
--- a/app/javascript/mastodon/components/hashtag.js
+++ b/app/javascript/mastodon/components/hashtag.js
@@ -1,7 +1,7 @@
 // @ts-check
 import React from 'react';
 import { Sparklines, SparklinesCurve } from 'react-sparklines';
-import { FormattedMessage, injectIntl, defineMessages } from 'react-intl';
+import { FormattedMessage } from 'react-intl';
 import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import Permalink from './permalink';
@@ -9,10 +9,6 @@ import ShortNumber from 'mastodon/components/short_number';
 import Skeleton from 'mastodon/components/skeleton';
 import classNames from 'classnames';
 
-const messages = defineMessages({
-  totalVolume: { id: 'hashtag.total_volume', defaultMessage: 'Total volume in the last {days, plural, one {day} other {{days} days}}' },
-});
-
 class SilentErrorBoundary extends React.Component {
 
   static propTypes = {
@@ -69,7 +65,7 @@ ImmutableHashtag.propTypes = {
   hashtag: ImmutablePropTypes.map.isRequired,
 };
 
-const Hashtag = injectIntl(({ name, href, to, people, uses, history, className, intl }) => (
+const Hashtag = ({ name, href, to, people, history, className }) => (
   <div className={classNames('trends__item', className)}>
     <div className='trends__item__name'>
       <Permalink href={href} to={to}>
@@ -79,11 +75,6 @@ const Hashtag = injectIntl(({ name, href, to, people, uses, history, className,
       {typeof people !== 'undefined' ? <ShortNumber value={people} renderer={accountsCountRenderer} /> : <Skeleton width={100} />}
     </div>
 
-    <abbr className='trends__item__current' title={intl.formatMessage(messages.totalVolume, { days: 2 })}>
-      {typeof uses !== 'undefined' ? <ShortNumber value={uses} /> : <Skeleton width={42} height={36} />}
-      <span className='trends__item__current__asterisk'>*</span>
-    </abbr>
-
     <div className='trends__item__sparkline'>
       <SilentErrorBoundary>
         <Sparklines width={50} height={28} data={history ? history : Array.from(Array(7)).map(() => 0)}>
@@ -92,7 +83,7 @@ const Hashtag = injectIntl(({ name, href, to, people, uses, history, className,
       </SilentErrorBoundary>
     </div>
   </div>
-));
+);
 
 Hashtag.propTypes = {
   name: PropTypes.string,
diff --git a/app/javascript/mastodon/components/logo.js b/app/javascript/mastodon/components/logo.js
index d1c7f08a9..3570b3644 100644
--- a/app/javascript/mastodon/components/logo.js
+++ b/app/javascript/mastodon/components/logo.js
@@ -1,8 +1,8 @@
 import React from 'react';
 
 const Logo = () => (
-  <svg viewBox='0 0 216.4144 232.00976' className='logo'>
-    <use xlinkHref='#mastodon-svg-logo' />
+  <svg viewBox='0 0 261 66' className='logo'>
+    <use xlinkHref='#logo-symbol-wordmark' />
   </svg>
 );
 
diff --git a/app/javascript/mastodon/components/poll.js b/app/javascript/mastodon/components/poll.js
index 85aa28816..3e643168e 100644
--- a/app/javascript/mastodon/components/poll.js
+++ b/app/javascript/mastodon/components/poll.js
@@ -34,6 +34,10 @@ const makeEmojiMap = record => record.get('emojis').reduce((obj, emoji) => {
 export default @injectIntl
 class Poll extends ImmutablePureComponent {
 
+  static contextTypes = {
+    identity: PropTypes.object,
+  };
+
   static propTypes = {
     poll: ImmutablePropTypes.map,
     intl: PropTypes.object.isRequired,
@@ -217,7 +221,7 @@ class Poll extends ImmutablePureComponent {
         </ul>
 
         <div className='poll__footer'>
-          {!showResults && <button className='button button-secondary' disabled={disabled} onClick={this.handleVote}><FormattedMessage id='poll.vote' defaultMessage='Vote' /></button>}
+          {!showResults && <button className='button button-secondary' disabled={disabled || !this.context.identity.signedIn} onClick={this.handleVote}><FormattedMessage id='poll.vote' defaultMessage='Vote' /></button>}
           {showResults && !this.props.disabled && <span><button className='poll__link' onClick={this.handleRefresh}><FormattedMessage id='poll.refresh' defaultMessage='Refresh' /></button> · </span>}
           {votesCount}
           {poll.get('expires_at') && <span> · {timeRemaining}</span>}
diff --git a/app/javascript/mastodon/components/status.js b/app/javascript/mastodon/components/status.js
index 6fc132bf5..0d3b51f07 100644
--- a/app/javascript/mastodon/components/status.js
+++ b/app/javascript/mastodon/components/status.js
@@ -85,6 +85,7 @@ class Status extends ImmutablePureComponent {
     onHeightChange: PropTypes.func,
     onToggleHidden: PropTypes.func,
     onToggleCollapsed: PropTypes.func,
+    onTranslate: PropTypes.func,
     muted: PropTypes.bool,
     hidden: PropTypes.bool,
     unread: PropTypes.bool,
@@ -171,6 +172,10 @@ class Status extends ImmutablePureComponent {
     this.props.onToggleCollapsed(this._properStatus(), isCollapsed);
   }
 
+  handleTranslate = () => {
+    this.props.onTranslate(this._properStatus());
+  }
+
   renderLoadingMediaGallery () {
     return <div className='media-gallery' style={{ height: '110px' }} />;
   }
@@ -512,7 +517,16 @@ class Status extends ImmutablePureComponent {
               </a>
             </div>
 
-            <StatusContent status={status} onClick={this.handleClick} expanded={!status.get('hidden')} showThread={showThread} onExpandedToggle={this.handleExpandedToggle} collapsable onCollapsedToggle={this.handleCollapsedToggle} />
+            <StatusContent
+              status={status}
+              onClick={this.handleClick}
+              expanded={!status.get('hidden')}
+              showThread={showThread}
+              onExpandedToggle={this.handleExpandedToggle}
+              onTranslate={this.handleTranslate}
+              collapsable
+              onCollapsedToggle={this.handleCollapsedToggle}
+            />
 
             {media}
 
diff --git a/app/javascript/mastodon/components/status_content.js b/app/javascript/mastodon/components/status_content.js
index 724165ada..a88c5f084 100644
--- a/app/javascript/mastodon/components/status_content.js
+++ b/app/javascript/mastodon/components/status_content.js
@@ -1,19 +1,21 @@
 import React from 'react';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import PropTypes from 'prop-types';
-import { FormattedMessage } from 'react-intl';
+import { FormattedMessage, injectIntl } from 'react-intl';
 import Permalink from './permalink';
 import classnames from 'classnames';
 import PollContainer from 'mastodon/containers/poll_container';
 import Icon from 'mastodon/components/icon';
-import { autoPlayGif } from 'mastodon/initial_state';
+import { autoPlayGif, languages as preloadedLanguages } from 'mastodon/initial_state';
 
 const MAX_HEIGHT = 642; // 20px * 32 (+ 2px padding at the top)
 
-export default class StatusContent extends React.PureComponent {
+export default @injectIntl
+class StatusContent extends React.PureComponent {
 
   static contextTypes = {
     router: PropTypes.object,
+    identity: PropTypes.object,
   };
 
   static propTypes = {
@@ -21,9 +23,11 @@ export default class StatusContent extends React.PureComponent {
     expanded: PropTypes.bool,
     showThread: PropTypes.bool,
     onExpandedToggle: PropTypes.func,
+    onTranslate: PropTypes.func,
     onClick: PropTypes.func,
     collapsable: PropTypes.bool,
     onCollapsedToggle: PropTypes.func,
+    intl: PropTypes.object,
   };
 
   state = {
@@ -163,20 +167,27 @@ export default class StatusContent extends React.PureComponent {
     }
   }
 
+  handleTranslate = () => {
+    this.props.onTranslate();
+  }
+
   setRef = (c) => {
     this.node = c;
   }
 
   render () {
-    const { status } = this.props;
+    const { status, intl } = this.props;
 
     const hidden = this.props.onExpandedToggle ? !this.props.expanded : this.state.hidden;
     const renderReadMore = this.props.onClick && status.get('collapsed');
     const renderViewThread = this.props.showThread && status.get('in_reply_to_id') && status.get('in_reply_to_account_id') === status.getIn(['account', 'id']);
+    const renderTranslate = this.context.identity.signedIn && this.props.onTranslate && ['public', 'unlisted'].includes(status.get('visibility')) && status.get('contentHtml').length > 0 && intl.locale !== status.get('language');
+    const language = preloadedLanguages.find(lang => lang[0] === status.get('language'));
+    const languageName = language ? language[2] : status.get('language');
 
-    const content = { __html: status.get('contentHtml') };
+    const content = { __html: status.get('translation') ? status.getIn(['translation', 'content']) : status.get('contentHtml') };
     const spoilerContent = { __html: status.get('spoilerHtml') };
-    const lang = status.get('language');
+    const lang = status.get('translation') ? intl.locale : status.get('language');
     const classNames = classnames('status__content', {
       'status__content--with-action': this.props.onClick && this.context.router,
       'status__content--with-spoiler': status.get('spoiler_text').length > 0,
@@ -195,6 +206,12 @@ export default class StatusContent extends React.PureComponent {
       </button>
     );
 
+    const translateButton = (
+      <button className='status__content__read-more-button' onClick={this.handleTranslate}>
+        {status.get('translation') ? <span><FormattedMessage id='status.translated_from' defaultMessage='Translated from {lang}' values={{ lang: languageName }} /> · <FormattedMessage id='status.show_original' defaultMessage='Show original' /></span> : <FormattedMessage id='status.translate' defaultMessage='Translate' />}
+      </button>
+    );
+
     if (status.get('spoiler_text').length > 0) {
       let mentionsPlaceholder = '';
 
@@ -223,7 +240,7 @@ export default class StatusContent extends React.PureComponent {
           <div tabIndex={!hidden ? 0 : null} className={`status__content__text ${!hidden ? 'status__content__text--visible' : ''} translate`} lang={lang} dangerouslySetInnerHTML={content} />
 
           {!hidden && !!status.get('poll') && <PollContainer pollId={status.get('poll')} />}
-
+          {!hidden && renderTranslate && translateButton}
           {renderViewThread && showThreadButton}
         </div>
       );
@@ -233,7 +250,7 @@ export default class StatusContent extends React.PureComponent {
           <div className='status__content__text status__content__text--visible translate' lang={lang} dangerouslySetInnerHTML={content} />
 
           {!!status.get('poll') && <PollContainer pollId={status.get('poll')} />}
-
+          {renderTranslate && translateButton}
           {renderViewThread && showThreadButton}
         </div>,
       ];
@@ -249,7 +266,7 @@ export default class StatusContent extends React.PureComponent {
           <div className='status__content__text status__content__text--visible translate' lang={lang} dangerouslySetInnerHTML={content} />
 
           {!!status.get('poll') && <PollContainer pollId={status.get('poll')} />}
-
+          {renderTranslate && translateButton}
           {renderViewThread && showThreadButton}
         </div>
       );
diff --git a/app/javascript/mastodon/containers/mastodon.js b/app/javascript/mastodon/containers/mastodon.js
index f4bef4686..08241522c 100644
--- a/app/javascript/mastodon/containers/mastodon.js
+++ b/app/javascript/mastodon/containers/mastodon.js
@@ -26,7 +26,7 @@ const createIdentityContext = state => ({
   signedIn: !!state.meta.me,
   accountId: state.meta.me,
   accessToken: state.meta.access_token,
-  permissions: state.role.permissions,
+  permissions: state.role ? state.role.permissions : 0,
 });
 
 export default class Mastodon extends React.PureComponent {
diff --git a/app/javascript/mastodon/containers/status_container.js b/app/javascript/mastodon/containers/status_container.js
index 28698b082..9280a6ee3 100644
--- a/app/javascript/mastodon/containers/status_container.js
+++ b/app/javascript/mastodon/containers/status_container.js
@@ -25,6 +25,8 @@ import {
   revealStatus,
   toggleStatusCollapse,
   editStatus,
+  translateStatus,
+  undoStatusTranslation,
 } from '../actions/statuses';
 import {
   unmuteAccount,
@@ -150,6 +152,14 @@ const mapDispatchToProps = (dispatch, { intl, contextType }) => ({
     dispatch(editStatus(status.get('id'), history));
   },
 
+  onTranslate (status) {
+    if (status.get('translation')) {
+      dispatch(undoStatusTranslation(status.get('id')));
+    } else {
+      dispatch(translateStatus(status.get('id')));
+    }
+  },
+
   onDirect (account, router) {
     dispatch(directCompose(account, router));
   },
diff --git a/app/javascript/mastodon/features/account/components/header.js b/app/javascript/mastodon/features/account/components/header.js
index 1ad9341c7..e407a0d55 100644
--- a/app/javascript/mastodon/features/account/components/header.js
+++ b/app/javascript/mastodon/features/account/components/header.js
@@ -4,7 +4,7 @@ import PropTypes from 'prop-types';
 import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
 import Button from 'mastodon/components/button';
 import ImmutablePureComponent from 'react-immutable-pure-component';
-import { autoPlayGif, me } from 'mastodon/initial_state';
+import { autoPlayGif, me, title, domain } from 'mastodon/initial_state';
 import classNames from 'classnames';
 import Icon from 'mastodon/components/icon';
 import IconButton from 'mastodon/components/icon_button';
@@ -15,6 +15,7 @@ import { NavLink } from 'react-router-dom';
 import DropdownMenuContainer from 'mastodon/containers/dropdown_menu_container';
 import AccountNoteContainer from '../containers/account_note_container';
 import { PERMISSION_MANAGE_USERS } from 'mastodon/permissions';
+import { Helmet } from 'react-helmet';
 
 const messages = defineMessages({
   unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' },
@@ -51,8 +52,17 @@ const messages = defineMessages({
   unendorse: { id: 'account.unendorse', defaultMessage: 'Don\'t feature on profile' },
   add_or_remove_from_list: { id: 'account.add_or_remove_from_list', defaultMessage: 'Add or Remove from lists' },
   admin_account: { id: 'status.admin_account', defaultMessage: 'Open moderation interface for @{name}' },
+  languages: { id: 'account.languages', defaultMessage: 'Change subscribed languages' },
 });
 
+const titleFromAccount = account => {
+  const displayName = account.get('display_name');
+  const acct = account.get('acct') === account.get('username') ? `${account.get('username')}@${domain}` : account.get('acct');
+  const prefix = displayName.trim().length === 0 ? account.get('username') : displayName;
+
+  return `${prefix} (@${acct})`;
+};
+
 const dateFormatOptions = {
   month: 'short',
   day: 'numeric',
@@ -85,6 +95,7 @@ class Header extends ImmutablePureComponent {
     onEndorseToggle: PropTypes.func.isRequired,
     onAddToList: PropTypes.func.isRequired,
     onEditAccountNote: PropTypes.func.isRequired,
+    onChangeLanguages: PropTypes.func.isRequired,
     intl: PropTypes.object.isRequired,
     domain: PropTypes.string.isRequired,
     hidden: PropTypes.bool,
@@ -130,6 +141,7 @@ class Header extends ImmutablePureComponent {
 
   render () {
     const { account, hidden, intl, domain } = this.props;
+    const { signedIn } = this.context.identity;
 
     if (!account) {
       return null;
@@ -160,12 +172,12 @@ class Header extends ImmutablePureComponent {
     }
 
     if (me !== account.get('id')) {
-      if (!account.get('relationship')) { // Wait until the relationship is loaded
+      if (signedIn && !account.get('relationship')) { // Wait until the relationship is loaded
         actionBtn = '';
       } else if (account.getIn(['relationship', 'requested'])) {
         actionBtn = <Button className={classNames('logo-button', { 'button--with-bell': bellBtn !== '' })} text={intl.formatMessage(messages.cancel_follow_request)} title={intl.formatMessage(messages.requested)} onClick={this.props.onFollow} />;
       } else if (!account.getIn(['relationship', 'blocking'])) {
-        actionBtn = <Button disabled={account.getIn(['relationship', 'blocked_by'])} className={classNames('logo-button', { 'button--destructive': account.getIn(['relationship', 'following']), 'button--with-bell': bellBtn !== '' })} text={intl.formatMessage(account.getIn(['relationship', 'following']) ? messages.unfollow : messages.follow)} onClick={this.props.onFollow} />;
+        actionBtn = <Button disabled={account.getIn(['relationship', 'blocked_by'])} className={classNames('logo-button', { 'button--destructive': account.getIn(['relationship', 'following']), 'button--with-bell': bellBtn !== '' })} text={intl.formatMessage(account.getIn(['relationship', 'following']) ? messages.unfollow : messages.follow)} onClick={signedIn ? this.props.onFollow : undefined} />;
       } else if (account.getIn(['relationship', 'blocking'])) {
         actionBtn = <Button className='logo-button' text={intl.formatMessage(messages.unblock, { name: account.get('username') })} onClick={this.props.onBlock} />;
       }
@@ -181,7 +193,7 @@ class Header extends ImmutablePureComponent {
       lockedIcon = <Icon id='lock' title={intl.formatMessage(messages.account_locked)} />;
     }
 
-    if (account.get('id') !== me) {
+    if (signedIn && account.get('id') !== me) {
       menu.push({ text: intl.formatMessage(messages.mention, { name: account.get('username') }), action: this.props.onMention });
       menu.push({ text: intl.formatMessage(messages.direct, { name: account.get('username') }), action: this.props.onDirect });
       menu.push(null);
@@ -204,7 +216,7 @@ class Header extends ImmutablePureComponent {
       menu.push({ text: intl.formatMessage(messages.mutes), to: '/mutes' });
       menu.push({ text: intl.formatMessage(messages.blocks), to: '/blocks' });
       menu.push({ text: intl.formatMessage(messages.domain_blocks), to: '/domain_blocks' });
-    } else {
+    } else if (signedIn) {
       if (account.getIn(['relationship', 'following'])) {
         if (!account.getIn(['relationship', 'muting'])) {
           if (account.getIn(['relationship', 'showing_reblogs'])) {
@@ -212,6 +224,9 @@ class Header extends ImmutablePureComponent {
           } else {
             menu.push({ text: intl.formatMessage(messages.showReblogs, { name: account.get('username') }), action: this.props.onReblogToggle });
           }
+
+          menu.push({ text: intl.formatMessage(messages.languages), action: this.props.onChangeLanguages });
+          menu.push(null);
         }
 
         menu.push({ text: intl.formatMessage(account.getIn(['relationship', 'endorsed']) ? messages.unendorse : messages.endorse), action: this.props.onEndorseToggle });
@@ -234,7 +249,7 @@ class Header extends ImmutablePureComponent {
       menu.push({ text: intl.formatMessage(messages.report, { name: account.get('username') }), action: this.props.onReport });
     }
 
-    if (account.get('acct') !== account.get('username')) {
+    if (signedIn && account.get('acct') !== account.get('username')) {
       const domain = account.get('acct').split('@')[1];
 
       menu.push(null);
@@ -293,7 +308,7 @@ class Header extends ImmutablePureComponent {
                   </React.Fragment>
                 )}
 
-                <DropdownMenuContainer items={menu} icon='ellipsis-v' size={24} direction='right' />
+                <DropdownMenuContainer disabled={menu.length === 0} items={menu} icon='ellipsis-v' size={24} direction='right' />
               </div>
             )}
           </div>
@@ -322,7 +337,7 @@ class Header extends ImmutablePureComponent {
                   </div>
                 )}
 
-                {account.get('id') !== me && <AccountNoteContainer account={account} />}
+                {(account.get('id') !== me && signedIn) && <AccountNoteContainer account={account} />}
 
                 {account.get('note').length > 0 && account.get('note') !== '<p></p>' && <div className='account__header__content translate' dangerouslySetInnerHTML={content} />}
 
@@ -354,6 +369,10 @@ class Header extends ImmutablePureComponent {
             </div>
           )}
         </div>
+
+        <Helmet>
+          <title>{titleFromAccount(account)} - {title}</title>
+        </Helmet>
       </div>
     );
   }
diff --git a/app/javascript/mastodon/features/account_timeline/components/header.js b/app/javascript/mastodon/features/account_timeline/components/header.js
index fab0bc597..f9838442f 100644
--- a/app/javascript/mastodon/features/account_timeline/components/header.js
+++ b/app/javascript/mastodon/features/account_timeline/components/header.js
@@ -22,6 +22,7 @@ export default class Header extends ImmutablePureComponent {
     onUnblockDomain: PropTypes.func.isRequired,
     onEndorseToggle: PropTypes.func.isRequired,
     onAddToList: PropTypes.func.isRequired,
+    onChangeLanguages: PropTypes.func.isRequired,
     hideTabs: PropTypes.bool,
     domain: PropTypes.string.isRequired,
     hidden: PropTypes.bool,
@@ -91,6 +92,10 @@ export default class Header extends ImmutablePureComponent {
     this.props.onEditAccountNote(this.props.account);
   }
 
+  handleChangeLanguages = () => {
+    this.props.onChangeLanguages(this.props.account);
+  }
+
   render () {
     const { account, hidden, hideTabs } = this.props;
 
@@ -117,6 +122,7 @@ export default class Header extends ImmutablePureComponent {
           onEndorseToggle={this.handleEndorseToggle}
           onAddToList={this.handleAddToList}
           onEditAccountNote={this.handleEditAccountNote}
+          onChangeLanguages={this.handleChangeLanguages}
           domain={this.props.domain}
           hidden={hidden}
         />
diff --git a/app/javascript/mastodon/features/account_timeline/containers/header_container.js b/app/javascript/mastodon/features/account_timeline/containers/header_container.js
index 371794dd7..3d6eb487d 100644
--- a/app/javascript/mastodon/features/account_timeline/containers/header_container.js
+++ b/app/javascript/mastodon/features/account_timeline/containers/header_container.js
@@ -121,12 +121,18 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
     dispatch(unblockDomain(domain));
   },
 
-  onAddToList(account){
+  onAddToList (account) {
     dispatch(openModal('LIST_ADDER', {
       accountId: account.get('id'),
     }));
   },
 
+  onChangeLanguages (account) {
+    dispatch(openModal('SUBSCRIBED_LANGUAGES', {
+      accountId: account.get('id'),
+    }));
+  },
+
 });
 
 export default injectIntl(connect(makeMapStateToProps, mapDispatchToProps)(Header));
diff --git a/app/javascript/mastodon/features/community_timeline/index.js b/app/javascript/mastodon/features/community_timeline/index.js
index 30f776048..f9d50e64c 100644
--- a/app/javascript/mastodon/features/community_timeline/index.js
+++ b/app/javascript/mastodon/features/community_timeline/index.js
@@ -9,6 +9,8 @@ import { expandCommunityTimeline } from '../../actions/timelines';
 import { addColumn, removeColumn, moveColumn } from '../../actions/columns';
 import ColumnSettingsContainer from './containers/column_settings_container';
 import { connectCommunityStream } from '../../actions/streaming';
+import { Helmet } from 'react-helmet';
+import { title } from 'mastodon/initial_state';
 
 const messages = defineMessages({
   title: { id: 'column.community', defaultMessage: 'Local timeline' },
@@ -128,6 +130,10 @@ class CommunityTimeline extends React.PureComponent {
           emptyMessage={<FormattedMessage id='empty_column.community' defaultMessage='The local timeline is empty. Write something publicly to get the ball rolling!' />}
           bindToDocument={!multiColumn}
         />
+
+        <Helmet>
+          <title>{intl.formatMessage(messages.title)} - {title}</title>
+        </Helmet>
       </Column>
     );
   }
diff --git a/app/javascript/mastodon/features/directory/index.js b/app/javascript/mastodon/features/directory/index.js
index 94d7d1a9c..36f46c510 100644
--- a/app/javascript/mastodon/features/directory/index.js
+++ b/app/javascript/mastodon/features/directory/index.js
@@ -13,6 +13,8 @@ import RadioButton from 'mastodon/components/radio_button';
 import LoadMore from 'mastodon/components/load_more';
 import ScrollContainer from 'mastodon/containers/scroll_container';
 import LoadingIndicator from 'mastodon/components/loading_indicator';
+import { title } from 'mastodon/initial_state';
+import { Helmet } from 'react-helmet';
 
 const messages = defineMessages({
   title: { id: 'column.directory', defaultMessage: 'Browse profiles' },
@@ -165,6 +167,10 @@ class Directory extends React.PureComponent {
         />
 
         {multiColumn && !pinned ? <ScrollContainer scrollKey='directory'>{scrollableArea}</ScrollContainer> : scrollableArea}
+
+        <Helmet>
+          <title>{intl.formatMessage(messages.title)} - {title}</title>
+        </Helmet>
       </Column>
     );
   }
diff --git a/app/javascript/mastodon/features/explore/index.js b/app/javascript/mastodon/features/explore/index.js
index 8082f2d99..e1d1eb563 100644
--- a/app/javascript/mastodon/features/explore/index.js
+++ b/app/javascript/mastodon/features/explore/index.js
@@ -11,6 +11,8 @@ import Statuses from './statuses';
 import Suggestions from './suggestions';
 import Search from 'mastodon/features/compose/containers/search_container';
 import SearchResults from './results';
+import { Helmet } from 'react-helmet';
+import { title } from 'mastodon/initial_state';
 
 const messages = defineMessages({
   title: { id: 'explore.title', defaultMessage: 'Explore' },
@@ -81,6 +83,10 @@ class Explore extends React.PureComponent {
                 <Route path='/explore/suggestions' component={Suggestions} />
                 <Route exact path={['/explore', '/explore/posts', '/search']} component={Statuses} componentParams={{ multiColumn }} />
               </Switch>
+
+              <Helmet>
+                <title>{intl.formatMessage(messages.title)} - {title}</title>
+              </Helmet>
             </React.Fragment>
           )}
         </div>
diff --git a/app/javascript/mastodon/features/explore/links.js b/app/javascript/mastodon/features/explore/links.js
index 6649fb6e4..d3aaa9cdd 100644
--- a/app/javascript/mastodon/features/explore/links.js
+++ b/app/javascript/mastodon/features/explore/links.js
@@ -5,6 +5,7 @@ import Story from './components/story';
 import LoadingIndicator from 'mastodon/components/loading_indicator';
 import { connect } from 'react-redux';
 import { fetchTrendingLinks } from 'mastodon/actions/trends';
+import { FormattedMessage } from 'react-intl';
 
 const mapStateToProps = state => ({
   links: state.getIn(['trends', 'links', 'items']),
@@ -28,6 +29,16 @@ class Links extends React.PureComponent {
   render () {
     const { isLoading, links } = this.props;
 
+    if (!isLoading && links.isEmpty()) {
+      return (
+        <div className='explore__links scrollable scrollable--flex'>
+          <div className='empty-column-indicator'>
+            <FormattedMessage id='empty_column.explore_statuses' defaultMessage='Nothing is trending right now. Check back later!' />
+          </div>
+        </div>
+      );
+    }
+
     return (
       <div className='explore__links'>
         {isLoading ? (<LoadingIndicator />) : links.map(link => (
diff --git a/app/javascript/mastodon/features/explore/results.js b/app/javascript/mastodon/features/explore/results.js
index 1286020f5..0dc108918 100644
--- a/app/javascript/mastodon/features/explore/results.js
+++ b/app/javascript/mastodon/features/explore/results.js
@@ -1,7 +1,7 @@
 import React from 'react';
 import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
-import { FormattedMessage } from 'react-intl';
+import { injectIntl, defineMessages, FormattedMessage } from 'react-intl';
 import { connect } from 'react-redux';
 import { expandSearch } from 'mastodon/actions/search';
 import Account from 'mastodon/containers/account_container';
@@ -10,10 +10,17 @@ import { ImmutableHashtag as Hashtag } from 'mastodon/components/hashtag';
 import { List as ImmutableList } from 'immutable';
 import LoadMore from 'mastodon/components/load_more';
 import LoadingIndicator from 'mastodon/components/loading_indicator';
+import { title } from 'mastodon/initial_state';
+import { Helmet } from 'react-helmet';
+
+const messages = defineMessages({
+  title: { id: 'search_results.title', defaultMessage: 'Search for {q}' },
+});
 
 const mapStateToProps = state => ({
   isLoading: state.getIn(['search', 'isLoading']),
   results: state.getIn(['search', 'results']),
+  q: state.getIn(['search', 'searchTerm']),
 });
 
 const appendLoadMore = (id, list, onLoadMore) => {
@@ -37,6 +44,7 @@ const renderStatuses = (results, onLoadMore) => appendLoadMore('statuses', resul
 )), onLoadMore);
 
 export default @connect(mapStateToProps)
+@injectIntl
 class Results extends React.PureComponent {
 
   static propTypes = {
@@ -44,6 +52,8 @@ class Results extends React.PureComponent {
     isLoading: PropTypes.bool,
     multiColumn: PropTypes.bool,
     dispatch: PropTypes.func.isRequired,
+    q: PropTypes.string,
+    intl: PropTypes.object,
   };
 
   state = {
@@ -64,7 +74,7 @@ class Results extends React.PureComponent {
   }
 
   render () {
-    const { isLoading, results } = this.props;
+    const { intl, isLoading, q, results } = this.props;
     const { type } = this.state;
 
     let filteredResults = ImmutableList();
@@ -106,6 +116,10 @@ class Results extends React.PureComponent {
         <div className='explore__search-results'>
           {isLoading ? <LoadingIndicator /> : filteredResults}
         </div>
+
+        <Helmet>
+          <title>{intl.formatMessage(messages.title, { q })} - {title}</title>
+        </Helmet>
       </React.Fragment>
     );
   }
diff --git a/app/javascript/mastodon/features/explore/suggestions.js b/app/javascript/mastodon/features/explore/suggestions.js
index 0c6a7ef8a..e6ad09974 100644
--- a/app/javascript/mastodon/features/explore/suggestions.js
+++ b/app/javascript/mastodon/features/explore/suggestions.js
@@ -5,6 +5,7 @@ import AccountCard from 'mastodon/features/directory/components/account_card';
 import LoadingIndicator from 'mastodon/components/loading_indicator';
 import { connect } from 'react-redux';
 import { fetchSuggestions } from 'mastodon/actions/suggestions';
+import { FormattedMessage } from 'react-intl';
 
 const mapStateToProps = state => ({
   suggestions: state.getIn(['suggestions', 'items']),
@@ -28,6 +29,16 @@ class Suggestions extends React.PureComponent {
   render () {
     const { isLoading, suggestions } = this.props;
 
+    if (!isLoading && suggestions.isEmpty()) {
+      return (
+        <div className='explore__suggestions scrollable scrollable--flex'>
+          <div className='empty-column-indicator'>
+            <FormattedMessage id='empty_column.explore_statuses' defaultMessage='Nothing is trending right now. Check back later!' />
+          </div>
+        </div>
+      );
+    }
+
     return (
       <div className='explore__suggestions'>
         {isLoading ? <LoadingIndicator /> : suggestions.map(suggestion => (
diff --git a/app/javascript/mastodon/features/explore/tags.js b/app/javascript/mastodon/features/explore/tags.js
index c0ad9fc6e..6cd3a6fb1 100644
--- a/app/javascript/mastodon/features/explore/tags.js
+++ b/app/javascript/mastodon/features/explore/tags.js
@@ -5,6 +5,7 @@ import { ImmutableHashtag as Hashtag } from 'mastodon/components/hashtag';
 import LoadingIndicator from 'mastodon/components/loading_indicator';
 import { connect } from 'react-redux';
 import { fetchTrendingHashtags } from 'mastodon/actions/trends';
+import { FormattedMessage } from 'react-intl';
 
 const mapStateToProps = state => ({
   hashtags: state.getIn(['trends', 'tags', 'items']),
@@ -28,6 +29,16 @@ class Tags extends React.PureComponent {
   render () {
     const { isLoading, hashtags } = this.props;
 
+    if (!isLoading && hashtags.isEmpty()) {
+      return (
+        <div className='explore__links scrollable scrollable--flex'>
+          <div className='empty-column-indicator'>
+            <FormattedMessage id='empty_column.explore_statuses' defaultMessage='Nothing is trending right now. Check back later!' />
+          </div>
+        </div>
+      );
+    }
+
     return (
       <div className='explore__links'>
         {isLoading ? (<LoadingIndicator />) : hashtags.map(hashtag => (
diff --git a/app/javascript/mastodon/features/follow_recommendations/index.js b/app/javascript/mastodon/features/follow_recommendations/index.js
index b5a71aef5..32b55eeb3 100644
--- a/app/javascript/mastodon/features/follow_recommendations/index.js
+++ b/app/javascript/mastodon/features/follow_recommendations/index.js
@@ -10,7 +10,6 @@ import { requestBrowserPermission } from 'mastodon/actions/notifications';
 import { markAsPartial } from 'mastodon/actions/timelines';
 import Column from 'mastodon/features/ui/components/column';
 import Account from './components/account';
-import Logo from 'mastodon/components/logo';
 import imageGreeting from 'mastodon/../images/elephant_ui_greeting.svg';
 import Button from 'mastodon/components/button';
 
@@ -78,7 +77,10 @@ class FollowRecommendations extends ImmutablePureComponent {
       <Column>
         <div className='scrollable follow-recommendations-container'>
           <div className='column-title'>
-            <Logo />
+            <svg viewBox='0 0 79 79' className='logo'>
+              <use xlinkHref='#logo-symbol-icon' />
+            </svg>
+
             <h3><FormattedMessage id='follow_recommendations.heading' defaultMessage="Follow people you'd like to see posts from! Here are some suggestions." /></h3>
             <p><FormattedMessage id='follow_recommendations.lead' defaultMessage="Posts from people you follow will show up in chronological order on your home feed. Don't be afraid to make mistakes, you can unfollow people just as easily any time!" /></p>
           </div>
diff --git a/app/javascript/mastodon/features/hashtag_timeline/index.js b/app/javascript/mastodon/features/hashtag_timeline/index.js
index dc8a61640..7069e0341 100644
--- a/app/javascript/mastodon/features/hashtag_timeline/index.js
+++ b/app/javascript/mastodon/features/hashtag_timeline/index.js
@@ -14,6 +14,8 @@ import { isEqual } from 'lodash';
 import { fetchHashtag, followHashtag, unfollowHashtag } from 'mastodon/actions/tags';
 import Icon from 'mastodon/components/icon';
 import classNames from 'classnames';
+import { title } from 'mastodon/initial_state';
+import { Helmet } from 'react-helmet';
 
 const messages = defineMessages({
   followHashtag: { id: 'hashtag.follow', defaultMessage: 'Follow hashtag' },
@@ -31,6 +33,10 @@ class HashtagTimeline extends React.PureComponent {
 
   disconnects = [];
 
+  static contextTypes = {
+    identity: PropTypes.object,
+  };
+
   static propTypes = {
     params: PropTypes.object.isRequired,
     columnId: PropTypes.string,
@@ -158,6 +164,11 @@ class HashtagTimeline extends React.PureComponent {
   handleFollow = () => {
     const { dispatch, params, tag } = this.props;
     const { id } = params;
+    const { signedIn } = this.context.identity;
+
+    if (!signedIn) {
+      return;
+    }
 
     if (tag.get('following')) {
       dispatch(unfollowHashtag(id));
@@ -170,6 +181,7 @@ class HashtagTimeline extends React.PureComponent {
     const { hasUnread, columnId, multiColumn, tag, intl } = this.props;
     const { id, local } = this.props.params;
     const pinned = !!columnId;
+    const { signedIn } = this.context.identity;
 
     let followButton;
 
@@ -177,7 +189,7 @@ class HashtagTimeline extends React.PureComponent {
       const following = tag.get('following');
 
       followButton = (
-        <button className={classNames('column-header__button')} onClick={this.handleFollow} title={intl.formatMessage(following ? messages.unfollowHashtag : messages.followHashtag)} aria-label={intl.formatMessage(following ? messages.unfollowHashtag : messages.followHashtag)} aria-pressed={following ? 'true' : 'false'}>
+        <button className={classNames('column-header__button')} onClick={this.handleFollow} disabled={!signedIn} title={intl.formatMessage(following ? messages.unfollowHashtag : messages.followHashtag)} aria-label={intl.formatMessage(following ? messages.unfollowHashtag : messages.followHashtag)} aria-pressed={following ? 'true' : 'false'}>
           <Icon id={following ? 'user-times' : 'user-plus'} fixedWidth className='column-header__icon' />
         </button>
       );
@@ -208,6 +220,10 @@ class HashtagTimeline extends React.PureComponent {
           emptyMessage={<FormattedMessage id='empty_column.hashtag' defaultMessage='There is nothing in this hashtag yet.' />}
           bindToDocument={!multiColumn}
         />
+
+        <Helmet>
+          <title>{`#${id}`} - {title}</title>
+        </Helmet>
       </Column>
     );
   }
diff --git a/app/javascript/mastodon/features/public_timeline/index.js b/app/javascript/mastodon/features/public_timeline/index.js
index b1d5518af..2f926678c 100644
--- a/app/javascript/mastodon/features/public_timeline/index.js
+++ b/app/javascript/mastodon/features/public_timeline/index.js
@@ -9,6 +9,8 @@ import { expandPublicTimeline } from '../../actions/timelines';
 import { addColumn, removeColumn, moveColumn } from '../../actions/columns';
 import ColumnSettingsContainer from './containers/column_settings_container';
 import { connectPublicStream } from '../../actions/streaming';
+import { Helmet } from 'react-helmet';
+import { title } from 'mastodon/initial_state';
 
 const messages = defineMessages({
   title: { id: 'column.public', defaultMessage: 'Federated timeline' },
@@ -131,6 +133,10 @@ class PublicTimeline extends React.PureComponent {
           emptyMessage={<FormattedMessage id='empty_column.public' defaultMessage='There is nothing here! Write something publicly, or manually follow users from other servers to fill it up' />}
           bindToDocument={!multiColumn}
         />
+
+        <Helmet>
+          <title>{intl.formatMessage(messages.title)} - {title}</title>
+        </Helmet>
       </Column>
     );
   }
diff --git a/app/javascript/mastodon/features/report/components/status_check_box.js b/app/javascript/mastodon/features/report/components/status_check_box.js
index 373c60e21..5366da90b 100644
--- a/app/javascript/mastodon/features/report/components/status_check_box.js
+++ b/app/javascript/mastodon/features/report/components/status_check_box.js
@@ -7,14 +7,25 @@ import DisplayName from 'mastodon/components/display_name';
 import RelativeTimestamp from 'mastodon/components/relative_timestamp';
 import Option from './option';
 import MediaAttachments from 'mastodon/components/media_attachments';
+import { injectIntl, defineMessages } from 'react-intl';
+import Icon from 'mastodon/components/icon';
 
-export default class StatusCheckBox extends React.PureComponent {
+const messages = defineMessages({
+  public_short: { id: 'privacy.public.short', defaultMessage: 'Public' },
+  unlisted_short: { id: 'privacy.unlisted.short', defaultMessage: 'Unlisted' },
+  private_short: { id: 'privacy.private.short', defaultMessage: 'Followers-only' },
+  direct_short: { id: 'privacy.direct.short', defaultMessage: 'Mentioned people only' },
+});
+
+export default @injectIntl
+class StatusCheckBox extends React.PureComponent {
 
   static propTypes = {
     id: PropTypes.string.isRequired,
     status: ImmutablePropTypes.map.isRequired,
     checked: PropTypes.bool,
     onToggle: PropTypes.func.isRequired,
+    intl: PropTypes.object.isRequired,
   };
 
   handleStatusesToggle = (value, checked) => {
@@ -23,12 +34,21 @@ export default class StatusCheckBox extends React.PureComponent {
   };
 
   render () {
-    const { status, checked } = this.props;
+    const { status, checked, intl } = this.props;
 
     if (status.get('reblog')) {
       return null;
     }
 
+    const visibilityIconInfo = {
+      'public': { icon: 'globe', text: intl.formatMessage(messages.public_short) },
+      'unlisted': { icon: 'unlock', text: intl.formatMessage(messages.unlisted_short) },
+      'private': { icon: 'lock', text: intl.formatMessage(messages.private_short) },
+      'direct': { icon: 'at', text: intl.formatMessage(messages.direct_short) },
+    };
+
+    const visibilityIcon = visibilityIconInfo[status.get('visibility')];
+
     const labelComponent = (
       <div className='status-check-box__status poll__option__text'>
         <div className='detailed-status__display-name'>
@@ -37,7 +57,7 @@ export default class StatusCheckBox extends React.PureComponent {
           </div>
 
           <div>
-            <DisplayName account={status.get('account')} /> · <RelativeTimestamp timestamp={status.get('created_at')} />
+            <DisplayName account={status.get('account')} /> · <span className='status__visibility-icon'><Icon id={visibilityIcon.icon} title={visibilityIcon.text} /></span> <RelativeTimestamp timestamp={status.get('created_at')} />
           </div>
         </div>
 
diff --git a/app/javascript/mastodon/features/status/components/detailed_status.js b/app/javascript/mastodon/features/status/components/detailed_status.js
index 5c43c2038..320a847f7 100644
--- a/app/javascript/mastodon/features/status/components/detailed_status.js
+++ b/app/javascript/mastodon/features/status/components/detailed_status.js
@@ -37,6 +37,7 @@ class DetailedStatus extends ImmutablePureComponent {
     onOpenMedia: PropTypes.func.isRequired,
     onOpenVideo: PropTypes.func.isRequired,
     onToggleHidden: PropTypes.func.isRequired,
+    onTranslate: PropTypes.func.isRequired,
     measureHeight: PropTypes.bool,
     onHeightChange: PropTypes.func,
     domain: PropTypes.string.isRequired,
@@ -103,6 +104,11 @@ class DetailedStatus extends ImmutablePureComponent {
     window.open(href, 'mastodon-intent', 'width=445,height=600,resizable=no,menubar=no,status=no,scrollbars=yes');
   }
 
+  handleTranslate = () => {
+    const { onTranslate, status } = this.props;
+    onTranslate(status);
+  }
+
   render () {
     const status = (this.props.status && this.props.status.get('reblog')) ? this.props.status.get('reblog') : this.props.status;
     const outerStyle = { boxSizing: 'border-box' };
@@ -260,7 +266,12 @@ class DetailedStatus extends ImmutablePureComponent {
             <DisplayName account={status.get('account')} localDomain={this.props.domain} />
           </a>
 
-          <StatusContent status={status} expanded={!status.get('hidden')} onExpandedToggle={this.handleExpandedToggle} />
+          <StatusContent
+            status={status}
+            expanded={!status.get('hidden')}
+            onExpandedToggle={this.handleExpandedToggle}
+            onTranslate={this.handleTranslate}
+          />
 
           {media}
 
diff --git a/app/javascript/mastodon/features/status/index.js b/app/javascript/mastodon/features/status/index.js
index 4d7f24834..748dc7a92 100644
--- a/app/javascript/mastodon/features/status/index.js
+++ b/app/javascript/mastodon/features/status/index.js
@@ -32,6 +32,8 @@ import {
   editStatus,
   hideStatus,
   revealStatus,
+  translateStatus,
+  undoStatusTranslation,
 } from '../../actions/statuses';
 import {
   unblockAccount,
@@ -54,10 +56,11 @@ import { openModal } from '../../actions/modal';
 import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
 import ImmutablePureComponent from 'react-immutable-pure-component';
 import { HotKeys } from 'react-hotkeys';
-import { boostModal, deleteModal } from '../../initial_state';
+import { boostModal, deleteModal, title } from '../../initial_state';
 import { attachFullscreenListener, detachFullscreenListener, isFullscreen } from '../ui/util/fullscreen';
 import { textForScreenReader, defaultMediaVisibility } from '../../components/status';
 import Icon from 'mastodon/components/icon';
+import { Helmet } from 'react-helmet';
 
 const messages = defineMessages({
   deleteConfirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' },
@@ -154,6 +157,23 @@ const makeMapStateToProps = () => {
   return mapStateToProps;
 };
 
+const truncate = (str, num) => {
+  if (str.length > num) {
+    return str.slice(0, num) + '…';
+  } else {
+    return str;
+  }
+};
+
+const titleFromStatus = status => {
+  const displayName = status.getIn(['account', 'display_name']);
+  const username = status.getIn(['account', 'username']);
+  const prefix = displayName.trim().length === 0 ? username : displayName;
+  const text = status.get('search_index');
+
+  return `${prefix}: "${truncate(text, 30)}"`;
+};
+
 export default @injectIntl
 @connect(makeMapStateToProps)
 class Status extends ImmutablePureComponent {
@@ -339,6 +359,16 @@ class Status extends ImmutablePureComponent {
     }
   }
 
+  handleTranslate = status => {
+    const { dispatch } = this.props;
+
+    if (status.get('translation')) {
+      dispatch(undoStatusTranslation(status.get('id')));
+    } else {
+      dispatch(translateStatus(status.get('id')));
+    }
+  }
+
   handleBlockClick = (status) => {
     const { dispatch } = this.props;
     const account = status.get('account');
@@ -558,6 +588,7 @@ class Status extends ImmutablePureComponent {
                   onOpenVideo={this.handleOpenVideo}
                   onOpenMedia={this.handleOpenMedia}
                   onToggleHidden={this.handleToggleHidden}
+                  onTranslate={this.handleTranslate}
                   domain={domain}
                   showMedia={this.state.showMedia}
                   onToggleMediaVisibility={this.handleToggleMediaVisibility}
@@ -592,6 +623,10 @@ class Status extends ImmutablePureComponent {
             {descendants}
           </div>
         </ScrollContainer>
+
+        <Helmet>
+          <title>{titleFromStatus(status)} - {title}</title>
+        </Helmet>
       </Column>
     );
   }
diff --git a/app/javascript/mastodon/features/subscribed_languages_modal/index.js b/app/javascript/mastodon/features/subscribed_languages_modal/index.js
new file mode 100644
index 000000000..6a1bb2c47
--- /dev/null
+++ b/app/javascript/mastodon/features/subscribed_languages_modal/index.js
@@ -0,0 +1,121 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import ImmutablePureComponent from 'react-immutable-pure-component';
+import ImmutablePropTypes from 'react-immutable-proptypes';
+import { connect } from 'react-redux';
+import { createSelector } from 'reselect';
+import { is, List as ImmutableList, Set as ImmutableSet } from 'immutable';
+import { languages as preloadedLanguages } from 'mastodon/initial_state';
+import Option from 'mastodon/features/report/components/option';
+import { defineMessages, FormattedMessage, injectIntl } from 'react-intl';
+import IconButton from 'mastodon/components/icon_button';
+import Button from 'mastodon/components/button';
+import { followAccount } from 'mastodon/actions/accounts';
+
+const messages = defineMessages({
+  close: { id: 'lightbox.close', defaultMessage: 'Close' },
+});
+
+const getAccountLanguages = createSelector([
+  (state, accountId) => state.getIn(['timelines', `account:${accountId}`, 'items'], ImmutableList()),
+  state => state.get('statuses'),
+], (statusIds, statuses) =>
+  new ImmutableSet(statusIds.map(statusId => statuses.get(statusId)).filter(status => !status.get('reblog')).map(status => status.get('language'))));
+
+const mapStateToProps = (state, { accountId }) => ({
+  acct: state.getIn(['accounts', accountId, 'acct']),
+  availableLanguages: getAccountLanguages(state, accountId),
+  selectedLanguages: ImmutableSet(state.getIn(['relationships', accountId, 'languages']) || ImmutableList()),
+});
+
+const mapDispatchToProps = (dispatch, { accountId }) => ({
+
+  onSubmit (languages) {
+    dispatch(followAccount(accountId, { languages }));
+  },
+
+});
+
+export default @connect(mapStateToProps, mapDispatchToProps)
+@injectIntl
+class SubscribedLanguagesModal extends ImmutablePureComponent {
+
+  static propTypes = {
+    accountId: PropTypes.string.isRequired,
+    acct: PropTypes.string.isRequired,
+    availableLanguages: ImmutablePropTypes.setOf(PropTypes.string),
+    selectedLanguages: ImmutablePropTypes.setOf(PropTypes.string),
+    onClose: PropTypes.func.isRequired,
+    languages: PropTypes.arrayOf(PropTypes.arrayOf(PropTypes.string)),
+    intl: PropTypes.object.isRequired,
+    submit: PropTypes.func.isRequired,
+  };
+
+  static defaultProps = {
+    languages: preloadedLanguages,
+  };
+
+  state = {
+    selectedLanguages: this.props.selectedLanguages,
+  };
+
+  handleLanguageToggle = (value, checked) => {
+    const { selectedLanguages } = this.state;
+
+    if (checked) {
+      this.setState({ selectedLanguages: selectedLanguages.add(value) });
+    } else {
+      this.setState({ selectedLanguages: selectedLanguages.delete(value) });
+    }
+  };
+
+  handleSubmit = () => {
+    this.props.onSubmit(this.state.selectedLanguages.toArray());
+    this.props.onClose();
+  }
+
+  renderItem (value) {
+    const language = this.props.languages.find(language => language[0] === value);
+    const checked = this.state.selectedLanguages.includes(value);
+
+    return (
+      <Option
+        key={value}
+        name='languages'
+        value={value}
+        label={language[1]}
+        checked={checked}
+        onToggle={this.handleLanguageToggle}
+        multiple
+      />
+    );
+  }
+
+  render () {
+    const { acct, availableLanguages, selectedLanguages, intl, onClose } = this.props;
+
+    return (
+      <div className='modal-root__modal report-dialog-modal'>
+        <div className='report-modal__target'>
+          <IconButton className='report-modal__close' title={intl.formatMessage(messages.close)} icon='times' onClick={onClose} size={20} />
+          <FormattedMessage id='subscribed_languages.target' defaultMessage='Change subscribed languages for {target}' values={{ target: <strong>{acct}</strong> }} />
+        </div>
+
+        <div className='report-dialog-modal__container'>
+          <p className='report-dialog-modal__lead'><FormattedMessage id='subscribed_languages.lead' defaultMessage='Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.' /></p>
+
+          <div>
+            {availableLanguages.union(selectedLanguages).map(value => this.renderItem(value))}
+          </div>
+
+          <div className='flex-spacer' />
+
+          <div className='report-dialog-modal__actions'>
+            <Button disabled={is(this.state.selectedLanguages, this.props.selectedLanguages)} onClick={this.handleSubmit}><FormattedMessage id='subscribed_languages.save' defaultMessage='Save changes' /></Button>
+          </div>
+        </div>
+      </div>
+    );
+  }
+
+}
diff --git a/app/javascript/mastodon/features/ui/components/columns_area.js b/app/javascript/mastodon/features/ui/components/columns_area.js
index 68017a5f1..83e10e003 100644
--- a/app/javascript/mastodon/features/ui/components/columns_area.js
+++ b/app/javascript/mastodon/features/ui/components/columns_area.js
@@ -60,6 +60,7 @@ class ColumnsArea extends ImmutablePureComponent {
 
   static contextTypes = {
     router: PropTypes.object.isRequired,
+    identity: PropTypes.object.isRequired,
   };
 
   static propTypes = {
@@ -212,11 +213,12 @@ class ColumnsArea extends ImmutablePureComponent {
   render () {
     const { columns, children, singleColumn, isModalOpen, intl } = this.props;
     const { shouldAnimate, renderComposePanel } = this.state;
+    const { signedIn } = this.context.identity;
 
     const columnIndex = getIndex(this.context.router.history.location.pathname);
 
     if (singleColumn) {
-      const floatingActionButton = shouldHideFAB(this.context.router.history.location.pathname) ? null : <Link key='floating-action-button' to='/publish' className='floating-action-button' aria-label={intl.formatMessage(messages.publish)}><Icon id='pencil' /></Link>;
+      const floatingActionButton = (!signedIn || shouldHideFAB(this.context.router.history.location.pathname)) ? null : <Link key='floating-action-button' to='/publish' className='floating-action-button' aria-label={intl.formatMessage(messages.publish)}><Icon id='pencil' /></Link>;
 
       const content = columnIndex !== -1 ? (
         <ReactSwipeableViews key='content' hysteresis={0.2} threshold={15} index={columnIndex} onChangeIndex={this.handleSwipe} onTransitionEnd={this.handleAnimationEnd} animateTransitions={shouldAnimate} springConfig={{ duration: '400ms', delay: '0s', easeFunction: 'ease' }} style={{ height: '100%' }} disabled={disableSwiping}>
diff --git a/app/javascript/mastodon/features/ui/components/compose_panel.js b/app/javascript/mastodon/features/ui/components/compose_panel.js
index 3d0c48c7a..1c128188f 100644
--- a/app/javascript/mastodon/features/ui/components/compose_panel.js
+++ b/app/javascript/mastodon/features/ui/components/compose_panel.js
@@ -10,6 +10,10 @@ import { changeComposing } from 'mastodon/actions/compose';
 export default @connect()
 class ComposePanel extends React.PureComponent {
 
+  static contextTypes = {
+    identity: PropTypes.object.isRequired,
+  };
+
   static propTypes = {
     dispatch: PropTypes.func.isRequired,
   };
@@ -23,11 +27,25 @@ class ComposePanel extends React.PureComponent {
   }
 
   render() {
+    const { signedIn } = this.context.identity;
+
     return (
       <div className='compose-panel' onFocus={this.onFocus}>
         <SearchContainer openInRoute />
-        <NavigationContainer onClose={this.onBlur} />
-        <ComposeFormContainer singleColumn />
+
+        {!signedIn && (
+          <React.Fragment>
+            <div className='flex-spacer' />
+          </React.Fragment>
+        )}
+
+        {signedIn && (
+          <React.Fragment>
+            <NavigationContainer onClose={this.onBlur} />
+            <ComposeFormContainer singleColumn />
+          </React.Fragment>
+        )}
+
         <LinkFooter withHotkeys />
       </div>
     );
diff --git a/app/javascript/mastodon/features/ui/components/document_title.js b/app/javascript/mastodon/features/ui/components/document_title.js
deleted file mode 100644
index cd081b20c..000000000
--- a/app/javascript/mastodon/features/ui/components/document_title.js
+++ /dev/null
@@ -1,41 +0,0 @@
-import { PureComponent } from 'react';
-import { connect } from 'react-redux';
-import PropTypes from 'prop-types';
-import { title } from 'mastodon/initial_state';
-
-const mapStateToProps = state => ({
-  unread: state.getIn(['missed_updates', 'unread']),
-});
-
-export default @connect(mapStateToProps)
-class DocumentTitle extends PureComponent {
-
-  static propTypes = {
-    unread: PropTypes.number.isRequired,
-  };
-
-  componentDidMount () {
-    this._sideEffects();
-  }
-
-  componentDidUpdate() {
-    this._sideEffects();
-  }
-
-  _sideEffects () {
-    const { unread } = this.props;
-
-    if (unread > 99) {
-      document.title = `(*) ${title}`;
-    } else if (unread > 0) {
-      document.title = `(${unread}) ${title}`;
-    } else {
-      document.title = title;
-    }
-  }
-
-  render () {
-    return null;
-  }
-
-}
diff --git a/app/javascript/mastodon/features/ui/components/link_footer.js b/app/javascript/mastodon/features/ui/components/link_footer.js
index bbb9b122a..dd05d03dd 100644
--- a/app/javascript/mastodon/features/ui/components/link_footer.js
+++ b/app/javascript/mastodon/features/ui/components/link_footer.js
@@ -49,20 +49,46 @@ class LinkFooter extends React.PureComponent {
 
   render () {
     const { withHotkeys } = this.props;
+    const { signedIn, permissions } = this.context.identity;
+    const items = [];
+
+    if ((permissions & PERMISSION_INVITE_USERS) === PERMISSION_INVITE_USERS) {
+      items.push(<a key='invites' href='/invites' target='_blank'><FormattedMessage id='getting_started.invite' defaultMessage='Invite people' /></a>);
+    }
+
+    if (signedIn && withHotkeys) {
+      items.push(<Link key='hotkeys' to='/keyboard-shortcuts'><FormattedMessage id='navigation_bar.keyboard_shortcuts' defaultMessage='Hotkeys' /></Link>);
+    }
+
+    if (signedIn) {
+      items.push(<a key='security' href='/auth/edit'><FormattedMessage id='getting_started.security' defaultMessage='Security' /></a>);
+    }
+
+    if (!limitedFederationMode) {
+      items.push(<a key='about' href='/about/more' target='_blank'><FormattedMessage id='navigation_bar.info' defaultMessage='About this server' /></a>);
+    }
+
+    if (profileDirectory) {
+      items.push(<Link key='directory' to='/directory'><FormattedMessage id='getting_started.directory' defaultMessage='Profile directory' /></Link>);
+    }
+
+    items.push(<a key='apps' href='https://joinmastodon.org/apps' target='_blank'><FormattedMessage id='navigation_bar.apps' defaultMessage='Mobile apps' /></a>);
+    items.push(<a key='privacy-policy' href='/privacy-policy' target='_blank'><FormattedMessage id='getting_started.privacy_policy' defaultMessage='Privacy Policy' /></a>);
+
+    if (signedIn) {
+      items.push(<a key='developers' href='/settings/applications' target='_blank'><FormattedMessage id='getting_started.developers' defaultMessage='Developers' /></a>);
+    }
+
+    items.push(<a key='docs' href='https://docs.joinmastodon.org' target='_blank'><FormattedMessage id='getting_started.documentation' defaultMessage='Documentation' /></a>);
+
+    if (signedIn) {
+      items.push(<a key='logout' href='/auth/sign_out' onClick={this.handleLogoutClick}><FormattedMessage id='navigation_bar.logout' defaultMessage='Logout' /></a>);
+    }
 
     return (
       <div className='getting-started__footer'>
         <ul>
-          {((this.context.identity.permissions & PERMISSION_INVITE_USERS) === PERMISSION_INVITE_USERS) && <li><a href='/invites' target='_blank'><FormattedMessage id='getting_started.invite' defaultMessage='Invite people' /></a> · </li>}
-          {withHotkeys && <li><Link to='/keyboard-shortcuts'><FormattedMessage id='navigation_bar.keyboard_shortcuts' defaultMessage='Hotkeys' /></Link> · </li>}
-          <li><a href='/auth/edit'><FormattedMessage id='getting_started.security' defaultMessage='Security' /></a> · </li>
-          {!limitedFederationMode && <li><a href='/about/more' target='_blank'><FormattedMessage id='navigation_bar.info' defaultMessage='About this server' /></a> · </li>}
-          {profileDirectory && <li><Link to='/directory'><FormattedMessage id='getting_started.directory' defaultMessage='Profile directory' /></Link> · </li>}
-          <li><a href='https://joinmastodon.org/apps' target='_blank'><FormattedMessage id='navigation_bar.apps' defaultMessage='Mobile apps' /></a> · </li>
-          <li><a href='/terms' target='_blank'><FormattedMessage id='getting_started.terms' defaultMessage='Terms of service' /></a> · </li>
-          <li><a href='/settings/applications' target='_blank'><FormattedMessage id='getting_started.developers' defaultMessage='Developers' /></a> · </li>
-          <li><a href='https://docs.joinmastodon.org' target='_blank'><FormattedMessage id='getting_started.documentation' defaultMessage='Documentation' /></a> · </li>
-          <li><a href='/auth/sign_out' onClick={this.handleLogoutClick}><FormattedMessage id='navigation_bar.logout' defaultMessage='Logout' /></a></li>
+          <li>{items.reduce((prev, curr) => [prev, ' · ', curr])}</li>
         </ul>
 
         <p>
diff --git a/app/javascript/mastodon/features/ui/components/modal_root.js b/app/javascript/mastodon/features/ui/components/modal_root.js
index b2c30e079..dfa89f2ce 100644
--- a/app/javascript/mastodon/features/ui/components/modal_root.js
+++ b/app/javascript/mastodon/features/ui/components/modal_root.js
@@ -11,6 +11,7 @@ import VideoModal from './video_modal';
 import BoostModal from './boost_modal';
 import AudioModal from './audio_modal';
 import ConfirmationModal from './confirmation_modal';
+import SubscribedLanguagesModal from 'mastodon/features/subscribed_languages_modal';
 import FocalPointModal from './focal_point_modal';
 import {
   MuteModal,
@@ -39,6 +40,7 @@ const MODAL_COMPONENTS = {
   'LIST_ADDER': ListAdder,
   'COMPARE_HISTORY': CompareHistoryModal,
   'FILTER': FilterModal,
+  'SUBSCRIBED_LANGUAGES': () => Promise.resolve({ default: SubscribedLanguagesModal }),
 };
 
 export default class ModalRoot extends React.PureComponent {
diff --git a/app/javascript/mastodon/features/ui/components/navigation_panel.js b/app/javascript/mastodon/features/ui/components/navigation_panel.js
index fe4ed5d77..00ae04761 100644
--- a/app/javascript/mastodon/features/ui/components/navigation_panel.js
+++ b/app/javascript/mastodon/features/ui/components/navigation_panel.js
@@ -1,5 +1,6 @@
 import React from 'react';
-import { NavLink, withRouter } from 'react-router-dom';
+import PropTypes from 'prop-types';
+import { NavLink, Link } from 'react-router-dom';
 import { FormattedMessage } from 'react-intl';
 import Icon from 'mastodon/components/icon';
 import { showTrends } from 'mastodon/initial_state';
@@ -7,30 +8,68 @@ import NotificationsCounterIcon from './notifications_counter_icon';
 import FollowRequestsNavLink from './follow_requests_nav_link';
 import ListPanel from './list_panel';
 import TrendsContainer from 'mastodon/features/getting_started/containers/trends_container';
+import Logo from 'mastodon/components/logo';
+import SignInBanner from './sign_in_banner';
 
-const NavigationPanel = () => (
-  <div className='navigation-panel'>
-    <NavLink className='column-link column-link--transparent' to='/home' data-preview-title-id='column.home' data-preview-icon='home' ><Icon className='column-link__icon' id='home' fixedWidth /><FormattedMessage id='tabs_bar.home' defaultMessage='Home' /></NavLink>
-    <NavLink className='column-link column-link--transparent' to='/notifications' data-preview-title-id='column.notifications' data-preview-icon='bell' ><NotificationsCounterIcon className='column-link__icon' /><FormattedMessage id='tabs_bar.notifications' defaultMessage='Notifications' /></NavLink>
-    <FollowRequestsNavLink />
-    <NavLink className='column-link column-link--transparent' to='/explore' data-preview-title-id='explore.title' data-preview-icon='hashtag'><Icon className='column-link__icon' id='hashtag' fixedWidth /><FormattedMessage id='explore.title' defaultMessage='Explore' /></NavLink>
-    <NavLink className='column-link column-link--transparent' to='/public/local' data-preview-title-id='column.community' data-preview-icon='users' ><Icon className='column-link__icon' id='users' fixedWidth /><FormattedMessage id='tabs_bar.local_timeline' defaultMessage='Local' /></NavLink>
-    <NavLink className='column-link column-link--transparent' exact to='/public' data-preview-title-id='column.public' data-preview-icon='globe' ><Icon className='column-link__icon' id='globe' fixedWidth /><FormattedMessage id='tabs_bar.federated_timeline' defaultMessage='Federated' /></NavLink>
-    <NavLink className='column-link column-link--transparent' to='/conversations'><Icon className='column-link__icon' id='at' fixedWidth /><FormattedMessage id='navigation_bar.direct' defaultMessage='Direct messages' /></NavLink>
-    <NavLink className='column-link column-link--transparent' to='/favourites'><Icon className='column-link__icon' id='star' fixedWidth /><FormattedMessage id='navigation_bar.favourites' defaultMessage='Favourites' /></NavLink>
-    <NavLink className='column-link column-link--transparent' to='/bookmarks'><Icon className='column-link__icon' id='bookmark' fixedWidth /><FormattedMessage id='navigation_bar.bookmarks' defaultMessage='Bookmarks' /></NavLink>
-    <NavLink className='column-link column-link--transparent' to='/lists'><Icon className='column-link__icon' id='list-ul' fixedWidth /><FormattedMessage id='navigation_bar.lists' defaultMessage='Lists' /></NavLink>
+export default class NavigationPanel extends React.Component {
 
-    <ListPanel />
+  static contextTypes = {
+    router: PropTypes.object.isRequired,
+    identity: PropTypes.object.isRequired,
+  };
 
-    <hr />
+  render () {
+    const { signedIn } = this.context.identity;
 
-    <a className='column-link column-link--transparent' href='/settings/preferences'><Icon className='column-link__icon' id='cog' fixedWidth /><FormattedMessage id='navigation_bar.preferences' defaultMessage='Preferences' /></a>
-    <a className='column-link column-link--transparent' href='/relationships'><Icon className='column-link__icon' id='users' fixedWidth /><FormattedMessage id='navigation_bar.follows_and_followers' defaultMessage='Follows and followers' /></a>
+    return (
+      <div className='navigation-panel'>
+        <Link to='/' className='column-link column-link--logo'><Logo /></Link>
 
-    {showTrends && <div className='flex-spacer' />}
-    {showTrends && <TrendsContainer />}
-  </div>
-);
+        <hr />
 
-export default withRouter(NavigationPanel);
+        {signedIn && (
+          <React.Fragment>
+            <NavLink className='column-link column-link--transparent' to='/home' data-preview-title-id='column.home' data-preview-icon='home' ><Icon className='column-link__icon' id='home' fixedWidth /><FormattedMessage id='tabs_bar.home' defaultMessage='Home' /></NavLink>
+            <NavLink className='column-link column-link--transparent' to='/notifications' data-preview-title-id='column.notifications' data-preview-icon='bell' ><NotificationsCounterIcon className='column-link__icon' /><FormattedMessage id='tabs_bar.notifications' defaultMessage='Notifications' /></NavLink>
+            <FollowRequestsNavLink />
+          </React.Fragment>
+        )}
+
+        <NavLink className='column-link column-link--transparent' to='/explore' data-preview-title-id='explore.title' data-preview-icon='hashtag'><Icon className='column-link__icon' id='hashtag' fixedWidth /><FormattedMessage id='explore.title' defaultMessage='Explore' /></NavLink>
+        <NavLink className='column-link column-link--transparent' to='/public/local' data-preview-title-id='column.community' data-preview-icon='users' ><Icon className='column-link__icon' id='users' fixedWidth /><FormattedMessage id='tabs_bar.local_timeline' defaultMessage='Local' /></NavLink>
+        <NavLink className='column-link column-link--transparent' exact to='/public' data-preview-title-id='column.public' data-preview-icon='globe' ><Icon className='column-link__icon' id='globe' fixedWidth /><FormattedMessage id='tabs_bar.federated_timeline' defaultMessage='Federated' /></NavLink>
+
+        {!signedIn && (
+          <React.Fragment>
+            <hr />
+            <SignInBanner />
+          </React.Fragment>
+        )}
+
+        {signedIn && (
+          <React.Fragment>
+            <NavLink className='column-link column-link--transparent' to='/conversations'><Icon className='column-link__icon' id='at' fixedWidth /><FormattedMessage id='navigation_bar.direct' defaultMessage='Direct messages' /></NavLink>
+            <NavLink className='column-link column-link--transparent' to='/favourites'><Icon className='column-link__icon' id='star' fixedWidth /><FormattedMessage id='navigation_bar.favourites' defaultMessage='Favourites' /></NavLink>
+            <NavLink className='column-link column-link--transparent' to='/bookmarks'><Icon className='column-link__icon' id='bookmark' fixedWidth /><FormattedMessage id='navigation_bar.bookmarks' defaultMessage='Bookmarks' /></NavLink>
+            <NavLink className='column-link column-link--transparent' to='/lists'><Icon className='column-link__icon' id='list-ul' fixedWidth /><FormattedMessage id='navigation_bar.lists' defaultMessage='Lists' /></NavLink>
+
+            <ListPanel />
+
+            <hr />
+
+            <a className='column-link column-link--transparent' href='/settings/preferences'><Icon className='column-link__icon' id='cog' fixedWidth /><FormattedMessage id='navigation_bar.preferences' defaultMessage='Preferences' /></a>
+            <a className='column-link column-link--transparent' href='/relationships'><Icon className='column-link__icon' id='users' fixedWidth /><FormattedMessage id='navigation_bar.follows_and_followers' defaultMessage='Follows and followers' /></a>
+          </React.Fragment>
+        )}
+
+        {showTrends && (
+          <React.Fragment>
+            <div className='flex-spacer' />
+            <TrendsContainer />
+          </React.Fragment>
+        )}
+      </div>
+    );
+  }
+
+}
diff --git a/app/javascript/mastodon/features/ui/components/sign_in_banner.js b/app/javascript/mastodon/features/ui/components/sign_in_banner.js
new file mode 100644
index 000000000..5ff4ee2a8
--- /dev/null
+++ b/app/javascript/mastodon/features/ui/components/sign_in_banner.js
@@ -0,0 +1,13 @@
+import React from 'react';
+import { FormattedMessage } from 'react-intl';
+import { registrationsOpen } from 'mastodon/initial_state';
+
+const SignInBanner = () => (
+  <div className='sign-in-banner'>
+    <p><FormattedMessage id='sign_in_banner.text' defaultMessage='Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.' /></p>
+    <a href='/auth/sign_in' className='button button--block'><FormattedMessage id='sign_in_banner.sign_in' defaultMessage='Sign in' /></a>
+    <a href={registrationsOpen ? '/auth/sign_up' : 'https://joinmastodon.org/servers'} className='button button--block button-tertiary'><FormattedMessage id='sign_in_banner.create_account' defaultMessage='Create account' /></a>
+  </div>
+);
+
+export default SignInBanner;
diff --git a/app/javascript/mastodon/features/ui/index.js b/app/javascript/mastodon/features/ui/index.js
index 9a901f12a..5825db1e4 100644
--- a/app/javascript/mastodon/features/ui/index.js
+++ b/app/javascript/mastodon/features/ui/index.js
@@ -20,7 +20,6 @@ import { synchronouslySubmitMarkers, submitMarkers, fetchMarkers } from 'mastodo
 import { WrappedSwitch, WrappedRoute } from './util/react_router_helpers';
 import UploadArea from './components/upload_area';
 import ColumnsAreaContainer from './containers/columns_area_container';
-import DocumentTitle from './components/document_title';
 import PictureInPicture from 'mastodon/features/picture_in_picture';
 import {
   Compose,
@@ -53,8 +52,9 @@ import {
   Explore,
   FollowRecommendations,
 } from './util/async-components';
-import { me } from '../../initial_state';
+import { me, title } from '../../initial_state';
 import { closeOnboarding, INTRODUCTION_VERSION } from 'mastodon/actions/onboarding';
+import { Helmet } from 'react-helmet';
 
 // Dummy import, to make sure that <Status /> ends up in the application bundle.
 // Without this it ends up in ~8 very commonly used bundles.
@@ -110,6 +110,10 @@ const keyMap = {
 
 class SwitchingColumnsArea extends React.PureComponent {
 
+  static contextTypes = {
+    identity: PropTypes.object,
+  };
+
   static propTypes = {
     children: PropTypes.node,
     location: PropTypes.object,
@@ -145,12 +149,25 @@ class SwitchingColumnsArea extends React.PureComponent {
 
   render () {
     const { children, mobile } = this.props;
-    const redirect = mobile ? <Redirect from='/' to='/home' exact /> : <Redirect from='/' to='/getting-started' exact />;
+    const { signedIn } = this.context.identity;
+
+    let redirect;
+
+    if (signedIn) {
+      if (mobile) {
+        redirect = <Redirect from='/' to='/home' exact />;
+      } else {
+        redirect = <Redirect from='/' to='/getting-started' exact />;
+      }
+    } else {
+      redirect = <Redirect from='/' to='/explore' exact />;
+    }
 
     return (
       <ColumnsAreaContainer ref={this.setRef} singleColumn={mobile}>
         <WrappedSwitch>
           {redirect}
+
           <WrappedRoute path='/getting-started' component={GettingStarted} content={children} />
           <WrappedRoute path='/keyboard-shortcuts' component={KeyboardShortcuts} content={children} />
 
@@ -208,6 +225,7 @@ class UI extends React.PureComponent {
 
   static contextTypes = {
     router: PropTypes.object.isRequired,
+    identity: PropTypes.object.isRequired,
   };
 
   static propTypes = {
@@ -343,6 +361,8 @@ class UI extends React.PureComponent {
   }
 
   componentDidMount () {
+    const { signedIn } = this.context.identity;
+
     window.addEventListener('focus', this.handleWindowFocus, false);
     window.addEventListener('blur', this.handleWindowBlur, false);
     window.addEventListener('beforeunload', this.handleBeforeUnload, false);
@@ -359,16 +379,18 @@ class UI extends React.PureComponent {
     }
 
     // On first launch, redirect to the follow recommendations page
-    if (this.props.firstLaunch) {
+    if (signedIn && this.props.firstLaunch) {
       this.context.router.history.replace('/start');
       this.props.dispatch(closeOnboarding());
     }
 
-    this.props.dispatch(fetchMarkers());
-    this.props.dispatch(expandHomeTimeline());
-    this.props.dispatch(expandNotifications());
+    if (signedIn) {
+      this.props.dispatch(fetchMarkers());
+      this.props.dispatch(expandHomeTimeline());
+      this.props.dispatch(expandNotifications());
 
-    setTimeout(() => this.props.dispatch(fetchRules()), 3000);
+      setTimeout(() => this.props.dispatch(fetchRules()), 3000);
+    }
 
     this.hotkeys.__mousetrap__.stopCallback = (e, element) => {
       return ['TEXTAREA', 'SELECT', 'INPUT'].includes(element.tagName);
@@ -546,7 +568,10 @@ class UI extends React.PureComponent {
           <LoadingBarContainer className='loading-bar' />
           <ModalContainer />
           <UploadArea active={draggingOver} onClose={this.closeUploadModal} />
-          <DocumentTitle />
+
+          <Helmet>
+            <title>{title}</title>
+          </Helmet>
         </div>
       </HotKeys>
     );
diff --git a/app/javascript/mastodon/initial_state.js b/app/javascript/mastodon/initial_state.js
index b1dd07f61..3587bb32a 100644
--- a/app/javascript/mastodon/initial_state.js
+++ b/app/javascript/mastodon/initial_state.js
@@ -3,6 +3,7 @@ const initialState = element && JSON.parse(element.textContent);
 
 const getMeta = (prop) => initialState && initialState.meta && initialState.meta[prop];
 
+export const domain = getMeta('domain');
 export const reduceMotion = getMeta('reduce_motion');
 export const autoPlayGif = getMeta('auto_play_gif');
 export const displayMedia = getMeta('display_media');
@@ -14,6 +15,7 @@ export const me = getMeta('me');
 export const searchEnabled = getMeta('search_enabled');
 export const maxChars = (initialState && initialState.max_toot_chars) || 500;
 export const limitedFederationMode = getMeta('limited_federation_mode');
+export const registrationsOpen = getMeta('registrations_open');
 export const repository = getMeta('repository');
 export const source_url = getMeta('source_url');
 export const version = getMeta('version');
@@ -27,5 +29,6 @@ export const title = getMeta('title');
 export const cropImages = getMeta('crop_images');
 export const disableSwiping = getMeta('disable_swiping');
 export const languages = initialState && initialState.languages;
+export const server = initialState && initialState.server;
 
 export default initialState;
diff --git a/app/javascript/mastodon/locales/af.json b/app/javascript/mastodon/locales/af.json
index 86d590654..54780cc9f 100644
--- a/app/javascript/mastodon/locales/af.json
+++ b/app/javascript/mastodon/locales/af.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Volg jou",
   "account.hide_reblogs": "Versteek hupstoot vanaf @{name}",
   "account.joined": "{date} aangesluit",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "Eienaarskap van die skakel was getoets op {date}",
   "account.locked_info": "Die rekening se privaatheidstatus is gesluit. Die eienaar hersien handmatig wie hom/haar kan volg.",
   "account.media": "Media",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Getting started",
   "getting_started.invite": "Invite people",
   "getting_started.open_source_notice": "Mastodon is open source software. You can contribute or report issues on GitHub at {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Security",
-  "getting_started.terms": "Terms of service",
   "hashtag.column_header.tag_mode.all": "and {additional}",
   "hashtag.column_header.tag_mode.any": "or {additional}",
   "hashtag.column_header.tag_mode.none": "without {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Could not find anything for these search terms",
   "search_results.statuses": "Toots",
   "search_results.statuses_fts_disabled": "Searching toots by their content is not enabled on this Mastodon server.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {result} other {results}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Open moderation interface for @{name}",
   "status.admin_status": "Open this status in the moderation interface",
   "status.block": "Block @{name}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Show less for all",
   "status.show_more": "Show more",
   "status.show_more_all": "Show more for all",
+  "status.show_original": "Show original",
   "status.show_thread": "Show thread",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "Not available",
   "status.unmute_conversation": "Unmute conversation",
   "status.unpin": "Unpin from profile",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "Dismiss suggestion",
   "suggestions.header": "You might be interested in…",
   "tabs_bar.federated_timeline": "Federated",
diff --git a/app/javascript/mastodon/locales/ar.json b/app/javascript/mastodon/locales/ar.json
index 220aa14ee..d2709c957 100644
--- a/app/javascript/mastodon/locales/ar.json
+++ b/app/javascript/mastodon/locales/ar.json
@@ -24,6 +24,7 @@
   "account.follows_you": "يُتابِعُك",
   "account.hide_reblogs": "إخفاء مشاركات @{name}",
   "account.joined": "انضم في {date}",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "تمَّ التَّحقق مِن مِلْكيّة هذا الرابط بتاريخ {date}",
   "account.locked_info": "تمَّ تعيين حالة خصوصية هذا الحساب إلى مُقفَل. يُراجع المالك يدويًا من يمكنه متابعته.",
   "account.media": "وسائط",
@@ -59,7 +60,7 @@
   "alert.unexpected.title": "المعذرة!",
   "announcement.announcement": "إعلان",
   "attachments_list.unprocessed": "(غير معالَج)",
-  "audio.hide": "Hide audio",
+  "audio.hide": "إخفاء المقطع الصوتي",
   "autosuggest_hashtag.per_week": "{count} في الأسبوع",
   "boost_modal.combo": "يُمكنك الضّغط على {combo} لتخطي هذا في المرة المُقبلة",
   "bundle_column_error.body": "لقد حدث خطأ ما أثناء تحميل هذا العنصر.",
@@ -203,7 +204,7 @@
   "filter_modal.added.expired_title": "Expired filter!",
   "filter_modal.added.review_and_configure": "To review and further configure this filter category, go to the {settings_link}.",
   "filter_modal.added.review_and_configure_title": "Filter settings",
-  "filter_modal.added.settings_link": "settings page",
+  "filter_modal.added.settings_link": "صفحة الإعدادات",
   "filter_modal.added.short_explanation": "This post has been added to the following filter category: {title}.",
   "filter_modal.added.title": "Filter added!",
   "filter_modal.select_filter.context_mismatch": "does not apply to this context",
@@ -226,8 +227,8 @@
   "getting_started.heading": "استعدّ للبدء",
   "getting_started.invite": "دعوة أشخاص",
   "getting_started.open_source_notice": "ماستدون برنامج مفتوح المصدر. يمكنك المساهمة، أو الإبلاغ عن تقارير الأخطاء، على جيت هب {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "الأمان",
-  "getting_started.terms": "شروط الخدمة",
   "hashtag.column_header.tag_mode.all": "و {additional}",
   "hashtag.column_header.tag_mode.any": "أو {additional}",
   "hashtag.column_header.tag_mode.none": "بدون {additional}",
@@ -347,7 +348,7 @@
   "notification.update": "عدّلَ {name} منشورًا",
   "notifications.clear": "امسح الإخطارات",
   "notifications.clear_confirmation": "أمتأكد من أنك تود مسح جل الإخطارات الخاصة بك و المتلقاة إلى حد الآن ؟",
-  "notifications.column_settings.admin.report": "New reports:",
+  "notifications.column_settings.admin.report": "التقارير الجديدة:",
   "notifications.column_settings.admin.sign_up": "التسجيلات الجديدة:",
   "notifications.column_settings.alert": "إشعارات سطح المكتب",
   "notifications.column_settings.favourite": "المُفَضَّلة:",
@@ -454,8 +455,8 @@
   "report.unfollow": "إلغاء متابعة @{name}",
   "report.unfollow_explanation": "أنت تتابع هذا الحساب، لإزالة مَنشوراته من تغذيَتِكَ الرئيسة ألغ متابعته.",
   "report_notification.attached_statuses": "{count, plural, one {{count} post} other {{count} posts}} attached",
-  "report_notification.categories.other": "Other",
-  "report_notification.categories.spam": "Spam",
+  "report_notification.categories.other": "آخر",
+  "report_notification.categories.spam": "مزعج",
   "report_notification.categories.violation": "Rule violation",
   "report_notification.open": "Open report",
   "search.placeholder": "ابحث",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "تعذر العثور على نتائج تتضمن هذه المصطلحات",
   "search_results.statuses": "المنشورات",
   "search_results.statuses_fts_disabled": "البحث عن المنشورات عن طريق المحتوى ليس مفعل في خادم ماستدون هذا.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, zero {} one {نتيجة} two {نتيجتين} few {نتائج} many {نتائج} other {نتائج}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "افتح الواجهة الإدارية لـ @{name}",
   "status.admin_status": "افتح هذا المنشور على واجهة الإشراف",
   "status.block": "احجب @{name}",
@@ -489,7 +494,7 @@
   "status.favourite": "أضف إلى المفضلة",
   "status.filter": "Filter this post",
   "status.filtered": "مُصفّى",
-  "status.hide": "Hide toot",
+  "status.hide": "اخف التبويق",
   "status.history.created": "أنشأه {name} {date}",
   "status.history.edited": "عدله {name} {date}",
   "status.load_more": "حمّل المزيد",
@@ -513,15 +518,21 @@
   "status.report": "ابلِغ عن @{name}",
   "status.sensitive_warning": "محتوى حساس",
   "status.share": "مشاركة",
-  "status.show_filter_reason": "Show anyway",
+  "status.show_filter_reason": "إظهار على أي حال",
   "status.show_less": "اعرض أقلّ",
   "status.show_less_all": "طي الكل",
   "status.show_more": "أظهر المزيد",
   "status.show_more_all": "توسيع الكل",
+  "status.show_original": "Show original",
   "status.show_thread": "الكشف عن المحادثة",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "غير متوفر",
   "status.unmute_conversation": "فك الكتم عن المحادثة",
   "status.unpin": "فك التدبيس من الصفحة التعريفية",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "حفظ التغييرات",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "إلغاء الاقتراح",
   "suggestions.header": "يمكن أن يهمك…",
   "tabs_bar.federated_timeline": "الموحَّد",
diff --git a/app/javascript/mastodon/locales/ast.json b/app/javascript/mastodon/locales/ast.json
index dba626299..acf1495b4 100644
--- a/app/javascript/mastodon/locales/ast.json
+++ b/app/javascript/mastodon/locales/ast.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Síguete",
   "account.hide_reblogs": "Anubrir les comparticiones de @{name}",
   "account.joined": "Joined {date}",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "La propiedá d'esti enllaz foi comprobada'l {date}",
   "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.",
   "account.media": "Media",
@@ -93,8 +94,8 @@
   "community.column_settings.local_only": "Local only",
   "community.column_settings.media_only": "Namái multimedia",
   "community.column_settings.remote_only": "Remote only",
-  "compose.language.change": "Change language",
-  "compose.language.search": "Search languages...",
+  "compose.language.change": "Camudar la llingua",
+  "compose.language.search": "Buscar llingües…",
   "compose_form.direct_message_warning_learn_more": "Saber más",
   "compose_form.encryption_warning": "Posts on Mastodon are not end-to-end encrypted. Do not share any dangerous information over Mastodon.",
   "compose_form.hashtag_warning": "This post won't be listed under any hashtag as it is unlisted. Only public posts can be searched by hashtag.",
@@ -149,7 +150,7 @@
   "directory.recently_active": "Actividá recién",
   "embed.instructions": "Empotra esti estáu nun sitiu web copiando'l códigu d'embaxo.",
   "embed.preview": "Asina ye cómo va vese:",
-  "emoji_button.activity": "Actividaes",
+  "emoji_button.activity": "Actividá",
   "emoji_button.clear": "Clear",
   "emoji_button.custom": "Custom",
   "emoji_button.flags": "Banderes",
@@ -170,7 +171,7 @@
   "empty_column.blocks": "Entá nun bloquiesti a nengún usuariu.",
   "empty_column.bookmarked_statuses": "Entá nun tienes nengún barritu en Marcadores. Cuando amiestes unu, va amosase equí.",
   "empty_column.community": "The local timeline is empty. Write something publicly to get the ball rolling!",
-  "empty_column.direct": "Entá nun tienes nengún mensaxe direutu. Cuando unvies o recibas dalgún, apaez equí.",
+  "empty_column.direct": "Entá nun tienes nengún mensaxe direutu. Cuando unvies o recibas dalgún, apaecen equí.",
   "empty_column.domain_blocks": "Entá nun hai dominios anubríos.",
   "empty_column.explore_statuses": "Nothing is trending right now. Check back later!",
   "empty_column.favourited_statuses": "Entá nun tienes nengún barritu en Favoritos. Cuando amiestes unu, va amosase equí.",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Entamu",
   "getting_started.invite": "Convidar a persones",
   "getting_started.open_source_notice": "Mastodon ye software de códigu abiertu. Pues collaborar o informar de fallos en GitHub: {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Axustes de la cuenta",
-  "getting_started.terms": "Términos del serviciu",
   "hashtag.column_header.tag_mode.all": "y {additional}",
   "hashtag.column_header.tag_mode.any": "o {additional}",
   "hashtag.column_header.tag_mode.none": "ensin {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Nun se pudo atopar nada con esos términos de busca",
   "search_results.statuses": "Barritos",
   "search_results.statuses_fts_disabled": "Esti sirvidor de Mastodon tien activada la gueta de barritos pol so conteníu.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {resultáu} other {resultaos}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Open moderation interface for @{name}",
   "status.admin_status": "Open this status in the moderation interface",
   "status.block": "Bloquiar a @{name}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Amosar menos en too",
   "status.show_more": "Amosar más",
   "status.show_more_all": "Amosar más en too",
+  "status.show_original": "Show original",
   "status.show_thread": "Amosar el filu",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "Non disponible",
   "status.unmute_conversation": "Unmute conversation",
   "status.unpin": "Desfixar del perfil",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "Dismiss suggestion",
   "suggestions.header": "Quiciabes t'interese…",
   "tabs_bar.federated_timeline": "Fediversu",
diff --git a/app/javascript/mastodon/locales/bg.json b/app/javascript/mastodon/locales/bg.json
index 4ded919e0..992d906d3 100644
--- a/app/javascript/mastodon/locales/bg.json
+++ b/app/javascript/mastodon/locales/bg.json
@@ -18,12 +18,13 @@
   "account.followers": "Последователи",
   "account.followers.empty": "Все още никой не следва този потребител.",
   "account.followers_counter": "{count, plural, one {{counter} Последовател} other {{counter} Последователи}}",
-  "account.following": "Following",
+  "account.following": "Последвани",
   "account.following_counter": "{count, plural, one {{counter} Последван} other {{counter} Последвани}}",
   "account.follows.empty": "Този потребител все още не следва никого.",
   "account.follows_you": "Твой последовател",
   "account.hide_reblogs": "Скриване на споделяния от @{name}",
-  "account.joined": "Joined {date}",
+  "account.joined": "Присъединил се на {date}",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "Собствеността върху тази връзка е проверена на {date}",
   "account.locked_info": "Този акаунт е поверително заключен. Собственикът преглежда ръчно кой може да го следва.",
   "account.media": "Мултимедия",
@@ -41,25 +42,25 @@
   "account.statuses_counter": "{count, plural, one {{counter} Публикация} other {{counter} Публикации}}",
   "account.unblock": "Не блокирай",
   "account.unblock_domain": "Unhide {domain}",
-  "account.unblock_short": "Unblock",
+  "account.unblock_short": "Отблокирай",
   "account.unendorse": "Не включвайте в профила",
   "account.unfollow": "Не следвай",
   "account.unmute": "Раззаглушаване на @{name}",
   "account.unmute_notifications": "Раззаглушаване на известия от @{name}",
   "account.unmute_short": "Unmute",
   "account_note.placeholder": "Click to add a note",
-  "admin.dashboard.daily_retention": "User retention rate by day after sign-up",
-  "admin.dashboard.monthly_retention": "User retention rate by month after sign-up",
-  "admin.dashboard.retention.average": "Average",
-  "admin.dashboard.retention.cohort": "Sign-up month",
-  "admin.dashboard.retention.cohort_size": "New users",
+  "admin.dashboard.daily_retention": "Ниво на задържани на потребители след регистрация, в дни",
+  "admin.dashboard.monthly_retention": "Ниво на задържани на потребители след регистрация, в месеци",
+  "admin.dashboard.retention.average": "Средно",
+  "admin.dashboard.retention.cohort": "Месец на регистрацията",
+  "admin.dashboard.retention.cohort_size": "Нови потребители",
   "alert.rate_limited.message": "Моля, опитайте отново след {retry_time, time, medium}.",
   "alert.rate_limited.title": "Скоростта е ограничена",
   "alert.unexpected.message": "Възникна неочаквана грешка.",
   "alert.unexpected.title": "Опаа!",
   "announcement.announcement": "Оповестяване",
-  "attachments_list.unprocessed": "(unprocessed)",
-  "audio.hide": "Hide audio",
+  "attachments_list.unprocessed": "(необработен)",
+  "audio.hide": "Скриване на видеото",
   "autosuggest_hashtag.per_week": "{count} на седмица",
   "boost_modal.combo": "Можете да натиснете {combo}, за да пропуснете това следващия път",
   "bundle_column_error.body": "Нещо се обърка при зареждането на този компонент.",
@@ -71,7 +72,7 @@
   "column.blocks": "Блокирани потребители",
   "column.bookmarks": "Отметки",
   "column.community": "Локална емисия",
-  "column.direct": "Direct messages",
+  "column.direct": "Лични съобщения",
   "column.directory": "Преглед на профили",
   "column.domain_blocks": "Hidden domains",
   "column.favourites": "Любими",
@@ -93,10 +94,10 @@
   "community.column_settings.local_only": "Само локално",
   "community.column_settings.media_only": "Media only",
   "community.column_settings.remote_only": "Само дистанционно",
-  "compose.language.change": "Change language",
-  "compose.language.search": "Search languages...",
+  "compose.language.change": "Смяна на езика",
+  "compose.language.search": "Търсене на езици...",
   "compose_form.direct_message_warning_learn_more": "Още информация",
-  "compose_form.encryption_warning": "Posts on Mastodon are not end-to-end encrypted. Do not share any dangerous information over Mastodon.",
+  "compose_form.encryption_warning": "Поставете в Мастодон не са криптирани от край до край. Не споделяйте никаква чувствителна информация.",
   "compose_form.hashtag_warning": "Тази публикация няма да бъде изброена под нито един хаштаг, тъй като е скрита. Само публични публикации могат да се търсят по хаштаг.",
   "compose_form.lock_disclaimer": "Вашият акаунт не е {locked}. Всеки може да ви последва, за да прегледа вашите публикации само за последователи.",
   "compose_form.lock_disclaimer.lock": "заключено",
@@ -107,9 +108,9 @@
   "compose_form.poll.remove_option": "Премахване на този избор",
   "compose_form.poll.switch_to_multiple": "Промяна на анкетата, за да се позволят множество възможни избора",
   "compose_form.poll.switch_to_single": "Промяна на анкетата, за да се позволи един възможен избор",
-  "compose_form.publish": "Publish",
+  "compose_form.publish": "Публикувай",
   "compose_form.publish_loud": "{publish}!",
-  "compose_form.save_changes": "Save changes",
+  "compose_form.save_changes": "Запази промените",
   "compose_form.sensitive.hide": "{count, plural, one {Маркиране на мултимедията като деликатна} other {Маркиране на мултимедиите като деликатни}}",
   "compose_form.sensitive.marked": "{count, plural, one {Мултимедията е маркирана като деликатна} other {Мултимедиите са маркирани като деликатни}}",
   "compose_form.sensitive.unmarked": "{count, plural, one {Мултимедията не е маркирана като деликатна} other {Мултимедиите не са маркирани като деликатни}}",
@@ -124,8 +125,8 @@
   "confirmations.delete.message": "Are you sure you want to delete this status?",
   "confirmations.delete_list.confirm": "Изтриване",
   "confirmations.delete_list.message": "Сигурни ли сте, че искате да изтриете окончателно този списък?",
-  "confirmations.discard_edit_media.confirm": "Discard",
-  "confirmations.discard_edit_media.message": "You have unsaved changes to the media description or preview, discard them anyway?",
+  "confirmations.discard_edit_media.confirm": "Отмени",
+  "confirmations.discard_edit_media.message": "Имате незапазени промени на описанието или прегледа на медията, отмяна въпреки това?",
   "confirmations.domain_block.confirm": "Hide entire domain",
   "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.",
   "confirmations.logout.confirm": "Излизане",
@@ -143,14 +144,14 @@
   "conversation.mark_as_read": "Маркиране като прочетено",
   "conversation.open": "Преглед на разговор",
   "conversation.with": "С {names}",
-  "directory.federated": "From known fediverse",
+  "directory.federated": "От познат федивърс",
   "directory.local": "Само от {domain}",
   "directory.new_arrivals": "Новодошли",
   "directory.recently_active": "Наскоро активни",
   "embed.instructions": "Embed this status on your website by copying the code below.",
   "embed.preview": "Ето как ще изглежда:",
   "emoji_button.activity": "Дейност",
-  "emoji_button.clear": "Clear",
+  "emoji_button.clear": "Изчисти",
   "emoji_button.custom": "Персонализирано",
   "emoji_button.flags": "Знамена",
   "emoji_button.food": "Храна и напитки",
@@ -170,16 +171,16 @@
   "empty_column.blocks": "Не сте блокирали потребители все още.",
   "empty_column.bookmarked_statuses": "Все още нямате отметнати публикации. Когато отметнете някоя, тя ще се покаже тук.",
   "empty_column.community": "Локалната емисия е празна. Напишете нещо публично, за да започнете!",
-  "empty_column.direct": "You don't have any direct messages yet. When you send or receive one, it will show up here.",
+  "empty_column.direct": "Все още нямате лични съобщения. Когато изпратите или получите ще се покаже тук.",
   "empty_column.domain_blocks": "There are no hidden domains yet.",
-  "empty_column.explore_statuses": "Nothing is trending right now. Check back later!",
+  "empty_column.explore_statuses": "Няма нищо популярно в момента. Проверете пак по-късно!",
   "empty_column.favourited_statuses": "Все още нямате любими публикации. Когато поставите някоя в любими, тя ще се покаже тук.",
   "empty_column.favourites": "Все още никой не е поставил тази публикация в любими. Когато някой го направи, ще се покаже тук.",
-  "empty_column.follow_recommendations": "Looks like no suggestions could be generated for you. You can try using search to look for people you might know or explore trending hashtags.",
+  "empty_column.follow_recommendations": "Изглежда, че няма генерирани предложения за вас. Можете да опитате да търсите за хора, които знаете или да разгледате популярните тагове.",
   "empty_column.follow_requests": "Все още нямате заявки за последване. Когато получите такава, тя ще се покаже тук.",
   "empty_column.hashtag": "В този хаштаг няма нищо все още.",
   "empty_column.home": "Вашата начална емисия е празна! Посетете {public} или използвайте търсене, за да започнете и да се запознаете с други потребители.",
-  "empty_column.home.suggestions": "See some suggestions",
+  "empty_column.home.suggestions": "Виж някои предложения",
   "empty_column.list": "There is nothing in this list yet.",
   "empty_column.lists": "Все още нямате списъци. Когато създадете такъв, той ще се покаже тук.",
   "empty_column.mutes": "Не сте заглушавали потребители все още.",
@@ -189,31 +190,31 @@
   "error.unexpected_crash.explanation_addons": "Тази страница не може да се покаже правилно. Тази грешка вероятно е причинена от добавка на браузъра или инструменти за автоматичен превод.",
   "error.unexpected_crash.next_steps": "Опитайте да опресните страницата. Ако това не помогне, все още можете да използвате Mastodon чрез различен браузър или приложение.",
   "error.unexpected_crash.next_steps_addons": "Опитайте да ги деактивирате и да опресните страницата. Ако това не помогне, може все още да използвате Mastodon чрез различен браузър или приложение.",
-  "errors.unexpected_crash.copy_stacktrace": "Copy stacktrace to clipboard",
+  "errors.unexpected_crash.copy_stacktrace": "Копиране на stacktrace-а в клипборда",
   "errors.unexpected_crash.report_issue": "Сигнал за проблем",
-  "explore.search_results": "Search results",
-  "explore.suggested_follows": "For you",
-  "explore.title": "Explore",
-  "explore.trending_links": "News",
-  "explore.trending_statuses": "Posts",
-  "explore.trending_tags": "Hashtags",
+  "explore.search_results": "Резултати от търсенето",
+  "explore.suggested_follows": "За вас",
+  "explore.title": "Разглеждане",
+  "explore.trending_links": "Новини",
+  "explore.trending_statuses": "Публикации",
+  "explore.trending_tags": "Тагове",
   "filter_modal.added.context_mismatch_explanation": "This filter category does not apply to the context in which you have accessed this post. If you want the post to be filtered in this context too, you will have to edit the filter.",
-  "filter_modal.added.context_mismatch_title": "Context mismatch!",
+  "filter_modal.added.context_mismatch_title": "Несъвпадение на контекста!",
   "filter_modal.added.expired_explanation": "This filter category has expired, you will need to change the expiration date for it to apply.",
-  "filter_modal.added.expired_title": "Expired filter!",
+  "filter_modal.added.expired_title": "Изтекал филтър!",
   "filter_modal.added.review_and_configure": "To review and further configure this filter category, go to the {settings_link}.",
-  "filter_modal.added.review_and_configure_title": "Filter settings",
-  "filter_modal.added.settings_link": "settings page",
+  "filter_modal.added.review_and_configure_title": "Настройки на филтър",
+  "filter_modal.added.settings_link": "страница с настройки",
   "filter_modal.added.short_explanation": "This post has been added to the following filter category: {title}.",
-  "filter_modal.added.title": "Filter added!",
-  "filter_modal.select_filter.context_mismatch": "does not apply to this context",
-  "filter_modal.select_filter.expired": "expired",
-  "filter_modal.select_filter.prompt_new": "New category: {name}",
-  "filter_modal.select_filter.search": "Search or create",
-  "filter_modal.select_filter.subtitle": "Use an existing category or create a new one",
-  "filter_modal.select_filter.title": "Filter this post",
-  "filter_modal.title.status": "Filter a post",
-  "follow_recommendations.done": "Done",
+  "filter_modal.added.title": "Филтърът е добавен!",
+  "filter_modal.select_filter.context_mismatch": "не е приложимо за този контекст",
+  "filter_modal.select_filter.expired": "изтекло",
+  "filter_modal.select_filter.prompt_new": "Нова категория: {name}",
+  "filter_modal.select_filter.search": "Търси или създай",
+  "filter_modal.select_filter.subtitle": "Изберете съществуваща категория или създайте нова",
+  "filter_modal.select_filter.title": "Филтриране на поста",
+  "filter_modal.title.status": "Филтрирай пост",
+  "follow_recommendations.done": "Готово",
   "follow_recommendations.heading": "Следвайте хора, които харесвате, за да виждате техните съобщения! Ето някои предложения.",
   "follow_recommendations.lead": "Съобщения от хора, които следвате, ще се показват в хронологичен ред на вашата главна страница. Не се страхувайте, че ще сгрешите, по всяко време много лесно можете да спрете да ги следвате!",
   "follow_request.authorize": "Упълномощаване",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Първи стъпки",
   "getting_started.invite": "Поканване на хора",
   "getting_started.open_source_notice": "Mastodon е софтуер с отворен код. Можеш да помогнеш или да докладваш за проблеми в Github: {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Security",
-  "getting_started.terms": "Условия за ползване",
   "hashtag.column_header.tag_mode.all": "и {additional}",
   "hashtag.column_header.tag_mode.any": "или {additional}",
   "hashtag.column_header.tag_mode.none": "без {additional}",
@@ -237,9 +238,9 @@
   "hashtag.column_settings.tag_mode.any": "Някое от тези",
   "hashtag.column_settings.tag_mode.none": "Никое от тези",
   "hashtag.column_settings.tag_toggle": "Include additional tags in this column",
-  "hashtag.follow": "Follow hashtag",
-  "hashtag.total_volume": "Total volume in the last {days, plural, one {day} other {{days} days}}",
-  "hashtag.unfollow": "Unfollow hashtag",
+  "hashtag.follow": "Следване на хаштаг",
+  "hashtag.total_volume": "Пълно количество в {days, plural,one {последния ден} other {последните {days} дни}}",
+  "hashtag.unfollow": "Спиране на следване на хаштаг",
   "home.column_settings.basic": "Основно",
   "home.column_settings.show_reblogs": "Показване на споделяния",
   "home.column_settings.show_replies": "Показване на отговори",
@@ -287,8 +288,8 @@
   "lightbox.expand": "Разгъване на полето за преглед на изображение",
   "lightbox.next": "Напред",
   "lightbox.previous": "Назад",
-  "limited_account_hint.action": "Show profile anyway",
-  "limited_account_hint.title": "This profile has been hidden by the moderators of your server.",
+  "limited_account_hint.action": "Покажи профила въпреки това",
+  "limited_account_hint.title": "Този профил е скрит от модераторите на сървъра Ви.",
   "lists.account.add": "Добавяне към списък",
   "lists.account.remove": "Премахване от списък",
   "lists.delete": "Изтриване на списък",
@@ -315,11 +316,11 @@
   "navigation_bar.bookmarks": "Отметки",
   "navigation_bar.community_timeline": "Локална емисия",
   "navigation_bar.compose": "Композиране на нова публикация",
-  "navigation_bar.direct": "Direct messages",
+  "navigation_bar.direct": "Директни съобщения",
   "navigation_bar.discover": "Откриване",
   "navigation_bar.domain_blocks": "Hidden domains",
   "navigation_bar.edit_profile": "Редактирай профил",
-  "navigation_bar.explore": "Explore",
+  "navigation_bar.explore": "Разглеждане",
   "navigation_bar.favourites": "Любими",
   "navigation_bar.filters": "Заглушени думи",
   "navigation_bar.follow_requests": "Заявки за последване",
@@ -334,8 +335,8 @@
   "navigation_bar.preferences": "Предпочитания",
   "navigation_bar.public_timeline": "Публичен канал",
   "navigation_bar.security": "Сигурност",
-  "notification.admin.report": "{name} reported {target}",
-  "notification.admin.sign_up": "{name} signed up",
+  "notification.admin.report": "{name} докладва {target}",
+  "notification.admin.sign_up": "{name} се регистрира",
   "notification.favourite": "{name} хареса твоята публикация",
   "notification.follow": "{name} те последва",
   "notification.follow_request": "{name} поиска да ви последва",
@@ -344,16 +345,16 @@
   "notification.poll": "Анкета, в която сте гласували, приключи",
   "notification.reblog": "{name} сподели твоята публикация",
   "notification.status": "{name} току-що публикува",
-  "notification.update": "{name} edited a post",
+  "notification.update": "{name} промени публикация",
   "notifications.clear": "Изчистване на известия",
   "notifications.clear_confirmation": "Сигурни ли сте, че искате да изчистите окончателно всичките си известия?",
-  "notifications.column_settings.admin.report": "New reports:",
-  "notifications.column_settings.admin.sign_up": "New sign-ups:",
+  "notifications.column_settings.admin.report": "Нови доклади:",
+  "notifications.column_settings.admin.sign_up": "Нови регистрации:",
   "notifications.column_settings.alert": "Десктоп известия",
   "notifications.column_settings.favourite": "Предпочитани:",
   "notifications.column_settings.filter_bar.advanced": "Показване на всички категории",
   "notifications.column_settings.filter_bar.category": "Лента за бърз филтър",
-  "notifications.column_settings.filter_bar.show_bar": "Show filter bar",
+  "notifications.column_settings.filter_bar.show_bar": "Покажи лентата с филтри",
   "notifications.column_settings.follow": "Нови последователи:",
   "notifications.column_settings.follow_request": "Нови заявки за последване:",
   "notifications.column_settings.mention": "Споменавания:",
@@ -363,9 +364,9 @@
   "notifications.column_settings.show": "Покажи в колона",
   "notifications.column_settings.sound": "Пускане на звук",
   "notifications.column_settings.status": "Нови публикации:",
-  "notifications.column_settings.unread_notifications.category": "Unread notifications",
-  "notifications.column_settings.unread_notifications.highlight": "Highlight unread notifications",
-  "notifications.column_settings.update": "Edits:",
+  "notifications.column_settings.unread_notifications.category": "Непрочетени известия",
+  "notifications.column_settings.unread_notifications.highlight": "Отбележи непрочетените уведомления",
+  "notifications.column_settings.update": "Редакции:",
   "notifications.filter.all": "Всичко",
   "notifications.filter.boosts": "Споделяния",
   "notifications.filter.favourites": "Любими",
@@ -389,15 +390,15 @@
   "poll.total_votes": "{count, plural, one {# глас} other {# гласа}}",
   "poll.vote": "Гласуване",
   "poll.voted": "Вие гласувахте за този отговор",
-  "poll.votes": "{votes, plural, one {# vote} other {# votes}}",
+  "poll.votes": "{votes, plural, one {# глас} other {# гласа}}",
   "poll_button.add_poll": "Добавяне на анкета",
   "poll_button.remove_poll": "Премахване на анкета",
   "privacy.change": "Adjust status privacy",
   "privacy.direct.long": "Post to mentioned users only",
-  "privacy.direct.short": "Direct",
+  "privacy.direct.short": "Само споменатите хора",
   "privacy.private.long": "Post to followers only",
-  "privacy.private.short": "Followers-only",
-  "privacy.public.long": "Visible for all",
+  "privacy.private.short": "Само последователи",
+  "privacy.public.long": "Видимо за всички",
   "privacy.public.short": "Публично",
   "privacy.unlisted.long": "Visible for all, but opted-out of discovery features",
   "privacy.unlisted.short": "Скрито",
@@ -468,10 +469,14 @@
   "search_results.accounts": "Хора",
   "search_results.all": "All",
   "search_results.hashtags": "Хаштагове",
-  "search_results.nothing_found": "Could not find anything for these search terms",
+  "search_results.nothing_found": "Не е намерено нищо за това търсене",
   "search_results.statuses": "Публикации",
   "search_results.statuses_fts_disabled": "Търсенето на публикации по тяхното съдържание не е активирано за този Mastodon сървър.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {резултат} other {резултата}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Отваряне на интерфейс за модериране за @{name}",
   "status.admin_status": "Open this status in the moderation interface",
   "status.block": "Блокиране на @{name}",
@@ -482,16 +487,16 @@
   "status.delete": "Изтриване",
   "status.detailed_status": "Подробен изглед на разговор",
   "status.direct": "Директно съобщение към @{name}",
-  "status.edit": "Edit",
-  "status.edited": "Edited {date}",
-  "status.edited_x_times": "Edited {count, plural, one {{count} time} other {{count} times}}",
+  "status.edit": "Редакция",
+  "status.edited": "Редактирано на {date}",
+  "status.edited_x_times": "Редактирано {count, plural,one {{count} път} other {{count} пъти}}",
   "status.embed": "Вграждане",
   "status.favourite": "Предпочитани",
-  "status.filter": "Filter this post",
+  "status.filter": "Филтриране на поста",
   "status.filtered": "Филтрирано",
-  "status.hide": "Hide toot",
-  "status.history.created": "{name} created {date}",
-  "status.history.edited": "{name} edited {date}",
+  "status.hide": "Скриване на поста",
+  "status.history.created": "{name} създаде {date}",
+  "status.history.edited": "{name} редактира {date}",
   "status.load_more": "Зареждане на още",
   "status.media_hidden": "Мултимедията е скрита",
   "status.mention": "Споменаване",
@@ -513,15 +518,21 @@
   "status.report": "Докладване на @{name}",
   "status.sensitive_warning": "Деликатно съдържание",
   "status.share": "Споделяне",
-  "status.show_filter_reason": "Show anyway",
+  "status.show_filter_reason": "Покажи въпреки това",
   "status.show_less": "Покажи по-малко",
   "status.show_less_all": "Покажи по-малко за всички",
   "status.show_more": "Покажи повече",
   "status.show_more_all": "Покажи повече за всички",
+  "status.show_original": "Show original",
   "status.show_thread": "Показване на тема",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "Не е налично",
   "status.unmute_conversation": "Раззаглушаване на разговор",
   "status.unpin": "Разкачане от профил",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "Отхвърляне на предложение",
   "suggestions.header": "Може да се интересувате от…",
   "tabs_bar.federated_timeline": "Обединен",
@@ -550,14 +561,14 @@
   "upload_error.poll": "Качването на файлове не е позволено с анкети.",
   "upload_form.audio_description": "Опишете за хора със загуба на слуха",
   "upload_form.description": "Опишете за хора със зрителни увреждания",
-  "upload_form.description_missing": "No description added",
+  "upload_form.description_missing": "Без добавено описание",
   "upload_form.edit": "Редакция",
   "upload_form.thumbnail": "Промяна на миниизображението",
   "upload_form.undo": "Отмяна",
   "upload_form.video_description": "Опишете за хора със загуба на слуха или зрително увреждане",
   "upload_modal.analyzing_picture": "Анализ на снимка…",
   "upload_modal.apply": "Прилагане",
-  "upload_modal.applying": "Applying…",
+  "upload_modal.applying": "Прилагане…",
   "upload_modal.choose_image": "Избор на изображение",
   "upload_modal.description_placeholder": "Ах, чудна българска земьо, полюшвай цъфтящи жита",
   "upload_modal.detect_text": "Откриване на текст от картина",
diff --git a/app/javascript/mastodon/locales/bn.json b/app/javascript/mastodon/locales/bn.json
index 94b0477b5..6157928e2 100644
--- a/app/javascript/mastodon/locales/bn.json
+++ b/app/javascript/mastodon/locales/bn.json
@@ -24,6 +24,7 @@
   "account.follows_you": "তোমাকে অনুসরণ করে",
   "account.hide_reblogs": "@{name}'র সমর্থনগুলি লুকিয়ে ফেলুন",
   "account.joined": "Joined {date}",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "এই লিংকের মালিকানা চেক করা হয়েছে {date} তারিখে",
   "account.locked_info": "এই নিবন্ধনের গোপনীয়তার ক্ষেত্র তালা দেওয়া আছে। নিবন্ধনকারী অনুসরণ করার অনুমতি যাদেরকে দেবেন, শুধু তারাই অনুসরণ করতে পারবেন।",
   "account.media": "মিডিয়া",
@@ -226,8 +227,8 @@
   "getting_started.heading": "শুরু করা",
   "getting_started.invite": "অন্যদের আমন্ত্রণ করুন",
   "getting_started.open_source_notice": "মাস্টাডন একটি মুক্ত সফটওয়্যার। তৈরিতে সাহায্য করতে বা কোনো সমস্যা সম্পর্কে জানাতে আমাদের গিটহাবে যেতে পারেন {github}।",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "নিরাপত্তা",
-  "getting_started.terms": "ব্যবহারের নিয়মাবলী",
   "hashtag.column_header.tag_mode.all": "এবং {additional}",
   "hashtag.column_header.tag_mode.any": "অথবা {additional}",
   "hashtag.column_header.tag_mode.none": "বাদ দিয়ে {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Could not find anything for these search terms",
   "search_results.statuses": "টুট",
   "search_results.statuses_fts_disabled": "তাদের সামগ্রী দ্বারা টুটগুলি অনুসন্ধান এই মস্তোডন সার্ভারে সক্ষম নয়।",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {ফলাফল} other {ফলাফল}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "@{name} র জন্য পরিচালনার ইন্টারফেসে ঢুকুন",
   "status.admin_status": "যায় লেখাটি পরিচালনার ইন্টারফেসে খুলুন",
   "status.block": "@{name} কে ব্লক করুন",
@@ -518,10 +523,16 @@
   "status.show_less_all": "সবগুলোতে কম দেখতে",
   "status.show_more": "আরো দেখাতে",
   "status.show_more_all": "সবগুলোতে আরো দেখতে",
+  "status.show_original": "Show original",
   "status.show_thread": "আলোচনা দেখতে",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "পাওয়া যাচ্ছে না",
   "status.unmute_conversation": "আলোচনার প্রজ্ঞাপন চালু করতে",
   "status.unpin": "নিজের পাতা থেকে পিন করে রাখাটির পিন খুলতে",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "সাহায্যের পরামর্শগুলো সরাতে",
   "suggestions.header": "আপনি হয়তোবা এগুলোতে আগ্রহী হতে পারেন…",
   "tabs_bar.federated_timeline": "যুক্তবিশ্ব",
diff --git a/app/javascript/mastodon/locales/br.json b/app/javascript/mastodon/locales/br.json
index 50837691f..4d5a943e3 100644
--- a/app/javascript/mastodon/locales/br.json
+++ b/app/javascript/mastodon/locales/br.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Ho heul",
   "account.hide_reblogs": "Kuzh toudoù rannet gant @{name}",
   "account.joined": "Amañ abaoe {date}",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "Gwiriet eo bet perc'hennidigezh al liamm d'an deiziad-mañ : {date}",
   "account.locked_info": "Prennet eo ar gont-mañ. Dibab a ra ar perc'henn ar re a c'hall heuliañ anezhi pe anezhañ.",
   "account.media": "Media",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Loc'hañ",
   "getting_started.invite": "Pediñ tud",
   "getting_started.open_source_notice": "Mastodoñ zo ur meziant digor e darzh. Gallout a rit kenoberzhiañ dezhañ pe danevellañ kudennoù war GitHub e {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Arventennoù ar gont",
-  "getting_started.terms": "Divizoù gwerzhañ hollek",
   "hashtag.column_header.tag_mode.all": "ha {additional}",
   "hashtag.column_header.tag_mode.any": "pe {additional}",
   "hashtag.column_header.tag_mode.none": "hep {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Could not find anything for these search terms",
   "search_results.statuses": "a doudoù",
   "search_results.statuses_fts_disabled": "Klask toudoù dre oc'h endalc'h n'eo ket aotreet war ar servijer-mañ.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {disoc'h} other {a zisoc'h}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Digeriñ etrefas evezherezh evit @{name}",
   "status.admin_status": "Digeriñ an toud e-barzh an etrefas evezherezh",
   "status.block": "Berzañ @{name}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Diskouez nebeutoc'h evit an holl",
   "status.show_more": "Diskouez muioc'h",
   "status.show_more_all": "Diskouez miuoc'h evit an holl",
+  "status.show_original": "Show original",
   "status.show_thread": "Diskouez ar gaozeadenn",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "Dihegerz",
   "status.unmute_conversation": "Diguzhat ar gaozeadenn",
   "status.unpin": "Dispilhennañ eus ar profil",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "Dilezel damvenegoù",
   "suggestions.header": "Marteze e vefec'h dedenet gant…",
   "tabs_bar.federated_timeline": "Kevredet",
diff --git a/app/javascript/mastodon/locales/ca.json b/app/javascript/mastodon/locales/ca.json
index f67a0f3fc..2a218ea84 100644
--- a/app/javascript/mastodon/locales/ca.json
+++ b/app/javascript/mastodon/locales/ca.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Et segueix",
   "account.hide_reblogs": "Amaga els impulsos de @{name}",
   "account.joined": "Membre des de {date}",
+  "account.languages": "Canviar les llengües subscrits",
   "account.link_verified_on": "La propietat d'aquest enllaç es va verificar el dia {date}",
   "account.locked_info": "Aquest estat de privadesa del compte està definit com a bloquejat. El propietari revisa manualment qui pot seguir-lo.",
   "account.media": "Multimèdia",
@@ -197,22 +198,22 @@
   "explore.trending_links": "Notícies",
   "explore.trending_statuses": "Publicacions",
   "explore.trending_tags": "Etiquetes",
-  "filter_modal.added.context_mismatch_explanation": "This filter category does not apply to the context in which you have accessed this post. If you want the post to be filtered in this context too, you will have to edit the filter.",
-  "filter_modal.added.context_mismatch_title": "Context mismatch!",
-  "filter_modal.added.expired_explanation": "This filter category has expired, you will need to change the expiration date for it to apply.",
-  "filter_modal.added.expired_title": "Expired filter!",
-  "filter_modal.added.review_and_configure": "To review and further configure this filter category, go to the {settings_link}.",
-  "filter_modal.added.review_and_configure_title": "Filter settings",
-  "filter_modal.added.settings_link": "settings page",
-  "filter_modal.added.short_explanation": "This post has been added to the following filter category: {title}.",
-  "filter_modal.added.title": "Filter added!",
-  "filter_modal.select_filter.context_mismatch": "does not apply to this context",
-  "filter_modal.select_filter.expired": "expired",
-  "filter_modal.select_filter.prompt_new": "New category: {name}",
-  "filter_modal.select_filter.search": "Search or create",
-  "filter_modal.select_filter.subtitle": "Use an existing category or create a new one",
-  "filter_modal.select_filter.title": "Filter this post",
-  "filter_modal.title.status": "Filter a post",
+  "filter_modal.added.context_mismatch_explanation": "Aquesta categoria del filtr no aplica al context en el que has accedit a aquest apunt. Si vols que l'apunt sigui filtrat també en aquest context, hauràs d'editar el filtre.",
+  "filter_modal.added.context_mismatch_title": "El context no coincideix!",
+  "filter_modal.added.expired_explanation": "La categoria d'aquest filtre ha caducat, necesitaràs canviar la seva data de caducitat per a aplicar-la.",
+  "filter_modal.added.expired_title": "Filtre caducat!",
+  "filter_modal.added.review_and_configure": "Per a revisar i configurar aquesta categoria de filtre, ves a {settings_link}.",
+  "filter_modal.added.review_and_configure_title": "Configuració del filtre",
+  "filter_modal.added.settings_link": "pàgina de configuració",
+  "filter_modal.added.short_explanation": "Aquest apunt s'ha afegit a la següent categoria de filtre: {title}.",
+  "filter_modal.added.title": "Filtre afegit!",
+  "filter_modal.select_filter.context_mismatch": "no aplica en aquest context",
+  "filter_modal.select_filter.expired": "caducat",
+  "filter_modal.select_filter.prompt_new": "Nova categoria: {name}",
+  "filter_modal.select_filter.search": "Cerca o crea",
+  "filter_modal.select_filter.subtitle": "Usa una categoria existent o crea una nova",
+  "filter_modal.select_filter.title": "Filtra aquest apunt",
+  "filter_modal.title.status": "Filtre un apunt",
   "follow_recommendations.done": "Fet",
   "follow_recommendations.heading": "Segueix a la gent de la que t'agradaria veure les seves publicacions! Aquí hi ha algunes recomanacions.",
   "follow_recommendations.lead": "Les publicacions del usuaris que segueixes es mostraran en ordre cronològic en la teva línia de temps Inici. No tinguis por en cometre errors, pots fàcilment deixar de seguir-los en qualsevol moment!",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Primers passos",
   "getting_started.invite": "Convidar gent",
   "getting_started.open_source_notice": "Mastodon és un programari de codi obert. Pots contribuir-hi o informar de problemes a GitHub a {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Configuració del compte",
-  "getting_started.terms": "Condicions de servei",
   "hashtag.column_header.tag_mode.all": "i {additional}",
   "hashtag.column_header.tag_mode.any": "o {additional}",
   "hashtag.column_header.tag_mode.none": "sense {additional}",
@@ -238,7 +239,7 @@
   "hashtag.column_settings.tag_mode.none": "Cap d’aquests",
   "hashtag.column_settings.tag_toggle": "Inclou etiquetes addicionals per a aquesta columna",
   "hashtag.follow": "Segueix etiqueta",
-  "hashtag.total_volume": "Total volume in the last {days, plural, one {day} other {{days} days}}",
+  "hashtag.total_volume": "Volumen total en els darrers {days, plural, one {day} other {{days} dies}}",
   "hashtag.unfollow": "Deixa de seguir etiqueta",
   "home.column_settings.basic": "Bàsic",
   "home.column_settings.show_reblogs": "Mostra els impulsos",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "No s'ha pogut trobar res per a aquests termes de cerca",
   "search_results.statuses": "Publicacions",
   "search_results.statuses_fts_disabled": "La cerca de publicacions pel seu contingut no està habilitada en aquest servidor Mastodon.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {resultat} other {resultats}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Obre l'interfície de moderació per a @{name}",
   "status.admin_status": "Obrir aquesta publicació a la interfície de moderació",
   "status.block": "Bloqueja @{name}",
@@ -487,7 +492,7 @@
   "status.edited_x_times": "Editat {count, plural, one {{count} vegada} other {{count} vegades}}",
   "status.embed": "Incrusta",
   "status.favourite": "Favorit",
-  "status.filter": "Filter this post",
+  "status.filter": "Filtre aquest apunt",
   "status.filtered": "Filtrat",
   "status.hide": "Amaga publicació",
   "status.history.created": "{name} ha creat {date}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Mostrar-ne menys per a tot",
   "status.show_more": "Mostrar-ne més",
   "status.show_more_all": "Mostrar-ne més per a tot",
+  "status.show_original": "Mostra l'original",
   "status.show_thread": "Mostra el fil",
+  "status.translate": "Tradueix",
+  "status.translated_from": "Traduït del: {lang}",
   "status.uncached_media_warning": "No està disponible",
   "status.unmute_conversation": "No silenciïs la conversa",
   "status.unpin": "No fixis al perfil",
+  "subscribed_languages.lead": "Només els apunts en les llengües seleccionades apareixeran en le teves línies de temps Inici i llista després del canvi. No en seleccionis cap per a rebre apunts en totes les llengües.",
+  "subscribed_languages.save": "Desa els canvis",
+  "subscribed_languages.target": "Canvia les llengües subscrites per a {target}",
   "suggestions.dismiss": "Ignora el suggeriment",
   "suggestions.header": "És possible que estiguis interessat en…",
   "tabs_bar.federated_timeline": "Federat",
@@ -538,7 +549,7 @@
   "timeline_hint.resources.followers": "Seguidors",
   "timeline_hint.resources.follows": "Seguiments",
   "timeline_hint.resources.statuses": "Publicacions més antigues",
-  "trends.counter_by_accounts": "{count, plural, one {{counter} person} other {{counter} people}} in the past {days, plural, one {day} other {{days} days}}",
+  "trends.counter_by_accounts": "{count, plural, one {{counter} person} other {{counter} persones}} en els passats {days, plural, one {day} other {{days} dies}}",
   "trends.trending_now": "En tendència",
   "ui.beforeunload": "El teu esborrany es perdrà si surts de Mastodon.",
   "units.short.billion": "{count}B",
diff --git a/app/javascript/mastodon/locales/ckb.json b/app/javascript/mastodon/locales/ckb.json
index 19d9550d0..0eca1dab4 100644
--- a/app/javascript/mastodon/locales/ckb.json
+++ b/app/javascript/mastodon/locales/ckb.json
@@ -24,6 +24,7 @@
   "account.follows_you": "شوێنکەوتووەکانت",
   "account.hide_reblogs": "داشاردنی بووستەکان لە @{name}",
   "account.joined": "بەشداری {date}",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "خاوەنداریەتی ئەم لینکە لە {date} چێک کراوە",
   "account.locked_info": "تایبەتمەندی ئەم هەژمارەیە ڕیکخراوە بۆ قوفڵدراوە. خاوەنەکە بە دەستی پێداچوونەوە دەکات کە کێ دەتوانێت شوێنیان بکەوێت.",
   "account.media": "میدیا",
@@ -226,8 +227,8 @@
   "getting_started.heading": "دەست پێکردن",
   "getting_started.invite": "بانگهێشتکردنی خەڵک",
   "getting_started.open_source_notice": "ماستۆدۆن نەرمەکالایەکی سەرچاوەی کراوەیە. دەتوانیت بەشداری بکەیت یان گوزارشت بکەیت لەسەر کێشەکانی لە پەڕەی گیتهاب {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "ڕێکخستنەکانی هەژمارە",
-  "getting_started.terms": "مەرجەکانی خزمەتگوزاری",
   "hashtag.column_header.tag_mode.all": "و {additional}",
   "hashtag.column_header.tag_mode.any": "یا {additional}",
   "hashtag.column_header.tag_mode.none": "بەبێ {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Could not find anything for these search terms",
   "search_results.statuses": "توتەکان",
   "search_results.statuses_fts_disabled": "گەڕانی توتەکان بە ناوەڕۆکیان لەسەر ئەم ڕاژەی ماستۆدۆن چالاک نەکراوە.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {دەرئەنجام} other {دەرئەنجام}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "کردنەوەی میانڕەوی بەڕێوەبەر بۆ @{name}",
   "status.admin_status": "ئەم توتە بکەوە لە ناو ڕووکاری بەڕیوەبەر",
   "status.block": "@{name} ئاستەنگ بکە",
@@ -518,10 +523,16 @@
   "status.show_less_all": "هەمووی بچووک بکەوە",
   "status.show_more": "زیاتر نیشان بدە",
   "status.show_more_all": "زیاتر نیشان بدە بۆ هەمووی",
+  "status.show_original": "Show original",
   "status.show_thread": "نیشاندانی گفتوگۆ",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "بەردەست نیە",
   "status.unmute_conversation": "گفتوگۆی بێدەنگ",
   "status.unpin": "لە سەرەوە لایبە",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "ڕەتکردنەوەی پێشنیار",
   "suggestions.header": "لەوانەیە حەزت لەمەش بێت…",
   "tabs_bar.federated_timeline": "گشتی",
diff --git a/app/javascript/mastodon/locales/co.json b/app/javascript/mastodon/locales/co.json
index 5ca3f4a4b..8b6592401 100644
--- a/app/javascript/mastodon/locales/co.json
+++ b/app/javascript/mastodon/locales/co.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Vi seguita",
   "account.hide_reblogs": "Piattà spartere da @{name}",
   "account.joined": "Quì dapoi {date}",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "A prupietà di stu ligame hè stata verificata u {date}",
   "account.locked_info": "U statutu di vita privata di u contu hè chjosu. U pruprietariu esamina manualmente e dumande d'abbunamentu.",
   "account.media": "Media",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Per principià",
   "getting_started.invite": "Invità ghjente",
   "getting_started.open_source_notice": "Mastodon ghjè un lugiziale liberu. Pudete cuntribuisce à u codice o a traduzione, o palisà un bug, nant'à GitHub: {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Sicurità",
-  "getting_started.terms": "Cundizione di u serviziu",
   "hashtag.column_header.tag_mode.all": "è {additional}",
   "hashtag.column_header.tag_mode.any": "o {additional}",
   "hashtag.column_header.tag_mode.none": "senza {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Could not find anything for these search terms",
   "search_results.statuses": "Statuti",
   "search_results.statuses_fts_disabled": "A ricerca di i cuntinuti di i statuti ùn hè micca attivata nant'à stu servore Mastodon.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {risultatu} other {risultati}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Apre l'interfaccia di muderazione per @{name}",
   "status.admin_status": "Apre stu statutu in l'interfaccia di muderazione",
   "status.block": "Bluccà @{name}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Ripiegà tuttu",
   "status.show_more": "Slibrà",
   "status.show_more_all": "Slibrà tuttu",
+  "status.show_original": "Show original",
   "status.show_thread": "Vede u filu",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "Micca dispunibule",
   "status.unmute_conversation": "Ùn piattà più a cunversazione",
   "status.unpin": "Spuntarulà da u prufile",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "Righjittà a pruposta",
   "suggestions.header": "Site forse interessatu·a da…",
   "tabs_bar.federated_timeline": "Glubale",
diff --git a/app/javascript/mastodon/locales/cs.json b/app/javascript/mastodon/locales/cs.json
index ef1a13d8f..c83e0b5b5 100644
--- a/app/javascript/mastodon/locales/cs.json
+++ b/app/javascript/mastodon/locales/cs.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Sleduje vás",
   "account.hide_reblogs": "Skrýt boosty od @{name}",
   "account.joined": "Založen {date}",
+  "account.languages": "Změnit odebírané jazyky",
   "account.link_verified_on": "Vlastnictví tohoto odkazu bylo zkontrolováno {date}",
   "account.locked_info": "Stav soukromí tohoto účtu je nastaven na zamčeno. Jeho vlastník ručně posuzuje, kdo ho může sledovat.",
   "account.media": "Média",
@@ -59,7 +60,7 @@
   "alert.unexpected.title": "Jejda!",
   "announcement.announcement": "Oznámení",
   "attachments_list.unprocessed": "(nezpracováno)",
-  "audio.hide": "Hide audio",
+  "audio.hide": "Skrýt zvuk",
   "autosuggest_hashtag.per_week": "{count} za týden",
   "boost_modal.combo": "Příště můžete pro přeskočení stisknout {combo}",
   "bundle_column_error.body": "Při načítání této komponenty se něco pokazilo.",
@@ -197,22 +198,22 @@
   "explore.trending_links": "Zprávy",
   "explore.trending_statuses": "Příspěvky",
   "explore.trending_tags": "Hashtagy",
-  "filter_modal.added.context_mismatch_explanation": "This filter category does not apply to the context in which you have accessed this post. If you want the post to be filtered in this context too, you will have to edit the filter.",
-  "filter_modal.added.context_mismatch_title": "Context mismatch!",
-  "filter_modal.added.expired_explanation": "This filter category has expired, you will need to change the expiration date for it to apply.",
-  "filter_modal.added.expired_title": "Expired filter!",
-  "filter_modal.added.review_and_configure": "To review and further configure this filter category, go to the {settings_link}.",
-  "filter_modal.added.review_and_configure_title": "Filter settings",
-  "filter_modal.added.settings_link": "settings page",
-  "filter_modal.added.short_explanation": "This post has been added to the following filter category: {title}.",
-  "filter_modal.added.title": "Filter added!",
-  "filter_modal.select_filter.context_mismatch": "does not apply to this context",
-  "filter_modal.select_filter.expired": "expired",
-  "filter_modal.select_filter.prompt_new": "New category: {name}",
-  "filter_modal.select_filter.search": "Search or create",
-  "filter_modal.select_filter.subtitle": "Use an existing category or create a new one",
-  "filter_modal.select_filter.title": "Filter this post",
-  "filter_modal.title.status": "Filter a post",
+  "filter_modal.added.context_mismatch_explanation": "Tato kategorie filtru se nevztahuje na kontext, ve kterém jste tento příspěvek otevřeli. Pokud chcete, aby byl příspěvek filtrován i v tomto kontextu, budete muset filtr upravit.",
+  "filter_modal.added.context_mismatch_title": "Kontext se neshoduje!",
+  "filter_modal.added.expired_explanation": "Tato kategorie filtrů vypršela, budete muset změnit datum vypršení platnosti, aby mohla být použita.",
+  "filter_modal.added.expired_title": "Vypršel filtr!",
+  "filter_modal.added.review_and_configure": "Chcete-li zkontrolovat a dále konfigurovat tuto kategorii filtru, přejděte na {settings_link}.",
+  "filter_modal.added.review_and_configure_title": "Nastavení filtru",
+  "filter_modal.added.settings_link": "stránka nastavení",
+  "filter_modal.added.short_explanation": "Tento příspěvek byl přidán do následující kategorie filtrů: {title}.",
+  "filter_modal.added.title": "Filtr přidán!",
+  "filter_modal.select_filter.context_mismatch": "nevztahuje se na tento kontext",
+  "filter_modal.select_filter.expired": "vypršela platnost",
+  "filter_modal.select_filter.prompt_new": "Nová kategorie: {name}",
+  "filter_modal.select_filter.search": "Vyhledat nebo vytvořit",
+  "filter_modal.select_filter.subtitle": "Použít existující kategorii nebo vytvořit novou kategorii",
+  "filter_modal.select_filter.title": "Filtrovat tento příspěvek",
+  "filter_modal.title.status": "Filtrovat příspěvek",
   "follow_recommendations.done": "Hotovo",
   "follow_recommendations.heading": "Sledujte lidi, jejichž příspěvky chcete vidět! Tady jsou nějaké návrhy.",
   "follow_recommendations.lead": "Příspěvky od lidí, které sledujete, se budou objevovat v chronologickém pořadí ve vaší domovské ose. Nebojte se, že uděláte chybu, můžete lidi stejně snadno kdykoliv přestat sledovat!",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Začínáme",
   "getting_started.invite": "Pozvat lidi",
   "getting_started.open_source_notice": "Mastodon je otevřený software. Přispět do jeho vývoje nebo hlásit chyby můžete na GitHubu {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Nastavení účtu",
-  "getting_started.terms": "Podmínky používání",
   "hashtag.column_header.tag_mode.all": "a {additional}",
   "hashtag.column_header.tag_mode.any": "nebo {additional}",
   "hashtag.column_header.tag_mode.none": "bez {additional}",
@@ -237,9 +238,9 @@
   "hashtag.column_settings.tag_mode.any": "Jakékoliv z těchto",
   "hashtag.column_settings.tag_mode.none": "Žádné z těchto",
   "hashtag.column_settings.tag_toggle": "Zahrnout v tomto sloupci dodatečné tagy",
-  "hashtag.follow": "Follow hashtag",
+  "hashtag.follow": "Sledovat hashtag",
   "hashtag.total_volume": "Total volume in the last {days, plural, one {day} other {{days} days}}",
-  "hashtag.unfollow": "Unfollow hashtag",
+  "hashtag.unfollow": "Zrušit sledování hashtagu",
   "home.column_settings.basic": "Základní",
   "home.column_settings.show_reblogs": "Zobrazit boosty",
   "home.column_settings.show_replies": "Zobrazit odpovědi",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Pro tyto hledané výrazy nebylo nic nenalezeno",
   "search_results.statuses": "Příspěvky",
   "search_results.statuses_fts_disabled": "Vyhledávání příspěvků podle jejich obsahu není na tomto Mastodon serveru povoleno.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {výsledek} few {výsledky} many {výsledků} other {výsledků}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Otevřít moderátorské rozhraní pro @{name}",
   "status.admin_status": "Otevřít tento příspěvek v moderátorském rozhraní",
   "status.block": "Zablokovat @{name}",
@@ -487,7 +492,7 @@
   "status.edited_x_times": "Upraven {count, plural, one {{count}krát} few {{count}krát} many {{count}krát} other {{count}krát}}",
   "status.embed": "Vložit na web",
   "status.favourite": "Oblíbit",
-  "status.filter": "Filter this post",
+  "status.filter": "Filtrovat tento příspěvek",
   "status.filtered": "Filtrováno",
   "status.hide": "Skrýt příspěvek",
   "status.history.created": "Uživatel {name} vytvořil {date}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Zobrazit méně pro všechny",
   "status.show_more": "Zobrazit více",
   "status.show_more_all": "Zobrazit více pro všechny",
+  "status.show_original": "Zobrazit původní",
   "status.show_thread": "Zobrazit vlákno",
+  "status.translate": "Přeložit",
+  "status.translated_from": "Přeloženo z {lang}",
   "status.uncached_media_warning": "Nedostupné",
   "status.unmute_conversation": "Odkrýt konverzaci",
   "status.unpin": "Odepnout z profilu",
+  "subscribed_languages.lead": "Po změně se objeví pouze příspěvky ve vybraných jazycích na vašem domě a zobrazí se seznam časových os. Pro příjem příspěvků ve všech jazycích nevyber žádnou.",
+  "subscribed_languages.save": "Uložit změny",
+  "subscribed_languages.target": "Změnit odebírané jazyky na {target}",
   "suggestions.dismiss": "Odmítnout návrh",
   "suggestions.header": "Mohlo by vás zajímat…",
   "tabs_bar.federated_timeline": "Federovaná",
diff --git a/app/javascript/mastodon/locales/cy.json b/app/javascript/mastodon/locales/cy.json
index cb1c90d69..f73b8cb48 100644
--- a/app/javascript/mastodon/locales/cy.json
+++ b/app/javascript/mastodon/locales/cy.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Yn eich dilyn chi",
   "account.hide_reblogs": "Cuddio bwstiau o @{name}",
   "account.joined": "Ymunodd {date}",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "Gwiriwyd perchnogaeth y ddolen yma ar {date}",
   "account.locked_info": "Mae'r statws preifatrwydd cyfrif hwn wedi'i osod i gloi. Mae'r perchennog yn adolygu'r sawl sy'n gallu eu dilyn.",
   "account.media": "Cyfryngau",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Dechrau",
   "getting_started.invite": "Gwahodd pobl",
   "getting_started.open_source_notice": "Mae Mastodon yn feddalwedd côd agored. Mae modd cyfrannu neu adrodd materion ar GitHUb ar {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Diogelwch",
-  "getting_started.terms": "Telerau Gwasanaeth",
   "hashtag.column_header.tag_mode.all": "a {additional}",
   "hashtag.column_header.tag_mode.any": "neu {additional}",
   "hashtag.column_header.tag_mode.none": "heb {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Methu dod o hyd i unrhyw beth ar gyfer y termau chwilio hyn",
   "search_results.statuses": "Postiadau",
   "search_results.statuses_fts_disabled": "Nid yw chwilio postiadau yn ôl eu cynnwys wedi'i alluogi ar y gweinydd Mastodon hwn.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, zero {canlyniad} one {canlyniad} two {ganlyniad} other {o ganlyniadau}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Agor rhyngwyneb goruwchwylio ar gyfer @{name}",
   "status.admin_status": "Agor y post hwn yn y rhyngwyneb goruwchwylio",
   "status.block": "Blocio @{name}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Dangos llai i bawb",
   "status.show_more": "Dangos mwy",
   "status.show_more_all": "Dangos mwy i bawb",
+  "status.show_original": "Show original",
   "status.show_thread": "Dangos edefyn",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "Dim ar gael",
   "status.unmute_conversation": "Dad-dawelu sgwrs",
   "status.unpin": "Dadbinio o'r proffil",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "Diswyddo",
   "suggestions.header": "Efallai y bydd gennych ddiddordeb mewn…",
   "tabs_bar.federated_timeline": "Ffederasiwn",
diff --git a/app/javascript/mastodon/locales/da.json b/app/javascript/mastodon/locales/da.json
index 8f015b50d..5ae3983a3 100644
--- a/app/javascript/mastodon/locales/da.json
+++ b/app/javascript/mastodon/locales/da.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Følger dig",
   "account.hide_reblogs": "Skjul boosts fra @{name}",
   "account.joined": "Tilmeldt {date}",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "Ejerskab af dette link blev tjekket {date}",
   "account.locked_info": "Denne kontos fortrolighedsstatus er sat til låst. Ejeren bedømmer manuelt, hvem der kan følge vedkommende.",
   "account.media": "Medier",
@@ -197,22 +198,22 @@
   "explore.trending_links": "Nyheder",
   "explore.trending_statuses": "Indlæg",
   "explore.trending_tags": "Hashtags",
-  "filter_modal.added.context_mismatch_explanation": "This filter category does not apply to the context in which you have accessed this post. If you want the post to be filtered in this context too, you will have to edit the filter.",
-  "filter_modal.added.context_mismatch_title": "Context mismatch!",
-  "filter_modal.added.expired_explanation": "This filter category has expired, you will need to change the expiration date for it to apply.",
-  "filter_modal.added.expired_title": "Expired filter!",
-  "filter_modal.added.review_and_configure": "To review and further configure this filter category, go to the {settings_link}.",
-  "filter_modal.added.review_and_configure_title": "Filter settings",
-  "filter_modal.added.settings_link": "settings page",
-  "filter_modal.added.short_explanation": "This post has been added to the following filter category: {title}.",
-  "filter_modal.added.title": "Filter added!",
-  "filter_modal.select_filter.context_mismatch": "does not apply to this context",
-  "filter_modal.select_filter.expired": "expired",
-  "filter_modal.select_filter.prompt_new": "New category: {name}",
-  "filter_modal.select_filter.search": "Search or create",
-  "filter_modal.select_filter.subtitle": "Use an existing category or create a new one",
-  "filter_modal.select_filter.title": "Filter this post",
-  "filter_modal.title.status": "Filter a post",
+  "filter_modal.added.context_mismatch_explanation": "Denne filterkategori omfatter ikke konteksten, hvorunder dette indlæg er tilgået. Redigér filteret, hvis indlægget også ønskes filtreret i denne kontekst.",
+  "filter_modal.added.context_mismatch_title": "Kontekstmisforhold!",
+  "filter_modal.added.expired_explanation": "Denne filterkategori er udløbet. Ændr dens udløbsdato, for at anvende den.",
+  "filter_modal.added.expired_title": "Udløbet filter!",
+  "filter_modal.added.review_and_configure": "Gå til {settings_link} for at gennemse og yderligere opsætte denne filterkategori.",
+  "filter_modal.added.review_and_configure_title": "Filterindstillinger",
+  "filter_modal.added.settings_link": "indstillingsside",
+  "filter_modal.added.short_explanation": "Dette indlæg er nu føjet til flg. filterkategori: {title}.",
+  "filter_modal.added.title": "Filter tilføjet!",
+  "filter_modal.select_filter.context_mismatch": "gælder ikke for denne kontekst",
+  "filter_modal.select_filter.expired": "udløbet",
+  "filter_modal.select_filter.prompt_new": "Ny kategori: {name}",
+  "filter_modal.select_filter.search": "Søg eller opret",
+  "filter_modal.select_filter.subtitle": "Vælg en eksisterende kategori eller opret en ny",
+  "filter_modal.select_filter.title": "Filtrér dette indlæg",
+  "filter_modal.title.status": "Filtrér et indlæg",
   "follow_recommendations.done": "Udført",
   "follow_recommendations.heading": "Følg personer du gerne vil se indlæg fra! Her er nogle forslag.",
   "follow_recommendations.lead": "Indlæg, fra personer du følger, vil fremgå kronologisk ordnet i dit hjemmefeed. Vær ikke bange for at begå fejl, da du altid og meget nemt kan ændre dit valg!",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Startmenu",
   "getting_started.invite": "Invitér folk",
   "getting_started.open_source_notice": "Mastodon er open-source software. Du kan bidrage eller anmelde fejl via GitHub {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Kontoindstillinger",
-  "getting_started.terms": "Tjenestevilkår",
   "hashtag.column_header.tag_mode.all": "og {additional}",
   "hashtag.column_header.tag_mode.any": "eller {additional}",
   "hashtag.column_header.tag_mode.none": "uden {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Ingen resultater for disse søgeord",
   "search_results.statuses": "Indlæg",
   "search_results.statuses_fts_disabled": "Søgning på indlæg efter deres indhold ikke aktiveret på denne Mastodon-server.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {resultat} other {resultater}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Åbn modereringsbrugerflade for @{name}",
   "status.admin_status": "Åbn dette indlæg i modereringsbrugerfladen",
   "status.block": "Blokér @{name}",
@@ -487,7 +492,7 @@
   "status.edited_x_times": "Redigeret {count, plural, one {{count} gang} other {{count} gange}}",
   "status.embed": "Indlejr",
   "status.favourite": "Favorit",
-  "status.filter": "Filter this post",
+  "status.filter": "Filtrér dette indlæg",
   "status.filtered": "Filtreret",
   "status.hide": "Skjul indlæg",
   "status.history.created": "{name} oprettet {date}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Vis mindre for alle",
   "status.show_more": "Vis mere",
   "status.show_more_all": "Vis mere for alle",
+  "status.show_original": "Vis original",
   "status.show_thread": "Vis tråd",
+  "status.translate": "Oversæt",
+  "status.translated_from": "Oversat fra {lang}",
   "status.uncached_media_warning": "Utilgængelig",
   "status.unmute_conversation": "Genaktivér samtale",
   "status.unpin": "Frigør fra profil",
+  "subscribed_languages.lead": "Kun indlæg på udvalgte sprog vil fremgå på Hjem og listetidslinjer efter ændringen. Vælg ingen for at modtage indlæg på alle sprog.",
+  "subscribed_languages.save": "Gem ændringer",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "Afvis foreslag",
   "suggestions.header": "Du er måske interesseret i…",
   "tabs_bar.federated_timeline": "Fælles",
diff --git a/app/javascript/mastodon/locales/de.json b/app/javascript/mastodon/locales/de.json
index 2df1dc0ea..6c72c3afc 100644
--- a/app/javascript/mastodon/locales/de.json
+++ b/app/javascript/mastodon/locales/de.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Folgt dir",
   "account.hide_reblogs": "Geteilte Beiträge von @{name} verbergen",
   "account.joined": "Beigetreten am {date}",
+  "account.languages": "Abonnierte Sprachen ändern",
   "account.link_verified_on": "Diesem Profil folgt niemand",
   "account.locked_info": "Der Privatsphärenstatus dieses Accounts wurde auf „gesperrt“ gesetzt. Die Person bestimmt manuell, wer ihm/ihr folgen darf.",
   "account.media": "Medien",
@@ -106,7 +107,7 @@
   "compose_form.poll.option_placeholder": "Wahl {number}",
   "compose_form.poll.remove_option": "Wahl entfernen",
   "compose_form.poll.switch_to_multiple": "Umfrage ändern, um mehrere Optionen zu erlauben",
-  "compose_form.poll.switch_to_single": "Umfrage ändern, um eine einzige Wahl zu erlauben",
+  "compose_form.poll.switch_to_single": "Umfrage ändern, sodass nur eine einzige Auswahl erlaubt ist",
   "compose_form.publish": "Veröffentlichen",
   "compose_form.publish_loud": "{publish}!",
   "compose_form.save_changes": "Änderungen speichern",
@@ -175,20 +176,20 @@
   "empty_column.explore_statuses": "Momentan ist nichts im Trend. Schau später wieder vorbei!",
   "empty_column.favourited_statuses": "Du hast noch keine favorisierten Tröts. Wenn du einen favorisierst, wird er hier erscheinen.",
   "empty_column.favourites": "Noch niemand hat diesen Beitrag favorisiert. Sobald es jemand tut, wird das hier angezeigt.",
-  "empty_column.follow_recommendations": "Es sieht so aus, als könnten keine Vorschläge für dich generiert werden. Du kannst versuchen nach Leuten zu suchen, die du vielleicht kennst oder du kannst angesagte Hashtags erkunden.",
+  "empty_column.follow_recommendations": "Es sieht so aus, als könnten keine Vorschläge für dich generiert werden. Du kannst versuchen, nach Leuten zu suchen, die du vielleicht kennst, oder du kannst angesagte Hashtags erkunden.",
   "empty_column.follow_requests": "Du hast noch keine Folge-Anfragen. Sobald du eine erhältst, wird sie hier angezeigt.",
   "empty_column.hashtag": "Unter diesem Hashtag gibt es noch nichts.",
   "empty_column.home": "Deine Startseite ist leer! Folge mehr Leuten, um sie zu füllen. {suggestions}",
   "empty_column.home.suggestions": "Ein paar Vorschläge ansehen",
   "empty_column.list": "Diese Liste ist derzeit leer. Wenn Konten auf dieser Liste neue Beiträge veröffentlichen werden sie hier erscheinen.",
-  "empty_column.lists": "Du hast noch keine Listen. Wenn du eine anlegst, wird sie hier angezeigt.",
+  "empty_column.lists": "Du hast noch keine Listen. Wenn du eine anlegst, wird sie hier angezeigt werden.",
   "empty_column.mutes": "Du hast keine Profile stummgeschaltet.",
   "empty_column.notifications": "Du hast noch keine Mitteilungen. Interagiere mit anderen, um ins Gespräch zu kommen.",
   "empty_column.public": "Hier ist nichts zu sehen! Schreibe etwas öffentlich oder folge Profilen von anderen Servern, um die Zeitleiste aufzufüllen",
-  "error.unexpected_crash.explanation": "Aufgrund eines Fehlers in unserem Code oder einer Browsereinkompatibilität konnte diese Seite nicht korrekt angezeigt werden.",
+  "error.unexpected_crash.explanation": "Aufgrund eines Fehlers in unserem Code oder einer Browser-Inkompatibilität konnte diese Seite nicht korrekt angezeigt werden.",
   "error.unexpected_crash.explanation_addons": "Diese Seite konnte nicht korrekt angezeigt werden. Dieser Fehler wird wahrscheinlich durch ein Browser-Add-on oder automatische Übersetzungswerkzeuge verursacht.",
-  "error.unexpected_crash.next_steps": "Versuche die Seite zu aktualisieren. Wenn das nicht hilft, kannst du Mastodon über einen anderen Browser oder eine native App verwenden.",
-  "error.unexpected_crash.next_steps_addons": "Versuche sie zu deaktivieren und lade dann die Seite neu. Wenn das Problem weiterhin besteht, solltest du Mastodon über einen anderen Browser oder eine native App nutzen.",
+  "error.unexpected_crash.next_steps": "Versuche, die Seite zu aktualisieren. Wenn das nicht hilft, kannst du Mastodon über einen anderen Browser oder eine native App verwenden.",
+  "error.unexpected_crash.next_steps_addons": "Versuche, sie zu deaktivieren, und lade dann die Seite neu. Wenn das Problem weiterhin besteht, solltest du Mastodon über einen anderen Browser oder eine native App nutzen.",
   "errors.unexpected_crash.copy_stacktrace": "Fehlerlog in die Zwischenablage kopieren",
   "errors.unexpected_crash.report_issue": "Problem melden",
   "explore.search_results": "Suchergebnisse",
@@ -197,22 +198,22 @@
   "explore.trending_links": "Nachrichten",
   "explore.trending_statuses": "Beiträge",
   "explore.trending_tags": "Hashtags",
-  "filter_modal.added.context_mismatch_explanation": "This filter category does not apply to the context in which you have accessed this post. If you want the post to be filtered in this context too, you will have to edit the filter.",
-  "filter_modal.added.context_mismatch_title": "Context mismatch!",
-  "filter_modal.added.expired_explanation": "This filter category has expired, you will need to change the expiration date for it to apply.",
-  "filter_modal.added.expired_title": "Expired filter!",
-  "filter_modal.added.review_and_configure": "To review and further configure this filter category, go to the {settings_link}.",
-  "filter_modal.added.review_and_configure_title": "Filter settings",
-  "filter_modal.added.settings_link": "settings page",
-  "filter_modal.added.short_explanation": "This post has been added to the following filter category: {title}.",
-  "filter_modal.added.title": "Filter added!",
-  "filter_modal.select_filter.context_mismatch": "does not apply to this context",
-  "filter_modal.select_filter.expired": "expired",
-  "filter_modal.select_filter.prompt_new": "New category: {name}",
-  "filter_modal.select_filter.search": "Search or create",
-  "filter_modal.select_filter.subtitle": "Use an existing category or create a new one",
-  "filter_modal.select_filter.title": "Filter this post",
-  "filter_modal.title.status": "Filter a post",
+  "filter_modal.added.context_mismatch_explanation": "Diese Filterkategorie gilt nicht für den Kontext, in welchem du auf diesen Beitrag zugegriffen hast. Wenn der Beitrag auch in diesem Kontext gefiltert werden soll, musst du den Filter bearbeiten.",
+  "filter_modal.added.context_mismatch_title": "Kontext stimmt nicht überein!",
+  "filter_modal.added.expired_explanation": "Diese Filterkategrie ist abgelaufen, du musst das Ablaufdatum für diese Kategorie ändern.",
+  "filter_modal.added.expired_title": "Abgelaufener Filter!",
+  "filter_modal.added.review_and_configure": "Um diese Filterkategorie zu überprüfen und weiter zu konfigurieren, gehe zu {settings_link}.",
+  "filter_modal.added.review_and_configure_title": "Filtereinstellungen",
+  "filter_modal.added.settings_link": "Einstellungsseite",
+  "filter_modal.added.short_explanation": "Dieser Post wurde zu folgender Filterkategorie hinzugefügt: {title}.",
+  "filter_modal.added.title": "Filter hinzugefügt!",
+  "filter_modal.select_filter.context_mismatch": "gilt nicht für diesen Kontext",
+  "filter_modal.select_filter.expired": "abgelaufen",
+  "filter_modal.select_filter.prompt_new": "Neue Kategorie: {name}",
+  "filter_modal.select_filter.search": "Suchen oder Erstellen",
+  "filter_modal.select_filter.subtitle": "Eine existierende Kategorie benutzen oder eine erstellen",
+  "filter_modal.select_filter.title": "Diesen Beitrag filtern",
+  "filter_modal.title.status": "Einen Beitrag filtern",
   "follow_recommendations.done": "Fertig",
   "follow_recommendations.heading": "Folge Leuten, von denen du Beiträge sehen möchtest! Hier sind einige Vorschläge.",
   "follow_recommendations.lead": "Beiträge von Personen, denen du folgst, werden in chronologischer Reihenfolge auf deiner Startseite angezeigt. Hab keine Angst, Fehler zu machen, du kannst den Leuten jederzeit wieder entfolgen!",
@@ -226,16 +227,16 @@
   "getting_started.heading": "Erste Schritte",
   "getting_started.invite": "Leute einladen",
   "getting_started.open_source_notice": "Mastodon ist quelloffene Software. Du kannst auf GitHub unter {github} dazu beitragen oder Probleme melden.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Konto & Sicherheit",
-  "getting_started.terms": "Nutzungsbedingungen",
   "hashtag.column_header.tag_mode.all": "und {additional}",
   "hashtag.column_header.tag_mode.any": "oder {additional}",
   "hashtag.column_header.tag_mode.none": "ohne {additional}",
   "hashtag.column_settings.select.no_options_message": "Keine Vorschläge gefunden",
   "hashtag.column_settings.select.placeholder": "Hashtags eintragen…",
   "hashtag.column_settings.tag_mode.all": "All diese",
-  "hashtag.column_settings.tag_mode.any": "Eins von diesen",
-  "hashtag.column_settings.tag_mode.none": "Keins von diesen",
+  "hashtag.column_settings.tag_mode.any": "Eines von diesen",
+  "hashtag.column_settings.tag_mode.none": "Keines von diesen",
   "hashtag.column_settings.tag_toggle": "Zusätzliche Hashtags für diese Spalte einfügen",
   "hashtag.follow": "Hashtag folgen",
   "hashtag.total_volume": "Gesamtes Aufkommen {days, plural, one {am letzten Tag} other {in den letzten {days} Tagen}}",
@@ -300,7 +301,7 @@
   "lists.replies_policy.list": "Mitglieder der Liste",
   "lists.replies_policy.none": "Niemand",
   "lists.replies_policy.title": "Antworten anzeigen für:",
-  "lists.search": "Suche nach Leuten denen du folgst",
+  "lists.search": "Suche nach Leuten, denen du folgst",
   "lists.subheading": "Deine Listen",
   "load_pending": "{count, plural, one {# neuer Beitrag} other {# neue Beiträge}}",
   "loading_indicator.label": "Wird geladen …",
@@ -341,7 +342,7 @@
   "notification.follow_request": "{name} möchte dir folgen",
   "notification.mention": "{name} hat dich erwähnt",
   "notification.own_poll": "Deine Umfrage ist beendet",
-  "notification.poll": "Eine Umfrage in der du abgestimmt hast ist vorbei",
+  "notification.poll": "Eine Umfrage, an der du teilgenommen hast, ist vorbei",
   "notification.reblog": "{name} hat deinen Beitrag geteilt",
   "notification.status": "{name} hat gerade etwas gepostet",
   "notification.update": "{name} bearbeitete einen Beitrag",
@@ -430,7 +431,7 @@
   "report.forward": "An {target} weiterleiten",
   "report.forward_hint": "Dieses Konto gehört zu einem anderen Server. Soll eine anonymisierte Kopie der Meldung auch dorthin geschickt werden?",
   "report.mute": "Stummschalten",
-  "report.mute_explanation": "Du wirst die Beiträge vom Konto nicht mehr sehen. Das Konto kann dir immernoch folgen und die Person hinter dem Konto wird deine Beiträge sehen können und nicht wissen, dass du sie stumm geschaltet hast.",
+  "report.mute_explanation": "Du wirst die Beiträge vom Konto nicht mehr sehen. Das Konto kann dir immer noch folgen, und die Person hinter dem Konto wird deine Beiträge sehen können und nicht wissen, dass du sie stummgeschaltet hast.",
   "report.next": "Weiter",
   "report.placeholder": "Zusätzliche Kommentare",
   "report.reasons.dislike": "Das gefällt mir nicht",
@@ -447,7 +448,7 @@
   "report.statuses.title": "Gibt es Beiträge, die diesen Bericht unterstützen?",
   "report.submit": "Absenden",
   "report.target": "{target} melden",
-  "report.thanks.take_action": "Das sind deine Möglichkeiten, zu bestimmen, was du auf Mastodon sehen möchtest:",
+  "report.thanks.take_action": "Das sind deine Möglichkeiten zu bestimmen, was du auf Mastodon sehen möchtest:",
   "report.thanks.take_action_actionable": "Während wir dies überprüfen, kannst du gegen @{name} vorgehen:",
   "report.thanks.title": "Möchtest du das nicht sehen?",
   "report.thanks.title_actionable": "Vielen Dank für die Meldung, wir werden uns das ansehen.",
@@ -460,7 +461,7 @@
   "report_notification.open": "Meldung öffnen",
   "search.placeholder": "Suche",
   "search_popout.search_format": "Fortgeschrittenes Suchformat",
-  "search_popout.tips.full_text": "Einfache Texteingabe gibt Beiträge, die du geschrieben, favorisiert und geteilt hast zurück. Außerdem auch Beiträge in denen du erwähnt wurdest, aber auch passende Nutzernamen, Anzeigenamen oder Hashtags.",
+  "search_popout.tips.full_text": "Einfache Texteingabe gibt Beiträge, die du geschrieben, favorisiert und geteilt hast, zurück; außerdem auch Beiträge, in denen du erwähnt wurdest, aber auch passende Nutzernamen, Anzeigenamen oder Hashtags.",
   "search_popout.tips.hashtag": "Hashtag",
   "search_popout.tips.status": "Tröt",
   "search_popout.tips.text": "Einfache Texteingabe gibt Anzeigenamen, Benutzernamen und Hashtags zurück",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Nichts für diese Suchbegriffe gefunden",
   "search_results.statuses": "Beiträge",
   "search_results.statuses_fts_disabled": "Die Suche für Beiträge nach ihrem Inhalt ist auf diesem Mastodon-Server deaktiviert.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {Ergebnis} other {Ergebnisse}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Öffne Moderationsoberfläche für @{name}",
   "status.admin_status": "Öffne Beitrag in der Moderationsoberfläche",
   "status.block": "Blockiere @{name}",
@@ -487,7 +492,7 @@
   "status.edited_x_times": "{count, plural, one {{count} mal} other {{count} mal}} bearbeitet",
   "status.embed": "Einbetten",
   "status.favourite": "Favorisieren",
-  "status.filter": "Filter this post",
+  "status.filter": "Diesen Beitrag filtern",
   "status.filtered": "Gefiltert",
   "status.hide": "Tröt verbergen",
   "status.history.created": "{name} erstellte {date}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Alle Inhaltswarnungen zuklappen",
   "status.show_more": "Mehr anzeigen",
   "status.show_more_all": "Alle Inhaltswarnungen aufklappen",
+  "status.show_original": "Original anzeigen",
   "status.show_thread": "Zeige Konversation",
+  "status.translate": "Übersetzen",
+  "status.translated_from": "Aus {lang} übersetzt",
   "status.uncached_media_warning": "Nicht verfügbar",
   "status.unmute_conversation": "Stummschaltung von Konversation aufheben",
   "status.unpin": "Vom Profil lösen",
+  "subscribed_languages.lead": "Nur Beiträge in ausgewählten Sprachen werden nach der Änderung auf deiner Startseite und den Listen angezeigt. Wähle keine aus, um Beiträge in allen Sprachen zu erhalten.",
+  "subscribed_languages.save": "Änderungen speichern",
+  "subscribed_languages.target": "Abonnierte Sprachen für {target} ändern",
   "suggestions.dismiss": "Empfehlung ausblenden",
   "suggestions.header": "Du bist vielleicht interessiert an…",
   "tabs_bar.federated_timeline": "Föderation",
diff --git a/app/javascript/mastodon/locales/defaultMessages.json b/app/javascript/mastodon/locales/defaultMessages.json
index a2f5b7174..d18e3d114 100644
--- a/app/javascript/mastodon/locales/defaultMessages.json
+++ b/app/javascript/mastodon/locales/defaultMessages.json
@@ -654,6 +654,18 @@
         "id": "status.read_more"
       },
       {
+        "defaultMessage": "Translated from {lang}",
+        "id": "status.translated_from"
+      },
+      {
+        "defaultMessage": "Show original",
+        "id": "status.show_original"
+      },
+      {
+        "defaultMessage": "Translate",
+        "id": "status.translate"
+      },
+      {
         "defaultMessage": "Show more",
         "id": "status.show_more"
       },
@@ -1031,6 +1043,10 @@
         "id": "status.admin_account"
       },
       {
+        "defaultMessage": "Change subscribed languages",
+        "id": "account.languages"
+      },
+      {
         "defaultMessage": "Follows you",
         "id": "account.follows_you"
       },
@@ -1827,6 +1843,19 @@
   {
     "descriptors": [
       {
+        "defaultMessage": "Nothing is trending right now. Check back later!",
+        "id": "empty_column.explore_statuses"
+      }
+    ],
+    "path": "app/javascript/mastodon/features/explore/links.json"
+  },
+  {
+    "descriptors": [
+      {
+        "defaultMessage": "Search for {q}",
+        "id": "search_results.title"
+      },
+      {
         "defaultMessage": "Could not find anything for these search terms",
         "id": "search_results.nothing_found"
       },
@@ -1861,6 +1890,24 @@
   {
     "descriptors": [
       {
+        "defaultMessage": "Nothing is trending right now. Check back later!",
+        "id": "empty_column.explore_statuses"
+      }
+    ],
+    "path": "app/javascript/mastodon/features/explore/suggestions.json"
+  },
+  {
+    "descriptors": [
+      {
+        "defaultMessage": "Nothing is trending right now. Check back later!",
+        "id": "empty_column.explore_statuses"
+      }
+    ],
+    "path": "app/javascript/mastodon/features/explore/tags.json"
+  },
+  {
+    "descriptors": [
+      {
         "defaultMessage": "Favourites",
         "id": "column.favourites"
       },
@@ -3021,6 +3068,27 @@
   {
     "descriptors": [
       {
+        "defaultMessage": "Public",
+        "id": "privacy.public.short"
+      },
+      {
+        "defaultMessage": "Unlisted",
+        "id": "privacy.unlisted.short"
+      },
+      {
+        "defaultMessage": "Followers-only",
+        "id": "privacy.private.short"
+      },
+      {
+        "defaultMessage": "Mentioned people only",
+        "id": "privacy.direct.short"
+      }
+    ],
+    "path": "app/javascript/mastodon/features/report/components/status_check_box.json"
+  },
+  {
+    "descriptors": [
+      {
         "defaultMessage": "Which rules are being violated?",
         "id": "report.rules.title"
       },
@@ -3353,6 +3421,27 @@
   {
     "descriptors": [
       {
+        "defaultMessage": "Close",
+        "id": "lightbox.close"
+      },
+      {
+        "defaultMessage": "Change subscribed languages for {target}",
+        "id": "subscribed_languages.target"
+      },
+      {
+        "defaultMessage": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+        "id": "subscribed_languages.lead"
+      },
+      {
+        "defaultMessage": "Save changes",
+        "id": "subscribed_languages.save"
+      }
+    ],
+    "path": "app/javascript/mastodon/features/subscribed_languages_modal/index.json"
+  },
+  {
+    "descriptors": [
+      {
         "defaultMessage": "Are you sure you want to block {name}?",
         "id": "confirmations.block.message"
       },
@@ -3633,8 +3722,8 @@
         "id": "navigation_bar.apps"
       },
       {
-        "defaultMessage": "Terms of service",
-        "id": "getting_started.terms"
+        "defaultMessage": "Privacy Policy",
+        "id": "getting_started.privacy_policy"
       },
       {
         "defaultMessage": "Developers",
@@ -3782,6 +3871,23 @@
   {
     "descriptors": [
       {
+        "defaultMessage": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
+        "id": "sign_in_banner.text"
+      },
+      {
+        "defaultMessage": "Sign in",
+        "id": "sign_in_banner.sign_in"
+      },
+      {
+        "defaultMessage": "Create account",
+        "id": "sign_in_banner.create_account"
+      }
+    ],
+    "path": "app/javascript/mastodon/features/ui/components/sign_in_banner.json"
+  },
+  {
+    "descriptors": [
+      {
         "defaultMessage": "Home",
         "id": "tabs_bar.home"
       },
diff --git a/app/javascript/mastodon/locales/el.json b/app/javascript/mastodon/locales/el.json
index 999f67c73..c03a93076 100644
--- a/app/javascript/mastodon/locales/el.json
+++ b/app/javascript/mastodon/locales/el.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Σε ακολουθεί",
   "account.hide_reblogs": "Απόκρυψη προωθήσεων από @{name}",
   "account.joined": "Μέλος από τις {date}",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "Η ιδιοκτησία αυτού του συνδέσμου ελέχθηκε την {date}",
   "account.locked_info": "Η κατάσταση απορρήτου αυτού του λογαριασμού είναι κλειδωμένη. Ο ιδιοκτήτης επιβεβαιώνει χειροκίνητα ποιος μπορεί να τον ακολουθήσει.",
   "account.media": "Πολυμέσα",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Αφετηρία",
   "getting_started.invite": "Προσκάλεσε κόσμο",
   "getting_started.open_source_notice": "Το Mastodon είναι ελεύθερο λογισμικό. Μπορείς να συνεισφέρεις ή να αναφέρεις ζητήματα στο GitHub στο {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Ασφάλεια",
-  "getting_started.terms": "Όροι χρήσης",
   "hashtag.column_header.tag_mode.all": "και {additional}",
   "hashtag.column_header.tag_mode.any": "ή {additional}",
   "hashtag.column_header.tag_mode.none": "χωρίς {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Could not find anything for these search terms",
   "search_results.statuses": "Τουτ",
   "search_results.statuses_fts_disabled": "Η αναζήτηση τουτ βάσει του περιεχόμενού τους δεν είναι ενεργοποιημένη σε αυτό τον κόμβο.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, zero {αποτελέσματα} one {αποτέλεσμα} other {αποτελέσματα}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Άνοιγμα λειτουργίας διαμεσολάβησης για τον/την @{name}",
   "status.admin_status": "Άνοιγμα αυτής της δημοσίευσης στη λειτουργία διαμεσολάβησης",
   "status.block": "Αποκλεισμός @{name}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Δείξε λιγότερα για όλα",
   "status.show_more": "Δείξε περισσότερα",
   "status.show_more_all": "Δείξε περισσότερα για όλα",
+  "status.show_original": "Εμφάνιση αρχικού",
   "status.show_thread": "Εμφάνιση νήματος",
+  "status.translate": "Μετάφραση",
+  "status.translated_from": "Μεταφράστηκε από {lang}",
   "status.uncached_media_warning": "Μη διαθέσιμα",
   "status.unmute_conversation": "Διέκοψε την αποσιώπηση της συζήτησης",
   "status.unpin": "Ξεκαρφίτσωσε από το προφίλ",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Αποθήκευση αλλαγών",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "Απόρριψη πρότασης",
   "suggestions.header": "Ίσως να ενδιαφέρεσαι για…",
   "tabs_bar.federated_timeline": "Ομοσπονδιακή",
diff --git a/app/javascript/mastodon/locales/en-GB.json b/app/javascript/mastodon/locales/en-GB.json
index 2287dcda5..3e418b9d3 100644
--- a/app/javascript/mastodon/locales/en-GB.json
+++ b/app/javascript/mastodon/locales/en-GB.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Follows you",
   "account.hide_reblogs": "Hide boosts from @{name}",
   "account.joined": "Joined {date}",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.",
   "account.media": "Media",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Getting started",
   "getting_started.invite": "Invite people",
   "getting_started.open_source_notice": "Mastodon is open source software. You can contribute or report issues on GitHub at {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Security",
-  "getting_started.terms": "Terms of service",
   "hashtag.column_header.tag_mode.all": "and {additional}",
   "hashtag.column_header.tag_mode.any": "or {additional}",
   "hashtag.column_header.tag_mode.none": "without {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Could not find anything for these search terms",
   "search_results.statuses": "Posts",
   "search_results.statuses_fts_disabled": "Searching posts by their content is not enabled on this Mastodon server.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {result} other {results}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Open moderation interface for @{name}",
   "status.admin_status": "Open this status in the moderation interface",
   "status.block": "Block @{name}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Show less for all",
   "status.show_more": "Show more",
   "status.show_more_all": "Show more for all",
+  "status.show_original": "Show original",
   "status.show_thread": "Show thread",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "Not available",
   "status.unmute_conversation": "Unmute conversation",
   "status.unpin": "Unpin from profile",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "Dismiss suggestion",
   "suggestions.header": "You might be interested in…",
   "tabs_bar.federated_timeline": "Federated",
diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json
index 5eb1fe313..a2d08d3a6 100644
--- a/app/javascript/mastodon/locales/en.json
+++ b/app/javascript/mastodon/locales/en.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Follows you",
   "account.hide_reblogs": "Hide boosts from @{name}",
   "account.joined": "Joined {date}",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.",
   "account.media": "Media",
@@ -230,8 +231,8 @@
   "getting_started.heading": "Getting started",
   "getting_started.invite": "Invite people",
   "getting_started.open_source_notice": "Mastodon is open source software. You can contribute or report issues on GitHub at {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Account settings",
-  "getting_started.terms": "Terms of service",
   "hashtag.column_header.tag_mode.all": "and {additional}",
   "hashtag.column_header.tag_mode.any": "or {additional}",
   "hashtag.column_header.tag_mode.none": "without {additional}",
@@ -476,7 +477,11 @@
   "search_results.nothing_found": "Could not find anything for these search terms",
   "search_results.statuses": "Posts",
   "search_results.statuses_fts_disabled": "Searching posts by their content is not enabled on this Mastodon server.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {result} other {results}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Open moderation interface for @{name}",
   "status.admin_status": "Open this post in the moderation interface",
   "status.block": "Block @{name}",
@@ -523,10 +528,16 @@
   "status.show_less_all": "Show less for all",
   "status.show_more": "Show more",
   "status.show_more_all": "Show more for all",
+  "status.show_original": "Show original",
   "status.show_thread": "Show thread",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "Not available",
   "status.unmute_conversation": "Unmute conversation",
   "status.unpin": "Unpin from profile",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "Dismiss suggestion",
   "suggestions.header": "You might be interested in…",
   "tabs_bar.federated_timeline": "Federated",
diff --git a/app/javascript/mastodon/locales/eo.json b/app/javascript/mastodon/locales/eo.json
index 082c53de7..b86fcb703 100644
--- a/app/javascript/mastodon/locales/eo.json
+++ b/app/javascript/mastodon/locales/eo.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Sekvas vin",
   "account.hide_reblogs": "Kaŝi la plusendojn de @{name}",
   "account.joined": "Kuniĝis {date}",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "La posedanto de tiu ligilo estis kontrolita je {date}",
   "account.locked_info": "La privateco de tiu konto estas elektita kiel fermita. La posedanto povas mane akcepti tiun, kiu povas sekvi rin.",
   "account.media": "Aŭdovidaĵoj",
@@ -59,7 +60,7 @@
   "alert.unexpected.title": "Aj!",
   "announcement.announcement": "Anonco",
   "attachments_list.unprocessed": "(neprilaborita)",
-  "audio.hide": "Hide audio",
+  "audio.hide": "Kaŝi aŭdion",
   "autosuggest_hashtag.per_week": "{count} semajne",
   "boost_modal.combo": "Vi povas premi {combo} por preterpasi sekvafoje",
   "bundle_column_error.body": "Io misfunkciis en la ŝargado de ĉi tiu elemento.",
@@ -202,16 +203,16 @@
   "filter_modal.added.expired_explanation": "This filter category has expired, you will need to change the expiration date for it to apply.",
   "filter_modal.added.expired_title": "Expired filter!",
   "filter_modal.added.review_and_configure": "To review and further configure this filter category, go to the {settings_link}.",
-  "filter_modal.added.review_and_configure_title": "Filter settings",
-  "filter_modal.added.settings_link": "settings page",
+  "filter_modal.added.review_and_configure_title": "Filtrilopcioj",
+  "filter_modal.added.settings_link": "opciopaĝo",
   "filter_modal.added.short_explanation": "This post has been added to the following filter category: {title}.",
   "filter_modal.added.title": "Filter added!",
   "filter_modal.select_filter.context_mismatch": "does not apply to this context",
-  "filter_modal.select_filter.expired": "expired",
-  "filter_modal.select_filter.prompt_new": "New category: {name}",
-  "filter_modal.select_filter.search": "Search or create",
+  "filter_modal.select_filter.expired": "eksvalidiĝinta",
+  "filter_modal.select_filter.prompt_new": "Nova klaso: {name}",
+  "filter_modal.select_filter.search": "Serĉi aŭ krei",
   "filter_modal.select_filter.subtitle": "Use an existing category or create a new one",
-  "filter_modal.select_filter.title": "Filter this post",
+  "filter_modal.select_filter.title": "Filtri ĉi afiŝo",
   "filter_modal.title.status": "Filter a post",
   "follow_recommendations.done": "Farita",
   "follow_recommendations.heading": "Sekvi la personojn kies mesaĝojn vi volas vidi! Jen iom da sugestoj.",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Por komenci",
   "getting_started.invite": "Inviti homojn",
   "getting_started.open_source_notice": "Mastodon estas malfermitkoda programo. Vi povas kontribui aŭ raporti problemojn en GitHub je {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Sekureco",
-  "getting_started.terms": "Kondiĉoj de la servo",
   "hashtag.column_header.tag_mode.all": "kaj {additional}",
   "hashtag.column_header.tag_mode.any": "aŭ {additional}",
   "hashtag.column_header.tag_mode.none": "sen {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Povis trovi nenion por ĉi tiuj serĉaj terminoj",
   "search_results.statuses": "Mesaĝoj",
   "search_results.statuses_fts_disabled": "Serĉi mesaĝojn laŭ enhavo ne estas ebligita en ĉi tiu Mastodon-servilo.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {rezulto} other {rezultoj}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Malfermi la kontrolan interfacon por @{name}",
   "status.admin_status": "Malfermi ĉi tiun mesaĝon en la kontrola interfaco",
   "status.block": "Bloki @{name}",
@@ -487,7 +492,7 @@
   "status.edited_x_times": "Redactita {count, plural, one {{count} fojon} other {{count} fojojn}}",
   "status.embed": "Enkorpigi",
   "status.favourite": "Aldoni al viaj preferaĵoj",
-  "status.filter": "Filter this post",
+  "status.filter": "Filtri ĉi afiŝo",
   "status.filtered": "Filtrita",
   "status.hide": "Kaŝi la mesaĝon",
   "status.history.created": "{name} kreis {date}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Montri malpli ĉiun",
   "status.show_more": "Montri pli",
   "status.show_more_all": "Montri pli ĉiun",
+  "status.show_original": "Show original",
   "status.show_thread": "Montri la mesaĝaron",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "Nedisponebla",
   "status.unmute_conversation": "Malsilentigi la konversacion",
   "status.unpin": "Depingli de profilo",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "Forigi la proponon",
   "suggestions.header": "Vi povus interesiĝi pri…",
   "tabs_bar.federated_timeline": "Fratara",
diff --git a/app/javascript/mastodon/locales/es-AR.json b/app/javascript/mastodon/locales/es-AR.json
index 8e4b906a2..9d1477d86 100644
--- a/app/javascript/mastodon/locales/es-AR.json
+++ b/app/javascript/mastodon/locales/es-AR.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Te sigue",
   "account.hide_reblogs": "Ocultar adhesiones de @{name}",
   "account.joined": "En este servidor desde {date}",
+  "account.languages": "Cambiar idiomas suscritos",
   "account.link_verified_on": "La propiedad de este enlace fue verificada el {date}",
   "account.locked_info": "Esta cuenta es privada. El propietario manualmente revisa quién puede seguirle.",
   "account.media": "Medios",
@@ -197,22 +198,22 @@
   "explore.trending_links": "Noticias",
   "explore.trending_statuses": "Mensajes",
   "explore.trending_tags": "Etiquetas",
-  "filter_modal.added.context_mismatch_explanation": "This filter category does not apply to the context in which you have accessed this post. If you want the post to be filtered in this context too, you will have to edit the filter.",
-  "filter_modal.added.context_mismatch_title": "Context mismatch!",
-  "filter_modal.added.expired_explanation": "This filter category has expired, you will need to change the expiration date for it to apply.",
-  "filter_modal.added.expired_title": "Expired filter!",
-  "filter_modal.added.review_and_configure": "To review and further configure this filter category, go to the {settings_link}.",
-  "filter_modal.added.review_and_configure_title": "Filter settings",
-  "filter_modal.added.settings_link": "settings page",
-  "filter_modal.added.short_explanation": "This post has been added to the following filter category: {title}.",
-  "filter_modal.added.title": "Filter added!",
-  "filter_modal.select_filter.context_mismatch": "does not apply to this context",
-  "filter_modal.select_filter.expired": "expired",
-  "filter_modal.select_filter.prompt_new": "New category: {name}",
-  "filter_modal.select_filter.search": "Search or create",
-  "filter_modal.select_filter.subtitle": "Use an existing category or create a new one",
-  "filter_modal.select_filter.title": "Filter this post",
-  "filter_modal.title.status": "Filter a post",
+  "filter_modal.added.context_mismatch_explanation": "Esta categoría de filtro no se aplica al contexto en el que accediste a este mensaje. Si querés que el mensaje sea filtrado también en este contexto, vas a tener que editar el filtro.",
+  "filter_modal.added.context_mismatch_title": "¡El contexto no coincide!",
+  "filter_modal.added.expired_explanation": "Esta categoría de filtro caducó; vas a necesitar cambiar la fecha de caducidad para que se aplique.",
+  "filter_modal.added.expired_title": "¡Filtro caducado!",
+  "filter_modal.added.review_and_configure": "Para revisar y configurar esta categoría de filtros, visitá a la {settings_link}.",
+  "filter_modal.added.review_and_configure_title": "Configuración de filtro",
+  "filter_modal.added.settings_link": "página de configuración",
+  "filter_modal.added.short_explanation": "Este mensaje fue agregado a la siguiente categoría de filtros: {title}.",
+  "filter_modal.added.title": "¡Filtro agregado!",
+  "filter_modal.select_filter.context_mismatch": "no aplica a este contexto",
+  "filter_modal.select_filter.expired": "expirado",
+  "filter_modal.select_filter.prompt_new": "Nueva categoría: {name}",
+  "filter_modal.select_filter.search": "Buscar o crear",
+  "filter_modal.select_filter.subtitle": "Usar una categoría existente o crear una nueva",
+  "filter_modal.select_filter.title": "Filtrar este mensaje",
+  "filter_modal.title.status": "Filtrar un mensaje",
   "follow_recommendations.done": "Listo",
   "follow_recommendations.heading": "¡Seguí cuentas cuyos mensajes te gustaría ver! Acá tenés algunas sugerencias.",
   "follow_recommendations.lead": "Los mensajes de las cuentas que seguís aparecerán en orden cronológico en la columna \"Inicio\". No tengás miedo de meter la pata, ¡podés dejar de seguir cuentas fácilmente en cualquier momento!",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Introducción",
   "getting_started.invite": "Invitar gente",
   "getting_started.open_source_notice": "Mastodon es software libre. Podés contribuir o informar errores en {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Configuración de la cuenta",
-  "getting_started.terms": "Términos del servicio",
   "hashtag.column_header.tag_mode.all": "y {additional}",
   "hashtag.column_header.tag_mode.any": "o {additional}",
   "hashtag.column_header.tag_mode.none": "sin {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "No se pudo encontrar nada para estos términos de búsqueda",
   "search_results.statuses": "Mensajes",
   "search_results.statuses_fts_disabled": "No se pueden buscar mensajes por contenido en este servidor de Mastodon.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {resultado} other {resultados}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Abrir interface de moderación para @{name}",
   "status.admin_status": "Abrir este mensaje en la interface de moderación",
   "status.block": "Bloquear a @{name}",
@@ -487,7 +492,7 @@
   "status.edited_x_times": "Editado {count, plural, one {{count} vez} other {{count} veces}}",
   "status.embed": "Insertar",
   "status.favourite": "Marcar como favorito",
-  "status.filter": "Filter this post",
+  "status.filter": "Filtrar este mensaje",
   "status.filtered": "Filtrado",
   "status.hide": "Ocultar mensaje",
   "status.history.created": "Creado por {name} el {date}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Mostrar menos para todo",
   "status.show_more": "Mostrar más",
   "status.show_more_all": "Mostrar más para todo",
+  "status.show_original": "Mostrar original",
   "status.show_thread": "Mostrar hilo",
+  "status.translate": "Traducir",
+  "status.translated_from": "Traducido desde el {lang}",
   "status.uncached_media_warning": "No disponible",
   "status.unmute_conversation": "Dejar de silenciar conversación",
   "status.unpin": "Dejar de fijar",
+  "subscribed_languages.lead": "Después del cambio, sólo los mensajes en los idiomas seleccionados aparecerán en tu línea temporal Principal y en las líneas de tiempo de lista. No seleccionés ningún idioma para poder recibir mensajes en todos los idiomas.",
+  "subscribed_languages.save": "Guardar cambios",
+  "subscribed_languages.target": "Cambiar idiomas suscritos para {target}",
   "suggestions.dismiss": "Descartar sugerencia",
   "suggestions.header": "Es posible que te interese…",
   "tabs_bar.federated_timeline": "Federada",
diff --git a/app/javascript/mastodon/locales/es-MX.json b/app/javascript/mastodon/locales/es-MX.json
index 96f0a59dc..48424f74e 100644
--- a/app/javascript/mastodon/locales/es-MX.json
+++ b/app/javascript/mastodon/locales/es-MX.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Te sigue",
   "account.hide_reblogs": "Ocultar retoots de @{name}",
   "account.joined": "Se unió el {date}",
+  "account.languages": "Cambiar idiomas suscritos",
   "account.link_verified_on": "El proprietario de este link fue comprobado el {date}",
   "account.locked_info": "El estado de privacidad de esta cuenta està configurado como bloqueado. El proprietario debe revisar manualmente quien puede seguirle.",
   "account.media": "Multimedia",
@@ -59,7 +60,7 @@
   "alert.unexpected.title": "¡Ups!",
   "announcement.announcement": "Anuncio",
   "attachments_list.unprocessed": "(sin procesar)",
-  "audio.hide": "Hide audio",
+  "audio.hide": "Ocultar audio",
   "autosuggest_hashtag.per_week": "{count} por semana",
   "boost_modal.combo": "Puedes hacer clic en {combo} para saltar este aviso la próxima vez",
   "bundle_column_error.body": "Algo salió mal al cargar este componente.",
@@ -197,22 +198,22 @@
   "explore.trending_links": "Noticias",
   "explore.trending_statuses": "Publicaciones",
   "explore.trending_tags": "Hashtags",
-  "filter_modal.added.context_mismatch_explanation": "This filter category does not apply to the context in which you have accessed this post. If you want the post to be filtered in this context too, you will have to edit the filter.",
-  "filter_modal.added.context_mismatch_title": "Context mismatch!",
-  "filter_modal.added.expired_explanation": "This filter category has expired, you will need to change the expiration date for it to apply.",
-  "filter_modal.added.expired_title": "Expired filter!",
-  "filter_modal.added.review_and_configure": "To review and further configure this filter category, go to the {settings_link}.",
-  "filter_modal.added.review_and_configure_title": "Filter settings",
-  "filter_modal.added.settings_link": "settings page",
-  "filter_modal.added.short_explanation": "This post has been added to the following filter category: {title}.",
-  "filter_modal.added.title": "Filter added!",
-  "filter_modal.select_filter.context_mismatch": "does not apply to this context",
-  "filter_modal.select_filter.expired": "expired",
-  "filter_modal.select_filter.prompt_new": "New category: {name}",
-  "filter_modal.select_filter.search": "Search or create",
-  "filter_modal.select_filter.subtitle": "Use an existing category or create a new one",
-  "filter_modal.select_filter.title": "Filter this post",
-  "filter_modal.title.status": "Filter a post",
+  "filter_modal.added.context_mismatch_explanation": "Esta categoría de filtro no se aplica al contexto en el que ha accedido a esta publlicación. Si quieres que la publicación sea filtrada también en este contexto, tendrás que editar el filtro.",
+  "filter_modal.added.context_mismatch_title": "¡El contexto no coincide!",
+  "filter_modal.added.expired_explanation": "Esta categoría de filtro ha caducado, necesitará cambiar la fecha de caducidad para que se aplique.",
+  "filter_modal.added.expired_title": "¡Filtro caducado!",
+  "filter_modal.added.review_and_configure": "Para revisar y configurar esta categoría de filtros, vaya a {settings_link}.",
+  "filter_modal.added.review_and_configure_title": "Ajustes de filtro",
+  "filter_modal.added.settings_link": "página de ajustes",
+  "filter_modal.added.short_explanation": "Esta publicación ha sido añadida a la siguiente categoría de filtros: {title}.",
+  "filter_modal.added.title": "¡Filtro añadido!",
+  "filter_modal.select_filter.context_mismatch": "no se aplica a este contexto",
+  "filter_modal.select_filter.expired": "expirado",
+  "filter_modal.select_filter.prompt_new": "Nueva categoría: {name}",
+  "filter_modal.select_filter.search": "Buscar o crear",
+  "filter_modal.select_filter.subtitle": "Usar una categoría existente o crear una nueva",
+  "filter_modal.select_filter.title": "Filtrar esta publicación",
+  "filter_modal.title.status": "Filtrar una publicación",
   "follow_recommendations.done": "Hecho",
   "follow_recommendations.heading": "¡Sigue a gente que publique cosas que te gusten! Aquí tienes algunas sugerencias.",
   "follow_recommendations.lead": "Las publicaciones de la gente a la que sigas aparecerán ordenadas cronológicamente en Inicio. No tengas miedo de cometer errores, ¡puedes dejarles de seguir en cualquier momento con la misma facilidad!",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Primeros pasos",
   "getting_started.invite": "Invitar usuarios",
   "getting_started.open_source_notice": "Mastodon es software libre. Puedes contribuir o reportar errores en {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Seguridad",
-  "getting_started.terms": "Términos de servicio",
   "hashtag.column_header.tag_mode.all": "y {additional}",
   "hashtag.column_header.tag_mode.any": "o {additional}",
   "hashtag.column_header.tag_mode.none": "sin {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "No se pudo encontrar nada para estos términos de busqueda",
   "search_results.statuses": "Toots",
   "search_results.statuses_fts_disabled": "Buscar toots por su contenido no está disponible en este servidor de Mastodon.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {resultado} other {resultados}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Abrir interfaz de moderación para @{name}",
   "status.admin_status": "Abrir este estado en la interfaz de moderación",
   "status.block": "Bloquear a @{name}",
@@ -487,7 +492,7 @@
   "status.edited_x_times": "Editado {count, plural, one {{count} time} other {{count} veces}}",
   "status.embed": "Incrustado",
   "status.favourite": "Favorito",
-  "status.filter": "Filter this post",
+  "status.filter": "Filtrar esta publicación",
   "status.filtered": "Filtrado",
   "status.hide": "Ocultar publicación",
   "status.history.created": "{name} creó {date}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Mostrar menos para todo",
   "status.show_more": "Mostrar más",
   "status.show_more_all": "Mostrar más para todo",
+  "status.show_original": "Mostrar original",
   "status.show_thread": "Mostrar hilo",
+  "status.translate": "Traducir",
+  "status.translated_from": "Traducido del {lang}",
   "status.uncached_media_warning": "No disponible",
   "status.unmute_conversation": "Dejar de silenciar conversación",
   "status.unpin": "Dejar de fijar",
+  "subscribed_languages.lead": "Sólo los mensajes en los idiomas seleccionados aparecerán en su inicio y otras líneas de tiempo después del cambio. Seleccione ninguno para recibir mensajes en todos los idiomas.",
+  "subscribed_languages.save": "Guardar cambios",
+  "subscribed_languages.target": "Cambiar idiomas suscritos para {target}",
   "suggestions.dismiss": "Descartar sugerencia",
   "suggestions.header": "Es posible que te interese…",
   "tabs_bar.federated_timeline": "Federado",
diff --git a/app/javascript/mastodon/locales/es.json b/app/javascript/mastodon/locales/es.json
index 5de01d5fc..b65dbbbd8 100644
--- a/app/javascript/mastodon/locales/es.json
+++ b/app/javascript/mastodon/locales/es.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Te sigue",
   "account.hide_reblogs": "Ocultar retoots de @{name}",
   "account.joined": "Se unió el {date}",
+  "account.languages": "Cambiar idiomas suscritos",
   "account.link_verified_on": "El proprietario de este link fue comprobado el {date}",
   "account.locked_info": "El estado de privacidad de esta cuenta està configurado como bloqueado. El proprietario debe revisar manualmente quien puede seguirle.",
   "account.media": "Multimedia",
@@ -197,22 +198,22 @@
   "explore.trending_links": "Noticias",
   "explore.trending_statuses": "Publicaciones",
   "explore.trending_tags": "Etiquetas",
-  "filter_modal.added.context_mismatch_explanation": "This filter category does not apply to the context in which you have accessed this post. If you want the post to be filtered in this context too, you will have to edit the filter.",
-  "filter_modal.added.context_mismatch_title": "Context mismatch!",
-  "filter_modal.added.expired_explanation": "This filter category has expired, you will need to change the expiration date for it to apply.",
-  "filter_modal.added.expired_title": "Expired filter!",
-  "filter_modal.added.review_and_configure": "To review and further configure this filter category, go to the {settings_link}.",
-  "filter_modal.added.review_and_configure_title": "Filter settings",
-  "filter_modal.added.settings_link": "settings page",
-  "filter_modal.added.short_explanation": "This post has been added to the following filter category: {title}.",
-  "filter_modal.added.title": "Filter added!",
-  "filter_modal.select_filter.context_mismatch": "does not apply to this context",
-  "filter_modal.select_filter.expired": "expired",
-  "filter_modal.select_filter.prompt_new": "New category: {name}",
-  "filter_modal.select_filter.search": "Search or create",
-  "filter_modal.select_filter.subtitle": "Use an existing category or create a new one",
-  "filter_modal.select_filter.title": "Filter this post",
-  "filter_modal.title.status": "Filter a post",
+  "filter_modal.added.context_mismatch_explanation": "Esta categoría de filtro no se aplica al contexto en el que ha accedido a esta publlicación. Si quieres que la publicación sea filtrada también en este contexto, tendrás que editar el filtro.",
+  "filter_modal.added.context_mismatch_title": "¡El contexto no coincide!",
+  "filter_modal.added.expired_explanation": "Esta categoría de filtro ha caducado, necesitará cambiar la fecha de caducidad para que se aplique.",
+  "filter_modal.added.expired_title": "¡Filtro caducado!",
+  "filter_modal.added.review_and_configure": "Para revisar y configurar esta categoría de filtros, vaya a {settings_link}.",
+  "filter_modal.added.review_and_configure_title": "Ajustes de filtro",
+  "filter_modal.added.settings_link": "página de ajustes",
+  "filter_modal.added.short_explanation": "Esta publicación ha sido añadida a la siguiente categoría de filtros: {title}.",
+  "filter_modal.added.title": "¡Filtro añadido!",
+  "filter_modal.select_filter.context_mismatch": "no se aplica a este contexto",
+  "filter_modal.select_filter.expired": "expirado",
+  "filter_modal.select_filter.prompt_new": "Nueva categoría: {name}",
+  "filter_modal.select_filter.search": "Buscar o crear",
+  "filter_modal.select_filter.subtitle": "Usar una categoría existente o crear una nueva",
+  "filter_modal.select_filter.title": "Filtrar esta publicación",
+  "filter_modal.title.status": "Filtrar una publicación",
   "follow_recommendations.done": "Hecho",
   "follow_recommendations.heading": "¡Sigue a gente que publique cosas que te gusten! Aquí tienes algunas sugerencias.",
   "follow_recommendations.lead": "Las publicaciones de la gente a la que sigas aparecerán ordenadas cronológicamente en Inicio. No tengas miedo de cometer errores, ¡puedes dejarles de seguir en cualquier momento con la misma facilidad!",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Primeros pasos",
   "getting_started.invite": "Invitar usuarios",
   "getting_started.open_source_notice": "Mastodon es software libre. Puedes contribuir o reportar errores en {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Seguridad",
-  "getting_started.terms": "Términos de servicio",
   "hashtag.column_header.tag_mode.all": "y {additional}",
   "hashtag.column_header.tag_mode.any": "o {additional}",
   "hashtag.column_header.tag_mode.none": "sin {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "No se pudo encontrar nada para estos términos de búsqueda",
   "search_results.statuses": "Publicaciones",
   "search_results.statuses_fts_disabled": "Buscar publicaciones por su contenido no está disponible en este servidor de Mastodon.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {resultado} other {resultados}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Abrir interfaz de moderación para @{name}",
   "status.admin_status": "Abrir este estado en la interfaz de moderación",
   "status.block": "Bloquear a @{name}",
@@ -487,7 +492,7 @@
   "status.edited_x_times": "Editado {count, plural, one {{count} vez} other {{count} veces}}",
   "status.embed": "Incrustado",
   "status.favourite": "Favorito",
-  "status.filter": "Filter this post",
+  "status.filter": "Filtrar esta publicación",
   "status.filtered": "Filtrado",
   "status.hide": "Ocultar publicación",
   "status.history.created": "{name} creó {date}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Mostrar menos para todo",
   "status.show_more": "Mostrar más",
   "status.show_more_all": "Mostrar más para todo",
+  "status.show_original": "Mostrar original",
   "status.show_thread": "Mostrar hilo",
+  "status.translate": "Traducir",
+  "status.translated_from": "Traducido del {lang}",
   "status.uncached_media_warning": "No disponible",
   "status.unmute_conversation": "Dejar de silenciar conversación",
   "status.unpin": "Dejar de fijar",
+  "subscribed_languages.lead": "Sólo los mensajes en los idiomas seleccionados aparecerán en su inicio y otras líneas de tiempo después del cambio. Seleccione ninguno para recibir mensajes en todos los idiomas.",
+  "subscribed_languages.save": "Guardar cambios",
+  "subscribed_languages.target": "Cambiar idiomas suscritos para {target}",
   "suggestions.dismiss": "Descartar sugerencia",
   "suggestions.header": "Es posible que te interese…",
   "tabs_bar.federated_timeline": "Federada",
diff --git a/app/javascript/mastodon/locales/et.json b/app/javascript/mastodon/locales/et.json
index 6737111fd..11c932346 100644
--- a/app/javascript/mastodon/locales/et.json
+++ b/app/javascript/mastodon/locales/et.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Jälgib Teid",
   "account.hide_reblogs": "Peida upitused kasutajalt @{name}",
   "account.joined": "Liitus {date}",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "Selle lingi autorsust kontrolliti {date}",
   "account.locked_info": "Selle konto privaatsussätteks on lukustatud. Omanik vaatab manuaalselt üle, kes teda jägida saab.",
   "account.media": "Meedia",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Alustamine",
   "getting_started.invite": "Kutsu inimesi",
   "getting_started.open_source_notice": "Mastodon on avatud lähtekoodiga tarkvara. Saate panustada või teatada probleemidest GitHubis {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Turvalisus",
-  "getting_started.terms": "Kasutustingimused",
   "hashtag.column_header.tag_mode.all": "ja {additional}",
   "hashtag.column_header.tag_mode.any": "või {additional}",
   "hashtag.column_header.tag_mode.none": "ilma {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Could not find anything for these search terms",
   "search_results.statuses": "Tuudid",
   "search_results.statuses_fts_disabled": "Tuutsude otsimine nende sisu järgi ei ole sellel Mastodoni serveril sisse lülitatud.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {tulemus} other {tulemust}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Ava moderaatoriliides kasutajale @{name}",
   "status.admin_status": "Ava see staatus moderaatoriliites",
   "status.block": "Blokeeri @{name}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Näita vähem kõigile",
   "status.show_more": "Näita veel",
   "status.show_more_all": "Näita enam kõigile",
+  "status.show_original": "Show original",
   "status.show_thread": "Kuva lõim",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "Pole saadaval",
   "status.unmute_conversation": "Ära vaigista vestlust",
   "status.unpin": "Kinnita profiililt lahti",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "Eira soovitust",
   "suggestions.header": "Teid võib huvitada…",
   "tabs_bar.federated_timeline": "Föderatiivne",
diff --git a/app/javascript/mastodon/locales/eu.json b/app/javascript/mastodon/locales/eu.json
index c8062f004..e4ffd2234 100644
--- a/app/javascript/mastodon/locales/eu.json
+++ b/app/javascript/mastodon/locales/eu.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Jarraitzen dizu",
   "account.hide_reblogs": "Ezkutatu @{name}(r)en bultzadak",
   "account.joined": "{date}(e)an elkartua",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "Esteka honen jabetzaren egiaztaketa data: {date}",
   "account.locked_info": "Kontu honen pribatutasun egoera blokeatuta gisa ezarri da. Jabeak eskuz erabakitzen du nork jarraitu diezaioken.",
   "account.media": "Multimedia",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Menua",
   "getting_started.invite": "Gonbidatu jendea",
   "getting_started.open_source_notice": "Mastodon software librea da. Ekarpenak egin ditzakezu edo akatsen berri eman GitHub bidez: {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Segurtasuna",
-  "getting_started.terms": "Erabilera baldintzak",
   "hashtag.column_header.tag_mode.all": "eta {osagarria}",
   "hashtag.column_header.tag_mode.any": "edo {osagarria}",
   "hashtag.column_header.tag_mode.none": "gabe {osagarria}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Ez da emaitzarik aurkitu bilaketa-termino horientzat",
   "search_results.statuses": "Bidalketak",
   "search_results.statuses_fts_disabled": "Mastodon zerbitzari honek ez du bidalketen edukiaren bilaketa gaitu.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {emaitza} other {emaitza}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Ireki @{name} erabiltzailearen moderazio interfazea",
   "status.admin_status": "Ireki bidalketa hau moderazio interfazean",
   "status.block": "Blokeatu @{name}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Erakutsi denetarik gutxiago",
   "status.show_more": "Erakutsi gehiago",
   "status.show_more_all": "Erakutsi denetarik gehiago",
+  "status.show_original": "Show original",
   "status.show_thread": "Erakutsi haria",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "Ez eskuragarri",
   "status.unmute_conversation": "Desmututu elkarrizketa",
   "status.unpin": "Desfinkatu profiletik",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "Errefusatu proposamena",
   "suggestions.header": "Hau interesatu dakizuke…",
   "tabs_bar.federated_timeline": "Federatua",
diff --git a/app/javascript/mastodon/locales/fa.json b/app/javascript/mastodon/locales/fa.json
index 775f38475..25b2fb3b4 100644
--- a/app/javascript/mastodon/locales/fa.json
+++ b/app/javascript/mastodon/locales/fa.json
@@ -24,6 +24,7 @@
   "account.follows_you": "پی می‌گیردتان",
   "account.hide_reblogs": "نهفتن تقویت‌های ‎@{name}",
   "account.joined": "پیوسته از {date}",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "مالکیت این پیوند در {date} بررسی شد",
   "account.locked_info": "این حساب خصوصی است. صاحبش تصمیم می‌گیرد که چه کسی پی‌گیرش باشد.",
   "account.media": "رسانه",
@@ -226,8 +227,8 @@
   "getting_started.heading": "آغاز کنید",
   "getting_started.invite": "دعوت از دیگران",
   "getting_started.open_source_notice": "ماستودون نرم‌افزاری آزاد است. می‌توانید روی {github} در آن مشارکت کرده یا مشکلاتش را گزارش دهید.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "تنظیمات حساب",
-  "getting_started.terms": "شرایط خدمات",
   "hashtag.column_header.tag_mode.all": "و {additional}",
   "hashtag.column_header.tag_mode.any": "یا {additional}",
   "hashtag.column_header.tag_mode.none": "بدون {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "چیزی برای این عبارت جست‌وجو یافت نشد",
   "search_results.statuses": "فرسته‌ها",
   "search_results.statuses_fts_disabled": "جست‌وجوی محتوای فرسته‌ها در این کارساز ماستودون به کار انداخته نشده است.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {نتیجه} other {نتیجه}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "گشودن واسط مدیریت برای ‎@{name}",
   "status.admin_status": "گشودن این فرسته در واسط مدیریت",
   "status.block": "مسدود کردن ‎@{name}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "نمایش کمتر همه",
   "status.show_more": "نمایش بیشتر",
   "status.show_more_all": "نمایش بیشتر همه",
+  "status.show_original": "Show original",
   "status.show_thread": "نمایش رشته",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "ناموجود",
   "status.unmute_conversation": "رفع خموشی گفت‌وگو",
   "status.unpin": "برداشتن سنجاق از نمایه",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "نادیده گرفتن پیشنهاد",
   "suggestions.header": "شاید این هم برایتان جالب باشد…",
   "tabs_bar.federated_timeline": "همگانی",
diff --git a/app/javascript/mastodon/locales/fi.json b/app/javascript/mastodon/locales/fi.json
index 0dece0c51..d3829ae91 100644
--- a/app/javascript/mastodon/locales/fi.json
+++ b/app/javascript/mastodon/locales/fi.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Seuraa sinua",
   "account.hide_reblogs": "Piilota buustaukset käyttäjältä @{name}",
   "account.joined": "Liittynyt {date}",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "Tämän linkin omistaja tarkistettiin {date}",
   "account.locked_info": "Tämän tilin yksityisyyden tila on asetettu lukituksi. Omistaja arvioi manuaalisesti, kuka voi seurata niitä.",
   "account.media": "Media",
@@ -197,22 +198,22 @@
   "explore.trending_links": "Uutiset",
   "explore.trending_statuses": "Viestit",
   "explore.trending_tags": "Aihetunnisteet",
-  "filter_modal.added.context_mismatch_explanation": "This filter category does not apply to the context in which you have accessed this post. If you want the post to be filtered in this context too, you will have to edit the filter.",
-  "filter_modal.added.context_mismatch_title": "Context mismatch!",
-  "filter_modal.added.expired_explanation": "This filter category has expired, you will need to change the expiration date for it to apply.",
-  "filter_modal.added.expired_title": "Expired filter!",
-  "filter_modal.added.review_and_configure": "To review and further configure this filter category, go to the {settings_link}.",
-  "filter_modal.added.review_and_configure_title": "Filter settings",
-  "filter_modal.added.settings_link": "settings page",
-  "filter_modal.added.short_explanation": "This post has been added to the following filter category: {title}.",
-  "filter_modal.added.title": "Filter added!",
-  "filter_modal.select_filter.context_mismatch": "does not apply to this context",
-  "filter_modal.select_filter.expired": "expired",
-  "filter_modal.select_filter.prompt_new": "New category: {name}",
-  "filter_modal.select_filter.search": "Search or create",
-  "filter_modal.select_filter.subtitle": "Use an existing category or create a new one",
-  "filter_modal.select_filter.title": "Filter this post",
-  "filter_modal.title.status": "Filter a post",
+  "filter_modal.added.context_mismatch_explanation": "Tämä suodatinluokka ei koske asiayhteyttä, jossa olet käyttänyt tätä viestiä. Jos haluat, että viesti suodatetaan myös tässä yhteydessä, sinun on muokattava suodatinta.",
+  "filter_modal.added.context_mismatch_title": "Asiayhteys ei täsmää!",
+  "filter_modal.added.expired_explanation": "Tämä suodatinluokka on vanhentunut ja sinun on muutettava viimeistä voimassaolon päivää, jotta sitä voidaan käyttää.",
+  "filter_modal.added.expired_title": "Vanhentunut suodatin!",
+  "filter_modal.added.review_and_configure": "Voit tarkastella tätä suodatinluokkaa ja määrittää sen tarkemmin siirtymällä {settings_link}.",
+  "filter_modal.added.review_and_configure_title": "Suodattimen asetukset",
+  "filter_modal.added.settings_link": "asetukset sivu",
+  "filter_modal.added.short_explanation": "Tämä viesti on lisätty seuraavaan suodatinluokkaan: {title}.",
+  "filter_modal.added.title": "Suodatin lisätty!",
+  "filter_modal.select_filter.context_mismatch": "ei sovellu tähän asiayhteyteen",
+  "filter_modal.select_filter.expired": "vanhentunut",
+  "filter_modal.select_filter.prompt_new": "Uusi luokka: {name}",
+  "filter_modal.select_filter.search": "Etsi tai luo",
+  "filter_modal.select_filter.subtitle": "Käytä olemassa olevaa luokkaa tai luo uusi luokka",
+  "filter_modal.select_filter.title": "Suodata tämä viesti",
+  "filter_modal.title.status": "Suodata viesti",
   "follow_recommendations.done": "Valmis",
   "follow_recommendations.heading": "Seuraa ihmisiä, joilta haluaisit nähdä julkaisuja! Tässä on muutamia ehdotuksia.",
   "follow_recommendations.lead": "Seuraamiesi julkaisut näkyvät aikajärjestyksessä kotisyötteessä. Älä pelkää seurata vahingossa, voit lopettaa seuraamisen yhtä helposti!",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Näin pääset alkuun",
   "getting_started.invite": "Kutsu ihmisiä",
   "getting_started.open_source_notice": "Mastodon on avoimen lähdekoodin ohjelma. Voit avustaa tai raportoida ongelmia GitHubissa: {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Tiliasetukset",
-  "getting_started.terms": "Käyttöehdot",
   "hashtag.column_header.tag_mode.all": "ja {additional}",
   "hashtag.column_header.tag_mode.any": "tai {additional}",
   "hashtag.column_header.tag_mode.none": "ilman {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Näille hakusanoille ei löytynyt mitään",
   "search_results.statuses": "Viestit",
   "search_results.statuses_fts_disabled": "Viestien haku sisällön perusteella ei ole käytössä tällä Mastodon-palvelimella.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {tulos} other {tulokset}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Avaa moderaattorinäkymä tilistä @{name}",
   "status.admin_status": "Avaa julkaisu moderointinäkymässä",
   "status.block": "Estä @{name}",
@@ -487,7 +492,7 @@
   "status.edited_x_times": "Muokattu {count, plural, one {{count} aika} other {{count} kertaa}}",
   "status.embed": "Upota",
   "status.favourite": "Tykkää",
-  "status.filter": "Filter this post",
+  "status.filter": "Suodata tämä viesti",
   "status.filtered": "Suodatettu",
   "status.hide": "Piilota toot",
   "status.history.created": "{name} luotu {date}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Näytä vähemmän kaikista",
   "status.show_more": "Näytä lisää",
   "status.show_more_all": "Näytä lisää kaikista",
+  "status.show_original": "Show original",
   "status.show_thread": "Näytä ketju",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "Ei saatavilla",
   "status.unmute_conversation": "Poista keskustelun mykistys",
   "status.unpin": "Irrota profiilista",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "Hylkää ehdotus",
   "suggestions.header": "Saatat olla kiinnostunut myös…",
   "tabs_bar.federated_timeline": "Yleinen",
diff --git a/app/javascript/mastodon/locales/fr.json b/app/javascript/mastodon/locales/fr.json
index dcac5c880..2befc94cb 100644
--- a/app/javascript/mastodon/locales/fr.json
+++ b/app/javascript/mastodon/locales/fr.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Vous suit",
   "account.hide_reblogs": "Masquer les partages de @{name}",
   "account.joined": "Ici depuis {date}",
+  "account.languages": "Changer les langues abonnées",
   "account.link_verified_on": "La propriété de ce lien a été vérifiée le {date}",
   "account.locked_info": "Ce compte est privé. Son ou sa propriétaire approuve manuellement qui peut le suivre.",
   "account.media": "Médias",
@@ -59,7 +60,7 @@
   "alert.unexpected.title": "Oups !",
   "announcement.announcement": "Annonce",
   "attachments_list.unprocessed": "(non traité)",
-  "audio.hide": "Hide audio",
+  "audio.hide": "Masquer l'audio",
   "autosuggest_hashtag.per_week": "{count} par semaine",
   "boost_modal.combo": "Vous pouvez appuyer sur {combo} pour passer ceci la prochaine fois",
   "bundle_column_error.body": "Une erreur s’est produite lors du chargement de ce composant.",
@@ -197,10 +198,10 @@
   "explore.trending_links": "Actualité",
   "explore.trending_statuses": "Messages",
   "explore.trending_tags": "Hashtags",
-  "filter_modal.added.context_mismatch_explanation": "This filter category does not apply to the context in which you have accessed this post. If you want the post to be filtered in this context too, you will have to edit the filter.",
-  "filter_modal.added.context_mismatch_title": "Context mismatch!",
-  "filter_modal.added.expired_explanation": "This filter category has expired, you will need to change the expiration date for it to apply.",
-  "filter_modal.added.expired_title": "Expired filter!",
+  "filter_modal.added.context_mismatch_explanation": "Cette catégorie de filtre ne s'applique pas au contexte dans lequel vous avez accédé à ce message. Si vous voulez que le message soit filtré dans ce contexte également, vous devrez modifier le filtre.",
+  "filter_modal.added.context_mismatch_title": "Incompatibilité du contexte !",
+  "filter_modal.added.expired_explanation": "Cette catégorie de filtre a expiré, vous devrez modifier la date d'expiration pour qu'elle soit appliquée.",
+  "filter_modal.added.expired_title": "Filtre expiré !",
   "filter_modal.added.review_and_configure": "To review and further configure this filter category, go to the {settings_link}.",
   "filter_modal.added.review_and_configure_title": "Filter settings",
   "filter_modal.added.settings_link": "settings page",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Pour commencer",
   "getting_started.invite": "Inviter des gens",
   "getting_started.open_source_notice": "Mastodon est un logiciel libre. Vous pouvez contribuer ou faire des rapports de bogues via {github} sur GitHub.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Sécurité",
-  "getting_started.terms": "Conditions d’utilisation",
   "hashtag.column_header.tag_mode.all": "et {additional}",
   "hashtag.column_header.tag_mode.any": "ou {additional}",
   "hashtag.column_header.tag_mode.none": "sans {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Aucun résultat avec ces mots-clefs",
   "search_results.statuses": "Messages",
   "search_results.statuses_fts_disabled": "La recherche de messages par leur contenu n'est pas activée sur ce serveur Mastodon.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {résultat} other {résultats}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Ouvrir l’interface de modération pour @{name}",
   "status.admin_status": "Ouvrir ce message dans l’interface de modération",
   "status.block": "Bloquer @{name}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Tout replier",
   "status.show_more": "Déplier",
   "status.show_more_all": "Tout déplier",
+  "status.show_original": "Show original",
   "status.show_thread": "Montrer le fil",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "Indisponible",
   "status.unmute_conversation": "Ne plus masquer la conversation",
   "status.unpin": "Retirer du profil",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "Rejeter la suggestion",
   "suggestions.header": "Vous pourriez être intéressé·e par…",
   "tabs_bar.federated_timeline": "Fil public global",
diff --git a/app/javascript/mastodon/locales/fy.json b/app/javascript/mastodon/locales/fy.json
index a53a1cf52..2c740bf85 100644
--- a/app/javascript/mastodon/locales/fy.json
+++ b/app/javascript/mastodon/locales/fy.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Folget dy",
   "account.hide_reblogs": "Hide boosts from @{name}",
   "account.joined": "Registrearre op {date}",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.",
   "account.media": "Media",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Utein sette",
   "getting_started.invite": "Minsken útnûgje",
   "getting_started.open_source_notice": "Mastodon is iepen boarne software. Jo kinne sels bydrage of problemen oanjaan troch GitHub op {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Account ynstellings",
-  "getting_started.terms": "Terms of service",
   "hashtag.column_header.tag_mode.all": "en {additional}",
   "hashtag.column_header.tag_mode.any": "of {additional}",
   "hashtag.column_header.tag_mode.none": "sûnder {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Could not find anything for these search terms",
   "search_results.statuses": "Posts",
   "search_results.statuses_fts_disabled": "Searching posts by their content is not enabled on this Mastodon server.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {result} other {results}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Open moderation interface for @{name}",
   "status.admin_status": "Open this status in the moderation interface",
   "status.block": "Block @{name}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Foar alles minder sjen litte",
   "status.show_more": "Mear sjen litte",
   "status.show_more_all": "Foar alles mear sjen litte",
+  "status.show_original": "Show original",
   "status.show_thread": "Petear sjen litte",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "Net beskikber",
   "status.unmute_conversation": "Petear net mear negearre",
   "status.unpin": "Unpin from profile",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "Dismiss suggestion",
   "suggestions.header": "You might be interested in…",
   "tabs_bar.federated_timeline": "Federated",
diff --git a/app/javascript/mastodon/locales/ga.json b/app/javascript/mastodon/locales/ga.json
index e05c4a41d..9e8011971 100644
--- a/app/javascript/mastodon/locales/ga.json
+++ b/app/javascript/mastodon/locales/ga.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Do do leanúint",
   "account.hide_reblogs": "Folaigh athphostálacha ó @{name}",
   "account.joined": "Ina bhall ó {date}",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.locked_info": "Tá an socrú príobháideachais don cuntas seo curtha go 'faoi ghlas'. Déanann an t-úinéir léirmheas ar cén daoine atá ceadaithe an cuntas leanúint.",
   "account.media": "Ábhair",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Getting started",
   "getting_started.invite": "Invite people",
   "getting_started.open_source_notice": "Mastodon is open source software. You can contribute or report issues on GitHub at {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Security",
-  "getting_started.terms": "Terms of service",
   "hashtag.column_header.tag_mode.all": "and {additional}",
   "hashtag.column_header.tag_mode.any": "or {additional}",
   "hashtag.column_header.tag_mode.none": "without {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Could not find anything for these search terms",
   "search_results.statuses": "Postálacha",
   "search_results.statuses_fts_disabled": "Searching posts by their content is not enabled on this Mastodon server.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {result} other {results}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Open moderation interface for @{name}",
   "status.admin_status": "Open this status in the moderation interface",
   "status.block": "Block @{name}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Show less for all",
   "status.show_more": "Show more",
   "status.show_more_all": "Show more for all",
+  "status.show_original": "Show original",
   "status.show_thread": "Show thread",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "Not available",
   "status.unmute_conversation": "Díbhalbhaigh comhrá",
   "status.unpin": "Díphionnáil de do phróifíl",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "Dismiss suggestion",
   "suggestions.header": "You might be interested in…",
   "tabs_bar.federated_timeline": "Federated",
diff --git a/app/javascript/mastodon/locales/gd.json b/app/javascript/mastodon/locales/gd.json
index c58729271..70ec2cbb0 100644
--- a/app/javascript/mastodon/locales/gd.json
+++ b/app/javascript/mastodon/locales/gd.json
@@ -24,6 +24,7 @@
   "account.follows_you": "’Gad leantainn",
   "account.hide_reblogs": "Falaich na brosnachaidhean o @{name}",
   "account.joined": "Air ballrachd fhaighinn {date}",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "Chaidh dearbhadh cò leis a tha an ceangal seo {date}",
   "account.locked_info": "Tha prìobhaideachd ghlaiste aig a’ chunntais seo. Nì an sealbhadair lèirmheas a làimh air cò dh’fhaodas leantainn orra.",
   "account.media": "Meadhanan",
@@ -59,7 +60,7 @@
   "alert.unexpected.title": "Oich!",
   "announcement.announcement": "Brath-fios",
   "attachments_list.unprocessed": "(gun phròiseasadh)",
-  "audio.hide": "Hide audio",
+  "audio.hide": "Falaich an fhuaim",
   "autosuggest_hashtag.per_week": "{count} san t-seachdain",
   "boost_modal.combo": "Brùth air {combo} nam b’ fheàrr leat leum a ghearradh thar seo an ath-thuras",
   "bundle_column_error.body": "Chaidh rudeigin cearr nuair a dh’fheuch sinn ris a’ cho-phàirt seo a luchdadh.",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Toiseach",
   "getting_started.invite": "Thoir cuireadh do dhaoine",
   "getting_started.open_source_notice": "’S e bathar-bog le bun-tùs fosgailte a th’ ann am Mastodon. ’S urrainn dhut cuideachadh leis no aithris a dhèanamh air duilgheadasan air GitHub fo {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Roghainnean a’ chunntais",
-  "getting_started.terms": "Teirmichean na seirbheise",
   "hashtag.column_header.tag_mode.all": "agus {additional}",
   "hashtag.column_header.tag_mode.any": "no {additional}",
   "hashtag.column_header.tag_mode.none": "às aonais {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Cha do lorg sinn dad dha na h-abairtean-luirg seo",
   "search_results.statuses": "Postaichean",
   "search_results.statuses_fts_disabled": "Chan eil lorg phostaichean a-rèir an susbaint an comas air an fhrithealaiche Mastodon seo.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {toradh} two {thoradh} few {toraidhean} other {toradh}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Fosgail eadar-aghaidh na maorsainneachd dha @{name}",
   "status.admin_status": "Fosgail am post seo ann an eadar-aghaidh na maorsainneachd",
   "status.block": "Bac @{name}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Seall nas lugha dhen a h-uile",
   "status.show_more": "Seall barrachd dheth",
   "status.show_more_all": "Seall barrachd dhen a h-uile",
+  "status.show_original": "Show original",
   "status.show_thread": "Seall an snàithlean",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "Chan eil seo ri fhaighinn",
   "status.unmute_conversation": "Dì-mhùch an còmhradh",
   "status.unpin": "Dì-phrìnich on phròifil",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "Leig seachad am moladh",
   "suggestions.header": "Dh’fhaoidte gu bheil ùidh agad ann an…",
   "tabs_bar.federated_timeline": "Co-naisgte",
diff --git a/app/javascript/mastodon/locales/gl.json b/app/javascript/mastodon/locales/gl.json
index 0c7baa332..9ed8c2872 100644
--- a/app/javascript/mastodon/locales/gl.json
+++ b/app/javascript/mastodon/locales/gl.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Séguete",
   "account.hide_reblogs": "Agochar repeticións de @{name}",
   "account.joined": "Uníuse {date}",
+  "account.languages": "Modificar os idiomas subscritos",
   "account.link_verified_on": "A propiedade desta ligazón foi verificada o {date}",
   "account.locked_info": "Esta é unha conta privada. A propietaria revisa de xeito manual quen pode seguila.",
   "account.media": "Multimedia",
@@ -197,22 +198,22 @@
   "explore.trending_links": "Novas",
   "explore.trending_statuses": "Publicacións",
   "explore.trending_tags": "Cancelos",
-  "filter_modal.added.context_mismatch_explanation": "This filter category does not apply to the context in which you have accessed this post. If you want the post to be filtered in this context too, you will have to edit the filter.",
-  "filter_modal.added.context_mismatch_title": "Context mismatch!",
-  "filter_modal.added.expired_explanation": "This filter category has expired, you will need to change the expiration date for it to apply.",
-  "filter_modal.added.expired_title": "Expired filter!",
-  "filter_modal.added.review_and_configure": "To review and further configure this filter category, go to the {settings_link}.",
-  "filter_modal.added.review_and_configure_title": "Filter settings",
-  "filter_modal.added.settings_link": "settings page",
-  "filter_modal.added.short_explanation": "This post has been added to the following filter category: {title}.",
-  "filter_modal.added.title": "Filter added!",
-  "filter_modal.select_filter.context_mismatch": "does not apply to this context",
-  "filter_modal.select_filter.expired": "expired",
-  "filter_modal.select_filter.prompt_new": "New category: {name}",
-  "filter_modal.select_filter.search": "Search or create",
-  "filter_modal.select_filter.subtitle": "Use an existing category or create a new one",
-  "filter_modal.select_filter.title": "Filter this post",
-  "filter_modal.title.status": "Filter a post",
+  "filter_modal.added.context_mismatch_explanation": "Esta categoría de filtro non se aplica ao contexto no que accedeches a esta publicación. Se queres que a publicación se filtre nese contexto tamén, terás que editar o filtro.",
+  "filter_modal.added.context_mismatch_title": "Non concorda o contexto!",
+  "filter_modal.added.expired_explanation": "Esta categoría de filtro caducou, terás que cambiar a data de caducidade para que se aplique.",
+  "filter_modal.added.expired_title": "Filtro caducado!",
+  "filter_modal.added.review_and_configure": "Para revisar e despois configurar esta categoría de filtro, vaite a {settings_link}.",
+  "filter_modal.added.review_and_configure_title": "Axustes do filtro",
+  "filter_modal.added.settings_link": "páxina de axustes",
+  "filter_modal.added.short_explanation": "Engadiuse esta publicación á seguinte categoría de filtro: {title}.",
+  "filter_modal.added.title": "Filtro engadido!",
+  "filter_modal.select_filter.context_mismatch": "non se aplica neste contexto",
+  "filter_modal.select_filter.expired": "caducado",
+  "filter_modal.select_filter.prompt_new": "Nova categoría: {name}",
+  "filter_modal.select_filter.search": "Buscar ou crear",
+  "filter_modal.select_filter.subtitle": "Usar unha categoría existente ou crear unha nova",
+  "filter_modal.select_filter.title": "Filtrar esta publicación",
+  "filter_modal.title.status": "Filtrar unha publicación",
   "follow_recommendations.done": "Feito",
   "follow_recommendations.heading": "Segue a persoas das que queiras ler publicacións! Aqui tes unhas suxestións.",
   "follow_recommendations.lead": "As publicacións das persoas que segues aparecerán na túa cronoloxía de inicio ordenadas temporalmente. Non teñas medo a equivocarte, podes deixar de seguirlas igual de fácil en calquera momento!",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Primeiros pasos",
   "getting_started.invite": "Convidar persoas",
   "getting_started.open_source_notice": "Mastodon é software de código aberto. Podes contribuír ou informar de fallos en GitHub en {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Seguranza",
-  "getting_started.terms": "Termos do servizo",
   "hashtag.column_header.tag_mode.all": "e {additional}",
   "hashtag.column_header.tag_mode.any": "ou {additional}",
   "hashtag.column_header.tag_mode.none": "sen {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Non atopamos nada con estos termos de busca",
   "search_results.statuses": "Publicacións",
   "search_results.statuses_fts_disabled": "Procurar publicacións polo seu contido non está activado neste servidor do Mastodon.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {resultado} other {resultados}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Abrir interface de moderación para @{name}",
   "status.admin_status": "Abrir esta publicación na interface de moderación",
   "status.block": "Bloquear a @{name}",
@@ -487,7 +492,7 @@
   "status.edited_x_times": "Editado {count, plural, one {{count} vez} other {{count} veces}}",
   "status.embed": "Incrustar",
   "status.favourite": "Favorito",
-  "status.filter": "Filter this post",
+  "status.filter": "Filtrar esta publicación",
   "status.filtered": "Filtrado",
   "status.hide": "Agochar publicación",
   "status.history.created": "{name} creouno o {date}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Amosar menos para todos",
   "status.show_more": "Amosar máis",
   "status.show_more_all": "Amosar máis para todos",
+  "status.show_original": "Mostrar o orixinal",
   "status.show_thread": "Amosar fío",
+  "status.translate": "Traducir",
+  "status.translated_from": "Traducido do {lang}",
   "status.uncached_media_warning": "Non dispoñíbel",
   "status.unmute_conversation": "Deixar de silenciar conversa",
   "status.unpin": "Desafixar do perfil",
+  "subscribed_languages.lead": "Ao facer cambios só as publicacións nos idiomas seleccionados aparecerán nas túas cronoloxías. Non elixas ningún para poder ver publicacións en tódolos idiomas.",
+  "subscribed_languages.save": "Gardar cambios",
+  "subscribed_languages.target": "Cambiar a subscrición a idiomas para {target}",
   "suggestions.dismiss": "Rexeitar suxestión",
   "suggestions.header": "Poderíache interesar…",
   "tabs_bar.federated_timeline": "Federada",
diff --git a/app/javascript/mastodon/locales/he.json b/app/javascript/mastodon/locales/he.json
index 281b91bc1..5e0323585 100644
--- a/app/javascript/mastodon/locales/he.json
+++ b/app/javascript/mastodon/locales/he.json
@@ -24,6 +24,7 @@
   "account.follows_you": "במעקב אחריך",
   "account.hide_reblogs": "להסתיר הידהודים מאת @{name}",
   "account.joined": "הצטרפו ב{date}",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "בעלות על הקישור הזה נבדקה לאחרונה ב{date}",
   "account.locked_info": "מצב הפרטיות של החשבון הנוכחי הוגדר כנעול. בעל החשבון קובע באופן פרטני מי יכול לעקוב אחריו.",
   "account.media": "מדיה",
@@ -59,7 +60,7 @@
   "alert.unexpected.title": "אופס!",
   "announcement.announcement": "הכרזה",
   "attachments_list.unprocessed": "(לא מעובד)",
-  "audio.hide": "Hide audio",
+  "audio.hide": "השתק",
   "autosuggest_hashtag.per_week": "{count} לשבוע",
   "boost_modal.combo": "ניתן להקיש {combo} כדי לדלג בפעם הבאה",
   "bundle_column_error.body": "משהו השתבש בעת טעינת הרכיב הזה.",
@@ -197,22 +198,22 @@
   "explore.trending_links": "חדשות",
   "explore.trending_statuses": "פוסטים",
   "explore.trending_tags": "האשטאגים",
-  "filter_modal.added.context_mismatch_explanation": "This filter category does not apply to the context in which you have accessed this post. If you want the post to be filtered in this context too, you will have to edit the filter.",
-  "filter_modal.added.context_mismatch_title": "Context mismatch!",
-  "filter_modal.added.expired_explanation": "This filter category has expired, you will need to change the expiration date for it to apply.",
-  "filter_modal.added.expired_title": "Expired filter!",
-  "filter_modal.added.review_and_configure": "To review and further configure this filter category, go to the {settings_link}.",
-  "filter_modal.added.review_and_configure_title": "Filter settings",
-  "filter_modal.added.settings_link": "settings page",
-  "filter_modal.added.short_explanation": "This post has been added to the following filter category: {title}.",
-  "filter_modal.added.title": "Filter added!",
-  "filter_modal.select_filter.context_mismatch": "does not apply to this context",
-  "filter_modal.select_filter.expired": "expired",
-  "filter_modal.select_filter.prompt_new": "New category: {name}",
-  "filter_modal.select_filter.search": "Search or create",
-  "filter_modal.select_filter.subtitle": "Use an existing category or create a new one",
-  "filter_modal.select_filter.title": "Filter this post",
-  "filter_modal.title.status": "Filter a post",
+  "filter_modal.added.context_mismatch_explanation": "קטגוריית הפילטר הזאת לא חלה על ההקשר שממנו הגעת אל הפוסט הזה. אם תרצה/י שהפוסט יסונן גם בהקשר זה, תצטרך/י לערוך את הפילטר.",
+  "filter_modal.added.context_mismatch_title": "אין התאמה להקשר!",
+  "filter_modal.added.expired_explanation": "פג תוקפה של קטגוריית הסינון הזו, יש צורך לשנות את תאריך התפוגה כדי שהסינון יוחל.",
+  "filter_modal.added.expired_title": "פג תוקף הפילטר!",
+  "filter_modal.added.review_and_configure": "לסקירה והתאמה מתקדמת של קטגוריית הסינון הזו, לכו ל{settings_link}.",
+  "filter_modal.added.review_and_configure_title": "אפשרויות סינון",
+  "filter_modal.added.settings_link": "דף הגדרות",
+  "filter_modal.added.short_explanation": "הפוסט הזה הוסף לקטגוריית הסינון הזו: {title}.",
+  "filter_modal.added.title": "הפילטר הוסף!",
+  "filter_modal.select_filter.context_mismatch": "לא חל בהקשר זה",
+  "filter_modal.select_filter.expired": "פג התוקף",
+  "filter_modal.select_filter.prompt_new": "קטגוריה חדשה {name}",
+  "filter_modal.select_filter.search": "חיפוש או יצירה",
+  "filter_modal.select_filter.subtitle": "שימוש בקטגורייה קיימת או יצירת אחת חדשה",
+  "filter_modal.select_filter.title": "סינון הפוסט הזה",
+  "filter_modal.title.status": "סנן פוסט",
   "follow_recommendations.done": "בוצע",
   "follow_recommendations.heading": "עקב/י אחרי אנשים שתרצה/י לראות את חצרוציהם! הנה כמה הצעות.",
   "follow_recommendations.lead": "חצרוצים מאנשים במעקב יופיעו בסדר כרונולוגי בפיד הבית. אל תחששו מטעויות, אפשר להסיר מעקב באותה הקלות ובכל זמן!",
@@ -226,8 +227,8 @@
   "getting_started.heading": "בואו נתחיל",
   "getting_started.invite": "להזמין אנשים",
   "getting_started.open_source_notice": "מסטודון היא תוכנה חופשית (בקוד פתוח). ניתן לתרום או לדווח על בעיות בגיטהאב: {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "הגדרות חשבון",
-  "getting_started.terms": "תנאי שימוש",
   "hashtag.column_header.tag_mode.all": "ו- {additional}",
   "hashtag.column_header.tag_mode.any": "או {additional}",
   "hashtag.column_header.tag_mode.none": "ללא {additional}",
@@ -256,7 +257,7 @@
   "keyboard_shortcuts.description": "תיאור",
   "keyboard_shortcuts.direct": "לפתיחת טור הודעות ישירות",
   "keyboard_shortcuts.down": "לנוע במורד הרשימה",
-  "keyboard_shortcuts.enter": "פתח חצרוץ",
+  "keyboard_shortcuts.enter": "פתח פוסט",
   "keyboard_shortcuts.favourite": "לחבב",
   "keyboard_shortcuts.favourites": "פתיחת רשימת מועדפים",
   "keyboard_shortcuts.federated": "פתיחת ציר זמן בין-קהילתי",
@@ -270,7 +271,7 @@
   "keyboard_shortcuts.my_profile": "פתיחת הפרופיל שלך",
   "keyboard_shortcuts.notifications": "פתיחת טור התראות",
   "keyboard_shortcuts.open_media": "פתיחת מדיה",
-  "keyboard_shortcuts.pinned": "פתיחת רשימת חצרותים מוצמדים",
+  "keyboard_shortcuts.pinned": "פתיחת פוסטים נעוצים",
   "keyboard_shortcuts.profile": "פתח את פרופיל המשתמש",
   "keyboard_shortcuts.reply": "תגובה לפוסט",
   "keyboard_shortcuts.requests": "פתיחת רשימת בקשות מעקב",
@@ -362,7 +363,7 @@
   "notifications.column_settings.reblog": "הדהודים:",
   "notifications.column_settings.show": "הצגה בטור",
   "notifications.column_settings.sound": "שמע מופעל",
-  "notifications.column_settings.status": "New toots:",
+  "notifications.column_settings.status": "פוסטים חדשים:",
   "notifications.column_settings.unread_notifications.category": "התראות שלא נקראו",
   "notifications.column_settings.unread_notifications.highlight": "הבלט התראות שלא נקראו",
   "notifications.column_settings.update": "שינויים:",
@@ -424,13 +425,13 @@
   "report.category.subtitle": "בחר/י את המתאים ביותר",
   "report.category.title": "ספר/י לנו מה קורה עם ה-{type} הזה",
   "report.category.title_account": "פרופיל",
-  "report.category.title_status": "חצרוץ",
+  "report.category.title_status": "פוסט",
   "report.close": "בוצע",
   "report.comment.title": "האם יש דבר נוסף שלדעתך חשוב שנדע?",
   "report.forward": "קדם ל-{target}",
   "report.forward_hint": "חשבון זה הוא משרת אחר. האם לשלוח בנוסף עותק אנונימי לשם?",
   "report.mute": "להשתיק",
-  "report.mute_explanation": "לא ניתן יהיה לראות את חצרוציהם. הם עדיין יוכלו לעקוב אחריך ולראות את חצרוציך ולא ידעו שהם מושתקים.",
+  "report.mute_explanation": "לא ניתן יהיה לראות את הפוסטים. הם עדיין יוכלו לעקוב אחריך ולראות את הפוסטים שלך ולא ידעו שהם מושתקים.",
   "report.next": "הבא",
   "report.placeholder": "הערות נוספות",
   "report.reasons.dislike": "אני לא אוהב את זה",
@@ -444,7 +445,7 @@
   "report.rules.subtitle": "בחר/י את כל המתאימים",
   "report.rules.title": "אילו חוקים מופרים?",
   "report.statuses.subtitle": "בחר/י את כל המתאימים",
-  "report.statuses.title": "האם ישנם חצרוצים התומכים בדיווח זה?",
+  "report.statuses.title": "האם ישנם פוסטים התומכים בדיווח זה?",
   "report.submit": "שליחה",
   "report.target": "דיווח על {target}",
   "report.thanks.take_action": "הנה כמה אפשרויות לשליטה בתצוגת מסטודון:",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "לא נמצא דבר עבור תנאי חיפוש אלה",
   "search_results.statuses": "פוסטים",
   "search_results.statuses_fts_disabled": "חיפוש פוסטים לפי תוכן לא מאופשר בשרת מסטודון זה.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {תוצאה} other {תוצאות}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "פתח/י ממשק ניהול עבור @{name}",
   "status.admin_status": "Open this status in the moderation interface",
   "status.block": "חסימת @{name}",
@@ -487,7 +492,7 @@
   "status.edited_x_times": "נערך {count, plural, one {פעם {count}} other {{count} פעמים}}",
   "status.embed": "הטמעה",
   "status.favourite": "חיבוב",
-  "status.filter": "Filter this post",
+  "status.filter": "סנן פוסט זה",
   "status.filtered": "סונן",
   "status.hide": "הסתר פוסט",
   "status.history.created": "{name} יצר/ה {date}",
@@ -505,7 +510,7 @@
   "status.reblog": "הדהוד",
   "status.reblog_private": "להדהד ברמת הנראות המקורית",
   "status.reblogged_by": "{name} הידהד/ה:",
-  "status.reblogs.empty": "No one has boosted this toot yet. When someone does, they will show up here.",
+  "status.reblogs.empty": "עוד לא הידהדו את הפוסט הזה. כאשר זה יקרה, ההדהודים יופיעו כאן.",
   "status.redraft": "מחיקה ועריכה מחדש",
   "status.remove_bookmark": "הסרת סימניה",
   "status.reply": "תגובה",
@@ -518,10 +523,16 @@
   "status.show_less_all": "להציג פחות מהכל",
   "status.show_more": "הראה יותר",
   "status.show_more_all": "להציג יותר מהכל",
+  "status.show_original": "Show original",
   "status.show_thread": "הצג כחלק מפתיל",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "לא זמין",
   "status.unmute_conversation": "הסרת השתקת שיחה",
   "status.unpin": "לשחרר מקיבוע באודות",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "להתעלם מהצעה",
   "suggestions.header": "ייתכן שזה יעניין אותך…",
   "tabs_bar.federated_timeline": "פיד כללי (בין-קהילתי)",
diff --git a/app/javascript/mastodon/locales/hi.json b/app/javascript/mastodon/locales/hi.json
index d2403c1f5..2d222d4cb 100644
--- a/app/javascript/mastodon/locales/hi.json
+++ b/app/javascript/mastodon/locales/hi.json
@@ -24,6 +24,7 @@
   "account.follows_you": "आपको फॉलो करता है",
   "account.hide_reblogs": "@{name} के बूस्ट छुपाएं",
   "account.joined": "शामिल हुये {date}",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "इस लिंक का स्वामित्व {date} को चेक किया गया था",
   "account.locked_info": "यह खाता गोपनीयता स्थिति लॉक करने के लिए सेट है। मालिक मैन्युअल रूप से समीक्षा करता है कि कौन उनको फॉलो कर सकता है।",
   "account.media": "मीडिया",
@@ -226,8 +227,8 @@
   "getting_started.heading": "पहले कदम रखें",
   "getting_started.invite": "दोस्तों को आमंत्रित करें",
   "getting_started.open_source_notice": "मास्टोडॉन एक मुक्त स्रोत सॉफ्टवेयर है. आप गिटहब {github} पर इस सॉफ्टवेयर में योगदान या किसी भी समस्या को सूचित कर सकते है.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "अकाउंट सेटिंग्स",
-  "getting_started.terms": "सेवा की शर्तें",
   "hashtag.column_header.tag_mode.all": "और {additional}",
   "hashtag.column_header.tag_mode.any": "या {additional}",
   "hashtag.column_header.tag_mode.none": "बिना {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Could not find anything for these search terms",
   "search_results.statuses": "Toots",
   "search_results.statuses_fts_disabled": "Searching toots by their content is not enabled on this Mastodon server.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {result} other {results}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Open moderation interface for @{name}",
   "status.admin_status": "Open this status in the moderation interface",
   "status.block": "Block @{name}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Show less for all",
   "status.show_more": "और दिखाएँ",
   "status.show_more_all": "Show more for all",
+  "status.show_original": "Show original",
   "status.show_thread": "Show thread",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "अनुपलब्ध",
   "status.unmute_conversation": "Unmute conversation",
   "status.unpin": "Unpin from profile",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "Dismiss suggestion",
   "suggestions.header": "You might be interested in…",
   "tabs_bar.federated_timeline": "फ़ेडरेटेड",
diff --git a/app/javascript/mastodon/locales/hr.json b/app/javascript/mastodon/locales/hr.json
index c66de9c0d..4356fd297 100644
--- a/app/javascript/mastodon/locales/hr.json
+++ b/app/javascript/mastodon/locales/hr.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Prati te",
   "account.hide_reblogs": "Sakrij boostove od @{name}",
   "account.joined": "Pridružio se {date}",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "Vlasništvo ove poveznice provjereno je {date}",
   "account.locked_info": "Status privatnosti ovog računa postavljen je na zaključano. Vlasnik ručno pregledava tko ih može pratiti.",
   "account.media": "Medijski sadržaj",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Počnimo",
   "getting_started.invite": "Pozovi ljude",
   "getting_started.open_source_notice": "Mastodon je softver otvorenog kôda. Možete pridonijeti ili prijaviti probleme na GitHubu na {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Postavke računa",
-  "getting_started.terms": "Uvjeti pružanja usluga",
   "hashtag.column_header.tag_mode.all": "i {additional}",
   "hashtag.column_header.tag_mode.any": "ili {additional}",
   "hashtag.column_header.tag_mode.none": "bez {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Could not find anything for these search terms",
   "search_results.statuses": "Toots",
   "search_results.statuses_fts_disabled": "Searching toots by their content is not enabled on this Mastodon server.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {result} other {results}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Open moderation interface for @{name}",
   "status.admin_status": "Open this status in the moderation interface",
   "status.block": "Block @{name}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Show less for all",
   "status.show_more": "Pokaži više",
   "status.show_more_all": "Show more for all",
+  "status.show_original": "Show original",
   "status.show_thread": "Prikaži nit",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "Nije dostupno",
   "status.unmute_conversation": "Poništi utišavanje razgovora",
   "status.unpin": "Otkvači s profila",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "Odbaci prijedlog",
   "suggestions.header": "Možda Vas zanima…",
   "tabs_bar.federated_timeline": "Federalno",
diff --git a/app/javascript/mastodon/locales/hu.json b/app/javascript/mastodon/locales/hu.json
index ce25cd103..3a183f304 100644
--- a/app/javascript/mastodon/locales/hu.json
+++ b/app/javascript/mastodon/locales/hu.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Követ téged",
   "account.hide_reblogs": "@{name} megtolásainak elrejtése",
   "account.joined": "Csatlakozott {date}",
+  "account.languages": "Feliratkozott nyelvek módosítása",
   "account.link_verified_on": "A linket eredetiségét ebben az időpontban ellenőriztük: {date}",
   "account.locked_info": "Ennek a fióknak zárolt a láthatósága. A tulajdonos kézzel engedélyezi, hogy ki követheti őt.",
   "account.media": "Média",
@@ -197,22 +198,22 @@
   "explore.trending_links": "Hírek",
   "explore.trending_statuses": "Bejegyzések",
   "explore.trending_tags": "Hashtagek",
-  "filter_modal.added.context_mismatch_explanation": "This filter category does not apply to the context in which you have accessed this post. If you want the post to be filtered in this context too, you will have to edit the filter.",
-  "filter_modal.added.context_mismatch_title": "Context mismatch!",
-  "filter_modal.added.expired_explanation": "This filter category has expired, you will need to change the expiration date for it to apply.",
-  "filter_modal.added.expired_title": "Expired filter!",
-  "filter_modal.added.review_and_configure": "To review and further configure this filter category, go to the {settings_link}.",
-  "filter_modal.added.review_and_configure_title": "Filter settings",
-  "filter_modal.added.settings_link": "settings page",
-  "filter_modal.added.short_explanation": "This post has been added to the following filter category: {title}.",
-  "filter_modal.added.title": "Filter added!",
-  "filter_modal.select_filter.context_mismatch": "does not apply to this context",
-  "filter_modal.select_filter.expired": "expired",
-  "filter_modal.select_filter.prompt_new": "New category: {name}",
-  "filter_modal.select_filter.search": "Search or create",
-  "filter_modal.select_filter.subtitle": "Use an existing category or create a new one",
-  "filter_modal.select_filter.title": "Filter this post",
-  "filter_modal.title.status": "Filter a post",
+  "filter_modal.added.context_mismatch_explanation": "Ez a szűrőkategória nem érvényes abban a környezetben, amelyből elérted ezt a bejegyzést. Ha ebben a környezetben is szűrni szeretnéd a bejegyzést, akkor szerkesztened kell a szűrőt.",
+  "filter_modal.added.context_mismatch_title": "Környezeti eltérés.",
+  "filter_modal.added.expired_explanation": "Ez a szűrőkategória elévült, a használatához módosítanod kell az elévülési dátumot.",
+  "filter_modal.added.expired_title": "Elévült szűrő.",
+  "filter_modal.added.review_and_configure": "A szűrőkategória felülvizsgálatához és további beállításához ugorjon a {settings_link} oldalra.",
+  "filter_modal.added.review_and_configure_title": "Szűrőbeállítások",
+  "filter_modal.added.settings_link": "beállítások oldal",
+  "filter_modal.added.short_explanation": "A következő bejegyzés hozzá lett adva a következő szűrőkategóriához: {title}.",
+  "filter_modal.added.title": "Szűrő hozzáadva.",
+  "filter_modal.select_filter.context_mismatch": "nem érvényes erre a környezetre",
+  "filter_modal.select_filter.expired": "elévült",
+  "filter_modal.select_filter.prompt_new": "Új kategória: {name}",
+  "filter_modal.select_filter.search": "Keresés vagy létrehozás",
+  "filter_modal.select_filter.subtitle": "Válassz egy meglévő kategóriát, vagy hozz létre egy újat",
+  "filter_modal.select_filter.title": "E bejegyzés szűrése",
+  "filter_modal.title.status": "Egy bejegyzés szűrése",
   "follow_recommendations.done": "Kész",
   "follow_recommendations.heading": "Kövesd azokat, akiknek a bejegyzéseit látni szeretnéd! Itt van néhány javaslat.",
   "follow_recommendations.lead": "Az általad követettek bejegyzései a saját idővonaladon fognak megjelenni időrendi sorrendben. Ne félj attól, hogy hibázol! A követést bármikor, ugyanilyen könnyen visszavonhatod!",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Első lépések",
   "getting_started.invite": "Mások meghívása",
   "getting_started.open_source_notice": "A Mastodon nyílt forráskódú szoftver. Közreműködhetsz vagy problémákat jelenthetsz a GitHubon: {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Fiókbeállítások",
-  "getting_started.terms": "Felhasználási feltételek",
   "hashtag.column_header.tag_mode.all": "és {additional}",
   "hashtag.column_header.tag_mode.any": "vagy {additional}",
   "hashtag.column_header.tag_mode.none": "{additional} nélkül",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Nincs találat ezekre a keresési kifejezésekre",
   "search_results.statuses": "Bejegyzések",
   "search_results.statuses_fts_disabled": "Ezen a Mastodon szerveren nem engedélyezett a bejegyzések tartalom szerinti keresése.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {találat} other {találat}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Moderációs felület megnyitása @{name} fiókhoz",
   "status.admin_status": "Bejegyzés megnyitása a moderációs felületen",
   "status.block": "@{name} letiltása",
@@ -487,7 +492,7 @@
   "status.edited_x_times": "{count, plural, one {{count} alkalommal} other {{count} alkalommal}} szerkesztve",
   "status.embed": "Beágyazás",
   "status.favourite": "Kedvenc",
-  "status.filter": "Filter this post",
+  "status.filter": "E bejegyzés szűrése",
   "status.filtered": "Megszűrt",
   "status.hide": "Bejegyzés elrejtése",
   "status.history.created": "{name} létrehozta: {date}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Kevesebbet mindenhol",
   "status.show_more": "Többet",
   "status.show_more_all": "Többet mindenhol",
+  "status.show_original": "Eredeti mutatása",
   "status.show_thread": "Szál mutatása",
+  "status.translate": "Fordítás",
+  "status.translated_from": "{lang} nyelvből fordítva",
   "status.uncached_media_warning": "Nem érhető el",
   "status.unmute_conversation": "Beszélgetés némításának feloldása",
   "status.unpin": "Kitűzés eltávolítása a profilodról",
+  "subscribed_languages.lead": "A változtatás után csak a kiválasztott nyelvű bejegyzések fognak megjelenni a kezdőlapon és az idővonalakon. Ha egy sincs kiválasztva, akkor minden nyelven megjelennek a bejegyzések.",
+  "subscribed_languages.save": "Változások mentése",
+  "subscribed_languages.target": "Feliratkozott nyelvek módosítása a következőnél: {target}",
   "suggestions.dismiss": "Javaslat elvetése",
   "suggestions.header": "Esetleg érdekelhet…",
   "tabs_bar.federated_timeline": "Föderációs",
diff --git a/app/javascript/mastodon/locales/hy.json b/app/javascript/mastodon/locales/hy.json
index 5a18eff04..48e5bc53f 100644
--- a/app/javascript/mastodon/locales/hy.json
+++ b/app/javascript/mastodon/locales/hy.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Հետեւում է քեզ",
   "account.hide_reblogs": "Թաքցնել @{name}֊ի տարածածները",
   "account.joined": "Միացել է {date}-ից",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "Սոյն յղման տիրապետումը ստուգուած է՝ {date}֊ին",
   "account.locked_info": "Սոյն հաշուի գաղտնիութեան մակարդակը նշուած է որպէս՝ փակ։ Հաշուի տէրն ընտրում է, թէ ով կարող է հետեւել իրեն։",
   "account.media": "Մեդիա",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Ինչպէս սկսել",
   "getting_started.invite": "Հրաւիրել մարդկանց",
   "getting_started.open_source_notice": "Մաստոդոնը բաց ելատեքստով ծրագրակազմ է։ Կարող ես ներդրում անել կամ վրէպներ զեկուցել ԳիթՀաբում՝ {github}։",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Հաշուի կարգաւորումներ",
-  "getting_started.terms": "Ծառայութեան պայմանները",
   "hashtag.column_header.tag_mode.all": "եւ {additional}",
   "hashtag.column_header.tag_mode.any": "կամ {additional}",
   "hashtag.column_header.tag_mode.none": "առանց {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Could not find anything for these search terms",
   "search_results.statuses": "Գրառումներ",
   "search_results.statuses_fts_disabled": "Այս հանգոյցում միացուած չէ ըստ բովանդակութեան գրառում փնտրելու հնարաւորութիւնը։",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {արդիւնք} other {արդիւնք}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Բացել @{name} օգտատիրոջ մոդերացիայի դիմերէսը։",
   "status.admin_status": "Բացել այս գրառումը մոդերատորի դիմերէսի մէջ",
   "status.block": "Արգելափակել @{name}֊ին",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Թաքցնել բոլոր նախազգուշացնումները",
   "status.show_more": "Աւելին",
   "status.show_more_all": "Ցուցադրել բոլոր նախազգուշացնումները",
+  "status.show_original": "Show original",
   "status.show_thread": "Բացել շղթան",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "Անհասանելի",
   "status.unmute_conversation": "Ապալռեցնել խօսակցութիւնը",
   "status.unpin": "Հանել անձնական էջից",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "Անտեսել առաջարկը",
   "suggestions.header": "Միգուցէ քեզ հետաքրքրի…",
   "tabs_bar.federated_timeline": "Դաշնային",
diff --git a/app/javascript/mastodon/locales/id.json b/app/javascript/mastodon/locales/id.json
index 9c3879212..f81b7d9ad 100644
--- a/app/javascript/mastodon/locales/id.json
+++ b/app/javascript/mastodon/locales/id.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Mengikuti anda",
   "account.hide_reblogs": "Sembunyikan boosts dari @{name}",
   "account.joined": "Bergabung {date}",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "Kepemilikan tautan ini telah dicek pada {date}",
   "account.locked_info": "Status privasi akun ini disetel untuk dikunci. Pemilik secara manual meninjau siapa yang dapat mengikutinya.",
   "account.media": "Media",
@@ -59,7 +60,7 @@
   "alert.unexpected.title": "Ups!",
   "announcement.announcement": "Pengumuman",
   "attachments_list.unprocessed": "(tidak diproses)",
-  "audio.hide": "Hide audio",
+  "audio.hide": "Indonesia",
   "autosuggest_hashtag.per_week": "{count} per minggu",
   "boost_modal.combo": "Anda dapat menekan {combo} untuk melewati ini",
   "bundle_column_error.body": "Kesalahan terjadi saat memuat komponen ini.",
@@ -197,7 +198,7 @@
   "explore.trending_links": "Berita",
   "explore.trending_statuses": "Postingan",
   "explore.trending_tags": "Tagar",
-  "filter_modal.added.context_mismatch_explanation": "This filter category does not apply to the context in which you have accessed this post. If you want the post to be filtered in this context too, you will have to edit the filter.",
+  "filter_modal.added.context_mismatch_explanation": "Indonesia Translate",
   "filter_modal.added.context_mismatch_title": "Context mismatch!",
   "filter_modal.added.expired_explanation": "This filter category has expired, you will need to change the expiration date for it to apply.",
   "filter_modal.added.expired_title": "Expired filter!",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Mulai",
   "getting_started.invite": "Undang orang",
   "getting_started.open_source_notice": "Mastodon adalah perangkat lunak yang bersifat terbuka. Anda dapat berkontribusi atau melaporkan permasalahan/bug di Github {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Keamanan",
-  "getting_started.terms": "Ketentuan layanan",
   "hashtag.column_header.tag_mode.all": "dan {additional}",
   "hashtag.column_header.tag_mode.any": "atau {additional}",
   "hashtag.column_header.tag_mode.none": "tanpa {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Tidak dapat menemukan apapun untuk istilah-istilah pencarian ini",
   "search_results.statuses": "Toot",
   "search_results.statuses_fts_disabled": "Pencarian toot berdasarkan konten tidak diaktifkan di server Mastadon ini.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {hasil} other {hasil}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Buka antar muka moderasi untuk @{name}",
   "status.admin_status": "Buka status ini dalam antar muka moderasi",
   "status.block": "Blokir @{name}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Tampilkan lebih sedikit",
   "status.show_more": "Tampilkan semua",
   "status.show_more_all": "Tampilkan lebih banyak",
+  "status.show_original": "Show original",
   "status.show_thread": "Tampilkan utas",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "Tak tersedia",
   "status.unmute_conversation": "Bunyikan percakapan",
   "status.unpin": "Hapus sematan dari profil",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "Hentikan saran",
   "suggestions.header": "Anda mungkin tertarik dg…",
   "tabs_bar.federated_timeline": "Gabungan",
diff --git a/app/javascript/mastodon/locales/io.json b/app/javascript/mastodon/locales/io.json
index f3bdb040c..9f61d8297 100644
--- a/app/javascript/mastodon/locales/io.json
+++ b/app/javascript/mastodon/locales/io.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Sequas tu",
   "account.hide_reblogs": "Celez busti de @{name}",
   "account.joined": "Juntas ye {date}",
+  "account.languages": "Chanjez abonita lingui",
   "account.link_verified_on": "Proprieteso di ca ligilo kontrolesis ye {date}",
   "account.locked_info": "La privatesostaco di ca konto fixesas quale lokata. Proprietato manue kontrolas personi qui povas sequar.",
   "account.media": "Medio",
@@ -197,22 +198,22 @@
   "explore.trending_links": "Niuzi",
   "explore.trending_statuses": "Posti",
   "explore.trending_tags": "Hashtagi",
-  "filter_modal.added.context_mismatch_explanation": "This filter category does not apply to the context in which you have accessed this post. If you want the post to be filtered in this context too, you will have to edit the filter.",
-  "filter_modal.added.context_mismatch_title": "Context mismatch!",
-  "filter_modal.added.expired_explanation": "This filter category has expired, you will need to change the expiration date for it to apply.",
-  "filter_modal.added.expired_title": "Expired filter!",
-  "filter_modal.added.review_and_configure": "To review and further configure this filter category, go to the {settings_link}.",
-  "filter_modal.added.review_and_configure_title": "Filter settings",
-  "filter_modal.added.settings_link": "settings page",
-  "filter_modal.added.short_explanation": "This post has been added to the following filter category: {title}.",
-  "filter_modal.added.title": "Filter added!",
-  "filter_modal.select_filter.context_mismatch": "does not apply to this context",
-  "filter_modal.select_filter.expired": "expired",
-  "filter_modal.select_filter.prompt_new": "New category: {name}",
-  "filter_modal.select_filter.search": "Search or create",
-  "filter_modal.select_filter.subtitle": "Use an existing category or create a new one",
-  "filter_modal.select_filter.title": "Filter this post",
-  "filter_modal.title.status": "Filter a post",
+  "filter_modal.added.context_mismatch_explanation": "Ca filtrilgrupo ne relatesas kun informo de ca acesesita posto. Se vu volas posto filtresar kun ca informo anke, vu bezonas modifikar filtrilo.",
+  "filter_modal.added.context_mismatch_title": "Kontenajneparigeso!",
+  "filter_modal.added.expired_explanation": "Ca filtrilgrupo expiris, vu bezonas chanjar expirtempo por apliko.",
+  "filter_modal.added.expired_title": "Expirinta filtrilo!",
+  "filter_modal.added.review_and_configure": "Por kontrolar e plue ajustar ca filtrilgrupo, irez a {settings_link}.",
+  "filter_modal.added.review_and_configure_title": "Filtrilopcioni",
+  "filter_modal.added.settings_link": "opcionpagino",
+  "filter_modal.added.short_explanation": "Ca posto adjuntesas a ca filtrilgrupo: {title}.",
+  "filter_modal.added.title": "Filtrilo adjuntesas!",
+  "filter_modal.select_filter.context_mismatch": "ne relatesas kun ca informo",
+  "filter_modal.select_filter.expired": "expiris",
+  "filter_modal.select_filter.prompt_new": "Nova grupo: {name}",
+  "filter_modal.select_filter.search": "Trovez o kreez",
+  "filter_modal.select_filter.subtitle": "Usez disponebla grupo o kreez novajo",
+  "filter_modal.select_filter.title": "Filtragez ca posto",
+  "filter_modal.title.status": "Filtragez posto",
   "follow_recommendations.done": "Fina",
   "follow_recommendations.heading": "Sequez personi quo igas posti quon vu volas vidar! Hike esas ula sugestati.",
   "follow_recommendations.lead": "Posti de personi quon vu sequas kronologiale montresos en vua hemniuzeto. Ne timas igar erori, vu povas desequar personi tam same facila irgatempe!",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Debuto",
   "getting_started.invite": "Invitez personi",
   "getting_started.open_source_notice": "Mastodon esas programaro kun apertita kodexo. Tu povas kontributar o signalar problemi en GitHub ye {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Kontoopcioni",
-  "getting_started.terms": "Servkondicioni",
   "hashtag.column_header.tag_mode.all": "e {additional}",
   "hashtag.column_header.tag_mode.any": "o {additional}",
   "hashtag.column_header.tag_mode.none": "sen {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Ne povas ganar irgo per ca trovvorti",
   "search_results.statuses": "Posti",
   "search_results.statuses_fts_disabled": "Searching toots by their content is not enabled on this Mastodon server.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {rezulto} other {rezulti}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Apertez jerintervizajo por @{name}",
   "status.admin_status": "Open this status in the moderation interface",
   "status.block": "Restriktez @{name}",
@@ -487,7 +492,7 @@
   "status.edited_x_times": "Modifikesis {count, plural, one {{count} foyo} other {{count} foyi}}",
   "status.embed": "Eninsertez",
   "status.favourite": "Favorizar",
-  "status.filter": "Filter this post",
+  "status.filter": "Filtragez ca posto",
   "status.filtered": "Filtrita",
   "status.hide": "Celez posto",
   "status.history.created": "{name} kreis ye {date}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Montrez min por omno",
   "status.show_more": "Montrar plue",
   "status.show_more_all": "Montrez pluse por omno",
+  "status.show_original": "Montrez originalo",
   "status.show_thread": "Montrez postaro",
+  "status.translate": "Tradukez",
+  "status.translated_from": "Tradukesis de {lang}",
   "status.uncached_media_warning": "Nedisplonebla",
   "status.unmute_conversation": "Desilencigez konverso",
   "status.unpin": "Depinglagez de profilo",
+  "subscribed_languages.lead": "Nur posti en selektita lingui aparos en vua hemo e listotempolineo pos chanjo. Selektez nulo por ganar posti en omna lingui.",
+  "subscribed_languages.save": "Sparez chanji",
+  "subscribed_languages.target": "Chanjez abonita lingui por {target}",
   "suggestions.dismiss": "Desklozez sugestajo",
   "suggestions.header": "Vu forsan havas intereso pri…",
   "tabs_bar.federated_timeline": "Federata",
diff --git a/app/javascript/mastodon/locales/is.json b/app/javascript/mastodon/locales/is.json
index 7e3a40fa7..d5ed6300d 100644
--- a/app/javascript/mastodon/locales/is.json
+++ b/app/javascript/mastodon/locales/is.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Fylgir þér",
   "account.hide_reblogs": "Fela endurbirtingar fyrir @{name}",
   "account.joined": "Gerðist þátttakandi {date}",
+  "account.languages": "Breyta tungumálum í áskrift",
   "account.link_verified_on": "Eignarhald á þessum tengli var athugað þann {date}",
   "account.locked_info": "Staða gagnaleyndar á þessum aðgangi er stillt á læsingu. Eigandinn yfirfer handvirkt hverjir geti fylgst með honum.",
   "account.media": "Myndskrár",
@@ -197,22 +198,22 @@
   "explore.trending_links": "Fréttir",
   "explore.trending_statuses": "Færslur",
   "explore.trending_tags": "Myllumerki",
-  "filter_modal.added.context_mismatch_explanation": "This filter category does not apply to the context in which you have accessed this post. If you want the post to be filtered in this context too, you will have to edit the filter.",
-  "filter_modal.added.context_mismatch_title": "Context mismatch!",
-  "filter_modal.added.expired_explanation": "This filter category has expired, you will need to change the expiration date for it to apply.",
-  "filter_modal.added.expired_title": "Expired filter!",
-  "filter_modal.added.review_and_configure": "To review and further configure this filter category, go to the {settings_link}.",
-  "filter_modal.added.review_and_configure_title": "Filter settings",
-  "filter_modal.added.settings_link": "settings page",
-  "filter_modal.added.short_explanation": "This post has been added to the following filter category: {title}.",
-  "filter_modal.added.title": "Filter added!",
-  "filter_modal.select_filter.context_mismatch": "does not apply to this context",
-  "filter_modal.select_filter.expired": "expired",
-  "filter_modal.select_filter.prompt_new": "New category: {name}",
-  "filter_modal.select_filter.search": "Search or create",
-  "filter_modal.select_filter.subtitle": "Use an existing category or create a new one",
-  "filter_modal.select_filter.title": "Filter this post",
-  "filter_modal.title.status": "Filter a post",
+  "filter_modal.added.context_mismatch_explanation": "Þessi síuflokkur á ekki við í því samhengi sem aðgangur þinn að þessari færslu felur í sér. Ef þú vilt að færslan sé einnig síuð í þessu samhengi, þá þarftu að breyta síunni.",
+  "filter_modal.added.context_mismatch_title": "Misræmi í samhengi!",
+  "filter_modal.added.expired_explanation": "Þessi síuflokkur er útrunninn, þú þarft að breyta gidistímanum svo hann geti átt við.",
+  "filter_modal.added.expired_title": "Útrunnin sía!",
+  "filter_modal.added.review_and_configure": "Til að yfirfara og stilla frekar þennan síuflokk, ættirðu að fara í {settings_link}.",
+  "filter_modal.added.review_and_configure_title": "Síustillingar",
+  "filter_modal.added.settings_link": "stillingasíða",
+  "filter_modal.added.short_explanation": "Þessari færslu hefur verið bætt í eftirfarandi síuflokk: {title}.",
+  "filter_modal.added.title": "Síu bætt við!",
+  "filter_modal.select_filter.context_mismatch": "á ekki við í þessu samhengi",
+  "filter_modal.select_filter.expired": "útrunnið",
+  "filter_modal.select_filter.prompt_new": "Nýr flokkur: {name}",
+  "filter_modal.select_filter.search": "Leita eða búa til",
+  "filter_modal.select_filter.subtitle": "Notaðu fyrirliggjandi flokk eða útbúðu nýjan",
+  "filter_modal.select_filter.title": "Sía þessa færslu",
+  "filter_modal.title.status": "Sía færslu",
   "follow_recommendations.done": "Lokið",
   "follow_recommendations.heading": "Fylgstu með fólki sem þú vilt sjá færslur frá! Hér eru nokkrar tillögur.",
   "follow_recommendations.lead": "Færslur frá fólki sem þú fylgist með eru birtar í tímaröð á heimastreyminu þínu. Þú þarft ekki að hræðast mistök, það er jafn auðvelt að hætta að fylgjast með fólki hvenær sem er!",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Komast í gang",
   "getting_started.invite": "Bjóða fólki",
   "getting_started.open_source_notice": "Mastodon er opinn og frjáls hugbúnaður. Þú getur lagt þitt af mörkum eða tilkynnt um vandamál á GitHub á slóðinni {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Stillingar notandaaðgangs",
-  "getting_started.terms": "Þjónustuskilmálar",
   "hashtag.column_header.tag_mode.all": "og {additional}",
   "hashtag.column_header.tag_mode.any": "eða {additional}",
   "hashtag.column_header.tag_mode.none": "án {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Gat ekki fundið neitt sem samsvarar þessum leitarorðum",
   "search_results.statuses": "Færslur",
   "search_results.statuses_fts_disabled": "Að leita í efni færslna er ekki virkt á þessum Mastodon-þjóni.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {niðurstaða} other {niðurstöður}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Opna umsjónarviðmót fyrir @{name}",
   "status.admin_status": "Opna þessa færslu í umsjónarviðmótinu",
   "status.block": "Útiloka @{name}",
@@ -487,7 +492,7 @@
   "status.edited_x_times": "Breytt {count, plural, one {{count} sinni} other {{count} sinnum}}",
   "status.embed": "Ívefja",
   "status.favourite": "Eftirlæti",
-  "status.filter": "Filter this post",
+  "status.filter": "Sía þessa færslu",
   "status.filtered": "Síað",
   "status.hide": "Fela færslu",
   "status.history.created": "{name} útbjó {date}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Sýna minna fyrir allt",
   "status.show_more": "Sýna meira",
   "status.show_more_all": "Sýna meira fyrir allt",
+  "status.show_original": "Sýna upprunalega",
   "status.show_thread": "Birta þráð",
+  "status.translate": "Þýða",
+  "status.translated_from": "Þýtt úr {lang}",
   "status.uncached_media_warning": "Ekki tiltækt",
   "status.unmute_conversation": "Hætta að þagga niður í samtali",
   "status.unpin": "Losa af notandasniði",
+  "subscribed_languages.lead": "Einungis færslur á völdum tungumálum munu birtast á upphafssíðu og tímalínum þínum eftir þessa breytingu. Veldu ekkert til að sjá færslur á öllum tungumálum.",
+  "subscribed_languages.save": "Vista breytingar",
+  "subscribed_languages.target": "Breyta tungumálum í áskrift fyrir {target}",
   "suggestions.dismiss": "Hafna tillögu",
   "suggestions.header": "Þú gætir haft áhuga á…",
   "tabs_bar.federated_timeline": "Sameiginlegt",
@@ -539,7 +550,7 @@
   "timeline_hint.resources.follows": "Fylgist með",
   "timeline_hint.resources.statuses": "Eldri færslur",
   "trends.counter_by_accounts": "{count, plural, one {{counter} aðili} other {{counter} manns}} {days, plural, one {síðasta sólarhringinn} other {síðustu {days} daga}}",
-  "trends.trending_now": "Í umræðunni núna",
+  "trends.trending_now": "Vinsælt núna",
   "ui.beforeunload": "Drögin tapast ef þú ferð út úr Mastodon.",
   "units.short.billion": "{count}B",
   "units.short.million": "{count}M",
diff --git a/app/javascript/mastodon/locales/it.json b/app/javascript/mastodon/locales/it.json
index 9f32a0685..6e2b97463 100644
--- a/app/javascript/mastodon/locales/it.json
+++ b/app/javascript/mastodon/locales/it.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Ti segue",
   "account.hide_reblogs": "Nascondi condivisioni da @{name}",
   "account.joined": "Su questa istanza dal {date}",
+  "account.languages": "Cambia le lingue di cui ricevere i post",
   "account.link_verified_on": "La proprietà di questo link è stata controllata il {date}",
   "account.locked_info": "Questo è un account privato. Il proprietario approva manualmente chi può seguirlo.",
   "account.media": "Media",
@@ -197,22 +198,22 @@
   "explore.trending_links": "Novità",
   "explore.trending_statuses": "Post",
   "explore.trending_tags": "Hashtag",
-  "filter_modal.added.context_mismatch_explanation": "This filter category does not apply to the context in which you have accessed this post. If you want the post to be filtered in this context too, you will have to edit the filter.",
-  "filter_modal.added.context_mismatch_title": "Context mismatch!",
-  "filter_modal.added.expired_explanation": "This filter category has expired, you will need to change the expiration date for it to apply.",
-  "filter_modal.added.expired_title": "Expired filter!",
-  "filter_modal.added.review_and_configure": "To review and further configure this filter category, go to the {settings_link}.",
-  "filter_modal.added.review_and_configure_title": "Filter settings",
-  "filter_modal.added.settings_link": "settings page",
-  "filter_modal.added.short_explanation": "This post has been added to the following filter category: {title}.",
-  "filter_modal.added.title": "Filter added!",
-  "filter_modal.select_filter.context_mismatch": "does not apply to this context",
-  "filter_modal.select_filter.expired": "expired",
-  "filter_modal.select_filter.prompt_new": "New category: {name}",
-  "filter_modal.select_filter.search": "Search or create",
-  "filter_modal.select_filter.subtitle": "Use an existing category or create a new one",
-  "filter_modal.select_filter.title": "Filter this post",
-  "filter_modal.title.status": "Filter a post",
+  "filter_modal.added.context_mismatch_explanation": "La categoria di questo filtro non si applica al contesto in cui hai acceduto a questo post. Se desideri che il post sia filtrato anche in questo contesto, dovrai modificare il filtro.",
+  "filter_modal.added.context_mismatch_title": "Contesto non corrispondente!",
+  "filter_modal.added.expired_explanation": "La categoria di questo filtro è scaduta, dovrai modificarne la data di scadenza per applicarlo.",
+  "filter_modal.added.expired_title": "Filtro scaduto!",
+  "filter_modal.added.review_and_configure": "Per revisionare e configurare ulteriormente la categoria di questo filtro, vai alle {settings_link}.",
+  "filter_modal.added.review_and_configure_title": "Impostazioni del filtro",
+  "filter_modal.added.settings_link": "pagina delle impostazioni",
+  "filter_modal.added.short_explanation": "Questo post è stato aggiunto alla categoria del filtro seguente: {title}.",
+  "filter_modal.added.title": "Filtro aggiunto!",
+  "filter_modal.select_filter.context_mismatch": "non si applica a questo contesto",
+  "filter_modal.select_filter.expired": "scaduto",
+  "filter_modal.select_filter.prompt_new": "Nuova categoria: {name}",
+  "filter_modal.select_filter.search": "Cerca o crea",
+  "filter_modal.select_filter.subtitle": "Usa una categoria esistente o creane una nuova",
+  "filter_modal.select_filter.title": "Filtra questo post",
+  "filter_modal.title.status": "Filtra un post",
   "follow_recommendations.done": "Fatto",
   "follow_recommendations.heading": "Segui le persone da cui vuoi vedere i messaggi! Ecco alcuni suggerimenti.",
   "follow_recommendations.lead": "I messaggi da persone che segui verranno visualizzati in ordine cronologico nel tuo home feed. Non abbiate paura di commettere errori, potete smettere di seguire le persone altrettanto facilmente in qualsiasi momento!",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Come iniziare",
   "getting_started.invite": "Invita qualcuno",
   "getting_started.open_source_notice": "Mastodon è un software open source. Puoi contribuire o segnalare errori su GitHub all'indirizzo {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Sicurezza",
-  "getting_started.terms": "Condizioni del servizio",
   "hashtag.column_header.tag_mode.all": "e {additional}",
   "hashtag.column_header.tag_mode.any": "o {additional}",
   "hashtag.column_header.tag_mode.none": "senza {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Impossibile trovare qualcosa per questi termini di ricerca",
   "search_results.statuses": "Post",
   "search_results.statuses_fts_disabled": "La ricerca di post per il loro contenuto non è abilitata su questo server Mastodon.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count} {count, plural, one {risultato} other {risultati}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Apri interfaccia di moderazione per @{name}",
   "status.admin_status": "Apri questo post nell'interfaccia di moderazione",
   "status.block": "Blocca @{name}",
@@ -487,7 +492,7 @@
   "status.edited_x_times": "Modificato {count, plural, one {{count} volta} other {{count} volte}}",
   "status.embed": "Incorpora",
   "status.favourite": "Apprezzato",
-  "status.filter": "Filter this post",
+  "status.filter": "Filtra questo post",
   "status.filtered": "Filtrato",
   "status.hide": "Nascondi toot",
   "status.history.created": "{name} ha creato {date}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Mostra meno per tutti",
   "status.show_more": "Mostra di più",
   "status.show_more_all": "Mostra di più per tutti",
+  "status.show_original": "Mostra originale",
   "status.show_thread": "Mostra conversazione",
+  "status.translate": "Traduci",
+  "status.translated_from": "Tradotto da {lang}",
   "status.uncached_media_warning": "Non disponibile",
   "status.unmute_conversation": "Annulla silenzia conversazione",
   "status.unpin": "Non fissare in cima al profilo",
+  "subscribed_languages.lead": "Solo i messaggi nelle lingue selezionate appariranno nella tua home e nelle timeline dopo il cambiamento. Seleziona nessuno per ricevere messaggi in tutte le lingue.",
+  "subscribed_languages.save": "Salva modifiche",
+  "subscribed_languages.target": "Cambia le lingue di cui ricevere i post per {target}",
   "suggestions.dismiss": "Elimina suggerimento",
   "suggestions.header": "Ti potrebbe interessare…",
   "tabs_bar.federated_timeline": "Federazione",
diff --git a/app/javascript/mastodon/locales/ja.json b/app/javascript/mastodon/locales/ja.json
index 57489011b..5f7c9c53a 100644
--- a/app/javascript/mastodon/locales/ja.json
+++ b/app/javascript/mastodon/locales/ja.json
@@ -24,6 +24,7 @@
   "account.follows_you": "フォローされています",
   "account.hide_reblogs": "@{name}さんからのブーストを非表示",
   "account.joined": "{date} に登録",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "このリンクの所有権は{date}に確認されました",
   "account.locked_info": "このアカウントは承認制アカウントです。相手が承認するまでフォローは完了しません。",
   "account.media": "メディア",
@@ -204,19 +205,19 @@
   "filter_modal.added.context_mismatch_explanation": "This filter category does not apply to the context in which you have accessed this post. If you want the post to be filtered in this context too, you will have to edit the filter.",
   "filter_modal.added.context_mismatch_title": "Context mismatch!",
   "filter_modal.added.expired_explanation": "This filter category has expired, you will need to change the expiration date for it to apply.",
-  "filter_modal.added.expired_title": "Expired filter!",
-  "filter_modal.added.review_and_configure": "To review and further configure this filter category, go to the {settings_link}.",
-  "filter_modal.added.review_and_configure_title": "Filter settings",
-  "filter_modal.added.settings_link": "settings page",
+  "filter_modal.added.expired_title": "フィルターの有効期限が切れています!",
+  "filter_modal.added.review_and_configure": "このフィルターカテゴリーを確認して設定するには、{settings_link}に移動します。",
+  "filter_modal.added.review_and_configure_title": "フィルター設定",
+  "filter_modal.added.settings_link": "設定",
   "filter_modal.added.short_explanation": "This post has been added to the following filter category: {title}.",
   "filter_modal.added.title": "Filter added!",
   "filter_modal.select_filter.context_mismatch": "does not apply to this context",
-  "filter_modal.select_filter.expired": "expired",
-  "filter_modal.select_filter.prompt_new": "New category: {name}",
-  "filter_modal.select_filter.search": "Search or create",
-  "filter_modal.select_filter.subtitle": "Use an existing category or create a new one",
-  "filter_modal.select_filter.title": "Filter this post",
-  "filter_modal.title.status": "Filter a post",
+  "filter_modal.select_filter.expired": "期限切れ",
+  "filter_modal.select_filter.prompt_new": "新しいカテゴリー: {name}",
+  "filter_modal.select_filter.search": "検索または新規作成",
+  "filter_modal.select_filter.subtitle": "既存のカテゴリーを使用するか新規作成します",
+  "filter_modal.select_filter.title": "この投稿をフィルターする",
+  "filter_modal.title.status": "投稿をフィルターする",
   "follow_recommendations.done": "完了",
   "follow_recommendations.heading": "投稿を見たい人をフォローしてください!ここにおすすめがあります。",
   "follow_recommendations.lead": "あなたがフォローしている人の投稿は、ホームフィードに時系列で表示されます。いつでも簡単に解除できるので、気軽にフォローしてみてください!",
@@ -230,8 +231,8 @@
   "getting_started.heading": "スタート",
   "getting_started.invite": "招待",
   "getting_started.open_source_notice": "Mastodonはオープンソースソフトウェアです。誰でもGitHub ({github}) から開発に参加したり、問題を報告したりできます。",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "アカウント設定",
-  "getting_started.terms": "プライバシーポリシー",
   "hashtag.column_header.tag_mode.all": "と{additional}",
   "hashtag.column_header.tag_mode.any": "か{additional}",
   "hashtag.column_header.tag_mode.none": "({additional} を除く)",
@@ -476,7 +477,11 @@
   "search_results.nothing_found": "この検索条件では何も見つかりませんでした",
   "search_results.statuses": "投稿",
   "search_results.statuses_fts_disabled": "このサーバーでは投稿本文の検索は利用できません。",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number}件の結果",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "@{name}さんのモデレーション画面を開く",
   "status.admin_status": "この投稿をモデレーション画面で開く",
   "status.block": "@{name}さんをブロック",
@@ -492,7 +497,7 @@
   "status.edited_x_times": "{count}回編集",
   "status.embed": "埋め込み",
   "status.favourite": "お気に入り",
-  "status.filter": "Filter this post",
+  "status.filter": "この投稿をフィルターする",
   "status.filtered": "フィルターされました",
   "status.hide": "トゥートを非表示",
   "status.history.created": "{name}さんが{date}に作成",
@@ -523,10 +528,16 @@
   "status.show_less_all": "全て隠す",
   "status.show_more": "もっと見る",
   "status.show_more_all": "全て見る",
+  "status.show_original": "原文を表示",
   "status.show_thread": "スレッドを表示",
+  "status.translate": "翻訳",
+  "status.translated_from": "{lang}からの翻訳",
   "status.uncached_media_warning": "利用できません",
   "status.unmute_conversation": "会話のミュートを解除",
   "status.unpin": "プロフィールへの固定を解除",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "変更を保存",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "隠す",
   "suggestions.header": "興味あるかもしれません…",
   "tabs_bar.federated_timeline": "連合",
diff --git a/app/javascript/mastodon/locales/ka.json b/app/javascript/mastodon/locales/ka.json
index c6c72b6ce..941c2e832 100644
--- a/app/javascript/mastodon/locales/ka.json
+++ b/app/javascript/mastodon/locales/ka.json
@@ -24,6 +24,7 @@
   "account.follows_you": "მოგყვებათ",
   "account.hide_reblogs": "დაიმალოს ბუსტები @{name}-სგან",
   "account.joined": "Joined {date}",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.",
   "account.media": "მედია",
@@ -226,8 +227,8 @@
   "getting_started.heading": "დაწყება",
   "getting_started.invite": "ხალხის მოწვევა",
   "getting_started.open_source_notice": "მასტოდონი ღია პროგრამაა. შეგიძლიათ შეუწყოთ ხელი ან შექმნათ პრობემის რეპორტი {github}-ზე.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "უსაფრთხოება",
-  "getting_started.terms": "მომსახურების პირობები",
   "hashtag.column_header.tag_mode.all": "and {additional}",
   "hashtag.column_header.tag_mode.any": "or {additional}",
   "hashtag.column_header.tag_mode.none": "without {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Could not find anything for these search terms",
   "search_results.statuses": "ტუტები",
   "search_results.statuses_fts_disabled": "Searching toots by their content is not enabled on this Mastodon server.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {result} other {results}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Open moderation interface for @{name}",
   "status.admin_status": "Open this status in the moderation interface",
   "status.block": "დაბლოკე @{name}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "აჩვენე ნაკლები ყველაზე",
   "status.show_more": "აჩვენე მეტი",
   "status.show_more_all": "აჩვენე მეტი ყველაზე",
+  "status.show_original": "Show original",
   "status.show_thread": "Show thread",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "Not available",
   "status.unmute_conversation": "საუბარზე გაჩუმების მოშორება",
   "status.unpin": "პროფილიდან პინის მოშორება",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "Dismiss suggestion",
   "suggestions.header": "You might be interested in…",
   "tabs_bar.federated_timeline": "ფედერალური",
diff --git a/app/javascript/mastodon/locales/kab.json b/app/javascript/mastodon/locales/kab.json
index 035ec7c84..11603156c 100644
--- a/app/javascript/mastodon/locales/kab.json
+++ b/app/javascript/mastodon/locales/kab.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Yeṭṭafaṛ-ik",
   "account.hide_reblogs": "Ffer ayen i ibeṭṭu @{name}",
   "account.joined": "Yerna-d {date}",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "Taɣara n useɣwen-a tettwasenqed ass n {date}",
   "account.locked_info": "Amiḍan-agi uslig isekweṛ. D bab-is kan i izemren ad yeǧǧ, s ufus-is, win ara t-iḍefṛen.",
   "account.media": "Amidya",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Bdu",
   "getting_started.invite": "Snebgi-d imdanen",
   "getting_started.open_source_notice": "Maṣṭudun d aseɣzan s uɣbalu yeldin. Tzemreḍ ad tɛiwneḍ neɣ ad temmleḍ uguren deg GitHub {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Iɣewwaṛen n umiḍan",
-  "getting_started.terms": "Tiwetlin n useqdec",
   "hashtag.column_header.tag_mode.all": "d {additional}",
   "hashtag.column_header.tag_mode.any": "neɣ {additional}",
   "hashtag.column_header.tag_mode.none": "war {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Could not find anything for these search terms",
   "search_results.statuses": "Tibeṛṛaniyin",
   "search_results.statuses_fts_disabled": "Anadi ɣef tjewwiqin s ugbur-nsent ur yermid ara deg uqeddac-agi n Maṣṭudun.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {n ugemmuḍ} other {n yigemmuḍen}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Open moderation interface for @{name}",
   "status.admin_status": "Open this status in the moderation interface",
   "status.block": "Seḥbes @{name}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Semẓi akk tisuffγin",
   "status.show_more": "Ssken-d ugar",
   "status.show_more_all": "Ẓerr ugar lebda",
+  "status.show_original": "Show original",
   "status.show_thread": "Ssken-d lxiḍ",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "Ulac-it",
   "status.unmute_conversation": "Kkes asgugem n udiwenni",
   "status.unpin": "Kkes asenteḍ seg umaɣnu",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "Sefsex asumer",
   "suggestions.header": "Ahat ad tcelgeḍ deg…",
   "tabs_bar.federated_timeline": "Amatu",
diff --git a/app/javascript/mastodon/locales/kk.json b/app/javascript/mastodon/locales/kk.json
index edcf0650c..d7d63fae7 100644
--- a/app/javascript/mastodon/locales/kk.json
+++ b/app/javascript/mastodon/locales/kk.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Сізге жазылыпты",
   "account.hide_reblogs": "@{name} атты қолданушының әрекеттерін жасыру",
   "account.joined": "Joined {date}",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "Сілтеме меншігі расталған күн {date}",
   "account.locked_info": "Бұл қолданушы өзі туралы мәліметтерді жасырған. Тек жазылғандар ғана көре алады.",
   "account.media": "Медиа",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Желіде",
   "getting_started.invite": "Адам шақыру",
   "getting_started.open_source_notice": "Mastodon - ашық кодты құрылым. Түзету енгізу немесе ұсыныстарды GitHub арқылы жасаңыз {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Қауіпсіздік",
-  "getting_started.terms": "Қызмет көрсету шарттары",
   "hashtag.column_header.tag_mode.all": "және {additional}",
   "hashtag.column_header.tag_mode.any": "немесе {additional}",
   "hashtag.column_header.tag_mode.none": "{additional} болмай",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Could not find anything for these search terms",
   "search_results.statuses": "Жазбалар",
   "search_results.statuses_fts_disabled": "Mastodon серверінде постты толық мәтінмен іздей алмайсыз.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {нәтиже} other {нәтиже}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "@{name} үшін модерация интерфейсін аш",
   "status.admin_status": "Бұл жазбаны модерация интерфейсінде аш",
   "status.block": "Бұғаттау @{name}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Бәрін аздап көрсет",
   "status.show_more": "Толығырақ",
   "status.show_more_all": "Бәрін толығымен",
+  "status.show_original": "Show original",
   "status.show_thread": "Желіні көрсет",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "Қолжетімді емес",
   "status.unmute_conversation": "Пікірталасты үнсіз қылмау",
   "status.unpin": "Профильден алып тастау",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "Өткізіп жіберу",
   "suggestions.header": "Қызығуыңыз мүмкін…",
   "tabs_bar.federated_timeline": "Жаһандық",
diff --git a/app/javascript/mastodon/locales/kn.json b/app/javascript/mastodon/locales/kn.json
index 3d2e0a68d..c91aac867 100644
--- a/app/javascript/mastodon/locales/kn.json
+++ b/app/javascript/mastodon/locales/kn.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Follows you",
   "account.hide_reblogs": "Hide boosts from @{name}",
   "account.joined": "Joined {date}",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.",
   "account.media": "Media",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Getting started",
   "getting_started.invite": "Invite people",
   "getting_started.open_source_notice": "Mastodon is open source software. You can contribute or report issues on GitHub at {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Security",
-  "getting_started.terms": "Terms of service",
   "hashtag.column_header.tag_mode.all": "and {additional}",
   "hashtag.column_header.tag_mode.any": "or {additional}",
   "hashtag.column_header.tag_mode.none": "without {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Could not find anything for these search terms",
   "search_results.statuses": "Toots",
   "search_results.statuses_fts_disabled": "Searching toots by their content is not enabled on this Mastodon server.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {result} other {results}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Open moderation interface for @{name}",
   "status.admin_status": "Open this status in the moderation interface",
   "status.block": "Block @{name}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Show less for all",
   "status.show_more": "Show more",
   "status.show_more_all": "Show more for all",
+  "status.show_original": "Show original",
   "status.show_thread": "Show thread",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "Not available",
   "status.unmute_conversation": "Unmute conversation",
   "status.unpin": "Unpin from profile",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "Dismiss suggestion",
   "suggestions.header": "You might be interested in…",
   "tabs_bar.federated_timeline": "Federated",
diff --git a/app/javascript/mastodon/locales/ko.json b/app/javascript/mastodon/locales/ko.json
index e5dfc7689..4910b9a88 100644
--- a/app/javascript/mastodon/locales/ko.json
+++ b/app/javascript/mastodon/locales/ko.json
@@ -24,6 +24,7 @@
   "account.follows_you": "날 팔로우합니다",
   "account.hide_reblogs": "@{name}의 부스트를 숨기기",
   "account.joined": "{date}에 가입함",
+  "account.languages": "구독한 언어 변경",
   "account.link_verified_on": "{date}에 이 링크의 소유권이 확인 됨",
   "account.locked_info": "이 계정의 프라이버시 설정은 잠금으로 설정되어 있습니다. 계정 소유자가 수동으로 팔로워를 승인합니다.",
   "account.media": "미디어",
@@ -197,22 +198,22 @@
   "explore.trending_links": "소식",
   "explore.trending_statuses": "게시물",
   "explore.trending_tags": "해시태그",
-  "filter_modal.added.context_mismatch_explanation": "This filter category does not apply to the context in which you have accessed this post. If you want the post to be filtered in this context too, you will have to edit the filter.",
-  "filter_modal.added.context_mismatch_title": "Context mismatch!",
-  "filter_modal.added.expired_explanation": "This filter category has expired, you will need to change the expiration date for it to apply.",
-  "filter_modal.added.expired_title": "Expired filter!",
-  "filter_modal.added.review_and_configure": "To review and further configure this filter category, go to the {settings_link}.",
-  "filter_modal.added.review_and_configure_title": "Filter settings",
-  "filter_modal.added.settings_link": "settings page",
-  "filter_modal.added.short_explanation": "This post has been added to the following filter category: {title}.",
-  "filter_modal.added.title": "Filter added!",
-  "filter_modal.select_filter.context_mismatch": "does not apply to this context",
-  "filter_modal.select_filter.expired": "expired",
-  "filter_modal.select_filter.prompt_new": "New category: {name}",
-  "filter_modal.select_filter.search": "Search or create",
-  "filter_modal.select_filter.subtitle": "Use an existing category or create a new one",
-  "filter_modal.select_filter.title": "Filter this post",
-  "filter_modal.title.status": "Filter a post",
+  "filter_modal.added.context_mismatch_explanation": "이 필터 카테고리는 당신이 이 게시물에 접근한 문맥에 적용되지 않습니다. 만약 이 문맥에서도 필터되길 원한다면, 필터를 수정해야 합니다.",
+  "filter_modal.added.context_mismatch_title": "문맥 불일치!",
+  "filter_modal.added.expired_explanation": "이 필터 카테고리는 만료되었습니다, 적용하려면 만료 일자를 변경할 필요가 있습니다.",
+  "filter_modal.added.expired_title": "만료된 필터!",
+  "filter_modal.added.review_and_configure": "이 필터 카테고리를 검토하거나 나중에 더 설정하려면, {settings_link}로 가십시오.",
+  "filter_modal.added.review_and_configure_title": "필터 설정",
+  "filter_modal.added.settings_link": "설정 페이지",
+  "filter_modal.added.short_explanation": "이 게시물을 다음 필터 카테고리에 추가되었습니다: {title}.",
+  "filter_modal.added.title": "필터 추가됨!",
+  "filter_modal.select_filter.context_mismatch": "이 문맥에 적용되지 않습니다",
+  "filter_modal.select_filter.expired": "만료됨",
+  "filter_modal.select_filter.prompt_new": "새 카테고리: {name}",
+  "filter_modal.select_filter.search": "검색 또는 생성",
+  "filter_modal.select_filter.subtitle": "기존의 카테고리를 사용하거나 새로 하나를 만듧니다",
+  "filter_modal.select_filter.title": "이 게시물을 필터",
+  "filter_modal.title.status": "게시물 필터",
   "follow_recommendations.done": "완료",
   "follow_recommendations.heading": "게시물을 받아 볼 사람들을 팔로우 하세요! 여기 몇몇의 추천이 있습니다.",
   "follow_recommendations.lead": "당신이 팔로우 하는 사람들의 게시물이 시간순으로 정렬되어 당신의 홈 피드에 표시될 것입니다. 실수를 두려워 하지 마세요, 언제든지 쉽게 팔로우 취소를 할 수 있습니다!",
@@ -226,8 +227,8 @@
   "getting_started.heading": "시작",
   "getting_started.invite": "초대",
   "getting_started.open_source_notice": "Mastodon은 오픈 소스 소프트웨어입니다. 누구나 GitHub({github})에서 개발에 참여하거나, 문제를 보고할 수 있습니다.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "계정 설정",
-  "getting_started.terms": "이용 약관",
   "hashtag.column_header.tag_mode.all": "그리고 {additional}",
   "hashtag.column_header.tag_mode.any": "또는 {additional}",
   "hashtag.column_header.tag_mode.none": "{additional}를 제외하고",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "검색어에 대한 결과를 찾을 수 없습니다",
   "search_results.statuses": "게시물",
   "search_results.statuses_fts_disabled": "이 마스토돈 서버에선 게시물의 내용을 통한 검색이 활성화 되어 있지 않습니다.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number}건의 결과",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "@{name}에 대한 중재 화면 열기",
   "status.admin_status": "중재 화면에서 이 게시물 열기",
   "status.block": "@{name} 차단",
@@ -487,7 +492,7 @@
   "status.edited_x_times": "{count}번 수정됨",
   "status.embed": "공유하기",
   "status.favourite": "좋아요",
-  "status.filter": "Filter this post",
+  "status.filter": "이 게시물을 필터",
   "status.filtered": "필터로 걸러짐",
   "status.hide": "툿 숨기기",
   "status.history.created": "{name} 님이 {date}에 생성함",
@@ -518,10 +523,16 @@
   "status.show_less_all": "모두 접기",
   "status.show_more": "더 보기",
   "status.show_more_all": "모두 펼치기",
+  "status.show_original": "원본 보기",
   "status.show_thread": "글타래 보기",
+  "status.translate": "번역",
+  "status.translated_from": "{lang}에서 번역됨",
   "status.uncached_media_warning": "사용할 수 없음",
   "status.unmute_conversation": "이 대화의 뮤트 해제하기",
   "status.unpin": "고정 해제",
+  "subscribed_languages.lead": "변경 후에는 선택한 언어들로 작성된 게시물들만 홈 타임라인과 리스트 타임라인에 나타나게 됩니다. 아무 것도 선택하지 않으면 모든 언어로 작성된 게시물을 받아봅니다.",
+  "subscribed_languages.save": "변경사항 저장",
+  "subscribed_languages.target": "{target}에 대한 구독 언어 변경",
   "suggestions.dismiss": "추천 지우기",
   "suggestions.header": "여기에 관심이 있을 것 같습니다…",
   "tabs_bar.federated_timeline": "연합",
diff --git a/app/javascript/mastodon/locales/ku.json b/app/javascript/mastodon/locales/ku.json
index 27033efbf..19d960a0a 100644
--- a/app/javascript/mastodon/locales/ku.json
+++ b/app/javascript/mastodon/locales/ku.json
@@ -24,8 +24,9 @@
   "account.follows_you": "Te dişopîne",
   "account.hide_reblogs": "Bilindkirinên ji @{name} veşêre",
   "account.joined": "Di {date} de tevlî bû",
+  "account.languages": "Zimanên beşdarbûyî biguherîne",
   "account.link_verified_on": "Xwedaniya li vê girêdanê di {date} de hatiye kontrolkirin",
-  "account.locked_info": "Rewşa vê ajimêrê wek kilît kirî hatiye saz kirin. Xwedî yê ajimêrê, kesên vê bişopîne bi dest vekolin dike.",
+  "account.locked_info": "Rewşa vê ajimêrê wek kilîtkirî hatiye sazkirin. Xwediyê ajimêrê, bi destan dinirxîne şopandinê dinirxîne.",
   "account.media": "Medya",
   "account.mention": "Qal @{name} bike",
   "account.moved_to": "{name} hate livandin bo:",
@@ -197,22 +198,22 @@
   "explore.trending_links": "Nûçe",
   "explore.trending_statuses": "Şandî",
   "explore.trending_tags": "Hashtag",
-  "filter_modal.added.context_mismatch_explanation": "This filter category does not apply to the context in which you have accessed this post. If you want the post to be filtered in this context too, you will have to edit the filter.",
-  "filter_modal.added.context_mismatch_title": "Context mismatch!",
-  "filter_modal.added.expired_explanation": "This filter category has expired, you will need to change the expiration date for it to apply.",
-  "filter_modal.added.expired_title": "Expired filter!",
-  "filter_modal.added.review_and_configure": "To review and further configure this filter category, go to the {settings_link}.",
-  "filter_modal.added.review_and_configure_title": "Filter settings",
-  "filter_modal.added.settings_link": "settings page",
-  "filter_modal.added.short_explanation": "This post has been added to the following filter category: {title}.",
-  "filter_modal.added.title": "Filter added!",
-  "filter_modal.select_filter.context_mismatch": "does not apply to this context",
-  "filter_modal.select_filter.expired": "expired",
-  "filter_modal.select_filter.prompt_new": "New category: {name}",
-  "filter_modal.select_filter.search": "Search or create",
-  "filter_modal.select_filter.subtitle": "Use an existing category or create a new one",
-  "filter_modal.select_filter.title": "Filter this post",
-  "filter_modal.title.status": "Filter a post",
+  "filter_modal.added.context_mismatch_explanation": "Ev beşa parzûnê ji bo naveroka ku te tê de xwe gihandiye vê şandiyê nayê sepandin. Ku tu dixwazî şandî di vê naverokê de jî werê parzûnkirin, divê tu parzûnê biguherînî.",
+  "filter_modal.added.context_mismatch_title": "Naverok li hev nagire!",
+  "filter_modal.added.expired_explanation": "Ev beşa parzûnê qediya ye, ji bo ku tu bikaribe wê biguherîne divê tu dema qedandinê biguherînî.",
+  "filter_modal.added.expired_title": "Dema parzûnê qediya!",
+  "filter_modal.added.review_and_configure": "Ji bo nîrxandin û bêtir sazkirina vê beşa parzûnê, biçe {settings_link}.",
+  "filter_modal.added.review_and_configure_title": "Sazkariyên parzûnê",
+  "filter_modal.added.settings_link": "rûpela sazkariyan",
+  "filter_modal.added.short_explanation": "Ev şandî li beşa parzûna jêrîn hate tevlîkirin: {title}.",
+  "filter_modal.added.title": "Parzûn tevlî bû!",
+  "filter_modal.select_filter.context_mismatch": "di vê naverokê de nayê sepandin",
+  "filter_modal.select_filter.expired": "dema wê qediya",
+  "filter_modal.select_filter.prompt_new": "Beşa nû: {name}",
+  "filter_modal.select_filter.search": "Lê bigere an jî biafirîne",
+  "filter_modal.select_filter.subtitle": "Beşeke nû ya heyî bi kar bîne an jî yekî nû biafirîne",
+  "filter_modal.select_filter.title": "Vê şandiyê parzûn bike",
+  "filter_modal.title.status": "Şandiyekê parzûn bike",
   "follow_recommendations.done": "Qediya",
   "follow_recommendations.heading": "Mirovên ku tu dixwazî ji wan peyaman bibînî bişopîne! Hin pêşnîyar li vir in.",
   "follow_recommendations.lead": "Li gorî rêza kronolojîkî peyamên mirovên ku tu dişopînî dê demnameya te de xûya bike. Ji xeletiyan netirse, bi awayekî hêsan her wextî tu dikarî dev ji şopandinê berdî!",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Destpêkirin",
   "getting_started.invite": "Kesan vexwîne",
   "getting_started.open_source_notice": "Mastodon nermalava çavkaniya vekirî ye. Tu dikarî pirsgirêkan li ser GitHub-ê ragihînî di {github} de an jî dikarî tevkariyê bikî.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Sazkariyên ajimêr",
-  "getting_started.terms": "Mercên karûberan",
   "hashtag.column_header.tag_mode.all": "û {additional}",
   "hashtag.column_header.tag_mode.any": "an {additional}",
   "hashtag.column_header.tag_mode.none": "bêyî {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Ji bo van peyvên lêgerînê tiştek nehate dîtin",
   "search_results.statuses": "Şandî",
   "search_results.statuses_fts_disabled": "Di vê rajekara Mastodonê da lêgerîna şandîyên li gorî naveroka wan ne çalak e.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {encam} other {encam}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Ji bo @{name} navrûya venihêrtinê veke",
   "status.admin_status": "Vê şandîyê di navrûya venihêrtinê de veke",
   "status.block": "@{name} asteng bike",
@@ -487,7 +492,7 @@
   "status.edited_x_times": "{count, plural, one {{count} car} other {{count} car}} hate serrastkirin",
   "status.embed": "Hedimandî",
   "status.favourite": "Bijarte",
-  "status.filter": "Filter this post",
+  "status.filter": "Vê şandiyê parzûn bike",
   "status.filtered": "Parzûnkirî",
   "status.hide": "Şandiyê veşêre",
   "status.history.created": "{name} {date} afirand",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Ji bo hemîyan kêmtir nîşan bide",
   "status.show_more": "Bêtir nîşan bide",
   "status.show_more_all": "Bêtir nîşan bide bo hemûyan",
+  "status.show_original": "A resen nîşan bide",
   "status.show_thread": "Mijarê nîşan bide",
+  "status.translate": "Wergerîne",
+  "status.translated_from": "Ji {lang} hate wergerandin",
   "status.uncached_media_warning": "Tune ye",
   "status.unmute_conversation": "Axaftinê bêdeng neke",
   "status.unpin": "Şandiya derzîkirî ji profîlê rake",
+  "subscribed_languages.lead": "Tenê şandiyên bi zimanên hilbijartî wê di rojev û demnameya te de wê xuya bibe û piştî guhertinê. Ji bo wergirtina şandiyan di hemû zimanan de ne yek hilbijêre.",
+  "subscribed_languages.save": "Guhertinan tomar bike",
+  "subscribed_languages.target": "Zimanên beşdarbûyî biguherîne ji bo {target}",
   "suggestions.dismiss": "Pêşniyarê paşguh bike",
   "suggestions.header": "Dibe ku bala te bikşîne…",
   "tabs_bar.federated_timeline": "Giştî",
diff --git a/app/javascript/mastodon/locales/kw.json b/app/javascript/mastodon/locales/kw.json
index f6a85a932..b63008eaa 100644
--- a/app/javascript/mastodon/locales/kw.json
+++ b/app/javascript/mastodon/locales/kw.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Y'th hol",
   "account.hide_reblogs": "Kudha kenerthow a @{name}",
   "account.joined": "Joined {date}",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "Perghenogeth an kolm ma a veu checkys dhe {date}",
   "account.locked_info": "Studh privetter an akont ma yw alhwedhys. An perghen a wra dasweles dre leuv piw a yll aga holya.",
   "account.media": "Myski",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Dhe dhalleth",
   "getting_started.invite": "Gelwel tus",
   "getting_started.open_source_notice": "Mastodon yw medhelweyth a fenten ygor. Hwi a yll kevri po reportya kudynnow dre GitHub dhe {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Dewisyow akont",
-  "getting_started.terms": "Ambosow an gonis",
   "hashtag.column_header.tag_mode.all": "ha(g) {additional}",
   "hashtag.column_header.tag_mode.any": "po {additional}",
   "hashtag.column_header.tag_mode.none": "heb {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Could not find anything for these search terms",
   "search_results.statuses": "Postow",
   "search_results.statuses_fts_disabled": "Nyns yw hwilas postow der aga dalgh gweythresys y'n leuren Mastodon ma.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {sewyans} other {sewyans}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Ygeri ynterfas koswa rag @{name}",
   "status.admin_status": "Ygeri an post ma y'n ynterfas koswa",
   "status.block": "Lettya @{name}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Diskwedhes le rag puptra",
   "status.show_more": "Diskwedhes moy",
   "status.show_more_all": "Diskwedhes moy rag puptra",
+  "status.show_original": "Show original",
   "status.show_thread": "Diskwedhes neusen",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "Ankavadow",
   "status.unmute_conversation": "Antawhe kesklapp",
   "status.unpin": "Anfastya a brofil",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "Gordhyllo profyans",
   "suggestions.header": "Martesen y fydh dhe les dhywgh…",
   "tabs_bar.federated_timeline": "Keffrysys",
diff --git a/app/javascript/mastodon/locales/lt.json b/app/javascript/mastodon/locales/lt.json
index 4e238273e..2c8bf82a5 100644
--- a/app/javascript/mastodon/locales/lt.json
+++ b/app/javascript/mastodon/locales/lt.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Follows you",
   "account.hide_reblogs": "Hide boosts from @{name}",
   "account.joined": "Joined {date}",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.",
   "account.media": "Media",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Getting started",
   "getting_started.invite": "Invite people",
   "getting_started.open_source_notice": "Mastodon is open source software. You can contribute or report issues on GitHub at {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Security",
-  "getting_started.terms": "Terms of service",
   "hashtag.column_header.tag_mode.all": "and {additional}",
   "hashtag.column_header.tag_mode.any": "or {additional}",
   "hashtag.column_header.tag_mode.none": "without {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Could not find anything for these search terms",
   "search_results.statuses": "Toots",
   "search_results.statuses_fts_disabled": "Searching toots by their content is not enabled on this Mastodon server.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {result} other {results}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Open moderation interface for @{name}",
   "status.admin_status": "Open this status in the moderation interface",
   "status.block": "Block @{name}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Show less for all",
   "status.show_more": "Show more",
   "status.show_more_all": "Show more for all",
+  "status.show_original": "Show original",
   "status.show_thread": "Show thread",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "Not available",
   "status.unmute_conversation": "Unmute conversation",
   "status.unpin": "Unpin from profile",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "Dismiss suggestion",
   "suggestions.header": "You might be interested in…",
   "tabs_bar.federated_timeline": "Federated",
diff --git a/app/javascript/mastodon/locales/lv.json b/app/javascript/mastodon/locales/lv.json
index 1912dd7db..d2fe1b745 100644
--- a/app/javascript/mastodon/locales/lv.json
+++ b/app/javascript/mastodon/locales/lv.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Seko tev",
   "account.hide_reblogs": "Paslēpt paceltos ierakstus no lietotāja @{name}",
   "account.joined": "Pievienojās {date}",
+  "account.languages": "Mainīt abonētās valodas",
   "account.link_verified_on": "Šīs saites piederība ir pārbaudīta {date}",
   "account.locked_info": "Šī konta privātuma statuss ir slēgts. Īpašnieks izskatīs, kurš viņam drīkst sekot.",
   "account.media": "Multivide",
@@ -197,22 +198,22 @@
   "explore.trending_links": "Jaunumi",
   "explore.trending_statuses": "Ziņas",
   "explore.trending_tags": "Tēmturi",
-  "filter_modal.added.context_mismatch_explanation": "This filter category does not apply to the context in which you have accessed this post. If you want the post to be filtered in this context too, you will have to edit the filter.",
-  "filter_modal.added.context_mismatch_title": "Context mismatch!",
-  "filter_modal.added.expired_explanation": "This filter category has expired, you will need to change the expiration date for it to apply.",
-  "filter_modal.added.expired_title": "Expired filter!",
-  "filter_modal.added.review_and_configure": "To review and further configure this filter category, go to the {settings_link}.",
-  "filter_modal.added.review_and_configure_title": "Filter settings",
-  "filter_modal.added.settings_link": "settings page",
-  "filter_modal.added.short_explanation": "This post has been added to the following filter category: {title}.",
-  "filter_modal.added.title": "Filter added!",
-  "filter_modal.select_filter.context_mismatch": "does not apply to this context",
-  "filter_modal.select_filter.expired": "expired",
-  "filter_modal.select_filter.prompt_new": "New category: {name}",
-  "filter_modal.select_filter.search": "Search or create",
-  "filter_modal.select_filter.subtitle": "Use an existing category or create a new one",
-  "filter_modal.select_filter.title": "Filter this post",
-  "filter_modal.title.status": "Filter a post",
+  "filter_modal.added.context_mismatch_explanation": "Šī filtra kategorija neattiecas uz kontekstu, kurā esi piekļuvis šai ziņai. Ja vēlies, lai ziņa tiktu filtrēta arī šajā kontekstā, tev būs jārediģē filtrs.",
+  "filter_modal.added.context_mismatch_title": "Konteksta neatbilstība!",
+  "filter_modal.added.expired_explanation": "Šai filtra kategorijai ir beidzies derīguma termiņš. Lai to lietotu, tev būs jāmaina derīguma termiņš.",
+  "filter_modal.added.expired_title": "Filtrs beidzies!",
+  "filter_modal.added.review_and_configure": "Lai pārskatītu un tālāk konfigurētu šo filtru kategoriju, dodies uz {settings_link}.",
+  "filter_modal.added.review_and_configure_title": "Filtra iestatījumi",
+  "filter_modal.added.settings_link": "iestatījumu lapa",
+  "filter_modal.added.short_explanation": "Šī ziņa ir pievienota šai filtra kategorijai: {title}.",
+  "filter_modal.added.title": "Filtrs pievienots!",
+  "filter_modal.select_filter.context_mismatch": "neattiecas uz šo kontekstu",
+  "filter_modal.select_filter.expired": "beidzies",
+  "filter_modal.select_filter.prompt_new": "Jauna kategorija: {name}",
+  "filter_modal.select_filter.search": "Meklē vai izveido",
+  "filter_modal.select_filter.subtitle": "Izmanto esošu kategoriju vai izveido jaunu",
+  "filter_modal.select_filter.title": "Filtrēt šo ziņu",
+  "filter_modal.title.status": "Filtrēt ziņu",
   "follow_recommendations.done": "Izpildīts",
   "follow_recommendations.heading": "Seko cilvēkiem, no kuriem vēlies redzēt ziņas! Šeit ir daži ieteikumi.",
   "follow_recommendations.lead": "Ziņas no cilvēkiem, kuriem seko, mājas plūsmā tiks parādītas hronoloģiskā secībā. Nebaidies kļūdīties, tu tikpat viegli vari pārtraukt sekot cilvēkiem jebkurā laikā!",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Darba sākšana",
   "getting_started.invite": "Uzaicini cilvēkus",
   "getting_started.open_source_notice": "Mastodon ir atvērtā koda programmatūra. Tu vari dot savu ieguldījumu vai arī ziņot par problēmām {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Konta iestatījumi",
-  "getting_started.terms": "Pakalpojuma noteikumi",
   "hashtag.column_header.tag_mode.all": "un {additional}",
   "hashtag.column_header.tag_mode.any": "vai {additional}",
   "hashtag.column_header.tag_mode.none": "bez {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Nevarēja atrast neko šiem meklēšanas vienumiem",
   "search_results.statuses": "Ziņas",
   "search_results.statuses_fts_disabled": "Šajā Mastodon serverī nav iespējota ziņu meklēšana pēc to satura.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {rezultāts} other {rezultāti}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Atvērt @{name} moderēšanas saskarni",
   "status.admin_status": "Atvērt šo ziņu moderācijas saskarnē",
   "status.block": "Bloķēt @{name}",
@@ -487,7 +492,7 @@
   "status.edited_x_times": "Rediģēts {count, plural, one {{count} reize} other {{count} reizes}}",
   "status.embed": "Iestrādāt",
   "status.favourite": "Iecienītā",
-  "status.filter": "Filter this post",
+  "status.filter": "Filtrē šo ziņu",
   "status.filtered": "Filtrēts",
   "status.hide": "Slēpt",
   "status.history.created": "{name} izveidots {date}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Rādīt mazāk visiem",
   "status.show_more": "Rādīt vairāk",
   "status.show_more_all": "Rādīt vairāk visiem",
+  "status.show_original": "Rādīt oriģinālu",
   "status.show_thread": "Rādīt tematu",
+  "status.translate": "Tulkot",
+  "status.translated_from": "Tulkot no {lang}",
   "status.uncached_media_warning": "Nav pieejams",
   "status.unmute_conversation": "Atvērt sarunu",
   "status.unpin": "Noņemt no profila",
+  "subscribed_languages.lead": "Pēc izmaiņu veikšanas tavā mājas lapā un saraksta laika skalās tiks rādītas tikai ziņas atlasītajās valodās. Neatlasi nevienu, lai saņemtu ziņas visās valodās.",
+  "subscribed_languages.save": "Saglabāt izmaiņas",
+  "subscribed_languages.target": "Mainīt abonētās valodas priekš {target}",
   "suggestions.dismiss": "Noraidīt ieteikumu",
   "suggestions.header": "Jūs varētu interesēt arī…",
   "tabs_bar.federated_timeline": "Federētā",
diff --git a/app/javascript/mastodon/locales/mk.json b/app/javascript/mastodon/locales/mk.json
index d782dff64..829251daa 100644
--- a/app/javascript/mastodon/locales/mk.json
+++ b/app/javascript/mastodon/locales/mk.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Те следи тебе",
   "account.hide_reblogs": "Сокриј буст од @{name}",
   "account.joined": "Joined {date}",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "Сопстевноста на овај линк беше проверен на {date}",
   "account.locked_info": "Статусот на приватност на овај корисник е сетиран како заклучен. Корисникот одлучува кој можи да го следи него.",
   "account.media": "Медија",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Започни",
   "getting_started.invite": "Покани луѓе",
   "getting_started.open_source_notice": "Мастодон е софтвер со отворен код. Можете да придонесувате или пријавувате проблеми во GitHub на {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Поставки на сметката",
-  "getting_started.terms": "Услови на користење",
   "hashtag.column_header.tag_mode.all": "и {additional}",
   "hashtag.column_header.tag_mode.any": "или {additional}",
   "hashtag.column_header.tag_mode.none": "без {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Could not find anything for these search terms",
   "search_results.statuses": "Toots",
   "search_results.statuses_fts_disabled": "Searching toots by their content is not enabled on this Mastodon server.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {result} other {results}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Open moderation interface for @{name}",
   "status.admin_status": "Open this status in the moderation interface",
   "status.block": "Block @{name}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Show less for all",
   "status.show_more": "Show more",
   "status.show_more_all": "Show more for all",
+  "status.show_original": "Show original",
   "status.show_thread": "Show thread",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "Not available",
   "status.unmute_conversation": "Unmute conversation",
   "status.unpin": "Unpin from profile",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "Dismiss suggestion",
   "suggestions.header": "You might be interested in…",
   "tabs_bar.federated_timeline": "Federated",
diff --git a/app/javascript/mastodon/locales/ml.json b/app/javascript/mastodon/locales/ml.json
index 37969475d..d8bfee5d2 100644
--- a/app/javascript/mastodon/locales/ml.json
+++ b/app/javascript/mastodon/locales/ml.json
@@ -24,6 +24,7 @@
   "account.follows_you": "നിങ്ങളെ പിന്തുടരുന്നു",
   "account.hide_reblogs": "@{name} ബൂസ്റ്റ് ചെയ്തവ മറയ്കുക",
   "account.joined": "{date} ൽ ചേർന്നു",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "ഈ ലിങ്കിന്റെ ഉടമസ്തത {date} ഇൽ ഉറപ്പാക്കിയതാണ്",
   "account.locked_info": "ഈ അംഗത്വത്തിന്റെ സ്വകാര്യതാ നിലപാട് അനുസരിച്ച് പിന്തുടരുന്നവരെ തിരഞ്ഞെടുക്കാനുള്ള വിവേചനാധികാരം ഉടമസ്ഥനിൽ നിഷിപ്തമായിരിക്കുന്നു.",
   "account.media": "മീഡിയ",
@@ -226,8 +227,8 @@
   "getting_started.heading": "തുടക്കം കുറിക്കുക",
   "getting_started.invite": "ആളുകളെ ക്ഷണിക്കുക",
   "getting_started.open_source_notice": "മാസ്റ്റഡോൺ ഒരു സ്വതന്ത്ര സോഫ്ട്‍വെയർ ആണ്. നിങ്ങൾക്ക് {github} GitHub ൽ സംഭാവന ചെയ്യുകയോ പ്രശ്നങ്ങൾ അറിയിക്കുകയോ ചെയ്യാം.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "അംഗത്വ ക്രമീകരണങ്ങൾ",
-  "getting_started.terms": "സേവന വ്യവസ്ഥകൾ",
   "hashtag.column_header.tag_mode.all": "{additional} ഉം കൂടെ",
   "hashtag.column_header.tag_mode.any": "അല്ലെങ്കിൽ {additional}",
   "hashtag.column_header.tag_mode.none": "{additional} ഇല്ലാതെ",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Could not find anything for these search terms",
   "search_results.statuses": "ടൂട്ടുകൾ",
   "search_results.statuses_fts_disabled": "Searching toots by their content is not enabled on this Mastodon server.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {result} other {results}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Open moderation interface for @{name}",
   "status.admin_status": "Open this status in the moderation interface",
   "status.block": "@{name} -നെ തടയുക",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Show less for all",
   "status.show_more": "കൂടുതകൽ കാണിക്കുക",
   "status.show_more_all": "എല്ലാവർക്കുമായി കൂടുതൽ കാണിക്കുക",
+  "status.show_original": "Show original",
   "status.show_thread": "ത്രെഡ് കാണിക്കുക",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "ലഭ്യമല്ല",
   "status.unmute_conversation": "Unmute conversation",
   "status.unpin": "Unpin from profile",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "നിർദ്ദേശം ഒഴിവാക്കൂ",
   "suggestions.header": "നിങ്ങൾക്ക് താൽപ്പര്യമുണ്ടാകാം…",
   "tabs_bar.federated_timeline": "സംയുക്തമായ",
diff --git a/app/javascript/mastodon/locales/mr.json b/app/javascript/mastodon/locales/mr.json
index 09eaea3f9..4e44813b2 100644
--- a/app/javascript/mastodon/locales/mr.json
+++ b/app/javascript/mastodon/locales/mr.json
@@ -24,6 +24,7 @@
   "account.follows_you": "तुमचा अनुयायी आहे",
   "account.hide_reblogs": "@{name} पासून सर्व बूस्ट लपवा",
   "account.joined": "Joined {date}",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.",
   "account.media": "दृक्‌‌श्राव्य मजकूर",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Getting started",
   "getting_started.invite": "Invite people",
   "getting_started.open_source_notice": "Mastodon is open source software. You can contribute or report issues on GitHub at {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Security",
-  "getting_started.terms": "Terms of service",
   "hashtag.column_header.tag_mode.all": "and {additional}",
   "hashtag.column_header.tag_mode.any": "or {additional}",
   "hashtag.column_header.tag_mode.none": "without {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Could not find anything for these search terms",
   "search_results.statuses": "Toots",
   "search_results.statuses_fts_disabled": "Searching toots by their content is not enabled on this Mastodon server.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {result} other {results}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Open moderation interface for @{name}",
   "status.admin_status": "Open this status in the moderation interface",
   "status.block": "Block @{name}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Show less for all",
   "status.show_more": "Show more",
   "status.show_more_all": "Show more for all",
+  "status.show_original": "Show original",
   "status.show_thread": "Show thread",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "Not available",
   "status.unmute_conversation": "Unmute conversation",
   "status.unpin": "Unpin from profile",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "Dismiss suggestion",
   "suggestions.header": "You might be interested in…",
   "tabs_bar.federated_timeline": "Federated",
diff --git a/app/javascript/mastodon/locales/ms.json b/app/javascript/mastodon/locales/ms.json
index 6a1302329..8457b4dc7 100644
--- a/app/javascript/mastodon/locales/ms.json
+++ b/app/javascript/mastodon/locales/ms.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Mengikuti anda",
   "account.hide_reblogs": "Sembunyikan galakan daripada @{name}",
   "account.joined": "Sertai pada {date}",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "Pemilikan pautan ini telah disemak pada {date}",
   "account.locked_info": "Status privasi akaun ini dikunci. Pemiliknya menyaring sendiri siapa yang boleh mengikutinya.",
   "account.media": "Media",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Mari bermula",
   "getting_started.invite": "Undang orang",
   "getting_started.open_source_notice": "Mastodon itu perisian bersumber terbuka. Anda boleh menyumbang atau melaporkan masalah di GitHub menerusi {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Tetapan akaun",
-  "getting_started.terms": "Terma perkhidmatan",
   "hashtag.column_header.tag_mode.all": "dan {additional}",
   "hashtag.column_header.tag_mode.any": "atau {additional}",
   "hashtag.column_header.tag_mode.none": "tanpa {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Could not find anything for these search terms",
   "search_results.statuses": "Hantaran",
   "search_results.statuses_fts_disabled": "Menggelintar hantaran menggunakan kandungannya tidak didayakan di pelayan Mastodon ini.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, other {hasil}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Buka antara muka penyederhanaan untuk @{name}",
   "status.admin_status": "Buka hantaran ini dalam antara muka penyederhanaan",
   "status.block": "Sekat @{name}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Tunjukkan kurang untuk semua",
   "status.show_more": "Tunjukkan lebih",
   "status.show_more_all": "Tunjukkan lebih untuk semua",
+  "status.show_original": "Show original",
   "status.show_thread": "Tunjuk bebenang",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "Tidak tersedia",
   "status.unmute_conversation": "Nyahbisukan perbualan",
   "status.unpin": "Nyahsemat daripada profil",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "Batalkan cadangan",
   "suggestions.header": "Anda mungkin berminat dengan…",
   "tabs_bar.federated_timeline": "Bersekutu",
diff --git a/app/javascript/mastodon/locales/nl.json b/app/javascript/mastodon/locales/nl.json
index b48ebbc16..db8c6957a 100644
--- a/app/javascript/mastodon/locales/nl.json
+++ b/app/javascript/mastodon/locales/nl.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Volgt jou",
   "account.hide_reblogs": "Boosts van @{name} verbergen",
   "account.joined": "Geregistreerd op {date}",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "Eigendom van deze link is gecontroleerd op {date}",
   "account.locked_info": "De privacystatus van dit account is op besloten gezet. De eigenaar bepaalt handmatig wie diegene kan volgen.",
   "account.media": "Media",
@@ -198,21 +199,21 @@
   "explore.trending_statuses": "Berichten",
   "explore.trending_tags": "Hashtags",
   "filter_modal.added.context_mismatch_explanation": "This filter category does not apply to the context in which you have accessed this post. If you want the post to be filtered in this context too, you will have to edit the filter.",
-  "filter_modal.added.context_mismatch_title": "Context mismatch!",
+  "filter_modal.added.context_mismatch_title": "Context komt niet overeen!",
   "filter_modal.added.expired_explanation": "This filter category has expired, you will need to change the expiration date for it to apply.",
-  "filter_modal.added.expired_title": "Expired filter!",
+  "filter_modal.added.expired_title": "Filter verlopen!",
   "filter_modal.added.review_and_configure": "To review and further configure this filter category, go to the {settings_link}.",
-  "filter_modal.added.review_and_configure_title": "Filter settings",
-  "filter_modal.added.settings_link": "settings page",
-  "filter_modal.added.short_explanation": "This post has been added to the following filter category: {title}.",
-  "filter_modal.added.title": "Filter added!",
-  "filter_modal.select_filter.context_mismatch": "does not apply to this context",
-  "filter_modal.select_filter.expired": "expired",
-  "filter_modal.select_filter.prompt_new": "New category: {name}",
-  "filter_modal.select_filter.search": "Search or create",
-  "filter_modal.select_filter.subtitle": "Use an existing category or create a new one",
-  "filter_modal.select_filter.title": "Filter this post",
-  "filter_modal.title.status": "Filter a post",
+  "filter_modal.added.review_and_configure_title": "Filterinstellingen",
+  "filter_modal.added.settings_link": "instellingspagina",
+  "filter_modal.added.short_explanation": "Dit bericht is toegevoegd aan de volgende filtercategorie: {title}.",
+  "filter_modal.added.title": "Filter toegevoegd!",
+  "filter_modal.select_filter.context_mismatch": "is niet van toepassing op deze context",
+  "filter_modal.select_filter.expired": "verlopen",
+  "filter_modal.select_filter.prompt_new": "Nieuwe categorie: {name}",
+  "filter_modal.select_filter.search": "Zoeken of toevoegen",
+  "filter_modal.select_filter.subtitle": "Gebruik een bestaande categorie of maak een nieuwe aan",
+  "filter_modal.select_filter.title": "Dit bericht filteren",
+  "filter_modal.title.status": "Een bericht filteren",
   "follow_recommendations.done": "Klaar",
   "follow_recommendations.heading": "Volg mensen waarvan je graag berichten wil zien! Hier zijn enkele aanbevelingen.",
   "follow_recommendations.lead": "Berichten van mensen die je volgt zullen in chronologische volgorde onder start verschijnen. Wees niet bang om hierin fouten te maken, want je kunt mensen op elk moment net zo eenvoudig ontvolgen!",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Aan de slag",
   "getting_started.invite": "Mensen uitnodigen",
   "getting_started.open_source_notice": "Mastodon is vrije software. Je kunt bijdragen of problemen melden op GitHub via {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Accountinstellingen",
-  "getting_started.terms": "Voorwaarden",
   "hashtag.column_header.tag_mode.all": "en {additional}",
   "hashtag.column_header.tag_mode.any": "of {additional}",
   "hashtag.column_header.tag_mode.none": "zonder {additional}",
@@ -238,7 +239,7 @@
   "hashtag.column_settings.tag_mode.none": "Geen van deze",
   "hashtag.column_settings.tag_toggle": "Additionele tags aan deze kolom toevoegen",
   "hashtag.follow": "Hashtag volgen",
-  "hashtag.total_volume": "Total volume in the last {days, plural, one {day} other {{days} days}}",
+  "hashtag.total_volume": "Totale hoeveelheid in {days, plural, one {het afgelopen etmaal} other {de afgelopen {days} dagen}}",
   "hashtag.unfollow": "Hashtag ontvolgen",
   "home.column_settings.basic": "Algemeen",
   "home.column_settings.show_reblogs": "Boosts tonen",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Deze zoektermen leveren geen resultaat op",
   "search_results.statuses": "Berichten",
   "search_results.statuses_fts_disabled": "Het zoeken in berichten is op deze Mastodon-server niet ingeschakeld.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {resultaat} other {resultaten}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Moderatie-omgeving van @{name} openen",
   "status.admin_status": "Dit bericht in de moderatie-omgeving openen",
   "status.block": "@{name} blokkeren",
@@ -487,7 +492,7 @@
   "status.edited_x_times": "{count, plural, one {{count} keer} other {{count} keer}} bewerkt",
   "status.embed": "Insluiten",
   "status.favourite": "Favoriet",
-  "status.filter": "Filter this post",
+  "status.filter": "Dit bericht filteren",
   "status.filtered": "Gefilterd",
   "status.hide": "Bericht verbergen",
   "status.history.created": "{name} plaatste dit {date}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Alles minder tonen",
   "status.show_more": "Meer tonen",
   "status.show_more_all": "Alles meer tonen",
+  "status.show_original": "Show original",
   "status.show_thread": "Gesprek tonen",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "Niet beschikbaar",
   "status.unmute_conversation": "Gesprek niet langer negeren",
   "status.unpin": "Van profielpagina losmaken",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Wijzigingen opslaan",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "Aanbeveling verwerpen",
   "suggestions.header": "Je bent waarschijnlijk ook geïnteresseerd in…",
   "tabs_bar.federated_timeline": "Globaal",
diff --git a/app/javascript/mastodon/locales/nn.json b/app/javascript/mastodon/locales/nn.json
index 33c06e11e..03db34b65 100644
--- a/app/javascript/mastodon/locales/nn.json
+++ b/app/javascript/mastodon/locales/nn.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Fylgjer deg",
   "account.hide_reblogs": "Gøym fremhevingar frå @{name}",
   "account.joined": "Vart med {date}",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "Eigarskap for denne lenkja vart sist sjekka {date}",
   "account.locked_info": "Denne kontoen er privat. Eigaren kan sjølv velja kven som kan fylgja han.",
   "account.media": "Media",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Kom i gang",
   "getting_started.invite": "Byd folk inn",
   "getting_started.open_source_notice": "Mastodon er fri programvare. Du kan bidraga eller rapportera problem med GitHub på {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Kontoinnstillingar",
-  "getting_started.terms": "Brukarvilkår",
   "hashtag.column_header.tag_mode.all": "og {additional}",
   "hashtag.column_header.tag_mode.any": "eller {additional}",
   "hashtag.column_header.tag_mode.none": "utan {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Kunne ikkje finne noko for desse søkeorda",
   "search_results.statuses": "Tut",
   "search_results.statuses_fts_disabled": "På denne Matsodon-tenaren kan du ikkje søkja på tut etter innhaldet deira.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {treff} other {treff}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Opne moderasjonsgrensesnitt for @{name}",
   "status.admin_status": "Opne denne statusen i moderasjonsgrensesnittet",
   "status.block": "Blokker @{name}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Vis mindre for alle",
   "status.show_more": "Vis meir",
   "status.show_more_all": "Vis meir for alle",
+  "status.show_original": "Show original",
   "status.show_thread": "Vis tråd",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "Ikkje tilgjengeleg",
   "status.unmute_conversation": "Opphev målbinding av samtalen",
   "status.unpin": "Løys frå profil",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "Avslå framlegg",
   "suggestions.header": "Du er kanskje interessert i…",
   "tabs_bar.federated_timeline": "Føderert",
diff --git a/app/javascript/mastodon/locales/no.json b/app/javascript/mastodon/locales/no.json
index 6e2783713..640a34f9e 100644
--- a/app/javascript/mastodon/locales/no.json
+++ b/app/javascript/mastodon/locales/no.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Følger deg",
   "account.hide_reblogs": "Skjul fremhevinger fra @{name}",
   "account.joined": "Ble med den {date}",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "Eierskap av denne lenken ble sjekket {date}",
   "account.locked_info": "Denne kontoens personvernstatus er satt til låst. Eieren vurderer manuelt hvem som kan følge dem.",
   "account.media": "Media",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Kom i gang",
   "getting_started.invite": "Inviter folk",
   "getting_started.open_source_notice": "Mastodon er fri programvare. Du kan bidra eller rapportere problemer på GitHub på {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Kontoinnstillinger",
-  "getting_started.terms": "Bruksvilkår",
   "hashtag.column_header.tag_mode.all": "og {additional}",
   "hashtag.column_header.tag_mode.any": "eller {additional}",
   "hashtag.column_header.tag_mode.none": "uten {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Could not find anything for these search terms",
   "search_results.statuses": "Tuter",
   "search_results.statuses_fts_disabled": "Å søke i tuter etter innhold er ikke skrudd på i denne Mastodon-tjeneren.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {resultat} other {resultater}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Åpne moderatorgrensesnittet for @{name}",
   "status.admin_status": "Åpne denne statusen i moderatorgrensesnittet",
   "status.block": "Blokkér @{name}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Vis mindre for alle",
   "status.show_more": "Vis mer",
   "status.show_more_all": "Vis mer for alle",
+  "status.show_original": "Show original",
   "status.show_thread": "Vis tråden",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "Ikke tilgjengelig",
   "status.unmute_conversation": "Ikke demp samtale",
   "status.unpin": "Angre festing på profilen",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "Utelukk forslaget",
   "suggestions.header": "Du er kanskje interessert i …",
   "tabs_bar.federated_timeline": "Felles",
diff --git a/app/javascript/mastodon/locales/oc.json b/app/javascript/mastodon/locales/oc.json
index fa3ef3967..28e8228b1 100644
--- a/app/javascript/mastodon/locales/oc.json
+++ b/app/javascript/mastodon/locales/oc.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Vos sèc",
   "account.hide_reblogs": "Rescondre los partatges de @{name}",
   "account.joined": "Arribèt en {date}",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "La proprietat d’aqueste ligam foguèt verificada lo {date}",
   "account.locked_info": "L’estatut de privacitat del compte es configurat sus clavat. Lo proprietari causís qual pòt sègre son compte.",
   "account.media": "Mèdias",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Per començar",
   "getting_started.invite": "Convidar de mond",
   "getting_started.open_source_notice": "Mastodon es un logicial liure. Podètz contribuir e mandar vòstres comentaris e rapòrt de bug via {github} sus GitHub.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Seguretat",
-  "getting_started.terms": "Condicions d’utilizacion",
   "hashtag.column_header.tag_mode.all": "e {additional}",
   "hashtag.column_header.tag_mode.any": "o {additional}",
   "hashtag.column_header.tag_mode.none": "sens {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Could not find anything for these search terms",
   "search_results.statuses": "Tuts",
   "search_results.statuses_fts_disabled": "La recèrca de tuts per lor contengut es pas activada sus aqueste servidor Mastodon.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {resultat} other {resultats}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Dobrir l’interfàcia de moderacion per @{name}",
   "status.admin_status": "Dobrir aqueste estatut dins l’interfàcia de moderacion",
   "status.block": "Blocar @{name}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Los tornar plegar totes",
   "status.show_more": "Desplegar",
   "status.show_more_all": "Los desplegar totes",
+  "status.show_original": "Show original",
   "status.show_thread": "Mostrar lo fil",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "Pas disponible",
   "status.unmute_conversation": "Tornar mostrar la conversacion",
   "status.unpin": "Tirar del perfil",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "Regetar la suggestion",
   "suggestions.header": "Vos poiriá interessar…",
   "tabs_bar.federated_timeline": "Flux public global",
diff --git a/app/javascript/mastodon/locales/pa.json b/app/javascript/mastodon/locales/pa.json
index c77444bff..7e3bba2df 100644
--- a/app/javascript/mastodon/locales/pa.json
+++ b/app/javascript/mastodon/locales/pa.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Follows you",
   "account.hide_reblogs": "Hide boosts from @{name}",
   "account.joined": "Joined {date}",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.",
   "account.media": "Media",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Getting started",
   "getting_started.invite": "Invite people",
   "getting_started.open_source_notice": "Mastodon is open source software. You can contribute or report issues on GitHub at {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Security",
-  "getting_started.terms": "Terms of service",
   "hashtag.column_header.tag_mode.all": "and {additional}",
   "hashtag.column_header.tag_mode.any": "or {additional}",
   "hashtag.column_header.tag_mode.none": "without {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Could not find anything for these search terms",
   "search_results.statuses": "Toots",
   "search_results.statuses_fts_disabled": "Searching toots by their content is not enabled on this Mastodon server.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {result} other {results}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Open moderation interface for @{name}",
   "status.admin_status": "Open this status in the moderation interface",
   "status.block": "Block @{name}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Show less for all",
   "status.show_more": "Show more",
   "status.show_more_all": "Show more for all",
+  "status.show_original": "Show original",
   "status.show_thread": "Show thread",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "Not available",
   "status.unmute_conversation": "Unmute conversation",
   "status.unpin": "Unpin from profile",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "Dismiss suggestion",
   "suggestions.header": "You might be interested in…",
   "tabs_bar.federated_timeline": "Federated",
diff --git a/app/javascript/mastodon/locales/pl.json b/app/javascript/mastodon/locales/pl.json
index e320ea3a1..34103dd1b 100644
--- a/app/javascript/mastodon/locales/pl.json
+++ b/app/javascript/mastodon/locales/pl.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Śledzi Cię",
   "account.hide_reblogs": "Ukryj podbicia od @{name}",
   "account.joined": "Dołączył(a) {date}",
+  "account.languages": "Zmień subskrybowane języki",
   "account.link_verified_on": "Własność tego odnośnika została potwierdzona {date}",
   "account.locked_info": "To konto jest prywatne. Właściciel ręcznie wybiera kto może go śledzić.",
   "account.media": "Zawartość multimedialna",
@@ -201,22 +202,22 @@
   "explore.trending_links": "Aktualności",
   "explore.trending_statuses": "Posty",
   "explore.trending_tags": "Hasztagi",
-  "filter_modal.added.context_mismatch_explanation": "This filter category does not apply to the context in which you have accessed this post. If you want the post to be filtered in this context too, you will have to edit the filter.",
-  "filter_modal.added.context_mismatch_title": "Context mismatch!",
-  "filter_modal.added.expired_explanation": "This filter category has expired, you will need to change the expiration date for it to apply.",
-  "filter_modal.added.expired_title": "Expired filter!",
-  "filter_modal.added.review_and_configure": "To review and further configure this filter category, go to the {settings_link}.",
-  "filter_modal.added.review_and_configure_title": "Filter settings",
-  "filter_modal.added.settings_link": "settings page",
-  "filter_modal.added.short_explanation": "This post has been added to the following filter category: {title}.",
-  "filter_modal.added.title": "Filter added!",
-  "filter_modal.select_filter.context_mismatch": "does not apply to this context",
-  "filter_modal.select_filter.expired": "expired",
-  "filter_modal.select_filter.prompt_new": "New category: {name}",
-  "filter_modal.select_filter.search": "Search or create",
-  "filter_modal.select_filter.subtitle": "Use an existing category or create a new one",
-  "filter_modal.select_filter.title": "Filter this post",
-  "filter_modal.title.status": "Filter a post",
+  "filter_modal.added.context_mismatch_explanation": "Ta kategoria filtrów nie ma zastosowania do kontekstu, w którym uzyskałeś dostęp do tego wpisu. Jeśli chcesz, aby wpis został przefiltrowany również w tym kontekście, będziesz musiał edytować filtr.",
+  "filter_modal.added.context_mismatch_title": "Niezgodność kontekstów!",
+  "filter_modal.added.expired_explanation": "Ta kategoria filtra wygasła, będziesz musiał zmienić datę wygaśnięcia, aby ją zastosować.",
+  "filter_modal.added.expired_title": "Wygasły filtr!",
+  "filter_modal.added.review_and_configure": "Aby przejrzeć i skonfigurować tę kategorię filtrów, przejdź do {settings_link}.",
+  "filter_modal.added.review_and_configure_title": "Ustawienia filtra",
+  "filter_modal.added.settings_link": "strona ustawień",
+  "filter_modal.added.short_explanation": "Ten wpis został dodany do następującej kategorii filtrów: {title}.",
+  "filter_modal.added.title": "Filtr dodany!",
+  "filter_modal.select_filter.context_mismatch": "nie dotyczy tego kontekstu",
+  "filter_modal.select_filter.expired": "wygasły",
+  "filter_modal.select_filter.prompt_new": "Nowa kategoria: {name}",
+  "filter_modal.select_filter.search": "Szukaj lub utwórz",
+  "filter_modal.select_filter.subtitle": "Użyj istniejącej kategorii lub utwórz nową",
+  "filter_modal.select_filter.title": "Filtruj ten wpis",
+  "filter_modal.title.status": "Filtruj wpis",
   "follow_recommendations.done": "Gotowe",
   "follow_recommendations.heading": "Śledź ludzi, których wpisy chcesz czytać. Oto kilka propozycji.",
   "follow_recommendations.lead": "Wpisy osób, które śledzisz będą pojawiać się w porządku chronologicznym na stronie głównej. Nie bój się popełniać błędów, możesz bez problemu przestać śledzić każdego w każdej chwili!",
@@ -230,8 +231,8 @@
   "getting_started.heading": "Rozpocznij",
   "getting_started.invite": "Zaproś znajomych",
   "getting_started.open_source_notice": "Mastodon jest oprogramowaniem o otwartym źródle. Możesz pomóc w rozwoju lub zgłaszać błędy na GitHubie tutaj: {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Bezpieczeństwo",
-  "getting_started.terms": "Zasady użytkowania",
   "hashtag.column_header.tag_mode.all": "i {additional}",
   "hashtag.column_header.tag_mode.any": "lub {additional}",
   "hashtag.column_header.tag_mode.none": "bez {additional}",
@@ -476,7 +477,11 @@
   "search_results.nothing_found": "Nie znaleziono innych wyników dla tego wyszukania",
   "search_results.statuses": "Wpisy",
   "search_results.statuses_fts_disabled": "Szukanie wpisów przy pomocy ich zawartości nie jest włączone na tym serwerze Mastodona.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {wynik} few {wyniki} many {wyników} other {wyników}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Otwórz interfejs moderacyjny dla @{name}",
   "status.admin_status": "Otwórz ten wpis w interfejsie moderacyjnym",
   "status.block": "Zablokuj @{name}",
@@ -492,7 +497,7 @@
   "status.edited_x_times": "Edytowano {count, plural, one {{count} raz} other {{count} razy}}",
   "status.embed": "Osadź",
   "status.favourite": "Dodaj do ulubionych",
-  "status.filter": "Filter this post",
+  "status.filter": "Filtruj ten wpis",
   "status.filtered": "Filtrowany(-a)",
   "status.hide": "Schowaj toota",
   "status.history.created": "{name} utworzył(a) {date}",
@@ -523,10 +528,16 @@
   "status.show_less_all": "Zwiń wszystkie",
   "status.show_more": "Rozwiń",
   "status.show_more_all": "Rozwiń wszystkie",
+  "status.show_original": "Pokaż oryginał",
   "status.show_thread": "Pokaż wątek",
+  "status.translate": "Przetłumacz",
+  "status.translated_from": "Przetłumaczone z {lang}",
   "status.uncached_media_warning": "Niedostępne",
   "status.unmute_conversation": "Cofnij wyciszenie konwersacji",
   "status.unpin": "Odepnij z profilu",
+  "subscribed_languages.lead": "Tylko posty w wybranych językach pojawią się na Twojej osi czasu po zmianie. Nie wybieraj żadnego języka aby otrzymywać posty we wszystkich językach.",
+  "subscribed_languages.save": "Zapisz zmiany",
+  "subscribed_languages.target": "Zmień subskrybowane języki dla {target}",
   "suggestions.dismiss": "Odrzuć sugestię",
   "suggestions.header": "Może Cię zainteresować…",
   "tabs_bar.federated_timeline": "Globalne",
diff --git a/app/javascript/mastodon/locales/pt-BR.json b/app/javascript/mastodon/locales/pt-BR.json
index ab1443ece..f6442086e 100644
--- a/app/javascript/mastodon/locales/pt-BR.json
+++ b/app/javascript/mastodon/locales/pt-BR.json
@@ -24,6 +24,7 @@
   "account.follows_you": "te segue",
   "account.hide_reblogs": "Ocultar boosts de @{name}",
   "account.joined": "Entrou em {date}",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "link verificado em {date}",
   "account.locked_info": "Trancado. Seguir requer aprovação manual do perfil.",
   "account.media": "Mídia",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Primeiros passos",
   "getting_started.invite": "Convidar pessoas",
   "getting_started.open_source_notice": "Mastodon é um software de código aberto. Você pode contribuir ou reportar problemas na página do projeto no GitHub em {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Configurações da conta",
-  "getting_started.terms": "Termos de serviço",
   "hashtag.column_header.tag_mode.all": "e {additional}",
   "hashtag.column_header.tag_mode.any": "ou {additional}",
   "hashtag.column_header.tag_mode.none": "sem {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Não foi possível encontrar nada para estes termos de busca",
   "search_results.statuses": "Toots",
   "search_results.statuses_fts_disabled": "Pesquisar toots por seu conteúdo não está ativado nesta instância Mastodon.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {resultado} other {resultados}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Abrir interface de moderação para @{name}",
   "status.admin_status": "Abrir este toot na interface de moderação",
   "status.block": "Bloquear @{name}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Mostrar menos em tudo",
   "status.show_more": "Mostrar mais",
   "status.show_more_all": "Mostrar mais em tudo",
+  "status.show_original": "Show original",
   "status.show_thread": "Mostrar conversa",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "Não disponível",
   "status.unmute_conversation": "Dessilenciar conversa",
   "status.unpin": "Desafixar",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "Ignorar sugestão",
   "suggestions.header": "Talvez seja do teu interesse…",
   "tabs_bar.federated_timeline": "Linha global",
diff --git a/app/javascript/mastodon/locales/pt-PT.json b/app/javascript/mastodon/locales/pt-PT.json
index ef097b380..56a08516c 100644
--- a/app/javascript/mastodon/locales/pt-PT.json
+++ b/app/javascript/mastodon/locales/pt-PT.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Segue-te",
   "account.hide_reblogs": "Esconder partilhas de @{name}",
   "account.joined": "Ingressou em {date}",
+  "account.languages": "Alterar idiomas subscritos",
   "account.link_verified_on": "A posse deste link foi verificada em {date}",
   "account.locked_info": "Esta conta é privada. O proprietário revê manualmente quem a pode seguir.",
   "account.media": "Média",
@@ -197,22 +198,22 @@
   "explore.trending_links": "Notícias",
   "explore.trending_statuses": "Publicações",
   "explore.trending_tags": "Hashtags",
-  "filter_modal.added.context_mismatch_explanation": "This filter category does not apply to the context in which you have accessed this post. If you want the post to be filtered in this context too, you will have to edit the filter.",
-  "filter_modal.added.context_mismatch_title": "Context mismatch!",
-  "filter_modal.added.expired_explanation": "This filter category has expired, you will need to change the expiration date for it to apply.",
-  "filter_modal.added.expired_title": "Expired filter!",
-  "filter_modal.added.review_and_configure": "To review and further configure this filter category, go to the {settings_link}.",
-  "filter_modal.added.review_and_configure_title": "Filter settings",
-  "filter_modal.added.settings_link": "settings page",
-  "filter_modal.added.short_explanation": "This post has been added to the following filter category: {title}.",
-  "filter_modal.added.title": "Filter added!",
-  "filter_modal.select_filter.context_mismatch": "does not apply to this context",
-  "filter_modal.select_filter.expired": "expired",
-  "filter_modal.select_filter.prompt_new": "New category: {name}",
-  "filter_modal.select_filter.search": "Search or create",
-  "filter_modal.select_filter.subtitle": "Use an existing category or create a new one",
-  "filter_modal.select_filter.title": "Filter this post",
-  "filter_modal.title.status": "Filter a post",
+  "filter_modal.added.context_mismatch_explanation": "Esta categoria de filtro não se aplica ao contexto em que acedeu a esta publicação. Se pretender que esta publicação seja filtrada também neste contexto, terá que editar o filtro.",
+  "filter_modal.added.context_mismatch_title": "Contexto incoerente!",
+  "filter_modal.added.expired_explanation": "Esta categoria de filtro expirou, necessita alterar a data de validade para que ele seja aplicado.",
+  "filter_modal.added.expired_title": "Filtro expirado!",
+  "filter_modal.added.review_and_configure": "Para rever e configurar mais detalhadamente esta categoria de filtro, vá a {settings_link}.",
+  "filter_modal.added.review_and_configure_title": "Definições do filtro",
+  "filter_modal.added.settings_link": "página de definições",
+  "filter_modal.added.short_explanation": "Esta publicação foi adicionada à seguinte categoria de filtro: {title}.",
+  "filter_modal.added.title": "Filtro adicionado!",
+  "filter_modal.select_filter.context_mismatch": "não se aplica a este contexto",
+  "filter_modal.select_filter.expired": "expirado",
+  "filter_modal.select_filter.prompt_new": "Nova categoria: {name}",
+  "filter_modal.select_filter.search": "Pesquisar ou criar",
+  "filter_modal.select_filter.subtitle": "Utilize uma categoria existente ou crie uma nova",
+  "filter_modal.select_filter.title": "Filtrar esta publicação",
+  "filter_modal.title.status": "Filtrar uma publicação",
   "follow_recommendations.done": "Concluído",
   "follow_recommendations.heading": "Siga pessoas das quais gostaria de ver publicações! Aqui estão algumas sugestões.",
   "follow_recommendations.lead": "As publicações das pessoas que segue serão exibidos em ordem cronológica na sua página inicial. Não tenha medo de cometer erros, você pode deixar de seguir as pessoas tão facilmente a qualquer momento!",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Primeiros passos",
   "getting_started.invite": "Convidar pessoas",
   "getting_started.open_source_notice": "Mastodon é um software de código aberto. Podes contribuir ou reportar problemas no GitHub do projeto: {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Segurança",
-  "getting_started.terms": "Termos de serviço",
   "hashtag.column_header.tag_mode.all": "e {additional}",
   "hashtag.column_header.tag_mode.any": "ou {additional}",
   "hashtag.column_header.tag_mode.none": "sem {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Não foi possível encontrar resultados para as expressões pesquisadas",
   "search_results.statuses": "Toots",
   "search_results.statuses_fts_disabled": "A pesquisa de toots pelo seu conteúdo não está disponível nesta instância Mastodon.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {resultado} other {resultados}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Abrir a interface de moderação para @{name}",
   "status.admin_status": "Abrir esta publicação na interface de moderação",
   "status.block": "Bloquear @{name}",
@@ -487,7 +492,7 @@
   "status.edited_x_times": "Editado {count, plural,one {{count} vez} other {{count} vezes}}",
   "status.embed": "Incorporar",
   "status.favourite": "Adicionar aos favoritos",
-  "status.filter": "Filter this post",
+  "status.filter": "Filtrar esta publicação",
   "status.filtered": "Filtrada",
   "status.hide": "Esconder publicação",
   "status.history.created": "{name} criado em {date}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Mostrar menos para todas",
   "status.show_more": "Mostrar mais",
   "status.show_more_all": "Mostrar mais para todas",
+  "status.show_original": "Mostrar original",
   "status.show_thread": "Mostrar conversa",
+  "status.translate": "Traduzir",
+  "status.translated_from": "Traduzido de {lang}",
   "status.uncached_media_warning": "Não disponível",
   "status.unmute_conversation": "Deixar de silenciar esta conversa",
   "status.unpin": "Não fixar no perfil",
+  "subscribed_languages.lead": "Após a alteração, apenas as publicações nos idiomas selecionados aparecerão na sua página inicial e listas. Não selecione nenhuma para receber publicações de todos os idiomas.",
+  "subscribed_languages.save": "Guardar alterações",
+  "subscribed_languages.target": "Alterar idiomas subscritos para {target}",
   "suggestions.dismiss": "Dispensar a sugestão",
   "suggestions.header": "Tu podes estar interessado em…",
   "tabs_bar.federated_timeline": "Federada",
diff --git a/app/javascript/mastodon/locales/ro.json b/app/javascript/mastodon/locales/ro.json
index ff5ec9b2a..a301aeade 100644
--- a/app/javascript/mastodon/locales/ro.json
+++ b/app/javascript/mastodon/locales/ro.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Este abonat la tine",
   "account.hide_reblogs": "Ascunde distribuirile de la @{name}",
   "account.joined": "S-a înscris în {date}",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "Proprietatea acestui link a fost verificată pe {date}",
   "account.locked_info": "Acest profil este privat. Această persoană aprobă manual conturile care se abonează la ea.",
   "account.media": "Media",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Primii pași",
   "getting_started.invite": "Invită persoane",
   "getting_started.open_source_notice": "Mastodon este un software cu sursă deschisă (open source). Poți contribui la dezvoltarea lui sau raporta probleme pe GitHub la {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Setări cont",
-  "getting_started.terms": "Termeni și condiții",
   "hashtag.column_header.tag_mode.all": "și {additional}",
   "hashtag.column_header.tag_mode.any": "sau {additional}",
   "hashtag.column_header.tag_mode.none": "fără {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Could not find anything for these search terms",
   "search_results.statuses": "Postări",
   "search_results.statuses_fts_disabled": "Căutarea de postări după conținutul lor nu este activată pe acest server.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {rezultat} other {rezultate}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Deschide interfața de moderare pentru @{name}",
   "status.admin_status": "Deschide această stare în interfața de moderare",
   "status.block": "Blochează pe @{name}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Arată mai puțin pentru toți",
   "status.show_more": "Arată mai mult",
   "status.show_more_all": "Arată mai mult pentru toți",
+  "status.show_original": "Show original",
   "status.show_thread": "Arată discuția",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "Indisponibil",
   "status.unmute_conversation": "Repornește conversația",
   "status.unpin": "Eliberează din profil",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "Omite sugestia",
   "suggestions.header": "Ai putea fi interesat de…",
   "tabs_bar.federated_timeline": "Global",
diff --git a/app/javascript/mastodon/locales/ru.json b/app/javascript/mastodon/locales/ru.json
index e53088e39..e8e7c4d3e 100644
--- a/app/javascript/mastodon/locales/ru.json
+++ b/app/javascript/mastodon/locales/ru.json
@@ -7,12 +7,12 @@
   "account.block_domain": "Заблокировать {domain}",
   "account.blocked": "Заблокирован(а)",
   "account.browse_more_on_origin_server": "Посмотреть в оригинальном профиле",
-  "account.cancel_follow_request": "Отменить запрос",
+  "account.cancel_follow_request": "Отменить подписку",
   "account.direct": "Написать @{name}",
-  "account.disable_notifications": "Отключить уведомления от @{name}",
+  "account.disable_notifications": "Не уведомлять о постах от @{name}",
   "account.domain_blocked": "Домен заблокирован",
   "account.edit_profile": "Редактировать профиль",
-  "account.enable_notifications": "Включить уведомления для @{name}",
+  "account.enable_notifications": "Уведомлять о постах от @{name}",
   "account.endorse": "Рекомендовать в профиле",
   "account.follow": "Подписаться",
   "account.followers": "Подписчики",
@@ -24,13 +24,14 @@
   "account.follows_you": "Подписан(а) на вас",
   "account.hide_reblogs": "Скрыть продвижения от @{name}",
   "account.joined": "Зарегистрирован(а) с {date}",
+  "account.languages": "Изменить языки подписки",
   "account.link_verified_on": "Владение этой ссылкой было проверено {date}",
   "account.locked_info": "Это закрытый аккаунт. Его владелец вручную одобряет подписчиков.",
   "account.media": "Медиа",
   "account.mention": "Упомянуть @{name}",
   "account.moved_to": "Ищите {name} здесь:",
   "account.mute": "Игнорировать @{name}",
-  "account.mute_notifications": "Скрыть уведомления от @{name}",
+  "account.mute_notifications": "Игнорировать уведомления от @{name}",
   "account.muted": "Игнорируется",
   "account.posts": "Посты",
   "account.posts_with_replies": "Посты и ответы",
@@ -44,7 +45,7 @@
   "account.unblock_short": "Разблокировать",
   "account.unendorse": "Не рекомендовать в профиле",
   "account.unfollow": "Отписаться",
-  "account.unmute": "Не игнорировать @{name}",
+  "account.unmute": "Убрать {name} из игнорируемых",
   "account.unmute_notifications": "Показывать уведомления от @{name}",
   "account.unmute_short": "Не игнорировать",
   "account_note.placeholder": "Текст заметки",
@@ -127,7 +128,7 @@
   "confirmations.discard_edit_media.confirm": "Отменить",
   "confirmations.discard_edit_media.message": "У вас есть несохранённые изменения описания мультимедиа или предпросмотра, отменить их?",
   "confirmations.domain_block.confirm": "Да, заблокировать узел",
-  "confirmations.domain_block.message": "Вы точно уверены, что хотите скрыть все посты с узла {domain}? В большинстве случаев пары блокировок и скрытий вполне достаточно.\n\nПри блокировке узла, вы перестанете получать уведомления оттуда, все посты будут скрыты из публичных лент, а подписчики убраны.",
+  "confirmations.domain_block.message": "Вы точно уверены, что хотите заблокировать {domain} полностью? В большинстве случаев нескольких блокировок и игнорирований вполне достаточно. Вы перестанете видеть публичную ленту и уведомления оттуда. Ваши подписчики из этого домена будут удалены.",
   "confirmations.logout.confirm": "Выйти",
   "confirmations.logout.message": "Вы уверены, что хотите выйти?",
   "confirmations.mute.confirm": "Игнорировать",
@@ -197,22 +198,22 @@
   "explore.trending_links": "Новости",
   "explore.trending_statuses": "Посты",
   "explore.trending_tags": "Хэштеги",
-  "filter_modal.added.context_mismatch_explanation": "This filter category does not apply to the context in which you have accessed this post. If you want the post to be filtered in this context too, you will have to edit the filter.",
-  "filter_modal.added.context_mismatch_title": "Context mismatch!",
-  "filter_modal.added.expired_explanation": "This filter category has expired, you will need to change the expiration date for it to apply.",
-  "filter_modal.added.expired_title": "Expired filter!",
-  "filter_modal.added.review_and_configure": "To review and further configure this filter category, go to the {settings_link}.",
-  "filter_modal.added.review_and_configure_title": "Filter settings",
-  "filter_modal.added.settings_link": "settings page",
-  "filter_modal.added.short_explanation": "This post has been added to the following filter category: {title}.",
-  "filter_modal.added.title": "Filter added!",
-  "filter_modal.select_filter.context_mismatch": "does not apply to this context",
-  "filter_modal.select_filter.expired": "expired",
-  "filter_modal.select_filter.prompt_new": "New category: {name}",
-  "filter_modal.select_filter.search": "Search or create",
-  "filter_modal.select_filter.subtitle": "Use an existing category or create a new one",
-  "filter_modal.select_filter.title": "Filter this post",
-  "filter_modal.title.status": "Filter a post",
+  "filter_modal.added.context_mismatch_explanation": "Эта категория не применяется к контексту, в котором вы получили доступ к этому посту. Если вы хотите, чтобы пост был отфильтрован в этом контексте, вам придётся отредактировать фильтр.",
+  "filter_modal.added.context_mismatch_title": "Несоответствие контекста!",
+  "filter_modal.added.expired_explanation": "Эта категория фильтра устарела, вам нужно изменить дату окончания фильтра, чтобы применить его.",
+  "filter_modal.added.expired_title": "Истёкший фильтр!",
+  "filter_modal.added.review_and_configure": "Для просмотра и настройки этой категории фильтра, перейдите в {settings_link}.",
+  "filter_modal.added.review_and_configure_title": "Настройки фильтра",
+  "filter_modal.added.settings_link": "страница настроек",
+  "filter_modal.added.short_explanation": "Этот пост был добавлен в следующую категорию фильтра: {title}.",
+  "filter_modal.added.title": "Фильтр добавлен!",
+  "filter_modal.select_filter.context_mismatch": "не применяется к этому контексту",
+  "filter_modal.select_filter.expired": "истекло",
+  "filter_modal.select_filter.prompt_new": "Новая категория: {name}",
+  "filter_modal.select_filter.search": "Поиск или создание",
+  "filter_modal.select_filter.subtitle": "Используйте существующую категорию или создайте новую",
+  "filter_modal.select_filter.title": "Фильтровать этот пост",
+  "filter_modal.title.status": "Фильтровать пост",
   "follow_recommendations.done": "Готово",
   "follow_recommendations.heading": "Подпишитесь на людей, чьи посты вы бы хотели видеть. Вот несколько предложений.",
   "follow_recommendations.lead": "Посты от людей, на которых вы подписаны, будут отображаться в вашей домашней ленте в хронологическом порядке. Не бойтесь ошибиться — вы так же легко сможете отписаться от них в любое время!",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Начать",
   "getting_started.invite": "Пригласить людей",
   "getting_started.open_source_notice": "Mastodon — сервис с открытым исходным кодом. Вы можете внести вклад или сообщить о проблемах на GitHub: {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Настройки учётной записи",
-  "getting_started.terms": "Условия использования",
   "hashtag.column_header.tag_mode.all": "и {additional}",
   "hashtag.column_header.tag_mode.any": "или {additional}",
   "hashtag.column_header.tag_mode.none": "без {additional}",
@@ -266,7 +267,7 @@
   "keyboard_shortcuts.legend": "показать это окно",
   "keyboard_shortcuts.local": "перейти к локальной ленте",
   "keyboard_shortcuts.mention": "упомянуть автора поста",
-  "keyboard_shortcuts.muted": "открыть список игнорируемых",
+  "keyboard_shortcuts.muted": "Открыть список игнорируемых",
   "keyboard_shortcuts.my_profile": "перейти к своему профилю",
   "keyboard_shortcuts.notifications": "перейти к уведомлениям",
   "keyboard_shortcuts.open_media": "открыть вложение",
@@ -328,7 +329,7 @@
   "navigation_bar.keyboard_shortcuts": "Сочетания клавиш",
   "navigation_bar.lists": "Списки",
   "navigation_bar.logout": "Выйти",
-  "navigation_bar.mutes": "Список игнорируемых пользователей",
+  "navigation_bar.mutes": "Игнорируемые пользователи",
   "navigation_bar.personal": "Личное",
   "navigation_bar.pins": "Закреплённые посты",
   "navigation_bar.preferences": "Настройки",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Ничего не найдено по этому запросу",
   "search_results.statuses": "Посты",
   "search_results.statuses_fts_disabled": "Поиск постов по их содержанию не поддерживается данным сервером Mastodon.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {результат} few {результата} many {результатов} other {результатов}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Открыть интерфейс модератора для @{name}",
   "status.admin_status": "Открыть этот пост в интерфейсе модератора",
   "status.block": "Заблокировать @{name}",
@@ -487,7 +492,7 @@
   "status.edited_x_times": "{count, plural, one {{count} изменение} many {{count} изменений} other {{count} изменения}}",
   "status.embed": "Встроить на свой сайт",
   "status.favourite": "В избранное",
-  "status.filter": "Filter this post",
+  "status.filter": "Фильтровать этот пост",
   "status.filtered": "Отфильтровано",
   "status.hide": "Скрыть пост",
   "status.history.created": "{name} создал {date}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Свернуть все спойлеры в ветке",
   "status.show_more": "Развернуть",
   "status.show_more_all": "Развернуть все спойлеры в ветке",
+  "status.show_original": "Показать оригинал",
   "status.show_thread": "Показать обсуждение",
+  "status.translate": "Перевод",
+  "status.translated_from": "Переведено с {lang}",
   "status.uncached_media_warning": "Невозможно отобразить файл",
   "status.unmute_conversation": "Не игнорировать обсуждение",
   "status.unpin": "Открепить от профиля",
+  "subscribed_languages.lead": "Посты только на выбранных языках будут отображаться на вашей домашней странице и в списке лент после изменения. Выберите «Нет», чтобы получать посты на всех языках.",
+  "subscribed_languages.save": "Сохранить изменения",
+  "subscribed_languages.target": "Изменить языки подписки для {target}",
   "suggestions.dismiss": "Удалить предложение",
   "suggestions.header": "Вам может быть интересно…",
   "tabs_bar.federated_timeline": "Глобальная",
diff --git a/app/javascript/mastodon/locales/sa.json b/app/javascript/mastodon/locales/sa.json
index 2ebda63cd..062aa51e8 100644
--- a/app/javascript/mastodon/locales/sa.json
+++ b/app/javascript/mastodon/locales/sa.json
@@ -24,6 +24,7 @@
   "account.follows_you": "त्वामनुसरति",
   "account.hide_reblogs": "@{name} मित्रस्य प्रकाशनानि छिद्यन्ताम्",
   "account.joined": "Joined {date}",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "अन्तर्जालस्थानस्यास्य स्वामित्वं परीक्षितमासीत् {date} दिने",
   "account.locked_info": "एतस्या लेखायाः गुह्यता \"निषिद्ध\"इति वर्तते । स्वामी स्वयञ्चिनोति कोऽनुसर्ता भवितुमर्हतीति ।",
   "account.media": "सामग्री",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Getting started",
   "getting_started.invite": "Invite people",
   "getting_started.open_source_notice": "Mastodon is open source software. You can contribute or report issues on GitHub at {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Security",
-  "getting_started.terms": "Terms of service",
   "hashtag.column_header.tag_mode.all": "and {additional}",
   "hashtag.column_header.tag_mode.any": "or {additional}",
   "hashtag.column_header.tag_mode.none": "without {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Could not find anything for these search terms",
   "search_results.statuses": "Toots",
   "search_results.statuses_fts_disabled": "Searching toots by their content is not enabled on this Mastodon server.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {result} other {results}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Open moderation interface for @{name}",
   "status.admin_status": "Open this status in the moderation interface",
   "status.block": "Block @{name}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Show less for all",
   "status.show_more": "Show more",
   "status.show_more_all": "Show more for all",
+  "status.show_original": "Show original",
   "status.show_thread": "Show thread",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "Not available",
   "status.unmute_conversation": "Unmute conversation",
   "status.unpin": "Unpin from profile",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "Dismiss suggestion",
   "suggestions.header": "You might be interested in…",
   "tabs_bar.federated_timeline": "Federated",
diff --git a/app/javascript/mastodon/locales/sc.json b/app/javascript/mastodon/locales/sc.json
index 7482d15fe..30e66f396 100644
--- a/app/javascript/mastodon/locales/sc.json
+++ b/app/javascript/mastodon/locales/sc.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Ti sighit",
   "account.hide_reblogs": "Cua is cumpartziduras de @{name}",
   "account.joined": "At aderidu su {date}",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "Sa propiedade de custu ligòngiu est istada controllada su {date}",
   "account.locked_info": "S'istadu de riservadesa de custu contu est istadu cunfiguradu comente blocadu. Sa persone chi tenet sa propiedade revisionat a manu chie dda podet sighire.",
   "account.media": "Cuntenutu multimediale",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Comente cumintzare",
   "getting_started.invite": "Invita gente",
   "getting_started.open_source_notice": "Mastodon est de còdighe abertu. Bi podes contribuire o sinnalare faddinas in {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Cunfiguratziones de su contu",
-  "getting_started.terms": "Cunditziones de su servìtziu",
   "hashtag.column_header.tag_mode.all": "e {additional}",
   "hashtag.column_header.tag_mode.any": "o {additional}",
   "hashtag.column_header.tag_mode.none": "sena {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Could not find anything for these search terms",
   "search_results.statuses": "Publicatziones",
   "search_results.statuses_fts_disabled": "Sa chirca de publicatziones pro su cuntenutu issoro no est abilitada in custu serbidore de Mastodon.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {resurtadu} other {resurtados}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Aberi s'interfache de moderatzione pro @{name}",
   "status.admin_status": "Aberi custa publicatzione in s'interfache de moderatzione",
   "status.block": "Bloca a @{name}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Ammustra·nde prus pagu pro totus",
   "status.show_more": "Ammustra·nde prus",
   "status.show_more_all": "Ammustra·nde prus pro totus",
+  "status.show_original": "Show original",
   "status.show_thread": "Ammustra su tema",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "No est a disponimentu",
   "status.unmute_conversation": "Torra a ativare s'arresonada",
   "status.unpin": "Boga dae pitzu de su profilu",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "Iscarta cussìgiu",
   "suggestions.header": "Est possìbile chi tèngias interessu in…",
   "tabs_bar.federated_timeline": "Federada",
diff --git a/app/javascript/mastodon/locales/si.json b/app/javascript/mastodon/locales/si.json
index 170c34b57..28738ccb5 100644
--- a/app/javascript/mastodon/locales/si.json
+++ b/app/javascript/mastodon/locales/si.json
@@ -24,7 +24,8 @@
   "account.follows_you": "ඔබව අනුගමනය කරයි",
   "account.hide_reblogs": "@{name}සිට බූස්ට් සඟවන්න",
   "account.joined": "{date} එක් වී ඇත",
-  "account.link_verified_on": "මෙම සබැඳියේ හිමිකාරිත්වය {date} දින පරීක්ෂා කරන ලදී",
+  "account.languages": "Change subscribed languages",
+  "account.link_verified_on": "මෙම සබැඳියේ අයිතිය {date} දී පරීක්‍ෂා කෙරිණි",
   "account.locked_info": "මෙම ගිණුමේ රහස්‍යතා තත්ත්වය අගුලු දමා ඇත. හිමිකරු ඔවුන් අනුගමනය කළ හැක්කේ කාටදැයි හස්තීයව සමාලෝචනය කරයි.",
   "account.media": "මාධ්‍යය",
   "account.mention": "@{name} සැඳහුම",
@@ -32,7 +33,7 @@
   "account.mute": "@{name} නිහඬ කරන්න",
   "account.mute_notifications": "@{name}වෙතින් දැනුම්දීම් නිහඬ කරන්න",
   "account.muted": "නිහඬ කළා",
-  "account.posts": "ටූට්ස්",
+  "account.posts": "ලිපි",
   "account.posts_with_replies": "ටූට්ස් සහ පිළිතුරු",
   "account.report": "@{name} වාර්තා කරන්න",
   "account.requested": "අනුමැතිය බලාපොරොත්තුවෙන්",
@@ -41,25 +42,25 @@
   "account.statuses_counter": "{count, plural, one {{counter} ටූට්} other {{counter} ටූට්ස්}}",
   "account.unblock": "@{name} අනවහිර කරන්න",
   "account.unblock_domain": "{domain} වසම අනවහිර කරන්න",
-  "account.unblock_short": "අවහිර කිරීම ඉවත් කරන්න",
+  "account.unblock_short": "අනවහිර",
   "account.unendorse": "පැතිකඩෙහි විශේෂාංග නොකරන්න",
   "account.unfollow": "අනුගමනය නොකරන්න",
   "account.unmute": "@{name}නිහඬ නොකරන්න",
   "account.unmute_notifications": "@{name}වෙතින් දැනුම්දීම් නිහඬ නොකරන්න",
-  "account.unmute_short": "නිහඬ නොකරන්න",
-  "account_note.placeholder": "සටහන එකතු කිරීමට ක්ලික් කරන්න",
+  "account.unmute_short": "නොනිහඬ",
+  "account_note.placeholder": "සටහන යෙදීමට ඔබන්න",
   "admin.dashboard.daily_retention": "ලියාපදිංචි වීමෙන් පසු දිනකට පරිශීලක රඳවා ගැනීමේ අනුපාතය",
   "admin.dashboard.monthly_retention": "ලියාපදිංචි වීමෙන් පසු මාසය අනුව පරිශීලක රඳවා ගැනීමේ අනුපාතය",
   "admin.dashboard.retention.average": "සාමාන්යය",
   "admin.dashboard.retention.cohort": "ලියාපදිංචි වීමේ මාසය",
   "admin.dashboard.retention.cohort_size": "නව පරිශීලකයින්",
-  "alert.rate_limited.message": "කරුණාකර {retry_time, time, medium} ට පසු නැවත උත්සාහ කරන්න.",
+  "alert.rate_limited.message": "{retry_time, time, medium} කට පසුව උත්සාහ කරන්න.",
   "alert.rate_limited.title": "මිල සීමා සහිතයි",
   "alert.unexpected.message": "අනපේක්ෂිත දෝෂයක් ඇතිවුනා.",
   "alert.unexpected.title": "අපොයි!",
   "announcement.announcement": "නිවේදනය",
   "attachments_list.unprocessed": "(සැකසුම් නොකළ)",
-  "audio.hide": "Hide audio",
+  "audio.hide": "හඬපටය සඟවන්න",
   "autosuggest_hashtag.per_week": "සතියකට {count}",
   "boost_modal.combo": "ඊළඟ වතාවේ මෙය මඟ හැරීමට ඔබට {combo} එබිය හැක",
   "bundle_column_error.body": "මෙම සංරචකය පූරණය කිරීමේදී යම් දෙයක් වැරදී ඇත.",
@@ -77,23 +78,23 @@
   "column.favourites": "ප්‍රියතමයන්",
   "column.follow_requests": "ඉල්ලීම් අනුගමනය කරන්න",
   "column.home": "මුල් පිටුව",
-  "column.lists": "ලැයිස්තුව",
-  "column.mutes": "සමඟ කළ පරිශීලකයන්",
+  "column.lists": "ලේඛන",
+  "column.mutes": "නිහඬ කළ අය",
   "column.notifications": "දැනුම්දීම්",
-  "column.pins": "පින් කළ දත",
+  "column.pins": "ඇමිණූ ලිපි",
   "column.public": "ෆෙඩරේටඩ් කාලරේඛාව",
   "column_back_button.label": "ආපසු",
   "column_header.hide_settings": "සැකසුම් සඟවන්න",
   "column_header.moveLeft_settings": "තීරුව වමට ගෙනයන්න",
   "column_header.moveRight_settings": "තීරුව දකුණට ගෙනයන්න",
-  "column_header.pin": "පින් කරන්න",
+  "column_header.pin": "අමුණන්න",
   "column_header.show_settings": "සැකසුම් පෙන්වන්න",
-  "column_header.unpin": "ඇමුණුම ඉවත් කරන්න",
+  "column_header.unpin": "ගළවන්න",
   "column_subheading.settings": "සැකසුම්",
   "community.column_settings.local_only": "ස්ථානීයව පමණයි",
   "community.column_settings.media_only": "මාධ්‍ය පමණයි",
   "community.column_settings.remote_only": "දුරස්ථව පමණයි",
-  "compose.language.change": "භාෂාව වෙනස් කරන්න",
+  "compose.language.change": "භාෂාව සංශෝධනය",
   "compose.language.search": "භාෂා සොයන්න...",
   "compose_form.direct_message_warning_learn_more": "තව දැනගන්න",
   "compose_form.encryption_warning": "Mastodon හි පළ කිරීම් අන්තයේ සිට අවසානය දක්වා සංකේතනය කර නොමැත. Mastodon හරහා කිසිදු සංවේදී තොරතුරක් බෙදා නොගන්න.",
@@ -101,13 +102,13 @@
   "compose_form.lock_disclaimer": "ඔබගේ ගිණුම {locked}නොවේ. ඔබගේ අනුගාමිකයින්ට පමණක් පළ කිරීම් බැලීමට ඕනෑම කෙනෙකුට ඔබව අනුගමනය කළ හැක.",
   "compose_form.lock_disclaimer.lock": "අගුළු දමා ඇත",
   "compose_form.placeholder": "ඔබගේ සිතුවිලි මොනවාද?",
-  "compose_form.poll.add_option": "තේරීමක් එකතු කරන්න",
+  "compose_form.poll.add_option": "තේරීමක් යොදන්න",
   "compose_form.poll.duration": "මත විමසීමේ කාලය",
   "compose_form.poll.option_placeholder": "තේරීම {number}",
   "compose_form.poll.remove_option": "මෙම ඉවත් කරන්න",
   "compose_form.poll.switch_to_multiple": "තේරීම් කිහිපයක් ඉඩ දීම සඳහා මත විමසුම වෙනස් කරන්න",
   "compose_form.poll.switch_to_single": "තනි තේරීමකට ඉඩ දීම සඳහා මත විමසුම වෙනස් කරන්න",
-  "compose_form.publish": "ප්‍රකාශ කරන්න",
+  "compose_form.publish": "ප්‍රකාශනය",
   "compose_form.publish_loud": "{publish}!",
   "compose_form.save_changes": "වෙනස්කම් සුරකින්න",
   "compose_form.sensitive.hide": "{count, plural, one {මාධ්ය සංවේදී ලෙස සලකුණු කරන්න} other {මාධ්ය සංවේදී ලෙස සලකුණු කරන්න}}",
@@ -115,11 +116,11 @@
   "compose_form.sensitive.unmarked": "{count, plural, one {මාධ්‍ය සංවේදී ලෙස සලකුණු කර නැත} other {මාධ්‍ය සංවේදී ලෙස සලකුණු කර නැත}}",
   "compose_form.spoiler.marked": "අනතුරු ඇඟවීම පිටුපස පෙළ සඟවා ඇත",
   "compose_form.spoiler.unmarked": "ප්‍රයෝජනය සඟවා නැත",
-  "compose_form.spoiler_placeholder": "ඔබගේ අවවාදය මෙහි ලියන්න",
+  "compose_form.spoiler_placeholder": "අවවාදය මෙහි ලියන්න",
   "confirmation_modal.cancel": "අවලංගු",
   "confirmations.block.block_and_report": "අවහිර කර වාර්තා කරන්න",
   "confirmations.block.confirm": "අවහිර",
-  "confirmations.block.message": "ඔබට {name} අවහිර කිරීමට අවශ්‍ය බව ද?",
+  "confirmations.block.message": "ඔබට {name} අවහිර කිරීමට වුවමනා ද?",
   "confirmations.delete.confirm": "මකන්න",
   "confirmations.delete.message": "ඔබට මෙම තත්ත්වය මැකීමට අවශ්‍ය බව විශ්වාසද?",
   "confirmations.delete_list.confirm": "මකන්න",
@@ -140,23 +141,23 @@
   "confirmations.unfollow.confirm": "අනුගමනය නොකරන්න",
   "confirmations.unfollow.message": "ඔබට {name}අනුගමනය නොකිරීමට අවශ්‍ය බව විශ්වාසද?",
   "conversation.delete": "සංවාදය මකන්න",
-  "conversation.mark_as_read": "කියවූ ලෙස සලකුණු කරන්න",
+  "conversation.mark_as_read": "කියවූ බව යොදන්න",
   "conversation.open": "සංවාදය බලන්න",
   "conversation.with": "{names} සමඟ",
   "directory.federated": "දන්නා fediverse වලින්",
-  "directory.local": "{domain} පමණි",
+  "directory.local": "{domain} වෙතින් පමණි",
   "directory.new_arrivals": "නව පැමිණීම්",
-  "directory.recently_active": "මෑතකදී ක්රියාකාරී",
+  "directory.recently_active": "මෑත දී සක්‍රියයි",
   "embed.instructions": "පහත කේතය පිටපත් කිරීමෙන් මෙම තත්ත්වය ඔබේ වෙබ් අඩවියට ඇතුළත් කරන්න.",
   "embed.preview": "එය පෙනෙන්නේ කෙසේද යන්න මෙන්න:",
   "emoji_button.activity": "ක්‍රියාකාරකම",
-  "emoji_button.clear": "පැහැදිලිව",
+  "emoji_button.clear": "මකන්න",
   "emoji_button.custom": "අභිරුචි",
   "emoji_button.flags": "කොඩි",
   "emoji_button.food": "ආහාර සහ පාන",
-  "emoji_button.label": "ඉමොජි ඇතුළු කරන්න",
+  "emoji_button.label": "ඉමොජි යොදන්න",
   "emoji_button.nature": "ස්වභාවික",
-  "emoji_button.not_found": "ගැළපෙන ඉමෝජි හමු නොවීය",
+  "emoji_button.not_found": "ගැළපෙන ඉමෝජි හමු නොවිණි",
   "emoji_button.objects": "වස්තූන්",
   "emoji_button.people": "මිනිසුන්",
   "emoji_button.recent": "නිතර භාවිතා වූ",
@@ -166,12 +167,12 @@
   "emoji_button.travel": "චාරිකා සහ ස්ථාන",
   "empty_column.account_suspended": "ගිණුම අත්හිටුවා ඇත",
   "empty_column.account_timeline": "මෙහි දත් නැත!",
-  "empty_column.account_unavailable": "පැතිකඩ නොමැත",
-  "empty_column.blocks": "ඔබ තවමත් කිසිදු පරිශීලකයෙකු අවහිර කර නැත.",
+  "empty_column.account_unavailable": "පැතිකඩ නොතිබේ",
+  "empty_column.blocks": "කිසිදු පරිශීලකයෙකු අවහිර කර නැත.",
   "empty_column.bookmarked_statuses": "ඔබට තවමත් පිටු සලකුණු කළ මෙවලම් කිසිවක් නොමැත. ඔබ එකක් පිටු සලකුණු කළ විට, එය මෙහි පෙන්වනු ඇත.",
   "empty_column.community": "දේශීය කාලරේඛාව හිස් ය. පන්දුව පෙරළීමට ප්‍රසිද්ධියේ යමක් ලියන්න!",
   "empty_column.direct": "ඔබට තවමත් සෘජු පණිවිඩ කිසිවක් නොමැත. ඔබ එකක් යවන විට හෝ ලැබුණු විට, එය මෙහි පෙන්වනු ඇත.",
-  "empty_column.domain_blocks": "අවහිර කළ වසම් නොමැත.",
+  "empty_column.domain_blocks": "අවහිර කරන ලද වසම් නැත.",
   "empty_column.explore_statuses": "දැන් කිසිවක් නැඹුරු නොවේ. පසුව නැවත පරීක්ෂා කරන්න!",
   "empty_column.favourited_statuses": "ඔබට තවමත් ප්‍රියතම දත් කිසිවක් නැත. ඔබ කැමති එකක් වූ විට, එය මෙහි පෙන්වනු ඇත.",
   "empty_column.favourites": "කිසිවෙකු තවමත් මෙම මෙවලමට ප්‍රිය කර නැත. යමෙකු එසේ කළ විට, ඔවුන් මෙහි පෙන්වනු ඇත.",
@@ -190,50 +191,50 @@
   "error.unexpected_crash.next_steps": "පිටුව නැවුම් කිරීමට උත්සාහ කරන්න. එය උදව් නොකළහොත්, ඔබට තවමත් වෙනත් බ්‍රවුසරයක් හෝ ස්වදේශීය යෙදුමක් හරහා Mastodon භාවිත කිරීමට හැකි වේ.",
   "error.unexpected_crash.next_steps_addons": "ඒවා අක්‍රිය කර පිටුව නැවුම් කිරීමට උත්සාහ කරන්න. එය උදව් නොකළහොත්, ඔබට තවමත් වෙනත් බ්‍රවුසරයක් හෝ ස්වදේශීය යෙදුමක් හරහා Mastodon භාවිත කිරීමට හැකි වේ.",
   "errors.unexpected_crash.copy_stacktrace": "ස්ටැක්ට්රේස් පසුරු පුවරුවට පිටපත් කරන්න",
-  "errors.unexpected_crash.report_issue": "ගැටලුව වාර්තා කරන්න",
+  "errors.unexpected_crash.report_issue": "ගැටළුව වාර්තාව",
   "explore.search_results": "සෙවුම් ප්‍රතිඵල",
-  "explore.suggested_follows": "ඔයා වෙනුවෙන්",
-  "explore.title": "ගවේෂණය කරන්න",
+  "explore.suggested_follows": "ඔබට",
+  "explore.title": "ගවේශණය",
   "explore.trending_links": "පුවත්",
-  "explore.trending_statuses": "තනතුරු",
+  "explore.trending_statuses": "ලිපි",
   "explore.trending_tags": "හැෂ් ටැග්",
   "filter_modal.added.context_mismatch_explanation": "This filter category does not apply to the context in which you have accessed this post. If you want the post to be filtered in this context too, you will have to edit the filter.",
   "filter_modal.added.context_mismatch_title": "Context mismatch!",
   "filter_modal.added.expired_explanation": "This filter category has expired, you will need to change the expiration date for it to apply.",
-  "filter_modal.added.expired_title": "Expired filter!",
+  "filter_modal.added.expired_title": "පෙරහන ඉකුත්ය!",
   "filter_modal.added.review_and_configure": "To review and further configure this filter category, go to the {settings_link}.",
-  "filter_modal.added.review_and_configure_title": "Filter settings",
-  "filter_modal.added.settings_link": "settings page",
+  "filter_modal.added.review_and_configure_title": "පෙරහන් සැකසුම්",
+  "filter_modal.added.settings_link": "සැකසුම් පිටුව",
   "filter_modal.added.short_explanation": "This post has been added to the following filter category: {title}.",
   "filter_modal.added.title": "Filter added!",
   "filter_modal.select_filter.context_mismatch": "does not apply to this context",
-  "filter_modal.select_filter.expired": "expired",
-  "filter_modal.select_filter.prompt_new": "New category: {name}",
-  "filter_modal.select_filter.search": "Search or create",
+  "filter_modal.select_filter.expired": "ඉකුත්ය",
+  "filter_modal.select_filter.prompt_new": "නව ප්‍රවර්ගය: {name}",
+  "filter_modal.select_filter.search": "සොයන්න හෝ සාදන්න",
   "filter_modal.select_filter.subtitle": "Use an existing category or create a new one",
   "filter_modal.select_filter.title": "Filter this post",
   "filter_modal.title.status": "Filter a post",
-  "follow_recommendations.done": "කළා",
+  "follow_recommendations.done": "අහවරයි",
   "follow_recommendations.heading": "ඔබ පළ කිරීම් බැලීමට කැමති පුද්ගලයින් අනුගමනය කරන්න! මෙන්න යෝජනා කිහිපයක්.",
   "follow_recommendations.lead": "ඔබ අනුගමන කරන පුද්ගලයින්ගේ පළ කිරීම් ඔබගේ නිවසේ සංග්‍රහයේ කාලානුක්‍රමික අනුපිළිවෙලට පෙන්වනු ඇත. වැරදි කිරීමට බිය නොවන්න, ඔබට ඕනෑම වේලාවක පහසුවෙන් මිනිසුන් අනුගමනය කළ නොහැක!",
   "follow_request.authorize": "අවසරලත්",
-  "follow_request.reject": "ප්රතික්ෂේප",
+  "follow_request.reject": "ප්‍රතික්‍ෂේප",
   "follow_requests.unlocked_explanation": "ඔබගේ ගිණුම අගුලු දමා නොතිබුණද, {domain} කාර්ය මණ්ඩලය සිතුවේ ඔබට මෙම ගිණුම් වලින් ලැබෙන ඉල්ලීම් හස්තීයව සමාලෝචනය කිරීමට අවශ්‍ය විය හැකි බවයි.",
   "generic.saved": "සුරැකිණි",
   "getting_started.developers": "සංවර්ධකයින්",
   "getting_started.directory": "පැතිකඩ නාමාවලිය",
   "getting_started.documentation": "ප්‍රලේඛනය",
-  "getting_started.heading": "ඇරඹේ",
-  "getting_started.invite": "මිනිසුන්ට ආරාධනා කරන්න",
+  "getting_started.heading": "පටන් ගන්න",
+  "getting_started.invite": "මිනිසුන්ට ආරාධනය",
   "getting_started.open_source_notice": "Mastodon යනු විවෘත කේත මෘදුකාංගයකි. ඔබට GitHub හි {github}ට දායක වීමට හෝ ගැටළු වාර්තා කිරීමට හැකිය.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "ගිණුමේ සැකසුම්",
-  "getting_started.terms": "සේවාවේ කොන්දේසි",
   "hashtag.column_header.tag_mode.all": "සහ {additional}",
   "hashtag.column_header.tag_mode.any": "හෝ {additional}",
   "hashtag.column_header.tag_mode.none": "{additional}නොමැතිව",
-  "hashtag.column_settings.select.no_options_message": "යෝජනා කිසිවක් හමු නොවිණි",
+  "hashtag.column_settings.select.no_options_message": "යෝජනා හමු නොවිණි",
   "hashtag.column_settings.select.placeholder": "හැෂ් ටැග්…ඇතුලත් කරන්න",
-  "hashtag.column_settings.tag_mode.all": "මේ වගේ",
+  "hashtag.column_settings.tag_mode.all": "මේ සියල්ලම",
   "hashtag.column_settings.tag_mode.any": "ඇතුළත් එකක්",
   "hashtag.column_settings.tag_mode.none": "මේ කිසිවක් නැත",
   "hashtag.column_settings.tag_toggle": "මෙම තීරුවේ අමතර ටැග් ඇතුළත් කරන්න",
@@ -242,13 +243,13 @@
   "hashtag.unfollow": "Unfollow hashtag",
   "home.column_settings.basic": "මූලික",
   "home.column_settings.show_reblogs": "බූස්ට් පෙන්වන්න",
-  "home.column_settings.show_replies": "ප්රතිචාර පෙන්වන්න",
+  "home.column_settings.show_replies": "පිළිතුරු පෙන්වන්න",
   "home.hide_announcements": "නිවේදන සඟවන්න",
   "home.show_announcements": "නිවේදන පෙන්වන්න",
   "intervals.full.days": "{number, plural, one {# දින} other {# දින}}",
   "intervals.full.hours": "{number, plural, one {# පැය} other {# පැය}}",
   "intervals.full.minutes": "{number, plural, one {විනාඩි #} other {# මිනිත්තු}}",
-  "keyboard_shortcuts.back": "ආපසු සැරිසැරීමට",
+  "keyboard_shortcuts.back": "ආපසු යාත්‍රණය",
   "keyboard_shortcuts.blocked": "අවහිර කළ පරිශීලක ලැයිස්තුව විවෘත කිරීමට",
   "keyboard_shortcuts.boost": "වැඩි කිරීමට",
   "keyboard_shortcuts.column": "එක් තීරුවක තත්ත්වය නාභිගත කිරීමට",
@@ -262,23 +263,23 @@
   "keyboard_shortcuts.federated": "ෆෙඩරේටඩ් කාලරාමුව විවෘත කිරීමට",
   "keyboard_shortcuts.heading": "යතුරුපුවරු කෙටිමං",
   "keyboard_shortcuts.home": "නිවසේ කාලරේඛාව විවෘත කිරීමට",
-  "keyboard_shortcuts.hotkey": "උණුසුම් යතුර",
+  "keyboard_shortcuts.hotkey": "උණු යතුර",
   "keyboard_shortcuts.legend": "මෙම පුරාවෘත්තය ප්රදර්ශනය කිරීමට",
   "keyboard_shortcuts.local": "දේශීය කාලරේඛාව විවෘත කිරීමට",
   "keyboard_shortcuts.mention": "කතුවරයා සඳහන් කිරීමට",
   "keyboard_shortcuts.muted": "නිශ්ශබ්ද පරිශීලක ලැයිස්තුව විවෘත කිරීමට",
-  "keyboard_shortcuts.my_profile": "ඔබගේ පැතිකඩ විවෘත කිරීමට",
+  "keyboard_shortcuts.my_profile": "ඔබගේ පැතිකඩ අරින්න",
   "keyboard_shortcuts.notifications": "දැනුම්දීම් තීරුව විවෘත කිරීමට",
-  "keyboard_shortcuts.open_media": "මාධ්‍ය විවෘත කිරීමට",
+  "keyboard_shortcuts.open_media": "මාධ්‍ය අරින්න",
   "keyboard_shortcuts.pinned": "පින් කළ මෙවලම් ලැයිස්තුව විවෘත කිරීමට",
-  "keyboard_shortcuts.profile": "කර්තෘගේ පැතිකඩ විවෘත කිරීමට",
+  "keyboard_shortcuts.profile": "කතෘගේ පැතිකඩ අරින්න",
   "keyboard_shortcuts.reply": "පිළිතුරු දීමට",
   "keyboard_shortcuts.requests": "පහත ඉල්ලීම් ලැයිස්තුව විවෘත කිරීමට",
   "keyboard_shortcuts.search": "සෙවුම් අවධානය යොමු කිරීමට",
   "keyboard_shortcuts.spoilers": "CW ක්ෂේත්‍රය පෙන්වීමට/සැඟවීමට",
-  "keyboard_shortcuts.start": "\"ආරම්භ කරන්න\" තීරුව විවෘත කිරීමට",
+  "keyboard_shortcuts.start": "\"පටන් ගන්න\" තීරුව අරින්න",
   "keyboard_shortcuts.toggle_hidden": "CW පිටුපස පෙළ පෙන්වීමට/සැඟවීමට",
-  "keyboard_shortcuts.toggle_sensitivity": "මාධ්‍ය පෙන්වීමට/සැඟවීමට",
+  "keyboard_shortcuts.toggle_sensitivity": "මාධ්‍ය පෙන්වන්න/සඟවන්න",
   "keyboard_shortcuts.toot": "අලුත්ම ටූට් එකක් පටන් ගන්න",
   "keyboard_shortcuts.unfocus": "අවධානය යොමු නොකිරීමට textarea/search රචනා කරන්න",
   "keyboard_shortcuts.up": "ලැයිස්තුවේ ඉහළට යාමට",
@@ -289,10 +290,10 @@
   "lightbox.previous": "පෙර",
   "limited_account_hint.action": "කෙසේ හෝ පැතිකඩ පෙන්වන්න",
   "limited_account_hint.title": "මෙම පැතිකඩ ඔබගේ සේවාදායකයේ පරිපාලකයින් විසින් සඟවා ඇත.",
-  "lists.account.add": "ලැයිස්තුවට එකතු කරන්න",
-  "lists.account.remove": "ලැයිස්තුවෙන් ඉවත්",
-  "lists.delete": "ලැයිස්තුව මකන්න",
-  "lists.edit": "ලැයිස්තුව සංස්කරණය කරන්න",
+  "lists.account.add": "ලේඛනයට දමන්න",
+  "lists.account.remove": "ලේඛනයෙන් ඉවතලන්න",
+  "lists.delete": "ලේඛනය මකන්න",
+  "lists.edit": "ලේඛනය සංස්කරණය",
   "lists.edit.submit": "මාතෘකාව වෙනස් කරන්න",
   "lists.new.create": "ලැයිස්තුව එකතු කරන්න",
   "lists.new.title_placeholder": "නව ලැයිස්තු මාතෘකාව",
@@ -301,37 +302,37 @@
   "lists.replies_policy.none": "කිසිවෙක් නැත",
   "lists.replies_policy.title": "පිළිතුරු පෙන්වන්න:",
   "lists.search": "ඔබ අනුගමනය කරන පුද්ගලයින් අතර සොයන්න",
-  "lists.subheading": "ඔබේ ලැයිස්තු",
+  "lists.subheading": "ඔබගේ ලේඛන",
   "load_pending": "{count, plural, one {# නව අයිතමයක්} other {නව අයිතම #ක්}}",
   "loading_indicator.label": "පූරණය වෙමින්...",
   "media_gallery.toggle_visible": "{number, plural, one {රූපය සඟවන්න} other {පින්තූර සඟවන්න}}",
-  "missing_indicator.label": "හමු වුණේ නැහැ",
-  "missing_indicator.sublabel": "මෙම සම්පත සොයාගත නොහැකි විය",
-  "mute_modal.duration": "කාල සීමාව",
+  "missing_indicator.label": "හමු නොවිණි",
+  "missing_indicator.sublabel": "මෙම සම්පත හමු නොවිණි",
+  "mute_modal.duration": "පරාසය",
   "mute_modal.hide_notifications": "මෙම පරිශීලකයාගෙන් දැනුම්දීම් සඟවන්නද?",
   "mute_modal.indefinite": "අවිනිශ්චිත",
   "navigation_bar.apps": "ජංගම යෙදුම්",
-  "navigation_bar.blocks": "අවහිර කළ පරිශීලකයින්",
-  "navigation_bar.bookmarks": "පොත් යොමු කරන්න",
+  "navigation_bar.blocks": "අවහිර කළ අය",
+  "navigation_bar.bookmarks": "පොත්යොමු",
   "navigation_bar.community_timeline": "දේශීය කාලරේඛාව",
   "navigation_bar.compose": "නව ටූට් සාදන්න",
   "navigation_bar.direct": "සෘජු පණිවිඩ",
   "navigation_bar.discover": "සොයා ගන්න",
-  "navigation_bar.domain_blocks": "සැඟවුණු වසම්",
+  "navigation_bar.domain_blocks": "අවහිර කළ වසම්",
   "navigation_bar.edit_profile": "පැතිකඩ සංස්කරණය",
   "navigation_bar.explore": "ගවේෂණය කරන්න",
   "navigation_bar.favourites": "ප්‍රියතමයන්",
-  "navigation_bar.filters": "සමඟ කළ වචන",
-  "navigation_bar.follow_requests": "ඉල්ලීම් අනුගමනය කරන්න",
-  "navigation_bar.follows_and_followers": "අනුගාමිකයින් සහ අනුගාමිකයින්",
-  "navigation_bar.info": "මෙම සේවාදායකය පිළිබඳව",
-  "navigation_bar.keyboard_shortcuts": "උණුසුම් යතුරු",
-  "navigation_bar.lists": "ලැයිස්තු",
+  "navigation_bar.filters": "නිහඬ කළ වචන",
+  "navigation_bar.follow_requests": "අනුගමන ඉල්ලීම්",
+  "navigation_bar.follows_and_followers": "අනුගමනය හා අනුගාමිකයින්",
+  "navigation_bar.info": "මෙම සේවාදායකය ගැන",
+  "navigation_bar.keyboard_shortcuts": "උණු යතුරු",
+  "navigation_bar.lists": "ලේඛන",
   "navigation_bar.logout": "නික්මෙන්න",
-  "navigation_bar.mutes": "නිශ්ශබ්ද පරිශීලකයන්",
+  "navigation_bar.mutes": "නිහඬ කළ අය",
   "navigation_bar.personal": "පුද්ගලික",
-  "navigation_bar.pins": "ඇලවූ දත්",
-  "navigation_bar.preferences": "මනාප",
+  "navigation_bar.pins": "ඇමිණූ ලිපි",
+  "navigation_bar.preferences": "අභිප්‍රේත",
   "navigation_bar.public_timeline": "ෆෙඩරේටඩ් කාලරේඛාව",
   "navigation_bar.security": "ආරක්ෂාව",
   "notification.admin.report": "{name} වාර්තා {target}",
@@ -340,46 +341,46 @@
   "notification.follow": "{name} ඔබව අනුගමනය කළා",
   "notification.follow_request": "{name} ඔබව අනුගමනය කිරීමට ඉල්ලා ඇත",
   "notification.mention": "{name} ඔබව සඳහන් කර ඇත",
-  "notification.own_poll": "ඔබේ මත විමසුම අවසන් වී ඇත",
-  "notification.poll": "ඔබ ඡන්දය දුන් මත විමසුමක් අවසන් වී ඇත",
+  "notification.own_poll": "ඔබගේ මත විමසුම නිමයි",
+  "notification.poll": "ඔබ ඡන්දය දුන් මත විමසුමක් නිමයි",
   "notification.reblog": "{name} ඔබේ තත්ත්වය ඉහළ නැංවීය",
   "notification.status": "{name} දැන් පළ කළා",
   "notification.update": "{name} පළ කිරීමක් සංස්කරණය කළා",
-  "notifications.clear": "දැනුම්දීම් හිස්කරන්න",
+  "notifications.clear": "දැනුම්දීම් මකන්න",
   "notifications.clear_confirmation": "ඔබට ඔබගේ සියලු දැනුම්දීම් ස්ථිරවම හිස් කිරීමට අවශ්‍ය බව විශ්වාසද?",
   "notifications.column_settings.admin.report": "නව වාර්තා:",
-  "notifications.column_settings.admin.sign_up": "නව ලියාපදිංචි කිරීම්:",
-  "notifications.column_settings.alert": "ඩෙස්ක්ටොප් දැනුම්දීම්",
+  "notifications.column_settings.admin.sign_up": "නව ලියාපදිංචි:",
+  "notifications.column_settings.alert": "වැඩතල දැනුම්දීම්",
   "notifications.column_settings.favourite": "ප්‍රියතමයන්:",
-  "notifications.column_settings.filter_bar.advanced": "සියලුම කාණ්ඩ පෙන්වන්න",
+  "notifications.column_settings.filter_bar.advanced": "සියළු ප්‍රවර්ග පෙන්වන්න",
   "notifications.column_settings.filter_bar.category": "ඉක්මන් පෙරහන් තීරුව",
   "notifications.column_settings.filter_bar.show_bar": "පෙරහන් තීරුව පෙන්වන්න",
   "notifications.column_settings.follow": "නව අනුගාමිකයින්:",
-  "notifications.column_settings.follow_request": "නව පහත ඉල්ලීම්:",
+  "notifications.column_settings.follow_request": "නව අනුගමන ඉල්ලීම්:",
   "notifications.column_settings.mention": "සැඳහුම්:",
   "notifications.column_settings.poll": "ඡන්ද ප්‍රතිඵල:",
   "notifications.column_settings.push": "තල්ලු දැනුම්දීම්",
   "notifications.column_settings.reblog": "තල්ලු කිරීම්:",
   "notifications.column_settings.show": "තීරුවෙහි පෙන්වන්න",
-  "notifications.column_settings.sound": "ශබ්දය සිදු කරන ලදී",
-  "notifications.column_settings.status": "නව දත්:",
+  "notifications.column_settings.sound": "ශබ්දය වාදනය",
+  "notifications.column_settings.status": "නව ලිපි:",
   "notifications.column_settings.unread_notifications.category": "නොකියවූ දැනුම්දීම්",
   "notifications.column_settings.unread_notifications.highlight": "නොකියවූ දැනුම්දීම් ඉස්මතු කරන්න",
-  "notifications.column_settings.update": "සංස්කරණ:",
+  "notifications.column_settings.update": "සංශෝධන:",
   "notifications.filter.all": "සියල්ල",
   "notifications.filter.boosts": "බූස්ට් කරයි",
   "notifications.filter.favourites": "ප්‍රියතමයන්",
-  "notifications.filter.follows": "පහත සඳහන්",
+  "notifications.filter.follows": "අනුගමනය",
   "notifications.filter.mentions": "සැඳහුම්",
   "notifications.filter.polls": "ඡන්ද ප්‍රතිඵල",
   "notifications.filter.statuses": "ඔබ අනුගමනය කරන පුද්ගලයින්ගෙන් යාවත්කාලීන",
   "notifications.grant_permission": "අවසර දෙන්න.",
   "notifications.group": "දැනුම්දීම් {count}",
-  "notifications.mark_as_read": "දැනුම්දීමක්ම කියවූ ලෙස සලකුණු කරන්න",
+  "notifications.mark_as_read": "සියළු දැනුම්දීම් කියවූ බව යොදන්න",
   "notifications.permission_denied": "කලින් ප්‍රතික්ෂේප කළ බ්‍රවුසර අවසර ඉල්ලීම හේතුවෙන් ඩෙස්ක්ටොප් දැනුම්දීම් නොමැත",
   "notifications.permission_denied_alert": "බ්‍රවුසර අවසරය පෙර ප්‍රතික්ෂේප කර ඇති බැවින්, ඩෙස්ක්ටොප් දැනුම්දීම් සබල කළ නොහැක",
   "notifications.permission_required": "අවශ්‍ය අවසරය ලබා දී නොමැති නිසා ඩෙස්ක්ටොප් දැනුම්දීම් නොමැත.",
-  "notifications_permission_banner.enable": "ඩෙස්ක්ටොප් දැනුම්දීම් සබල කරන්න",
+  "notifications_permission_banner.enable": "වැඩතල දැනුම්දීම් සබල කරන්න",
   "notifications_permission_banner.how_to_control": "Mastodon විවෘතව නොමැති විට දැනුම්දීම් ලබා ගැනීමට, ඩෙස්ක්ටොප් දැනුම්දීම් සබල කරන්න. ඔබට ඒවා සක්‍රිය කළ පසු ඉහත {icon} බොත්තම හරහා ඩෙස්ක්ටොප් දැනුම්දීම් ජනනය කරන්නේ කුමන ආකාරයේ අන්තර්ක්‍රියාද යන්න නිවැරදිව පාලනය කළ හැක.",
   "notifications_permission_banner.title": "කිසිම දෙයක් අතපසු කරන්න එපා",
   "picture_in_picture.restore": "ආපහු දාන්න",
@@ -387,59 +388,59 @@
   "poll.refresh": "නැවුම් කරන්න",
   "poll.total_people": "{count, plural, one {# පුද්ගලයා} other {# මහජන}}",
   "poll.total_votes": "{count, plural, one {# ඡන්දය} other {ඡන්ද #}}",
-  "poll.vote": "මනාපය",
+  "poll.vote": "ඡන්දය",
   "poll.voted": "ඔබ මෙම පිළිතුරට ඡන්දය දුන්නා",
   "poll.votes": "{votes, plural, one {# ඡන්දය} other {ඡන්ද #}}",
-  "poll_button.add_poll": "මත විමසුමක් එක් කරන්න",
-  "poll_button.remove_poll": "ඡන්ද විමසීම ඉවත් කරන්න",
-  "privacy.change": "තත්ත්‍වයේ පෞද්ගලිකත්වය සීරුමාරු කරන්න",
-  "privacy.direct.long": "සඳහන් කළ පරිශීලකයින් සඳහා පමණක් දෘශ්‍යමාන වේ",
-  "privacy.direct.short": "සඳහන් කළ පුද්ගලයන් පමණි",
-  "privacy.private.long": "අනුගාමිකයින් සඳහා පමණක් දෘශ්‍යමාන වේ",
+  "poll_button.add_poll": "මත විමසුමක් යොදන්න",
+  "poll_button.remove_poll": "මත විමසුම ඉවතලන්න",
+  "privacy.change": "ලිපියේ රහස්‍යතාව සංශෝධනය",
+  "privacy.direct.long": "සඳහන් කළ අයට දිස්වෙයි",
+  "privacy.direct.short": "සඳහන් කළ අයට පමණි",
+  "privacy.private.long": "අනුගාමිකයින්ට දිස්වේ",
   "privacy.private.short": "අනුගාමිකයින් පමණි",
-  "privacy.public.long": "සැමට දෘශ්‍යමානයි",
-  "privacy.public.short": "ප්රසිද්ධ",
+  "privacy.public.long": "සැමට දිස්වෙයි",
+  "privacy.public.short": "ප්‍රසිද්ධ",
   "privacy.unlisted.long": "සැමට දෘශ්‍යමාන, නමුත් සොයාගැනීමේ විශේෂාංග වලින් ඉවත් විය",
   "privacy.unlisted.short": "ලැයිස්තුගත නොකළ",
   "refresh": "නැවුම් කරන්න",
   "regeneration_indicator.label": "පූරණය වෙමින්…",
   "regeneration_indicator.sublabel": "ඔබේ නිවසේ පෝෂණය සූදානම් වෙමින් පවතී!",
-  "relative_time.days": "{number}d",
+  "relative_time.days": "ද. {number}",
   "relative_time.full.days": "{number, plural, one {# දින} other {# දින}} පෙර",
-  "relative_time.full.hours": "{number, plural, one {# පැය} other {# පැය}} පෙර",
+  "relative_time.full.hours": "{number, plural, one {පැය #} other {පැය #}} කට පෙර",
   "relative_time.full.just_now": "මේ දැන්",
-  "relative_time.full.minutes": "{number, plural, one {විනාඩි #} other {# මිනිත්තු}} පෙර",
-  "relative_time.full.seconds": "{number, plural, one {# දෙවැනි} other {# තත්පර}} පෙර",
+  "relative_time.full.minutes": "{number, plural, one {විනාඩි #} other {විනාඩි #}} කට පෙර",
+  "relative_time.full.seconds": "{number, plural, one {තත්පර #} other {තත්පර #}} කට පෙර",
   "relative_time.hours": "පැය {number}",
   "relative_time.just_now": "දැන්",
-  "relative_time.minutes": "මීටර් {number}",
-  "relative_time.seconds": "{number}තත්",
+  "relative_time.minutes": "වි. {number}",
+  "relative_time.seconds": "තත්. {number}",
   "relative_time.today": "අද",
   "reply_indicator.cancel": "අවලංගු කරන්න",
-  "report.block": "අවහිර කරන්න",
+  "report.block": "අවහිර",
   "report.block_explanation": "ඔබට ඔවුන්ගේ පෝස්ට් නොපෙනේ. ඔවුන්ට ඔබේ පළ කිරීම් බැලීමට හෝ ඔබව අනුගමනය කිරීමට නොහැකි වනු ඇත. ඔවුන් අවහිර කර ඇති බව ඔවුන්ට පැවසිය හැකිය.",
   "report.categories.other": "වෙනත්",
-  "report.categories.spam": "ආයාචිත තැපැල්",
+  "report.categories.spam": "ආයාචිත",
   "report.categories.violation": "අන්තර්ගතය සේවාදායක නීති එකක් හෝ කිහිපයක් උල්ලංඝනය කරයි",
   "report.category.subtitle": "හොඳම ගැලපීම තෝරන්න",
   "report.category.title": "මෙම {type}සමඟ සිදුවන්නේ කුමක්දැයි අපට කියන්න",
   "report.category.title_account": "පැතිකඩ",
   "report.category.title_status": "තැපැල්",
-  "report.close": "කළා",
+  "report.close": "අහවරයි",
   "report.comment.title": "අප දැනගත යුතු යැයි ඔබ සිතන තවත් යමක් තිබේද?",
-  "report.forward": "{target}වෙත යොමු කරන්න",
+  "report.forward": "{target} වෙත හරවන්න",
   "report.forward_hint": "ගිණුම වෙනත් සේවාදායකයකින්. වාර්තාවේ නිර්නාමික පිටපතක් එතනටත් එවන්න?",
-  "report.mute": "නිහඬ කරන්න",
+  "report.mute": "නිහඬ",
   "report.mute_explanation": "ඔබට ඔවුන්ගේ පෝස්ට් නොපෙනේ. ඔවුන්ට තවමත් ඔබව අනුගමනය කිරීමට සහ ඔබේ පළ කිරීම් දැකීමට හැකි අතර ඒවා නිශ්ශබ්ද කර ඇති බව නොදැනේ.",
   "report.next": "ඊළඟ",
   "report.placeholder": "අමතර අදහස්",
-  "report.reasons.dislike": "මම ඒකට කැමති නැහැ",
+  "report.reasons.dislike": "මම එයට අකැමතියි",
   "report.reasons.dislike_description": "ඒක බලන්න ඕන දෙයක් නෙවෙයි",
   "report.reasons.other": "ඒක වෙන දෙයක්",
   "report.reasons.other_description": "ගැටළුව වෙනත් වර්ග වලට නොගැලපේ",
-  "report.reasons.spam": "එය අයාචිත තැපැල් ය",
+  "report.reasons.spam": "එය අයාචිතයි",
   "report.reasons.spam_description": "අනිෂ්ට සබැඳි, ව්‍යාජ නියැලීම, හෝ පුනරාවර්තන පිළිතුරු",
-  "report.reasons.violation": "එය සේවාදායක නීති උල්ලංඝනය කරයි",
+  "report.reasons.violation": "එය සේවාදායකයේ නීති කඩ කරයි",
   "report.reasons.violation_description": "එය නිශ්චිත නීති කඩ කරන බව ඔබ දන්නවා",
   "report.rules.subtitle": "අදාළ සියල්ල තෝරන්න",
   "report.rules.title": "කුමන නීති උල්ලංඝනය කරන්නේද?",
@@ -449,14 +450,14 @@
   "report.target": "වාර්තාව {target}",
   "report.thanks.take_action": "Mastodon හි ඔබ දකින දේ පාලනය කිරීම සඳහා ඔබේ විකල්ප මෙන්න:",
   "report.thanks.take_action_actionable": "අපි මෙය සමාලෝචනය කරන අතරතුර, ඔබට @{name}ට එරෙහිව පියවර ගත හැක:",
-  "report.thanks.title": "මේක බලන්න ඕන නැද්ද?",
+  "report.thanks.title": "මෙය නොපෙන්විය යුතුද?",
   "report.thanks.title_actionable": "වාර්තා කිරීමට ස්තූතියි, අපි මේ ගැන සොයා බලමු.",
   "report.unfollow": "@{name}අනුගමනය නොකරන්න",
   "report.unfollow_explanation": "ඔබ මෙම ගිණුම අනුගමනය කරයි. ඔබේ නිවසේ සංග්‍රහයේ ඔවුන්ගේ පළ කිරීම් තවදුරටත් නොදැකීමට, ඒවා අනුගමනය නොකරන්න.",
   "report_notification.attached_statuses": "{count, plural, one {{count} තැපැල්} other {{count} තනතුරු}} අමුණා ඇත",
   "report_notification.categories.other": "වෙනත්",
-  "report_notification.categories.spam": "ආයාචිත තැපැල්",
-  "report_notification.categories.violation": "රීති උල්ලංඝනය කිරීම",
+  "report_notification.categories.spam": "ආයාචිත",
+  "report_notification.categories.violation": "නීතිය කඩ කිරීම",
   "report_notification.open": "විවෘත වාර්තාව",
   "search.placeholder": "සොයන්න",
   "search_popout.search_format": "උසස් සෙවුම් ආකෘතිය",
@@ -466,63 +467,73 @@
   "search_popout.tips.text": "සරල පෙළ ගැළපෙන සංදර්ශක නම්, පරිශීලක නාම සහ හැෂ් ටැග් ලබා දෙයි",
   "search_popout.tips.user": "පරිශීලක",
   "search_results.accounts": "මිනිසුන්",
-  "search_results.all": "සියලුම",
+  "search_results.all": "සියල්ල",
   "search_results.hashtags": "හැෂ් ටැග්",
   "search_results.nothing_found": "මෙම සෙවුම් පද සඳහා කිසිවක් සොයාගත නොහැකි විය",
-  "search_results.statuses": "ටූට්ස්",
+  "search_results.statuses": "ලිපි",
   "search_results.statuses_fts_disabled": "මෙම Mastodon සේවාදායකයේ ඒවායේ අන්තර්ගතය අනුව මෙවලම් සෙවීම සබල නොවේ.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {ප්රතිඵලය} other {ප්රතිපල}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "@{name}සඳහා මධ්‍යස්ථ අතුරුමුහුණත විවෘත කරන්න",
   "status.admin_status": "මධ්‍යස්ථ අතුරුමුහුණතෙහි මෙම තත්ත්වය විවෘත කරන්න",
-  "status.block": "@{name} අවහිර කරන්න",
-  "status.bookmark": "පොත් යොමුව",
+  "status.block": "@{name} අවහිර",
+  "status.bookmark": "පොත්යොමුවක්",
   "status.cancel_reblog_private": "Unboost",
   "status.cannot_reblog": "මෙම තනතුර වැඩි කළ නොහැක",
   "status.copy": "තත්වයට සබැඳිය පිටපත් කරන්න",
   "status.delete": "මකන්න",
-  "status.detailed_status": "සවිස්තරාත්මක සංවාද දසුන",
-  "status.direct": "@{name} සෘජු පණිවිඩය",
-  "status.edit": "සංස්කරණය කරන්න",
-  "status.edited": "සංස්කරණය {date}",
-  "status.edited_x_times": "සංස්කරණය කළා {count, plural, one {{count} කාලය} other {{count} වාර}}",
-  "status.embed": "එබ්බවූ",
+  "status.detailed_status": "විස්තරාත්මක සංවාද දැක්ම",
+  "status.direct": "@{name} සෘජු පණිවිඩයක්",
+  "status.edit": "සංස්කරණය",
+  "status.edited": "සංශෝධිතයි {date}",
+  "status.edited_x_times": "සංශෝධිතයි {count, plural, one {වාර {count}} other {වාර {count}}}",
+  "status.embed": "කාවැද්දූ",
   "status.favourite": "ප්‍රියතම",
   "status.filter": "Filter this post",
   "status.filtered": "පෙරන ලද",
   "status.hide": "Hide toot",
   "status.history.created": "{name} නිර්මාණය {date}",
   "status.history.edited": "{name} සංස්කරණය {date}",
-  "status.load_more": "තව පූරණය කරන්න",
-  "status.media_hidden": "මාධ්‍ය සංගුවා ඇත",
+  "status.load_more": "තව පූරණය",
+  "status.media_hidden": "මාධ්‍ය සඟවා ඇත",
   "status.mention": "@{name} සැඳහුම",
   "status.more": "තව",
-  "status.mute": "@{name} කරන්න",
-  "status.mute_conversation": "සංවාදයෙන් කරන්න",
-  "status.open": "මෙම තත්ත්වය පුළුල් කරන්න",
-  "status.pin": "පැතිකඩ මත අමුණන්න",
-  "status.pinned": "පින් කළ දත",
+  "status.mute": "@{name} නිහඬව",
+  "status.mute_conversation": "සංවාදය නිහඬව",
+  "status.open": "මෙම ලිපිය විහිදන්න",
+  "status.pin": "පැතිකඩට අමුණන්න",
+  "status.pinned": "ඇමිණූ ලිපියකි",
   "status.read_more": "තව කියවන්න",
   "status.reblog": "බූස්ට් කරන්න",
   "status.reblog_private": "මුල් දෘශ්‍යතාව සමඟ වැඩි කරන්න",
   "status.reblogged_by": "{name} වැඩි කරන ලදී",
   "status.reblogs.empty": "තාම කවුරුත් මේ toot එක boost කරලා නැහැ. යමෙකු එසේ කළ විට, ඔවුන් මෙහි පෙන්වනු ඇත.",
   "status.redraft": "මකන්න සහ නැවත කෙටුම්පත",
-  "status.remove_bookmark": "පොත්යොමුව ඉවත් කරන්න",
+  "status.remove_bookmark": "පොත්යොමුව ඉවතලන්න",
   "status.reply": "පිළිතුරු",
   "status.replyAll": "ත්‍රෙඩ් එකට පිළිතුරු දෙන්න",
-  "status.report": "@{name} වාර්තා කරන්න",
+  "status.report": "@{name} වාර්තාව",
   "status.sensitive_warning": "සංවේදී අන්තර්ගතයකි",
   "status.share": "බෙදාගන්න",
-  "status.show_filter_reason": "Show anyway",
+  "status.show_filter_reason": "කෙසේ වුවද පෙන්වන්න",
   "status.show_less": "අඩුවෙන් පෙන්වන්න",
-  "status.show_less_all": "සියල්ලටම අඩුවෙන් පෙන්වන්න",
-  "status.show_more": "තව පෙන්වන්න",
-  "status.show_more_all": "සියල්ල සඳහා තවත් පෙන්වන්න",
+  "status.show_less_all": "සියල්ල අඩුවෙන් පෙන්වන්න",
+  "status.show_more": "තවත් පෙන්වන්න",
+  "status.show_more_all": "සියල්ල වැඩියෙන් පෙන්වන්න",
+  "status.show_original": "Show original",
   "status.show_thread": "නූල් පෙන්වන්න",
-  "status.uncached_media_warning": "ලද නොහැක",
-  "status.unmute_conversation": "සංවාදය නිහඬ නොකරන්න",
-  "status.unpin": "පැතිකඩෙන් ඉවත් කරන්න",
-  "suggestions.dismiss": "යෝජනාව ඉවත ලන්න",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
+  "status.uncached_media_warning": "නොතිබේ",
+  "status.unmute_conversation": "සංවාදය නොනිහඬ",
+  "status.unpin": "පැතිකඩෙන් ගළවන්න",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "වෙනස්කම් සුරකින්න",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
+  "suggestions.dismiss": "යෝජනාව ඉවතලන්න",
   "suggestions.header": "ඔබ…ගැන උනන්දු විය හැකිය",
   "tabs_bar.federated_timeline": "ෆෙඩරල්",
   "tabs_bar.home": "මුල් පිටුව",
@@ -536,44 +547,44 @@
   "time_remaining.seconds": "{number, plural, one {# දෙවැනි} other {# තත්පර}} අත්හැරියා",
   "timeline_hint.remote_resource_not_displayed": "වෙනත් සේවාදායකයන්ගෙන් {resource} දර්ශනය නොවේ.",
   "timeline_hint.resources.followers": "අනුගාමිකයින්",
-  "timeline_hint.resources.follows": "පහත සඳහන්",
-  "timeline_hint.resources.statuses": "පැරණි දත්",
+  "timeline_hint.resources.follows": "අනුගමනය",
+  "timeline_hint.resources.statuses": "පරණ ලිපි",
   "trends.counter_by_accounts": "{count, plural, one {{counter} person} other {{counter} people}} in the past {days, plural, one {day} other {{days} days}}",
   "trends.trending_now": "දැන් ප්‍රවණතාවය",
-  "ui.beforeunload": "ඔබ Mastodon හැර ගියහොත් ඔබේ කෙටුම්පත නැති වනු ඇත.",
+  "ui.beforeunload": "ඔබ මාස්ටඩන් හැර ගියහොත් කටුපිටපත අහිමි වේ.",
   "units.short.billion": "{count}බී",
   "units.short.million": "{count}එම්",
   "units.short.thousand": "{count}කි",
-  "upload_area.title": "උඩුගත කිරීමට ඇද දමන්න",
-  "upload_button.label": "පින්තූර, වීඩියෝවක් හෝ ශ්‍රව්‍ය ගොනුවක් එක් කරන්න",
-  "upload_error.limit": "ගොනුව උඩුගත කළ හැකි සීමාවන් ඇත.",
-  "upload_error.poll": "ඡන්ද විමසීම් සමඟ ගොනු උඩුගත කිරීමට අවසර නැත.",
-  "upload_form.audio_description": "ශ්‍රවණාබාධ ඇති පුද්ගලයන් සඳහා විස්තර කරන්න",
+  "upload_area.title": "උඩුගතයට ඇද දමන්න",
+  "upload_button.label": "රූප, දෘශ්‍යක හෝ හඬපට යොදන්න",
+  "upload_error.limit": "සීමාව ඉක්මවා ඇත.",
+  "upload_error.poll": "මත විමසුම් සමඟ ගොනු යෙදීමට ඉඩ නොදේ.",
+  "upload_form.audio_description": "නොඇසෙන අය සඳහා විස්තර කරන්න",
   "upload_form.description": "දෘශ්‍යාබාධිතයන් සඳහා විස්තර කරන්න",
-  "upload_form.description_missing": "විස්තරයක් එක් කර නැත",
+  "upload_form.description_missing": "සවිස්තරයක් නැත",
   "upload_form.edit": "සංස්කරණය",
   "upload_form.thumbnail": "සිඟිති රුව වෙනස් කරන්න",
   "upload_form.undo": "මකන්න",
   "upload_form.video_description": "ශ්‍රවණාබාධ හෝ දෘශ්‍යාබාධිත පුද්ගලයන් සඳහා විස්තර කරන්න",
   "upload_modal.analyzing_picture": "පින්තූරය විශ්ලේෂණය කරමින්…",
   "upload_modal.apply": "යොදන්න",
-  "upload_modal.applying": "…යෙදීම",
-  "upload_modal.choose_image": "පින්තුරයක් තෝරාගන්න",
-  "upload_modal.description_placeholder": "කඩිසර හා හිවලෙක් කම්මැලි බල්ලා මතින් පනී",
-  "upload_modal.detect_text": "පින්තූරයෙන් හඳුනාගන්න",
+  "upload_modal.applying": "යොදමින්…",
+  "upload_modal.choose_image": "රූපයක් තෝරන්න",
+  "upload_modal.description_placeholder": "කඩිසර දුඹුරු හිවලෙක් කම්මැලි බල්ලා මතින් පනී",
+  "upload_modal.detect_text": "රූපයෙහි පෙළ අනාවරණය",
   "upload_modal.edit_media": "මාධ්‍ය සංස්කරණය",
   "upload_modal.hint": "සියලුම සිඟිති රූ මත සැම විටම දර්ශනය වන නාභි ලක්ෂ්‍යය තේරීමට පෙරදසුනෙහි රවුම ක්ලික් කරන්න හෝ අදින්න.",
   "upload_modal.preparing_ocr": "OCR…සූදානම් කරමින්",
   "upload_modal.preview_label": "පෙරදසුන ({ratio})",
   "upload_progress.label": "උඩුගත වෙමින්...",
-  "video.close": "දෘශ්‍යයක් වසන්න",
+  "video.close": "දෘශ්‍යකය වසන්න",
   "video.download": "ගොනුව බාගන්න",
   "video.exit_fullscreen": "පූර්ණ තිරයෙන් පිටවන්න",
-  "video.expand": "වීඩියෝව දිග හරින්න",
+  "video.expand": "දෘශ්‍යකය විහිදන්න",
   "video.fullscreen": "පූර්ණ තිරය",
-  "video.hide": "දෘශ්‍ය‍ය සඟවන්න",
-  "video.mute": "ශබ්දය නිශ්ශබ්ද කරන්න",
+  "video.hide": "දෘශ්‍යකය සඟවන්න",
+  "video.mute": "ශබ්දය නිහඬ",
   "video.pause": "විරාමය",
   "video.play": "ධාවනය",
-  "video.unmute": "ශබ්දය නිශ්ශබ්ද කරන්න"
+  "video.unmute": "ශබ්දය නොනිහඬ"
 }
diff --git a/app/javascript/mastodon/locales/sk.json b/app/javascript/mastodon/locales/sk.json
index 8aeb2aec6..f44495a82 100644
--- a/app/javascript/mastodon/locales/sk.json
+++ b/app/javascript/mastodon/locales/sk.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Nasleduje ťa",
   "account.hide_reblogs": "Skry vyzdvihnutia od @{name}",
   "account.joined": "Pridal/a sa v {date}",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "Vlastníctvo tohto odkazu bolo skontrolované {date}",
   "account.locked_info": "Stav súkromia pre tento účet je nastavený na zamknutý. Jeho vlastník sám prehodnocuje, kto ho môže sledovať.",
   "account.media": "Médiá",
@@ -59,7 +60,7 @@
   "alert.unexpected.title": "Ups!",
   "announcement.announcement": "Oboznámenie",
   "attachments_list.unprocessed": "(nespracované)",
-  "audio.hide": "Hide audio",
+  "audio.hide": "Skry zvuk",
   "autosuggest_hashtag.per_week": "{count} týždenne",
   "boost_modal.combo": "Nabudúce môžeš kliknúť {combo} pre preskočenie",
   "bundle_column_error.body": "Pri načítaní tohto prvku nastala nejaká chyba.",
@@ -202,12 +203,12 @@
   "filter_modal.added.expired_explanation": "This filter category has expired, you will need to change the expiration date for it to apply.",
   "filter_modal.added.expired_title": "Expired filter!",
   "filter_modal.added.review_and_configure": "To review and further configure this filter category, go to the {settings_link}.",
-  "filter_modal.added.review_and_configure_title": "Filter settings",
+  "filter_modal.added.review_and_configure_title": "Nastavenie triedenia",
   "filter_modal.added.settings_link": "settings page",
   "filter_modal.added.short_explanation": "This post has been added to the following filter category: {title}.",
-  "filter_modal.added.title": "Filter added!",
+  "filter_modal.added.title": "Triedenie pridané!",
   "filter_modal.select_filter.context_mismatch": "does not apply to this context",
-  "filter_modal.select_filter.expired": "expired",
+  "filter_modal.select_filter.expired": "vypršalo",
   "filter_modal.select_filter.prompt_new": "New category: {name}",
   "filter_modal.select_filter.search": "Search or create",
   "filter_modal.select_filter.subtitle": "Use an existing category or create a new one",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Začni tu",
   "getting_started.invite": "Pozvi ľudí",
   "getting_started.open_source_notice": "Mastodon je softvér s otvoreným kódom. Nahlásiť chyby, alebo prispievať môžeš na GitHube v {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Zabezpečenie",
-  "getting_started.terms": "Podmienky prevozu",
   "hashtag.column_header.tag_mode.all": "a {additional}",
   "hashtag.column_header.tag_mode.any": "alebo {additional}",
   "hashtag.column_header.tag_mode.none": "bez {additional}",
@@ -403,7 +404,7 @@
   "privacy.unlisted.short": "Verejne, ale nezobraziť v osi",
   "refresh": "Obnoviť",
   "regeneration_indicator.label": "Načítava sa…",
-  "regeneration_indicator.sublabel": "Vaša nástenka sa pripravuje!",
+  "regeneration_indicator.sublabel": "Tvoja domovská nástenka sa pripravuje!",
   "relative_time.days": "{number}dní",
   "relative_time.full.days": "{number, plural, one {# day} other {# days}} ago",
   "relative_time.full.hours": "{number, plural, one {# hour} other {# hours}} ago",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Could not find anything for these search terms",
   "search_results.statuses": "Príspevky",
   "search_results.statuses_fts_disabled": "Vyhľadávanie v obsahu príspevkov nieje na tomto Mastodon serveri povolené.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {výsledok} many {výsledkov} other {výsledky}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Otvor moderovacie rozhranie užívateľa @{name}",
   "status.admin_status": "Otvor tento príspevok v moderovacom rozhraní",
   "status.block": "Blokuj @{name}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Všetkým ukáž menej",
   "status.show_more": "Ukáž viac",
   "status.show_more_all": "Všetkým ukáž viac",
+  "status.show_original": "Show original",
   "status.show_thread": "Ukáž diskusné vlákno",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "Nedostupný/é",
   "status.unmute_conversation": "Prestaň si nevšímať konverzáciu",
   "status.unpin": "Odopni z profilu",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "Zavrhni návrh",
   "suggestions.header": "Mohlo by ťa zaujímať…",
   "tabs_bar.federated_timeline": "Federovaná",
diff --git a/app/javascript/mastodon/locales/sl.json b/app/javascript/mastodon/locales/sl.json
index c793d9de8..a33fb8b89 100644
--- a/app/javascript/mastodon/locales/sl.json
+++ b/app/javascript/mastodon/locales/sl.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Vam sledi",
   "account.hide_reblogs": "Skrij izpostavitve od @{name}",
   "account.joined": "Pridružen/a {date}",
+  "account.languages": "Spremeni naročene jezike",
   "account.link_verified_on": "Lastništvo te povezave je bilo preverjeno {date}",
   "account.locked_info": "Stanje zasebnosti računa je nastavljeno na zaklenjeno. Lastnik ročno pregleda, kdo ga lahko spremlja.",
   "account.media": "Mediji",
@@ -197,22 +198,22 @@
   "explore.trending_links": "Novice",
   "explore.trending_statuses": "Objave",
   "explore.trending_tags": "Ključniki",
-  "filter_modal.added.context_mismatch_explanation": "This filter category does not apply to the context in which you have accessed this post. If you want the post to be filtered in this context too, you will have to edit the filter.",
-  "filter_modal.added.context_mismatch_title": "Context mismatch!",
-  "filter_modal.added.expired_explanation": "This filter category has expired, you will need to change the expiration date for it to apply.",
-  "filter_modal.added.expired_title": "Expired filter!",
-  "filter_modal.added.review_and_configure": "To review and further configure this filter category, go to the {settings_link}.",
-  "filter_modal.added.review_and_configure_title": "Filter settings",
-  "filter_modal.added.settings_link": "settings page",
-  "filter_modal.added.short_explanation": "This post has been added to the following filter category: {title}.",
-  "filter_modal.added.title": "Filter added!",
-  "filter_modal.select_filter.context_mismatch": "does not apply to this context",
-  "filter_modal.select_filter.expired": "expired",
-  "filter_modal.select_filter.prompt_new": "New category: {name}",
-  "filter_modal.select_filter.search": "Search or create",
-  "filter_modal.select_filter.subtitle": "Use an existing category or create a new one",
-  "filter_modal.select_filter.title": "Filter this post",
-  "filter_modal.title.status": "Filter a post",
+  "filter_modal.added.context_mismatch_explanation": "Ta kategorija filtra ne velja za kontekst, v katerem ste dostopali do te objave. Če želite, da je objava filtrirana tudi v tem kontekstu, morate urediti filter.",
+  "filter_modal.added.context_mismatch_title": "Neujamanje konteksta!",
+  "filter_modal.added.expired_explanation": "Ta kategorija filtra je pretekla, morali boste spremeniti datum veljavnosti, da bo veljal še naprej.",
+  "filter_modal.added.expired_title": "Filter je pretekel!",
+  "filter_modal.added.review_and_configure": "Če želite pregledati in nadalje prilagoditi kategorijo filtra, obiščite {settings_link}.",
+  "filter_modal.added.review_and_configure_title": "Nastavitve filtra",
+  "filter_modal.added.settings_link": "stran nastavitev",
+  "filter_modal.added.short_explanation": "Ta objava je bila dodana v naslednjo kategorijo filtra: {title}.",
+  "filter_modal.added.title": "Filter dodan!",
+  "filter_modal.select_filter.context_mismatch": "ne velja za ta kontekst",
+  "filter_modal.select_filter.expired": "poteklo",
+  "filter_modal.select_filter.prompt_new": "Nova kategorija: {name}",
+  "filter_modal.select_filter.search": "Išči ali ustvari",
+  "filter_modal.select_filter.subtitle": "Uporabite obstoječo kategorijo ali ustvarite novo",
+  "filter_modal.select_filter.title": "Filtriraj to objavo",
+  "filter_modal.title.status": "Filtrirajte objave",
   "follow_recommendations.done": "Opravljeno",
   "follow_recommendations.heading": "Sledite osebam, katerih objave želite videti! Tukaj je nekaj predlogov.",
   "follow_recommendations.lead": "Objave oseb, ki jim sledite, se bodo prikazale v kronološkem zaporedju v vašem domačem viru. Ne bojte se storiti napake, osebam enako enostavno nehate slediti kadar koli!",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Kako začeti",
   "getting_started.invite": "Povabite osebe",
   "getting_started.open_source_notice": "Mastodon je odprtokodna programska oprema. Na GitHubu na {github} lahko prispevate ali poročate o napakah.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Varnost",
-  "getting_started.terms": "Pogoji uporabe",
   "hashtag.column_header.tag_mode.all": "in {additional}",
   "hashtag.column_header.tag_mode.any": "ali {additional}",
   "hashtag.column_header.tag_mode.none": "brez {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Za ta iskalni niz ni zadetkov",
   "search_results.statuses": "Objave",
   "search_results.statuses_fts_disabled": "Iskanje objav po njihovi vsebini ni omogočeno na tem strežniku Mastodon.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {rezultat} other {rezultatov}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Odpri vmesnik za moderiranje za @{name}",
   "status.admin_status": "Odpri status v vmesniku za moderiranje",
   "status.block": "Blokiraj @{name}",
@@ -487,7 +492,7 @@
   "status.edited_x_times": "Urejeno {count, plural, one {#-krat} two {#-krat} few {#-krat} other {#-krat}}",
   "status.embed": "Vgradi",
   "status.favourite": "Priljubljen",
-  "status.filter": "Filter this post",
+  "status.filter": "Filtriraj to objavo",
   "status.filtered": "Filtrirano",
   "status.hide": "Skrij tut",
   "status.history.created": "{name}: ustvarjeno {date}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Prikaži manj za vse",
   "status.show_more": "Prikaži več",
   "status.show_more_all": "Prikaži več za vse",
+  "status.show_original": "Pokaži izvirnik",
   "status.show_thread": "Prikaži objavo",
+  "status.translate": "Prevedi",
+  "status.translated_from": "Prevedeno iz jezika: {lang}",
   "status.uncached_media_warning": "Ni na voljo",
   "status.unmute_conversation": "Odtišaj pogovor",
   "status.unpin": "Odpni iz profila",
+  "subscribed_languages.lead": "Po spremembi bodo na vaši domači in seznamski časovnici prikazane objave samo v izbranih jezikih.",
+  "subscribed_languages.save": "Shrani spremembe",
+  "subscribed_languages.target": "Spremeni naročene jezike za {target}",
   "suggestions.dismiss": "Zavrni predlog",
   "suggestions.header": "Morda bi vas zanimalo…",
   "tabs_bar.federated_timeline": "Združeno",
diff --git a/app/javascript/mastodon/locales/sq.json b/app/javascript/mastodon/locales/sq.json
index 0b7fabb45..344d76344 100644
--- a/app/javascript/mastodon/locales/sq.json
+++ b/app/javascript/mastodon/locales/sq.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Ju ndjek",
   "account.hide_reblogs": "Fshih përforcime nga @{name}",
   "account.joined": "U bë pjesë më {date}",
+  "account.languages": "Ndryshoni gjuhë pajtimesh",
   "account.link_verified_on": "Pronësia e kësaj lidhjeje qe kontrolluar më {date}",
   "account.locked_info": "Gjendja e privatësisë së kësaj llogarie është caktuar si e kyçur. I zoti merr dorazi në shqyrtim cilët mund ta ndjekin.",
   "account.media": "Media",
@@ -197,22 +198,22 @@
   "explore.trending_links": "Lajme",
   "explore.trending_statuses": "Postime",
   "explore.trending_tags": "Hashtagë",
-  "filter_modal.added.context_mismatch_explanation": "This filter category does not apply to the context in which you have accessed this post. If you want the post to be filtered in this context too, you will have to edit the filter.",
-  "filter_modal.added.context_mismatch_title": "Context mismatch!",
-  "filter_modal.added.expired_explanation": "This filter category has expired, you will need to change the expiration date for it to apply.",
-  "filter_modal.added.expired_title": "Expired filter!",
-  "filter_modal.added.review_and_configure": "To review and further configure this filter category, go to the {settings_link}.",
-  "filter_modal.added.review_and_configure_title": "Filter settings",
-  "filter_modal.added.settings_link": "settings page",
-  "filter_modal.added.short_explanation": "This post has been added to the following filter category: {title}.",
-  "filter_modal.added.title": "Filter added!",
-  "filter_modal.select_filter.context_mismatch": "does not apply to this context",
-  "filter_modal.select_filter.expired": "expired",
-  "filter_modal.select_filter.prompt_new": "New category: {name}",
-  "filter_modal.select_filter.search": "Search or create",
-  "filter_modal.select_filter.subtitle": "Use an existing category or create a new one",
-  "filter_modal.select_filter.title": "Filter this post",
-  "filter_modal.title.status": "Filter a post",
+  "filter_modal.added.context_mismatch_explanation": "Kjo kategori filtrash nuk aplikohet për kontekstin nën të cilin po merreni me këtë postim. Nëse doni që postimi të filtrohet edhe në këtë kontekst, do t’ju duhet të përpunoni filtrin.",
+  "filter_modal.added.context_mismatch_title": "Mospërputhje kontekstesh!",
+  "filter_modal.added.expired_explanation": "Kjo kategori filtrash ka skaduar, do t’ju duhet të ndryshoni datën e skadimit për të, pa të aplikohet.",
+  "filter_modal.added.expired_title": "Filtër i skaduar!",
+  "filter_modal.added.review_and_configure": "Që të shqyrtoni dhe formësoni më tej këtë kategori filtrash, kaloni te {settings_link}.",
+  "filter_modal.added.review_and_configure_title": "Rregullime filtrash",
+  "filter_modal.added.settings_link": "faqe rregullimesh",
+  "filter_modal.added.short_explanation": "Ky postim është shtuar te kategoria vijuese e filtrave: {title}.",
+  "filter_modal.added.title": "U shtua filtër!",
+  "filter_modal.select_filter.context_mismatch": "mos e apliko mbi këtë kontekst",
+  "filter_modal.select_filter.expired": "ka skaduar",
+  "filter_modal.select_filter.prompt_new": "Kategori e re: {name}",
+  "filter_modal.select_filter.search": "Kërkoni, ose krijoni",
+  "filter_modal.select_filter.subtitle": "Përdorni një kategori ekzistuese, ose krijoni një të re",
+  "filter_modal.select_filter.title": "Filtroje këtë postim",
+  "filter_modal.title.status": "Filtroni një postim",
   "follow_recommendations.done": "U bë",
   "follow_recommendations.heading": "Ndiqni persona prej të cilëve doni të shihni postime! Ja ca sugjerime.",
   "follow_recommendations.lead": "Postimet prej personash që ndiqni do të shfaqen në rend kohor te prurja juaj kryesore. Mos kini frikë të bëni gabime, mund të ndalni po aq kollaj ndjekjen e dikujt, në çfarëdo kohe!",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Si t’ia fillohet",
   "getting_started.invite": "Ftoni njerëz",
   "getting_started.open_source_notice": "Mastodon-i është software me burim të hapur. Mund të jepni ndihmesë ose të njoftoni probleme në GitHub, te {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Rregullime llogarie",
-  "getting_started.terms": "Kushte shërbimi",
   "hashtag.column_header.tag_mode.all": "dhe {additional}",
   "hashtag.column_header.tag_mode.any": "ose {additional}",
   "hashtag.column_header.tag_mode.none": "pa {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "S’u gjet gjë për këto terma kërkimi",
   "search_results.statuses": "Mesazhe",
   "search_results.statuses_fts_disabled": "Kërkimi i mesazheve sipas lëndës së tyre s’është i aktivizuar në këtë shërbyes Mastodon.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {përfundim} other {përfundime}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Hap ndërfaqe moderimi për @{name}",
   "status.admin_status": "Hape këtë mesazh te ndërfaqja e moderimit",
   "status.block": "Blloko @{name}",
@@ -487,7 +492,7 @@
   "status.edited_x_times": "Përpunuar {count, plural, one {{count} herë} other {{count} herë}}",
   "status.embed": "Trupëzim",
   "status.favourite": "I parapëlqyer",
-  "status.filter": "Filter this post",
+  "status.filter": "Filtroje këtë postim",
   "status.filtered": "I filtruar",
   "status.hide": "Fshihe mesazhin",
   "status.history.created": "{name} u krijua më {date}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Shfaq më pak për të tërë",
   "status.show_more": "Shfaq më tepër",
   "status.show_more_all": "Shfaq më tepër për të tërë",
+  "status.show_original": "Shfaq origjinalin",
   "status.show_thread": "Shfaq rrjedhën",
+  "status.translate": "Përktheje",
+  "status.translated_from": "Përkthyer nga {lang}",
   "status.uncached_media_warning": "Jo e passhme",
   "status.unmute_conversation": "Ktheji zërin bisedës",
   "status.unpin": "Shfiksoje nga profili",
+  "subscribed_languages.lead": "Pas ndryshimit, te kreu juaj dhe te rrjedha kohore liste do të shfaqen vetëm postime në gjuhët e përzgjedhura. Që të merrni postime në krejt gjuhë, mos përzgjidhni gjë.",
+  "subscribed_languages.save": "Ruaji ndryshimet",
+  "subscribed_languages.target": "Ndryshoni gjuhë pajtimesh për {target}",
   "suggestions.dismiss": "Mos e merr parasysh sugjerimin",
   "suggestions.header": "Mund t’ju interesonte…",
   "tabs_bar.federated_timeline": "E federuar",
diff --git a/app/javascript/mastodon/locales/sr-Latn.json b/app/javascript/mastodon/locales/sr-Latn.json
index 8e955727d..d5aa11511 100644
--- a/app/javascript/mastodon/locales/sr-Latn.json
+++ b/app/javascript/mastodon/locales/sr-Latn.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Prati Vas",
   "account.hide_reblogs": "Sakrij podrške koje daje korisnika @{name}",
   "account.joined": "Joined {date}",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.",
   "account.media": "Mediji",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Da počnete",
   "getting_started.invite": "Invite people",
   "getting_started.open_source_notice": "Mastodont je softver otvorenog koda. Možete mu doprineti ili prijaviti probleme preko GitHub-a na {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Security",
-  "getting_started.terms": "Terms of service",
   "hashtag.column_header.tag_mode.all": "and {additional}",
   "hashtag.column_header.tag_mode.any": "or {additional}",
   "hashtag.column_header.tag_mode.none": "without {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Could not find anything for these search terms",
   "search_results.statuses": "Toots",
   "search_results.statuses_fts_disabled": "Searching toots by their content is not enabled on this Mastodon server.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {rezultat} few {rezultata} other {rezultata}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Open moderation interface for @{name}",
   "status.admin_status": "Open this status in the moderation interface",
   "status.block": "Block @{name}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Show less for all",
   "status.show_more": "Prikaži više",
   "status.show_more_all": "Show more for all",
+  "status.show_original": "Show original",
   "status.show_thread": "Show thread",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "Not available",
   "status.unmute_conversation": "Uključi prepisku",
   "status.unpin": "Otkači sa profila",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "Dismiss suggestion",
   "suggestions.header": "You might be interested in…",
   "tabs_bar.federated_timeline": "Federisano",
diff --git a/app/javascript/mastodon/locales/sr.json b/app/javascript/mastodon/locales/sr.json
index 442e7ee3d..19c79920d 100644
--- a/app/javascript/mastodon/locales/sr.json
+++ b/app/javascript/mastodon/locales/sr.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Прати Вас",
   "account.hide_reblogs": "Сакриј подршке које даје корисника @{name}",
   "account.joined": "Придружио/ла се {date}",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "Власништво над овом везом је проверено {date}",
   "account.locked_info": "Статус приватности овог налога је подешен на закључано. Власник ручно прегледа ко га може пратити.",
   "account.media": "Медији",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Да почнете",
   "getting_started.invite": "Позовите људе",
   "getting_started.open_source_notice": "Мастoдон је софтвер отвореног кода. Можете му допринети или пријавити проблеме преко ГитХаба на {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Безбедност",
-  "getting_started.terms": "Услови коришћења",
   "hashtag.column_header.tag_mode.all": "и {additional}",
   "hashtag.column_header.tag_mode.any": "или {additional}",
   "hashtag.column_header.tag_mode.none": "без {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Could not find anything for these search terms",
   "search_results.statuses": "Трубе",
   "search_results.statuses_fts_disabled": "Searching toots by their content is not enabled on this Mastodon server.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {резултат} few {резултата} other {резултата}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Отвори модераторски интерфејс за @{name}",
   "status.admin_status": "Отвори овај статус у модераторском интерфејсу",
   "status.block": "Блокирај @{name}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Прикажи мање за све",
   "status.show_more": "Прикажи више",
   "status.show_more_all": "Прикажи више за све",
+  "status.show_original": "Show original",
   "status.show_thread": "Show thread",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "Није доступно",
   "status.unmute_conversation": "Укључи преписку",
   "status.unpin": "Откачи са налога",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "Dismiss suggestion",
   "suggestions.header": "You might be interested in…",
   "tabs_bar.federated_timeline": "Федерисано",
diff --git a/app/javascript/mastodon/locales/sv.json b/app/javascript/mastodon/locales/sv.json
index a150deadb..ea98863e7 100644
--- a/app/javascript/mastodon/locales/sv.json
+++ b/app/javascript/mastodon/locales/sv.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Följer dig",
   "account.hide_reblogs": "Dölj knuffar från @{name}",
   "account.joined": "Gick med {date}",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "Ägarskap för detta konto kontrollerades den {date}",
   "account.locked_info": "Detta konto har låst integritetsstatus. Ägaren väljer manuellt vem som kan följa.",
   "account.media": "Media",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Kom igång",
   "getting_started.invite": "Skicka inbjudningar",
   "getting_started.open_source_notice": "Mastodon är programvara med öppen källkod. Du kan bidra eller rapportera problem via GitHub på {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Kontoinställningar",
-  "getting_started.terms": "Användarvillkor",
   "hashtag.column_header.tag_mode.all": "och {additional}",
   "hashtag.column_header.tag_mode.any": "eller {additional}",
   "hashtag.column_header.tag_mode.none": "utan {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Kunde inte hitta något för dessa sökord",
   "search_results.statuses": "Inlägg",
   "search_results.statuses_fts_disabled": "Att söka toots med deras innehåll är inte möjligt på denna Mastodon-server.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {result} other {results}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Öppet modereringsgränssnitt för @{name}",
   "status.admin_status": "Öppna denna status i modereringsgränssnittet",
   "status.block": "Blockera @{name}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Visa mindre för alla",
   "status.show_more": "Visa mer",
   "status.show_more_all": "Visa mer för alla",
+  "status.show_original": "Show original",
   "status.show_thread": "Visa tråd",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "Ej tillgängligt",
   "status.unmute_conversation": "Öppna konversation",
   "status.unpin": "Ångra fäst i profil",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "Avfärda förslag",
   "suggestions.header": "Du kanske är intresserad av…",
   "tabs_bar.federated_timeline": "Federerad",
diff --git a/app/javascript/mastodon/locales/szl.json b/app/javascript/mastodon/locales/szl.json
index c77444bff..7e3bba2df 100644
--- a/app/javascript/mastodon/locales/szl.json
+++ b/app/javascript/mastodon/locales/szl.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Follows you",
   "account.hide_reblogs": "Hide boosts from @{name}",
   "account.joined": "Joined {date}",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.",
   "account.media": "Media",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Getting started",
   "getting_started.invite": "Invite people",
   "getting_started.open_source_notice": "Mastodon is open source software. You can contribute or report issues on GitHub at {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Security",
-  "getting_started.terms": "Terms of service",
   "hashtag.column_header.tag_mode.all": "and {additional}",
   "hashtag.column_header.tag_mode.any": "or {additional}",
   "hashtag.column_header.tag_mode.none": "without {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Could not find anything for these search terms",
   "search_results.statuses": "Toots",
   "search_results.statuses_fts_disabled": "Searching toots by their content is not enabled on this Mastodon server.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {result} other {results}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Open moderation interface for @{name}",
   "status.admin_status": "Open this status in the moderation interface",
   "status.block": "Block @{name}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Show less for all",
   "status.show_more": "Show more",
   "status.show_more_all": "Show more for all",
+  "status.show_original": "Show original",
   "status.show_thread": "Show thread",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "Not available",
   "status.unmute_conversation": "Unmute conversation",
   "status.unpin": "Unpin from profile",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "Dismiss suggestion",
   "suggestions.header": "You might be interested in…",
   "tabs_bar.federated_timeline": "Federated",
diff --git a/app/javascript/mastodon/locales/ta.json b/app/javascript/mastodon/locales/ta.json
index 728cfac11..4d12bb1cc 100644
--- a/app/javascript/mastodon/locales/ta.json
+++ b/app/javascript/mastodon/locales/ta.json
@@ -9,21 +9,22 @@
   "account.browse_more_on_origin_server": "மேலும் உலாவ சுயவிவரத்திற்குச் செல்க",
   "account.cancel_follow_request": "பின்தொடரும் கோரிக்கையை நிராகரி",
   "account.direct": "நேரடி செய்தி @{name}",
-  "account.disable_notifications": "Stop notifying me when @{name} posts",
+  "account.disable_notifications": "@{name} பதிவிட்டல் எனக்கு தெரியபடுத்த வேண்டாம்",
   "account.domain_blocked": "மறைக்கப்பட்டத் தளங்கள்",
   "account.edit_profile": "சுயவிவரத்தை மாற்று",
-  "account.enable_notifications": "Notify me when @{name} posts",
+  "account.enable_notifications": "@{name} பதிவிட்டல் எனக்குத் தெரியப்படுத்தவும்",
   "account.endorse": "சுயவிவரத்தில் வெளிப்படுத்து",
   "account.follow": "பின்தொடர்",
   "account.followers": "பின்தொடர்பவர்கள்",
   "account.followers.empty": "இதுவரை யாரும் இந்த பயனரைப் பின்தொடரவில்லை.",
   "account.followers_counter": "{count, plural, one {{counter} வாசகர்} other {{counter} வாசகர்கள்}}",
-  "account.following": "Following",
+  "account.following": "பின்தொடரும்",
   "account.following_counter": "{count, plural,one {{counter} சந்தா} other {{counter} சந்தாக்கள்}}",
   "account.follows.empty": "இந்த பயனர் இதுவரை யாரையும் பின்தொடரவில்லை.",
   "account.follows_you": "உங்களைப் பின்தொடர்கிறார்",
   "account.hide_reblogs": "இருந்து ஊக்கியாக மறை @{name}",
-  "account.joined": "Joined {date}",
+  "account.joined": "சேர்ந்த நாள் {date}",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "இந்த இணைப்பை உரிமையாளர் சரிபார்க்கப்பட்டது {date}",
   "account.locked_info": "இந்தக் கணக்கு தனியுரிமை நிலை பூட்டப்பட்டுள்ளது. அவர்களைப் பின்தொடர்பவர் யார் என்பதை உரிமையாளர் கைமுறையாக மதிப்பாய்வு செய்கிறார்.",
   "account.media": "ஊடகங்கள்",
@@ -41,25 +42,25 @@
   "account.statuses_counter": "{count, plural, one {{counter} டூட்} other {{counter} டூட்டுகள்}}",
   "account.unblock": "@{name} மீது தடை நீக்குக",
   "account.unblock_domain": "{domain} ஐ காண்பி",
-  "account.unblock_short": "Unblock",
+  "account.unblock_short": "தடையை நீக்கு",
   "account.unendorse": "சுயவிவரத்தில் இடம்பெற வேண்டாம்",
   "account.unfollow": "பின்தொடர்வதை நிறுத்துக",
   "account.unmute": "@{name} இன் மீது மௌனத் தடையை நீக்குக",
   "account.unmute_notifications": "@{name} இலிருந்து அறிவிப்புகளின் மீது மௌனத் தடையை நீக்குக",
-  "account.unmute_short": "Unmute",
+  "account.unmute_short": "அமைதியை நீக்கு",
   "account_note.placeholder": "குறிப்பு ஒன்றை சேர்க்க சொடுக்கவும்",
-  "admin.dashboard.daily_retention": "User retention rate by day after sign-up",
-  "admin.dashboard.monthly_retention": "User retention rate by month after sign-up",
-  "admin.dashboard.retention.average": "Average",
-  "admin.dashboard.retention.cohort": "Sign-up month",
-  "admin.dashboard.retention.cohort_size": "New users",
+  "admin.dashboard.daily_retention": "பதிவுசெய்த பிறகு நாள்தோறும் பயனர் தக்கவைப்பு விகிதம்",
+  "admin.dashboard.monthly_retention": "பதிவுசெய்த பிறகு மாதந்தோறும் பயனர் தக்கவைப்பு விகிதம்",
+  "admin.dashboard.retention.average": "சராசரி",
+  "admin.dashboard.retention.cohort": "பதிவுசெய்த மாதம்",
+  "admin.dashboard.retention.cohort_size": "புதிய பயனர்கள்",
   "alert.rate_limited.message": "{retry_time, time, medium} க்கு பிறகு மீண்டும் முயற்சிக்கவும்.",
   "alert.rate_limited.title": "பயன்பாடு கட்டுப்படுத்தப்பட்டுள்ளது",
   "alert.unexpected.message": "எதிர்பாராத பிழை ஏற்பட்டுவிட்டது.",
   "alert.unexpected.title": "அச்சச்சோ!",
   "announcement.announcement": "அறிவிப்பு",
-  "attachments_list.unprocessed": "(unprocessed)",
-  "audio.hide": "Hide audio",
+  "attachments_list.unprocessed": "(செயலாக்கப்படாதது)",
+  "audio.hide": "ஆடியோவை மறை",
   "autosuggest_hashtag.per_week": "ஒவ்வொரு வாரம் {count}",
   "boost_modal.combo": "நீங்கள் இதை அடுத்தமுறை தவிர்க்க {combo} வை அழுத்தவும்",
   "bundle_column_error.body": "இக்கூற்றை ஏற்றம் செய்யும்பொழுது ஏதோ தவறு ஏற்பட்டுள்ளது.",
@@ -71,7 +72,7 @@
   "column.blocks": "தடுக்கப்பட்ட பயனர்கள்",
   "column.bookmarks": "அடையாளக்குறிகள்",
   "column.community": "சுய நிகழ்வு காலவரிசை",
-  "column.direct": "Direct messages",
+  "column.direct": "நேரடி செய்திகள்",
   "column.directory": "சுயவிவரங்களை உலாவு",
   "column.domain_blocks": "மறைந்திருக்கும் திரளங்கள்",
   "column.favourites": "பிடித்தவைகள்",
@@ -93,10 +94,10 @@
   "community.column_settings.local_only": "அருகிலிருந்து மட்டுமே",
   "community.column_settings.media_only": "படங்கள் மட்டுமே",
   "community.column_settings.remote_only": "தொலைவிலிருந்து மட்டுமே",
-  "compose.language.change": "Change language",
-  "compose.language.search": "Search languages...",
+  "compose.language.change": "மொழியை மாற்று",
+  "compose.language.search": "தேடல் மொழிகள்...",
   "compose_form.direct_message_warning_learn_more": "மேலும் அறிய",
-  "compose_form.encryption_warning": "Posts on Mastodon are not end-to-end encrypted. Do not share any dangerous information over Mastodon.",
+  "compose_form.encryption_warning": "Mastodonல் உள்ள பதிவுகள் முறையாக என்க்ரிப்ட்(encrypt) செய்யபடவில்லை. அதனால் முக்கிய தகவல்களை இங்கே பகிர வேண்டாம்.",
   "compose_form.hashtag_warning": "இது ஒரு பட்டியலிடப்படாத டூட் என்பதால் எந்த ஹேஷ்டேகின் கீழும் வராது. ஹேஷ்டேகின் மூலம் பொதுவில் உள்ள டூட்டுகளை மட்டுமே தேட முடியும்.",
   "compose_form.lock_disclaimer": "உங்கள் கணக்கு {locked} செய்யப்படவில்லை. உங்கள் பதிவுகளை யார் வேண்டுமானாலும் பின்தொடர்ந்து காணலாம்.",
   "compose_form.lock_disclaimer.lock": "பூட்டப்பட்டது",
@@ -107,9 +108,9 @@
   "compose_form.poll.remove_option": "இந்தத் தேர்வை அகற்று",
   "compose_form.poll.switch_to_multiple": "பல தேர்வுகளை அனுமதிக்குமாறு மாற்று",
   "compose_form.poll.switch_to_single": "ஒரே ஒரு தேர்வை மட்டும் அனுமதிக்குமாறு மாற்று",
-  "compose_form.publish": "Publish",
+  "compose_form.publish": "வெளியிடு",
   "compose_form.publish_loud": "{publish}!",
-  "compose_form.save_changes": "Save changes",
+  "compose_form.save_changes": "மாற்றங்களை சேமி",
   "compose_form.sensitive.hide": "அனைவருக்கும் ஏற்றப் படம் இல்லை எனக் குறியிடு",
   "compose_form.sensitive.marked": "இப்படம் அனைவருக்கும் ஏற்றதல்ல எனக் குறியிடப்பட்டுள்ளது",
   "compose_form.sensitive.unmarked": "இப்படம் அனைவருக்கும் ஏற்றதல்ல எனக் குறியிடப்படவில்லை",
@@ -124,8 +125,8 @@
   "confirmations.delete.message": "இப்பதிவை நிச்சயமாக நீக்க விரும்புகிறீர்களா?",
   "confirmations.delete_list.confirm": "நீக்கு",
   "confirmations.delete_list.message": "இப்பட்டியலை நிரந்தரமாக நீக்க நிச்சயம் விரும்புகிறீர்களா?",
-  "confirmations.discard_edit_media.confirm": "Discard",
-  "confirmations.discard_edit_media.message": "You have unsaved changes to the media description or preview, discard them anyway?",
+  "confirmations.discard_edit_media.confirm": "நிராகரி",
+  "confirmations.discard_edit_media.message": "சேமிக்கப்படாத மாற்றங்கள் ஊடக விளக்கம் அல்லது முன்னோட்டத்தில் உள்ளது. அவற்றை நிராகரிக்கவா?",
   "confirmations.domain_block.confirm": "முழு களத்தையும் மறை",
   "confirmations.domain_block.message": "நீங்கள் முழு {domain} களத்தையும் நிச்சயமாக, நிச்சயமாகத் தடுக்க விரும்புகிறீர்களா? பெரும்பாலும் சில குறிப்பிட்ட பயனர்களைத் தடுப்பதே போதுமானது. முழு களத்தையும் தடுத்தால், அதிலிருந்து வரும் எந்தப் பதிவையும் உங்களால் காண முடியாது, மேலும் அப்பதிவுகள் குறித்த அறிவிப்புகளும் உங்களுக்கு வராது. அந்தக் களத்தில் இருக்கும் பின்தொடர்பவர்கள் உங்கள் பக்கத்திலிருந்து நீக்கப்படுவார்கள்.",
   "confirmations.logout.confirm": "வெளியேறு",
@@ -150,7 +151,7 @@
   "embed.instructions": "இந்தப் பதிவை உங்கள் வலைதளத்தில் பொதிக்கக் கீழே உள்ள வரிகளை காப்பி செய்யவும்.",
   "embed.preview": "பார்க்க இப்படி இருக்கும்:",
   "emoji_button.activity": "செயல்பாடு",
-  "emoji_button.clear": "Clear",
+  "emoji_button.clear": "அழி",
   "emoji_button.custom": "தனிப்பயன்",
   "emoji_button.flags": "கொடிகள்",
   "emoji_button.food": "உணவு மற்றும் பானம்",
@@ -164,13 +165,13 @@
   "emoji_button.search_results": "தேடல் முடிவுகள்",
   "emoji_button.symbols": "குறியீடுகள்",
   "emoji_button.travel": "சுற்றுலா மற்றும் இடங்கள்",
-  "empty_column.account_suspended": "Account suspended",
+  "empty_column.account_suspended": "கணக்கு இடைநீக்கப்பட்டது",
   "empty_column.account_timeline": "டூட்டுகள் ஏதும் இல்லை!",
   "empty_column.account_unavailable": "சுயவிவரம் கிடைக்கவில்லை",
   "empty_column.blocks": "நீங்கள் இதுவரை எந்தப் பயனர்களையும் முடக்கியிருக்கவில்லை.",
   "empty_column.bookmarked_statuses": "உங்களிடம் அடையாளக்குறியிட்ட டூட்டுகள் எவையும் இல்லை. அடையாளக்குறியிட்ட பிறகு அவை இங்கே காட்டப்படும்.",
   "empty_column.community": "உங்கள் மாஸ்டடான் முச்சந்தியில் யாரும் இல்லை. எதையேனும் எழுதி ஆட்டத்தைத் துவக்குங்கள்!",
-  "empty_column.direct": "You don't have any direct messages yet. When you send or receive one, it will show up here.",
+  "empty_column.direct": "உங்களுக்குத் தனிப்பட்ட செய்திகள் ஏதும் இல்லை. செய்தியை நீங்கள் அனுப்பும்போதோ அல்லது பெறும்போதோ, அது இங்கே காண்பிக்கப்படும்.",
   "empty_column.domain_blocks": "தடுக்கப்பட்டக் களங்கள் இதுவரை இல்லை.",
   "empty_column.explore_statuses": "Nothing is trending right now. Check back later!",
   "empty_column.favourited_statuses": "உங்களுக்குப் பிடித்த டூட்டுகள் இதுவரை இல்லை. ஒரு டூட்டில் நீங்கள் விருப்பக்குறி இட்டால், அது இங்கே காண்பிக்கப்படும்.",
@@ -226,8 +227,8 @@
   "getting_started.heading": "முதன்மைப் பக்கம்",
   "getting_started.invite": "நண்பர்களை அழைக்க",
   "getting_started.open_source_notice": "மாஸ்டடான் ஒரு open source மென்பொருள் ஆகும். {github} -இன் மூலம் உங்களால் இதில் பங்களிக்கவோ, சிக்கல்களைத் தெரியப்படுத்தவோ முடியும்.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "கணக்கு அமைப்புகள்",
-  "getting_started.terms": "சேவை விதிமுறைகள்",
   "hashtag.column_header.tag_mode.all": "மற்றும் {additional}",
   "hashtag.column_header.tag_mode.any": "அல்லது {additional}",
   "hashtag.column_header.tag_mode.none": "{additional} தவிர்த்து",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Could not find anything for these search terms",
   "search_results.statuses": "டூட்டுகள்",
   "search_results.statuses_fts_disabled": "டூட்டுகளின் வார்த்தைகளைக்கொண்டு தேடுவது இந்த மச்டோடன் வழங்கியில் இயல்விக்கப்படவில்லை.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {result} மற்ற {results}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "மிதமான இடைமுகத்தை திறக்க @{name}",
   "status.admin_status": "மிதமான இடைமுகத்தில் இந்த நிலையை திறக்கவும்",
   "status.block": "@{name} -ஐத் தடு",
@@ -518,10 +523,16 @@
   "status.show_less_all": "அனைத்தையும் குறைவாக காட்டு",
   "status.show_more": "மேலும் காட்ட",
   "status.show_more_all": "அனைவருக்கும் மேலும் காட்டு",
+  "status.show_original": "Show original",
   "status.show_thread": "நூல் காட்டு",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "கிடைக்கவில்லை",
   "status.unmute_conversation": "ஊமையாக உரையாடல் இல்லை",
   "status.unpin": "சுயவிவரத்திலிருந்து நீக்கவும்",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "பரிந்துரை விலக்க",
   "suggestions.header": "நீங்கள் ஆர்வமாக இருக்கலாம் …",
   "tabs_bar.federated_timeline": "கூட்டமைந்த",
diff --git a/app/javascript/mastodon/locales/tai.json b/app/javascript/mastodon/locales/tai.json
index beba8e333..79ed59434 100644
--- a/app/javascript/mastodon/locales/tai.json
+++ b/app/javascript/mastodon/locales/tai.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Follows you",
   "account.hide_reblogs": "Hide boosts from @{name}",
   "account.joined": "Joined {date}",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.",
   "account.media": "Mûi-thé",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Getting started",
   "getting_started.invite": "Invite people",
   "getting_started.open_source_notice": "Mastodon is open source software. You can contribute or report issues on GitHub at {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Security",
-  "getting_started.terms": "Terms of service",
   "hashtag.column_header.tag_mode.all": "and {additional}",
   "hashtag.column_header.tag_mode.any": "or {additional}",
   "hashtag.column_header.tag_mode.none": "without {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Could not find anything for these search terms",
   "search_results.statuses": "Toots",
   "search_results.statuses_fts_disabled": "Searching toots by their content is not enabled on this Mastodon server.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {result} other {results}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Open moderation interface for @{name}",
   "status.admin_status": "Open this status in the moderation interface",
   "status.block": "Block @{name}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Show less for all",
   "status.show_more": "Show more",
   "status.show_more_all": "Show more for all",
+  "status.show_original": "Show original",
   "status.show_thread": "Show thread",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "Not available",
   "status.unmute_conversation": "Unmute conversation",
   "status.unpin": "Unpin from profile",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "Dismiss suggestion",
   "suggestions.header": "You might be interested in…",
   "tabs_bar.federated_timeline": "Federated",
diff --git a/app/javascript/mastodon/locales/te.json b/app/javascript/mastodon/locales/te.json
index d5cc02b10..e327c3859 100644
--- a/app/javascript/mastodon/locales/te.json
+++ b/app/javascript/mastodon/locales/te.json
@@ -24,6 +24,7 @@
   "account.follows_you": "మిమ్మల్ని అనుసరిస్తున్నారు",
   "account.hide_reblogs": "@{name} నుంచి బూస్ట్ లను దాచిపెట్టు",
   "account.joined": "Joined {date}",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "ఈ లంకె యొక్క యాజమాన్యం {date}న పరీక్షించబడింది",
   "account.locked_info": "ఈ ఖాతా యొక్క గోప్యత స్థితి లాక్ చేయబడి వుంది. ఈ ఖాతాను ఎవరు అనుసరించవచ్చో యజమానే నిర్ణయం తీసుకుంటారు.",
   "account.media": "మీడియా",
@@ -226,8 +227,8 @@
   "getting_started.heading": "మొదలుపెడదాం",
   "getting_started.invite": "వ్యక్తులను ఆహ్వానించండి",
   "getting_started.open_source_notice": "మాస్టొడొన్ ఓపెన్ సోర్స్ సాఫ్ట్వేర్. మీరు {github} వద్ద GitHub పై సమస్యలను నివేదించవచ్చు లేదా తోడ్పడచ్చు.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "భద్రత",
-  "getting_started.terms": "సేవా నిబంధనలు",
   "hashtag.column_header.tag_mode.all": "మరియు {additional}",
   "hashtag.column_header.tag_mode.any": "లేదా {additional}",
   "hashtag.column_header.tag_mode.none": "{additional} లేకుండా",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Could not find anything for these search terms",
   "search_results.statuses": "టూట్లు",
   "search_results.statuses_fts_disabled": "Searching toots by their content is not enabled on this Mastodon server.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {result} other {results}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "@{name} కొరకు సమన్వయ వినిమయసీమను తెరువు",
   "status.admin_status": "సమన్వయ వినిమయసీమలో ఈ స్టేటస్ ను తెరవండి",
   "status.block": "@{name} ను బ్లాక్ చేయి",
@@ -518,10 +523,16 @@
   "status.show_less_all": "అన్నిటికీ తక్కువ చూపించు",
   "status.show_more": "ఇంకా చూపించు",
   "status.show_more_all": "అన్నిటికీ ఇంకా చూపించు",
+  "status.show_original": "Show original",
   "status.show_thread": "గొలుసును చూపించు",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "Not available",
   "status.unmute_conversation": "సంభాషణను అన్మ్యూట్ చేయి",
   "status.unpin": "ప్రొఫైల్ నుండి పీకివేయు",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "సూచనను రద్దు చేయి",
   "suggestions.header": "మీకు వీటి మీద ఆసక్తి ఉండవచ్చు…",
   "tabs_bar.federated_timeline": "సమాఖ్య",
diff --git a/app/javascript/mastodon/locales/th.json b/app/javascript/mastodon/locales/th.json
index 38539d512..287448bf4 100644
--- a/app/javascript/mastodon/locales/th.json
+++ b/app/javascript/mastodon/locales/th.json
@@ -24,6 +24,7 @@
   "account.follows_you": "ติดตามคุณ",
   "account.hide_reblogs": "ซ่อนการดันจาก @{name}",
   "account.joined": "เข้าร่วมเมื่อ {date}",
+  "account.languages": "เปลี่ยนภาษาที่บอกรับ",
   "account.link_verified_on": "ตรวจสอบความเป็นเจ้าของของลิงก์นี้เมื่อ {date}",
   "account.locked_info": "มีการตั้งสถานะความเป็นส่วนตัวของบัญชีนี้เป็นล็อคอยู่ เจ้าของตรวจทานผู้ที่สามารถติดตามเขาด้วยตนเอง",
   "account.media": "สื่อ",
@@ -198,21 +199,21 @@
   "explore.trending_statuses": "โพสต์",
   "explore.trending_tags": "แฮชแท็ก",
   "filter_modal.added.context_mismatch_explanation": "This filter category does not apply to the context in which you have accessed this post. If you want the post to be filtered in this context too, you will have to edit the filter.",
-  "filter_modal.added.context_mismatch_title": "Context mismatch!",
-  "filter_modal.added.expired_explanation": "This filter category has expired, you will need to change the expiration date for it to apply.",
-  "filter_modal.added.expired_title": "Expired filter!",
-  "filter_modal.added.review_and_configure": "To review and further configure this filter category, go to the {settings_link}.",
-  "filter_modal.added.review_and_configure_title": "Filter settings",
-  "filter_modal.added.settings_link": "settings page",
-  "filter_modal.added.short_explanation": "This post has been added to the following filter category: {title}.",
-  "filter_modal.added.title": "Filter added!",
-  "filter_modal.select_filter.context_mismatch": "does not apply to this context",
-  "filter_modal.select_filter.expired": "expired",
-  "filter_modal.select_filter.prompt_new": "New category: {name}",
-  "filter_modal.select_filter.search": "Search or create",
-  "filter_modal.select_filter.subtitle": "Use an existing category or create a new one",
-  "filter_modal.select_filter.title": "Filter this post",
-  "filter_modal.title.status": "Filter a post",
+  "filter_modal.added.context_mismatch_title": "บริบทไม่ตรงกัน!",
+  "filter_modal.added.expired_explanation": "หมวดหมู่ตัวกรองนี้หมดอายุแล้ว คุณจะต้องเปลี่ยนวันหมดอายุสำหรับหมวดหมู่เพื่อนำไปใช้",
+  "filter_modal.added.expired_title": "ตัวกรองหมดอายุแล้ว!",
+  "filter_modal.added.review_and_configure": "เพื่อตรวจทานและกำหนดค่าหมวดหมู่ตัวกรองนี้เพิ่มเติม ไปยัง {settings_link}",
+  "filter_modal.added.review_and_configure_title": "การตั้งค่าตัวกรอง",
+  "filter_modal.added.settings_link": "หน้าการตั้งค่า",
+  "filter_modal.added.short_explanation": "เพิ่มโพสต์นี้ไปยังหมวดหมู่ตัวกรองดังต่อไปนี้แล้ว: {title}",
+  "filter_modal.added.title": "เพิ่มตัวกรองแล้ว!",
+  "filter_modal.select_filter.context_mismatch": "ไม่นำไปใช้กับบริบทนี้",
+  "filter_modal.select_filter.expired": "หมดอายุแล้ว",
+  "filter_modal.select_filter.prompt_new": "หมวดหมู่ใหม่: {name}",
+  "filter_modal.select_filter.search": "ค้นหาหรือสร้าง",
+  "filter_modal.select_filter.subtitle": "ใช้หมวดหมู่ที่มีอยู่หรือสร้างหมวดหมู่ใหม่",
+  "filter_modal.select_filter.title": "กรองโพสต์นี้",
+  "filter_modal.title.status": "กรองโพสต์",
   "follow_recommendations.done": "เสร็จสิ้น",
   "follow_recommendations.heading": "ติดตามผู้คนที่คุณต้องการเห็นโพสต์! นี่คือข้อเสนอแนะบางส่วน",
   "follow_recommendations.lead": "โพสต์จากผู้คนที่คุณติดตามจะแสดงตามลำดับเวลาในฟีดหน้าแรกของคุณ อย่ากลัวที่จะทำผิดพลาด คุณสามารถเลิกติดตามผู้คนได้อย่างง่ายดายเมื่อใดก็ตาม!",
@@ -226,8 +227,8 @@
   "getting_started.heading": "เริ่มต้นใช้งาน",
   "getting_started.invite": "เชิญผู้คน",
   "getting_started.open_source_notice": "Mastodon เป็นซอฟต์แวร์โอเพนซอร์ส คุณสามารถมีส่วนร่วมหรือรายงานปัญหาได้ใน GitHub ที่ {github}",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "การตั้งค่าบัญชี",
-  "getting_started.terms": "เงื่อนไขการให้บริการ",
   "hashtag.column_header.tag_mode.all": "และ {additional}",
   "hashtag.column_header.tag_mode.any": "หรือ {additional}",
   "hashtag.column_header.tag_mode.none": "โดยไม่มี {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "ไม่พบสิ่งใดสำหรับคำค้นหาเหล่านี้",
   "search_results.statuses": "โพสต์",
   "search_results.statuses_fts_disabled": "ไม่มีการเปิดใช้งานการค้นหาโพสต์โดยเนื้อหาของโพสต์ในเซิร์ฟเวอร์ Mastodon นี้",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, other {ผลลัพธ์}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "เปิดส่วนติดต่อการควบคุมสำหรับ @{name}",
   "status.admin_status": "เปิดโพสต์นี้ในส่วนติดต่อการควบคุม",
   "status.block": "ปิดกั้น @{name}",
@@ -487,7 +492,7 @@
   "status.edited_x_times": "แก้ไข {count, plural, other {{count} ครั้ง}}",
   "status.embed": "ฝัง",
   "status.favourite": "ชื่นชอบ",
-  "status.filter": "Filter this post",
+  "status.filter": "กรองโพสต์นี้",
   "status.filtered": "กรองอยู่",
   "status.hide": "ซ่อนโพสต์",
   "status.history.created": "{name} ได้สร้างเมื่อ {date}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "แสดงน้อยลงทั้งหมด",
   "status.show_more": "แสดงเพิ่มเติม",
   "status.show_more_all": "แสดงเพิ่มเติมทั้งหมด",
+  "status.show_original": "Show original",
   "status.show_thread": "แสดงกระทู้",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "ไม่พร้อมใช้งาน",
   "status.unmute_conversation": "เลิกซ่อนการสนทนา",
   "status.unpin": "ถอนหมุดจากโปรไฟล์",
+  "subscribed_languages.lead": "เฉพาะโพสต์ในภาษาที่เลือกเท่านั้นที่จะปรากฏในเส้นเวลาหน้าแรกและรายการหลังจากการเปลี่ยนแปลง เลือก ไม่มี เพื่อรับโพสต์ในภาษาทั้งหมด",
+  "subscribed_languages.save": "บันทึกการเปลี่ยนแปลง",
+  "subscribed_languages.target": "เปลี่ยนภาษาที่บอกรับสำหรับ {target}",
   "suggestions.dismiss": "ปิดข้อเสนอแนะ",
   "suggestions.header": "คุณอาจสนใจ…",
   "tabs_bar.federated_timeline": "ที่ติดต่อกับภายนอก",
diff --git a/app/javascript/mastodon/locales/tr.json b/app/javascript/mastodon/locales/tr.json
index 35c888e47..b3b539f68 100644
--- a/app/javascript/mastodon/locales/tr.json
+++ b/app/javascript/mastodon/locales/tr.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Seni takip ediyor",
   "account.hide_reblogs": "@{name} kişisinin boostlarını gizle",
   "account.joined": "{date} tarihinde katıldı",
+  "account.languages": "Abone olunan dilleri değiştir",
   "account.link_verified_on": "Bu bağlantının sahipliği {date} tarihinde kontrol edildi",
   "account.locked_info": "Bu hesabın gizlilik durumu gizli olarak ayarlanmış. Sahibi, onu kimin takip edebileceğini manuel olarak onaylıyor.",
   "account.media": "Medya",
@@ -197,22 +198,22 @@
   "explore.trending_links": "Haberler",
   "explore.trending_statuses": "Gönderiler",
   "explore.trending_tags": "Etiketler",
-  "filter_modal.added.context_mismatch_explanation": "This filter category does not apply to the context in which you have accessed this post. If you want the post to be filtered in this context too, you will have to edit the filter.",
-  "filter_modal.added.context_mismatch_title": "Context mismatch!",
-  "filter_modal.added.expired_explanation": "This filter category has expired, you will need to change the expiration date for it to apply.",
-  "filter_modal.added.expired_title": "Expired filter!",
-  "filter_modal.added.review_and_configure": "To review and further configure this filter category, go to the {settings_link}.",
-  "filter_modal.added.review_and_configure_title": "Filter settings",
-  "filter_modal.added.settings_link": "settings page",
-  "filter_modal.added.short_explanation": "This post has been added to the following filter category: {title}.",
-  "filter_modal.added.title": "Filter added!",
-  "filter_modal.select_filter.context_mismatch": "does not apply to this context",
-  "filter_modal.select_filter.expired": "expired",
-  "filter_modal.select_filter.prompt_new": "New category: {name}",
-  "filter_modal.select_filter.search": "Search or create",
-  "filter_modal.select_filter.subtitle": "Use an existing category or create a new one",
-  "filter_modal.select_filter.title": "Filter this post",
-  "filter_modal.title.status": "Filter a post",
+  "filter_modal.added.context_mismatch_explanation": "Bu filtre kategorisi, bu gönderide eriştiğin bağlama uymuyor. Eğer gönderinin bu bağlamda da filtrelenmesini istiyorsanız, filtreyi düzenlemeniz gerekiyor.",
+  "filter_modal.added.context_mismatch_title": "Bağlam uyumsuzluğu!",
+  "filter_modal.added.expired_explanation": "Bu filtre kategorisinin süresi dolmuş, filtreyi uygulamak için bitiş tarihini değiştirmeniz gerekiyor.",
+  "filter_modal.added.expired_title": "Süresi dolmuş filtre!",
+  "filter_modal.added.review_and_configure": "Bu filtre kategorisini gözden geçirmek ve daha ayrıntılı bir şekilde yapılandırmak için {settings_link} adresine gidin.",
+  "filter_modal.added.review_and_configure_title": "Filtre ayarları",
+  "filter_modal.added.settings_link": "ayarlar sayfası",
+  "filter_modal.added.short_explanation": "Bu gönderi şu filtre kategorisine eklendi: {title}.",
+  "filter_modal.added.title": "Filtre eklendi!",
+  "filter_modal.select_filter.context_mismatch": "bu bağlama uymuyor",
+  "filter_modal.select_filter.expired": "süresi dolmuş",
+  "filter_modal.select_filter.prompt_new": "Yeni kategori: {name}",
+  "filter_modal.select_filter.search": "Ara veya oluştur",
+  "filter_modal.select_filter.subtitle": "Mevcut bir kategoriyi kullan veya yeni bir tane oluştur",
+  "filter_modal.select_filter.title": "Bu gönderiyi filtrele",
+  "filter_modal.title.status": "Bir gönderi filtrele",
   "follow_recommendations.done": "Tamam",
   "follow_recommendations.heading": "Gönderilerini görmek isteyeceğiniz kişileri takip edin! Burada bazı öneriler bulabilirsiniz.",
   "follow_recommendations.lead": "Takip ettiğiniz kişilerin gönderileri anasayfa akışınızda kronolojik sırada görünmeye devam edecek. Hata yapmaktan çekinmeyin, kişileri istediğiniz anda kolayca takipten çıkabilirsiniz!",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Başlarken",
   "getting_started.invite": "İnsanları davet et",
   "getting_started.open_source_notice": "Mastodon açık kaynaklı bir yazılımdır. GitHub'taki {github} üzerinden katkıda bulunabilir veya sorunları bildirebilirsiniz.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Hesap ayarları",
-  "getting_started.terms": "Kullanım şartları",
   "hashtag.column_header.tag_mode.all": "ve {additional}",
   "hashtag.column_header.tag_mode.any": "ya da {additional}",
   "hashtag.column_header.tag_mode.none": "{additional} olmadan",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Bu arama seçenekleriyle bir sonuç bulunamadı",
   "search_results.statuses": "Gönderiler",
   "search_results.statuses_fts_disabled": "Bu Mastodon sunucusunda gönderi içeriğine göre arama etkin değil.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {sonuç} other {sonuç}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "@{name} için denetim arayüzünü açın",
   "status.admin_status": "Denetim arayüzünde bu gönderiyi açın",
   "status.block": "@{name} adlı kişiyi engelle",
@@ -487,7 +492,7 @@
   "status.edited_x_times": "{count, plural, one {{count} kez} other {{count} kez}} düzenlendi",
   "status.embed": "Gömülü",
   "status.favourite": "Favorilerine ekle",
-  "status.filter": "Filter this post",
+  "status.filter": "Bu gönderiyi filtrele",
   "status.filtered": "Filtrelenmiş",
   "status.hide": "Gönderiyi sakla",
   "status.history.created": "{name} oluşturdu {date}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Hepsi için daha az göster",
   "status.show_more": "Daha fazlasını göster",
   "status.show_more_all": "Hepsi için daha fazla göster",
+  "status.show_original": "Orijinali göster",
   "status.show_thread": "Konuyu göster",
+  "status.translate": "Çevir",
+  "status.translated_from": "{lang} dilinden çevrildi",
   "status.uncached_media_warning": "Mevcut değil",
   "status.unmute_conversation": "Sohbet sesini aç",
   "status.unpin": "Profilden sabitlemeyi kaldır",
+  "subscribed_languages.lead": "Değişiklikten sonra ana akışınızda sadece seçili dillerdeki gönderiler görüntülenecek ve zaman akışları listelenecektir. Tüm dillerde gönderiler için hiçbirini seçin.",
+  "subscribed_languages.save": "Değişiklikleri kaydet",
+  "subscribed_languages.target": "{target} abone olduğu dilleri değiştir",
   "suggestions.dismiss": "Öneriyi görmezden gel",
   "suggestions.header": "Şuna ilgi duyuyor olabilirsiniz…",
   "tabs_bar.federated_timeline": "Federe",
diff --git a/app/javascript/mastodon/locales/tt.json b/app/javascript/mastodon/locales/tt.json
index c2739e181..0bc6dee62 100644
--- a/app/javascript/mastodon/locales/tt.json
+++ b/app/javascript/mastodon/locales/tt.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Сезгә язылган",
   "account.hide_reblogs": "Hide boosts from @{name}",
   "account.joined": "{date} көнендә теркәлде",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.locked_info": "Бу - ябык аккаунт. Аны язылучылар гына күрә ала.",
   "account.media": "Медиа",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Getting started",
   "getting_started.invite": "Invite people",
   "getting_started.open_source_notice": "Mastodon is open source software. You can contribute or report issues on GitHub at {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Security",
-  "getting_started.terms": "Terms of service",
   "hashtag.column_header.tag_mode.all": "and {additional}",
   "hashtag.column_header.tag_mode.any": "or {additional}",
   "hashtag.column_header.tag_mode.none": "without {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Could not find anything for these search terms",
   "search_results.statuses": "Toots",
   "search_results.statuses_fts_disabled": "Searching toots by their content is not enabled on this Mastodon server.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {result} other {results}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Open moderation interface for @{name}",
   "status.admin_status": "Open this status in the moderation interface",
   "status.block": "@{name} блоклау",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Show less for all",
   "status.show_more": "Күбрәк күрсәтү",
   "status.show_more_all": "Show more for all",
+  "status.show_original": "Show original",
   "status.show_thread": "Show thread",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "Not available",
   "status.unmute_conversation": "Unmute conversation",
   "status.unpin": "Unpin from profile",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "Dismiss suggestion",
   "suggestions.header": "You might be interested in…",
   "tabs_bar.federated_timeline": "Federated",
diff --git a/app/javascript/mastodon/locales/ug.json b/app/javascript/mastodon/locales/ug.json
index c77444bff..7e3bba2df 100644
--- a/app/javascript/mastodon/locales/ug.json
+++ b/app/javascript/mastodon/locales/ug.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Follows you",
   "account.hide_reblogs": "Hide boosts from @{name}",
   "account.joined": "Joined {date}",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.",
   "account.media": "Media",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Getting started",
   "getting_started.invite": "Invite people",
   "getting_started.open_source_notice": "Mastodon is open source software. You can contribute or report issues on GitHub at {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Security",
-  "getting_started.terms": "Terms of service",
   "hashtag.column_header.tag_mode.all": "and {additional}",
   "hashtag.column_header.tag_mode.any": "or {additional}",
   "hashtag.column_header.tag_mode.none": "without {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Could not find anything for these search terms",
   "search_results.statuses": "Toots",
   "search_results.statuses_fts_disabled": "Searching toots by their content is not enabled on this Mastodon server.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {result} other {results}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Open moderation interface for @{name}",
   "status.admin_status": "Open this status in the moderation interface",
   "status.block": "Block @{name}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Show less for all",
   "status.show_more": "Show more",
   "status.show_more_all": "Show more for all",
+  "status.show_original": "Show original",
   "status.show_thread": "Show thread",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "Not available",
   "status.unmute_conversation": "Unmute conversation",
   "status.unpin": "Unpin from profile",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "Dismiss suggestion",
   "suggestions.header": "You might be interested in…",
   "tabs_bar.federated_timeline": "Federated",
diff --git a/app/javascript/mastodon/locales/uk.json b/app/javascript/mastodon/locales/uk.json
index e1b10445d..1001222c2 100644
--- a/app/javascript/mastodon/locales/uk.json
+++ b/app/javascript/mastodon/locales/uk.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Підписані на вас",
   "account.hide_reblogs": "Сховати поширення від @{name}",
   "account.joined": "Долучилися {date}",
+  "account.languages": "Змінити підписані мови",
   "account.link_verified_on": "Права власності на це посилання були перевірені {date}",
   "account.locked_info": "Це закритий обліковий запис. Власник вручну обирає, хто може на нього підписуватися.",
   "account.media": "Медіа",
@@ -197,22 +198,22 @@
   "explore.trending_links": "Новини",
   "explore.trending_statuses": "Дописи",
   "explore.trending_tags": "Хештеґи",
-  "filter_modal.added.context_mismatch_explanation": "This filter category does not apply to the context in which you have accessed this post. If you want the post to be filtered in this context too, you will have to edit the filter.",
-  "filter_modal.added.context_mismatch_title": "Context mismatch!",
-  "filter_modal.added.expired_explanation": "This filter category has expired, you will need to change the expiration date for it to apply.",
-  "filter_modal.added.expired_title": "Expired filter!",
-  "filter_modal.added.review_and_configure": "To review and further configure this filter category, go to the {settings_link}.",
-  "filter_modal.added.review_and_configure_title": "Filter settings",
-  "filter_modal.added.settings_link": "settings page",
-  "filter_modal.added.short_explanation": "This post has been added to the following filter category: {title}.",
-  "filter_modal.added.title": "Filter added!",
-  "filter_modal.select_filter.context_mismatch": "does not apply to this context",
-  "filter_modal.select_filter.expired": "expired",
-  "filter_modal.select_filter.prompt_new": "New category: {name}",
-  "filter_modal.select_filter.search": "Search or create",
-  "filter_modal.select_filter.subtitle": "Use an existing category or create a new one",
-  "filter_modal.select_filter.title": "Filter this post",
-  "filter_modal.title.status": "Filter a post",
+  "filter_modal.added.context_mismatch_explanation": "Ця категорія фільтра не застосовується до контексту, в якому ви отримали доступ до цього допису. Якщо ви хочете, щоб дописи також фільтрувалися за цим контекстом, вам доведеться редагувати фільтр.",
+  "filter_modal.added.context_mismatch_title": "Невідповідність контексту!",
+  "filter_modal.added.expired_explanation": "Категорія цього фільтра застаріла, Вам потрібно змінити дату закінчення терміну дії, щоб застосувати її.",
+  "filter_modal.added.expired_title": "Застарілий фільтр!",
+  "filter_modal.added.review_and_configure": "Щоб розглянути та далі налаштувати цю категорію фільтрів, перейдіть на {settings_link}.",
+  "filter_modal.added.review_and_configure_title": "Налаштування фільтра",
+  "filter_modal.added.settings_link": "сторінка налаштувань",
+  "filter_modal.added.short_explanation": "Цей допис було додано до такої категорії фільтра: {title}.",
+  "filter_modal.added.title": "Фільтр додано!",
+  "filter_modal.select_filter.context_mismatch": "не застосовується до цього контексту",
+  "filter_modal.select_filter.expired": "застарілий",
+  "filter_modal.select_filter.prompt_new": "Нова категорія: {name}",
+  "filter_modal.select_filter.search": "Пошук або створення",
+  "filter_modal.select_filter.subtitle": "Використати наявну категорію або створити нову",
+  "filter_modal.select_filter.title": "Фільтрувати цей допис",
+  "filter_modal.title.status": "Фільтрувати допис",
   "follow_recommendations.done": "Готово",
   "follow_recommendations.heading": "Підпишіться на людей, чиї дописи ви хочете бачити! Ось деякі пропозиції.",
   "follow_recommendations.lead": "Дописи від людей, за якими ви стежите, з'являться в хронологічному порядку у вашій домашній стрічці. Не бійся помилятися, ви можете відписатися від людей так само легко в будь-який час!",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Розпочати",
   "getting_started.invite": "Запросити людей",
   "getting_started.open_source_notice": "Mastodon — програма з відкритим сирцевим кодом. Ви можете допомогти проєкту, або повідомити про проблеми на GitHub: {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Налаштування облікового запису",
-  "getting_started.terms": "Умови використання",
   "hashtag.column_header.tag_mode.all": "та {additional}",
   "hashtag.column_header.tag_mode.any": "або {additional}",
   "hashtag.column_header.tag_mode.none": "без {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Нічого не вдалося знайти за цими пошуковими термінами",
   "search_results.statuses": "Дмухів",
   "search_results.statuses_fts_disabled": "Пошук дописів за вмістом недоступний на даному сервері Mastodon.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {результат} few {результати} many {результатів} other {результатів}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Відкрити інтерфейс модерації для @{name}",
   "status.admin_status": "Відкрити цей статус в інтерфейсі модерації",
   "status.block": "Заблокувати @{name}",
@@ -487,7 +492,7 @@
   "status.edited_x_times": "Відредаговано {count, plural, one {{count} раз} few {{count} рази} many {{counter} разів} other {{counter} разів}}",
   "status.embed": "Вбудувати",
   "status.favourite": "Подобається",
-  "status.filter": "Filter this post",
+  "status.filter": "Фільтрувати цей допис",
   "status.filtered": "Відфільтровано",
   "status.hide": "Сховати дмух",
   "status.history.created": "{name} створює {date}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Показувати менше для всіх",
   "status.show_more": "Розгорнути",
   "status.show_more_all": "Показувати більше для всіх",
+  "status.show_original": "Показати оригінал",
   "status.show_thread": "Показати ланцюжок",
+  "status.translate": "Перекласти",
+  "status.translated_from": "Перекладено з {lang}",
   "status.uncached_media_warning": "Недоступно",
   "status.unmute_conversation": "Не ігнорувати діалог",
   "status.unpin": "Відкріпити від профілю",
+  "subscribed_languages.lead": "Лише дописи вибраними мовами з'являтимуться на вашій домівці та у списку стрічок після змін. Виберіть «none», щоб отримувати повідомлення всіма мовами.",
+  "subscribed_languages.save": "Зберегти зміни",
+  "subscribed_languages.target": "Змінити підписані мови для {target}",
   "suggestions.dismiss": "Відхилити пропозицію",
   "suggestions.header": "Вас може зацікавити…",
   "tabs_bar.federated_timeline": "Глобальна",
diff --git a/app/javascript/mastodon/locales/ur.json b/app/javascript/mastodon/locales/ur.json
index 19cee9c2a..b79391be0 100644
--- a/app/javascript/mastodon/locales/ur.json
+++ b/app/javascript/mastodon/locales/ur.json
@@ -24,6 +24,7 @@
   "account.follows_you": "آپ کا پیروکار ہے",
   "account.hide_reblogs": "@{name} سے فروغ چھپائیں",
   "account.joined": "{date} شامل ہوئے",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "اس لنک کی ملکیت کی توثیق {date} پر کی گئی تھی",
   "account.locked_info": "اس اکاونٹ کا اخفائی ضابطہ مقفل ہے۔ صارف کی پیروی کون کر سکتا ہے اس کا جائزہ وہ خود لیتا ہے.",
   "account.media": "وسائل",
@@ -226,8 +227,8 @@
   "getting_started.heading": "آغاز کریں",
   "getting_started.invite": "دوستوں کو دعوت دیں",
   "getting_started.open_source_notice": "ماسٹوڈون آزاد منبع سوفٹویر ہے. آپ {github} گِٹ ہب پر مسائل میں معاونت یا مشکلات کی اطلاع دے سکتے ہیں.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "ترتیباتِ اکاؤنٹ",
-  "getting_started.terms": "شرائط خدمات",
   "hashtag.column_header.tag_mode.all": "اور {additional}",
   "hashtag.column_header.tag_mode.any": "یا {additional}",
   "hashtag.column_header.tag_mode.none": "بغیر {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Could not find anything for these search terms",
   "search_results.statuses": "Toots",
   "search_results.statuses_fts_disabled": "Searching toots by their content is not enabled on this Mastodon server.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {result} other {results}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Open moderation interface for @{name}",
   "status.admin_status": "Open this status in the moderation interface",
   "status.block": "Block @{name}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Show less for all",
   "status.show_more": "Show more",
   "status.show_more_all": "Show more for all",
+  "status.show_original": "Show original",
   "status.show_thread": "Show thread",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "Not available",
   "status.unmute_conversation": "Unmute conversation",
   "status.unpin": "Unpin from profile",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "Dismiss suggestion",
   "suggestions.header": "You might be interested in…",
   "tabs_bar.federated_timeline": "Federated",
diff --git a/app/javascript/mastodon/locales/vi.json b/app/javascript/mastodon/locales/vi.json
index 3dc6db112..c349fcf8c 100644
--- a/app/javascript/mastodon/locales/vi.json
+++ b/app/javascript/mastodon/locales/vi.json
@@ -24,6 +24,7 @@
   "account.follows_you": "Đang theo dõi bạn",
   "account.hide_reblogs": "Ẩn tút @{name} đăng lại",
   "account.joined": "Đã tham gia {date}",
+  "account.languages": "Đổi ngôn ngữ mong muốn",
   "account.link_verified_on": "Liên kết này đã được xác minh vào {date}",
   "account.locked_info": "Đây là tài khoản riêng tư. Họ sẽ tự mình xét duyệt các yêu cầu theo dõi.",
   "account.media": "Media",
@@ -197,22 +198,22 @@
   "explore.trending_links": "Tin tức",
   "explore.trending_statuses": "Tút",
   "explore.trending_tags": "Hashtag",
-  "filter_modal.added.context_mismatch_explanation": "This filter category does not apply to the context in which you have accessed this post. If you want the post to be filtered in this context too, you will have to edit the filter.",
-  "filter_modal.added.context_mismatch_title": "Context mismatch!",
-  "filter_modal.added.expired_explanation": "This filter category has expired, you will need to change the expiration date for it to apply.",
-  "filter_modal.added.expired_title": "Expired filter!",
-  "filter_modal.added.review_and_configure": "To review and further configure this filter category, go to the {settings_link}.",
-  "filter_modal.added.review_and_configure_title": "Filter settings",
-  "filter_modal.added.settings_link": "settings page",
-  "filter_modal.added.short_explanation": "This post has been added to the following filter category: {title}.",
-  "filter_modal.added.title": "Filter added!",
-  "filter_modal.select_filter.context_mismatch": "does not apply to this context",
-  "filter_modal.select_filter.expired": "expired",
-  "filter_modal.select_filter.prompt_new": "New category: {name}",
-  "filter_modal.select_filter.search": "Search or create",
-  "filter_modal.select_filter.subtitle": "Use an existing category or create a new one",
-  "filter_modal.select_filter.title": "Filter this post",
-  "filter_modal.title.status": "Filter a post",
+  "filter_modal.added.context_mismatch_explanation": "Danh mục bộ lọc này không áp dụng cho ngữ cảnh mà bạn đã truy cập tút này. Nếu bạn muốn tút cũng được lọc trong ngữ cảnh này, bạn sẽ phải chỉnh sửa bộ lọc.",
+  "filter_modal.added.context_mismatch_title": "Bối cảnh không phù hợp!",
+  "filter_modal.added.expired_explanation": "Danh mục bộ lọc này đã hết hạn, bạn sẽ cần thay đổi ngày hết hạn để áp dụng.",
+  "filter_modal.added.expired_title": "Bộ lọc đã hết hạn!",
+  "filter_modal.added.review_and_configure": "Để xem lại và định cấu hình thêm danh mục bộ lọc này, hãy xem {settings_link}.",
+  "filter_modal.added.review_and_configure_title": "Thiết lập bộ lọc",
+  "filter_modal.added.settings_link": "trang cài đặt",
+  "filter_modal.added.short_explanation": "Tút này đã được thêm vào danh mục bộ lọc sau: {title}.",
+  "filter_modal.added.title": "Đã thêm bộ lọc!",
+  "filter_modal.select_filter.context_mismatch": "không áp dụng cho bối cảnh này",
+  "filter_modal.select_filter.expired": "hết hạn",
+  "filter_modal.select_filter.prompt_new": "Danh mục mới: {name}",
+  "filter_modal.select_filter.search": "Tìm kiếm hoặc tạo mới",
+  "filter_modal.select_filter.subtitle": "Sử dụng một danh mục hiện có hoặc tạo một danh mục mới",
+  "filter_modal.select_filter.title": "Lọc tút này",
+  "filter_modal.title.status": "Lọc một tút",
   "follow_recommendations.done": "Xong",
   "follow_recommendations.heading": "Theo dõi những người bạn muốn đọc tút của họ! Dưới đây là vài gợi ý.",
   "follow_recommendations.lead": "Tút từ những người bạn theo dõi sẽ hiện theo thứ tự thời gian trên bảng tin. Đừng ngại, bạn có thể dễ dàng ngưng theo dõi họ bất cứ lúc nào!",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Quản lý",
   "getting_started.invite": "Mời bạn bè",
   "getting_started.open_source_notice": "Mastodon là phần mềm mã nguồn mở. Bạn có thể đóng góp hoặc báo lỗi trên GitHub tại {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "Bảo mật",
-  "getting_started.terms": "Điều khoản dịch vụ",
   "hashtag.column_header.tag_mode.all": "và {additional}",
   "hashtag.column_header.tag_mode.any": "hoặc {additional}",
   "hashtag.column_header.tag_mode.none": "mà không {additional}",
@@ -422,7 +423,7 @@
   "report.categories.spam": "Spam",
   "report.categories.violation": "Vi phạm quy tắc máy chủ",
   "report.category.subtitle": "Chọn mục gần khớp nhất",
-  "report.category.title": "Nói với họ chuyện gì xảy ra với {type}",
+  "report.category.title": "Có vấn đề gì với {type}",
   "report.category.title_account": "người dùng",
   "report.category.title_status": "tút",
   "report.close": "Xong",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Không tìm thấy kết quả trùng khớp",
   "search_results.statuses": "Tút",
   "search_results.statuses_fts_disabled": "Máy chủ của bạn không bật tính năng tìm kiếm tút.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {kết quả} other {kết quả}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Mở giao diện quản trị @{name}",
   "status.admin_status": "Mở tút này trong giao diện quản trị",
   "status.block": "Chặn @{name}",
@@ -487,7 +492,7 @@
   "status.edited_x_times": "Đã sửa {count, plural, other {{count} lần}}",
   "status.embed": "Nhúng",
   "status.favourite": "Thích",
-  "status.filter": "Filter this post",
+  "status.filter": "Lọc tút này",
   "status.filtered": "Bộ lọc",
   "status.hide": "Ẩn tút",
   "status.history.created": "{name} tạo lúc {date}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "Thu gọn toàn bộ",
   "status.show_more": "Xem thêm",
   "status.show_more_all": "Hiển thị tất cả",
+  "status.show_original": "Bản gốc",
   "status.show_thread": "Xem chuỗi tút này",
+  "status.translate": "Dịch",
+  "status.translated_from": "Dịch từ {lang}",
   "status.uncached_media_warning": "Uncached",
   "status.unmute_conversation": "Quan tâm",
   "status.unpin": "Bỏ ghim trên hồ sơ",
+  "subscribed_languages.lead": "Chỉ các tút đăng bằng các ngôn ngữ đã chọn mới được xuất hiện trên bảng tin của bạn. Không chọn gì cả để đọc tút đăng bằng mọi ngôn ngữ.",
+  "subscribed_languages.save": "Lưu thay đổi",
+  "subscribed_languages.target": "Đổi ngôn ngữ mong muốn cho {target}",
   "suggestions.dismiss": "Tắt đề xuất",
   "suggestions.header": "Có thể bạn quan tâm…",
   "tabs_bar.federated_timeline": "Thế giới",
diff --git a/app/javascript/mastodon/locales/zgh.json b/app/javascript/mastodon/locales/zgh.json
index 92201375d..9d551e30a 100644
--- a/app/javascript/mastodon/locales/zgh.json
+++ b/app/javascript/mastodon/locales/zgh.json
@@ -24,6 +24,7 @@
   "account.follows_you": "ⴹⴼⵕⵏ ⴽⵯⵏ",
   "account.hide_reblogs": "Hide boosts from @{name}",
   "account.joined": "Joined {date}",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "Ownership of this link was checked on {date}",
   "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.",
   "account.media": "ⴰⵙⵏⵖⵎⵉⵙ",
@@ -226,8 +227,8 @@
   "getting_started.heading": "Getting started",
   "getting_started.invite": "Invite people",
   "getting_started.open_source_notice": "Mastodon is open source software. You can contribute or report issues on GitHub at {github}.",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "ⵜⵉⵙⵖⴰⵍ ⵏ ⵓⵎⵉⴹⴰⵏ",
-  "getting_started.terms": "Terms of service",
   "hashtag.column_header.tag_mode.all": "ⴷ {additional}",
   "hashtag.column_header.tag_mode.any": "ⵏⵖ {additional}",
   "hashtag.column_header.tag_mode.none": "without {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Could not find anything for these search terms",
   "search_results.statuses": "Toots",
   "search_results.statuses_fts_disabled": "Searching toots by their content is not enabled on this Mastodon server.",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} {count, plural, one {result} other {results}}",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "Open moderation interface for @{name}",
   "status.admin_status": "Open this status in the moderation interface",
   "status.block": "ⴳⴷⵍ @{name}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "ⵙⵎⴰⵍ ⴷⵔⵓⵙ ⵉ ⵎⴰⵕⵕⴰ",
   "status.show_more": "ⵙⵎⴰⵍ ⵓⴳⴳⴰⵔ",
   "status.show_more_all": "ⵙⵎⴰⵍ ⵓⴳⴳⴰⵔ ⵉ ⵎⴰⵕⵕⴰ",
+  "status.show_original": "Show original",
   "status.show_thread": "Show thread",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "Not available",
   "status.unmute_conversation": "Unmute conversation",
   "status.unpin": "Unpin from profile",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "Dismiss suggestion",
   "suggestions.header": "You might be interested in…",
   "tabs_bar.federated_timeline": "Federated",
diff --git a/app/javascript/mastodon/locales/zh-CN.json b/app/javascript/mastodon/locales/zh-CN.json
index 9241eeec8..dfddf0a66 100644
--- a/app/javascript/mastodon/locales/zh-CN.json
+++ b/app/javascript/mastodon/locales/zh-CN.json
@@ -24,6 +24,7 @@
   "account.follows_you": "关注了你",
   "account.hide_reblogs": "隐藏来自 @{name} 的转贴",
   "account.joined": "加入于 {date}",
+  "account.languages": "更改订阅语言",
   "account.link_verified_on": "此链接的所有权已在 {date} 检查",
   "account.locked_info": "此账户已锁嘟。账户所有者会手动审核关注者。",
   "account.media": "媒体",
@@ -197,22 +198,22 @@
   "explore.trending_links": "最新消息",
   "explore.trending_statuses": "嘟文",
   "explore.trending_tags": "话题标签",
-  "filter_modal.added.context_mismatch_explanation": "This filter category does not apply to the context in which you have accessed this post. If you want the post to be filtered in this context too, you will have to edit the filter.",
-  "filter_modal.added.context_mismatch_title": "Context mismatch!",
-  "filter_modal.added.expired_explanation": "This filter category has expired, you will need to change the expiration date for it to apply.",
-  "filter_modal.added.expired_title": "Expired filter!",
-  "filter_modal.added.review_and_configure": "To review and further configure this filter category, go to the {settings_link}.",
-  "filter_modal.added.review_and_configure_title": "Filter settings",
-  "filter_modal.added.settings_link": "settings page",
-  "filter_modal.added.short_explanation": "This post has been added to the following filter category: {title}.",
-  "filter_modal.added.title": "Filter added!",
-  "filter_modal.select_filter.context_mismatch": "does not apply to this context",
-  "filter_modal.select_filter.expired": "expired",
-  "filter_modal.select_filter.prompt_new": "New category: {name}",
-  "filter_modal.select_filter.search": "Search or create",
-  "filter_modal.select_filter.subtitle": "Use an existing category or create a new one",
-  "filter_modal.select_filter.title": "Filter this post",
-  "filter_modal.title.status": "Filter a post",
+  "filter_modal.added.context_mismatch_explanation": "此过滤器分类不适用访问过嘟文的环境中。如果你想要在环境中过滤嘟文,你必须编辑此过滤器。",
+  "filter_modal.added.context_mismatch_title": "环境不匹配!",
+  "filter_modal.added.expired_explanation": "此过滤器分类已过期,你需要修改到期日期才能应用。",
+  "filter_modal.added.expired_title": "过滤器已过期!",
+  "filter_modal.added.review_and_configure": "要审核并进一步配置此过滤器分类,请前往{settings_link}。",
+  "filter_modal.added.review_and_configure_title": "过滤器设置",
+  "filter_modal.added.settings_link": "设置页面",
+  "filter_modal.added.short_explanation": "此嘟文已添加到以下过滤器分类:{title}。",
+  "filter_modal.added.title": "过滤器已添加 !",
+  "filter_modal.select_filter.context_mismatch": "不适用于此环境",
+  "filter_modal.select_filter.expired": "已过期",
+  "filter_modal.select_filter.prompt_new": "新分类:{name}",
+  "filter_modal.select_filter.search": "搜索或创建",
+  "filter_modal.select_filter.subtitle": "使用一个已存在分类,或创建一个新分类",
+  "filter_modal.select_filter.title": "过滤此嘟文",
+  "filter_modal.title.status": "过滤一条嘟文",
   "follow_recommendations.done": "完成",
   "follow_recommendations.heading": "关注你感兴趣的用户!这里有一些推荐。",
   "follow_recommendations.lead": "你关注的人的嘟文将按时间顺序在你的主页上显示。 别担心,你可以随时取消关注!",
@@ -226,8 +227,8 @@
   "getting_started.heading": "开始使用",
   "getting_started.invite": "邀请用户",
   "getting_started.open_source_notice": "Mastodon 是开源软件。欢迎前往 GitHub({github})贡献代码或反馈问题。",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "账号设置",
-  "getting_started.terms": "使用条款",
   "hashtag.column_header.tag_mode.all": "以及 {additional}",
   "hashtag.column_header.tag_mode.any": "或是 {additional}",
   "hashtag.column_header.tag_mode.none": "而不用 {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "无法找到符合这些搜索词的任何内容",
   "search_results.statuses": "嘟文",
   "search_results.statuses_fts_disabled": "此 Mastodon 服务器未启用帖子内容搜索。",
+  "search_results.title": "Search for {q}",
   "search_results.total": "共 {count, number} 个结果",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "打开 @{name} 的管理界面",
   "status.admin_status": "打开此帖的管理界面",
   "status.block": "屏蔽 @{name}",
@@ -487,7 +492,7 @@
   "status.edited_x_times": "共编辑 {count, plural, one {{count} 次} other {{count} 次}}",
   "status.embed": "嵌入",
   "status.favourite": "喜欢",
-  "status.filter": "Filter this post",
+  "status.filter": "过滤此嘟文",
   "status.filtered": "已过滤",
   "status.hide": "屏蔽嘟文",
   "status.history.created": "{name} 创建于 {date}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "隐藏全部内容",
   "status.show_more": "显示更多",
   "status.show_more_all": "显示全部内容",
+  "status.show_original": "显示原文",
   "status.show_thread": "显示全部对话",
+  "status.translate": "翻译",
+  "status.translated_from": "翻译自 {lang}",
   "status.uncached_media_warning": "暂不可用",
   "status.unmute_conversation": "恢复此对话的通知提醒",
   "status.unpin": "在个人资料页面取消置顶",
+  "subscribed_languages.lead": "更改此选择后,仅选定语言的嘟文会出现在您的主页和列表时间轴上。选择「无」将接收所有语言的嘟文。",
+  "subscribed_languages.save": "保存更改",
+  "subscribed_languages.target": "为 {target} 更改订阅语言",
   "suggestions.dismiss": "关闭建议",
   "suggestions.header": "你可能会感兴趣…",
   "tabs_bar.federated_timeline": "跨站",
diff --git a/app/javascript/mastodon/locales/zh-HK.json b/app/javascript/mastodon/locales/zh-HK.json
index fdc206800..65c366a01 100644
--- a/app/javascript/mastodon/locales/zh-HK.json
+++ b/app/javascript/mastodon/locales/zh-HK.json
@@ -24,6 +24,7 @@
   "account.follows_you": "關注你",
   "account.hide_reblogs": "隱藏 @{name} 的轉推",
   "account.joined": "於 {date} 加入",
+  "account.languages": "Change subscribed languages",
   "account.link_verified_on": "此連結的所有權已在 {date} 檢查過",
   "account.locked_info": "這位使用者將私隱設定為「不公開」,會手動審批誰能關注他/她。",
   "account.media": "媒體",
@@ -226,8 +227,8 @@
   "getting_started.heading": "開始使用",
   "getting_started.invite": "邀請使用者",
   "getting_started.open_source_notice": "Mastodon(萬象)是一個開放源碼的軟件。你可以在官方 GitHub {github} 貢獻或者回報問題。",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "帳戶設定",
-  "getting_started.terms": "服務條款",
   "hashtag.column_header.tag_mode.all": "以及{additional}",
   "hashtag.column_header.tag_mode.any": "或是{additional}",
   "hashtag.column_header.tag_mode.none": "而無需{additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "Could not find anything for these search terms",
   "search_results.statuses": "文章",
   "search_results.statuses_fts_disabled": "此 Mastodon 伺服器並未啟用「搜尋文章內章」功能。",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} 項結果",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "開啟 @{name} 的管理介面",
   "status.admin_status": "在管理介面開啟這篇文章",
   "status.block": "封鎖 @{name}",
@@ -518,10 +523,16 @@
   "status.show_less_all": "全部收起",
   "status.show_more": "展開",
   "status.show_more_all": "全部展開",
+  "status.show_original": "Show original",
   "status.show_thread": "顯示討論串",
+  "status.translate": "Translate",
+  "status.translated_from": "Translated from {lang}",
   "status.uncached_media_warning": "無法使用",
   "status.unmute_conversation": "對話解除靜音",
   "status.unpin": "解除置頂",
+  "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.",
+  "subscribed_languages.save": "Save changes",
+  "subscribed_languages.target": "Change subscribed languages for {target}",
   "suggestions.dismiss": "關閉建議",
   "suggestions.header": "你可能對這些感興趣…",
   "tabs_bar.federated_timeline": "跨站",
diff --git a/app/javascript/mastodon/locales/zh-TW.json b/app/javascript/mastodon/locales/zh-TW.json
index 13eee62de..42ee65281 100644
--- a/app/javascript/mastodon/locales/zh-TW.json
+++ b/app/javascript/mastodon/locales/zh-TW.json
@@ -24,6 +24,7 @@
   "account.follows_you": "跟隨了您",
   "account.hide_reblogs": "隱藏來自 @{name} 的轉嘟",
   "account.joined": "加入於 {date}",
+  "account.languages": "變更訂閱的語言",
   "account.link_verified_on": "已在 {date} 檢查此連結的擁有者權限",
   "account.locked_info": "此帳戶的隱私狀態被設為鎖定。該擁有者會手動審核能跟隨此帳號的人。",
   "account.media": "媒體",
@@ -197,22 +198,22 @@
   "explore.trending_links": "最新消息",
   "explore.trending_statuses": "嘟文",
   "explore.trending_tags": "主題標籤",
-  "filter_modal.added.context_mismatch_explanation": "This filter category does not apply to the context in which you have accessed this post. If you want the post to be filtered in this context too, you will have to edit the filter.",
-  "filter_modal.added.context_mismatch_title": "Context mismatch!",
-  "filter_modal.added.expired_explanation": "This filter category has expired, you will need to change the expiration date for it to apply.",
-  "filter_modal.added.expired_title": "Expired filter!",
-  "filter_modal.added.review_and_configure": "To review and further configure this filter category, go to the {settings_link}.",
-  "filter_modal.added.review_and_configure_title": "Filter settings",
-  "filter_modal.added.settings_link": "settings page",
-  "filter_modal.added.short_explanation": "This post has been added to the following filter category: {title}.",
-  "filter_modal.added.title": "Filter added!",
-  "filter_modal.select_filter.context_mismatch": "does not apply to this context",
-  "filter_modal.select_filter.expired": "expired",
-  "filter_modal.select_filter.prompt_new": "New category: {name}",
-  "filter_modal.select_filter.search": "Search or create",
-  "filter_modal.select_filter.subtitle": "Use an existing category or create a new one",
-  "filter_modal.select_filter.title": "Filter this post",
-  "filter_modal.title.status": "Filter a post",
+  "filter_modal.added.context_mismatch_explanation": "此過濾器類別不是用您所存取嘟文的情境。若您想要此嘟文被於此情境被過濾,您必須編輯過濾器。",
+  "filter_modal.added.context_mismatch_title": "不符合情境!",
+  "filter_modal.added.expired_explanation": "此過濾器類別已失效,您需要更新過期日期以套用。",
+  "filter_modal.added.expired_title": "過期的過濾器!",
+  "filter_modal.added.review_and_configure": "若欲檢視和進一步設定此過濾器類別,請至 {settings_link}。",
+  "filter_modal.added.review_and_configure_title": "過濾器設定",
+  "filter_modal.added.settings_link": "設定頁面",
+  "filter_modal.added.short_explanation": "此嘟文已被新增至以下過濾器類別:{title}。",
+  "filter_modal.added.title": "已新增過濾器!",
+  "filter_modal.select_filter.context_mismatch": "不是用目前情境",
+  "filter_modal.select_filter.expired": "已過期",
+  "filter_modal.select_filter.prompt_new": "新類別:{name}",
+  "filter_modal.select_filter.search": "搜尋或新增",
+  "filter_modal.select_filter.subtitle": "使用既有的類別或是新增",
+  "filter_modal.select_filter.title": "過濾此嘟文",
+  "filter_modal.title.status": "過濾一則嘟文",
   "follow_recommendations.done": "完成",
   "follow_recommendations.heading": "跟隨您想檢視其嘟文的人!這裡有一些建議。",
   "follow_recommendations.lead": "來自您跟隨的人之嘟文將會按時間順序顯示在您的首頁時間軸上。不要害怕犯錯,您隨時都可以取消跟隨其他人!",
@@ -226,8 +227,8 @@
   "getting_started.heading": "開始使用",
   "getting_started.invite": "邀請使用者",
   "getting_started.open_source_notice": "Mastodon 是開源軟體。您可以在 GitHub {github} 上貢獻或是回報問題。",
+  "getting_started.privacy_policy": "Privacy Policy",
   "getting_started.security": "帳號安全性設定",
-  "getting_started.terms": "服務條款",
   "hashtag.column_header.tag_mode.all": "以及 {additional}",
   "hashtag.column_header.tag_mode.any": "或是 {additional}",
   "hashtag.column_header.tag_mode.none": "而無需 {additional}",
@@ -471,7 +472,11 @@
   "search_results.nothing_found": "無法找到符合搜尋條件之結果",
   "search_results.statuses": "嘟文",
   "search_results.statuses_fts_disabled": "「依內容搜尋嘟文」未在此 Mastodon 伺服器啟用。",
+  "search_results.title": "Search for {q}",
   "search_results.total": "{count, number} 項結果",
+  "sign_in_banner.create_account": "Create account",
+  "sign_in_banner.sign_in": "Sign in",
+  "sign_in_banner.text": "Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.",
   "status.admin_account": "開啟 @{name} 的管理介面",
   "status.admin_status": "在管理介面開啟此嘟文",
   "status.block": "封鎖 @{name}",
@@ -487,7 +492,7 @@
   "status.edited_x_times": "已編輯 {count, plural, one {{count} 次} other {{count} 次}}",
   "status.embed": "內嵌",
   "status.favourite": "最愛",
-  "status.filter": "Filter this post",
+  "status.filter": "過濾此嘟文",
   "status.filtered": "已過濾",
   "status.hide": "隱藏嘟文",
   "status.history.created": "{name} 於 {date} 建立",
@@ -518,10 +523,16 @@
   "status.show_less_all": "減少顯示這類嘟文",
   "status.show_more": "顯示更多",
   "status.show_more_all": "顯示更多這類嘟文",
+  "status.show_original": "顯示原文",
   "status.show_thread": "顯示討論串",
+  "status.translate": "翻譯",
+  "status.translated_from": "翻譯自 {lang}",
   "status.uncached_media_warning": "無法使用",
   "status.unmute_conversation": "解除此對話的靜音",
   "status.unpin": "從個人檔案頁面解除釘選",
+  "subscribed_languages.lead": "僅選定語言的嘟文才會出現在您的首頁上,並在變更後列出時間軸。選取「無」以接收所有語言的嘟文。",
+  "subscribed_languages.save": "儲存變更",
+  "subscribed_languages.target": "變更 {target} 的訂閱語言",
   "suggestions.dismiss": "關閉建議",
   "suggestions.header": "您可能對這些東西有興趣…",
   "tabs_bar.federated_timeline": "聯邦宇宙",
diff --git a/app/javascript/mastodon/reducers/statuses.js b/app/javascript/mastodon/reducers/statuses.js
index 53dec9585..7efb49d85 100644
--- a/app/javascript/mastodon/reducers/statuses.js
+++ b/app/javascript/mastodon/reducers/statuses.js
@@ -13,6 +13,8 @@ import {
   STATUS_REVEAL,
   STATUS_HIDE,
   STATUS_COLLAPSE,
+  STATUS_TRANSLATE_SUCCESS,
+  STATUS_TRANSLATE_UNDO,
 } from '../actions/statuses';
 import { TIMELINE_DELETE } from '../actions/timelines';
 import { STATUS_IMPORT, STATUSES_IMPORT } from '../actions/importer';
@@ -77,6 +79,10 @@ export default function statuses(state = initialState, action) {
     return state.setIn([action.id, 'collapsed'], action.isCollapsed);
   case TIMELINE_DELETE:
     return deleteStatus(state, action.id, action.references);
+  case STATUS_TRANSLATE_SUCCESS:
+    return state.setIn([action.id, 'translation'], fromJS(action.translation));
+  case STATUS_TRANSLATE_UNDO:
+    return state.deleteIn([action.id, 'translation']);
   default:
     return state;
   }
diff --git a/app/javascript/mastodon/utils/icons.js b/app/javascript/mastodon/utils/icons.js
index be566032e..c3e362e39 100644
--- a/app/javascript/mastodon/utils/icons.js
+++ b/app/javascript/mastodon/utils/icons.js
@@ -1,3 +1,5 @@
+import React from 'react';
+
 // Copied from emoji-mart for consistency with emoji picker and since
 // they don't export the icons in the package
 export const loupeIcon = (
diff --git a/app/javascript/styles/mastodon/_mixins.scss b/app/javascript/styles/mastodon/_mixins.scss
index 68cad0fde..dcfab6bd0 100644
--- a/app/javascript/styles/mastodon/_mixins.scss
+++ b/app/javascript/styles/mastodon/_mixins.scss
@@ -20,6 +20,7 @@
   font-family: inherit;
   background: $ui-base-color;
   color: $darker-text-color;
+  border-radius: 4px;
   font-size: 14px;
   margin: 0;
 }
diff --git a/app/javascript/styles/mastodon/accounts.scss b/app/javascript/styles/mastodon/accounts.scss
index 54b65bfc8..c007eb4b5 100644
--- a/app/javascript/styles/mastodon/accounts.scss
+++ b/app/javascript/styles/mastodon/accounts.scss
@@ -202,7 +202,8 @@
 }
 
 .account-role,
-.simple_form .recommended {
+.simple_form .recommended,
+.simple_form .not_recommended {
   display: inline-block;
   padding: 4px 6px;
   cursor: default;
@@ -227,6 +228,12 @@
   }
 }
 
+.simple_form .not_recommended {
+  color: lighten($error-red, 12%);
+  background-color: rgba(lighten($error-red, 12%), 0.1);
+  border-color: rgba(lighten($error-red, 12%), 0.5);
+}
+
 .account__header__fields {
   max-width: 100vw;
   padding: 0;
diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss
index 00f654082..a75437b1c 100644
--- a/app/javascript/styles/mastodon/components.scss
+++ b/app/javascript/styles/mastodon/components.scss
@@ -126,6 +126,27 @@
     &:hover {
       border-color: lighten($ui-primary-color, 4%);
       color: lighten($darker-text-color, 4%);
+      text-decoration: none;
+    }
+
+    &:disabled {
+      opacity: 0.5;
+    }
+  }
+
+  &.button-tertiary {
+    background: transparent;
+    padding: 6px 17px;
+    color: $highlight-text-color;
+    border: 1px solid $highlight-text-color;
+
+    &:active,
+    &:focus,
+    &:hover {
+      background: $ui-highlight-color;
+      color: $primary-text-color;
+      border: 0;
+      padding: 7px 18px;
     }
 
     &:disabled {
@@ -700,6 +721,19 @@
   transition: height 0.4s ease, opacity 0.4s ease;
 }
 
+.sign-in-banner {
+  padding: 10px;
+
+  p {
+    color: $darker-text-color;
+    margin-bottom: 20px;
+  }
+
+  .button {
+    margin-bottom: 10px;
+  }
+}
+
 .emojione {
   font-size: inherit;
   vertical-align: middle;
@@ -2214,6 +2248,7 @@ a.account__display-name {
 
   > .scrollable {
     background: $ui-base-color;
+    border-radius: 0 0 4px 4px;
   }
 }
 
@@ -2660,6 +2695,26 @@ a.account__display-name {
   height: calc(100% - 10px);
   overflow-y: hidden;
 
+  .hero-widget {
+    box-shadow: none;
+
+    &__text,
+    &__img,
+    &__img img {
+      border-radius: 0;
+    }
+
+    &__text {
+      padding: 15px;
+      color: $secondary-text-color;
+
+      strong {
+        font-weight: 700;
+        color: $primary-text-color;
+      }
+    }
+  }
+
   .navigation-bar {
     padding-top: 20px;
     padding-bottom: 20px;
@@ -2667,10 +2722,6 @@ a.account__display-name {
     min-height: 20px;
   }
 
-  .flex-spacer {
-    background: transparent;
-  }
-
   .compose-form {
     flex: 1;
     overflow-y: hidden;
@@ -2709,6 +2760,14 @@ a.account__display-name {
     flex: 0 0 auto;
   }
 
+  .logo {
+    height: 30px;
+    width: auto;
+  }
+}
+
+.navigation-panel,
+.compose-panel {
   hr {
     flex: 0 0 auto;
     border: 0;
@@ -2836,6 +2895,7 @@ a.account__display-name {
   box-sizing: border-box;
   width: 100%;
   background: lighten($ui-base-color, 4%);
+  border-radius: 4px 4px 0 0;
   color: $highlight-text-color;
   cursor: pointer;
   flex: 0 0 auto;
@@ -3031,6 +3091,17 @@ a.account__display-name {
       color: $highlight-text-color;
     }
   }
+
+  &--logo {
+    background: transparent;
+    padding: 10px;
+
+    &:hover,
+    &:focus,
+    &:active {
+      background: transparent;
+    }
+  }
 }
 
 .column-link__icon {
@@ -3551,6 +3622,7 @@ a.status-card.compact:hover {
   display: flex;
   font-size: 16px;
   background: lighten($ui-base-color, 4%);
+  border-radius: 4px 4px 0 0;
   flex: 0 0 auto;
   cursor: pointer;
   position: relative;
@@ -3623,6 +3695,11 @@ a.status-card.compact:hover {
       background: lighten($ui-base-color, 8%);
     }
   }
+
+  &:disabled {
+    color: $dark-text-color;
+    cursor: default;
+  }
 }
 
 .column-header__collapsible {
diff --git a/app/javascript/styles/mastodon/forms.scss b/app/javascript/styles/mastodon/forms.scss
index 990903859..a6419821f 100644
--- a/app/javascript/styles/mastodon/forms.scss
+++ b/app/javascript/styles/mastodon/forms.scss
@@ -102,7 +102,8 @@ code {
         }
       }
 
-      .recommended {
+      .recommended,
+      .not_recommended {
         position: absolute;
         margin: 0 4px;
         margin-top: -2px;
diff --git a/app/lib/activitypub/activity.rb b/app/lib/activitypub/activity.rb
index 7ff06ea39..f4c67cccd 100644
--- a/app/lib/activitypub/activity.rb
+++ b/app/lib/activitypub/activity.rb
@@ -116,12 +116,12 @@ class ActivityPub::Activity
   def dereference_object!
     return unless @object.is_a?(String)
 
-    dereferencer = ActivityPub::Dereferencer.new(@object, permitted_origin: @account.uri, signature_account: signed_fetch_account)
+    dereferencer = ActivityPub::Dereferencer.new(@object, permitted_origin: @account.uri, signature_actor: signed_fetch_actor)
 
     @object = dereferencer.object unless dereferencer.object.nil?
   end
 
-  def signed_fetch_account
+  def signed_fetch_actor
     return Account.find(@options[:delivered_to_account_id]) if @options[:delivered_to_account_id].present?
 
     first_mentioned_local_account || first_local_follower
@@ -163,15 +163,15 @@ class ActivityPub::Activity
   end
 
   def followed_by_local_accounts?
-    @account.passive_relationships.exists? || @options[:relayed_through_account]&.passive_relationships&.exists?
+    @account.passive_relationships.exists? || (@options[:relayed_through_actor].is_a?(Account) && @options[:relayed_through_actor].passive_relationships&.exists?)
   end
 
   def requested_through_relay?
-    @options[:relayed_through_account] && Relay.find_by(inbox_url: @options[:relayed_through_account].inbox_url)&.enabled?
+    @options[:relayed_through_actor] && Relay.find_by(inbox_url: @options[:relayed_through_actor].inbox_url)&.enabled?
   end
 
   def reject_payload!
-    Rails.logger.info("Rejected #{@json['type']} activity #{@json['id']} from #{@account.uri}#{@options[:relayed_through_account] && "via #{@options[:relayed_through_account].uri}"}")
+    Rails.logger.info("Rejected #{@json['type']} activity #{@json['id']} from #{@account.uri}#{@options[:relayed_through_actor] && "via #{@options[:relayed_through_actor].uri}"}")
     nil
   end
 end
diff --git a/app/lib/activitypub/dereferencer.rb b/app/lib/activitypub/dereferencer.rb
index bea69608f..4d7756d71 100644
--- a/app/lib/activitypub/dereferencer.rb
+++ b/app/lib/activitypub/dereferencer.rb
@@ -3,10 +3,10 @@
 class ActivityPub::Dereferencer
   include JsonLdHelper
 
-  def initialize(uri, permitted_origin: nil, signature_account: nil)
+  def initialize(uri, permitted_origin: nil, signature_actor: nil)
     @uri               = uri
     @permitted_origin  = permitted_origin
-    @signature_account = signature_account
+    @signature_actor = signature_actor
   end
 
   def object
@@ -46,7 +46,7 @@ class ActivityPub::Dereferencer
 
     req.add_headers('Accept' => 'application/activity+json, application/ld+json')
     req.add_headers(headers) if headers
-    req.on_behalf_of(@signature_account) if @signature_account
+    req.on_behalf_of(@signature_actor) if @signature_actor
 
     req.perform do |res|
       if res.code == 200
diff --git a/app/lib/activitypub/linked_data_signature.rb b/app/lib/activitypub/linked_data_signature.rb
index e853a970e..f90adaf6c 100644
--- a/app/lib/activitypub/linked_data_signature.rb
+++ b/app/lib/activitypub/linked_data_signature.rb
@@ -9,7 +9,7 @@ class ActivityPub::LinkedDataSignature
     @json = json.with_indifferent_access
   end
 
-  def verify_account!
+  def verify_actor!
     return unless @json['signature'].is_a?(Hash)
 
     type        = @json['signature']['type']
@@ -18,7 +18,7 @@ class ActivityPub::LinkedDataSignature
 
     return unless type == 'RsaSignature2017'
 
-    creator   = ActivityPub::TagManager.instance.uri_to_resource(creator_uri, Account)
+    creator   = ActivityPub::TagManager.instance.uri_to_actor(creator_uri)
     creator ||= ActivityPub::FetchRemoteKeyService.new.call(creator_uri, id: false)
 
     return if creator.nil?
@@ -35,7 +35,7 @@ class ActivityPub::LinkedDataSignature
   def sign!(creator, sign_with: nil)
     options = {
       'type'    => 'RsaSignature2017',
-      'creator' => [ActivityPub::TagManager.instance.uri_for(creator), '#main-key'].join,
+      'creator' => ActivityPub::TagManager.instance.key_uri_for(creator),
       'created' => Time.now.utc.iso8601,
     }
 
diff --git a/app/lib/activitypub/tag_manager.rb b/app/lib/activitypub/tag_manager.rb
index f6b9741fa..3d6b28ef5 100644
--- a/app/lib/activitypub/tag_manager.rb
+++ b/app/lib/activitypub/tag_manager.rb
@@ -44,6 +44,10 @@ class ActivityPub::TagManager
     end
   end
 
+  def key_uri_for(target)
+    [uri_for(target), '#main-key'].join
+  end
+
   def uri_for_username(username)
     account_url(username: username)
   end
@@ -155,6 +159,10 @@ class ActivityPub::TagManager
     path_params[param]
   end
 
+  def uri_to_actor(uri)
+    uri_to_resource(uri, Account)
+  end
+
   def uri_to_resource(uri, klass)
     return if uri.nil?
 
diff --git a/app/lib/feed_manager.rb b/app/lib/feed_manager.rb
index c607223fc..0bc7e254e 100644
--- a/app/lib/feed_manager.rb
+++ b/app/lib/feed_manager.rb
@@ -403,6 +403,7 @@ class FeedManager
   def filter_from_home?(status, receiver_id, crutches)
     return false if receiver_id == status.account_id
     return true  if status.reply? && (status.in_reply_to_id.nil? || status.in_reply_to_account_id.nil?)
+    return true  if crutches[:languages][status.account_id].present? && status.language.present? && !crutches[:languages][status.account_id].include?(status.language)
 
     check_for_blocks = crutches[:active_mentions][status.id] || []
     check_for_blocks.concat([status.account_id])
@@ -600,6 +601,7 @@ class FeedManager
     end
 
     crutches[:following]       = Follow.where(account_id: receiver_id, target_account_id: statuses.map(&:in_reply_to_account_id).compact).pluck(:target_account_id).index_with(true)
+    crutches[:languages]       = Follow.where(account_id: receiver_id, target_account_id: statuses.map(&:account_id)).pluck(:target_account_id, :languages).to_h
     crutches[:hiding_reblogs]  = Follow.where(account_id: receiver_id, target_account_id: statuses.map { |s| s.account_id if s.reblog? }.compact, show_reblogs: false).pluck(:target_account_id).index_with(true)
     crutches[:blocking]        = Block.where(account_id: receiver_id, target_account_id: check_for_blocks).pluck(:target_account_id).index_with(true)
     crutches[:muting]          = Mute.where(account_id: receiver_id, target_account_id: check_for_blocks).pluck(:target_account_id).index_with(true)
diff --git a/app/lib/permalink_redirector.rb b/app/lib/permalink_redirector.rb
index e48bce060..6d15f3963 100644
--- a/app/lib/permalink_redirector.rb
+++ b/app/lib/permalink_redirector.rb
@@ -17,10 +17,6 @@ class PermalinkRedirector
         find_status_url_by_id(path_segments[2])
       elsif path_segments[1] == 'accounts' && path_segments[2] =~ /\d/
         find_account_url_by_id(path_segments[2])
-      elsif path_segments[1] == 'timelines' && path_segments[2] == 'tag' && path_segments[3].present?
-        find_tag_url_by_name(path_segments[3])
-      elsif path_segments[1] == 'tags' && path_segments[2].present?
-        find_tag_url_by_name(path_segments[2])
       end
     end
   end
diff --git a/app/lib/redis_configuration.rb b/app/lib/redis_configuration.rb
index e14d6c8b6..f0e86d985 100644
--- a/app/lib/redis_configuration.rb
+++ b/app/lib/redis_configuration.rb
@@ -7,9 +7,7 @@ class RedisConfiguration
       @pool = ConnectionPool.new(size: new_pool_size) { new.connection }
     end
 
-    def with
-      pool.with { |redis| yield redis }
-    end
+    delegate :with, to: :pool
 
     def pool
       @pool ||= establish_pool(pool_size)
@@ -17,7 +15,7 @@ class RedisConfiguration
 
     def pool_size
       if Sidekiq.server?
-        Sidekiq.options[:concurrency]
+        Sidekiq[:concurrency]
       else
         ENV['MAX_THREADS'] || 5
       end
diff --git a/app/lib/request.rb b/app/lib/request.rb
index f5123d776..648aa3085 100644
--- a/app/lib/request.rb
+++ b/app/lib/request.rb
@@ -40,12 +40,11 @@ class Request
     set_digest! if options.key?(:body)
   end
 
-  def on_behalf_of(account, key_id_format = :uri, sign_with: nil)
-    raise ArgumentError, 'account must not be nil' if account.nil?
+  def on_behalf_of(actor, sign_with: nil)
+    raise ArgumentError, 'actor must not be nil' if actor.nil?
 
-    @account       = account
-    @keypair       = sign_with.present? ? OpenSSL::PKey::RSA.new(sign_with) : @account.keypair
-    @key_id_format = key_id_format
+    @actor         = actor
+    @keypair       = sign_with.present? ? OpenSSL::PKey::RSA.new(sign_with) : @actor.keypair
 
     self
   end
@@ -79,7 +78,7 @@ class Request
   end
 
   def headers
-    (@account ? @headers.merge('Signature' => signature) : @headers).without(REQUEST_TARGET)
+    (@actor ? @headers.merge('Signature' => signature) : @headers).without(REQUEST_TARGET)
   end
 
   class << self
@@ -128,12 +127,7 @@ class Request
   end
 
   def key_id
-    case @key_id_format
-    when :acct
-      @account.to_webfinger_s
-    when :uri
-      [ActivityPub::TagManager.instance.uri_for(@account), '#main-key'].join
-    end
+    ActivityPub::TagManager.instance.key_uri_for(@actor)
   end
 
   def http_client
@@ -208,7 +202,7 @@ class Request
 
         addresses.each do |address|
           begin
-            check_private_address(address)
+            check_private_address(address, host)
 
             sock     = ::Socket.new(address.is_a?(Resolv::IPv6) ? ::Socket::AF_INET6 : ::Socket::AF_INET, ::Socket::SOCK_STREAM, 0)
             sockaddr = ::Socket.pack_sockaddr_in(port, address.to_s)
@@ -264,10 +258,10 @@ class Request
 
       alias new open
 
-      def check_private_address(address)
+      def check_private_address(address, host)
         addr = IPAddr.new(address.to_s)
         return if private_address_exceptions.any? { |range| range.include?(addr) }
-        raise Mastodon::HostValidationError if PrivateAddressCheck.private_address?(addr)
+        raise Mastodon::PrivateNetworkAddressError, host if PrivateAddressCheck.private_address?(addr)
       end
 
       def private_address_exceptions
diff --git a/app/lib/translation_service.rb b/app/lib/translation_service.rb
new file mode 100644
index 000000000..526e26ae5
--- /dev/null
+++ b/app/lib/translation_service.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+class TranslationService
+  class Error < StandardError; end
+  class NotConfiguredError < Error; end
+  class TooManyRequestsError < Error; end
+  class QuotaExceededError < Error; end
+  class UnexpectedResponseError < Error; end
+
+  def self.configured
+    if ENV['DEEPL_API_KEY'].present?
+      TranslationService::DeepL.new(ENV.fetch('DEEPL_PLAN', 'free'), ENV['DEEPL_API_KEY'])
+    elsif ENV['LIBRE_TRANSLATE_ENDPOINT'].present?
+      TranslationService::LibreTranslate.new(ENV['LIBRE_TRANSLATE_ENDPOINT'], ENV['LIBRE_TRANSLATE_API_KEY'])
+    else
+      raise NotConfiguredError
+    end
+  end
+
+  def translate(_text, _source_language, _target_language)
+    raise NotImplementedError
+  end
+end
diff --git a/app/lib/translation_service/deepl.rb b/app/lib/translation_service/deepl.rb
new file mode 100644
index 000000000..b75b604a8
--- /dev/null
+++ b/app/lib/translation_service/deepl.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+class TranslationService::DeepL < TranslationService
+  include JsonLdHelper
+
+  def initialize(plan, api_key)
+    super()
+
+    @plan    = plan
+    @api_key = api_key
+  end
+
+  def translate(text, source_language, target_language)
+    request(text, source_language, target_language).perform do |res|
+      case res.code
+      when 429
+        raise TooManyRequestsError
+      when 456
+        raise QuotaExceededError
+      when 200...300
+        transform_response(res.body_with_limit)
+      else
+        raise UnexpectedResponseError
+      end
+    end
+  end
+
+  private
+
+  def request(text, source_language, target_language)
+    req = Request.new(:post, endpoint_url, form: { text: text, source_lang: source_language&.upcase, target_lang: target_language, tag_handling: 'html' })
+    req.add_headers('Authorization': "DeepL-Auth-Key #{@api_key}")
+    req
+  end
+
+  def endpoint_url
+    if @plan == 'free'
+      'https://api-free.deepl.com/v2/translate'
+    else
+      'https://api.deepl.com/v2/translate'
+    end
+  end
+
+  def transform_response(str)
+    json = Oj.load(str, mode: :strict)
+
+    raise UnexpectedResponseError unless json.is_a?(Hash)
+
+    Translation.new(text: json.dig('translations', 0, 'text'), detected_source_language: json.dig('translations', 0, 'detected_source_language')&.downcase)
+  rescue Oj::ParseError
+    raise UnexpectedResponseError
+  end
+end
diff --git a/app/lib/translation_service/libre_translate.rb b/app/lib/translation_service/libre_translate.rb
new file mode 100644
index 000000000..8cf26f868
--- /dev/null
+++ b/app/lib/translation_service/libre_translate.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+class TranslationService::LibreTranslate < TranslationService
+  def initialize(base_url, api_key)
+    super()
+
+    @base_url = base_url
+    @api_key  = api_key
+  end
+
+  def translate(text, source_language, target_language)
+    request(text, source_language, target_language).perform do |res|
+      case res.code
+      when 429
+        raise TooManyRequestsError
+      when 403
+        raise QuotaExceededError
+      when 200...300
+        transform_response(res.body_with_limit, source_language)
+      else
+        raise UnexpectedResponseError
+      end
+    end
+  end
+
+  private
+
+  def request(text, source_language, target_language)
+    body = Oj.dump(q: text, source: source_language.presence || 'auto', target: target_language, format: 'html', api_key: @api_key)
+    req = Request.new(:post, "#{@base_url}/translate", body: body)
+    req.add_headers('Content-Type': 'application/json')
+    req
+  end
+
+  def transform_response(str, source_language)
+    json = Oj.load(str, mode: :strict)
+
+    raise UnexpectedResponseError unless json.is_a?(Hash)
+
+    Translation.new(text: json['translatedText'], detected_source_language: source_language)
+  rescue Oj::ParseError
+    raise UnexpectedResponseError
+  end
+end
diff --git a/app/lib/translation_service/translation.rb b/app/lib/translation_service/translation.rb
new file mode 100644
index 000000000..a55b82574
--- /dev/null
+++ b/app/lib/translation_service/translation.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+class TranslationService::Translation < ActiveModelSerializers::Model
+  attributes :text, :detected_source_language
+end
diff --git a/app/lib/vacuum.rb b/app/lib/vacuum.rb
new file mode 100644
index 000000000..9db1ec90b
--- /dev/null
+++ b/app/lib/vacuum.rb
@@ -0,0 +1,3 @@
+# frozen_string_literal: true
+
+module Vacuum; end
diff --git a/app/workers/scheduler/doorkeeper_cleanup_scheduler.rb b/app/lib/vacuum/access_tokens_vacuum.rb
index 9303a352f..4f3878027 100644
--- a/app/workers/scheduler/doorkeeper_cleanup_scheduler.rb
+++ b/app/lib/vacuum/access_tokens_vacuum.rb
@@ -1,13 +1,18 @@
 # frozen_string_literal: true
 
-class Scheduler::DoorkeeperCleanupScheduler
-  include Sidekiq::Worker
+class Vacuum::AccessTokensVacuum
+  def perform
+    vacuum_revoked_access_tokens!
+    vacuum_revoked_access_grants!
+  end
 
-  sidekiq_options retry: 0
+  private
 
-  def perform
+  def vacuum_revoked_access_tokens!
     Doorkeeper::AccessToken.where('revoked_at IS NOT NULL').where('revoked_at < NOW()').delete_all
+  end
+
+  def vacuum_revoked_access_grants!
     Doorkeeper::AccessGrant.where('revoked_at IS NOT NULL').where('revoked_at < NOW()').delete_all
-    SystemKey.expired.delete_all
   end
 end
diff --git a/app/lib/vacuum/backups_vacuum.rb b/app/lib/vacuum/backups_vacuum.rb
new file mode 100644
index 000000000..3b83072f3
--- /dev/null
+++ b/app/lib/vacuum/backups_vacuum.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+class Vacuum::BackupsVacuum
+  def initialize(retention_period)
+    @retention_period = retention_period
+  end
+
+  def perform
+    vacuum_expired_backups! if retention_period?
+  end
+
+  private
+
+  def vacuum_expired_backups!
+    backups_past_retention_period.in_batches.destroy_all
+  end
+
+  def backups_past_retention_period
+    Backup.unscoped.where(Backup.arel_table[:created_at].lt(@retention_period.ago))
+  end
+
+  def retention_period?
+    @retention_period.present?
+  end
+end
diff --git a/app/lib/vacuum/feeds_vacuum.rb b/app/lib/vacuum/feeds_vacuum.rb
new file mode 100644
index 000000000..00b9fd646
--- /dev/null
+++ b/app/lib/vacuum/feeds_vacuum.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+class Vacuum::FeedsVacuum
+  def perform
+    vacuum_inactive_home_feeds!
+    vacuum_inactive_list_feeds!
+    vacuum_inactive_direct_feeds!
+  end
+
+  private
+
+  def vacuum_inactive_home_feeds!
+    inactive_users.select(:id, :account_id).find_in_batches do |users|
+      feed_manager.clean_feeds!(:home, users.map(&:account_id))
+    end
+  end
+
+  def vacuum_inactive_list_feeds!
+    inactive_users_lists.select(:id).find_in_batches do |lists|
+      feed_manager.clean_feeds!(:list, lists.map(&:id))
+    end
+  end
+
+  def vacuum_inactive_direct_feeds!
+    inactive_users_lists.select(:id).find_in_batches do |lists|
+      feed_manager.clean_feeds!(:direct, lists.map(&:id))
+    end
+  end
+
+  def inactive_users
+    User.confirmed.inactive
+  end
+
+  def inactive_users_lists
+    List.where(account_id: inactive_users.select(:account_id))
+  end
+
+  def feed_manager
+    FeedManager.instance
+  end
+end
diff --git a/app/lib/vacuum/media_attachments_vacuum.rb b/app/lib/vacuum/media_attachments_vacuum.rb
new file mode 100644
index 000000000..7fb347ce4
--- /dev/null
+++ b/app/lib/vacuum/media_attachments_vacuum.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+class Vacuum::MediaAttachmentsVacuum
+  TTL = 1.day.freeze
+
+  def initialize(retention_period)
+    @retention_period = retention_period
+  end
+
+  def perform
+    vacuum_cached_files! if retention_period?
+    vacuum_orphaned_records!
+  end
+
+  private
+
+  def vacuum_cached_files!
+    media_attachments_past_retention_period.find_each do |media_attachment|
+      media_attachment.file.destroy
+      media_attachment.thumbnail.destroy
+      media_attachment.save
+    end
+  end
+
+  def vacuum_orphaned_records!
+    orphaned_media_attachments.in_batches.destroy_all
+  end
+
+  def media_attachments_past_retention_period
+    MediaAttachment.unscoped.remote.cached.where(MediaAttachment.arel_table[:created_at].lt(@retention_period.ago)).where(MediaAttachment.arel_table[:updated_at].lt(@retention_period.ago))
+  end
+
+  def orphaned_media_attachments
+    MediaAttachment.unscoped.unattached.where(MediaAttachment.arel_table[:created_at].lt(TTL.ago))
+  end
+
+  def retention_period?
+    @retention_period.present?
+  end
+end
diff --git a/app/lib/vacuum/preview_cards_vacuum.rb b/app/lib/vacuum/preview_cards_vacuum.rb
new file mode 100644
index 000000000..84ef100ed
--- /dev/null
+++ b/app/lib/vacuum/preview_cards_vacuum.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+class Vacuum::PreviewCardsVacuum
+  TTL = 1.day.freeze
+
+  def initialize(retention_period)
+    @retention_period = retention_period
+  end
+
+  def perform
+    vacuum_cached_images! if retention_period?
+    vacuum_orphaned_records!
+  end
+
+  private
+
+  def vacuum_cached_images!
+    preview_cards_past_retention_period.find_each do |preview_card|
+      preview_card.image.destroy
+      preview_card.save
+    end
+  end
+
+  def vacuum_orphaned_records!
+    orphaned_preview_cards.in_batches.destroy_all
+  end
+
+  def preview_cards_past_retention_period
+    PreviewCard.cached.where(PreviewCard.arel_table[:updated_at].lt(@retention_period.ago))
+  end
+
+  def orphaned_preview_cards
+    PreviewCard.where('NOT EXISTS (SELECT 1 FROM preview_cards_statuses WHERE preview_cards_statuses.preview_card_id = preview_cards.id)').where(PreviewCard.arel_table[:created_at].lt(TTL.ago))
+  end
+
+  def retention_period?
+    @retention_period.present?
+  end
+end
diff --git a/app/lib/vacuum/statuses_vacuum.rb b/app/lib/vacuum/statuses_vacuum.rb
new file mode 100644
index 000000000..41d6ba270
--- /dev/null
+++ b/app/lib/vacuum/statuses_vacuum.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+class Vacuum::StatusesVacuum
+  include Redisable
+
+  def initialize(retention_period)
+    @retention_period = retention_period
+  end
+
+  def perform
+    vacuum_statuses! if retention_period?
+  end
+
+  private
+
+  def vacuum_statuses!
+    statuses_scope.find_in_batches do |statuses|
+      # Side-effects not covered by foreign keys, such
+      # as the search index, must be handled first.
+
+      remove_from_account_conversations(statuses)
+      remove_from_search_index(statuses)
+
+      # Foreign keys take care of most associated records
+      # for us. Media attachments will be orphaned.
+
+      Status.where(id: statuses.map(&:id)).delete_all
+    end
+  end
+
+  def statuses_scope
+    Status.unscoped.kept.where(account: Account.remote).where(Status.arel_table[:id].lt(retention_period_as_id)).select(:id, :visibility)
+  end
+
+  def retention_period_as_id
+    Mastodon::Snowflake.id_at(@retention_period.ago, with_random: false)
+  end
+
+  def analyze_statuses!
+    ActiveRecord::Base.connection.execute('ANALYZE statuses')
+  end
+
+  def remove_from_account_conversations(statuses)
+    Status.where(id: statuses.select(&:direct_visibility?).map(&:id)).includes(:account, mentions: :account).each(&:unlink_from_conversations)
+  end
+
+  def remove_from_search_index(statuses)
+    with_redis { |redis| redis.sadd('chewy:queue:StatusesIndex', statuses.map(&:id)) } if Chewy.enabled?
+  end
+
+  def retention_period?
+    @retention_period.present?
+  end
+end
diff --git a/app/lib/vacuum/system_keys_vacuum.rb b/app/lib/vacuum/system_keys_vacuum.rb
new file mode 100644
index 000000000..ceee2fd16
--- /dev/null
+++ b/app/lib/vacuum/system_keys_vacuum.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class Vacuum::SystemKeysVacuum
+  def perform
+    vacuum_expired_system_keys!
+  end
+
+  private
+
+  def vacuum_expired_system_keys!
+    SystemKey.expired.delete_all
+  end
+end
diff --git a/app/lib/webfinger.rb b/app/lib/webfinger.rb
index a681e0815..7c0c10c33 100644
--- a/app/lib/webfinger.rb
+++ b/app/lib/webfinger.rb
@@ -3,7 +3,7 @@
 class Webfinger
   class Error < StandardError; end
   class GoneError < Error; end
-  class RedirectError < StandardError; end
+  class RedirectError < Error; end
 
   class Response
     attr_reader :uri
diff --git a/app/models/account.rb b/app/models/account.rb
index f75750838..33870beda 100644
--- a/app/models/account.rb
+++ b/app/models/account.rb
@@ -262,6 +262,10 @@ class Account < ApplicationRecord
     update!(memorial: true)
   end
 
+  def trendable
+    boolean_with_default('trendable', Setting.trendable_by_default)
+  end
+
   def sign?
     true
   end
diff --git a/app/models/concerns/account_interactions.rb b/app/models/concerns/account_interactions.rb
index 9b358d338..15c49f2fe 100644
--- a/app/models/concerns/account_interactions.rb
+++ b/app/models/concerns/account_interactions.rb
@@ -9,6 +9,7 @@ module AccountInteractions
         mapping[follow.target_account_id] = {
           reblogs: follow.show_reblogs?,
           notify: follow.notify?,
+          languages: follow.languages,
         }
       end
     end
@@ -38,6 +39,7 @@ module AccountInteractions
         mapping[follow_request.target_account_id] = {
           reblogs: follow_request.show_reblogs?,
           notify: follow_request.notify?,
+          languages: follow_request.languages,
         }
       end
     end
@@ -100,12 +102,13 @@ module AccountInteractions
     has_many :announcement_mutes, dependent: :destroy
   end
 
-  def follow!(other_account, reblogs: nil, notify: nil, uri: nil, rate_limit: false, bypass_limit: false)
-    rel = active_relationships.create_with(show_reblogs: reblogs.nil? ? true : reblogs, notify: notify.nil? ? false : notify, uri: uri, rate_limit: rate_limit, bypass_follow_limit: bypass_limit)
+  def follow!(other_account, reblogs: nil, notify: nil, languages: nil, uri: nil, rate_limit: false, bypass_limit: false)
+    rel = active_relationships.create_with(show_reblogs: reblogs.nil? ? true : reblogs, notify: notify.nil? ? false : notify, languages: languages, uri: uri, rate_limit: rate_limit, bypass_follow_limit: bypass_limit)
                               .find_or_create_by!(target_account: other_account)
 
-    rel.show_reblogs = reblogs unless reblogs.nil?
-    rel.notify       = notify  unless notify.nil?
+    rel.show_reblogs = reblogs   unless reblogs.nil?
+    rel.notify       = notify    unless notify.nil?
+    rel.languages    = languages unless languages.nil?
 
     rel.save! if rel.changed?
 
@@ -114,12 +117,13 @@ module AccountInteractions
     rel
   end
 
-  def request_follow!(other_account, reblogs: nil, notify: nil, uri: nil, rate_limit: false, bypass_limit: false)
-    rel = follow_requests.create_with(show_reblogs: reblogs.nil? ? true : reblogs, notify: notify.nil? ? false : notify, uri: uri, rate_limit: rate_limit, bypass_follow_limit: bypass_limit)
+  def request_follow!(other_account, reblogs: nil, notify: nil, languages: nil, uri: nil, rate_limit: false, bypass_limit: false)
+    rel = follow_requests.create_with(show_reblogs: reblogs.nil? ? true : reblogs, notify: notify.nil? ? false : notify, uri: uri, languages: languages, rate_limit: rate_limit, bypass_follow_limit: bypass_limit)
                          .find_or_create_by!(target_account: other_account)
 
-    rel.show_reblogs = reblogs unless reblogs.nil?
-    rel.notify       = notify  unless notify.nil?
+    rel.show_reblogs = reblogs   unless reblogs.nil?
+    rel.notify       = notify    unless notify.nil?
+    rel.languages    = languages unless languages.nil?
 
     rel.save! if rel.changed?
 
@@ -288,8 +292,7 @@ module AccountInteractions
 
   private
 
-  def remove_potential_friendship(other_account, mutual = false)
+  def remove_potential_friendship(other_account)
     PotentialFriendshipTracker.remove(id, other_account.id)
-    PotentialFriendshipTracker.remove(other_account.id, id) if mutual
   end
 end
diff --git a/app/models/content_retention_policy.rb b/app/models/content_retention_policy.rb
new file mode 100644
index 000000000..b5e922c8c
--- /dev/null
+++ b/app/models/content_retention_policy.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+class ContentRetentionPolicy
+  def self.current
+    new
+  end
+
+  def media_cache_retention_period
+    retention_period Setting.media_cache_retention_period
+  end
+
+  def content_cache_retention_period
+    retention_period Setting.content_cache_retention_period
+  end
+
+  def backups_retention_period
+    retention_period Setting.backups_retention_period
+  end
+
+  private
+
+  def retention_period(value)
+    value.days if value.is_a?(Integer) && value.positive?
+  end
+end
diff --git a/app/models/export.rb b/app/models/export.rb
index 5216eed5e..2457dcc15 100644
--- a/app/models/export.rb
+++ b/app/models/export.rb
@@ -30,9 +30,9 @@ class Export
   end
 
   def to_following_accounts_csv
-    CSV.generate(headers: ['Account address', 'Show boosts'], write_headers: true) do |csv|
+    CSV.generate(headers: ['Account address', 'Show boosts', 'Notify on new posts', 'Languages'], write_headers: true) do |csv|
       account.active_relationships.includes(:target_account).reorder(id: :desc).each do |follow|
-        csv << [acct(follow.target_account), follow.show_reblogs]
+        csv << [acct(follow.target_account), follow.show_reblogs, follow.notify, follow.languages&.join(', ')]
       end
     end
   end
diff --git a/app/models/follow.rb b/app/models/follow.rb
index a5e3fe809..e5cecbbc1 100644
--- a/app/models/follow.rb
+++ b/app/models/follow.rb
@@ -11,6 +11,7 @@
 #  show_reblogs      :boolean          default(TRUE), not null
 #  uri               :string
 #  notify            :boolean          default(FALSE), not null
+#  languages         :string           is an Array
 #
 
 class Follow < ApplicationRecord
@@ -27,6 +28,7 @@ class Follow < ApplicationRecord
   has_one :notification, as: :activity, dependent: :destroy
 
   validates :account_id, uniqueness: { scope: :target_account_id }
+  validates :languages, language: true
 
   scope :recent, -> { reorder(id: :desc) }
 
@@ -35,7 +37,7 @@ class Follow < ApplicationRecord
   end
 
   def revoke_request!
-    FollowRequest.create!(account: account, target_account: target_account, show_reblogs: show_reblogs, notify: notify, uri: uri)
+    FollowRequest.create!(account: account, target_account: target_account, show_reblogs: show_reblogs, notify: notify, languages: languages, uri: uri)
     destroy!
   end
 
diff --git a/app/models/follow_request.rb b/app/models/follow_request.rb
index 0b6f7629a..9034250c0 100644
--- a/app/models/follow_request.rb
+++ b/app/models/follow_request.rb
@@ -11,6 +11,7 @@
 #  show_reblogs      :boolean          default(TRUE), not null
 #  uri               :string
 #  notify            :boolean          default(FALSE), not null
+#  languages         :string           is an Array
 #
 
 class FollowRequest < ApplicationRecord
@@ -27,9 +28,10 @@ class FollowRequest < ApplicationRecord
   has_one :notification, as: :activity, dependent: :destroy
 
   validates :account_id, uniqueness: { scope: :target_account_id }
+  validates :languages, language: true
 
   def authorize!
-    account.follow!(target_account, reblogs: show_reblogs, notify: notify, uri: uri, bypass_limit: true)
+    account.follow!(target_account, reblogs: show_reblogs, notify: notify, languages: languages, uri: uri, bypass_limit: true)
     MergeWorker.perform_async(target_account.id, account.id) if account.local?
     destroy!
   end
diff --git a/app/models/form/admin_settings.rb b/app/models/form/admin_settings.rb
index 4c100ba6b..68c98d43f 100644
--- a/app/models/form/admin_settings.rb
+++ b/app/models/form/admin_settings.rb
@@ -40,6 +40,9 @@ class Form::AdminSettings
     outgoing_spoilers
     require_invite_text
     captcha_enabled
+    media_cache_retention_period
+    content_cache_retention_period
+    backups_retention_period
   ).freeze
 
   BOOLEAN_KEYS = %i(
@@ -81,6 +84,7 @@ class Form::AdminSettings
   validates :bootstrap_timeline_accounts, existing_username: { multiple: true }
   validates :show_domain_blocks, inclusion: { in: %w(disabled users all) }
   validates :show_domain_blocks_rationale, inclusion: { in: %w(disabled users all) }
+  validates :media_cache_retention_period, :content_cache_retention_period, :backups_retention_period, numericality: { only_integer: true }, allow_blank: true
 
   def initialize(_attributes = {})
     super
diff --git a/app/models/user.rb b/app/models/user.rb
index 962ca68ff..de59fe4b3 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -282,7 +282,7 @@ class User < ApplicationRecord
   end
 
   def preferred_posting_language
-    valid_locale_cascade(settings.default_language, locale)
+    valid_locale_cascade(settings.default_language, locale, I18n.locale)
   end
 
   def setting_default_privacy
diff --git a/app/serializers/activitypub/public_key_serializer.rb b/app/serializers/activitypub/public_key_serializer.rb
index 62ed49e81..8621517e7 100644
--- a/app/serializers/activitypub/public_key_serializer.rb
+++ b/app/serializers/activitypub/public_key_serializer.rb
@@ -6,7 +6,7 @@ class ActivityPub::PublicKeySerializer < ActivityPub::Serializer
   attributes :id, :owner, :public_key_pem
 
   def id
-    [ActivityPub::TagManager.instance.uri_for(object), '#main-key'].join
+    ActivityPub::TagManager.instance.key_uri_for(object)
   end
 
   def owner
diff --git a/app/serializers/initial_state_serializer.rb b/app/serializers/initial_state_serializer.rb
index b555be633..45a5cda6f 100644
--- a/app/serializers/initial_state_serializer.rb
+++ b/app/serializers/initial_state_serializer.rb
@@ -1,10 +1,12 @@
 # frozen_string_literal: true
 
 class InitialStateSerializer < ActiveModel::Serializer
+  include RoutingHelper
+
   attributes :meta, :compose, :accounts,
              :media_attachments, :settings,
              :max_toot_chars, :poll_limits,
-             :languages
+             :languages, :server
 
   has_one :push_subscription, serializer: REST::WebPushSubscriptionSerializer
   has_one :role, serializer: REST::RoleSerializer
@@ -38,6 +40,7 @@ class InitialStateSerializer < ActiveModel::Serializer
       mascot: instance_presenter.mascot&.file&.url,
       profile_directory: Setting.profile_directory,
       trends: Setting.trends,
+      registrations_open: Setting.registrations_mode != 'none' && !Rails.configuration.x.single_user_mode,
     }
 
     if object.current_account
@@ -99,6 +102,13 @@ class InitialStateSerializer < ActiveModel::Serializer
     LanguagesHelper::SUPPORTED_LOCALES.map { |(key, value)| [key, value[0], value[1]] }
   end
 
+  def server
+    {
+      hero: instance_presenter.hero&.file&.url || instance_presenter.thumbnail&.file&.url || asset_pack_path('media/images/preview.png'),
+      description: instance_presenter.site_short_description.presence || I18n.t('about.about_mastodon_html'),
+    }
+  end
+
   private
 
   def instance_presenter
diff --git a/app/serializers/rest/admin/account_serializer.rb b/app/serializers/rest/admin/account_serializer.rb
index 3480e8c5a..2fbc7b1cb 100644
--- a/app/serializers/rest/admin/account_serializer.rb
+++ b/app/serializers/rest/admin/account_serializer.rb
@@ -77,6 +77,6 @@ class REST::Admin::AccountSerializer < ActiveModel::Serializer
   end
 
   def ip
-    ips&.first
+    ips&.first&.ip
   end
 end
diff --git a/app/serializers/rest/relationship_serializer.rb b/app/serializers/rest/relationship_serializer.rb
index afd4cddf9..31fc60eb2 100644
--- a/app/serializers/rest/relationship_serializer.rb
+++ b/app/serializers/rest/relationship_serializer.rb
@@ -1,7 +1,7 @@
 # frozen_string_literal: true
 
 class REST::RelationshipSerializer < ActiveModel::Serializer
-  attributes :id, :following, :showing_reblogs, :notifying, :followed_by,
+  attributes :id, :following, :showing_reblogs, :notifying, :languages, :followed_by,
              :blocking, :blocked_by, :muting, :muting_notifications, :requested,
              :domain_blocking, :endorsed, :note
 
@@ -25,6 +25,11 @@ class REST::RelationshipSerializer < ActiveModel::Serializer
       false
   end
 
+  def languages
+    (instance_options[:relationships].following[object.id] || {})[:languages] ||
+      (instance_options[:relationships].requested[object.id] || {})[:languages]
+  end
+
   def followed_by
     instance_options[:relationships].followed_by[object.id] || false
   end
diff --git a/app/serializers/rest/translation_serializer.rb b/app/serializers/rest/translation_serializer.rb
new file mode 100644
index 000000000..a06f23f32
--- /dev/null
+++ b/app/serializers/rest/translation_serializer.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class REST::TranslationSerializer < ActiveModel::Serializer
+  attributes :content, :detected_source_language
+
+  def content
+    object.text
+  end
+end
diff --git a/app/services/activitypub/fetch_remote_account_service.rb b/app/services/activitypub/fetch_remote_account_service.rb
index 9d01f5386..ca7a8c6ca 100644
--- a/app/services/activitypub/fetch_remote_account_service.rb
+++ b/app/services/activitypub/fetch_remote_account_service.rb
@@ -1,66 +1,12 @@
 # frozen_string_literal: true
 
-class ActivityPub::FetchRemoteAccountService < BaseService
-  include JsonLdHelper
-  include DomainControlHelper
-  include WebfingerHelper
-
-  SUPPORTED_TYPES = %w(Application Group Organization Person Service).freeze
-
+class ActivityPub::FetchRemoteAccountService < ActivityPub::FetchRemoteActorService
   # Does a WebFinger roundtrip on each call, unless `only_key` is true
-  def call(uri, id: true, prefetched_body: nil, break_on_redirect: false, only_key: false)
-    return if domain_not_allowed?(uri)
-    return ActivityPub::TagManager.instance.uri_to_resource(uri, Account) if ActivityPub::TagManager.instance.local_uri?(uri)
-
-    @json = begin
-      if prefetched_body.nil?
-        fetch_resource(uri, id)
-      else
-        body_to_json(prefetched_body, compare_id: id ? uri : nil)
-      end
-    end
-
-    return if !supported_context? || !expected_type? || (break_on_redirect && @json['movedTo'].present?)
-
-    @uri      = @json['id']
-    @username = @json['preferredUsername']
-    @domain   = Addressable::URI.parse(@uri).normalized_host
-
-    return unless only_key || verified_webfinger?
-
-    ActivityPub::ProcessAccountService.new.call(@username, @domain, @json, only_key: only_key, verified_webfinger: !only_key)
-  rescue Oj::ParseError
-    nil
-  end
-
-  private
-
-  def verified_webfinger?
-    webfinger                            = webfinger!("acct:#{@username}@#{@domain}")
-    confirmed_username, confirmed_domain = split_acct(webfinger.subject)
-
-    return webfinger.link('self', 'href') == @uri if @username.casecmp(confirmed_username).zero? && @domain.casecmp(confirmed_domain).zero?
-
-    webfinger                            = webfinger!("acct:#{confirmed_username}@#{confirmed_domain}")
-    @username, @domain                   = split_acct(webfinger.subject)
-
-    return false unless @username.casecmp(confirmed_username).zero? && @domain.casecmp(confirmed_domain).zero?
-    return false if webfinger.link('self', 'href') != @uri
-
-    true
-  rescue Webfinger::Error
-    false
-  end
-
-  def split_acct(acct)
-    acct.gsub(/\Aacct:/, '').split('@')
-  end
-
-  def supported_context?
-    super(@json)
-  end
+  def call(uri, id: true, prefetched_body: nil, break_on_redirect: false, only_key: false, suppress_errors: true)
+    actor = super
+    return actor if actor.nil? || actor.is_a?(Account)
 
-  def expected_type?
-    equals_or_includes_any?(@json['type'], SUPPORTED_TYPES)
+    Rails.logger.debug "Fetching account #{uri} failed: Expected Account, got #{actor.class.name}"
+    raise Error, "Expected Account, got #{actor.class.name}" unless suppress_errors
   end
 end
diff --git a/app/services/activitypub/fetch_remote_actor_service.rb b/app/services/activitypub/fetch_remote_actor_service.rb
new file mode 100644
index 000000000..17bf2f287
--- /dev/null
+++ b/app/services/activitypub/fetch_remote_actor_service.rb
@@ -0,0 +1,80 @@
+# frozen_string_literal: true
+
+class ActivityPub::FetchRemoteActorService < BaseService
+  include JsonLdHelper
+  include DomainControlHelper
+  include WebfingerHelper
+
+  class Error < StandardError; end
+
+  SUPPORTED_TYPES = %w(Application Group Organization Person Service).freeze
+
+  # Does a WebFinger roundtrip on each call, unless `only_key` is true
+  def call(uri, id: true, prefetched_body: nil, break_on_redirect: false, only_key: false, suppress_errors: true)
+    return if domain_not_allowed?(uri)
+    return ActivityPub::TagManager.instance.uri_to_actor(uri) if ActivityPub::TagManager.instance.local_uri?(uri)
+
+    @json = begin
+      if prefetched_body.nil?
+        fetch_resource(uri, id)
+      else
+        body_to_json(prefetched_body, compare_id: id ? uri : nil)
+      end
+    rescue Oj::ParseError
+      raise Error, "Error parsing JSON-LD document #{uri}"
+    end
+
+    raise Error, "Error fetching actor JSON at #{uri}" if @json.nil?
+    raise Error, "Unsupported JSON-LD context for document #{uri}" unless supported_context?
+    raise Error, "Unexpected object type for actor #{uri} (expected any of: #{SUPPORTED_TYPES})" unless expected_type?
+    raise Error, "Actor #{uri} has moved to #{@json['movedTo']}" if break_on_redirect && @json['movedTo'].present?
+
+    @uri      = @json['id']
+    @username = @json['preferredUsername']
+    @domain   = Addressable::URI.parse(@uri).normalized_host
+
+    check_webfinger! unless only_key
+
+    ActivityPub::ProcessAccountService.new.call(@username, @domain, @json, only_key: only_key, verified_webfinger: !only_key)
+  rescue Error => e
+    Rails.logger.debug "Fetching actor #{uri} failed: #{e.message}"
+    raise unless suppress_errors
+  end
+
+  private
+
+  def check_webfinger!
+    webfinger                            = webfinger!("acct:#{@username}@#{@domain}")
+    confirmed_username, confirmed_domain = split_acct(webfinger.subject)
+
+    if @username.casecmp(confirmed_username).zero? && @domain.casecmp(confirmed_domain).zero?
+      raise Error, "Webfinger response for #{@username}@#{@domain} does not loop back to #{@uri}" if webfinger.link('self', 'href') != @uri
+      return
+    end
+
+    webfinger                            = webfinger!("acct:#{confirmed_username}@#{confirmed_domain}")
+    @username, @domain                   = split_acct(webfinger.subject)
+
+    unless confirmed_username.casecmp(@username).zero? && confirmed_domain.casecmp(@domain).zero?
+      raise Webfinger::RedirectError, "Too many webfinger redirects for URI #{uri} (stopped at #{@username}@#{@domain})"
+    end
+
+    raise Error, "Webfinger response for #{@username}@#{@domain} does not loop back to #{@uri}" if webfinger.link('self', 'href') != @uri
+  rescue Webfinger::RedirectError => e
+    raise Error, e.message
+  rescue Webfinger::Error => e
+    raise Error, "Webfinger error when resolving #{@username}@#{@domain}: #{e.message}"
+  end
+
+  def split_acct(acct)
+    acct.gsub(/\Aacct:/, '').split('@')
+  end
+
+  def supported_context?
+    super(@json)
+  end
+
+  def expected_type?
+    equals_or_includes_any?(@json['type'], SUPPORTED_TYPES)
+  end
+end
diff --git a/app/services/activitypub/fetch_remote_key_service.rb b/app/services/activitypub/fetch_remote_key_service.rb
index c48288b3b..32e82b47a 100644
--- a/app/services/activitypub/fetch_remote_key_service.rb
+++ b/app/services/activitypub/fetch_remote_key_service.rb
@@ -3,17 +3,19 @@
 class ActivityPub::FetchRemoteKeyService < BaseService
   include JsonLdHelper
 
-  # Returns account that owns the key
-  def call(uri, id: true, prefetched_body: nil)
-    return if uri.blank?
+  class Error < StandardError; end
+
+  # Returns actor that owns the key
+  def call(uri, id: true, prefetched_body: nil, suppress_errors: true)
+    raise Error, 'No key URI given' if uri.blank?
 
     if prefetched_body.nil?
       if id
         @json = fetch_resource_without_id_validation(uri)
-        if person?
+        if actor_type?
           @json = fetch_resource(@json['id'], true)
         elsif uri != @json['id']
-          return
+          raise Error, "Fetched URI #{uri} has wrong id #{@json['id']}"
         end
       else
         @json = fetch_resource(uri, id)
@@ -22,30 +24,38 @@ class ActivityPub::FetchRemoteKeyService < BaseService
       @json = body_to_json(prefetched_body, compare_id: id ? uri : nil)
     end
 
-    return unless supported_context?(@json) && expected_type?
-    return find_account(@json['id'], @json) if person?
+    raise Error, "Unable to fetch key JSON at #{uri}" if @json.nil?
+    raise Error, "Unsupported JSON-LD context for document #{uri}" unless supported_context?(@json)
+    raise Error, "Unexpected object type for key #{uri}" unless expected_type?
+    return find_actor(@json['id'], @json, suppress_errors) if actor_type?
 
     @owner = fetch_resource(owner_uri, true)
 
-    return unless supported_context?(@owner) && confirmed_owner?
+    raise Error, "Unable to fetch actor JSON #{owner_uri}" if @owner.nil?
+    raise Error, "Unsupported JSON-LD context for document #{owner_uri}" unless supported_context?(@owner)
+    raise Error, "Unexpected object type for actor #{owner_uri} (expected any of: #{SUPPORTED_TYPES})" unless expected_owner_type?
+    raise Error, "publicKey id for #{owner_uri} does not correspond to #{@json['id']}" unless confirmed_owner?
 
-    find_account(owner_uri, @owner)
+    find_actor(owner_uri, @owner, suppress_errors)
+  rescue Error => e
+    Rails.logger.debug "Fetching key #{uri} failed: #{e.message}"
+    raise unless suppress_errors
   end
 
   private
 
-  def find_account(uri, prefetched_body)
-    account   = ActivityPub::TagManager.instance.uri_to_resource(uri, Account)
-    account ||= ActivityPub::FetchRemoteAccountService.new.call(uri, prefetched_body: prefetched_body)
-    account
+  def find_actor(uri, prefetched_body, suppress_errors)
+    actor   = ActivityPub::TagManager.instance.uri_to_actor(uri)
+    actor ||= ActivityPub::FetchRemoteActorService.new.call(uri, prefetched_body: prefetched_body, suppress_errors: suppress_errors)
+    actor
   end
 
   def expected_type?
-    person? || public_key?
+    actor_type? || public_key?
   end
 
-  def person?
-    equals_or_includes_any?(@json['type'], ActivityPub::FetchRemoteAccountService::SUPPORTED_TYPES)
+  def actor_type?
+    equals_or_includes_any?(@json['type'], ActivityPub::FetchRemoteActorService::SUPPORTED_TYPES)
   end
 
   def public_key?
@@ -56,7 +66,11 @@ class ActivityPub::FetchRemoteKeyService < BaseService
     @owner_uri ||= value_or_id(@json['owner'])
   end
 
+  def expected_owner_type?
+    equals_or_includes_any?(@owner['type'], ActivityPub::FetchRemoteActorService::SUPPORTED_TYPES)
+  end
+
   def confirmed_owner?
-    equals_or_includes_any?(@owner['type'], ActivityPub::FetchRemoteAccountService::SUPPORTED_TYPES) && value_or_id(@owner['publicKey']) == @json['id']
+    value_or_id(@owner['publicKey']) == @json['id']
   end
 end
diff --git a/app/services/activitypub/process_account_service.rb b/app/services/activitypub/process_account_service.rb
index 34750dba6..456b3524b 100644
--- a/app/services/activitypub/process_account_service.rb
+++ b/app/services/activitypub/process_account_service.rb
@@ -32,8 +32,6 @@ class ActivityPub::ProcessAccountService < BaseService
       process_duplicate_accounts! if @options[:verified_webfinger]
     end
 
-    return if @account.nil?
-
     after_protocol_change! if protocol_changed?
     after_key_change! if key_changed? && !@options[:signed_with_known_key]
     clear_tombstones! if key_changed?
diff --git a/app/services/activitypub/process_collection_service.rb b/app/services/activitypub/process_collection_service.rb
index eb008c40a..fffe30195 100644
--- a/app/services/activitypub/process_collection_service.rb
+++ b/app/services/activitypub/process_collection_service.rb
@@ -3,8 +3,8 @@
 class ActivityPub::ProcessCollectionService < BaseService
   include JsonLdHelper
 
-  def call(body, account, **options)
-    @account = account
+  def call(body, actor, **options)
+    @account = actor
     @json    = original_json = Oj.load(body, mode: :strict)
     @options = options
 
@@ -16,6 +16,7 @@ class ActivityPub::ProcessCollectionService < BaseService
     end
 
     return if !supported_context? || (different_actor? && verify_account!.nil?) || suspended_actor? || @account.local?
+    return unless @account.is_a?(Account)
 
     if @json['signature'].present?
       # We have verified the signature, but in the compaction step above, might
@@ -66,8 +67,10 @@ class ActivityPub::ProcessCollectionService < BaseService
   end
 
   def verify_account!
-    @options[:relayed_through_account] = @account
-    @account = ActivityPub::LinkedDataSignature.new(@json).verify_account!
+    @options[:relayed_through_actor] = @account
+    @account = ActivityPub::LinkedDataSignature.new(@json).verify_actor!
+    @account = nil unless @account.is_a?(Account)
+    @account
   rescue JSON::LD::JsonLdError => e
     Rails.logger.debug "Could not verify LD-Signature for #{value_or_id(@json['actor'])}: #{e.message}"
     nil
diff --git a/app/services/fetch_resource_service.rb b/app/services/fetch_resource_service.rb
index 6c0093cd4..73204e55d 100644
--- a/app/services/fetch_resource_service.rb
+++ b/app/services/fetch_resource_service.rb
@@ -47,7 +47,7 @@ class FetchResourceService < BaseService
       body = response.body_with_limit
       json = body_to_json(body)
 
-      [json['id'], { prefetched_body: body, id: true }] if supported_context?(json) && (equals_or_includes_any?(json['type'], ActivityPub::FetchRemoteAccountService::SUPPORTED_TYPES) || expected_type?(json))
+      [json['id'], { prefetched_body: body, id: true }] if supported_context?(json) && (equals_or_includes_any?(json['type'], ActivityPub::FetchRemoteActorService::SUPPORTED_TYPES) || expected_type?(json))
     elsif !terminal
       link_header = response['Link'] && parse_link_header(response)
 
diff --git a/app/services/follow_service.rb b/app/services/follow_service.rb
index ed28e1371..feea40e3c 100644
--- a/app/services/follow_service.rb
+++ b/app/services/follow_service.rb
@@ -11,6 +11,7 @@ class FollowService < BaseService
   # @param [Hash] options
   # @option [Boolean] :reblogs Whether or not to show reblogs, defaults to true
   # @option [Boolean] :notify Whether to create notifications about new posts, defaults to false
+  # @option [Array<String>] :languages Which languages to allow on the home feed from this account, defaults to all
   # @option [Boolean] :bypass_locked
   # @option [Boolean] :bypass_limit Allow following past the total follow number
   # @option [Boolean] :with_rate_limit
@@ -57,15 +58,15 @@ class FollowService < BaseService
   end
 
   def change_follow_options!
-    @source_account.follow!(@target_account, reblogs: @options[:reblogs], notify: @options[:notify])
+    @source_account.follow!(@target_account, **follow_options)
   end
 
   def change_follow_request_options!
-    @source_account.request_follow!(@target_account, reblogs: @options[:reblogs], notify: @options[:notify])
+    @source_account.request_follow!(@target_account, **follow_options)
   end
 
   def request_follow!
-    follow_request = @source_account.request_follow!(@target_account, reblogs: @options[:reblogs], notify: @options[:notify], rate_limit: @options[:with_rate_limit], bypass_limit: @options[:bypass_limit])
+    follow_request = @source_account.request_follow!(@target_account, **follow_options.merge(rate_limit: @options[:with_rate_limit], bypass_limit: @options[:bypass_limit]))
 
     if @target_account.local?
       LocalNotificationWorker.perform_async(@target_account.id, follow_request.id, follow_request.class.name, 'follow_request')
@@ -77,7 +78,7 @@ class FollowService < BaseService
   end
 
   def direct_follow!
-    follow = @source_account.follow!(@target_account, reblogs: @options[:reblogs], notify: @options[:notify], rate_limit: @options[:with_rate_limit], bypass_limit: @options[:bypass_limit])
+    follow = @source_account.follow!(@target_account, **follow_options.merge(rate_limit: @options[:with_rate_limit], bypass_limit: @options[:bypass_limit]))
 
     LocalNotificationWorker.perform_async(@target_account.id, follow.id, follow.class.name, 'follow')
     MergeWorker.perform_async(@target_account.id, @source_account.id)
@@ -88,4 +89,8 @@ class FollowService < BaseService
   def build_json(follow_request)
     Oj.dump(serialize_payload(follow_request, ActivityPub::FollowSerializer))
   end
+
+  def follow_options
+    @options.slice(:reblogs, :notify, :languages)
+  end
 end
diff --git a/app/services/import_service.rb b/app/services/import_service.rb
index 8e6640b9d..676c37bde 100644
--- a/app/services/import_service.rb
+++ b/app/services/import_service.rb
@@ -27,7 +27,7 @@ class ImportService < BaseService
 
   def import_follows!
     parse_import_data!(['Account address'])
-    import_relationships!('follow', 'unfollow', @account.following, ROWS_PROCESSING_LIMIT, reblogs: { header: 'Show boosts', default: true })
+    import_relationships!('follow', 'unfollow', @account.following, ROWS_PROCESSING_LIMIT, reblogs: { header: 'Show boosts', default: true }, notify: { header: 'Notify on new posts', default: false }, languages: { header: 'Languages', default: nil })
   end
 
   def import_blocks!
diff --git a/app/services/keys/claim_service.rb b/app/services/keys/claim_service.rb
index 69568a0d1..ae9e24a24 100644
--- a/app/services/keys/claim_service.rb
+++ b/app/services/keys/claim_service.rb
@@ -72,7 +72,7 @@ class Keys::ClaimService < BaseService
 
   def build_post_request(uri)
     Request.new(:post, uri).tap do |request|
-      request.on_behalf_of(@source_account, :uri)
+      request.on_behalf_of(@source_account)
       request.add_headers(HEADERS)
     end
   end
diff --git a/app/services/process_mentions_service.rb b/app/services/process_mentions_service.rb
index 8c63b611d..c9c158af1 100644
--- a/app/services/process_mentions_service.rb
+++ b/app/services/process_mentions_service.rb
@@ -38,7 +38,7 @@ class ProcessMentionsService < BaseService
       mentioned_account = Account.find_remote(username, domain)
 
       # Unapproved and unconfirmed accounts should not be mentionable
-      next if mentioned_account&.local? && !(mentioned_account.user_confirmed? && mentioned_account.user_approved?)
+      next match if mentioned_account&.local? && !(mentioned_account.user_confirmed? && mentioned_account.user_approved?)
 
       # If the account cannot be found or isn't the right protocol,
       # first try to resolve it
diff --git a/app/services/resolve_account_service.rb b/app/services/resolve_account_service.rb
index b55e45409..e3b370968 100644
--- a/app/services/resolve_account_service.rb
+++ b/app/services/resolve_account_service.rb
@@ -1,7 +1,6 @@
 # frozen_string_literal: true
 
 class ResolveAccountService < BaseService
-  include JsonLdHelper
   include DomainControlHelper
   include WebfingerHelper
   include Redisable
@@ -13,6 +12,7 @@ class ResolveAccountService < BaseService
   # @param [Hash] options
   # @option options [Boolean] :redirected Do not follow further Webfinger redirects
   # @option options [Boolean] :skip_webfinger Do not attempt any webfinger query or refreshing account data
+  # @option options [Boolean] :suppress_errors When failing, return nil instead of raising an error
   # @return [Account]
   def call(uri, options = {})
     return if uri.blank?
@@ -52,15 +52,15 @@ class ResolveAccountService < BaseService
     # either needs to be created, or updated from fresh data
 
     fetch_account!
-  rescue Webfinger::Error, Oj::ParseError => e
+  rescue Webfinger::Error => e
     Rails.logger.debug "Webfinger query for #{@uri} failed: #{e}"
-    nil
+    raise unless @options[:suppress_errors]
   end
 
   private
 
   def process_options!(uri, options)
-    @options = options
+    @options = { suppress_errors: true }.merge(options)
 
     if uri.is_a?(Account)
       @account  = uri
@@ -96,7 +96,7 @@ class ResolveAccountService < BaseService
     @username, @domain = split_acct(@webfinger.subject)
 
     unless confirmed_username.casecmp(@username).zero? && confirmed_domain.casecmp(@domain).zero?
-      raise Webfinger::RedirectError, "The URI #{uri} tries to hijack #{@username}@#{@domain}"
+      raise Webfinger::RedirectError, "Too many webfinger redirects for URI #{uri} (stopped at #{@username}@#{@domain})"
     end
   rescue Webfinger::GoneError
     @gone = true
@@ -110,7 +110,7 @@ class ResolveAccountService < BaseService
     return unless activitypub_ready?
 
     with_lock("resolve:#{@username}@#{@domain}") do
-      @account = ActivityPub::FetchRemoteAccountService.new.call(actor_url)
+      @account = ActivityPub::FetchRemoteAccountService.new.call(actor_url, suppress_errors: @options[:suppress_errors])
     end
 
     @account
diff --git a/app/services/resolve_url_service.rb b/app/services/resolve_url_service.rb
index e2c745673..37c856cf8 100644
--- a/app/services/resolve_url_service.rb
+++ b/app/services/resolve_url_service.rb
@@ -20,8 +20,8 @@ class ResolveURLService < BaseService
   private
 
   def process_url
-    if equals_or_includes_any?(type, ActivityPub::FetchRemoteAccountService::SUPPORTED_TYPES)
-      ActivityPub::FetchRemoteAccountService.new.call(resource_url, prefetched_body: body)
+    if equals_or_includes_any?(type, ActivityPub::FetchRemoteActorService::SUPPORTED_TYPES)
+      ActivityPub::FetchRemoteActorService.new.call(resource_url, prefetched_body: body)
     elsif equals_or_includes_any?(type, ActivityPub::Activity::Create::SUPPORTED_TYPES + ActivityPub::Activity::Create::CONVERTED_TYPES)
       status = FetchRemoteStatusService.new.call(resource_url, body)
       authorize_with @on_behalf_of, status, :show? unless status.nil?
diff --git a/app/services/translate_status_service.rb b/app/services/translate_status_service.rb
new file mode 100644
index 000000000..539a0d9db
--- /dev/null
+++ b/app/services/translate_status_service.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+class TranslateStatusService < BaseService
+  CACHE_TTL = 1.day.freeze
+
+  include FormattingHelper
+
+  def call(status, target_language)
+    raise Mastodon::NotPermittedError unless status.public_visibility? || status.unlisted_visibility?
+
+    @status = status
+    @content = status_content_format(@status)
+    @target_language = target_language
+
+    Rails.cache.fetch("translations/#{@status.language}/#{@target_language}/#{content_hash}", expires_in: CACHE_TTL) { translation_backend.translate(@content, @status.language, @target_language) }
+  end
+
+  private
+
+  def translation_backend
+    TranslationService.configured
+  end
+
+  def content_hash
+    Digest::SHA256.base64digest(@content)
+  end
+end
diff --git a/app/validators/language_validator.rb b/app/validators/language_validator.rb
new file mode 100644
index 000000000..b723e1a40
--- /dev/null
+++ b/app/validators/language_validator.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+class LanguageValidator < ActiveModel::EachValidator
+  include LanguagesHelper
+
+  def validate_each(record, attribute, value)
+    record.errors.add(attribute, :invalid) unless valid?(value)
+  end
+
+  private
+
+  def valid?(str)
+    if str.nil?
+      true
+    elsif str.is_a?(Array)
+      str.all? { |x| valid_locale?(x) }
+    else
+      valid_locale?(str)
+    end
+  end
+end
diff --git a/app/views/admin/settings/edit.html.haml b/app/views/admin/settings/edit.html.haml
index 98af7e718..c8ebb3360 100644
--- a/app/views/admin/settings/edit.html.haml
+++ b/app/views/admin/settings/edit.html.haml
@@ -81,7 +81,7 @@
       = f.input :trends, as: :boolean, wrapper: :with_label, label: t('admin.settings.trends.title'), hint: t('admin.settings.trends.desc_html')
 
     .fields-group
-      = f.input :trendable_by_default, as: :boolean, wrapper: :with_label, label: t('admin.settings.trendable_by_default.title'), hint: t('admin.settings.trendable_by_default.desc_html')
+      = f.input :trendable_by_default, as: :boolean, wrapper: :with_label, label: t('admin.settings.trendable_by_default.title'), hint: t('admin.settings.trendable_by_default.desc_html'), recommended: :not_recommended
 
     .fields-group
       = f.input :trending_status_cw, as: :boolean, wrapper: :with_label, label: t('admin.settings.trending_status_cw.title'), hint: t('admin.settings.trending_status_cw.desc_html')
@@ -115,5 +115,12 @@
     = f.input :site_terms, wrapper: :with_block_label, as: :text, label: t('admin.settings.site_terms.title'), hint: t('admin.settings.site_terms.desc_html'), input_html: { rows: 8 }
     = f.input :custom_css, wrapper: :with_block_label, as: :text, input_html: { rows: 8 }, label: t('admin.settings.custom_css.title'), hint: t('admin.settings.custom_css.desc_html')
 
+  %hr.spacer/
+
+  .fields-group
+    = f.input :media_cache_retention_period, wrapper: :with_block_label, input_html: { pattern: '[0-9]+' }
+    = f.input :content_cache_retention_period, wrapper: :with_block_label, input_html: { pattern: '[0-9]+' }
+    = f.input :backups_retention_period, wrapper: :with_block_label, input_html: { pattern: '[0-9]+' }
+
   .actions
     = f.button :button, t('generic.save_changes'), type: :submit
diff --git a/app/views/home/index.html.haml b/app/views/home/index.html.haml
index 568b23eff..437c33715 100644
--- a/app/views/home/index.html.haml
+++ b/app/views/home/index.html.haml
@@ -1,10 +1,14 @@
 - content_for :header_tags do
-  = preload_pack_asset 'features/getting_started.js', crossorigin: 'anonymous'
-  = preload_pack_asset 'features/compose.js', crossorigin: 'anonymous'
-  = preload_pack_asset 'features/home_timeline.js', crossorigin: 'anonymous'
-  = preload_pack_asset 'features/notifications.js', crossorigin: 'anonymous'
+  - if user_signed_in?
+    = preload_pack_asset 'features/getting_started.js', crossorigin: 'anonymous'
+    = preload_pack_asset 'features/compose.js', crossorigin: 'anonymous'
+    = preload_pack_asset 'features/home_timeline.js', crossorigin: 'anonymous'
+    = preload_pack_asset 'features/notifications.js', crossorigin: 'anonymous'
+
+  = render partial: 'shared/og'
 
   %meta{name: 'applicationServerKey', content: Rails.configuration.x.vapid_public_key}
+
   = render_initial_state
 
 .notranslate.app-holder#mastodon{ data: { props: Oj.dump(default_props) } }
diff --git a/app/views/layouts/public.html.haml b/app/views/layouts/public.html.haml
index f4ef199e6..10bc681ce 100644
--- a/app/views/layouts/public.html.haml
+++ b/app/views/layouts/public.html.haml
@@ -32,8 +32,7 @@
           .column-0
             %h4= t 'footer.resources'
             %ul
-              %li= link_to t('about.terms'), terms_path
-              %li= link_to t('about.privacy_policy'), terms_path
+              %li= link_to t('about.privacy_policy'), privacy_policy_path
           .column-1
             %h4= t 'footer.developers'
             %ul
@@ -56,6 +55,6 @@
         .legal-xs
           = link_to "v#{Mastodon::Version.to_s}", Mastodon::Version.source_url
           ·
-          = link_to t('about.privacy_policy'), terms_path
+          = link_to t('about.privacy_policy'), privacy_policy_path
 
 = render template: 'layouts/application'
diff --git a/app/views/about/terms.html.haml b/app/views/privacy/show.html.haml
index 9d076a91b..9d076a91b 100644
--- a/app/views/about/terms.html.haml
+++ b/app/views/privacy/show.html.haml
diff --git a/app/views/settings/deletes/show.html.haml b/app/views/settings/deletes/show.html.haml
index 08792e0af..ddf090879 100644
--- a/app/views/settings/deletes/show.html.haml
+++ b/app/views/settings/deletes/show.html.haml
@@ -16,7 +16,7 @@
       %li.positive-hint= t('deletes.warning.email_contact_html', email: Setting.site_contact_email)
       %li.positive-hint= t('deletes.warning.username_available')
 
-  %p.hint= t('deletes.warning.more_details_html', terms_path: terms_path)
+  %p.hint= t('deletes.warning.more_details_html', terms_path: privacy_policy_path)
 
   %hr.spacer/
 
diff --git a/app/views/user_mailer/confirmation_instructions.html.haml b/app/views/user_mailer/confirmation_instructions.html.haml
index 39a83faff..447e689b4 100644
--- a/app/views/user_mailer/confirmation_instructions.html.haml
+++ b/app/views/user_mailer/confirmation_instructions.html.haml
@@ -77,4 +77,4 @@
                         %tbody
                           %tr
                             %td.column-cell.text-center
-                              %p= t 'devise.mailer.confirmation_instructions.extra_html', terms_path: about_more_url, policy_path: terms_url
+                              %p= t 'devise.mailer.confirmation_instructions.extra_html', terms_path: about_more_url, policy_path: privacy_policy_url
diff --git a/app/views/user_mailer/confirmation_instructions.text.erb b/app/views/user_mailer/confirmation_instructions.text.erb
index aad91cd9d..a1b2ba7d2 100644
--- a/app/views/user_mailer/confirmation_instructions.text.erb
+++ b/app/views/user_mailer/confirmation_instructions.text.erb
@@ -6,7 +6,7 @@
 
 => <%= confirmation_url(@resource, confirmation_token: @token, redirect_to_app: @resource.created_by_application ? 'true' : nil) %>
 
-<%= strip_tags(t('devise.mailer.confirmation_instructions.extra_html', terms_path: about_more_url, policy_path: terms_url)) %>
+<%= strip_tags(t('devise.mailer.confirmation_instructions.extra_html', terms_path: about_more_url, policy_path: privacy_policy_url)) %>
 
 => <%= about_more_url %>
-=> <%= terms_url %>
+=> <%= privacy_policy_url %>
diff --git a/app/workers/activitypub/delivery_worker.rb b/app/workers/activitypub/delivery_worker.rb
index 788f2cf80..d9153132b 100644
--- a/app/workers/activitypub/delivery_worker.rb
+++ b/app/workers/activitypub/delivery_worker.rb
@@ -37,7 +37,7 @@ class ActivityPub::DeliveryWorker
 
   def build_request(http_client)
     Request.new(:post, @inbox_url, body: @json, http_client: http_client).tap do |request|
-      request.on_behalf_of(@source_account, :uri, sign_with: @options[:sign_with])
+      request.on_behalf_of(@source_account, sign_with: @options[:sign_with])
       request.add_headers(HEADERS)
       request.add_headers({ 'Collection-Synchronization' => synchronization_header }) if ENV['DISABLE_FOLLOWERS_SYNCHRONIZATION'] != 'true' && @options[:synchronize_followers]
     end
diff --git a/app/workers/activitypub/processing_worker.rb b/app/workers/activitypub/processing_worker.rb
index 37e316354..4d06ad079 100644
--- a/app/workers/activitypub/processing_worker.rb
+++ b/app/workers/activitypub/processing_worker.rb
@@ -5,11 +5,15 @@ class ActivityPub::ProcessingWorker
 
   sidekiq_options backtrace: true, retry: 8
 
-  def perform(account_id, body, delivered_to_account_id = nil)
-    account = Account.find_by(id: account_id)
-    return if account.nil?
+  def perform(actor_id, body, delivered_to_account_id = nil, actor_type = 'Account')
+    case actor_type
+    when 'Account'
+      actor = Account.find_by(id: actor_id)
+    end
 
-    ActivityPub::ProcessCollectionService.new.call(body, account, override_timestamps: true, delivered_to_account_id: delivered_to_account_id, delivery: true)
+    return if actor.nil?
+
+    ActivityPub::ProcessCollectionService.new.call(body, actor, override_timestamps: true, delivered_to_account_id: delivered_to_account_id, delivery: true)
   rescue ActiveRecord::RecordInvalid => e
     Rails.logger.debug "Error processing incoming ActivityPub object: #{e}"
   end
diff --git a/app/workers/refollow_worker.rb b/app/workers/refollow_worker.rb
index 319b00109..4b712d3aa 100644
--- a/app/workers/refollow_worker.rb
+++ b/app/workers/refollow_worker.rb
@@ -10,8 +10,9 @@ class RefollowWorker
     return unless target_account.activitypub?
 
     target_account.passive_relationships.where(account: Account.where(domain: nil)).includes(:account).reorder(nil).find_each do |follow|
-      reblogs = follow.show_reblogs?
-      notify  = follow.notify?
+      reblogs   = follow.show_reblogs?
+      notify    = follow.notify?
+      languages = follow.languages
 
       # Locally unfollow remote account
       follower = follow.account
@@ -19,7 +20,7 @@ class RefollowWorker
 
       # Schedule re-follow
       begin
-        FollowService.new.call(follower, target_account, reblogs: reblogs, notify: notify, bypass_limit: true)
+        FollowService.new.call(follower, target_account, reblogs: reblogs, notify: notify, languages: languages, bypass_limit: true)
       rescue Mastodon::NotPermittedError, ActiveRecord::RecordNotFound, Mastodon::UnexpectedResponseError, HTTP::Error, OpenSSL::SSL::SSLError
         next
       end
diff --git a/app/workers/scheduler/backup_cleanup_scheduler.rb b/app/workers/scheduler/backup_cleanup_scheduler.rb
deleted file mode 100644
index 85d5312c0..000000000
--- a/app/workers/scheduler/backup_cleanup_scheduler.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class Scheduler::BackupCleanupScheduler
-  include Sidekiq::Worker
-
-  sidekiq_options retry: 0
-
-  def perform
-    old_backups.reorder(nil).find_each(&:destroy!)
-  end
-
-  private
-
-  def old_backups
-    Backup.where('created_at < ?', 7.days.ago)
-  end
-end
diff --git a/app/workers/scheduler/feed_cleanup_scheduler.rb b/app/workers/scheduler/feed_cleanup_scheduler.rb
deleted file mode 100644
index 78adc97e2..000000000
--- a/app/workers/scheduler/feed_cleanup_scheduler.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-# frozen_string_literal: true
-
-class Scheduler::FeedCleanupScheduler
-  include Sidekiq::Worker
-  include Redisable
-
-  sidekiq_options retry: 0
-
-  def perform
-    clean_home_feeds!
-    clean_list_feeds!
-    clean_direct_feeds!
-  end
-
-  private
-
-  def clean_home_feeds!
-    feed_manager.clean_feeds!(:home, inactive_account_ids)
-  end
-
-  def clean_list_feeds!
-    feed_manager.clean_feeds!(:list, inactive_list_ids)
-  end
-
-  def clean_direct_feeds!
-    feed_manager.clean_feeds!(:direct, inactive_account_ids)
-  end
-
-  def inactive_account_ids
-    @inactive_account_ids ||= User.confirmed.inactive.pluck(:account_id)
-  end
-
-  def inactive_list_ids
-    List.where(account_id: inactive_account_ids).pluck(:id)
-  end
-
-  def feed_manager
-    FeedManager.instance
-  end
-end
diff --git a/app/workers/scheduler/media_cleanup_scheduler.rb b/app/workers/scheduler/media_cleanup_scheduler.rb
deleted file mode 100644
index 24d30a6be..000000000
--- a/app/workers/scheduler/media_cleanup_scheduler.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class Scheduler::MediaCleanupScheduler
-  include Sidekiq::Worker
-
-  sidekiq_options retry: 0
-
-  def perform
-    unattached_media.find_each(&:destroy)
-  end
-
-  private
-
-  def unattached_media
-    MediaAttachment.reorder(nil).unattached.where('created_at < ?', 1.day.ago)
-  end
-end
diff --git a/app/workers/scheduler/vacuum_scheduler.rb b/app/workers/scheduler/vacuum_scheduler.rb
new file mode 100644
index 000000000..ce88ff204
--- /dev/null
+++ b/app/workers/scheduler/vacuum_scheduler.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+
+class Scheduler::VacuumScheduler
+  include Sidekiq::Worker
+
+  sidekiq_options retry: 0
+
+  def perform
+    vacuum_operations.each do |operation|
+      operation.perform
+    rescue => e
+      Rails.logger.error("Error while running #{operation.class.name}: #{e}")
+    end
+  end
+
+  private
+
+  def vacuum_operations
+    [
+      statuses_vacuum,
+      media_attachments_vacuum,
+      preview_cards_vacuum,
+      backups_vacuum,
+      access_tokens_vacuum,
+      feeds_vacuum,
+    ]
+  end
+
+  def statuses_vacuum
+    Vacuum::StatusesVacuum.new(content_retention_policy.content_cache_retention_period)
+  end
+
+  def media_attachments_vacuum
+    Vacuum::MediaAttachmentsVacuum.new(content_retention_policy.media_cache_retention_period)
+  end
+
+  def preview_cards_vacuum
+    Vacuum::PreviewCardsVacuum.new(content_retention_policy.media_cache_retention_period)
+  end
+
+  def backups_vacuum
+    Vacuum::BackupsVacuum.new(content_retention_policy.backups_retention_period)
+  end
+
+  def access_tokens_vacuum
+    Vacuum::AccessTokensVacuum.new
+  end
+
+  def feeds_vacuum
+    Vacuum::FeedsVacuum.new
+  end
+
+  def content_retention_policy
+    ContentRetentionPolicy.current
+  end
+end
diff --git a/app/workers/unfollow_follow_worker.rb b/app/workers/unfollow_follow_worker.rb
index 0bd5ff472..7203b4888 100644
--- a/app/workers/unfollow_follow_worker.rb
+++ b/app/workers/unfollow_follow_worker.rb
@@ -10,11 +10,12 @@ class UnfollowFollowWorker
     old_target_account = Account.find(old_target_account_id)
     new_target_account = Account.find(new_target_account_id)
 
-    follow  = follower_account.active_relationships.find_by(target_account: old_target_account)
-    reblogs = follow&.show_reblogs?
-    notify  = follow&.notify?
+    follow    = follower_account.active_relationships.find_by(target_account: old_target_account)
+    reblogs   = follow&.show_reblogs?
+    notify    = follow&.notify?
+    languages = follow&.languages
 
-    FollowService.new.call(follower_account, new_target_account, reblogs: reblogs, notify: notify, bypass_locked: bypass_locked, bypass_limit: true)
+    FollowService.new.call(follower_account, new_target_account, reblogs: reblogs, notify: notify, languages: languages, bypass_locked: bypass_locked, bypass_limit: true)
     UnfollowService.new.call(follower_account, old_target_account, skip_unmerge: true)
   rescue ActiveRecord::RecordNotFound, Mastodon::NotPermittedError
     true