about summary refs log tree commit diff
path: root/app/javascript
diff options
context:
space:
mode:
Diffstat (limited to 'app/javascript')
-rw-r--r--app/javascript/flavours/glitch/actions/filters.js69
-rw-r--r--app/javascript/flavours/glitch/actions/importer/index.js11
-rw-r--r--app/javascript/flavours/glitch/actions/importer/normalizer.js12
-rw-r--r--app/javascript/flavours/glitch/actions/notifications.js32
-rw-r--r--app/javascript/flavours/glitch/actions/statuses.js4
-rw-r--r--app/javascript/flavours/glitch/actions/streaming.js4
-rw-r--r--app/javascript/flavours/glitch/actions/tags.js6
-rw-r--r--app/javascript/flavours/glitch/actions/timelines.js16
-rw-r--r--app/javascript/flavours/glitch/components/icon_button.js14
-rw-r--r--app/javascript/flavours/glitch/components/status.js29
-rw-r--r--app/javascript/flavours/glitch/components/status_action_bar.js23
-rw-r--r--app/javascript/flavours/glitch/containers/status_container.js51
-rw-r--r--app/javascript/flavours/glitch/features/audio/index.js64
-rw-r--r--app/javascript/flavours/glitch/features/compose/components/language_dropdown.js19
-rw-r--r--app/javascript/flavours/glitch/features/filters/added_to_filter.js102
-rw-r--r--app/javascript/flavours/glitch/features/filters/select_filter.js192
-rw-r--r--app/javascript/flavours/glitch/features/local_settings/page/index.js23
-rw-r--r--app/javascript/flavours/glitch/features/status/components/detailed_status.js4
-rw-r--r--app/javascript/flavours/glitch/features/ui/components/filter_modal.js134
-rw-r--r--app/javascript/flavours/glitch/features/ui/components/modal_root.js2
-rw-r--r--app/javascript/flavours/glitch/features/ui/index.js3
-rw-r--r--app/javascript/flavours/glitch/reducers/filters.js41
-rw-r--r--app/javascript/flavours/glitch/reducers/local_settings.js1
-rw-r--r--app/javascript/flavours/glitch/reducers/notifications.js12
-rw-r--r--app/javascript/flavours/glitch/selectors/index.js118
-rw-r--r--app/javascript/flavours/glitch/styles/components/media.scss7
-rw-r--r--app/javascript/flavours/glitch/styles/components/modal.scss18
-rw-r--r--app/javascript/flavours/glitch/util/async-components.js4
-rw-r--r--app/javascript/flavours/glitch/util/filters.js16
-rw-r--r--app/javascript/flavours/glitch/util/icons.js13
-rw-r--r--app/javascript/mastodon/actions/filters.js93
-rw-r--r--app/javascript/mastodon/actions/notifications.js19
-rw-r--r--app/javascript/mastodon/actions/statuses.js4
-rw-r--r--app/javascript/mastodon/actions/tags.js6
-rw-r--r--app/javascript/mastodon/components/icon_button.js14
-rw-r--r--app/javascript/mastodon/components/status.js7
-rw-r--r--app/javascript/mastodon/components/status_action_bar.js16
-rw-r--r--app/javascript/mastodon/containers/status_container.js9
-rw-r--r--app/javascript/mastodon/features/audio/index.js64
-rw-r--r--app/javascript/mastodon/features/compose/components/language_dropdown.js19
-rw-r--r--app/javascript/mastodon/features/filters/added_to_filter.js102
-rw-r--r--app/javascript/mastodon/features/filters/select_filter.js192
-rw-r--r--app/javascript/mastodon/features/status/components/detailed_status.js4
-rw-r--r--app/javascript/mastodon/features/ui/components/filter_modal.js134
-rw-r--r--app/javascript/mastodon/features/ui/components/modal_root.js2
-rw-r--r--app/javascript/mastodon/features/ui/util/async-components.js4
-rw-r--r--app/javascript/mastodon/locales/af.json18
-rw-r--r--app/javascript/mastodon/locales/ar.json18
-rw-r--r--app/javascript/mastodon/locales/ast.json18
-rw-r--r--app/javascript/mastodon/locales/bg.json18
-rw-r--r--app/javascript/mastodon/locales/bn.json18
-rw-r--r--app/javascript/mastodon/locales/br.json38
-rw-r--r--app/javascript/mastodon/locales/ca.json22
-rw-r--r--app/javascript/mastodon/locales/ckb.json18
-rw-r--r--app/javascript/mastodon/locales/co.json18
-rw-r--r--app/javascript/mastodon/locales/cs.json18
-rw-r--r--app/javascript/mastodon/locales/cy.json18
-rw-r--r--app/javascript/mastodon/locales/da.json22
-rw-r--r--app/javascript/mastodon/locales/de.json22
-rw-r--r--app/javascript/mastodon/locales/defaultMessages.json107
-rw-r--r--app/javascript/mastodon/locales/el.json22
-rw-r--r--app/javascript/mastodon/locales/en-GB.json18
-rw-r--r--app/javascript/mastodon/locales/en.json18
-rw-r--r--app/javascript/mastodon/locales/eo.json22
-rw-r--r--app/javascript/mastodon/locales/es-AR.json22
-rw-r--r--app/javascript/mastodon/locales/es-MX.json26
-rw-r--r--app/javascript/mastodon/locales/es.json22
-rw-r--r--app/javascript/mastodon/locales/et.json18
-rw-r--r--app/javascript/mastodon/locales/eu.json18
-rw-r--r--app/javascript/mastodon/locales/fa.json18
-rw-r--r--app/javascript/mastodon/locales/fi.json84
-rw-r--r--app/javascript/mastodon/locales/fr.json22
-rw-r--r--app/javascript/mastodon/locales/fy.json18
-rw-r--r--app/javascript/mastodon/locales/ga.json18
-rw-r--r--app/javascript/mastodon/locales/gd.json52
-rw-r--r--app/javascript/mastodon/locales/gl.json24
-rw-r--r--app/javascript/mastodon/locales/he.json24
-rw-r--r--app/javascript/mastodon/locales/hi.json18
-rw-r--r--app/javascript/mastodon/locales/hr.json18
-rw-r--r--app/javascript/mastodon/locales/hu.json22
-rw-r--r--app/javascript/mastodon/locales/hy.json18
-rw-r--r--app/javascript/mastodon/locales/id.json18
-rw-r--r--app/javascript/mastodon/locales/io.json22
-rw-r--r--app/javascript/mastodon/locales/is.json26
-rw-r--r--app/javascript/mastodon/locales/it.json22
-rw-r--r--app/javascript/mastodon/locales/ja.json22
-rw-r--r--app/javascript/mastodon/locales/ka.json18
-rw-r--r--app/javascript/mastodon/locales/kab.json18
-rw-r--r--app/javascript/mastodon/locales/kk.json18
-rw-r--r--app/javascript/mastodon/locales/kn.json18
-rw-r--r--app/javascript/mastodon/locales/ko.json22
-rw-r--r--app/javascript/mastodon/locales/ku.json68
-rw-r--r--app/javascript/mastodon/locales/kw.json18
-rw-r--r--app/javascript/mastodon/locales/lt.json18
-rw-r--r--app/javascript/mastodon/locales/lv.json22
-rw-r--r--app/javascript/mastodon/locales/mk.json18
-rw-r--r--app/javascript/mastodon/locales/ml.json18
-rw-r--r--app/javascript/mastodon/locales/mr.json18
-rw-r--r--app/javascript/mastodon/locales/ms.json18
-rw-r--r--app/javascript/mastodon/locales/nl.json36
-rw-r--r--app/javascript/mastodon/locales/nn.json154
-rw-r--r--app/javascript/mastodon/locales/no.json18
-rw-r--r--app/javascript/mastodon/locales/oc.json18
-rw-r--r--app/javascript/mastodon/locales/pa.json18
-rw-r--r--app/javascript/mastodon/locales/pl.json22
-rw-r--r--app/javascript/mastodon/locales/pt-BR.json18
-rw-r--r--app/javascript/mastodon/locales/pt-PT.json22
-rw-r--r--app/javascript/mastodon/locales/ro.json18
-rw-r--r--app/javascript/mastodon/locales/ru.json24
-rw-r--r--app/javascript/mastodon/locales/sa.json18
-rw-r--r--app/javascript/mastodon/locales/sc.json18
-rw-r--r--app/javascript/mastodon/locales/si.json18
-rw-r--r--app/javascript/mastodon/locales/sk.json30
-rw-r--r--app/javascript/mastodon/locales/sl.json22
-rw-r--r--app/javascript/mastodon/locales/sq.json22
-rw-r--r--app/javascript/mastodon/locales/sr-Latn.json18
-rw-r--r--app/javascript/mastodon/locales/sr.json18
-rw-r--r--app/javascript/mastodon/locales/sv.json18
-rw-r--r--app/javascript/mastodon/locales/szl.json18
-rw-r--r--app/javascript/mastodon/locales/ta.json18
-rw-r--r--app/javascript/mastodon/locales/tai.json18
-rw-r--r--app/javascript/mastodon/locales/te.json18
-rw-r--r--app/javascript/mastodon/locales/th.json26
-rw-r--r--app/javascript/mastodon/locales/tr.json36
-rw-r--r--app/javascript/mastodon/locales/tt.json18
-rw-r--r--app/javascript/mastodon/locales/ug.json18
-rw-r--r--app/javascript/mastodon/locales/uk.json22
-rw-r--r--app/javascript/mastodon/locales/ur.json18
-rw-r--r--app/javascript/mastodon/locales/vi.json22
-rw-r--r--app/javascript/mastodon/locales/zgh.json18
-rw-r--r--app/javascript/mastodon/locales/zh-CN.json34
-rw-r--r--app/javascript/mastodon/locales/zh-HK.json18
-rw-r--r--app/javascript/mastodon/locales/zh-TW.json22
-rw-r--r--app/javascript/mastodon/reducers/filters.js11
-rw-r--r--app/javascript/mastodon/reducers/notifications.js10
-rw-r--r--app/javascript/mastodon/selectors/index.js19
-rw-r--r--app/javascript/mastodon/utils/filters.js16
-rw-r--r--app/javascript/mastodon/utils/icons.js13
-rw-r--r--app/javascript/styles/mastodon/components.scss25
139 files changed, 3388 insertions, 590 deletions
diff --git a/app/javascript/flavours/glitch/actions/filters.js b/app/javascript/flavours/glitch/actions/filters.js
index 050b30322..9aa31028a 100644
--- a/app/javascript/flavours/glitch/actions/filters.js
+++ b/app/javascript/flavours/glitch/actions/filters.js
@@ -1,9 +1,24 @@
 import api from 'flavours/glitch/util/api';
+import { openModal } from './modal';
 
 export const FILTERS_FETCH_REQUEST = 'FILTERS_FETCH_REQUEST';
 export const FILTERS_FETCH_SUCCESS = 'FILTERS_FETCH_SUCCESS';
 export const FILTERS_FETCH_FAIL    = 'FILTERS_FETCH_FAIL';
 
+export const FILTERS_STATUS_CREATE_REQUEST = 'FILTERS_STATUS_CREATE_REQUEST';
+export const FILTERS_STATUS_CREATE_SUCCESS = 'FILTERS_STATUS_CREATE_SUCCESS';
+export const FILTERS_STATUS_CREATE_FAIL    = 'FILTERS_STATUS_CREATE_FAIL';
+
+export const FILTERS_CREATE_REQUEST = 'FILTERS_CREATE_REQUEST';
+export const FILTERS_CREATE_SUCCESS = 'FILTERS_CREATE_SUCCESS';
+export const FILTERS_CREATE_FAIL    = 'FILTERS_CREATE_FAIL';
+
+export const initAddFilter = (status, { contextType }) => dispatch =>
+  dispatch(openModal('FILTER', {
+    statusId: status?.get('id'),
+    contextType: contextType,
+  }));
+
 export const fetchFilters = () => (dispatch, getState) => {
   dispatch({
     type: FILTERS_FETCH_REQUEST,
@@ -11,7 +26,7 @@ export const fetchFilters = () => (dispatch, getState) => {
   });
 
   api(getState)
-    .get('/api/v1/filters')
+    .get('/api/v2/filters')
     .then(({ data }) => dispatch({
       type: FILTERS_FETCH_SUCCESS,
       filters: data,
@@ -24,3 +39,55 @@ export const fetchFilters = () => (dispatch, getState) => {
       skipAlert: true,
     }));
 };
+
+export const createFilterStatus = (params, onSuccess, onFail) => (dispatch, getState) => {
+  dispatch(createFilterStatusRequest());
+
+  api(getState).post(`/api/v1/filters/${params.filter_id}/statuses`, params).then(response => {
+    dispatch(createFilterStatusSuccess(response.data));
+    if (onSuccess) onSuccess();
+  }).catch(error => {
+    dispatch(createFilterStatusFail(error));
+    if (onFail) onFail();
+  });
+};
+
+export const createFilterStatusRequest = () => ({
+  type: FILTERS_STATUS_CREATE_REQUEST,
+});
+
+export const createFilterStatusSuccess = filter_status => ({
+  type: FILTERS_STATUS_CREATE_SUCCESS,
+  filter_status,
+});
+
+export const createFilterStatusFail = error => ({
+  type: FILTERS_STATUS_CREATE_FAIL,
+  error,
+});
+
+export const createFilter = (params, onSuccess, onFail) => (dispatch, getState) => {
+  dispatch(createFilterRequest());
+
+  api(getState).post('/api/v2/filters', params).then(response => {
+    dispatch(createFilterSuccess(response.data));
+    if (onSuccess) onSuccess(response.data);
+  }).catch(error => {
+    dispatch(createFilterFail(error));
+    if (onFail) onFail();
+  });
+};
+
+export const createFilterRequest = () => ({
+  type: FILTERS_CREATE_REQUEST,
+});
+
+export const createFilterSuccess = filter => ({
+  type: FILTERS_CREATE_SUCCESS,
+  filter,
+});
+
+export const createFilterFail = error => ({
+  type: FILTERS_CREATE_FAIL,
+  error,
+});
diff --git a/app/javascript/flavours/glitch/actions/importer/index.js b/app/javascript/flavours/glitch/actions/importer/index.js
index ec41fea6e..94d133b5f 100644
--- a/app/javascript/flavours/glitch/actions/importer/index.js
+++ b/app/javascript/flavours/glitch/actions/importer/index.js
@@ -5,6 +5,7 @@ export const ACCOUNTS_IMPORT = 'ACCOUNTS_IMPORT';
 export const STATUS_IMPORT   = 'STATUS_IMPORT';
 export const STATUSES_IMPORT = 'STATUSES_IMPORT';
 export const POLLS_IMPORT    = 'POLLS_IMPORT';
+export const FILTERS_IMPORT  = 'FILTERS_IMPORT';
 
 function pushUnique(array, object) {
   if (array.every(element => element.id !== object.id)) {
@@ -28,6 +29,10 @@ export function importStatuses(statuses) {
   return { type: STATUSES_IMPORT, statuses };
 }
 
+export function importFilters(filters) {
+  return { type: FILTERS_IMPORT, filters };
+}
+
 export function importPolls(polls) {
   return { type: POLLS_IMPORT, polls };
 }
@@ -61,11 +66,16 @@ export function importFetchedStatuses(statuses) {
     const accounts = [];
     const normalStatuses = [];
     const polls = [];
+    const filters = [];
 
     function processStatus(status) {
       pushUnique(normalStatuses, normalizeStatus(status, getState().getIn(['statuses', status.id]), getState().get('local_settings')));
       pushUnique(accounts, status.account);
 
+      if (status.filtered) {
+        status.filtered.forEach(result => pushUnique(filters, result.filter));
+      }
+
       if (status.reblog && status.reblog.id) {
         processStatus(status.reblog);
       }
@@ -80,6 +90,7 @@ export function importFetchedStatuses(statuses) {
     dispatch(importPolls(polls));
     dispatch(importFetchedAccounts(accounts));
     dispatch(importStatuses(normalStatuses));
+    dispatch(importFilters(filters));
   };
 }
 
diff --git a/app/javascript/flavours/glitch/actions/importer/normalizer.js b/app/javascript/flavours/glitch/actions/importer/normalizer.js
index c6acdbdbb..9950a720b 100644
--- a/app/javascript/flavours/glitch/actions/importer/normalizer.js
+++ b/app/javascript/flavours/glitch/actions/importer/normalizer.js
@@ -42,6 +42,14 @@ export function normalizeAccount(account) {
   return account;
 }
 
+export function normalizeFilterResult(result) {
+  const normalResult = { ...result };
+
+  normalResult.filter = normalResult.filter.id;
+
+  return normalResult;
+}
+
 export function normalizeStatus(status, normalOldStatus, settings) {
   const normalStatus   = { ...status };
   normalStatus.account = status.account.id;
@@ -54,6 +62,10 @@ export function normalizeStatus(status, normalOldStatus, settings) {
     normalStatus.poll = status.poll.id;
   }
 
+  if (status.filtered) {
+    normalStatus.filtered = status.filtered.map(normalizeFilterResult);
+  }
+
   // Only calculate these values when status first encountered and
   // when the underlying values change. Otherwise keep the ones
   // already in the reducer
diff --git a/app/javascript/flavours/glitch/actions/notifications.js b/app/javascript/flavours/glitch/actions/notifications.js
index 3993b1ea5..4581ebc36 100644
--- a/app/javascript/flavours/glitch/actions/notifications.js
+++ b/app/javascript/flavours/glitch/actions/notifications.js
@@ -12,10 +12,8 @@ import { saveSettings } from './settings';
 import { defineMessages } from 'react-intl';
 import { List as ImmutableList } from 'immutable';
 import { unescapeHTML } from 'flavours/glitch/util/html';
-import { getFiltersRegex } from 'flavours/glitch/selectors';
 import { usePendingItems as preferPendingItems } from 'flavours/glitch/util/initial_state';
 import compareId from 'flavours/glitch/util/compare_id';
-import { searchTextFromRawStatus } from 'flavours/glitch/actions/importer/normalizer';
 import { requestNotificationPermission } from 'flavours/glitch/util/notifications';
 
 export const NOTIFICATIONS_UPDATE = 'NOTIFICATIONS_UPDATE';
@@ -74,20 +72,17 @@ export function updateNotifications(notification, intlMessages, intlLocale) {
     const showInColumn = activeFilter === 'all' ? getState().getIn(['settings', 'notifications', 'shows', notification.type], true) : activeFilter === notification.type;
     const showAlert    = getState().getIn(['settings', 'notifications', 'alerts', notification.type], true);
     const playSound    = getState().getIn(['settings', 'notifications', 'sounds', notification.type], true);
-    const filters      = getFiltersRegex(getState(), { contextType: 'notifications' });
 
     let filtered = false;
 
-    if (['mention', 'status'].includes(notification.type)) {
-      const dropRegex   = filters[0];
-      const regex       = filters[1];
-      const searchIndex = searchTextFromRawStatus(notification.status);
+    if (['mention', 'status'].includes(notification.type) && notification.status.filtered) {
+      const filters = notification.status.filtered.filter(result => result.filter.context.includes('notifications'));
 
-      if (dropRegex && dropRegex.test(searchIndex)) {
+      if (filters.some(result => result.filter.filter_action === 'hide')) {
         return;
       }
 
-      filtered = regex && regex.test(searchIndex);
+      filtered = filters.length > 0;
     }
 
     if (['follow_request'].includes(notification.type)) {
@@ -158,15 +153,22 @@ const excludeTypesFromFilter = filter => {
 
 const noOp = () => {};
 
-export function expandNotifications({ maxId } = {}, done = noOp) {
+let expandNotificationsController = new AbortController();
+
+export function expandNotifications({ maxId, forceLoad } = {}, done = noOp) {
   return (dispatch, getState) => {
     const activeFilter = getState().getIn(['settings', 'notifications', 'quickFilter', 'active']);
     const notifications = getState().get('notifications');
     const isLoadingMore = !!maxId;
 
     if (notifications.get('isLoading')) {
-      done();
-      return;
+      if (forceLoad) {
+        expandNotificationsController.abort();
+        expandNotificationsController = new AbortController();
+      } else {
+        done();
+        return;
+      }
     }
 
     const params = {
@@ -191,7 +193,7 @@ export function expandNotifications({ maxId } = {}, done = noOp) {
 
     dispatch(expandNotificationsRequest(isLoadingMore));
 
-    api(getState).get('/api/v1/notifications', { params }).then(response => {
+    api(getState).get('/api/v1/notifications', { params, signal: expandNotificationsController.signal }).then(response => {
       const next = getLinks(response).refs.find(link => link.rel === 'next');
 
       dispatch(importFetchedAccounts(response.data.map(item => item.account)));
@@ -232,7 +234,7 @@ export function expandNotificationsFail(error, isLoadingMore) {
     type: NOTIFICATIONS_EXPAND_FAIL,
     error,
     skipLoading: !isLoadingMore,
-    skipAlert: !isLoadingMore,
+    skipAlert: !isLoadingMore || error.name === 'AbortError',
   };
 };
 
@@ -343,7 +345,7 @@ export function setFilter (filterType) {
       path: ['notifications', 'quickFilter', 'active'],
       value: filterType,
     });
-    dispatch(expandNotifications());
+    dispatch(expandNotifications({ forceLoad: true }));
     dispatch(saveSettings());
   };
 };
diff --git a/app/javascript/flavours/glitch/actions/statuses.js b/app/javascript/flavours/glitch/actions/statuses.js
index 1f223f22e..58c1d44a6 100644
--- a/app/javascript/flavours/glitch/actions/statuses.js
+++ b/app/javascript/flavours/glitch/actions/statuses.js
@@ -42,9 +42,9 @@ export function fetchStatusRequest(id, skipLoading) {
   };
 };
 
-export function fetchStatus(id) {
+export function fetchStatus(id, forceFetch = false) {
   return (dispatch, getState) => {
-    const skipLoading = getState().getIn(['statuses', id], null) !== null;
+    const skipLoading = !forceFetch && getState().getIn(['statuses', id], null) !== null;
 
     dispatch(fetchContext(id));
 
diff --git a/app/javascript/flavours/glitch/actions/streaming.js b/app/javascript/flavours/glitch/actions/streaming.js
index 90d6a0231..375728cb5 100644
--- a/app/javascript/flavours/glitch/actions/streaming.js
+++ b/app/javascript/flavours/glitch/actions/streaming.js
@@ -21,7 +21,6 @@ import {
   updateReaction as updateAnnouncementsReaction,
   deleteAnnouncement,
 } from './announcements';
-import { fetchFilters } from './filters';
 import { getLocale } from 'mastodon/locales';
 
 const { messages } = getLocale();
@@ -97,9 +96,6 @@ export const connectTimelineStream = (timelineId, channelName, params = {}, opti
         case 'conversation':
           dispatch(updateConversations(JSON.parse(data.payload)));
           break;
-        case 'filters_changed':
-          dispatch(fetchFilters());
-          break;
         case 'announcement':
           dispatch(updateAnnouncements(JSON.parse(data.payload)));
           break;
diff --git a/app/javascript/flavours/glitch/actions/tags.js b/app/javascript/flavours/glitch/actions/tags.js
index 3933da8ba..4016cf96f 100644
--- a/app/javascript/flavours/glitch/actions/tags.js
+++ b/app/javascript/flavours/glitch/actions/tags.js
@@ -75,18 +75,18 @@ export const unfollowHashtag = name => (dispatch, getState) => {
 };
 
 export const unfollowHashtagRequest = name => ({
-  type: HASHTAG_FETCH_REQUEST,
+  type: HASHTAG_UNFOLLOW_REQUEST,
   name,
 });
 
 export const unfollowHashtagSuccess = (name, tag) => ({
-  type: HASHTAG_FETCH_SUCCESS,
+  type: HASHTAG_UNFOLLOW_SUCCESS,
   name,
   tag,
 });
 
 export const unfollowHashtagFail = (name, error) => ({
-  type: HASHTAG_FETCH_FAIL,
+  type: HASHTAG_UNFOLLOW_FAIL,
   name,
   error,
 });
diff --git a/app/javascript/flavours/glitch/actions/timelines.js b/app/javascript/flavours/glitch/actions/timelines.js
index 0b36d8ac3..0d6f844b3 100644
--- a/app/javascript/flavours/glitch/actions/timelines.js
+++ b/app/javascript/flavours/glitch/actions/timelines.js
@@ -4,8 +4,7 @@ import api, { getLinks } from 'flavours/glitch/util/api';
 import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
 import compareId from 'flavours/glitch/util/compare_id';
 import { me, usePendingItems as preferPendingItems } from 'flavours/glitch/util/initial_state';
-import { getFiltersRegex } from 'flavours/glitch/selectors';
-import { searchTextFromRawStatus } from 'flavours/glitch/actions/importer/normalizer';
+import { toServerSideType } from 'flavours/glitch/util/filters';
 
 export const TIMELINE_UPDATE  = 'TIMELINE_UPDATE';
 export const TIMELINE_DELETE  = 'TIMELINE_DELETE';
@@ -40,14 +39,13 @@ export function updateTimeline(timeline, status, accept) {
       return;
     }
 
-    const filters   = getFiltersRegex(getState(), { contextType: timeline });
-    const dropRegex = filters[0];
-    const regex     = filters[1];
-    const text      = searchTextFromRawStatus(status);
-    let filtered    = false;
+    let filtered = false;
 
-    if (status.account.id !== me) {
-      filtered = (dropRegex && dropRegex.test(text)) || (regex && regex.test(text));
+    if (status.filtered) {
+      const contextType = toServerSideType(timeline);
+      const filters = status.filtered.filter(result => result.filter.context.includes(contextType));
+
+      filtered = filters.length > 0;
     }
 
     dispatch(importFetchedStatus(status));
diff --git a/app/javascript/flavours/glitch/components/icon_button.js b/app/javascript/flavours/glitch/components/icon_button.js
index be2468d68..9ff745355 100644
--- a/app/javascript/flavours/glitch/components/icon_button.js
+++ b/app/javascript/flavours/glitch/components/icon_button.js
@@ -139,17 +139,9 @@ export default class IconButton extends React.PureComponent {
       </React.Fragment>
     );
 
-    if (href) {
-      return (
-        <a
-          href={href}
-          aria-label={title}
-          title={title}
-          target='_blank'
-          rel='noopener noreferrer'
-          className={classes}
-          style={style}
-        >
+    if (href && !this.prop) {
+      contents = (
+        <a href={href} target='_blank' rel='noopener noreferrer'>
           {contents}
         </a>
       );
diff --git a/app/javascript/flavours/glitch/components/status.js b/app/javascript/flavours/glitch/components/status.js
index 11c81765b..e238456c5 100644
--- a/app/javascript/flavours/glitch/components/status.js
+++ b/app/javascript/flavours/glitch/components/status.js
@@ -79,6 +79,7 @@ class Status extends ImmutablePureComponent {
     onOpenMedia: PropTypes.func,
     onOpenVideo: PropTypes.func,
     onBlock: PropTypes.func,
+    onAddFilter: PropTypes.func,
     onEmbed: PropTypes.func,
     onHeightChange: PropTypes.func,
     onToggleHidden: PropTypes.func,
@@ -455,8 +456,8 @@ class Status extends ImmutablePureComponent {
   }
 
   handleUnfilterClick = e => {
-    const { onUnfilter, status } = this.props;
-    onUnfilter(status.get('reblog') ? status.get('reblog') : status, () => this.setState({ forceFilter: false }));
+    this.setState({ forceFilter: false });
+    e.preventDefault();
   }
 
   handleFilterClick = () => {
@@ -557,8 +558,8 @@ class Status extends ImmutablePureComponent {
       );
     }
 
-    const filtered = (status.get('filtered') || status.getIn(['reblog', 'filtered'])) && settings.get('filtering_behavior') !== 'content_warning';
-    if (forceFilter === undefined ? filtered : forceFilter) {
+    const matchedFilters = status.get('matched_filters');
+    if (this.state.forceFilter === undefined ? matchedFilters : this.state.forceFilter) {
       const minHandlers = this.props.muted ? {} : {
         moveUp: this.handleHotkeyMoveUp,
         moveDown: this.handleHotkeyMoveDown,
@@ -567,13 +568,11 @@ class Status extends ImmutablePureComponent {
       return (
         <HotKeys handlers={minHandlers}>
           <div className='status__wrapper status__wrapper--filtered focusable' tabIndex='0' ref={this.handleRef}>
-            <FormattedMessage id='status.filtered' defaultMessage='Filtered' />
-            {settings.get('filtering_behavior') !== 'upstream' && ' '}
-            {settings.get('filtering_behavior') !== 'upstream' && (
-              <button className='status__wrapper--filtered__button' onClick={this.handleUnfilterClick}>
-                <FormattedMessage id='status.show_filter_reason' defaultMessage='(show why)' />
-              </button>
-            )}
+            <FormattedMessage id='status.filtered' defaultMessage='Filtered' />: {matchedFilters.join(', ')}.
+            {' '}
+            <button className='status__wrapper--filtered__button' onClick={this.handleUnfilterClick}>
+              <FormattedMessage id='status.show_filter_reason' defaultMessage='Show anyway' />
+            </button>
           </div>
         </HotKeys>
       );
@@ -625,6 +624,10 @@ class Status extends ImmutablePureComponent {
                 height={110}
                 cacheWidth={this.props.cacheMediaWidth}
                 deployPictureInPicture={this.handleDeployPictureInPicture}
+                sensitive={status.get('sensitive')}
+                blurhash={attachment.get('blurhash')}
+                visible={this.state.showMedia}
+                onToggleVisibility={this.handleToggleMediaVisibility}
               />
             )}
           </Bundle>,
@@ -785,11 +788,11 @@ class Status extends ImmutablePureComponent {
 
           {!isCollapsed || !(muted || !settings.getIn(['collapsed', 'show_action_bar'])) ? (
             <StatusActionBar
-              {...other}
               status={status}
               account={status.get('account')}
               showReplyCount={settings.get('show_reply_count')}
-              onFilter={this.handleFilterClick}
+              onFilter={matchedFilters ? this.handleFilterClick : null}
+              {...other}
             />
           ) : null}
           {notification ? (
diff --git a/app/javascript/flavours/glitch/components/status_action_bar.js b/app/javascript/flavours/glitch/components/status_action_bar.js
index 667afac5a..c0cd496ce 100644
--- a/app/javascript/flavours/glitch/components/status_action_bar.js
+++ b/app/javascript/flavours/glitch/components/status_action_bar.js
@@ -41,6 +41,7 @@ const messages = defineMessages({
   copy: { id: 'status.copy', defaultMessage: 'Copy link to status' },
   hide: { id: 'status.hide', defaultMessage: 'Hide toot' },
   edited: { id: 'status.edited', defaultMessage: 'Edited {date}' },
+  filter: { id: 'status.filter', defaultMessage: 'Filter this post' },
 });
 
 export default @injectIntl
@@ -67,6 +68,7 @@ class StatusActionBar extends ImmutablePureComponent {
     onPin: PropTypes.func,
     onBookmark: PropTypes.func,
     onFilter: PropTypes.func,
+    onAddFilter: PropTypes.func,
     withDismiss: PropTypes.bool,
     showReplyCount: PropTypes.bool,
     scrollKey: PropTypes.string,
@@ -193,10 +195,14 @@ class StatusActionBar extends ImmutablePureComponent {
     }
   }
 
-  handleFilterClick = () => {
+  handleHideClick = () => {
     this.props.onFilter();
   }
 
+  handleFilterClick = () => {
+    this.props.onAddFilter(this.props.status);
+  }
+
   render () {
     const { status, intl, withDismiss, showReplyCount, scrollKey } = this.props;
 
@@ -238,6 +244,12 @@ class StatusActionBar extends ImmutablePureComponent {
       menu.push({ text: intl.formatMessage(messages.mention, { name: status.getIn(['account', 'username']) }), action: this.handleMentionClick });
       menu.push({ text: intl.formatMessage(messages.direct, { name: status.getIn(['account', 'username']) }), action: this.handleDirectClick });
       menu.push(null);
+
+      if (!this.props.onFilter) {
+        menu.push({ text: intl.formatMessage(messages.filter), action: this.handleFilterClick });
+        menu.push(null);
+      }
+
       menu.push({ text: intl.formatMessage(messages.mute, { name: status.getIn(['account', 'username']) }), action: this.handleMuteClick });
       menu.push({ text: intl.formatMessage(messages.block, { name: status.getIn(['account', 'username']) }), action: this.handleBlockClick });
       menu.push({ text: intl.formatMessage(messages.report, { name: status.getIn(['account', 'username']) }), action: this.handleReport });
@@ -271,10 +283,6 @@ class StatusActionBar extends ImmutablePureComponent {
       <IconButton className='status__action-bar-button' title={intl.formatMessage(messages.share)} icon='share-alt' onClick={this.handleShareClick} />
     );
 
-    const filterButton = status.get('filtered') && (
-      <IconButton className='status__action-bar-button' title={intl.formatMessage(messages.hide)} icon='eye' onClick={this.handleFilterClick} />
-    );
-
     let replyButton = (
       <IconButton
         className='status__action-bar-button'
@@ -309,6 +317,10 @@ class StatusActionBar extends ImmutablePureComponent {
       reblogTitle = intl.formatMessage(messages.cannot_reblog);
     }
 
+    const filterButton = this.props.onFilter && (
+      <IconButton className='status__action-bar-button' title={intl.formatMessage(messages.hide)} icon='eye' onClick={this.handleHideClick} />
+    );
+
     return (
       <div className='status__action-bar'>
         {replyButton}
@@ -316,6 +328,7 @@ class StatusActionBar extends ImmutablePureComponent {
         <IconButton className='status__action-bar-button star-icon' animate active={status.get('favourited')} pressed={status.get('favourited')} title={intl.formatMessage(messages.favourite)} icon='star' onClick={this.handleFavouriteClick} />
         {shareButton}
         <IconButton className='status__action-bar-button bookmark-icon' disabled={anonymousAccess} active={status.get('bookmarked')} pressed={status.get('bookmarked')} title={intl.formatMessage(messages.bookmark)} icon='bookmark' onClick={this.handleBookmarkClick} />
+
         {filterButton}
 
         <div className='status__action-bar-dropdown'>
diff --git a/app/javascript/flavours/glitch/containers/status_container.js b/app/javascript/flavours/glitch/containers/status_container.js
index 6c8f261e4..0ba2e712c 100644
--- a/app/javascript/flavours/glitch/containers/status_container.js
+++ b/app/javascript/flavours/glitch/containers/status_container.js
@@ -1,7 +1,7 @@
 import { connect } from 'react-redux';
 import Status from 'flavours/glitch/components/status';
 import { List as ImmutableList } from 'immutable';
-import { makeGetStatus, regexFromFilters, toServerSideType } from 'flavours/glitch/selectors';
+import { makeGetStatus } from 'flavours/glitch/selectors';
 import {
   replyCompose,
   mentionCompose,
@@ -25,6 +25,9 @@ import {
   revealStatus,
   editStatus
 } from 'flavours/glitch/actions/statuses';
+import {
+  initAddFilter,
+} from 'flavours/glitch/actions/filters';
 import { initMuteModal } from 'flavours/glitch/actions/mutes';
 import { initBlockModal } from 'flavours/glitch/actions/blocks';
 import { initReport } from 'flavours/glitch/actions/reports';
@@ -201,52 +204,14 @@ const mapDispatchToProps = (dispatch, { intl, contextType }) => ({
     dispatch(initBlockModal(account));
   },
 
-  onUnfilter (status, onConfirm) {
-    dispatch((_, getState) => {
-      let state = getState();
-      const serverSideType = toServerSideType(contextType);
-      const enabledFilters = state.get('filters', ImmutableList()).filter(filter => filter.get('context').includes(serverSideType) && (filter.get('expires_at') === null || Date.parse(filter.get('expires_at')) > (new Date()))).toArray();
-      const searchIndex = status.get('search_index');
-      const matchingFilters = enabledFilters.filter(filter => regexFromFilters([filter]).test(searchIndex));
-      dispatch(openModal('CONFIRM', {
-        message: [
-          <FormattedMessage id='confirmations.unfilter' defaultMessage='Information about this filtered toot' />,
-          <div className='filtered-status-info'>
-            <Spoilers spoilerText={intl.formatMessage(messages.author)}>
-              <AccountContainer id={status.getIn(['account', 'id'])} />
-            </Spoilers>
-            <Spoilers spoilerText={intl.formatMessage(messages.matchingFilters, {count: matchingFilters.size})}>
-              <ul>
-                {matchingFilters.map(filter => (
-                  <li>
-                    {filter.get('phrase')}
-                    {!!filterEditLink && ' '}
-                    {!!filterEditLink && (
-                      <a
-                        target='_blank'
-                        className='filtered-status-edit-link'
-                        title={intl.formatMessage(messages.editFilter)}
-                        href={filterEditLink(filter.get('id'))}
-                      >
-                        <Icon id='pencil' />
-                      </a>
-                    )}
-                  </li>
-                ))}
-              </ul>
-            </Spoilers>
-          </div>
-        ],
-        confirm: intl.formatMessage(messages.unfilterConfirm),
-        onConfirm: onConfirm,
-      }));
-    });
-  },
-
   onReport (status) {
     dispatch(initReport(status.get('account'), status));
   },
 
+  onAddFilter (status) {
+    dispatch(initAddFilter(status, { contextType }));
+  },
+
   onMute (account) {
     dispatch(initMuteModal(account));
   },
diff --git a/app/javascript/flavours/glitch/features/audio/index.js b/app/javascript/flavours/glitch/features/audio/index.js
index ac0468f70..8fa64342e 100644
--- a/app/javascript/flavours/glitch/features/audio/index.js
+++ b/app/javascript/flavours/glitch/features/audio/index.js
@@ -1,6 +1,6 @@
 import React from 'react';
 import PropTypes from 'prop-types';
-import { defineMessages, injectIntl } from 'react-intl';
+import { defineMessages, FormattedMessage, injectIntl } from 'react-intl';
 import { formatTime } from 'flavours/glitch/features/video';
 import Icon from 'flavours/glitch/components/icon';
 import classNames from 'classnames';
@@ -8,6 +8,9 @@ import { throttle } from 'lodash';
 import { getPointerPosition, fileNameFromURL } from 'flavours/glitch/features/video';
 import { debounce } from 'lodash';
 import Visualizer from './visualizer';
+import { displayMedia, useBlurhash } from 'flavours/glitch/util/initial_state';
+import Blurhash from 'flavours/glitch/components/blurhash';
+import { is } from 'immutable';
 
 const messages = defineMessages({
   play: { id: 'video.play', defaultMessage: 'Play' },
@@ -15,6 +18,7 @@ const messages = defineMessages({
   mute: { id: 'video.mute', defaultMessage: 'Mute sound' },
   unmute: { id: 'video.unmute', defaultMessage: 'Unmute sound' },
   download: { id: 'video.download', defaultMessage: 'Download file' },
+  hide: { id: 'audio.hide', defaultMessage: 'Hide audio' },
 });
 
 const TICK_SIZE = 10;
@@ -30,10 +34,14 @@ class Audio extends React.PureComponent {
     duration: PropTypes.number,
     width: PropTypes.number,
     height: PropTypes.number,
+    sensitive: PropTypes.bool,
     editable: PropTypes.bool,
     fullscreen: PropTypes.bool,
     intl: PropTypes.object.isRequired,
+    blurhash: PropTypes.string,
     cacheWidth: PropTypes.func,
+    visible: PropTypes.bool,
+    onToggleVisibility: PropTypes.func,
     backgroundColor: PropTypes.string,
     foregroundColor: PropTypes.string,
     accentColor: PropTypes.string,
@@ -53,6 +61,7 @@ class Audio extends React.PureComponent {
     muted: false,
     volume: 0.5,
     dragging: false,
+    revealed: this.props.visible !== undefined ? this.props.visible : (displayMedia !== 'hide_all' && !this.props.sensitive || displayMedia === 'show_all'),
   };
 
   constructor (props) {
@@ -78,6 +87,8 @@ class Audio extends React.PureComponent {
       backgroundColor: this.props.backgroundColor,
       foregroundColor: this.props.foregroundColor,
       accentColor: this.props.accentColor,
+      sensitive: this.props.sensitive,
+      visible: this.props.visible,
     };
   }
 
@@ -132,6 +143,12 @@ class Audio extends React.PureComponent {
     }
   }
 
+  componentWillReceiveProps (nextProps) {
+    if (!is(nextProps.visible, this.props.visible) && nextProps.visible !== undefined) {
+      this.setState({ revealed: nextProps.visible });
+    }
+  }
+
   componentWillUnmount () {
     window.removeEventListener('scroll', this.handleScroll);
     window.removeEventListener('resize', this.handleResize);
@@ -195,6 +212,14 @@ class Audio extends React.PureComponent {
     });
   }
 
+  toggleReveal = () => {
+    if (this.props.onToggleVisibility) {
+      this.props.onToggleVisibility();
+    } else {
+      this.setState({ revealed: !this.state.revealed });
+    }
+  }
+
   handleVolumeMouseDown = e => {
     document.addEventListener('mousemove', this.handleMouseVolSlide, true);
     document.addEventListener('mouseup', this.handleVolumeMouseUp, true);
@@ -439,13 +464,29 @@ class Audio extends React.PureComponent {
   }
 
   render () {
-    const { src, intl, alt, editable, autoPlay } = this.props;
-    const { paused, muted, volume, currentTime, duration, buffer, dragging } = this.state;
+    const { src, intl, alt, editable, autoPlay, sensitive, blurhash } = this.props;
+    const { paused, muted, volume, currentTime, duration, buffer, dragging, revealed } = this.state;
     const progress = Math.min((currentTime / duration) * 100, 100);
 
+    let warning;
+    if (sensitive) {
+      warning = <FormattedMessage id='status.sensitive_warning' defaultMessage='Sensitive content' />;
+    } else {
+      warning = <FormattedMessage id='status.media_hidden' defaultMessage='Media hidden' />;
+    }
+
     return (
-      <div className={classNames('audio-player', { editable })} ref={this.setPlayerRef} style={{ backgroundColor: this._getBackgroundColor(), color: this._getForegroundColor(), width: '100%', height: this.props.fullscreen ? '100%' : (this.state.height || this.props.height) }} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave} tabIndex='0' onKeyDown={this.handleKeyDown}>
-        <audio
+      <div className={classNames('audio-player', { editable, inactive: !revealed })} ref={this.setPlayerRef} style={{ backgroundColor: this._getBackgroundColor(), color: this._getForegroundColor(), width: '100%', height: this.props.fullscreen ? '100%' : (this.state.height || this.props.height) }} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave} tabIndex='0' onKeyDown={this.handleKeyDown}>
+
+        <Blurhash
+          hash={blurhash}
+          className={classNames('media-gallery__preview', {
+            'media-gallery__preview--hidden': revealed,
+          })}
+          dummy={!useBlurhash}
+        />
+
+        {(revealed || editable) && <audio
           src={src}
           ref={this.setAudioRef}
           preload={autoPlay ? 'auto' : 'none'}
@@ -454,7 +495,7 @@ class Audio extends React.PureComponent {
           onProgress={this.handleProgress}
           onLoadedData={this.handleLoadedData}
           crossOrigin='anonymous'
-        />
+        />}
 
         <canvas
           role='button'
@@ -470,13 +511,19 @@ class Audio extends React.PureComponent {
           aria-label={alt}
         />
 
-        <img
+        <div className={classNames('spoiler-button', { 'spoiler-button--hidden': revealed || editable })}>
+          <button type='button' className='spoiler-button__overlay' onClick={this.toggleReveal}>
+            <span className='spoiler-button__overlay__label'>{warning}</span>
+          </button>
+        </div>
+
+        {(revealed || editable) && <img
           src={this.props.poster}
           alt=''
           width={(this._getRadius() - TICK_SIZE) * 2}
           height={(this._getRadius() - TICK_SIZE) * 2}
           style={{ position: 'absolute', left: this._getCX(), top: this._getCY(), transform: 'translate(-50%, -50%)', borderRadius: '50%', pointerEvents: 'none' }}
-        />
+        />}
 
         <div className='video-player__seek' onMouseDown={this.handleMouseDown} ref={this.setSeekRef}>
           <div className='video-player__seek__buffer' style={{ width: `${buffer}%` }} />
@@ -514,6 +561,7 @@ class Audio extends React.PureComponent {
             </div>
 
             <div className='video-player__buttons right'>
+              {!editable && <button type='button' title={intl.formatMessage(messages.hide)} aria-label={intl.formatMessage(messages.hide)} className='player-button' onClick={this.toggleReveal}><Icon id='eye-slash' fixedWidth /></button>}
               <a title={intl.formatMessage(messages.download)} aria-label={intl.formatMessage(messages.download)} className='video-player__download__icon player-button' href={this.props.src} download>
                 <Icon id={'download'} fixedWidth />
               </a>
diff --git a/app/javascript/flavours/glitch/features/compose/components/language_dropdown.js b/app/javascript/flavours/glitch/features/compose/components/language_dropdown.js
index c8c503e58..035b0c0c3 100644
--- a/app/javascript/flavours/glitch/features/compose/components/language_dropdown.js
+++ b/app/javascript/flavours/glitch/features/compose/components/language_dropdown.js
@@ -8,6 +8,7 @@ import spring from 'react-motion/lib/spring';
 import { supportsPassiveEvents } from 'detect-passive-events';
 import classNames from 'classnames';
 import { languages as preloadedLanguages } from 'flavours/glitch/util/initial_state';
+import { loupeIcon, deleteIcon } from 'flavours/glitch/util/icons';
 import fuzzysort from 'fuzzysort';
 
 const messages = defineMessages({
@@ -16,22 +17,6 @@ const messages = defineMessages({
   clear: { id: 'emoji_button.clear', defaultMessage: 'Clear' },
 });
 
-// Copied from emoji-mart for consistency with emoji picker and since
-// they don't export the icons in the package
-const icons = {
-  loupe: (
-    <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' width='13' height='13'>
-      <path d='M12.9 14.32a8 8 0 1 1 1.41-1.41l5.35 5.33-1.42 1.42-5.33-5.34zM8 14A6 6 0 1 0 8 2a6 6 0 0 0 0 12z' />
-    </svg>
-  ),
-
-  delete: (
-    <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' width='13' height='13'>
-      <path d='M10 8.586L2.929 1.515 1.515 2.929 8.586 10l-7.071 7.071 1.414 1.414L10 11.414l7.071 7.071 1.414-1.414L11.414 10l7.071-7.071-1.414-1.414L10 8.586z' />
-    </svg>
-  ),
-};
-
 const listenerOptions = supportsPassiveEvents ? { passive: true } : false;
 
 class LanguageDropdownMenu extends React.PureComponent {
@@ -242,7 +227,7 @@ class LanguageDropdownMenu extends React.PureComponent {
           <div className={`language-dropdown__dropdown ${placement}`} style={{ ...style, opacity: opacity, transform: mounted ? `scale(${scaleX}, ${scaleY})` : null }} ref={this.setRef}>
             <div className='emoji-mart-search'>
               <input type='search' value={searchValue} onChange={this.handleSearchChange} onKeyDown={this.handleSearchKeyDown} placeholder={intl.formatMessage(messages.search)} autoFocus />
-              <button className='emoji-mart-search-icon' disabled={!isSearching} aria-label={intl.formatMessage(messages.clear)} onClick={this.handleClear}>{!isSearching ? icons.loupe : icons.delete}</button>
+              <button className='emoji-mart-search-icon' disabled={!isSearching} aria-label={intl.formatMessage(messages.clear)} onClick={this.handleClear}>{!isSearching ? loupeIcon : deleteIcon}</button>
             </div>
 
             <div className='language-dropdown__dropdown__results emoji-mart-scroll' role='listbox' ref={this.setListRef}>
diff --git a/app/javascript/flavours/glitch/features/filters/added_to_filter.js b/app/javascript/flavours/glitch/features/filters/added_to_filter.js
new file mode 100644
index 000000000..f777ca429
--- /dev/null
+++ b/app/javascript/flavours/glitch/features/filters/added_to_filter.js
@@ -0,0 +1,102 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import ImmutablePropTypes from 'react-immutable-proptypes';
+import { FormattedMessage } from 'react-intl';
+import { toServerSideType } from 'flavours/glitch/util/filters';
+import Button from 'flavours/glitch/components/button';
+import { connect } from 'react-redux';
+
+const mapStateToProps = (state, { filterId }) => ({
+  filter: state.getIn(['filters', filterId]),
+});
+
+export default @connect(mapStateToProps)
+class AddedToFilter extends React.PureComponent {
+
+  static propTypes = {
+    onClose: PropTypes.func.isRequired,
+    contextType: PropTypes.string,
+    filter: ImmutablePropTypes.map.isRequired,
+    dispatch: PropTypes.func.isRequired,
+  };
+
+  handleCloseClick = () => {
+    const { onClose } = this.props;
+    onClose();
+  };
+
+  render () {
+    const { filter, contextType } = this.props;
+
+    let expiredMessage = null;
+    if (filter.get('expires_at') && filter.get('expires_at') < new Date()) {
+      expiredMessage = (
+        <React.Fragment>
+          <h4 className='report-dialog-modal__subtitle'><FormattedMessage id='filter_modal.added.expired_title' defaultMessage='Expired filter!' /></h4>
+          <p className='report-dialog-modal__lead'>
+            <FormattedMessage
+              id='filter_modal.added.expired_explanation'
+              defaultMessage='This filter category has expired, you will need to change the expiration date for it to apply.'
+            />
+          </p>
+        </React.Fragment>
+      );
+    }
+
+    let contextMismatchMessage = null;
+    if (contextType && !filter.get('context').includes(toServerSideType(contextType))) {
+      contextMismatchMessage = (
+        <React.Fragment>
+          <h4 className='report-dialog-modal__subtitle'><FormattedMessage id='filter_modal.added.context_mismatch_title' defaultMessage='Context mismatch!' /></h4>
+          <p className='report-dialog-modal__lead'>
+            <FormattedMessage
+              id='filter_modal.added.context_mismatch_explanation'
+              defaultMessage='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.'
+            />
+          </p>
+        </React.Fragment>
+      );
+    }
+
+    const settings_link = (
+      <a href={`/filters/${filter.get('id')}/edit`}>
+        <FormattedMessage
+          id='filter_modal.added.settings_link'
+          defaultMessage='settings page'
+        />
+      </a>
+    );
+
+    return (
+      <React.Fragment>
+        <h3 className='report-dialog-modal__title'><FormattedMessage id='filter_modal.added.title' defaultMessage='Filter added!' /></h3>
+        <p className='report-dialog-modal__lead'>
+          <FormattedMessage
+            id='filter_modal.added.short_explanation'
+            defaultMessage='This post has been added to the following filter category: {title}.'
+            values={{ title: filter.get('title') }}
+          />
+        </p>
+
+        {expiredMessage}
+        {contextMismatchMessage}
+
+        <h4 className='report-dialog-modal__subtitle'><FormattedMessage id='filter_modal.added.review_and_configure_title' defaultMessage='Filter settings' /></h4>
+        <p className='report-dialog-modal__lead'>
+          <FormattedMessage
+            id='filter_modal.added.review_and_configure'
+            defaultMessage='To review and further configure this filter category, go to the {settings_link}.'
+            values={{ settings_link }}
+          />
+        </p>
+
+        <div className='flex-spacer' />
+
+        <div className='report-dialog-modal__actions'>
+          <Button onClick={this.handleCloseClick}><FormattedMessage id='report.close' defaultMessage='Done' /></Button>
+        </div>
+      </React.Fragment>
+    );
+  }
+
+}
diff --git a/app/javascript/flavours/glitch/features/filters/select_filter.js b/app/javascript/flavours/glitch/features/filters/select_filter.js
new file mode 100644
index 000000000..5321dbb96
--- /dev/null
+++ b/app/javascript/flavours/glitch/features/filters/select_filter.js
@@ -0,0 +1,192 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { connect } from 'react-redux';
+import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
+import { toServerSideType } from 'flavours/glitch/util/filters';
+import { loupeIcon, deleteIcon } from 'flavours/glitch/util/icons';
+import Icon from 'flavours/glitch/components/icon';
+import fuzzysort from 'fuzzysort';
+
+const messages = defineMessages({
+  search: { id: 'filter_modal.select_filter.search', defaultMessage: 'Search or create' },
+  clear: { id: 'emoji_button.clear', defaultMessage: 'Clear' },
+});
+
+const mapStateToProps = (state, { contextType }) => ({
+  filters: Array.from(state.get('filters').values()).map((filter) => [
+    filter.get('id'),
+    filter.get('title'),
+    filter.get('keywords')?.map((keyword) => keyword.get('keyword')).join('\n'),
+    filter.get('expires_at') && filter.get('expires_at') < new Date(),
+    contextType && !filter.get('context').includes(toServerSideType(contextType)),
+  ]),
+});
+
+export default @connect(mapStateToProps)
+@injectIntl
+class SelectFilter extends React.PureComponent {
+
+  static propTypes = {
+    onSelectFilter: PropTypes.func.isRequired,
+    onNewFilter: PropTypes.func.isRequired,
+    filters: PropTypes.arrayOf(PropTypes.arrayOf(PropTypes.object)),
+    intl: PropTypes.object.isRequired,
+  };
+
+  state = {
+    searchValue: '',
+  };
+
+  search () {
+    const { filters } = this.props;
+    const { searchValue } = this.state;
+
+    if (searchValue === '') {
+      return filters;
+    }
+
+    return fuzzysort.go(searchValue, filters, {
+      keys: ['1', '2'],
+      limit: 5,
+      threshold: -10000,
+    }).map(result => result.obj);
+  }
+
+  renderItem = filter => {
+    let warning = null;
+    if (filter[3] || filter[4]) {
+      warning = (
+        <span className='language-dropdown__dropdown__results__item__common-name'>
+          (
+          {filter[3] && <FormattedMessage id='filter_modal.select_filter.expired' defaultMessage='expired' />}
+          {filter[3] && filter[4] && ', '}
+          {filter[4] && <FormattedMessage id='filter_modal.select_filter.context_mismatch' defaultMessage='does not apply to this context' />}
+          )
+        </span>
+      );
+    }
+
+    return (
+      <div key={filter[0]} role='button' tabIndex='0' data-index={filter[0]} className='language-dropdown__dropdown__results__item' onClick={this.handleItemClick} onKeyDown={this.handleKeyDown}>
+        <span className='language-dropdown__dropdown__results__item__native-name'>{filter[1]}</span> {warning}
+      </div>
+    );
+  }
+
+  renderCreateNew (name) {
+    return (
+      <div key='add-new-filter' role='button' tabIndex='0' className='language-dropdown__dropdown__results__item' onClick={this.handleNewFilterClick} onKeyDown={this.handleKeyDown}>
+        <Icon id='plus' fixedWidth /> <FormattedMessage id='filter_modal.select_filter.prompt_new' defaultMessage='New category: {name}' values={{ name }} />
+      </div>
+    );
+  }
+
+  handleSearchChange = ({ target }) => {
+    this.setState({ searchValue: target.value });
+  }
+
+  setListRef = c => {
+    this.listNode = c;
+  }
+
+  handleKeyDown = e => {
+    const index = Array.from(this.listNode.childNodes).findIndex(node => node === e.currentTarget);
+
+    let element = null;
+
+    switch(e.key) {
+    case ' ':
+    case 'Enter':
+      e.currentTarget.click();
+      break;
+    case 'ArrowDown':
+      element = this.listNode.childNodes[index + 1] || this.listNode.firstChild;
+      break;
+    case 'ArrowUp':
+      element = this.listNode.childNodes[index - 1] || this.listNode.lastChild;
+      break;
+    case 'Tab':
+      if (e.shiftKey) {
+        element = this.listNode.childNodes[index - 1] || this.listNode.lastChild;
+      } else {
+        element = this.listNode.childNodes[index + 1] || this.listNode.firstChild;
+      }
+      break;
+    case 'Home':
+      element = this.listNode.firstChild;
+      break;
+    case 'End':
+      element = this.listNode.lastChild;
+      break;
+    }
+
+    if (element) {
+      element.focus();
+      e.preventDefault();
+      e.stopPropagation();
+    }
+  }
+
+  handleSearchKeyDown = e => {
+    let element = null;
+
+    switch(e.key) {
+    case 'Tab':
+    case 'ArrowDown':
+      element = this.listNode.firstChild;
+
+      if (element) {
+        element.focus();
+        e.preventDefault();
+        e.stopPropagation();
+      }
+
+      break;
+    }
+  }
+
+  handleClear = () => {
+    this.setState({ searchValue: '' });
+  }
+
+  handleItemClick = e => {
+    const value = e.currentTarget.getAttribute('data-index');
+
+    e.preventDefault();
+
+    this.props.onSelectFilter(value);
+  }
+
+  handleNewFilterClick = e => {
+    e.preventDefault();
+
+    this.props.onNewFilter(this.state.searchValue);
+  };
+
+  render () {
+    const { intl } = this.props;
+
+    const { searchValue } = this.state;
+    const isSearching = searchValue !== '';
+    const results = this.search();
+
+    return (
+      <React.Fragment>
+        <h3 className='report-dialog-modal__title'><FormattedMessage id='filter_modal.select_filter.title' defaultMessage='Filter this post' /></h3>
+        <p className='report-dialog-modal__lead'><FormattedMessage id='filter_modal.select_filter.subtitle' defaultMessage='Use an existing category or create a new one' /></p>
+
+        <div className='emoji-mart-search'>
+          <input type='search' value={searchValue} onChange={this.handleSearchChange} onKeyDown={this.handleSearchKeyDown} placeholder={intl.formatMessage(messages.search)} autoFocus />
+          <button className='emoji-mart-search-icon' disabled={!isSearching} aria-label={intl.formatMessage(messages.clear)} onClick={this.handleClear}>{!isSearching ? loupeIcon : deleteIcon}</button>
+        </div>
+
+        <div className='language-dropdown__dropdown__results emoji-mart-scroll' role='listbox' ref={this.setListRef}>
+          {results.map(this.renderItem)}
+          {isSearching && this.renderCreateNew(searchValue) }
+        </div>
+
+      </React.Fragment>
+    );
+  }
+
+}
diff --git a/app/javascript/flavours/glitch/features/local_settings/page/index.js b/app/javascript/flavours/glitch/features/local_settings/page/index.js
index ffa4e3409..333b73b45 100644
--- a/app/javascript/flavours/glitch/features/local_settings/page/index.js
+++ b/app/javascript/flavours/glitch/features/local_settings/page/index.js
@@ -24,10 +24,6 @@ const messages = defineMessages({
   side_arm_copy: { id: 'settings.side_arm_reply_mode.copy', defaultMessage: 'Copy privacy setting of the toot being replied to' },
   side_arm_restrict: { id: 'settings.side_arm_reply_mode.restrict', defaultMessage: 'Restrict privacy setting to that of the toot being replied to' },
   regexp: { id: 'settings.content_warnings.regexp', defaultMessage: 'Regular expression' },
-  filters_drop: { id: 'settings.filtering_behavior.drop', defaultMessage: 'Hide filtered toots completely' },
-  filters_upstream: { id: 'settings.filtering_behavior.upstream', defaultMessage: 'Show "filtered" like vanilla Mastodon' },
-  filters_hide: { id: 'settings.filtering_behavior.hide', defaultMessage: 'Show "filtered" and add a button to display why' },
-  filters_cw: { id: 'settings.filtering_behavior.cw', defaultMessage: 'Still display the post, and add filtered words to content warning' },
   rewrite_mentions_no: { id: 'settings.rewrite_mentions_no', defaultMessage: 'Do not rewrite mentions' },
   rewrite_mentions_acct: { id: 'settings.rewrite_mentions_acct', defaultMessage: 'Rewrite with username and domain (when the account is remote)' },
   rewrite_mentions_username: { id: 'settings.rewrite_mentions_username', defaultMessage:  'Rewrite with username' },
@@ -358,25 +354,6 @@ class LocalSettingsPage extends React.PureComponent {
         </section>
       </div>
     ),
-    ({ intl, onChange, settings }) => (
-      <div className='glitch local-settings__page filters'>
-        <h1><FormattedMessage id='settings.filters' defaultMessage='Filters' /></h1>
-        <LocalSettingsPageItem
-          settings={settings}
-          item={['filtering_behavior']}
-          id='mastodon-settings--filters-behavior'
-          onChange={onChange}
-          options={[
-            { value: 'drop', message: intl.formatMessage(messages.filters_drop) },
-            { value: 'upstream', message: intl.formatMessage(messages.filters_upstream) },
-            { value: 'hide', message: intl.formatMessage(messages.filters_hide) },
-            { value: 'content_warning', message: intl.formatMessage(messages.filters_cw) }
-          ]}
-        >
-          <FormattedMessage id='settings.filtering_behavior' defaultMessage='Filtering behavior' />
-        </LocalSettingsPageItem>
-      </div>
-    ),
     ({ onChange, settings }) => (
       <div className='glitch local-settings__page collapsed'>
         <h1><FormattedMessage id='settings.collapsed_statuses' defaultMessage='Collapsed toots' /></h1>
diff --git a/app/javascript/flavours/glitch/features/status/components/detailed_status.js b/app/javascript/flavours/glitch/features/status/components/detailed_status.js
index 301a2add6..91dc5ba20 100644
--- a/app/javascript/flavours/glitch/features/status/components/detailed_status.js
+++ b/app/javascript/flavours/glitch/features/status/components/detailed_status.js
@@ -165,7 +165,11 @@ class DetailedStatus extends ImmutablePureComponent {
             backgroundColor={attachment.getIn(['meta', 'colors', 'background'])}
             foregroundColor={attachment.getIn(['meta', 'colors', 'foreground'])}
             accentColor={attachment.getIn(['meta', 'colors', 'accent'])}
+            sensitive={status.get('sensitive')}
+            visible={this.props.showMedia}
+            blurhash={attachment.get('blurhash')}
             height={150}
+            onToggleVisibility={this.props.onToggleMediaVisibility}
           />,
         );
         mediaIcons.push('music');
diff --git a/app/javascript/flavours/glitch/features/ui/components/filter_modal.js b/app/javascript/flavours/glitch/features/ui/components/filter_modal.js
new file mode 100644
index 000000000..d2482e733
--- /dev/null
+++ b/app/javascript/flavours/glitch/features/ui/components/filter_modal.js
@@ -0,0 +1,134 @@
+import React from 'react';
+import { connect } from 'react-redux';
+import { fetchStatus } from 'flavours/glitch/actions/statuses';
+import { fetchFilters, createFilter, createFilterStatus } from 'flavours/glitch/actions/filters';
+import PropTypes from 'prop-types';
+import { defineMessages, FormattedMessage, injectIntl } from 'react-intl';
+import ImmutablePureComponent from 'react-immutable-pure-component';
+import IconButton from 'flavours/glitch/components/icon_button';
+import SelectFilter from 'flavours/glitch/features/filters/select_filter';
+import AddedToFilter from 'flavours/glitch/features/filters/added_to_filter';
+
+const messages = defineMessages({
+  close: { id: 'lightbox.close', defaultMessage: 'Close' },
+});
+
+export default @connect(undefined)
+@injectIntl
+class FilterModal extends ImmutablePureComponent {
+
+  static propTypes = {
+    statusId: PropTypes.string.isRequired,
+    contextType: PropTypes.string,
+    dispatch: PropTypes.func.isRequired,
+    intl: PropTypes.object.isRequired,
+  };
+
+  state = {
+    step: 'select',
+    filterId: null,
+    isSubmitting: false,
+    isSubmitted: false,
+  };
+
+  handleNewFilterSuccess = (result) => {
+    this.handleSelectFilter(result.id);
+  };
+
+  handleSuccess = () => {
+    const { dispatch, statusId } = this.props;
+    dispatch(fetchStatus(statusId, true));
+    this.setState({ isSubmitting: false, isSubmitted: true, step: 'submitted' });
+  };
+
+  handleFail = () => {
+    this.setState({ isSubmitting: false });
+  };
+
+  handleNextStep = step => {
+    this.setState({ step });
+  };
+
+  handleSelectFilter = (filterId) => {
+    const { dispatch, statusId } = this.props;
+
+    this.setState({ isSubmitting: true, filterId });
+
+    dispatch(createFilterStatus({
+      filter_id: filterId,
+      status_id: statusId,
+    }, this.handleSuccess, this.handleFail));
+  };
+
+  handleNewFilter = (title) => {
+    const { dispatch } = this.props;
+
+    this.setState({ isSubmitting: true });
+
+    dispatch(createFilter({
+      title,
+      context: ['home', 'notifications', 'public', 'thread', 'account'],
+      action: 'warn',
+    }, this.handleNewFilterSuccess, this.handleFail));
+  };
+
+  componentDidMount () {
+    const { dispatch } = this.props;
+
+    dispatch(fetchFilters());
+  }
+
+  render () {
+    const {
+      intl,
+      statusId,
+      contextType,
+      onClose,
+    } = this.props;
+
+    const {
+      step,
+      filterId,
+    } = this.state;
+
+    let stepComponent;
+
+    switch(step) {
+    case 'select':
+      stepComponent = (
+        <SelectFilter
+          contextType={contextType}
+          onSelectFilter={this.handleSelectFilter}
+          onNewFilter={this.handleNewFilter}
+        />
+      );
+      break;
+    case 'create':
+      stepComponent = null;
+      break;
+    case 'submitted':
+      stepComponent = (
+        <AddedToFilter
+          contextType={contextType}
+          filterId={filterId}
+          statusId={statusId}
+          onClose={onClose}
+        />
+      );
+    }
+
+    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='filter_modal.title.status' defaultMessage='Filter a post' />
+        </div>
+
+        <div className='report-dialog-modal__container'>
+          {stepComponent}
+        </div>
+      </div>
+    );
+  }
+
+}
diff --git a/app/javascript/flavours/glitch/features/ui/components/modal_root.js b/app/javascript/flavours/glitch/features/ui/components/modal_root.js
index 8f18d93b7..4df3a0dee 100644
--- a/app/javascript/flavours/glitch/features/ui/components/modal_root.js
+++ b/app/javascript/flavours/glitch/features/ui/components/modal_root.js
@@ -26,6 +26,7 @@ import {
   ListAdder,
   PinnedAccountsEditor,
   CompareHistoryModal,
+  FilterModal,
 } from 'flavours/glitch/util/async-components';
 
 const MODAL_COMPONENTS = {
@@ -49,6 +50,7 @@ const MODAL_COMPONENTS = {
   'LIST_ADDER': ListAdder,
   'PINNED_ACCOUNTS_EDITOR': PinnedAccountsEditor,
   'COMPARE_HISTORY': CompareHistoryModal,
+  'FILTER': FilterModal,
 };
 
 export default class ModalRoot extends React.PureComponent {
diff --git a/app/javascript/flavours/glitch/features/ui/index.js b/app/javascript/flavours/glitch/features/ui/index.js
index 099ffc69c..2be6d9478 100644
--- a/app/javascript/flavours/glitch/features/ui/index.js
+++ b/app/javascript/flavours/glitch/features/ui/index.js
@@ -10,7 +10,6 @@ import { debounce } from 'lodash';
 import { uploadCompose, resetCompose, changeComposeSpoilerness } from 'flavours/glitch/actions/compose';
 import { expandHomeTimeline } from 'flavours/glitch/actions/timelines';
 import { expandNotifications, notificationsSetVisibility } from 'flavours/glitch/actions/notifications';
-import { fetchFilters } from 'flavours/glitch/actions/filters';
 import { fetchRules } from 'flavours/glitch/actions/rules';
 import { clearHeight } from 'flavours/glitch/actions/height_cache';
 import { synchronouslySubmitMarkers, submitMarkers, fetchMarkers } from 'flavours/glitch/actions/markers';
@@ -402,7 +401,7 @@ class UI extends React.Component {
     this.props.dispatch(fetchMarkers());
     this.props.dispatch(expandHomeTimeline());
     this.props.dispatch(expandNotifications());
-    setTimeout(() => this.props.dispatch(fetchFilters()), 500);
+
     setTimeout(() => this.props.dispatch(fetchRules()), 3000);
   }
 
diff --git a/app/javascript/flavours/glitch/reducers/filters.js b/app/javascript/flavours/glitch/reducers/filters.js
index 33f0c6732..f4f97cd3a 100644
--- a/app/javascript/flavours/glitch/reducers/filters.js
+++ b/app/javascript/flavours/glitch/reducers/filters.js
@@ -1,10 +1,43 @@
-import { FILTERS_FETCH_SUCCESS } from '../actions/filters';
-import { List as ImmutableList, fromJS } from 'immutable';
+import { FILTERS_IMPORT } from '../actions/importer';
+import { FILTERS_FETCH_SUCCESS, FILTERS_CREATE_SUCCESS } from '../actions/filters';
+import { Map as ImmutableMap, is, fromJS } from 'immutable';
 
-export default function filters(state = ImmutableList(), action) {
+const normalizeFilter = (state, filter) => {
+  const normalizedFilter = fromJS({
+    id: filter.id,
+    title: filter.title,
+    context: filter.context,
+    filter_action: filter.filter_action,
+    keywords: filter.keywords,
+    expires_at: filter.expires_at ? Date.parse(filter.expires_at) : null,
+  });
+
+  if (is(state.get(filter.id), normalizedFilter)) {
+    return state;
+  } else {
+    // Do not overwrite keywords when receiving a partial filter
+    return state.update(filter.id, ImmutableMap(), (old) => (
+      old.mergeWith(((old_value, new_value) => (new_value === undefined ? old_value : new_value)), normalizedFilter)
+    ));
+  }
+};
+
+const normalizeFilters = (state, filters) => {
+  filters.forEach(filter => {
+    state = normalizeFilter(state, filter);
+  });
+
+  return state;
+};
+
+export default function filters(state = ImmutableMap(), action) {
   switch(action.type) {
+  case FILTERS_CREATE_SUCCESS:
+    return normalizeFilter(state, action.filter);
   case FILTERS_FETCH_SUCCESS:
-    return fromJS(action.filters);
+    return normalizeFilters(ImmutableMap(), action.filters);
+  case FILTERS_IMPORT:
+    return normalizeFilters(state, action.filters);
   default:
     return state;
   }
diff --git a/app/javascript/flavours/glitch/reducers/local_settings.js b/app/javascript/flavours/glitch/reducers/local_settings.js
index 62ce29f0c..81ab1cb0d 100644
--- a/app/javascript/flavours/glitch/reducers/local_settings.js
+++ b/app/javascript/flavours/glitch/reducers/local_settings.js
@@ -21,7 +21,6 @@ const initialState = ImmutableMap({
   inline_preview_cards: true,
   hicolor_privacy_icons: false,
   show_content_type_choice: false,
-  filtering_behavior: 'hide',
   tag_misleading_links: true,
   rewrite_mentions: 'no',
   content_warnings : ImmutableMap({
diff --git a/app/javascript/flavours/glitch/reducers/notifications.js b/app/javascript/flavours/glitch/reducers/notifications.js
index f538af7fa..51d7886d7 100644
--- a/app/javascript/flavours/glitch/reducers/notifications.js
+++ b/app/javascript/flavours/glitch/reducers/notifications.js
@@ -43,7 +43,7 @@ const initialState = ImmutableMap({
   unread: 0,
   lastReadId: '0',
   readMarkerId: '0',
-  isLoading: false,
+  isLoading: 0,
   cleaningMode: false,
   isTabVisible: true,
   browserSupport: false,
@@ -121,7 +121,7 @@ const expandNormalizedNotifications = (state, notifications, next, isLoadingRece
       }
     }
 
-    mutable.set('isLoading', false);
+    mutable.update('isLoading', (nbLoading) => nbLoading - 1);
   });
 };
 
@@ -249,10 +249,10 @@ export default function notifications(state = initialState, action) {
     return state.update('items', list => state.get('pendingItems').concat(list.take(40))).set('pendingItems', ImmutableList()).set('unread', 0);
   case NOTIFICATIONS_EXPAND_REQUEST:
   case NOTIFICATIONS_DELETE_MARKED_REQUEST:
-    return state.set('isLoading', true);
+    return state.set('isLoading', (nbLoading) => nbLoading + 1);
   case NOTIFICATIONS_DELETE_MARKED_FAIL:
   case NOTIFICATIONS_EXPAND_FAIL:
-    return state.set('isLoading', false);
+    return state.set('isLoading', (nbLoading) => nbLoading - 1);
   case NOTIFICATIONS_FILTER_SET:
     return state.set('items', ImmutableList()).set('hasMore', true);
   case NOTIFICATIONS_SCROLL_TOP:
@@ -270,8 +270,6 @@ export default function notifications(state = initialState, action) {
   case FOLLOW_REQUEST_AUTHORIZE_SUCCESS:
   case FOLLOW_REQUEST_REJECT_SUCCESS:
     return filterNotifications(state, [action.id], 'follow_request');
-  case ACCOUNT_MUTE_SUCCESS:
-    return action.relationship.muting_notifications ? filterNotifications(state, [action.relationship.id]) : state;
   case NOTIFICATIONS_CLEAR:
     return state.set('items', ImmutableList()).set('pendingItems', ImmutableList()).set('hasMore', false);
   case TIMELINE_DELETE:
@@ -289,7 +287,7 @@ export default function notifications(state = initialState, action) {
     return markForDelete(state, action.id, action.yes);
 
   case NOTIFICATIONS_DELETE_MARKED_SUCCESS:
-    return deleteMarkedNotifs(state).set('isLoading', false);
+    return deleteMarkedNotifs(state).set('isLoading', (nbLoading) => nbLoading - 1);
 
   case NOTIFICATIONS_ENTER_CLEARING_MODE:
     st = state.set('cleaningMode', action.yes);
diff --git a/app/javascript/flavours/glitch/selectors/index.js b/app/javascript/flavours/glitch/selectors/index.js
index d9aa8f140..377805f16 100644
--- a/app/javascript/flavours/glitch/selectors/index.js
+++ b/app/javascript/flavours/glitch/selectors/index.js
@@ -1,6 +1,7 @@
 import escapeTextContentForBrowser from 'escape-html';
 import { createSelector } from 'reselect';
-import { List as ImmutableList, is } from 'immutable';
+import { List as ImmutableList } from 'immutable';
+import { toServerSideType } from 'flavours/glitch/util/filters';
 import { me } from 'flavours/glitch/util/initial_state';
 
 const getAccountBase         = (state, id) => state.getIn(['accounts', id], null);
@@ -21,69 +22,15 @@ export const makeGetAccount = () => {
   });
 };
 
-export const toServerSideType = columnType => {
-  switch (columnType) {
-  case 'home':
-  case 'notifications':
-  case 'public':
-  case 'thread':
-  case 'account':
-    return columnType;
-  default:
-    if (columnType.indexOf('list:') > -1) {
-      return 'home';
-    } else {
-      return 'public'; // community, account, hashtag
-    }
-  }
-};
-
-const escapeRegExp = string =>
-  string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
-
-export const regexFromFilters = filters => {
-  if (filters.size === 0) {
-    return null;
-  }
-
-  return new RegExp(filters.map(filter => {
-    let expr = escapeRegExp(filter.get('phrase'));
-
-    if (filter.get('whole_word')) {
-      if (/^[\w]/.test(expr)) {
-        expr = `\\b${expr}`;
-      }
-
-      if (/[\w]$/.test(expr)) {
-        expr = `${expr}\\b`;
-      }
-    }
-
-    return expr;
-  }).join('|'), 'i');
-};
-
-// Memoize the filter regexps for each valid server contextType
-const makeGetFiltersRegex = () => {
-  let memo = {};
-
-  return (state, { contextType }) => {
-    if (!contextType) return ImmutableList();
+const getFilters = (state, { contextType }) => {
+  if (!contextType) return null;
 
-    const serverSideType = toServerSideType(contextType);
-    const filters = state.get('filters', ImmutableList()).filter(filter => filter.get('context').includes(serverSideType) && (filter.get('expires_at') === null || Date.parse(filter.get('expires_at')) > (new Date())));
+  const serverSideType = toServerSideType(contextType);
+  const now = new Date();
 
-    if (!memo[serverSideType] || !is(memo[serverSideType].filters, filters)) {
-      const dropRegex = regexFromFilters(filters.filter(filter => filter.get('irreversible')));
-      const regex = regexFromFilters(filters);
-      memo[serverSideType] = { filters: filters, results: [dropRegex, regex] };
-    }
-    return memo[serverSideType].results;
-  };
+  return state.get('filters').filter((filter) => filter.get('context').includes(serverSideType) && (filter.get('expires_at') === null || filter.get('expires_at') > now));
 };
 
-export const getFiltersRegex = makeGetFiltersRegex();
-
 export const makeGetStatus = () => {
   return createSelector(
     [
@@ -91,60 +38,37 @@ export const makeGetStatus = () => {
       (state, { id }) => state.getIn(['statuses', state.getIn(['statuses', id, 'reblog'])]),
       (state, { id }) => state.getIn(['accounts', state.getIn(['statuses', id, 'account'])]),
       (state, { id }) => state.getIn(['accounts', state.getIn(['statuses', state.getIn(['statuses', id, 'reblog']), 'account'])]),
-      (state, _) => state.getIn(['local_settings', 'filtering_behavior']),
-      (state, _) => state.get('filters', ImmutableList()),
-      (_, { contextType }) => contextType,
-      getFiltersRegex,
+      getFilters,
     ],
 
-    (statusBase, statusReblog, accountBase, accountReblog, filteringBehavior, filters, contextType, filtersRegex) => {
+    (statusBase, statusReblog, accountBase, accountReblog, filters) => {
       if (!statusBase) {
         return null;
       }
 
-      const dropRegex = (accountReblog || accountBase).get('id') !== me && filtersRegex[0];
-
-      if (dropRegex && dropRegex.test(statusBase.get('reblog') ? statusReblog.get('search_index') : statusBase.get('search_index'))) {
-        return null;
-      }
-
-      const regex  = (accountReblog || accountBase).get('id') !== me && filtersRegex[1];
       let filtered = false;
+      if ((accountReblog || accountBase).get('id') !== me && filters) {
+        let filterResults = statusReblog?.get('filtered') || statusBase.get('filtered') || ImmutableList();
+        if (filterResults.some((result) => filters.getIn([result.get('filter'), 'filter_action']) === 'hide')) {
+          return null;
+        }
+        filterResults = filterResults.filter(result => filters.has(result.get('filter')));
+        if (!filterResults.isEmpty()) {
+          filtered = filterResults.map(result => filters.getIn([result.get('filter'), 'title']));
+        }
+      }
 
       if (statusReblog) {
-        filtered     = regex && regex.test(statusReblog.get('search_index'));
         statusReblog = statusReblog.set('account', accountReblog);
-        statusReblog = statusReblog.set('filtered', filtered);
+        statusReblog = statusReblog.set('matched_filters', filtered);
       } else {
         statusReblog = null;
       }
 
-      filtered = filtered || regex && regex.test(statusBase.get('search_index'));
-
-      if (filtered && filteringBehavior === 'drop') {
-        return null;
-      } else if (filtered && filteringBehavior === 'content_warning') {
-        let spoilerText = (statusReblog || statusBase).get('spoiler_text', '');
-        const searchIndex = (statusReblog || statusBase).get('search_index');
-        const serverSideType = toServerSideType(contextType);
-        const enabledFilters = filters.filter(filter => filter.get('context').includes(serverSideType) && (filter.get('expires_at') === null || Date.parse(filter.get('expires_at')) > (new Date()))).toArray();
-        const matchingFilters = enabledFilters.filter(filter => {
-          const regexp = regexFromFilters([filter]);
-          return regexp.test(searchIndex) && !regexp.test(spoilerText);
-        });
-        if (statusReblog) {
-          statusReblog = statusReblog.set('spoiler_text', matchingFilters.map(filter => filter.get('phrase')).concat([spoilerText]).filter(cw => !!cw).join(', '));
-          statusReblog = statusReblog.update('spoilerHtml', '', spoilerText => matchingFilters.map(filter => escapeTextContentForBrowser(filter.get('phrase'))).concat([spoilerText]).filter(cw => !!cw).join(', '));
-        } else {
-          statusBase = statusBase.set('spoiler_text', matchingFilters.map(filter => filter.get('phrase')).concat([spoilerText]).filter(cw => !!cw).join(', '));
-          statusBase = statusBase.update('spoilerHtml', '', spoilerText => matchingFilters.map(filter => escapeTextContentForBrowser(filter.get('phrase'))).concat([spoilerText]).filter(cw => !!cw).join(', '));
-        }
-      }
-
       return statusBase.withMutations(map => {
         map.set('reblog', statusReblog);
         map.set('account', accountBase);
-        map.set('filtered', filtered);
+        map.set('matched_filters', filtered);
       });
     },
   );
diff --git a/app/javascript/flavours/glitch/styles/components/media.scss b/app/javascript/flavours/glitch/styles/components/media.scss
index 8a551be73..9776e2265 100644
--- a/app/javascript/flavours/glitch/styles/components/media.scss
+++ b/app/javascript/flavours/glitch/styles/components/media.scss
@@ -389,6 +389,13 @@
     height: 100%;
   }
 
+  &.inactive {
+    audio,
+    .video-player__controls {
+      visibility: hidden;
+    }
+  }
+
   .video-player__volume::before,
   .video-player__seek::before {
     background: currentColor;
diff --git a/app/javascript/flavours/glitch/styles/components/modal.scss b/app/javascript/flavours/glitch/styles/components/modal.scss
index 90e0da02a..e95bea0d7 100644
--- a/app/javascript/flavours/glitch/styles/components/modal.scss
+++ b/app/javascript/flavours/glitch/styles/components/modal.scss
@@ -583,6 +583,16 @@
     line-height: 22px;
     color: lighten($inverted-text-color, 16%);
     margin-bottom: 30px;
+
+    a {
+      text-decoration: none;
+      color: $inverted-text-color;
+      font-weight: 500;
+
+      &:hover {
+        text-decoration: underline;
+      }
+    }
   }
 
   &__actions {
@@ -730,6 +740,14 @@
     background: transparent;
     margin: 15px 0;
   }
+
+  .emoji-mart-search {
+    padding-right: 10px;
+  }
+
+  .emoji-mart-search-icon {
+    right: 10px + 5px;
+  }
 }
 
 .report-modal__container {
diff --git a/app/javascript/flavours/glitch/util/async-components.js b/app/javascript/flavours/glitch/util/async-components.js
index 8c9630eea..86bb7be36 100644
--- a/app/javascript/flavours/glitch/util/async-components.js
+++ b/app/javascript/flavours/glitch/util/async-components.js
@@ -177,3 +177,7 @@ export function FollowRecommendations () {
 export function CompareHistoryModal () {
   return import(/*webpackChunkName: "flavours/glitch/async/compare_history_modal" */'flavours/glitch/features/ui/components/compare_history_modal');
 }
+
+export function FilterModal () {
+  return import(/*webpackChunkName: "flavours/glitch/async/filter_modal" */'flavours/glitch/features/ui/components/filter_modal');
+}
diff --git a/app/javascript/flavours/glitch/util/filters.js b/app/javascript/flavours/glitch/util/filters.js
new file mode 100644
index 000000000..97b433a99
--- /dev/null
+++ b/app/javascript/flavours/glitch/util/filters.js
@@ -0,0 +1,16 @@
+export const toServerSideType = columnType => {
+  switch (columnType) {
+  case 'home':
+  case 'notifications':
+  case 'public':
+  case 'thread':
+  case 'account':
+    return columnType;
+  default:
+    if (columnType.indexOf('list:') > -1) {
+      return 'home';
+    } else {
+      return 'public'; // community, account, hashtag
+    }
+  }
+};
diff --git a/app/javascript/flavours/glitch/util/icons.js b/app/javascript/flavours/glitch/util/icons.js
new file mode 100644
index 000000000..be566032e
--- /dev/null
+++ b/app/javascript/flavours/glitch/util/icons.js
@@ -0,0 +1,13 @@
+// Copied from emoji-mart for consistency with emoji picker and since
+// they don't export the icons in the package
+export const loupeIcon = (
+  <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' width='13' height='13'>
+    <path d='M12.9 14.32a8 8 0 1 1 1.41-1.41l5.35 5.33-1.42 1.42-5.33-5.34zM8 14A6 6 0 1 0 8 2a6 6 0 0 0 0 12z' />
+  </svg>
+);
+
+export const deleteIcon = (
+  <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' width='13' height='13'>
+    <path d='M10 8.586L2.929 1.515 1.515 2.929 8.586 10l-7.071 7.071 1.414 1.414L10 11.414l7.071 7.071 1.414-1.414L11.414 10l7.071-7.071-1.414-1.414L10 8.586z' />
+  </svg>
+);
diff --git a/app/javascript/mastodon/actions/filters.js b/app/javascript/mastodon/actions/filters.js
new file mode 100644
index 000000000..76326802e
--- /dev/null
+++ b/app/javascript/mastodon/actions/filters.js
@@ -0,0 +1,93 @@
+import api from '../api';
+import { openModal } from './modal';
+
+export const FILTERS_FETCH_REQUEST = 'FILTERS_FETCH_REQUEST';
+export const FILTERS_FETCH_SUCCESS = 'FILTERS_FETCH_SUCCESS';
+export const FILTERS_FETCH_FAIL    = 'FILTERS_FETCH_FAIL';
+
+export const FILTERS_STATUS_CREATE_REQUEST = 'FILTERS_STATUS_CREATE_REQUEST';
+export const FILTERS_STATUS_CREATE_SUCCESS = 'FILTERS_STATUS_CREATE_SUCCESS';
+export const FILTERS_STATUS_CREATE_FAIL    = 'FILTERS_STATUS_CREATE_FAIL';
+
+export const FILTERS_CREATE_REQUEST = 'FILTERS_CREATE_REQUEST';
+export const FILTERS_CREATE_SUCCESS = 'FILTERS_CREATE_SUCCESS';
+export const FILTERS_CREATE_FAIL    = 'FILTERS_CREATE_FAIL';
+
+export const initAddFilter = (status, { contextType }) => dispatch =>
+  dispatch(openModal('FILTER', {
+    statusId: status?.get('id'),
+    contextType: contextType,
+  }));
+
+export const fetchFilters = () => (dispatch, getState) => {
+  dispatch({
+    type: FILTERS_FETCH_REQUEST,
+    skipLoading: true,
+  });
+
+  api(getState)
+    .get('/api/v2/filters')
+    .then(({ data }) => dispatch({
+      type: FILTERS_FETCH_SUCCESS,
+      filters: data,
+      skipLoading: true,
+    }))
+    .catch(err => dispatch({
+      type: FILTERS_FETCH_FAIL,
+      err,
+      skipLoading: true,
+      skipAlert: true,
+    }));
+};
+
+export const createFilterStatus = (params, onSuccess, onFail) => (dispatch, getState) => {
+  dispatch(createFilterStatusRequest());
+
+  api(getState).post(`/api/v1/filters/${params.filter_id}/statuses`, params).then(response => {
+    dispatch(createFilterStatusSuccess(response.data));
+    if (onSuccess) onSuccess();
+  }).catch(error => {
+    dispatch(createFilterStatusFail(error));
+    if (onFail) onFail();
+  });
+};
+
+export const createFilterStatusRequest = () => ({
+  type: FILTERS_STATUS_CREATE_REQUEST,
+});
+
+export const createFilterStatusSuccess = filter_status => ({
+  type: FILTERS_STATUS_CREATE_SUCCESS,
+  filter_status,
+});
+
+export const createFilterStatusFail = error => ({
+  type: FILTERS_STATUS_CREATE_FAIL,
+  error,
+});
+
+export const createFilter = (params, onSuccess, onFail) => (dispatch, getState) => {
+  dispatch(createFilterRequest());
+
+  api(getState).post('/api/v2/filters', params).then(response => {
+    dispatch(createFilterSuccess(response.data));
+    if (onSuccess) onSuccess(response.data);
+  }).catch(error => {
+    dispatch(createFilterFail(error));
+    if (onFail) onFail();
+  });
+};
+
+export const createFilterRequest = () => ({
+  type: FILTERS_CREATE_REQUEST,
+});
+
+export const createFilterSuccess = filter => ({
+  type: FILTERS_CREATE_SUCCESS,
+  filter,
+});
+
+export const createFilterFail = error => ({
+  type: FILTERS_CREATE_FAIL,
+  error,
+});
diff --git a/app/javascript/mastodon/actions/notifications.js b/app/javascript/mastodon/actions/notifications.js
index 3c42f71da..d4588db2c 100644
--- a/app/javascript/mastodon/actions/notifications.js
+++ b/app/javascript/mastodon/actions/notifications.js
@@ -141,15 +141,22 @@ const excludeTypesFromFilter = filter => {
 
 const noOp = () => {};
 
-export function expandNotifications({ maxId } = {}, done = noOp) {
+let expandNotificationsController = new AbortController();
+
+export function expandNotifications({ maxId, forceLoad } = {}, done = noOp) {
   return (dispatch, getState) => {
     const activeFilter = getState().getIn(['settings', 'notifications', 'quickFilter', 'active']);
     const notifications = getState().get('notifications');
     const isLoadingMore = !!maxId;
 
     if (notifications.get('isLoading')) {
-      done();
-      return;
+      if (forceLoad) {
+        expandNotificationsController.abort();
+        expandNotificationsController = new AbortController();
+      } else {
+        done();
+        return;
+      }
     }
 
     const params = {
@@ -174,7 +181,7 @@ export function expandNotifications({ maxId } = {}, done = noOp) {
 
     dispatch(expandNotificationsRequest(isLoadingMore));
 
-    api(getState).get('/api/v1/notifications', { params }).then(response => {
+    api(getState).get('/api/v1/notifications', { params, signal: expandNotificationsController.signal }).then(response => {
       const next = getLinks(response).refs.find(link => link.rel === 'next');
 
       dispatch(importFetchedAccounts(response.data.map(item => item.account)));
@@ -215,7 +222,7 @@ export function expandNotificationsFail(error, isLoadingMore) {
     type: NOTIFICATIONS_EXPAND_FAIL,
     error,
     skipLoading: !isLoadingMore,
-    skipAlert: !isLoadingMore,
+    skipAlert: !isLoadingMore || error.name === 'AbortError',
   };
 };
 
@@ -243,7 +250,7 @@ export function setFilter (filterType) {
       path: ['notifications', 'quickFilter', 'active'],
       value: filterType,
     });
-    dispatch(expandNotifications());
+    dispatch(expandNotifications({ forceLoad: true }));
     dispatch(saveSettings());
   };
 };
diff --git a/app/javascript/mastodon/actions/statuses.js b/app/javascript/mastodon/actions/statuses.js
index adc24eabf..32a4f1f85 100644
--- a/app/javascript/mastodon/actions/statuses.js
+++ b/app/javascript/mastodon/actions/statuses.js
@@ -42,9 +42,9 @@ export function fetchStatusRequest(id, skipLoading) {
   };
 };
 
-export function fetchStatus(id) {
+export function fetchStatus(id, forceFetch = false) {
   return (dispatch, getState) => {
-    const skipLoading = getState().getIn(['statuses', id], null) !== null;
+    const skipLoading = !forceFetch && getState().getIn(['statuses', id], null) !== null;
 
     dispatch(fetchContext(id));
 
diff --git a/app/javascript/mastodon/actions/tags.js b/app/javascript/mastodon/actions/tags.js
index 216e5b541..37e79d4cb 100644
--- a/app/javascript/mastodon/actions/tags.js
+++ b/app/javascript/mastodon/actions/tags.js
@@ -75,18 +75,18 @@ export const unfollowHashtag = name => (dispatch, getState) => {
 };
 
 export const unfollowHashtagRequest = name => ({
-  type: HASHTAG_FETCH_REQUEST,
+  type: HASHTAG_UNFOLLOW_REQUEST,
   name,
 });
 
 export const unfollowHashtagSuccess = (name, tag) => ({
-  type: HASHTAG_FETCH_SUCCESS,
+  type: HASHTAG_UNFOLLOW_SUCCESS,
   name,
   tag,
 });
 
 export const unfollowHashtagFail = (name, error) => ({
-  type: HASHTAG_FETCH_FAIL,
+  type: HASHTAG_UNFOLLOW_FAIL,
   name,
   error,
 });
diff --git a/app/javascript/mastodon/components/icon_button.js b/app/javascript/mastodon/components/icon_button.js
index 81743a1db..47945c475 100644
--- a/app/javascript/mastodon/components/icon_button.js
+++ b/app/javascript/mastodon/components/icon_button.js
@@ -131,17 +131,9 @@ export default class IconButton extends React.PureComponent {
       </React.Fragment>
     );
 
-    if (href) {
-      return (
-        <a
-          href={href}
-          aria-label={title}
-          title={title}
-          target='_blank'
-          rel='noopener noreferrer'
-          className={classes}
-          style={style}
-        >
+    if (href && !this.prop) {
+      contents = (
+        <a href={href} target='_blank' rel='noopener noreferrer'>
           {contents}
         </a>
       );
diff --git a/app/javascript/mastodon/components/status.js b/app/javascript/mastodon/components/status.js
index 238a0d734..6fc132bf5 100644
--- a/app/javascript/mastodon/components/status.js
+++ b/app/javascript/mastodon/components/status.js
@@ -80,6 +80,7 @@ class Status extends ImmutablePureComponent {
     onOpenMedia: PropTypes.func,
     onOpenVideo: PropTypes.func,
     onBlock: PropTypes.func,
+    onAddFilter: PropTypes.func,
     onEmbed: PropTypes.func,
     onHeightChange: PropTypes.func,
     onToggleHidden: PropTypes.func,
@@ -409,6 +410,10 @@ class Status extends ImmutablePureComponent {
                 height={110}
                 cacheWidth={this.props.cacheMediaWidth}
                 deployPictureInPicture={pictureInPicture.get('available') ? this.handleDeployPictureInPicture : undefined}
+                sensitive={status.get('sensitive')}
+                blurhash={attachment.get('blurhash')}
+                visible={this.state.showMedia}
+                onToggleVisibility={this.handleToggleMediaVisibility}
               />
             )}
           </Bundle>
@@ -511,7 +516,7 @@ class Status extends ImmutablePureComponent {
 
             {media}
 
-            <StatusActionBar scrollKey={scrollKey} status={status} account={account} onFilter={matchedFilters && this.handleFilterClick} {...other} />
+            <StatusActionBar scrollKey={scrollKey} status={status} account={account} onFilter={matchedFilters ? this.handleFilterClick : null} {...other} />
           </div>
         </div>
       </HotKeys>
diff --git a/app/javascript/mastodon/components/status_action_bar.js b/app/javascript/mastodon/components/status_action_bar.js
index d44da482d..4b384e6e5 100644
--- a/app/javascript/mastodon/components/status_action_bar.js
+++ b/app/javascript/mastodon/components/status_action_bar.js
@@ -44,6 +44,7 @@ const messages = defineMessages({
   unblockDomain: { id: 'account.unblock_domain', defaultMessage: 'Unblock domain {domain}' },
   unmute: { id: 'account.unmute', defaultMessage: 'Unmute @{name}' },
   unblock: { id: 'account.unblock', defaultMessage: 'Unblock @{name}' },
+  filter: { id: 'status.filter', defaultMessage: 'Filter this post' },
 });
 
 const mapStateToProps = (state, { status }) => ({
@@ -80,6 +81,7 @@ class StatusActionBar extends ImmutablePureComponent {
     onPin: PropTypes.func,
     onBookmark: PropTypes.func,
     onFilter: PropTypes.func,
+    onAddFilter: PropTypes.func,
     withDismiss: PropTypes.bool,
     withCounters: PropTypes.bool,
     scrollKey: PropTypes.string,
@@ -211,8 +213,8 @@ class StatusActionBar extends ImmutablePureComponent {
     this.props.onMuteConversation(this.props.status);
   }
 
-  handleFilter = () => {
-    this.props.onFilter();
+  handleFilterClick = () => {
+    this.props.onAddFilter(this.props.status);
   }
 
   handleCopy = () => {
@@ -235,7 +237,7 @@ class StatusActionBar extends ImmutablePureComponent {
   }
 
 
-  handleFilterClick = () => {
+  handleHideClick = () => {
     this.props.onFilter();
   }
 
@@ -294,6 +296,12 @@ class StatusActionBar extends ImmutablePureComponent {
         menu.push({ text: intl.formatMessage(messages.block, { name: account.get('username') }), action: this.handleBlockClick });
       }
 
+      if (!this.props.onFilter) {
+        menu.push(null);
+        menu.push({ text: intl.formatMessage(messages.filter), action: this.handleFilterClick });
+        menu.push(null);
+      }
+
       menu.push({ text: intl.formatMessage(messages.report, { name: account.get('username') }), action: this.handleReport });
 
       if (account.get('acct') !== account.get('username')) {
@@ -343,7 +351,7 @@ class StatusActionBar extends ImmutablePureComponent {
     );
 
     const filterButton = this.props.onFilter && (
-      <IconButton className='status__action-bar-button' title={intl.formatMessage(messages.hide)} icon='eye' onClick={this.handleFilterClick} />
+      <IconButton className='status__action-bar-button' title={intl.formatMessage(messages.hide)} icon='eye' onClick={this.handleHideClick} />
     );
 
     return (
diff --git a/app/javascript/mastodon/containers/status_container.js b/app/javascript/mastodon/containers/status_container.js
index ef0aca13a..28698b082 100644
--- a/app/javascript/mastodon/containers/status_container.js
+++ b/app/javascript/mastodon/containers/status_container.js
@@ -34,6 +34,9 @@ import {
   blockDomain,
   unblockDomain,
 } from '../actions/domain_blocks';
+import {
+  initAddFilter,
+} from '../actions/filters';
 import { initMuteModal } from '../actions/mutes';
 import { initBlockModal } from '../actions/blocks';
 import { initBoostModal } from '../actions/boosts';
@@ -66,7 +69,7 @@ const makeMapStateToProps = () => {
   return mapStateToProps;
 };
 
-const mapDispatchToProps = (dispatch, { intl }) => ({
+const mapDispatchToProps = (dispatch, { intl, contextType }) => ({
 
   onReply (status, router) {
     dispatch((_, getState) => {
@@ -176,6 +179,10 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
     dispatch(initReport(status.get('account'), status));
   },
 
+  onAddFilter (status) {
+    dispatch(initAddFilter(status, { contextType }));
+  },
+
   onMute (account) {
     dispatch(initMuteModal(account));
   },
diff --git a/app/javascript/mastodon/features/audio/index.js b/app/javascript/mastodon/features/audio/index.js
index c47f55dd1..00854d0e4 100644
--- a/app/javascript/mastodon/features/audio/index.js
+++ b/app/javascript/mastodon/features/audio/index.js
@@ -1,6 +1,6 @@
 import React from 'react';
 import PropTypes from 'prop-types';
-import { defineMessages, injectIntl } from 'react-intl';
+import { defineMessages, FormattedMessage, injectIntl } from 'react-intl';
 import { formatTime } from 'mastodon/features/video';
 import Icon from 'mastodon/components/icon';
 import classNames from 'classnames';
@@ -8,6 +8,9 @@ import { throttle } from 'lodash';
 import { getPointerPosition, fileNameFromURL } from 'mastodon/features/video';
 import { debounce } from 'lodash';
 import Visualizer from './visualizer';
+import { displayMedia, useBlurhash } from '../../initial_state';
+import Blurhash from '../../components/blurhash';
+import { is } from 'immutable';
 
 const messages = defineMessages({
   play: { id: 'video.play', defaultMessage: 'Play' },
@@ -15,6 +18,7 @@ const messages = defineMessages({
   mute: { id: 'video.mute', defaultMessage: 'Mute sound' },
   unmute: { id: 'video.unmute', defaultMessage: 'Unmute sound' },
   download: { id: 'video.download', defaultMessage: 'Download file' },
+  hide: { id: 'audio.hide', defaultMessage: 'Hide audio' },
 });
 
 const TICK_SIZE = 10;
@@ -30,10 +34,14 @@ class Audio extends React.PureComponent {
     duration: PropTypes.number,
     width: PropTypes.number,
     height: PropTypes.number,
+    sensitive: PropTypes.bool,
     editable: PropTypes.bool,
     fullscreen: PropTypes.bool,
     intl: PropTypes.object.isRequired,
+    blurhash: PropTypes.string,
     cacheWidth: PropTypes.func,
+    visible: PropTypes.bool,
+    onToggleVisibility: PropTypes.func,
     backgroundColor: PropTypes.string,
     foregroundColor: PropTypes.string,
     accentColor: PropTypes.string,
@@ -53,6 +61,7 @@ class Audio extends React.PureComponent {
     muted: false,
     volume: 0.5,
     dragging: false,
+    revealed: this.props.visible !== undefined ? this.props.visible : (displayMedia !== 'hide_all' && !this.props.sensitive || displayMedia === 'show_all'),
   };
 
   constructor (props) {
@@ -78,6 +87,8 @@ class Audio extends React.PureComponent {
       backgroundColor: this.props.backgroundColor,
       foregroundColor: this.props.foregroundColor,
       accentColor: this.props.accentColor,
+      sensitive: this.props.sensitive,
+      visible: this.props.visible,
     };
   }
 
@@ -126,6 +137,12 @@ class Audio extends React.PureComponent {
     }
   }
 
+  componentWillReceiveProps (nextProps) {
+    if (!is(nextProps.visible, this.props.visible) && nextProps.visible !== undefined) {
+      this.setState({ revealed: nextProps.visible });
+    }
+  }
+
   componentWillUnmount () {
     window.removeEventListener('scroll', this.handleScroll);
     window.removeEventListener('resize', this.handleResize);
@@ -189,6 +206,14 @@ class Audio extends React.PureComponent {
     });
   }
 
+  toggleReveal = () => {
+    if (this.props.onToggleVisibility) {
+      this.props.onToggleVisibility();
+    } else {
+      this.setState({ revealed: !this.state.revealed });
+    }
+  }
+
   handleVolumeMouseDown = e => {
     document.addEventListener('mousemove', this.handleMouseVolSlide, true);
     document.addEventListener('mouseup', this.handleVolumeMouseUp, true);
@@ -433,13 +458,29 @@ class Audio extends React.PureComponent {
   }
 
   render () {
-    const { src, intl, alt, editable, autoPlay } = this.props;
-    const { paused, muted, volume, currentTime, duration, buffer, dragging } = this.state;
+    const { src, intl, alt, editable, autoPlay, sensitive, blurhash } = this.props;
+    const { paused, muted, volume, currentTime, duration, buffer, dragging, revealed } = this.state;
     const progress = Math.min((currentTime / duration) * 100, 100);
 
+    let warning;
+    if (sensitive) {
+      warning = <FormattedMessage id='status.sensitive_warning' defaultMessage='Sensitive content' />;
+    } else {
+      warning = <FormattedMessage id='status.media_hidden' defaultMessage='Media hidden' />;
+    }
+
     return (
-      <div className={classNames('audio-player', { editable })} ref={this.setPlayerRef} style={{ backgroundColor: this._getBackgroundColor(), color: this._getForegroundColor(), width: '100%', height: this.props.fullscreen ? '100%' : (this.state.height || this.props.height) }} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave} tabIndex='0' onKeyDown={this.handleKeyDown}>
-        <audio
+      <div className={classNames('audio-player', { editable, inactive: !revealed })} ref={this.setPlayerRef} style={{ backgroundColor: this._getBackgroundColor(), color: this._getForegroundColor(), width: '100%', height: this.props.fullscreen ? '100%' : (this.state.height || this.props.height) }} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave} tabIndex='0' onKeyDown={this.handleKeyDown}>
+
+        <Blurhash
+          hash={blurhash}
+          className={classNames('media-gallery__preview', {
+            'media-gallery__preview--hidden': revealed,
+          })}
+          dummy={!useBlurhash}
+        />
+
+        {(revealed || editable) && <audio
           src={src}
           ref={this.setAudioRef}
           preload={autoPlay ? 'auto' : 'none'}
@@ -448,7 +489,7 @@ class Audio extends React.PureComponent {
           onProgress={this.handleProgress}
           onLoadedData={this.handleLoadedData}
           crossOrigin='anonymous'
-        />
+        />}
 
         <canvas
           role='button'
@@ -464,13 +505,19 @@ class Audio extends React.PureComponent {
           aria-label={alt}
         />
 
-        <img
+        <div className={classNames('spoiler-button', { 'spoiler-button--hidden': revealed || editable })}>
+          <button type='button' className='spoiler-button__overlay' onClick={this.toggleReveal}>
+            <span className='spoiler-button__overlay__label'>{warning}</span>
+          </button>
+        </div>
+
+        {(revealed || editable) && <img
           src={this.props.poster}
           alt=''
           width={(this._getRadius() - TICK_SIZE) * 2}
           height={(this._getRadius() - TICK_SIZE) * 2}
           style={{ position: 'absolute', left: this._getCX(), top: this._getCY(), transform: 'translate(-50%, -50%)', borderRadius: '50%', pointerEvents: 'none' }}
-        />
+        />}
 
         <div className='video-player__seek' onMouseDown={this.handleMouseDown} ref={this.setSeekRef}>
           <div className='video-player__seek__buffer' style={{ width: `${buffer}%` }} />
@@ -508,6 +555,7 @@ class Audio extends React.PureComponent {
             </div>
 
             <div className='video-player__buttons right'>
+              {!editable && <button type='button' title={intl.formatMessage(messages.hide)} aria-label={intl.formatMessage(messages.hide)} className='player-button' onClick={this.toggleReveal}><Icon id='eye-slash' fixedWidth /></button>}
               <a title={intl.formatMessage(messages.download)} aria-label={intl.formatMessage(messages.download)} className='video-player__download__icon player-button' href={this.props.src} download>
                 <Icon id={'download'} fixedWidth />
               </a>
diff --git a/app/javascript/mastodon/features/compose/components/language_dropdown.js b/app/javascript/mastodon/features/compose/components/language_dropdown.js
index d76490c77..0af3db7a4 100644
--- a/app/javascript/mastodon/features/compose/components/language_dropdown.js
+++ b/app/javascript/mastodon/features/compose/components/language_dropdown.js
@@ -8,6 +8,7 @@ import spring from 'react-motion/lib/spring';
 import { supportsPassiveEvents } from 'detect-passive-events';
 import classNames from 'classnames';
 import { languages as preloadedLanguages } from 'mastodon/initial_state';
+import { loupeIcon, deleteIcon } from 'mastodon/utils/icons';
 import fuzzysort from 'fuzzysort';
 
 const messages = defineMessages({
@@ -16,22 +17,6 @@ const messages = defineMessages({
   clear: { id: 'emoji_button.clear', defaultMessage: 'Clear' },
 });
 
-// Copied from emoji-mart for consistency with emoji picker and since
-// they don't export the icons in the package
-const icons = {
-  loupe: (
-    <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' width='13' height='13'>
-      <path d='M12.9 14.32a8 8 0 1 1 1.41-1.41l5.35 5.33-1.42 1.42-5.33-5.34zM8 14A6 6 0 1 0 8 2a6 6 0 0 0 0 12z' />
-    </svg>
-  ),
-
-  delete: (
-    <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' width='13' height='13'>
-      <path d='M10 8.586L2.929 1.515 1.515 2.929 8.586 10l-7.071 7.071 1.414 1.414L10 11.414l7.071 7.071 1.414-1.414L11.414 10l7.071-7.071-1.414-1.414L10 8.586z' />
-    </svg>
-  ),
-};
-
 const listenerOptions = supportsPassiveEvents ? { passive: true } : false;
 
 class LanguageDropdownMenu extends React.PureComponent {
@@ -242,7 +227,7 @@ class LanguageDropdownMenu extends React.PureComponent {
           <div className={`language-dropdown__dropdown ${placement}`} style={{ ...style, opacity: opacity, transform: mounted ? `scale(${scaleX}, ${scaleY})` : null }} ref={this.setRef}>
             <div className='emoji-mart-search'>
               <input type='search' value={searchValue} onChange={this.handleSearchChange} onKeyDown={this.handleSearchKeyDown} placeholder={intl.formatMessage(messages.search)} autoFocus />
-              <button className='emoji-mart-search-icon' disabled={!isSearching} aria-label={intl.formatMessage(messages.clear)} onClick={this.handleClear}>{!isSearching ? icons.loupe : icons.delete}</button>
+              <button className='emoji-mart-search-icon' disabled={!isSearching} aria-label={intl.formatMessage(messages.clear)} onClick={this.handleClear}>{!isSearching ? loupeIcon : deleteIcon}</button>
             </div>
 
             <div className='language-dropdown__dropdown__results emoji-mart-scroll' role='listbox' ref={this.setListRef}>
diff --git a/app/javascript/mastodon/features/filters/added_to_filter.js b/app/javascript/mastodon/features/filters/added_to_filter.js
new file mode 100644
index 000000000..3785eb3c5
--- /dev/null
+++ b/app/javascript/mastodon/features/filters/added_to_filter.js
@@ -0,0 +1,102 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import ImmutablePropTypes from 'react-immutable-proptypes';
+import { FormattedMessage } from 'react-intl';
+import { toServerSideType } from 'mastodon/utils/filters';
+import Button from 'mastodon/components/button';
+import { connect } from 'react-redux';
+
+const mapStateToProps = (state, { filterId }) => ({
+  filter: state.getIn(['filters', filterId]),
+});
+
+export default @connect(mapStateToProps)
+class AddedToFilter extends React.PureComponent {
+
+  static propTypes = {
+    onClose: PropTypes.func.isRequired,
+    contextType: PropTypes.string,
+    filter: ImmutablePropTypes.map.isRequired,
+    dispatch: PropTypes.func.isRequired,
+  };
+
+  handleCloseClick = () => {
+    const { onClose } = this.props;
+    onClose();
+  };
+
+  render () {
+    const { filter, contextType } = this.props;
+
+    let expiredMessage = null;
+    if (filter.get('expires_at') && filter.get('expires_at') < new Date()) {
+      expiredMessage = (
+        <React.Fragment>
+          <h4 className='report-dialog-modal__subtitle'><FormattedMessage id='filter_modal.added.expired_title' defaultMessage='Expired filter!' /></h4>
+          <p className='report-dialog-modal__lead'>
+            <FormattedMessage
+              id='filter_modal.added.expired_explanation'
+              defaultMessage='This filter category has expired, you will need to change the expiration date for it to apply.'
+            />
+          </p>
+        </React.Fragment>
+      );
+    }
+
+    let contextMismatchMessage = null;
+    if (contextType && !filter.get('context').includes(toServerSideType(contextType))) {
+      contextMismatchMessage = (
+        <React.Fragment>
+          <h4 className='report-dialog-modal__subtitle'><FormattedMessage id='filter_modal.added.context_mismatch_title' defaultMessage='Context mismatch!' /></h4>
+          <p className='report-dialog-modal__lead'>
+            <FormattedMessage
+              id='filter_modal.added.context_mismatch_explanation'
+              defaultMessage='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.'
+            />
+          </p>
+        </React.Fragment>
+      );
+    }
+
+    const settings_link = (
+      <a href={`/filters/${filter.get('id')}/edit`}>
+        <FormattedMessage
+          id='filter_modal.added.settings_link'
+          defaultMessage='settings page'
+        />
+      </a>
+    );
+
+    return (
+      <React.Fragment>
+        <h3 className='report-dialog-modal__title'><FormattedMessage id='filter_modal.added.title' defaultMessage='Filter added!' /></h3>
+        <p className='report-dialog-modal__lead'>
+          <FormattedMessage
+            id='filter_modal.added.short_explanation'
+            defaultMessage='This post has been added to the following filter category: {title}.'
+            values={{ title: filter.get('title') }}
+          />
+        </p>
+
+        {expiredMessage}
+        {contextMismatchMessage}
+
+        <h4 className='report-dialog-modal__subtitle'><FormattedMessage id='filter_modal.added.review_and_configure_title' defaultMessage='Filter settings' /></h4>
+        <p className='report-dialog-modal__lead'>
+          <FormattedMessage
+            id='filter_modal.added.review_and_configure'
+            defaultMessage='To review and further configure this filter category, go to the {settings_link}.'
+            values={{ settings_link }}
+          />
+        </p>
+
+        <div className='flex-spacer' />
+
+        <div className='report-dialog-modal__actions'>
+          <Button onClick={this.handleCloseClick}><FormattedMessage id='report.close' defaultMessage='Done' /></Button>
+        </div>
+      </React.Fragment>
+    );
+  }
+
+}
diff --git a/app/javascript/mastodon/features/filters/select_filter.js b/app/javascript/mastodon/features/filters/select_filter.js
new file mode 100644
index 000000000..b5b354529
--- /dev/null
+++ b/app/javascript/mastodon/features/filters/select_filter.js
@@ -0,0 +1,192 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { connect } from 'react-redux';
+import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
+import { toServerSideType } from 'mastodon/utils/filters';
+import { loupeIcon, deleteIcon } from 'mastodon/utils/icons';
+import Icon from 'mastodon/components/icon';
+import fuzzysort from 'fuzzysort';
+
+const messages = defineMessages({
+  search: { id: 'filter_modal.select_filter.search', defaultMessage: 'Search or create' },
+  clear: { id: 'emoji_button.clear', defaultMessage: 'Clear' },
+});
+
+const mapStateToProps = (state, { contextType }) => ({
+  filters: Array.from(state.get('filters').values()).map((filter) => [
+    filter.get('id'),
+    filter.get('title'),
+    filter.get('keywords')?.map((keyword) => keyword.get('keyword')).join('\n'),
+    filter.get('expires_at') && filter.get('expires_at') < new Date(),
+    contextType && !filter.get('context').includes(toServerSideType(contextType)),
+  ]),
+});
+
+export default @connect(mapStateToProps)
+@injectIntl
+class SelectFilter extends React.PureComponent {
+
+  static propTypes = {
+    onSelectFilter: PropTypes.func.isRequired,
+    onNewFilter: PropTypes.func.isRequired,
+    filters: PropTypes.arrayOf(PropTypes.arrayOf(PropTypes.object)),
+    intl: PropTypes.object.isRequired,
+  };
+
+  state = {
+    searchValue: '',
+  };
+
+  search () {
+    const { filters } = this.props;
+    const { searchValue } = this.state;
+
+    if (searchValue === '') {
+      return filters;
+    }
+
+    return fuzzysort.go(searchValue, filters, {
+      keys: ['1', '2'],
+      limit: 5,
+      threshold: -10000,
+    }).map(result => result.obj);
+  }
+
+  renderItem = filter => {
+    let warning = null;
+    if (filter[3] || filter[4]) {
+      warning = (
+        <span className='language-dropdown__dropdown__results__item__common-name'>
+          (
+          {filter[3] && <FormattedMessage id='filter_modal.select_filter.expired' defaultMessage='expired' />}
+          {filter[3] && filter[4] && ', '}
+          {filter[4] && <FormattedMessage id='filter_modal.select_filter.context_mismatch' defaultMessage='does not apply to this context' />}
+          )
+        </span>
+      );
+    }
+
+    return (
+      <div key={filter[0]} role='button' tabIndex='0' data-index={filter[0]} className='language-dropdown__dropdown__results__item' onClick={this.handleItemClick} onKeyDown={this.handleKeyDown}>
+        <span className='language-dropdown__dropdown__results__item__native-name'>{filter[1]}</span> {warning}
+      </div>
+    );
+  }
+
+  renderCreateNew (name) {
+    return (
+      <div key='add-new-filter' role='button' tabIndex='0' className='language-dropdown__dropdown__results__item' onClick={this.handleNewFilterClick} onKeyDown={this.handleKeyDown}>
+        <Icon id='plus' fixedWidth /> <FormattedMessage id='filter_modal.select_filter.prompt_new' defaultMessage='New category: {name}' values={{ name }} />
+      </div>
+    );
+  }
+
+  handleSearchChange = ({ target }) => {
+    this.setState({ searchValue: target.value });
+  }
+
+  setListRef = c => {
+    this.listNode = c;
+  }
+
+  handleKeyDown = e => {
+    const index = Array.from(this.listNode.childNodes).findIndex(node => node === e.currentTarget);
+
+    let element = null;
+
+    switch(e.key) {
+    case ' ':
+    case 'Enter':
+      e.currentTarget.click();
+      break;
+    case 'ArrowDown':
+      element = this.listNode.childNodes[index + 1] || this.listNode.firstChild;
+      break;
+    case 'ArrowUp':
+      element = this.listNode.childNodes[index - 1] || this.listNode.lastChild;
+      break;
+    case 'Tab':
+      if (e.shiftKey) {
+        element = this.listNode.childNodes[index - 1] || this.listNode.lastChild;
+      } else {
+        element = this.listNode.childNodes[index + 1] || this.listNode.firstChild;
+      }
+      break;
+    case 'Home':
+      element = this.listNode.firstChild;
+      break;
+    case 'End':
+      element = this.listNode.lastChild;
+      break;
+    }
+
+    if (element) {
+      element.focus();
+      e.preventDefault();
+      e.stopPropagation();
+    }
+  }
+
+  handleSearchKeyDown = e => {
+    let element = null;
+
+    switch(e.key) {
+    case 'Tab':
+    case 'ArrowDown':
+      element = this.listNode.firstChild;
+
+      if (element) {
+        element.focus();
+        e.preventDefault();
+        e.stopPropagation();
+      }
+
+      break;
+    }
+  }
+
+  handleClear = () => {
+    this.setState({ searchValue: '' });
+  }
+
+  handleItemClick = e => {
+    const value = e.currentTarget.getAttribute('data-index');
+
+    e.preventDefault();
+
+    this.props.onSelectFilter(value);
+  }
+
+  handleNewFilterClick = e => {
+    e.preventDefault();
+
+    this.props.onNewFilter(this.state.searchValue);
+  };
+
+  render () {
+    const { intl } = this.props;
+
+    const { searchValue } = this.state;
+    const isSearching = searchValue !== '';
+    const results = this.search();
+
+    return (
+      <React.Fragment>
+        <h3 className='report-dialog-modal__title'><FormattedMessage id='filter_modal.select_filter.title' defaultMessage='Filter this post' /></h3>
+        <p className='report-dialog-modal__lead'><FormattedMessage id='filter_modal.select_filter.subtitle' defaultMessage='Use an existing category or create a new one' /></p>
+
+        <div className='emoji-mart-search'>
+          <input type='search' value={searchValue} onChange={this.handleSearchChange} onKeyDown={this.handleSearchKeyDown} placeholder={intl.formatMessage(messages.search)} autoFocus />
+          <button className='emoji-mart-search-icon' disabled={!isSearching} aria-label={intl.formatMessage(messages.clear)} onClick={this.handleClear}>{!isSearching ? loupeIcon : deleteIcon}</button>
+        </div>
+
+        <div className='language-dropdown__dropdown__results emoji-mart-scroll' role='listbox' ref={this.setListRef}>
+          {results.map(this.renderItem)}
+          {isSearching && this.renderCreateNew(searchValue) }
+        </div>
+
+      </React.Fragment>
+    );
+  }
+
+}
diff --git a/app/javascript/mastodon/features/status/components/detailed_status.js b/app/javascript/mastodon/features/status/components/detailed_status.js
index 13bce1b83..5c43c2038 100644
--- a/app/javascript/mastodon/features/status/components/detailed_status.js
+++ b/app/javascript/mastodon/features/status/components/detailed_status.js
@@ -138,7 +138,11 @@ class DetailedStatus extends ImmutablePureComponent {
             backgroundColor={attachment.getIn(['meta', 'colors', 'background'])}
             foregroundColor={attachment.getIn(['meta', 'colors', 'foreground'])}
             accentColor={attachment.getIn(['meta', 'colors', 'accent'])}
+            sensitive={status.get('sensitive')}
+            visible={this.props.showMedia}
+            blurhash={attachment.get('blurhash')}
             height={150}
+            onToggleVisibility={this.props.onToggleMediaVisibility}
           />
         );
       } else if (status.getIn(['media_attachments', 0, 'type']) === 'video') {
diff --git a/app/javascript/mastodon/features/ui/components/filter_modal.js b/app/javascript/mastodon/features/ui/components/filter_modal.js
new file mode 100644
index 000000000..376db961d
--- /dev/null
+++ b/app/javascript/mastodon/features/ui/components/filter_modal.js
@@ -0,0 +1,134 @@
+import React from 'react';
+import { connect } from 'react-redux';
+import { fetchStatus } from 'mastodon/actions/statuses';
+import { fetchFilters, createFilter, createFilterStatus } from 'mastodon/actions/filters';
+import PropTypes from 'prop-types';
+import { defineMessages, FormattedMessage, injectIntl } from 'react-intl';
+import ImmutablePureComponent from 'react-immutable-pure-component';
+import IconButton from 'mastodon/components/icon_button';
+import SelectFilter from 'mastodon/features/filters/select_filter';
+import AddedToFilter from 'mastodon/features/filters/added_to_filter';
+
+const messages = defineMessages({
+  close: { id: 'lightbox.close', defaultMessage: 'Close' },
+});
+
+export default @connect(undefined)
+@injectIntl
+class FilterModal extends ImmutablePureComponent {
+
+  static propTypes = {
+    statusId: PropTypes.string.isRequired,
+    contextType: PropTypes.string,
+    dispatch: PropTypes.func.isRequired,
+    intl: PropTypes.object.isRequired,
+  };
+
+  state = {
+    step: 'select',
+    filterId: null,
+    isSubmitting: false,
+    isSubmitted: false,
+  };
+
+  handleNewFilterSuccess = (result) => {
+    this.handleSelectFilter(result.id);
+  };
+
+  handleSuccess = () => {
+    const { dispatch, statusId } = this.props;
+    dispatch(fetchStatus(statusId, true));
+    this.setState({ isSubmitting: false, isSubmitted: true, step: 'submitted' });
+  };
+
+  handleFail = () => {
+    this.setState({ isSubmitting: false });
+  };
+
+  handleNextStep = step => {
+    this.setState({ step });
+  };
+
+  handleSelectFilter = (filterId) => {
+    const { dispatch, statusId } = this.props;
+
+    this.setState({ isSubmitting: true, filterId });
+
+    dispatch(createFilterStatus({
+      filter_id: filterId,
+      status_id: statusId,
+    }, this.handleSuccess, this.handleFail));
+  };
+
+  handleNewFilter = (title) => {
+    const { dispatch } = this.props;
+
+    this.setState({ isSubmitting: true });
+
+    dispatch(createFilter({
+      title,
+      context: ['home', 'notifications', 'public', 'thread', 'account'],
+      action: 'warn',
+    }, this.handleNewFilterSuccess, this.handleFail));
+  };
+
+  componentDidMount () {
+    const { dispatch } = this.props;
+
+    dispatch(fetchFilters());
+  }
+
+  render () {
+    const {
+      intl,
+      statusId,
+      contextType,
+      onClose,
+    } = this.props;
+
+    const {
+      step,
+      filterId,
+    } = this.state;
+
+    let stepComponent;
+
+    switch(step) {
+    case 'select':
+      stepComponent = (
+        <SelectFilter
+          contextType={contextType}
+          onSelectFilter={this.handleSelectFilter}
+          onNewFilter={this.handleNewFilter}
+        />
+      );
+      break;
+    case 'create':
+      stepComponent = null;
+      break;
+    case 'submitted':
+      stepComponent = (
+        <AddedToFilter
+          contextType={contextType}
+          filterId={filterId}
+          statusId={statusId}
+          onClose={onClose}
+        />
+      );
+    }
+
+    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='filter_modal.title.status' defaultMessage='Filter a post' />
+        </div>
+
+        <div className='report-dialog-modal__container'>
+          {stepComponent}
+        </div>
+      </div>
+    );
+  }
+
+}
diff --git a/app/javascript/mastodon/features/ui/components/modal_root.js b/app/javascript/mastodon/features/ui/components/modal_root.js
index 3fc235849..b2c30e079 100644
--- a/app/javascript/mastodon/features/ui/components/modal_root.js
+++ b/app/javascript/mastodon/features/ui/components/modal_root.js
@@ -20,6 +20,7 @@ import {
   ListEditor,
   ListAdder,
   CompareHistoryModal,
+  FilterModal,
 } from 'mastodon/features/ui/util/async-components';
 
 const MODAL_COMPONENTS = {
@@ -37,6 +38,7 @@ const MODAL_COMPONENTS = {
   'FOCAL_POINT': () => Promise.resolve({ default: FocalPointModal }),
   'LIST_ADDER': ListAdder,
   'COMPARE_HISTORY': CompareHistoryModal,
+  'FILTER': FilterModal,
 };
 
 export default class ModalRoot extends React.PureComponent {
diff --git a/app/javascript/mastodon/features/ui/util/async-components.js b/app/javascript/mastodon/features/ui/util/async-components.js
index 92c683e2f..29b06206a 100644
--- a/app/javascript/mastodon/features/ui/util/async-components.js
+++ b/app/javascript/mastodon/features/ui/util/async-components.js
@@ -161,3 +161,7 @@ export function CompareHistoryModal () {
 export function Explore () {
   return import(/* webpackChunkName: "features/explore" */'../../explore');
 }
+
+export function FilterModal () {
+  return import(/*webpackChunkName: "modals/filter_modal" */'../components/filter_modal');
+}
diff --git a/app/javascript/mastodon/locales/af.json b/app/javascript/mastodon/locales/af.json
index 942c8191f..86d590654 100644
--- a/app/javascript/mastodon/locales/af.json
+++ b/app/javascript/mastodon/locales/af.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Oops!",
   "announcement.announcement": "Aankondiging",
   "attachments_list.unprocessed": "(unprocessed)",
+  "audio.hide": "Hide audio",
   "autosuggest_hashtag.per_week": "{count} per week",
   "boost_modal.combo": "You can press {combo} to skip this next time",
   "bundle_column_error.body": "Something went wrong while loading this component.",
@@ -196,6 +197,22 @@
   "explore.trending_links": "News",
   "explore.trending_statuses": "Posts",
   "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",
   "follow_recommendations.done": "Done",
   "follow_recommendations.heading": "Follow people you'd like to see posts from! Here are some suggestions.",
   "follow_recommendations.lead": "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!",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "Edited {count, plural, one {{count} time} other {{count} times}}",
   "status.embed": "Embed",
   "status.favourite": "Favourite",
+  "status.filter": "Filter this post",
   "status.filtered": "Filtered",
   "status.hide": "Hide toot",
   "status.history.created": "{name} created {date}",
diff --git a/app/javascript/mastodon/locales/ar.json b/app/javascript/mastodon/locales/ar.json
index 13d6e4e7a..220aa14ee 100644
--- a/app/javascript/mastodon/locales/ar.json
+++ b/app/javascript/mastodon/locales/ar.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "المعذرة!",
   "announcement.announcement": "إعلان",
   "attachments_list.unprocessed": "(غير معالَج)",
+  "audio.hide": "Hide audio",
   "autosuggest_hashtag.per_week": "{count} في الأسبوع",
   "boost_modal.combo": "يُمكنك الضّغط على {combo} لتخطي هذا في المرة المُقبلة",
   "bundle_column_error.body": "لقد حدث خطأ ما أثناء تحميل هذا العنصر.",
@@ -196,6 +197,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",
   "follow_recommendations.done": "تم",
   "follow_recommendations.heading": "تابع الأشخاص الذين ترغب في رؤية منشوراتهم! إليك بعض الاقتراحات.",
   "follow_recommendations.lead": "ستظهر منشورات الأشخاص الذين تُتابعتهم بترتيب تسلسلي زمني على صفحتك الرئيسية. لا تخف إذا ارتكبت أي أخطاء، تستطيع إلغاء متابعة أي شخص في أي وقت تريد!",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "عُدّل {count, plural, zero {} one {{count} مرة} two {{count} مرتين} few {{count} مرات} many {{count} مرات} other {{count} مرة}}",
   "status.embed": "إدماج",
   "status.favourite": "أضف إلى المفضلة",
+  "status.filter": "Filter this post",
   "status.filtered": "مُصفّى",
   "status.hide": "Hide toot",
   "status.history.created": "أنشأه {name} {date}",
diff --git a/app/javascript/mastodon/locales/ast.json b/app/javascript/mastodon/locales/ast.json
index 034885e81..dba626299 100644
--- a/app/javascript/mastodon/locales/ast.json
+++ b/app/javascript/mastodon/locales/ast.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "¡Meca!",
   "announcement.announcement": "Anunciu",
   "attachments_list.unprocessed": "(ensin procesar)",
+  "audio.hide": "Hide audio",
   "autosuggest_hashtag.per_week": "{count} per selmana",
   "boost_modal.combo": "Pues primir {combo} pa saltar esto la próxima vegada",
   "bundle_column_error.body": "Asocedió daqué malo mentanto se cargaba esti componente.",
@@ -196,6 +197,22 @@
   "explore.trending_links": "Noticies",
   "explore.trending_statuses": "Posts",
   "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",
   "follow_recommendations.done": "Done",
   "follow_recommendations.heading": "Follow people you'd like to see posts from! Here are some suggestions.",
   "follow_recommendations.lead": "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!",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "Edited {count, plural, one {{count} time} other {{count} times}}",
   "status.embed": "Empotrar",
   "status.favourite": "Favourite",
+  "status.filter": "Filter this post",
   "status.filtered": "Filtered",
   "status.hide": "Hide toot",
   "status.history.created": "{name} created {date}",
diff --git a/app/javascript/mastodon/locales/bg.json b/app/javascript/mastodon/locales/bg.json
index 89f2efc85..4ded919e0 100644
--- a/app/javascript/mastodon/locales/bg.json
+++ b/app/javascript/mastodon/locales/bg.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Опаа!",
   "announcement.announcement": "Оповестяване",
   "attachments_list.unprocessed": "(unprocessed)",
+  "audio.hide": "Hide audio",
   "autosuggest_hashtag.per_week": "{count} на седмица",
   "boost_modal.combo": "Можете да натиснете {combo}, за да пропуснете това следващия път",
   "bundle_column_error.body": "Нещо се обърка при зареждането на този компонент.",
@@ -196,6 +197,22 @@
   "explore.trending_links": "News",
   "explore.trending_statuses": "Posts",
   "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",
   "follow_recommendations.done": "Done",
   "follow_recommendations.heading": "Следвайте хора, които харесвате, за да виждате техните съобщения! Ето някои предложения.",
   "follow_recommendations.lead": "Съобщения от хора, които следвате, ще се показват в хронологичен ред на вашата главна страница. Не се страхувайте, че ще сгрешите, по всяко време много лесно можете да спрете да ги следвате!",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "Edited {count, plural, one {{count} time} other {{count} times}}",
   "status.embed": "Вграждане",
   "status.favourite": "Предпочитани",
+  "status.filter": "Filter this post",
   "status.filtered": "Филтрирано",
   "status.hide": "Hide toot",
   "status.history.created": "{name} created {date}",
diff --git a/app/javascript/mastodon/locales/bn.json b/app/javascript/mastodon/locales/bn.json
index 852c4c720..94b0477b5 100644
--- a/app/javascript/mastodon/locales/bn.json
+++ b/app/javascript/mastodon/locales/bn.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "ওহো!",
   "announcement.announcement": "ঘোষণা",
   "attachments_list.unprocessed": "(unprocessed)",
+  "audio.hide": "Hide audio",
   "autosuggest_hashtag.per_week": "প্রতি সপ্তাহে {count}",
   "boost_modal.combo": "পরেরবার আপনি {combo} টিপলে এটি আর আসবে না",
   "bundle_column_error.body": "এই অংশটি দেখতে যেয়ে কোনো সমস্যা হয়েছে।.",
@@ -196,6 +197,22 @@
   "explore.trending_links": "News",
   "explore.trending_statuses": "Posts",
   "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",
   "follow_recommendations.done": "সম্পন্ন",
   "follow_recommendations.heading": "Follow people you'd like to see posts from! Here are some suggestions.",
   "follow_recommendations.lead": "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!",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "Edited {count, plural, one {{count} time} other {{count} times}}",
   "status.embed": "এমবেড করতে",
   "status.favourite": "পছন্দের করতে",
+  "status.filter": "Filter this post",
   "status.filtered": "ছাঁকনিদিত",
   "status.hide": "Hide toot",
   "status.history.created": "{name} created {date}",
diff --git a/app/javascript/mastodon/locales/br.json b/app/javascript/mastodon/locales/br.json
index ac504c49c..50837691f 100644
--- a/app/javascript/mastodon/locales/br.json
+++ b/app/javascript/mastodon/locales/br.json
@@ -18,7 +18,7 @@
   "account.followers": "Heulier·ezed·ien",
   "account.followers.empty": "Den na heul an implijer-mañ c'hoazh.",
   "account.followers_counter": "{count, plural, other{{counter} Heulier}}",
-  "account.following": "Following",
+  "account.following": "O heuliañ",
   "account.following_counter": "{count, plural, other {{counter} Heuliañ}}",
   "account.follows.empty": "An implijer·ez-mañ na heul den ebet.",
   "account.follows_you": "Ho heul",
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Hopala!",
   "announcement.announcement": "Kemenn",
   "attachments_list.unprocessed": "(ket meret)",
+  "audio.hide": "Hide audio",
   "autosuggest_hashtag.per_week": "{count} bep sizhun",
   "boost_modal.combo": "Ar wezh kentañ e c'halliot gwaskañ war {combo} evit tremen hebiou",
   "bundle_column_error.body": "Degouezhet ez eus bet ur fazi en ur gargañ an elfenn-mañ.",
@@ -108,7 +109,7 @@
   "compose_form.poll.switch_to_single": "Kemmañ ar sontadeg evit aotren un dibab hepken",
   "compose_form.publish": "Embann",
   "compose_form.publish_loud": "{publish} !",
-  "compose_form.save_changes": "Save changes",
+  "compose_form.save_changes": "Enrollañ ar cheñchamantoù",
   "compose_form.sensitive.hide": "Merkañ ar media evel kizidik",
   "compose_form.sensitive.marked": "Merket eo ar media evel kizidik",
   "compose_form.sensitive.unmarked": "N'eo ket merket ar media evel kizidik",
@@ -149,7 +150,7 @@
   "embed.instructions": "Enkorfit ar statud war ho lec'hienn en ur eilañ ar c'hod dindan.",
   "embed.preview": "Setu penaos e vo diskouezet:",
   "emoji_button.activity": "Obererezh",
-  "emoji_button.clear": "Clear",
+  "emoji_button.clear": "Diverkañ",
   "emoji_button.custom": "Kempennet",
   "emoji_button.flags": "Bannieloù",
   "emoji_button.food": "Boued hag Evaj",
@@ -169,7 +170,7 @@
   "empty_column.blocks": "N'eus ket bet berzet implijer·ez ganeoc'h c'hoazh.",
   "empty_column.bookmarked_statuses": "N'ho peus toud ebet enrollet en ho sinedoù c'hoazh. Pa vo ouzhpennet unan ganeoc'h e teuio war wel amañ.",
   "empty_column.community": "Goulo eo ar red-amzer lec'hel. Skrivit'ta un dra evit lakaat tan dezhi !",
-  "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": "N'ho peus kemennad prevez ebet c'hoazh. Pa vo resevet pe kaset unan ganeoc'h e teuio war wel amañ.",
   "empty_column.domain_blocks": "N'eus domani kuzh ebet c'hoazh.",
   "empty_column.explore_statuses": "Nothing is trending right now. Check back later!",
   "empty_column.favourited_statuses": "N'ho peus toud muiañ-karet ebet c'hoazh. Pa vo lakaet unan ganeoc'h e vo diskouezet amañ.",
@@ -196,6 +197,22 @@
   "explore.trending_links": "Keleier",
   "explore.trending_statuses": "Posts",
   "explore.trending_tags": "Gerioù-klik",
+  "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",
   "follow_recommendations.done": "Graet",
   "follow_recommendations.heading": "Heuliit tud e plijfe deoc'h lenn toudoù! Setu un tamm alioù.",
   "follow_recommendations.lead": "Toudoù eus tud heuliet ganeoc'h a zeuio war wel en un urzh amzeroniezhel war ho red degemer. N'ho peus ket aon ober fazioù, gallout a rit paouez heuliañ tud ken aes n'eus forzh pegoulz!",
@@ -220,9 +237,9 @@
   "hashtag.column_settings.tag_mode.any": "Unan e mesk anezho",
   "hashtag.column_settings.tag_mode.none": "Hini ebet anezho",
   "hashtag.column_settings.tag_toggle": "Endelc'her gerioù-alc'hwez ouzhpenn evit ar bannad-mañ",
-  "hashtag.follow": "Follow hashtag",
+  "hashtag.follow": "Heuliañ ar ger-klik",
   "hashtag.total_volume": "Total volume in the last {days, plural, one {day} other {{days} days}}",
-  "hashtag.unfollow": "Unfollow hashtag",
+  "hashtag.unfollow": "Paouez heuliañ ar ger-klik",
   "home.column_settings.basic": "Diazez",
   "home.column_settings.show_reblogs": "Diskouez ar skignadennoù",
   "home.column_settings.show_replies": "Diskouez ar respontoù",
@@ -270,8 +287,8 @@
   "lightbox.expand": "Ledanaat boest hewel ar skeudenn",
   "lightbox.next": "Da-heul",
   "lightbox.previous": "A-raok",
-  "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": "Diskouez an aelad memes tra",
+  "limited_account_hint.title": "Kuzhet eo bet an aelad-mañ gant habaskerien·ezed ho servijer.",
   "lists.account.add": "Ouzhpennañ d'al listenn",
   "lists.account.remove": "Lemel kuit eus al listenn",
   "lists.delete": "Dilemel al listenn",
@@ -317,8 +334,8 @@
   "navigation_bar.preferences": "Gwellvezioù",
   "navigation_bar.public_timeline": "Red-amzer kevreet",
   "navigation_bar.security": "Diogelroez",
-  "notification.admin.report": "{name} reported {target}",
-  "notification.admin.sign_up": "{name} signed up",
+  "notification.admin.report": "Disklêriet eo bet {target} gant {name}",
+  "notification.admin.sign_up": "{name} en·he deus lakaet e·hec'h anv",
   "notification.favourite": "{name} en/he deus lakaet ho toud en e/he muiañ-karet",
   "notification.follow": "heuliañ a ra {name} ac'hanoc'h",
   "notification.follow_request": "{name} en/he deus goulennet da heuliañ ac'hanoc'h",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "Edited {count, plural, one {{count} time} other {{count} times}}",
   "status.embed": "Enframmañ",
   "status.favourite": "Muiañ-karet",
+  "status.filter": "Filter this post",
   "status.filtered": "Silet",
   "status.hide": "Hide toot",
   "status.history.created": "{name} created {date}",
diff --git a/app/javascript/mastodon/locales/ca.json b/app/javascript/mastodon/locales/ca.json
index bc6029fe0..f67a0f3fc 100644
--- a/app/javascript/mastodon/locales/ca.json
+++ b/app/javascript/mastodon/locales/ca.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Vaja!",
   "announcement.announcement": "Anunci",
   "attachments_list.unprocessed": "(sense processar)",
+  "audio.hide": "Amaga l'àudio",
   "autosuggest_hashtag.per_week": "{count} per setmana",
   "boost_modal.combo": "Pots prémer {combo} per evitar-ho el pròxim cop",
   "bundle_column_error.body": "S'ha produït un error en carregar aquest component.",
@@ -196,6 +197,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",
   "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!",
@@ -220,9 +237,9 @@
   "hashtag.column_settings.tag_mode.any": "Qualsevol d’aquests",
   "hashtag.column_settings.tag_mode.none": "Cap d’aquests",
   "hashtag.column_settings.tag_toggle": "Inclou etiquetes addicionals per a aquesta columna",
-  "hashtag.follow": "Follow hashtag",
+  "hashtag.follow": "Segueix etiqueta",
   "hashtag.total_volume": "Total volume in the last {days, plural, one {day} other {{days} days}}",
-  "hashtag.unfollow": "Unfollow hashtag",
+  "hashtag.unfollow": "Deixa de seguir etiqueta",
   "home.column_settings.basic": "Bàsic",
   "home.column_settings.show_reblogs": "Mostra els impulsos",
   "home.column_settings.show_replies": "Mostra les respostes",
@@ -470,6 +487,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.filtered": "Filtrat",
   "status.hide": "Amaga publicació",
   "status.history.created": "{name} ha creat {date}",
diff --git a/app/javascript/mastodon/locales/ckb.json b/app/javascript/mastodon/locales/ckb.json
index 80c5089ae..19d9550d0 100644
--- a/app/javascript/mastodon/locales/ckb.json
+++ b/app/javascript/mastodon/locales/ckb.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "تەححح!",
   "announcement.announcement": "بانگەواز",
   "attachments_list.unprocessed": "(unprocessed)",
+  "audio.hide": "Hide audio",
   "autosuggest_hashtag.per_week": "{count} هەرهەفتە",
   "boost_modal.combo": "دەتوانیت دەست بنێی بە سەر {combo} بۆ بازدان لە جاری داهاتوو",
   "bundle_column_error.body": "هەڵەیەک ڕوویدا لەکاتی بارکردنی ئەم پێکهاتەیە.",
@@ -196,6 +197,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",
   "follow_recommendations.done": "تەواو",
   "follow_recommendations.heading": "شوێن ئەو کەسانە بکەون کە دەتەوێت پۆستەکان ببینیت لە! لێرەدا چەند پێشنیارێک هەیە.",
   "follow_recommendations.lead": "بابەتەکانی ئەو کەسانەی کە بەدوایدا دەگەڕێیت بە فەرمانی کرۆنۆلۆجی لە خواردنەکانی ماڵەکەت دەردەکەون. مەترسە لە هەڵەکردن، دەتوانیت بە ئاسانی خەڵک هەڵبکەیت هەر کاتێک!",
@@ -470,6 +487,7 @@
   "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}",
diff --git a/app/javascript/mastodon/locales/co.json b/app/javascript/mastodon/locales/co.json
index 2dbc256ee..5ca3f4a4b 100644
--- a/app/javascript/mastodon/locales/co.json
+++ b/app/javascript/mastodon/locales/co.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Uups!",
   "announcement.announcement": "Annunziu",
   "attachments_list.unprocessed": "(micca trattata)",
+  "audio.hide": "Hide audio",
   "autosuggest_hashtag.per_week": "{count} per settimana",
   "boost_modal.combo": "Pudete appughjà nant'à {combo} per saltà quessa a prussima volta",
   "bundle_column_error.body": "C'hè statu un prublemu caricandu st'elementu.",
@@ -196,6 +197,22 @@
   "explore.trending_links": "News",
   "explore.trending_statuses": "Posts",
   "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",
   "follow_recommendations.done": "Fatta",
   "follow_recommendations.heading": "Siguitate a ghjente da quelli vulete vede i missaghji! Eccu qualchì ricumandazione.",
   "follow_recommendations.lead": "I missaghji da a ghjente che voi siguitate figureranu in ordine crunulogicu nant'a vostra pagina d'accolta. Ùn timite micca di fà un sbagliu, pudete sempre disabbunavvi d'un contu à ogni mumentu!",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "Edited {count, plural, one {{count} time} other {{count} times}}",
   "status.embed": "Integrà",
   "status.favourite": "Aghjunghje à i favuriti",
+  "status.filter": "Filter this post",
   "status.filtered": "Filtratu",
   "status.hide": "Hide toot",
   "status.history.created": "{name} created {date}",
diff --git a/app/javascript/mastodon/locales/cs.json b/app/javascript/mastodon/locales/cs.json
index 2f667eae6..ef1a13d8f 100644
--- a/app/javascript/mastodon/locales/cs.json
+++ b/app/javascript/mastodon/locales/cs.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Jejda!",
   "announcement.announcement": "Oznámení",
   "attachments_list.unprocessed": "(nezpracováno)",
+  "audio.hide": "Hide audio",
   "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.",
@@ -196,6 +197,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",
   "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!",
@@ -470,6 +487,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.filtered": "Filtrováno",
   "status.hide": "Skrýt příspěvek",
   "status.history.created": "Uživatel {name} vytvořil {date}",
diff --git a/app/javascript/mastodon/locales/cy.json b/app/javascript/mastodon/locales/cy.json
index 228fd280f..cb1c90d69 100644
--- a/app/javascript/mastodon/locales/cy.json
+++ b/app/javascript/mastodon/locales/cy.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Wps!",
   "announcement.announcement": "Cyhoeddiad",
   "attachments_list.unprocessed": "(heb eu prosesu)",
+  "audio.hide": "Hide audio",
   "autosuggest_hashtag.per_week": "{count} yr wythnos",
   "boost_modal.combo": "Mae modd gwasgu {combo} er mwyn sgipio hyn tro nesa",
   "bundle_column_error.body": "Aeth rhywbeth o'i le tra'n llwytho'r elfen hon.",
@@ -196,6 +197,22 @@
   "explore.trending_links": "Newyddion",
   "explore.trending_statuses": "Postiadau",
   "explore.trending_tags": "Hashnodau",
+  "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",
   "follow_recommendations.done": "Wedi gorffen",
   "follow_recommendations.heading": "Dilynwch y bobl yr hoffech chi weld eu postiadau! Dyma ambell i awgrymiad.",
   "follow_recommendations.lead": "Bydd postiadau gan bobl rydych chi'n eu dilyn yn ymddangos mewn trefn amser ar eich ffrwd cartref. Peidiwch â bod ofn gwneud camgymeriadau, gallwch chi ddad-ddilyn pobl yr un mor hawdd unrhyw bryd!",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "Golygwyd {count, plural, one {unwaith} two {dwywaith} other {{count} gwaith}}",
   "status.embed": "Plannu",
   "status.favourite": "Hoffi",
+  "status.filter": "Filter this post",
   "status.filtered": "Wedi'i hidlo",
   "status.hide": "Hide toot",
   "status.history.created": "{name} greuodd {date}",
diff --git a/app/javascript/mastodon/locales/da.json b/app/javascript/mastodon/locales/da.json
index 0898b9081..8f015b50d 100644
--- a/app/javascript/mastodon/locales/da.json
+++ b/app/javascript/mastodon/locales/da.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Ups!",
   "announcement.announcement": "Bekendtgørelse",
   "attachments_list.unprocessed": "(ubehandlet)",
+  "audio.hide": "Skjul lyd",
   "autosuggest_hashtag.per_week": "{count} pr. uge",
   "boost_modal.combo": "Du kan trykke på {combo} for at overspringe dette næste gang",
   "bundle_column_error.body": "Noget gik galt under indlæsningen af denne komponent.",
@@ -196,6 +197,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",
   "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!",
@@ -220,9 +237,9 @@
   "hashtag.column_settings.tag_mode.any": "Nogle af disse",
   "hashtag.column_settings.tag_mode.none": "Ingen af disse",
   "hashtag.column_settings.tag_toggle": "Inkludér ekstra tags for denne kolonne",
-  "hashtag.follow": "Follow hashtag",
+  "hashtag.follow": "Følg hashtag",
   "hashtag.total_volume": "Samlet volumen {days, plural, one {den seneste dag} other {de seneste {days} dage}}",
-  "hashtag.unfollow": "Unfollow hashtag",
+  "hashtag.unfollow": "Stop med at følge hashtag",
   "home.column_settings.basic": "Grundlæggende",
   "home.column_settings.show_reblogs": "Vis boosts",
   "home.column_settings.show_replies": "Vis svar",
@@ -470,6 +487,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.filtered": "Filtreret",
   "status.hide": "Skjul indlæg",
   "status.history.created": "{name} oprettet {date}",
diff --git a/app/javascript/mastodon/locales/de.json b/app/javascript/mastodon/locales/de.json
index 200b85152..fae92a4b6 100644
--- a/app/javascript/mastodon/locales/de.json
+++ b/app/javascript/mastodon/locales/de.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Hoppla!",
   "announcement.announcement": "Ankündigung",
   "attachments_list.unprocessed": "(ausstehend)",
+  "audio.hide": "Audio stummschalten",
   "autosuggest_hashtag.per_week": "{count} pro Woche",
   "boost_modal.combo": "Drücke {combo}, um dieses Fenster zu überspringen",
   "bundle_column_error.body": "Etwas ist beim Laden schiefgelaufen.",
@@ -196,6 +197,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",
   "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!",
@@ -220,9 +237,9 @@
   "hashtag.column_settings.tag_mode.any": "Eins von diesen",
   "hashtag.column_settings.tag_mode.none": "Keins von diesen",
   "hashtag.column_settings.tag_toggle": "Zusätzliche Hashtags für diese Spalte einfügen",
-  "hashtag.follow": "Follow hashtag",
+  "hashtag.follow": "Hashtag folgen",
   "hashtag.total_volume": "Gesamtes Aufkommen {days, plural, one {am letzten Tag} other {in den letzten {days} Tagen}}",
-  "hashtag.unfollow": "Unfollow hashtag",
+  "hashtag.unfollow": "Hashtag entfolgen",
   "home.column_settings.basic": "Einfach",
   "home.column_settings.show_reblogs": "Geteilte Beiträge anzeigen",
   "home.column_settings.show_replies": "Antworten anzeigen",
@@ -470,6 +487,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.filtered": "Gefiltert",
   "status.hide": "Tröt verbergen",
   "status.history.created": "{name} erstellte {date}",
diff --git a/app/javascript/mastodon/locales/defaultMessages.json b/app/javascript/mastodon/locales/defaultMessages.json
index 0c0c912ce..f397851a8 100644
--- a/app/javascript/mastodon/locales/defaultMessages.json
+++ b/app/javascript/mastodon/locales/defaultMessages.json
@@ -635,6 +635,10 @@
       {
         "defaultMessage": "Unblock @{name}",
         "id": "account.unblock"
+      },
+      {
+        "defaultMessage": "Filter this post",
+        "id": "status.filter"
       }
     ],
     "path": "app/javascript/mastodon/components/status_action_bar.json"
@@ -1078,6 +1082,18 @@
       {
         "defaultMessage": "Download file",
         "id": "video.download"
+      },
+      {
+        "defaultMessage": "Hide audio",
+        "id": "audio.hide"
+      },
+      {
+        "defaultMessage": "Sensitive content",
+        "id": "status.sensitive_warning"
+      },
+      {
+        "defaultMessage": "Media hidden",
+        "id": "status.media_hidden"
       }
     ],
     "path": "app/javascript/mastodon/features/audio/index.json"
@@ -1871,6 +1887,84 @@
   {
     "descriptors": [
       {
+        "defaultMessage": "Expired filter!",
+        "id": "filter_modal.added.expired_title"
+      },
+      {
+        "defaultMessage": "This filter category has expired, you will need to change the expiration date for it to apply.",
+        "id": "filter_modal.added.expired_explanation"
+      },
+      {
+        "defaultMessage": "Context mismatch!",
+        "id": "filter_modal.added.context_mismatch_title"
+      },
+      {
+        "defaultMessage": "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.",
+        "id": "filter_modal.added.context_mismatch_explanation"
+      },
+      {
+        "defaultMessage": "settings page",
+        "id": "filter_modal.added.settings_link"
+      },
+      {
+        "defaultMessage": "Filter added!",
+        "id": "filter_modal.added.title"
+      },
+      {
+        "defaultMessage": "This post has been added to the following filter category: {title}.",
+        "id": "filter_modal.added.short_explanation"
+      },
+      {
+        "defaultMessage": "Filter settings",
+        "id": "filter_modal.added.review_and_configure_title"
+      },
+      {
+        "defaultMessage": "To review and further configure this filter category, go to the {settings_link}.",
+        "id": "filter_modal.added.review_and_configure"
+      },
+      {
+        "defaultMessage": "Done",
+        "id": "report.close"
+      }
+    ],
+    "path": "app/javascript/mastodon/features/filters/added_to_filter.json"
+  },
+  {
+    "descriptors": [
+      {
+        "defaultMessage": "Search or create",
+        "id": "filter_modal.select_filter.search"
+      },
+      {
+        "defaultMessage": "Clear",
+        "id": "emoji_button.clear"
+      },
+      {
+        "defaultMessage": "expired",
+        "id": "filter_modal.select_filter.expired"
+      },
+      {
+        "defaultMessage": "does not apply to this context",
+        "id": "filter_modal.select_filter.context_mismatch"
+      },
+      {
+        "defaultMessage": "New category: {name}",
+        "id": "filter_modal.select_filter.prompt_new"
+      },
+      {
+        "defaultMessage": "Filter this post",
+        "id": "filter_modal.select_filter.title"
+      },
+      {
+        "defaultMessage": "Use an existing category or create a new one",
+        "id": "filter_modal.select_filter.subtitle"
+      }
+    ],
+    "path": "app/javascript/mastodon/features/filters/select_filter.json"
+  },
+  {
+    "descriptors": [
+      {
         "defaultMessage": "Follow",
         "id": "account.follow"
       },
@@ -3416,6 +3510,19 @@
         "id": "lightbox.close"
       },
       {
+        "defaultMessage": "Filter a post",
+        "id": "filter_modal.title.status"
+      }
+    ],
+    "path": "app/javascript/mastodon/features/ui/components/filter_modal.json"
+  },
+  {
+    "descriptors": [
+      {
+        "defaultMessage": "Close",
+        "id": "lightbox.close"
+      },
+      {
         "defaultMessage": "Apply",
         "id": "upload_modal.apply"
       },
diff --git a/app/javascript/mastodon/locales/el.json b/app/javascript/mastodon/locales/el.json
index 3cfce1647..999f67c73 100644
--- a/app/javascript/mastodon/locales/el.json
+++ b/app/javascript/mastodon/locales/el.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Εεπ!",
   "announcement.announcement": "Ανακοίνωση",
   "attachments_list.unprocessed": "(μη επεξεργασμένο)",
+  "audio.hide": "Απόκρυψη αρχείου ήχου",
   "autosuggest_hashtag.per_week": "{count} ανα εβδομάδα",
   "boost_modal.combo": "Μπορείς να πατήσεις {combo} για να το προσπεράσεις αυτό την επόμενη φορά",
   "bundle_column_error.body": "Κάτι πήγε στραβά ενώ φορτωνόταν αυτό το στοιχείο.",
@@ -196,6 +197,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",
   "follow_recommendations.done": "Ολοκληρώθηκε",
   "follow_recommendations.heading": "Ακολουθήστε άτομα από τα οποία θα θέλατε να βλέπετε δημοσιεύσεις! Ορίστε μερικές προτάσεις.",
   "follow_recommendations.lead": "Οι αναρτήσεις των ατόμων που ακολουθείτε θα εμφανίζονται με χρονολογική σειρά στη ροή σας. Μη φοβάστε να κάνετε λάθη, καθώς μπορείτε πολύ εύκολα να σταματήσετε να ακολουθείτε άλλα άτομα οποιαδήποτε στιγμή!",
@@ -220,9 +237,9 @@
   "hashtag.column_settings.tag_mode.any": "Οποιοδήποτε από αυτά",
   "hashtag.column_settings.tag_mode.none": "Κανένα από αυτά",
   "hashtag.column_settings.tag_toggle": "Προσθήκη επιπλέον ταμπελών για την κολώνα",
-  "hashtag.follow": "Follow hashtag",
+  "hashtag.follow": "Παρακολούθηση ετικέτας",
   "hashtag.total_volume": "Συνολικός όγκος κατά την τελευταία {days, plural, one {ημέρα} other {{days} ημέρες}}",
-  "hashtag.unfollow": "Unfollow hashtag",
+  "hashtag.unfollow": "Διακοπή παρακολούθησης ετικέτας",
   "home.column_settings.basic": "Βασικές ρυθμίσεις",
   "home.column_settings.show_reblogs": "Εμφάνιση προωθήσεων",
   "home.column_settings.show_replies": "Εμφάνιση απαντήσεων",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "Edited {count, plural, one {{count} time} other {{count} times}}",
   "status.embed": "Ενσωμάτωσε",
   "status.favourite": "Σημείωσε ως αγαπημένο",
+  "status.filter": "Filter this post",
   "status.filtered": "Φιλτραρισμένα",
   "status.hide": "Απόκρυψη toot",
   "status.history.created": "{name} created {date}",
diff --git a/app/javascript/mastodon/locales/en-GB.json b/app/javascript/mastodon/locales/en-GB.json
index 535c5852a..2287dcda5 100644
--- a/app/javascript/mastodon/locales/en-GB.json
+++ b/app/javascript/mastodon/locales/en-GB.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Oops!",
   "announcement.announcement": "Announcement",
   "attachments_list.unprocessed": "(unprocessed)",
+  "audio.hide": "Hide audio",
   "autosuggest_hashtag.per_week": "{count} per week",
   "boost_modal.combo": "You can press {combo} to skip this next time",
   "bundle_column_error.body": "Something went wrong while loading this component.",
@@ -196,6 +197,22 @@
   "explore.trending_links": "News",
   "explore.trending_statuses": "Posts",
   "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",
   "follow_recommendations.done": "Done",
   "follow_recommendations.heading": "Follow people you'd like to see posts from! Here are some suggestions.",
   "follow_recommendations.lead": "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!",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "Edited {count, plural, one {{count} time} other {{count} times}}",
   "status.embed": "Embed",
   "status.favourite": "Favourite",
+  "status.filter": "Filter this post",
   "status.filtered": "Filtered",
   "status.hide": "Hide toot",
   "status.history.created": "{name} created {date}",
diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json
index 60279436d..6a186562f 100644
--- a/app/javascript/mastodon/locales/en.json
+++ b/app/javascript/mastodon/locales/en.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Oops!",
   "announcement.announcement": "Announcement",
   "attachments_list.unprocessed": "(unprocessed)",
+  "audio.hide": "Hide audio",
   "autosuggest_hashtag.per_week": "{count} per week",
   "boost_modal.combo": "You can press {combo} to skip this next time",
   "bundle_column_error.body": "Something went wrong while loading this component.",
@@ -200,6 +201,22 @@
   "explore.trending_links": "News",
   "explore.trending_statuses": "Posts",
   "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",
   "follow_recommendations.done": "Done",
   "follow_recommendations.heading": "Follow people you'd like to see posts from! Here are some suggestions.",
   "follow_recommendations.lead": "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!",
@@ -475,6 +492,7 @@
   "status.edited_x_times": "Edited {count, plural, one {{count} time} other {{count} times}}",
   "status.embed": "Embed",
   "status.favourite": "Favourite",
+  "status.filter": "Filter this post",
   "status.filtered": "Filtered",
   "status.hide": "Hide toot",
   "status.history.created": "{name} created {date}",
diff --git a/app/javascript/mastodon/locales/eo.json b/app/javascript/mastodon/locales/eo.json
index 67872ff0a..082c53de7 100644
--- a/app/javascript/mastodon/locales/eo.json
+++ b/app/javascript/mastodon/locales/eo.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Aj!",
   "announcement.announcement": "Anonco",
   "attachments_list.unprocessed": "(neprilaborita)",
+  "audio.hide": "Hide audio",
   "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.",
@@ -196,6 +197,22 @@
   "explore.trending_links": "Novaĵoj",
   "explore.trending_statuses": "Afiŝoj",
   "explore.trending_tags": "Kradvortoj",
+  "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",
   "follow_recommendations.done": "Farita",
   "follow_recommendations.heading": "Sekvi la personojn kies mesaĝojn vi volas vidi! Jen iom da sugestoj.",
   "follow_recommendations.lead": "La mesaĝoj de personoj kiujn vi sekvas, aperos laŭ kronologia ordo en via hejma templinio. Ne timu erari, vi povas ĉesi sekvi facile iam ajn!",
@@ -220,9 +237,9 @@
   "hashtag.column_settings.tag_mode.any": "Iu ajn",
   "hashtag.column_settings.tag_mode.none": "Neniu",
   "hashtag.column_settings.tag_toggle": "Aldoni pliajn etikedojn por ĉi tiu kolumno",
-  "hashtag.follow": "Follow hashtag",
+  "hashtag.follow": "Sekvi la kradvorton",
   "hashtag.total_volume": "Total volume in the last {days, plural, one {day} other {{days} days}}",
-  "hashtag.unfollow": "Unfollow hashtag",
+  "hashtag.unfollow": "Ne plu sekvi la kradvorton",
   "home.column_settings.basic": "Bazaj agordoj",
   "home.column_settings.show_reblogs": "Montri plusendojn",
   "home.column_settings.show_replies": "Montri respondojn",
@@ -470,6 +487,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.filtered": "Filtrita",
   "status.hide": "Kaŝi la mesaĝon",
   "status.history.created": "{name} kreis {date}",
diff --git a/app/javascript/mastodon/locales/es-AR.json b/app/javascript/mastodon/locales/es-AR.json
index 0eeb6e1ff..8e4b906a2 100644
--- a/app/javascript/mastodon/locales/es-AR.json
+++ b/app/javascript/mastodon/locales/es-AR.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "¡Epa!",
   "announcement.announcement": "Anuncio",
   "attachments_list.unprocessed": "[sin procesar]",
+  "audio.hide": "Ocultar audio",
   "autosuggest_hashtag.per_week": "{count} por semana",
   "boost_modal.combo": "Podés hacer clic en {combo} para saltar esto la próxima vez",
   "bundle_column_error.body": "Algo salió mal al cargar este componente.",
@@ -196,6 +197,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",
   "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!",
@@ -220,9 +237,9 @@
   "hashtag.column_settings.tag_mode.any": "Cualquiera de estas",
   "hashtag.column_settings.tag_mode.none": "Ninguna de estas",
   "hashtag.column_settings.tag_toggle": "Incluir etiquetas adicionales para esta columna",
-  "hashtag.follow": "Follow hashtag",
+  "hashtag.follow": "Seguir etiqueta",
   "hashtag.total_volume": "Volumen total en el/los último/s {days, plural, one {día} other {{days} días}}",
-  "hashtag.unfollow": "Unfollow hashtag",
+  "hashtag.unfollow": "Dejar de seguir etiqueta",
   "home.column_settings.basic": "Básico",
   "home.column_settings.show_reblogs": "Mostrar adhesiones",
   "home.column_settings.show_replies": "Mostrar respuestas",
@@ -470,6 +487,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.filtered": "Filtrado",
   "status.hide": "Ocultar mensaje",
   "status.history.created": "Creado por {name} el {date}",
diff --git a/app/javascript/mastodon/locales/es-MX.json b/app/javascript/mastodon/locales/es-MX.json
index 23a8d7247..96f0a59dc 100644
--- a/app/javascript/mastodon/locales/es-MX.json
+++ b/app/javascript/mastodon/locales/es-MX.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "¡Ups!",
   "announcement.announcement": "Anuncio",
   "attachments_list.unprocessed": "(sin procesar)",
+  "audio.hide": "Hide 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.",
@@ -196,6 +197,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",
   "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!",
@@ -220,9 +237,9 @@
   "hashtag.column_settings.tag_mode.any": "Cualquiera de estos",
   "hashtag.column_settings.tag_mode.none": "Ninguno de estos",
   "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": "Seguir etiqueta",
+  "hashtag.total_volume": "Volumen total en los últimos {days, plural, one {día} other {{days} días}}",
+  "hashtag.unfollow": "Dejar de seguir etiqueta",
   "home.column_settings.basic": "Básico",
   "home.column_settings.show_reblogs": "Mostrar retoots",
   "home.column_settings.show_replies": "Mostrar respuestas",
@@ -470,6 +487,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.filtered": "Filtrado",
   "status.hide": "Ocultar publicación",
   "status.history.created": "{name} creó {date}",
@@ -520,7 +538,7 @@
   "timeline_hint.resources.followers": "Seguidores",
   "timeline_hint.resources.follows": "Seguidos",
   "timeline_hint.resources.statuses": "Toots más antiguos",
-  "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} persona} other {{counter} personas}} en los últimos {days, plural, one {días} other {{days} días}}",
   "trends.trending_now": "Tendencia ahora",
   "ui.beforeunload": "Tu borrador se perderá si sales de Mastodon.",
   "units.short.billion": "{count} MM",
diff --git a/app/javascript/mastodon/locales/es.json b/app/javascript/mastodon/locales/es.json
index 857f3a3cd..57259e21c 100644
--- a/app/javascript/mastodon/locales/es.json
+++ b/app/javascript/mastodon/locales/es.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "¡Ups!",
   "announcement.announcement": "Anuncio",
   "attachments_list.unprocessed": "(sin procesar)",
+  "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.",
@@ -196,6 +197,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",
   "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!",
@@ -220,9 +237,9 @@
   "hashtag.column_settings.tag_mode.any": "Cualquiera de estos",
   "hashtag.column_settings.tag_mode.none": "Ninguno de estos",
   "hashtag.column_settings.tag_toggle": "Include additional tags in this column",
-  "hashtag.follow": "Follow hashtag",
+  "hashtag.follow": "Seguir etiqueta",
   "hashtag.total_volume": "Volumen total en los últimos {days, plural, one {día} other {{days} días}}",
-  "hashtag.unfollow": "Unfollow hashtag",
+  "hashtag.unfollow": "Dejar de seguir etiqueta",
   "home.column_settings.basic": "Básico",
   "home.column_settings.show_reblogs": "Mostrar retoots",
   "home.column_settings.show_replies": "Mostrar respuestas",
@@ -470,6 +487,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.filtered": "Filtrado",
   "status.hide": "Ocultar publicación",
   "status.history.created": "{name} creó {date}",
diff --git a/app/javascript/mastodon/locales/et.json b/app/javascript/mastodon/locales/et.json
index 2b6594b87..6737111fd 100644
--- a/app/javascript/mastodon/locales/et.json
+++ b/app/javascript/mastodon/locales/et.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Oih!",
   "announcement.announcement": "Teadaanne",
   "attachments_list.unprocessed": "(unprocessed)",
+  "audio.hide": "Hide audio",
   "autosuggest_hashtag.per_week": "{count} nädalas",
   "boost_modal.combo": "Võite vajutada {combo}, et see järgmine kord vahele jätta",
   "bundle_column_error.body": "Midagi läks valesti selle komponendi laadimisel.",
@@ -196,6 +197,22 @@
   "explore.trending_links": "Uudised",
   "explore.trending_statuses": "Postitused",
   "explore.trending_tags": "Sildid",
+  "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",
   "follow_recommendations.done": "Done",
   "follow_recommendations.heading": "Follow people you'd like to see posts from! Here are some suggestions.",
   "follow_recommendations.lead": "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!",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "Edited {count, plural, one {{count} time} other {{count} times}}",
   "status.embed": "Sängita",
   "status.favourite": "Lemmik",
+  "status.filter": "Filter this post",
   "status.filtered": "Filtreeritud",
   "status.hide": "Hide toot",
   "status.history.created": "{name} created {date}",
diff --git a/app/javascript/mastodon/locales/eu.json b/app/javascript/mastodon/locales/eu.json
index 44ab5f80e..c8062f004 100644
--- a/app/javascript/mastodon/locales/eu.json
+++ b/app/javascript/mastodon/locales/eu.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Ene!",
   "announcement.announcement": "Iragarpena",
   "attachments_list.unprocessed": "(prozesatu gabe)",
+  "audio.hide": "Hide audio",
   "autosuggest_hashtag.per_week": "{count} asteko",
   "boost_modal.combo": "{combo} sakatu dezakezu hurrengoan hau saltatzeko",
   "bundle_column_error.body": "Zerbait okerra gertatu da osagai hau kargatzean.",
@@ -196,6 +197,22 @@
   "explore.trending_links": "Berriak",
   "explore.trending_statuses": "Bidalketak",
   "explore.trending_tags": "Traolak",
+  "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",
   "follow_recommendations.done": "Egina",
   "follow_recommendations.heading": "Jarraitu jendea beren bidalketak ikusteko! Hemen dituzu iradokizun batzuk.",
   "follow_recommendations.lead": "Jarraitzen duzun jendearen bidalketak ordena kronologikoan agertuko dira zure hasierako jarioan. Ez izan akatsak egiteko beldurrik, jendea jarraitzeari uztea erraza da!",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "{count, plural, one {behin} other {{count} aldiz}} editatua",
   "status.embed": "Txertatu",
   "status.favourite": "Gogokoa",
+  "status.filter": "Filter this post",
   "status.filtered": "Iragazita",
   "status.hide": "Hide toot",
   "status.history.created": "{name} erabiltzaileak sortua {date}",
diff --git a/app/javascript/mastodon/locales/fa.json b/app/javascript/mastodon/locales/fa.json
index 977b0aa74..775f38475 100644
--- a/app/javascript/mastodon/locales/fa.json
+++ b/app/javascript/mastodon/locales/fa.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "ای وای!",
   "announcement.announcement": "اعلامیه",
   "attachments_list.unprocessed": "(پردازش نشده)",
+  "audio.hide": "Hide audio",
   "autosuggest_hashtag.per_week": "{count} در هفته",
   "boost_modal.combo": "دکمهٔ {combo} را بزنید تا دیگر این را نبینید",
   "bundle_column_error.body": "هنگام بار کردن این مولفه، اشتباهی رخ داد.",
@@ -196,6 +197,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",
   "follow_recommendations.done": "انجام شد",
   "follow_recommendations.heading": "افرادی را که می‌خواهید فرسته‌هایشان را ببینید پی‌گیری کنید! این‌ها تعدادی پیشنهاد هستند.",
   "follow_recommendations.lead": "فرسته‌های افرادی که دنبال می‌کنید به ترتیب زمانی در خوراک خانه‌تان نشان داده خواهد شد. از اشتباه کردن نترسید. می‌توانید به همین سادگی در هر زمانی از دنبال کردن افراد دست بکشید!",
@@ -470,6 +487,7 @@
   "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} ایجاد شد",
diff --git a/app/javascript/mastodon/locales/fi.json b/app/javascript/mastodon/locales/fi.json
index 68dbe44aa..3eb0f3e06 100644
--- a/app/javascript/mastodon/locales/fi.json
+++ b/app/javascript/mastodon/locales/fi.json
@@ -18,7 +18,7 @@
   "account.followers": "Seuraajat",
   "account.followers.empty": "Kukaan ei seuraa tätä käyttäjää vielä.",
   "account.followers_counter": "{count, plural, one {{counter} seuraaja} other {{counter} seuraajat}}",
-  "account.following": "Following",
+  "account.following": "Seurataan",
   "account.following_counter": "{count, plural, one {{counter} seuraa} other {{counter} seuraa}}",
   "account.follows.empty": "Tämä käyttäjä ei vielä seuraa ketään.",
   "account.follows_you": "Seuraa sinua",
@@ -41,12 +41,12 @@
   "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}",
   "account.unblock": "Salli @{name}",
   "account.unblock_domain": "Salli {domain}",
-  "account.unblock_short": "Unblock",
+  "account.unblock_short": "Poista esto",
   "account.unendorse": "Poista suosittelu profiilistasi",
   "account.unfollow": "Lopeta seuraaminen",
   "account.unmute": "Poista käyttäjän @{name} mykistys",
   "account.unmute_notifications": "Poista mykistys käyttäjän @{name} ilmoituksilta",
-  "account.unmute_short": "Unmute",
+  "account.unmute_short": "Poista mykistys",
   "account_note.placeholder": "Lisää muistiinpano napsauttamalla",
   "admin.dashboard.daily_retention": "Käyttäjän säilyminen rekisteröitymisen jälkeiseen päivään mennessä",
   "admin.dashboard.monthly_retention": "Käyttäjän säilyminen rekisteröitymisen jälkeiseen kuukauteen mennessä",
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Hups!",
   "announcement.announcement": "Ilmoitus",
   "attachments_list.unprocessed": "(käsittelemätön)",
+  "audio.hide": "Piilota ääni",
   "autosuggest_hashtag.per_week": "{count} viikossa",
   "boost_modal.combo": "Ensi kerralla voit ohittaa tämän painamalla {combo}",
   "bundle_column_error.body": "Jokin meni vikaan komponenttia ladattaessa.",
@@ -70,7 +71,7 @@
   "column.blocks": "Estetyt käyttäjät",
   "column.bookmarks": "Kirjanmerkit",
   "column.community": "Paikallinen aikajana",
-  "column.direct": "Direct messages",
+  "column.direct": "Yksityisviestit",
   "column.directory": "Selaa profiileja",
   "column.domain_blocks": "Piilotetut verkkotunnukset",
   "column.favourites": "Suosikit",
@@ -92,10 +93,10 @@
   "community.column_settings.local_only": "Vain paikalliset",
   "community.column_settings.media_only": "Vain media",
   "community.column_settings.remote_only": "Vain etäkäyttö",
-  "compose.language.change": "Change language",
-  "compose.language.search": "Search languages...",
+  "compose.language.change": "Vaihda kieli",
+  "compose.language.search": "Hae kieliä...",
   "compose_form.direct_message_warning_learn_more": "Lisätietoja",
-  "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": "Mastodonin viestit eivät ole päästä päähän salattuja. Älä jaa arkaluonteisia tietoja Mastodonissa.",
   "compose_form.hashtag_warning": "Tätä julkaisua listata minkään hastagin alle, koska se on listaamaton. Ainoastaan julkisia julkaisuja etsiä hastageilla.",
   "compose_form.lock_disclaimer": "Tilisi ei ole {locked}. Kuka tahansa voi seurata tiliäsi ja nähdä vain seuraajille rajaamasi julkaisut.",
   "compose_form.lock_disclaimer.lock": "lukittu",
@@ -106,7 +107,7 @@
   "compose_form.poll.remove_option": "Poista tämä valinta",
   "compose_form.poll.switch_to_multiple": "Muuta kysely monivalinnaksi",
   "compose_form.poll.switch_to_single": "Muuta kysely sallimaan vain yksi valinta",
-  "compose_form.publish": "Publish",
+  "compose_form.publish": "Julkaise",
   "compose_form.publish_loud": "{publish}!",
   "compose_form.save_changes": "Tallenna muutokset",
   "compose_form.sensitive.hide": "{count, plural, one {Merkitse media arkaluontoiseksi} other {Merkitse media arkaluontoiseksi}}",
@@ -149,7 +150,7 @@
   "embed.instructions": "Upota julkaisu verkkosivullesi kopioimalla alla oleva koodi.",
   "embed.preview": "Se tulee näyttämään tältä:",
   "emoji_button.activity": "Aktiviteetit",
-  "emoji_button.clear": "Clear",
+  "emoji_button.clear": "Tyhjennä",
   "emoji_button.custom": "Mukautetut",
   "emoji_button.flags": "Liput",
   "emoji_button.food": "Ruoka ja juoma",
@@ -169,7 +170,7 @@
   "empty_column.blocks": "Et ole vielä estänyt yhtään käyttäjää.",
   "empty_column.bookmarked_statuses": "Et ole vielä lisännyt viestejä kirjanmerkkeihisi. Kun lisäät yhden, se näkyy tässä.",
   "empty_column.community": "Paikallinen aikajana on tyhjä. Kirjoita jotain julkista, niin homma lähtee käyntiin!",
-  "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": "Sinulla ei ole vielä yksityisviestejä. Kun lähetät tai vastaanotat sellaisen, se näkyy tässä.",
   "empty_column.domain_blocks": "Yhtään verkko-osoitetta ei ole vielä estetty.",
   "empty_column.explore_statuses": "Mikään ei ole nyt trendi. Tarkista myöhemmin!",
   "empty_column.favourited_statuses": "Et ole vielä lisännyt viestejä kirjanmerkkeihisi. Kun lisäät yhden, se näkyy tässä.",
@@ -196,6 +197,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",
   "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!",
@@ -220,9 +237,9 @@
   "hashtag.column_settings.tag_mode.any": "Mikä tahansa näistä",
   "hashtag.column_settings.tag_mode.none": "Ei mitään näistä",
   "hashtag.column_settings.tag_toggle": "Sisällytä lisätunnisteet tähän sarakkeeseen",
-  "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": "Seuraa hashtagia",
+  "hashtag.total_volume": "Kokonaismäärä viimeiset {days, plural, one {päivä} other {{days} päivää}}",
+  "hashtag.unfollow": "Lopeta seuraaminen hashtagilla",
   "home.column_settings.basic": "Perusasetukset",
   "home.column_settings.show_reblogs": "Näytä buustaukset",
   "home.column_settings.show_replies": "Näytä vastaukset",
@@ -237,7 +254,7 @@
   "keyboard_shortcuts.column": "Kohdista sarakkeeseen",
   "keyboard_shortcuts.compose": "siirry tekstinsyöttöön",
   "keyboard_shortcuts.description": "Kuvaus",
-  "keyboard_shortcuts.direct": "to open direct messages column",
+  "keyboard_shortcuts.direct": "avaa yksityisviesti sarake",
   "keyboard_shortcuts.down": "Siirry listassa alaspäin",
   "keyboard_shortcuts.enter": "Avaa julkaisu",
   "keyboard_shortcuts.favourite": "Lisää suosikkeihin",
@@ -270,8 +287,8 @@
   "lightbox.expand": "Laajenna kuvan näkymälaatikko",
   "lightbox.next": "Seuraava",
   "lightbox.previous": "Edellinen",
-  "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": "Näytä profiili joka tapauksessa",
+  "limited_account_hint.title": "Tämä profiili on piilotettu serverisi valvojien toimesta.",
   "lists.account.add": "Lisää listaan",
   "lists.account.remove": "Poista listasta",
   "lists.delete": "Poista lista",
@@ -298,11 +315,11 @@
   "navigation_bar.bookmarks": "Kirjanmerkit",
   "navigation_bar.community_timeline": "Paikallinen aikajana",
   "navigation_bar.compose": "Luo uusi viesti",
-  "navigation_bar.direct": "Direct messages",
+  "navigation_bar.direct": "Yksityisviestit",
   "navigation_bar.discover": "Löydä uutta",
   "navigation_bar.domain_blocks": "Estetyt verkkotunnukset",
   "navigation_bar.edit_profile": "Muokkaa profiilia",
-  "navigation_bar.explore": "Explore",
+  "navigation_bar.explore": "Selaa",
   "navigation_bar.favourites": "Suosikit",
   "navigation_bar.filters": "Mykistetyt sanat",
   "navigation_bar.follow_requests": "Seuraamispyynnöt",
@@ -317,7 +334,7 @@
   "navigation_bar.preferences": "Asetukset",
   "navigation_bar.public_timeline": "Yleinen aikajana",
   "navigation_bar.security": "Turvallisuus",
-  "notification.admin.report": "{name} reported {target}",
+  "notification.admin.report": "{name} ilmoitti {target}",
   "notification.admin.sign_up": "{name} rekisteröitynyt",
   "notification.favourite": "{name} tykkäsi viestistäsi",
   "notification.follow": "{name} seurasi sinua",
@@ -330,7 +347,7 @@
   "notification.update": "{name} muokkasi viestiä",
   "notifications.clear": "Tyhjennä ilmoitukset",
   "notifications.clear_confirmation": "Haluatko varmasti poistaa kaikki ilmoitukset pysyvästi?",
-  "notifications.column_settings.admin.report": "New reports:",
+  "notifications.column_settings.admin.report": "Uudet raportit:",
   "notifications.column_settings.admin.sign_up": "Uudet kirjautumiset:",
   "notifications.column_settings.alert": "Työpöytäilmoitukset",
   "notifications.column_settings.favourite": "Tykkäykset:",
@@ -377,12 +394,12 @@
   "poll_button.remove_poll": "Poista kysely",
   "privacy.change": "Muuta julkaisun näkyvyyttä",
   "privacy.direct.long": "Julkaise vain mainituille käyttäjille",
-  "privacy.direct.short": "Direct",
+  "privacy.direct.short": "Vain mainitut henkilöt",
   "privacy.private.long": "Julkaise vain seuraajille",
-  "privacy.private.short": "Followers-only",
-  "privacy.public.long": "Visible for all",
+  "privacy.private.short": "Vain seuraajat",
+  "privacy.public.long": "Näkyvissä kaikille",
   "privacy.public.short": "Julkinen",
-  "privacy.unlisted.long": "Visible for all, but opted-out of discovery features",
+  "privacy.unlisted.long": "Näkyvissä kaikille, mutta jättäen pois hakemisen mahdollisuus",
   "privacy.unlisted.short": "Listaamaton julkinen",
   "refresh": "Päivitä",
   "regeneration_indicator.label": "Ladataan…",
@@ -436,11 +453,11 @@
   "report.thanks.title_actionable": "Kiitos raportista, tutkimme asiaa.",
   "report.unfollow": "Lopeta seuraaminen @{name}",
   "report.unfollow_explanation": "Seuraat tätä tiliä. Jotta et enää näkisi heidän kirjoituksiaan, lopeta niiden seuraaminen.",
-  "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.violation": "Rule violation",
-  "report_notification.open": "Open report",
+  "report_notification.attached_statuses": "{count, plural, one {{count} post} other {{count} viestiä}} liitteenä",
+  "report_notification.categories.other": "Muu",
+  "report_notification.categories.spam": "Roskaposti",
+  "report_notification.categories.violation": "Sääntöjen rikkominen",
+  "report_notification.open": "Avaa raportti",
   "search.placeholder": "Hae",
   "search_popout.search_format": "Tarkennettu haku",
   "search_popout.tips.full_text": "Tekstihaku listaa tilapäivitykset, jotka olet kirjoittanut, lisännyt suosikkeihisi, boostannut tai joissa sinut mainitaan, sekä tekstin sisältävät käyttäjänimet, nimimerkit ja hastagit.",
@@ -470,8 +487,9 @@
   "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.filtered": "Suodatettu",
-  "status.hide": "Hide toot",
+  "status.hide": "Piilota toot",
   "status.history.created": "{name} luotu {date}",
   "status.history.edited": "{name} muokkasi {date}",
   "status.load_more": "Lataa lisää",
@@ -495,7 +513,7 @@
   "status.report": "Raportoi @{name}",
   "status.sensitive_warning": "Arkaluontoista sisältöä",
   "status.share": "Jaa",
-  "status.show_filter_reason": "Show anyway",
+  "status.show_filter_reason": "Näytä joka tapauksessa",
   "status.show_less": "Näytä vähemmän",
   "status.show_less_all": "Näytä vähemmän kaikista",
   "status.show_more": "Näytä lisää",
@@ -520,7 +538,7 @@
   "timeline_hint.resources.followers": "Seuraajat",
   "timeline_hint.resources.follows": "Seuraa",
   "timeline_hint.resources.statuses": "Vanhemmat julkaisut",
-  "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} henkilö} other {{counter} henkilöä}} viimeinen {days, plural, one {päivä} other {{days} päivää}}",
   "trends.trending_now": "Suosittua nyt",
   "ui.beforeunload": "Luonnos häviää, jos poistut Mastodonista.",
   "units.short.billion": "{count} mrd.",
@@ -532,7 +550,7 @@
   "upload_error.poll": "Tiedon lataaminen ei ole sallittua kyselyissä.",
   "upload_form.audio_description": "Kuvaile kuulovammaisille",
   "upload_form.description": "Anna kuvaus näkörajoitteisia varten",
-  "upload_form.description_missing": "No description added",
+  "upload_form.description_missing": "Kuvausta ei ole lisätty",
   "upload_form.edit": "Kuvaile",
   "upload_form.thumbnail": "Vaihda pikkukuva",
   "upload_form.undo": "Peru",
diff --git a/app/javascript/mastodon/locales/fr.json b/app/javascript/mastodon/locales/fr.json
index 93d68190e..cc710250d 100644
--- a/app/javascript/mastodon/locales/fr.json
+++ b/app/javascript/mastodon/locales/fr.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Oups !",
   "announcement.announcement": "Annonce",
   "attachments_list.unprocessed": "(non traité)",
+  "audio.hide": "Hide 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.",
@@ -196,6 +197,22 @@
   "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.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",
   "follow_recommendations.done": "Terminé",
   "follow_recommendations.heading": "Suivez les personnes dont vous aimeriez voir les messages ! Voici quelques suggestions.",
   "follow_recommendations.lead": "Les messages des personnes que vous suivez apparaîtront par ordre chronologique sur votre fil d'accueil. Ne craignez pas de faire des erreurs, vous pouvez arrêter de suivre les gens aussi facilement à tout moment !",
@@ -220,9 +237,9 @@
   "hashtag.column_settings.tag_mode.any": "Au moins un de ces éléments",
   "hashtag.column_settings.tag_mode.none": "Aucun de ces éléments",
   "hashtag.column_settings.tag_toggle": "Inclure des hashtags additionnels pour cette colonne",
-  "hashtag.follow": "Follow hashtag",
+  "hashtag.follow": "Suivre le hashtag",
   "hashtag.total_volume": "Volume total {days, plural, one {des dernières 24h} other {des {days} derniers jours}}",
-  "hashtag.unfollow": "Unfollow hashtag",
+  "hashtag.unfollow": "Ne plus suivre le hashtag",
   "home.column_settings.basic": "Basique",
   "home.column_settings.show_reblogs": "Afficher les partages",
   "home.column_settings.show_replies": "Afficher les réponses",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "Edité {count, plural, one {{count} fois} other {{count} fois}}",
   "status.embed": "Intégrer",
   "status.favourite": "Ajouter aux favoris",
+  "status.filter": "Filter this post",
   "status.filtered": "Filtré",
   "status.hide": "Cacher le pouet",
   "status.history.created": "créé par {name} {date}",
diff --git a/app/javascript/mastodon/locales/fy.json b/app/javascript/mastodon/locales/fy.json
index ea5a61cdc..a53a1cf52 100644
--- a/app/javascript/mastodon/locales/fy.json
+++ b/app/javascript/mastodon/locales/fy.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Oops!",
   "announcement.announcement": "Announcement",
   "attachments_list.unprocessed": "(net ferwurke)",
+  "audio.hide": "Hide audio",
   "autosuggest_hashtag.per_week": "{count} per week",
   "boost_modal.combo": "You can press {combo} to skip this next time",
   "bundle_column_error.body": "Something went wrong while loading this component.",
@@ -196,6 +197,22 @@
   "explore.trending_links": "Nijs",
   "explore.trending_statuses": "Berjochten",
   "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",
   "follow_recommendations.done": "Klear",
   "follow_recommendations.heading": "Folgje minsken wer as jo graach berjochten fan sjen wolle! Hjir binne wat suggestjes.",
   "follow_recommendations.lead": "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!",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "{count, plural, one {{count} kear} other {{count} kearen}} bewurke",
   "status.embed": "Ynslute",
   "status.favourite": "Favorite",
+  "status.filter": "Filter this post",
   "status.filtered": "Filtere",
   "status.hide": "Hide toot",
   "status.history.created": "{name} makke dit {date}",
diff --git a/app/javascript/mastodon/locales/ga.json b/app/javascript/mastodon/locales/ga.json
index 1dd7e635f..e05c4a41d 100644
--- a/app/javascript/mastodon/locales/ga.json
+++ b/app/javascript/mastodon/locales/ga.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Hiúps!",
   "announcement.announcement": "Fógra",
   "attachments_list.unprocessed": "(unprocessed)",
+  "audio.hide": "Hide audio",
   "autosuggest_hashtag.per_week": "{count} per week",
   "boost_modal.combo": "Is féidir leat brúigh {combo} chun é seo a scipeáil an chéad uair eile",
   "bundle_column_error.body": "Something went wrong while loading this component.",
@@ -196,6 +197,22 @@
   "explore.trending_links": "Nuacht",
   "explore.trending_statuses": "Postálacha",
   "explore.trending_tags": "Haischlibeanna",
+  "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",
   "follow_recommendations.done": "Déanta",
   "follow_recommendations.heading": "Follow people you'd like to see posts from! Here are some suggestions.",
   "follow_recommendations.lead": "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!",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "Curtha in eagar {count, plural, one {{count} uair amháin} two {{count} uair} few {{count} uair} many {{count} uair} other {{count} uair}}",
   "status.embed": "Embed",
   "status.favourite": "Rogha",
+  "status.filter": "Filter this post",
   "status.filtered": "Filtered",
   "status.hide": "Hide toot",
   "status.history.created": "{name} created {date}",
diff --git a/app/javascript/mastodon/locales/gd.json b/app/javascript/mastodon/locales/gd.json
index f7ffe0d87..c58729271 100644
--- a/app/javascript/mastodon/locales/gd.json
+++ b/app/javascript/mastodon/locales/gd.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Oich!",
   "announcement.announcement": "Brath-fios",
   "attachments_list.unprocessed": "(gun phròiseasadh)",
+  "audio.hide": "Hide audio",
   "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.",
@@ -196,6 +197,22 @@
   "explore.trending_links": "Naidheachdan",
   "explore.trending_statuses": "Postaichean",
   "explore.trending_tags": "Tagaichean hais",
+  "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",
   "follow_recommendations.done": "Deiseil",
   "follow_recommendations.heading": "Lean air daoine ma tha thu airson nam postaichean aca fhaicinn! Seo moladh no dà dhut.",
   "follow_recommendations.lead": "Nochdaidh na postaichean aig na daoine air a leanas tu a-rèir an ama air inbhir na dachaighe agad. Bi dàna on as urrainn dhut sgur de leantainn air daoine cuideachd uair sam bith!",
@@ -220,9 +237,9 @@
   "hashtag.column_settings.tag_mode.any": "Gin sam bith dhiubh",
   "hashtag.column_settings.tag_mode.none": "Às aonais gin sam bith dhiubh",
   "hashtag.column_settings.tag_toggle": "Gabh a-steach barrachd tagaichean sa cholbh seo",
-  "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": "Lean air an taga hais",
+  "hashtag.total_volume": "An t-iomlan sna {days, plural, one {{days} latha} two {{days} latha} few {{days} làithean} other {{days} latha}} seo chaidh",
+  "hashtag.unfollow": "Na lean air an taga hais tuilleadh",
   "home.column_settings.basic": "Bunasach",
   "home.column_settings.show_reblogs": "Seall na brosnachaidhean",
   "home.column_settings.show_replies": "Seall na freagairtean",
@@ -317,7 +334,7 @@
   "navigation_bar.preferences": "Roghainnean",
   "navigation_bar.public_timeline": "Loidhne-ama cho-naisgte",
   "navigation_bar.security": "Tèarainteachd",
-  "notification.admin.report": "{name} reported {target}",
+  "notification.admin.report": "Rinn {name} mu {target}",
   "notification.admin.sign_up": "Chlàraich {name}",
   "notification.favourite": "Is annsa le {name} am post agad",
   "notification.follow": "Tha {name} a’ leantainn ort a-nis",
@@ -330,7 +347,7 @@
   "notification.update": "Dheasaich {name} post",
   "notifications.clear": "Falamhaich na brathan",
   "notifications.clear_confirmation": "A bheil thu cinnteach gu bheil thu airson na brathan uile agad fhalamhachadh gu buan?",
-  "notifications.column_settings.admin.report": "New reports:",
+  "notifications.column_settings.admin.report": "Gearanan ùra:",
   "notifications.column_settings.admin.sign_up": "Clàraidhean ùra:",
   "notifications.column_settings.alert": "Brathan deasga",
   "notifications.column_settings.favourite": "Na h-annsachdan:",
@@ -388,11 +405,11 @@
   "regeneration_indicator.label": "’Ga luchdadh…",
   "regeneration_indicator.sublabel": "Tha inbhir na dachaigh agad ’ga ullachadh!",
   "relative_time.days": "{number}l",
-  "relative_time.full.days": "{count, plural, one {# latha} two {# latha} few {# làithean} other {# latha}} air ais",
-  "relative_time.full.hours": "{count, plural, one {# uair a thìde} two {# uair a thìde} few {# uairean a thìde} other {# uair a thìde}} air ais",
+  "relative_time.full.days": "{number, plural, one {# latha} two {# latha} few {# làithean} other {# latha}} air ais",
+  "relative_time.full.hours": "{number, plural, one {# uair a thìde} two {# uair a thìde} few {# uairean a thìde} other {# uair a thìde}} air ais",
   "relative_time.full.just_now": "an-dràsta fhèin",
-  "relative_time.full.minutes": "{count, plural, one {# mhionaid} two {# mhionaid} few {# mionaidean} other {# mionaid}} air ais",
-  "relative_time.full.seconds": "{count, plural, one {# diog} two {# dhiog} few {# diogan} other {# diog}} air ais",
+  "relative_time.full.minutes": "{number, plural, one {# mhionaid} two {# mhionaid} few {# mionaidean} other {# mionaid}} air ais",
+  "relative_time.full.seconds": "{number, plural, one {# diog} two {# dhiog} few {# diogan} other {# diog}} air ais",
   "relative_time.hours": "{number}u",
   "relative_time.just_now": "an-dràsta",
   "relative_time.minutes": "{number}m",
@@ -436,11 +453,11 @@
   "report.thanks.title_actionable": "Mòran taing airson a’ ghearain, bheir sinn sùil air.",
   "report.unfollow": "Na lean air @{name} tuilleadh",
   "report.unfollow_explanation": "Tha thu a’ leantainn air a’ chunntas seo. Sgur de leantainn orra ach nach fhaic thu na puist aca air inbhir na dachaigh agad.",
-  "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.violation": "Rule violation",
-  "report_notification.open": "Open report",
+  "report_notification.attached_statuses": "Tha {count, plural, one {{counter} phost} two {{counter} phost} few {{counter} postaichean} other {{counter} post}} ceangailte ris",
+  "report_notification.categories.other": "Eile",
+  "report_notification.categories.spam": "Spama",
+  "report_notification.categories.violation": "Briseadh riaghailte",
+  "report_notification.open": "Fosgail an gearan",
   "search.placeholder": "Lorg",
   "search_popout.search_format": "Fòrmat adhartach an luirg",
   "search_popout.tips.full_text": "Bheir teacsa sìmplidh dhut na postaichean a sgrìobh thu, a tha nan annsachdan dhut, a bhrosnaich thu no san deach iomradh a thoirt ort cho math ri ainmean-cleachdaiche, ainmean taisbeanaidh agus tagaichean hais a mhaidsicheas.",
@@ -470,8 +487,9 @@
   "status.edited_x_times": "Chaidh a dheasachadh {count, plural, one {{counter} turas} two {{counter} thuras} few {{counter} tursan} other {{counter} turas}}",
   "status.embed": "Leabaich",
   "status.favourite": "Cuir ris na h-annsachdan",
+  "status.filter": "Filter this post",
   "status.filtered": "Criathraichte",
-  "status.hide": "Hide toot",
+  "status.hide": "Falaich am post",
   "status.history.created": "Chruthaich {name} {date} e",
   "status.history.edited": "Dheasaich {name} {date} e",
   "status.load_more": "Luchdaich barrachd dheth",
@@ -495,7 +513,7 @@
   "status.report": "Dèan gearan mu @{name}",
   "status.sensitive_warning": "Susbaint fhrionasach",
   "status.share": "Co-roinn",
-  "status.show_filter_reason": "Show anyway",
+  "status.show_filter_reason": "Seall e co-dhiù",
   "status.show_less": "Seall nas lugha dheth",
   "status.show_less_all": "Seall nas lugha dhen a h-uile",
   "status.show_more": "Seall barrachd dheth",
@@ -520,7 +538,7 @@
   "timeline_hint.resources.followers": "Luchd-leantainn",
   "timeline_hint.resources.follows": "A’ leantainn air",
   "timeline_hint.resources.statuses": "Postaichean nas sine",
-  "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} neach} two {{counter} neach} few {{counter} daoine} other {{counter} duine}} sna {days, plural, one {{days} latha} two {{days} latha} few {{days} làithean} other {{days} latha}} seo chaidh",
   "trends.trending_now": "A’ treandadh an-dràsta",
   "ui.beforeunload": "Caillidh tu an dreachd agad ma dh’fhàgas tu Mastodon an-dràsta.",
   "units.short.billion": "{count}B",
diff --git a/app/javascript/mastodon/locales/gl.json b/app/javascript/mastodon/locales/gl.json
index 56ceb54e8..0c7baa332 100644
--- a/app/javascript/mastodon/locales/gl.json
+++ b/app/javascript/mastodon/locales/gl.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Vaites!",
   "announcement.announcement": "Anuncio",
   "attachments_list.unprocessed": "(sen procesar)",
+  "audio.hide": "Agochar audio",
   "autosuggest_hashtag.per_week": "{count} por semana",
   "boost_modal.combo": "Preme {combo} para ignorar isto na seguinte vez",
   "bundle_column_error.body": "Ocorreu un erro ó cargar este compoñente.",
@@ -196,6 +197,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",
   "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!",
@@ -220,9 +237,9 @@
   "hashtag.column_settings.tag_mode.any": "Calquera destes",
   "hashtag.column_settings.tag_mode.none": "Ningún destes",
   "hashtag.column_settings.tag_toggle": "Incluír cancelos adicionais para esta columna",
-  "hashtag.follow": "Follow hashtag",
+  "hashtag.follow": "Seguir cancelo",
   "hashtag.total_volume": "Cantidade total {days, plural, one {no último día} other {nos {days} últimos días}}",
-  "hashtag.unfollow": "Unfollow hashtag",
+  "hashtag.unfollow": "Deixar de seguir cancelo",
   "home.column_settings.basic": "Básico",
   "home.column_settings.show_reblogs": "Amosar compartidos",
   "home.column_settings.show_replies": "Amosar respostas",
@@ -470,6 +487,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.filtered": "Filtrado",
   "status.hide": "Agochar publicación",
   "status.history.created": "{name} creouno o {date}",
@@ -520,7 +538,7 @@
   "timeline_hint.resources.followers": "Seguidoras",
   "timeline_hint.resources.follows": "Seguindo",
   "timeline_hint.resources.statuses": "Publicacións antigas",
-  "trends.counter_by_accounts": "{count, plural, one {{counter} persoa} other {{counter} persoas}} nos últimos {days, plural, one {día} other {{days} días}}",
+  "trends.counter_by_accounts": "{count, plural, one {{counter} persoa} other {{counter} persoas}} {days, plural, one {no último día} other {nos {days} últimos días}}",
   "trends.trending_now": "Tendencias actuais",
   "ui.beforeunload": "O borrador perderase se saes de Mastodon.",
   "units.short.billion": "{count}B",
diff --git a/app/javascript/mastodon/locales/he.json b/app/javascript/mastodon/locales/he.json
index 4cb3380b4..281b91bc1 100644
--- a/app/javascript/mastodon/locales/he.json
+++ b/app/javascript/mastodon/locales/he.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "אופס!",
   "announcement.announcement": "הכרזה",
   "attachments_list.unprocessed": "(לא מעובד)",
+  "audio.hide": "Hide audio",
   "autosuggest_hashtag.per_week": "{count} לשבוע",
   "boost_modal.combo": "ניתן להקיש {combo} כדי לדלג בפעם הבאה",
   "bundle_column_error.body": "משהו השתבש בעת טעינת הרכיב הזה.",
@@ -196,6 +197,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",
   "follow_recommendations.done": "בוצע",
   "follow_recommendations.heading": "עקב/י אחרי אנשים שתרצה/י לראות את חצרוציהם! הנה כמה הצעות.",
   "follow_recommendations.lead": "חצרוצים מאנשים במעקב יופיעו בסדר כרונולוגי בפיד הבית. אל תחששו מטעויות, אפשר להסיר מעקב באותה הקלות ובכל זמן!",
@@ -220,9 +237,9 @@
   "hashtag.column_settings.tag_mode.any": "כל אלה",
   "hashtag.column_settings.tag_mode.none": "אף אחד מאלה",
   "hashtag.column_settings.tag_toggle": "כלול תגיות נוספות בטור זה",
-  "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": "הצגת תגובות",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "נערך {count, plural, one {פעם {count}} other {{count} פעמים}}",
   "status.embed": "הטמעה",
   "status.favourite": "חיבוב",
+  "status.filter": "Filter this post",
   "status.filtered": "סונן",
   "status.hide": "הסתר פוסט",
   "status.history.created": "{name} יצר/ה {date}",
diff --git a/app/javascript/mastodon/locales/hi.json b/app/javascript/mastodon/locales/hi.json
index aa76ebf10..d2403c1f5 100644
--- a/app/javascript/mastodon/locales/hi.json
+++ b/app/javascript/mastodon/locales/hi.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "उफ़!",
   "announcement.announcement": "घोषणा",
   "attachments_list.unprocessed": "(असंसाधित)",
+  "audio.hide": "Hide audio",
   "autosuggest_hashtag.per_week": "{count} हर सप्ताह",
   "boost_modal.combo": "अगली बार स्किप करने के लिए आप {combo} दबा सकते है",
   "bundle_column_error.body": "इस कॉम्पोनेन्ट को लोड करते वक्त कुछ गलत हो गया",
@@ -196,6 +197,22 @@
   "explore.trending_links": "News",
   "explore.trending_statuses": "Posts",
   "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",
   "follow_recommendations.done": "Done",
   "follow_recommendations.heading": "Follow people you'd like to see posts from! Here are some suggestions.",
   "follow_recommendations.lead": "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!",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "Edited {count, plural, one {{count} time} other {{count} times}}",
   "status.embed": "Embed",
   "status.favourite": "Favourite",
+  "status.filter": "Filter this post",
   "status.filtered": "Filtered",
   "status.hide": "Hide toot",
   "status.history.created": "{name} created {date}",
diff --git a/app/javascript/mastodon/locales/hr.json b/app/javascript/mastodon/locales/hr.json
index fe0379f0a..c66de9c0d 100644
--- a/app/javascript/mastodon/locales/hr.json
+++ b/app/javascript/mastodon/locales/hr.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Ups!",
   "announcement.announcement": "Najava",
   "attachments_list.unprocessed": "(neobrađeno)",
+  "audio.hide": "Hide audio",
   "autosuggest_hashtag.per_week": "{count} tjedno",
   "boost_modal.combo": "Možete pritisnuti {combo} kako biste preskočili ovo sljedeći put",
   "bundle_column_error.body": "Nešto je pošlo po zlu tijekom učitavanja ove komponente.",
@@ -196,6 +197,22 @@
   "explore.trending_links": "News",
   "explore.trending_statuses": "Posts",
   "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",
   "follow_recommendations.done": "Učinjeno",
   "follow_recommendations.heading": "Zaprati osobe čije objave želiš vidjeti! Evo nekoliko prijedloga.",
   "follow_recommendations.lead": "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!",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "Edited {count, plural, one {{count} time} other {{count} times}}",
   "status.embed": "Embed",
   "status.favourite": "Označi favoritom",
+  "status.filter": "Filter this post",
   "status.filtered": "Filtered",
   "status.hide": "Hide toot",
   "status.history.created": "{name} created {date}",
diff --git a/app/javascript/mastodon/locales/hu.json b/app/javascript/mastodon/locales/hu.json
index def9348ec..ce25cd103 100644
--- a/app/javascript/mastodon/locales/hu.json
+++ b/app/javascript/mastodon/locales/hu.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Hoppá!",
   "announcement.announcement": "Közlemény",
   "attachments_list.unprocessed": "(feldolgozatlan)",
+  "audio.hide": "Hang elrejtése",
   "autosuggest_hashtag.per_week": "{count} hetente",
   "boost_modal.combo": "Hogy átugord ezt következő alkalommal, használd {combo}",
   "bundle_column_error.body": "Valami hiba történt a komponens betöltése közben.",
@@ -196,6 +197,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",
   "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!",
@@ -220,9 +237,9 @@
   "hashtag.column_settings.tag_mode.any": "Bármelyik",
   "hashtag.column_settings.tag_mode.none": "Egyik sem",
   "hashtag.column_settings.tag_toggle": "Új címkék felvétele ehhez az oszlophoz",
-  "hashtag.follow": "Follow hashtag",
+  "hashtag.follow": "Hashtag követése",
   "hashtag.total_volume": "Teljes mennyiség az elmúlt {days, plural, one {napban} other {{days} napban}}",
-  "hashtag.unfollow": "Unfollow hashtag",
+  "hashtag.unfollow": "Hashtag követésének megszüntetése",
   "home.column_settings.basic": "Alapvető",
   "home.column_settings.show_reblogs": "Megtolások mutatása",
   "home.column_settings.show_replies": "Válaszok megjelenítése",
@@ -470,6 +487,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.filtered": "Megszűrt",
   "status.hide": "Bejegyzés elrejtése",
   "status.history.created": "{name} létrehozta: {date}",
diff --git a/app/javascript/mastodon/locales/hy.json b/app/javascript/mastodon/locales/hy.json
index 9aa8ec4c3..5a18eff04 100644
--- a/app/javascript/mastodon/locales/hy.json
+++ b/app/javascript/mastodon/locales/hy.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Վա՜յ",
   "announcement.announcement": "Յայտարարութիւններ",
   "attachments_list.unprocessed": "(unprocessed)",
+  "audio.hide": "Hide audio",
   "autosuggest_hashtag.per_week": "շաբաթը՝ {count}",
   "boost_modal.combo": "Կարող ես սեղմել {combo}՝ սա յաջորդ անգամ բաց թողնելու համար",
   "bundle_column_error.body": "Այս բաղադրիչը բեռնելու ընթացքում ինչ֊որ բան խափանուեց։",
@@ -196,6 +197,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",
   "follow_recommendations.done": "Աւարտուած է",
   "follow_recommendations.heading": "Հետեւիր այն մարդկանց, որոնց գրառումները կը ցանկանաս տեսնել։ Ահա մի քանի առաջարկ։",
   "follow_recommendations.lead": "Քո հոսքում, ժամանակագրական դասաւորութեամբ կը տեսնես այն մարդկանց գրառումները, որոնց հետեւում ես։ Մի վախեցիր սխալուել, դու միշտ կարող ես հեշտութեամբ ապահետեւել մարդկանց։",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "Edited {count, plural, one {{count} time} other {{count} times}}",
   "status.embed": "Ներդնել",
   "status.favourite": "Հաւանել",
+  "status.filter": "Filter this post",
   "status.filtered": "Զտուած",
   "status.hide": "Hide toot",
   "status.history.created": "{name} created {date}",
diff --git a/app/javascript/mastodon/locales/id.json b/app/javascript/mastodon/locales/id.json
index effc01737..9c3879212 100644
--- a/app/javascript/mastodon/locales/id.json
+++ b/app/javascript/mastodon/locales/id.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Ups!",
   "announcement.announcement": "Pengumuman",
   "attachments_list.unprocessed": "(tidak diproses)",
+  "audio.hide": "Hide audio",
   "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.",
@@ -196,6 +197,22 @@
   "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_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",
   "follow_recommendations.done": "Selesai",
   "follow_recommendations.heading": "Ikuti orang yang ingin Anda lihat kirimannya! Ini ada beberapa saran.",
   "follow_recommendations.lead": "Kiriman dari orang yang Anda ikuti akan tampil berdasar waktu di beranda Anda. Jangan takut membuat kesalahan, Anda dapat berhenti mengikuti mereka dengan mudah kapan saja!",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "Diedit {count, plural, other {{count} kali}}",
   "status.embed": "Tanam",
   "status.favourite": "Difavoritkan",
+  "status.filter": "Filter this post",
   "status.filtered": "Disaring",
   "status.hide": "Hide toot",
   "status.history.created": "{name} membuat pada {date}",
diff --git a/app/javascript/mastodon/locales/io.json b/app/javascript/mastodon/locales/io.json
index d54687117..f3bdb040c 100644
--- a/app/javascript/mastodon/locales/io.json
+++ b/app/javascript/mastodon/locales/io.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Problemo!",
   "announcement.announcement": "Anunco",
   "attachments_list.unprocessed": "(neprocedita)",
+  "audio.hide": "Celez audio",
   "autosuggest_hashtag.per_week": "{count} dum singla semano",
   "boost_modal.combo": "Tu povas presar sur {combo} por omisar co en la venonta foyo",
   "bundle_column_error.body": "Nulo ne functionis dum chargar ca kompozaj.",
@@ -196,6 +197,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",
   "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!",
@@ -220,9 +237,9 @@
   "hashtag.column_settings.tag_mode.any": "Irga co",
   "hashtag.column_settings.tag_mode.none": "Nula co",
   "hashtag.column_settings.tag_toggle": "Include additional tags in this column",
-  "hashtag.follow": "Follow hashtag",
+  "hashtag.follow": "Sequez hashtago",
   "hashtag.total_volume": "Sumo en antea {days, plural,one {dio} other {{days} dii}}",
-  "hashtag.unfollow": "Unfollow hashtag",
+  "hashtag.unfollow": "Desequez hashtago",
   "home.column_settings.basic": "Simpla",
   "home.column_settings.show_reblogs": "Montrar repeti",
   "home.column_settings.show_replies": "Montrar respondi",
@@ -470,6 +487,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.filtered": "Filtrita",
   "status.hide": "Celez posto",
   "status.history.created": "{name} kreis ye {date}",
diff --git a/app/javascript/mastodon/locales/is.json b/app/javascript/mastodon/locales/is.json
index e12bfe305..7e3a40fa7 100644
--- a/app/javascript/mastodon/locales/is.json
+++ b/app/javascript/mastodon/locales/is.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Úbbs!",
   "announcement.announcement": "Auglýsing",
   "attachments_list.unprocessed": "(óunnið)",
+  "audio.hide": "Fela hljóð",
   "autosuggest_hashtag.per_week": "{count} á viku",
   "boost_modal.combo": "Þú getur ýtt á {combo} til að sleppa þessu næst",
   "bundle_column_error.body": "Eitthvað fór úrskeiðis við að hlaða inn þessari einingu.",
@@ -196,6 +197,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",
   "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!",
@@ -220,9 +237,9 @@
   "hashtag.column_settings.tag_mode.any": "Hvað sem er af þessu",
   "hashtag.column_settings.tag_mode.none": "Ekkert af þessu",
   "hashtag.column_settings.tag_toggle": "Taka með viðbótarmerki fyrir þennan dálk",
-  "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": "Fylgjast með myllumerki",
+  "hashtag.total_volume": "Heildarmagn {days, plural, one {síðasta {days} sólarhring} other {síðustu {days} daga}}",
+  "hashtag.unfollow": "Hætta að fylgjast með myllumerki",
   "home.column_settings.basic": "Einfalt",
   "home.column_settings.show_reblogs": "Sýna endurbirtingar",
   "home.column_settings.show_replies": "Birta svör",
@@ -470,6 +487,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.filtered": "Síað",
   "status.hide": "Fela færslu",
   "status.history.created": "{name} útbjó {date}",
@@ -520,7 +538,7 @@
   "timeline_hint.resources.followers": "Fylgjendur",
   "timeline_hint.resources.follows": "Fylgist með",
   "timeline_hint.resources.statuses": "Eldri færslur",
-  "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} aðili} other {{counter} manns}} {days, plural, one {síðasta sólarhringinn} other {síðustu {days} daga}}",
   "trends.trending_now": "Í umræðunni núna",
   "ui.beforeunload": "Drögin tapast ef þú ferð út úr Mastodon.",
   "units.short.billion": "{count}B",
diff --git a/app/javascript/mastodon/locales/it.json b/app/javascript/mastodon/locales/it.json
index da29dfde1..9f32a0685 100644
--- a/app/javascript/mastodon/locales/it.json
+++ b/app/javascript/mastodon/locales/it.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Oops!",
   "announcement.announcement": "Annuncio",
   "attachments_list.unprocessed": "(non elaborato)",
+  "audio.hide": "Nascondi audio",
   "autosuggest_hashtag.per_week": "{count} per settimana",
   "boost_modal.combo": "Puoi premere {combo} per saltare questo passaggio la prossima volta",
   "bundle_column_error.body": "E' avvenuto un errore durante il caricamento di questo componente.",
@@ -196,6 +197,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",
   "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!",
@@ -220,9 +237,9 @@
   "hashtag.column_settings.tag_mode.any": "Uno o più di questi",
   "hashtag.column_settings.tag_mode.none": "Nessuno di questi",
   "hashtag.column_settings.tag_toggle": "Include additional tags in this column",
-  "hashtag.follow": "Follow hashtag",
+  "hashtag.follow": "Segui l'hashtag",
   "hashtag.total_volume": "Volume totale {days, plural, one {nell'ultimo giorno} other {negli ultimi {days} giorni}}",
-  "hashtag.unfollow": "Unfollow hashtag",
+  "hashtag.unfollow": "Cessa di seguire l'hashtag",
   "home.column_settings.basic": "Semplice",
   "home.column_settings.show_reblogs": "Mostra condivisioni",
   "home.column_settings.show_replies": "Mostra risposte",
@@ -470,6 +487,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.filtered": "Filtrato",
   "status.hide": "Nascondi toot",
   "status.history.created": "{name} ha creato {date}",
diff --git a/app/javascript/mastodon/locales/ja.json b/app/javascript/mastodon/locales/ja.json
index 8e1746a07..2b3513693 100644
--- a/app/javascript/mastodon/locales/ja.json
+++ b/app/javascript/mastodon/locales/ja.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "エラー!",
   "announcement.announcement": "お知らせ",
   "attachments_list.unprocessed": "(未処理)",
+  "audio.hide": "Hide audio",
   "autosuggest_hashtag.per_week": "{count} 回 / 週",
   "boost_modal.combo": "次からは{combo}を押せばスキップできます",
   "bundle_column_error.body": "コンポーネントの読み込み中に問題が発生しました。",
@@ -200,6 +201,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",
   "follow_recommendations.done": "完了",
   "follow_recommendations.heading": "投稿を見たい人をフォローしてください!ここにおすすめがあります。",
   "follow_recommendations.lead": "あなたがフォローしている人の投稿は、ホームフィードに時系列で表示されます。いつでも簡単に解除できるので、気軽にフォローしてみてください!",
@@ -224,9 +241,9 @@
   "hashtag.column_settings.tag_mode.any": "いずれかを含む",
   "hashtag.column_settings.tag_mode.none": "これらを除く",
   "hashtag.column_settings.tag_toggle": "このカラムに追加のタグを含める",
-  "hashtag.follow": "Follow hashtag",
+  "hashtag.follow": "ハッシュタグをフォローする",
   "hashtag.total_volume": "Total volume in the last {days, plural, one {day} other {{days} days}}",
-  "hashtag.unfollow": "Unfollow hashtag",
+  "hashtag.unfollow": "ハッシュタグのフォローを解除",
   "home.column_settings.basic": "基本設定",
   "home.column_settings.show_reblogs": "ブースト表示",
   "home.column_settings.show_replies": "返信表示",
@@ -475,6 +492,7 @@
   "status.edited_x_times": "{count}回編集",
   "status.embed": "埋め込み",
   "status.favourite": "お気に入り",
+  "status.filter": "Filter this post",
   "status.filtered": "フィルターされました",
   "status.hide": "トゥートを非表示",
   "status.history.created": "{name}さんが{date}に作成",
diff --git a/app/javascript/mastodon/locales/ka.json b/app/javascript/mastodon/locales/ka.json
index a01b2290c..c6c72b6ce 100644
--- a/app/javascript/mastodon/locales/ka.json
+++ b/app/javascript/mastodon/locales/ka.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "უპს!",
   "announcement.announcement": "Announcement",
   "attachments_list.unprocessed": "(unprocessed)",
+  "audio.hide": "Hide audio",
   "autosuggest_hashtag.per_week": "კვირაში {count}",
   "boost_modal.combo": "შეგიძლიათ დააჭიროთ {combo}-ს რათა შემდეგ ჯერზე გამოტოვოთ ეს",
   "bundle_column_error.body": "ამ კომპონენტის ჩატვირთვისას რაღაც აირია.",
@@ -196,6 +197,22 @@
   "explore.trending_links": "News",
   "explore.trending_statuses": "Posts",
   "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",
   "follow_recommendations.done": "Done",
   "follow_recommendations.heading": "Follow people you'd like to see posts from! Here are some suggestions.",
   "follow_recommendations.lead": "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!",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "Edited {count, plural, one {{count} time} other {{count} times}}",
   "status.embed": "ჩართვა",
   "status.favourite": "ფავორიტი",
+  "status.filter": "Filter this post",
   "status.filtered": "ფილტრირებული",
   "status.hide": "Hide toot",
   "status.history.created": "{name} created {date}",
diff --git a/app/javascript/mastodon/locales/kab.json b/app/javascript/mastodon/locales/kab.json
index d5ab20008..035ec7c84 100644
--- a/app/javascript/mastodon/locales/kab.json
+++ b/app/javascript/mastodon/locales/kab.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Ayhuh!",
   "announcement.announcement": "Ulɣu",
   "attachments_list.unprocessed": "(unprocessed)",
+  "audio.hide": "Hide audio",
   "autosuggest_hashtag.per_week": "{count} i yimalas",
   "boost_modal.combo": "Tzemreḍ ad tetekkiḍ ɣef {combo} akken ad tessurfeḍ aya tikelt-nniḍen",
   "bundle_column_error.body": "Tella-d kra n tuccḍa mi d-yettali ugbur-agi.",
@@ -196,6 +197,22 @@
   "explore.trending_links": "News",
   "explore.trending_statuses": "Tisuffaɣ",
   "explore.trending_tags": "Ihacṭagen",
+  "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",
   "follow_recommendations.done": "Immed",
   "follow_recommendations.heading": "Follow people you'd like to see posts from! Here are some suggestions.",
   "follow_recommendations.lead": "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!",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "Edited {count, plural, one {{count} time} other {{count} times}}",
   "status.embed": "Seddu",
   "status.favourite": "Rnu ɣer yismenyifen",
+  "status.filter": "Filter this post",
   "status.filtered": "Yettwasizdeg",
   "status.hide": "Hide toot",
   "status.history.created": "{name} created {date}",
diff --git a/app/javascript/mastodon/locales/kk.json b/app/javascript/mastodon/locales/kk.json
index 5334331c4..edcf0650c 100644
--- a/app/javascript/mastodon/locales/kk.json
+++ b/app/javascript/mastodon/locales/kk.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Өй!",
   "announcement.announcement": "Хабарландыру",
   "attachments_list.unprocessed": "(unprocessed)",
+  "audio.hide": "Hide audio",
   "autosuggest_hashtag.per_week": "{count} аптасына",
   "boost_modal.combo": "Келесіде өткізіп жіберу үшін басыңыз {combo}",
   "bundle_column_error.body": "Бұл компонентті жүктеген кезде бір қате пайда болды.",
@@ -196,6 +197,22 @@
   "explore.trending_links": "News",
   "explore.trending_statuses": "Posts",
   "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",
   "follow_recommendations.done": "Done",
   "follow_recommendations.heading": "Follow people you'd like to see posts from! Here are some suggestions.",
   "follow_recommendations.lead": "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!",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "Edited {count, plural, one {{count} time} other {{count} times}}",
   "status.embed": "Embеd",
   "status.favourite": "Таңдаулы",
+  "status.filter": "Filter this post",
   "status.filtered": "Фильтрленген",
   "status.hide": "Hide toot",
   "status.history.created": "{name} created {date}",
diff --git a/app/javascript/mastodon/locales/kn.json b/app/javascript/mastodon/locales/kn.json
index bde13c04c..3d2e0a68d 100644
--- a/app/javascript/mastodon/locales/kn.json
+++ b/app/javascript/mastodon/locales/kn.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "ಅಯ್ಯೋ!",
   "announcement.announcement": "Announcement",
   "attachments_list.unprocessed": "(unprocessed)",
+  "audio.hide": "Hide audio",
   "autosuggest_hashtag.per_week": "{count} per week",
   "boost_modal.combo": "You can press {combo} to skip this next time",
   "bundle_column_error.body": "Something went wrong while loading this component.",
@@ -196,6 +197,22 @@
   "explore.trending_links": "News",
   "explore.trending_statuses": "Posts",
   "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",
   "follow_recommendations.done": "Done",
   "follow_recommendations.heading": "Follow people you'd like to see posts from! Here are some suggestions.",
   "follow_recommendations.lead": "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!",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "Edited {count, plural, one {{count} time} other {{count} times}}",
   "status.embed": "Embed",
   "status.favourite": "Favourite",
+  "status.filter": "Filter this post",
   "status.filtered": "Filtered",
   "status.hide": "Hide toot",
   "status.history.created": "{name} created {date}",
diff --git a/app/javascript/mastodon/locales/ko.json b/app/javascript/mastodon/locales/ko.json
index 30cf08ff2..e5dfc7689 100644
--- a/app/javascript/mastodon/locales/ko.json
+++ b/app/javascript/mastodon/locales/ko.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "앗!",
   "announcement.announcement": "공지사항",
   "attachments_list.unprocessed": "(처리 안 됨)",
+  "audio.hide": "소리 숨기기",
   "autosuggest_hashtag.per_week": "주간 {count}회",
   "boost_modal.combo": "다음엔 {combo}를 눌러서 이 과정을 건너뛸 수 있습니다",
   "bundle_column_error.body": "컴포넌트를 불러오는 과정에서 문제가 발생했습니다.",
@@ -196,6 +197,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",
   "follow_recommendations.done": "완료",
   "follow_recommendations.heading": "게시물을 받아 볼 사람들을 팔로우 하세요! 여기 몇몇의 추천이 있습니다.",
   "follow_recommendations.lead": "당신이 팔로우 하는 사람들의 게시물이 시간순으로 정렬되어 당신의 홈 피드에 표시될 것입니다. 실수를 두려워 하지 마세요, 언제든지 쉽게 팔로우 취소를 할 수 있습니다!",
@@ -220,9 +237,9 @@
   "hashtag.column_settings.tag_mode.any": "아무것이든",
   "hashtag.column_settings.tag_mode.none": "이것들을 제외하고",
   "hashtag.column_settings.tag_toggle": "추가 해시태그를 이 컬럼에 추가합니다",
-  "hashtag.follow": "Follow hashtag",
+  "hashtag.follow": "해시태그 팔로우",
   "hashtag.total_volume": "최근 {days}일 동안의 총 사용량",
-  "hashtag.unfollow": "Unfollow hashtag",
+  "hashtag.unfollow": "해시태그 팔로우 해제",
   "home.column_settings.basic": "기본",
   "home.column_settings.show_reblogs": "부스트 표시",
   "home.column_settings.show_replies": "답글 표시",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "{count}번 수정됨",
   "status.embed": "공유하기",
   "status.favourite": "좋아요",
+  "status.filter": "Filter this post",
   "status.filtered": "필터로 걸러짐",
   "status.hide": "툿 숨기기",
   "status.history.created": "{name} 님이 {date}에 생성함",
diff --git a/app/javascript/mastodon/locales/ku.json b/app/javascript/mastodon/locales/ku.json
index d8c4151d3..27033efbf 100644
--- a/app/javascript/mastodon/locales/ku.json
+++ b/app/javascript/mastodon/locales/ku.json
@@ -17,28 +17,28 @@
   "account.follow": "Bişopîne",
   "account.followers": "Şopîner",
   "account.followers.empty": "Kesekî hin ev bikarhêner neşopandiye.",
-  "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
+  "account.followers_counter": "{count, plural, one {{counter} Şopîner} other {{counter} Şopîner}}",
   "account.following": "Dişopîne",
   "account.following_counter": "{count, plural, one {{counter} Dişopîne} other {{counter} Dişopîne}}",
   "account.follows.empty": "Ev bikarhêner hin kesekî heya niha neşopandiye.",
   "account.follows_you": "Te dişopîne",
   "account.hide_reblogs": "Bilindkirinên ji @{name} veşêre",
-  "account.joined": "Tevlîbû di {date} de",
+  "account.joined": "Di {date} de tevlî bû",
   "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.media": "Medya",
   "account.mention": "Qal @{name} bike",
   "account.moved_to": "{name} hate livandin bo:",
-  "account.mute": "@{name} Bêdeng bike",
+  "account.mute": "@{name} bêdeng bike",
   "account.mute_notifications": "Agahdariyan ji @{name} bêdeng bike",
   "account.muted": "Bêdengkirî",
   "account.posts": "Şandî",
   "account.posts_with_replies": "Şandî û bersiv",
-  "account.report": "@{name} Ragihîne",
+  "account.report": "@{name} ragihîne",
   "account.requested": "Li benda erêkirinê ye. Ji bo betal kirina daxwazê pêl bikin",
   "account.share": "Profîla @{name} parve bike",
   "account.show_reblogs": "Bilindkirinên ji @{name} nîşan bike",
-  "account.statuses_counter": "{count, plural,one {{counter} şandî}other {{counter} şandî}}",
+  "account.statuses_counter": "{count, plural,one {{counter} Şandî}other {{counter} Şandî}}",
   "account.unblock": "Astengê li ser @{name} rake",
   "account.unblock_domain": "Astengê li ser navperê {domain} rake",
   "account.unblock_short": "Astengiyê rake",
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Wey li min!",
   "announcement.announcement": "Daxuyanî",
   "attachments_list.unprocessed": "(bêpêvajo)",
+  "audio.hide": "Dengê veşêre",
   "autosuggest_hashtag.per_week": "Her hefte {count}",
   "boost_modal.combo": "Ji bo derbas bî carekî din de pêlê {combo} bike",
   "bundle_column_error.body": "Di dema barkirina vê hêmanê de tiştek çewt çê bû.",
@@ -75,12 +76,12 @@
   "column.domain_blocks": "Navperên astengkirî",
   "column.favourites": "Bijarte",
   "column.follow_requests": "Daxwazên şopandinê",
-  "column.home": "Serrûpel",
+  "column.home": "Rûpela sereke",
   "column.lists": "Rêzok",
   "column.mutes": "Bikarhênerên bêdengkirî",
   "column.notifications": "Agahdarî",
   "column.pins": "Şandiya derzîkirî",
-  "column.public": "Demnameyê federalîkirî",
+  "column.public": "Demnameya giştî",
   "column_back_button.label": "Vegere",
   "column_header.hide_settings": "Sazkariyan veşêre",
   "column_header.moveLeft_settings": "Stûnê bilivîne bo çepê",
@@ -167,12 +168,12 @@
   "empty_column.account_timeline": "Li vir şandî tune!",
   "empty_column.account_unavailable": "Profîl nayê peydakirin",
   "empty_column.blocks": "Te tu bikarhêner asteng nekiriye.",
-  "empty_column.bookmarked_statuses": "Hîn tu peyamên şûnpelkirî tuneye. Gava ku hûn yek şûnpel bikin, ew ê li vir xûya bike.",
+  "empty_column.bookmarked_statuses": "Hîn tu peyamên te yên şûnpelkirî tune ne. Dema ku tu yekî şûnpel bikî, ew ê li vir xuya bibe.",
   "empty_column.community": "Demnameya herêmî vala ye. Tiştek ji raya giştî re binivsînin da ku rûpel biherike!",
-  "empty_column.direct": "Hêj peyameke te yê rasterast tuneye. Gava ku tu yekî bişeynî an jî bigirî, ew ê li vir xûya bike.",
+  "empty_column.direct": "Hîn peyamên te yên rasterast tune ne. Dema ku tu yekî bişînî an jî wergirî, ew ê li vir xuya bibe.",
   "empty_column.domain_blocks": "Hê jî navperên hatine asteng kirin tune ne.",
   "empty_column.explore_statuses": "Tiştek niha di rojevê de tune. Paşê vegere!",
-  "empty_column.favourited_statuses": "Hîn tu peyamên te yên bijare tunene. Gava ku te yekî bijart, ew ê li vir xûya bike.",
+  "empty_column.favourited_statuses": "Hîn tu peyamên te yên bijarte tune ne. Dema ku te yekî bijart, ew ê li vir xuya bibe.",
   "empty_column.favourites": "Hîn tu kes vê peyamê nebijartiye. Gava ku hin kes bijartin, ew ê li vir xûya bikin.",
   "empty_column.follow_recommendations": "Wusa dixuye ku ji bo we tu pêşniyar nehatine çêkirin. Hûn dikarin lêgerînê bikarbînin da ku li kesên ku hûn nas dikin bigerin an hashtagên trendî bigerin.",
   "empty_column.follow_requests": "Hê jî daxwaza şopandinê tunne ye. Dema daxwazek hat, yê li vir were nîşan kirin.",
@@ -180,7 +181,7 @@
   "empty_column.home": "Demnameya mala we vala ye! Ji bona tijîkirinê bêtir mirovan bişopînin. {suggestions}",
   "empty_column.home.suggestions": "Hinek pêşniyaran bibîne",
   "empty_column.list": "Di vê rêzokê de hîn tiştek tune ye. Gava ku endamên vê rêzokê peyamên nû biweşînin, ew ê li vir xuya bibin.",
-  "empty_column.lists": "Hêj qet rêzokê te tunne ye. Dema yek peyda bû, yê li vir were nîşan kirin.",
+  "empty_column.lists": "Hîn tu rêzokên te tune ne. Dema yekî çê bikî, ew ê li vir xuya bibe.",
   "empty_column.mutes": "Te tu bikarhêner bêdeng nekiriye.",
   "empty_column.notifications": "Hêj hişyariyên te tunene. Dema ku mirovên din bi we re têkilî danîn, hûn ê wê li vir bibînin.",
   "empty_column.public": "Li vir tiştekî tuneye! Ji raya giştî re tiştekî binivîsîne, an ji bo tijîkirinê ji rajekerên din bikarhêneran bi destan bişopînin",
@@ -196,6 +197,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",
   "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î!",
@@ -220,9 +237,9 @@
   "hashtag.column_settings.tag_mode.any": "Yek ji van",
   "hashtag.column_settings.tag_mode.none": "Ne yek ji van",
   "hashtag.column_settings.tag_toggle": "Ji bo vê stûnê hin pêvekan tevlî bike",
-  "hashtag.follow": "Follow hashtag",
+  "hashtag.follow": "Hashtagê bişopîne",
   "hashtag.total_volume": "Tevahiya giraniyê dawîn di {days, plural, one {roj} other {{days} roj}} de",
-  "hashtag.unfollow": "Unfollow hashtag",
+  "hashtag.unfollow": "Hashtagê neşopîne",
   "home.column_settings.basic": "Bingehîn",
   "home.column_settings.show_reblogs": "Bilindkirinan nîşan bike",
   "home.column_settings.show_replies": "Bersivan nîşan bide",
@@ -242,10 +259,10 @@
   "keyboard_shortcuts.enter": "Şandiyê veke",
   "keyboard_shortcuts.favourite": "Şandiya bijarte",
   "keyboard_shortcuts.favourites": "Rêzokên bijarte veke",
-  "keyboard_shortcuts.federated": "Demnameyê federalîkirî veke",
+  "keyboard_shortcuts.federated": "Demnameya giştî veke",
   "keyboard_shortcuts.heading": "Kurterêyên klavyeyê",
   "keyboard_shortcuts.home": "Demnameyê veke",
-  "keyboard_shortcuts.hotkey": "Bişkoka kurterê",
+  "keyboard_shortcuts.hotkey": "Kurte bişkok",
   "keyboard_shortcuts.legend": "Vê çîrokê nîşan bike",
   "keyboard_shortcuts.local": "Demnameya herêmî veke",
   "keyboard_shortcuts.mention": "Qala nivîskarî/ê bike",
@@ -271,7 +288,7 @@
   "lightbox.next": "Pêş",
   "lightbox.previous": "Paş",
   "limited_account_hint.action": "Bi heman awayî profîlê nîşan bide",
-  "limited_account_hint.title": "Ev profîl ji aliyê çavêriya li ser rajekarê te hatiye veşartin.",
+  "limited_account_hint.title": "Ev profîl ji aliyê çavdêriya li ser rajekarê te hatiye veşartin.",
   "lists.account.add": "Tevlî rêzokê bike",
   "lists.account.remove": "Ji rêzokê rake",
   "lists.delete": "Rêzokê jê bibe",
@@ -293,7 +310,7 @@
   "mute_modal.duration": "Dem",
   "mute_modal.hide_notifications": "Agahdariyan ji ev bikarhêner veşêre?",
   "mute_modal.indefinite": "Nediyar",
-  "navigation_bar.apps": "Sepana mobîl",
+  "navigation_bar.apps": "Sepana mobayil",
   "navigation_bar.blocks": "Bikarhênerên astengkirî",
   "navigation_bar.bookmarks": "Şûnpel",
   "navigation_bar.community_timeline": "Demnameya herêmî",
@@ -308,14 +325,14 @@
   "navigation_bar.follow_requests": "Daxwazên şopandinê",
   "navigation_bar.follows_and_followers": "Şopandin û şopîner",
   "navigation_bar.info": "Derbarê vî rajekarî",
-  "navigation_bar.keyboard_shortcuts": "Bişkoka kurterê",
+  "navigation_bar.keyboard_shortcuts": "Kurte bişkok",
   "navigation_bar.lists": "Rêzok",
   "navigation_bar.logout": "Derkeve",
   "navigation_bar.mutes": "Bikarhênerên bêdengkirî",
   "navigation_bar.personal": "Kesanî",
   "navigation_bar.pins": "Şandiya derzîkirî",
   "navigation_bar.preferences": "Sazkarî",
-  "navigation_bar.public_timeline": "Demnameyê federalîkirî",
+  "navigation_bar.public_timeline": "Demnameya giştî",
   "navigation_bar.security": "Ewlehî",
   "notification.admin.report": "{name} hate ragihandin {target}",
   "notification.admin.sign_up": "{name} tomar bû",
@@ -386,7 +403,7 @@
   "privacy.unlisted.short": "Nerêzok",
   "refresh": "Nû bike",
   "regeneration_indicator.label": "Tê barkirin…",
-  "regeneration_indicator.sublabel": "Mala te da tê amedekirin!",
+  "regeneration_indicator.sublabel": "Naveroka rûpela sereke ya te tê amedekirin!",
   "relative_time.days": "{number}r",
   "relative_time.full.days": "{number, plural, one {# roj} other {# roj}} berê",
   "relative_time.full.hours": "{number, plural, one {# demjimêr} other {# demjimêr}} berê",
@@ -411,7 +428,7 @@
   "report.close": "Qediya",
   "report.comment.title": "Tiştek din heye ku tu difikirî ku divê em zanibin?",
   "report.forward": "Biçe bo {target}",
-  "report.forward_hint": "Ajimêr ji rajekarek din da ne. Tu kopîyeka anonîm ya raporê bişînî li wur?",
+  "report.forward_hint": "Ajimêr ji rajekareke din e. Tu kopîyeka anonîm ya raporê bişînî wir jî?",
   "report.mute": "Bêdeng bike",
   "report.mute_explanation": "Tê yê şandiyên wan nebînî. Ew hin jî dikarin te bişopînin û şandiyên te bibînin û wê nizanibin ku ew hatine bêdengkirin.",
   "report.next": "Pêş",
@@ -436,7 +453,7 @@
   "report.thanks.title_actionable": "Spas ji bo ragihandina te, em ê binirxînin.",
   "report.unfollow": "@{name} neşopîne",
   "report.unfollow_explanation": "Tê vê ajimêrê dişopînî. Ji bo ku êdî şandiyên wan di rojeva xwe de nebînî, wan neşopîne.",
-  "report_notification.attached_statuses": "{count, plural,one {{count} şandî} other {{count} şandî }} pêvekirî",
+  "report_notification.attached_statuses": "{count, plural,one {{count} şandî} other {{count} şandî}} pêvekirî",
   "report_notification.categories.other": "Ên din",
   "report_notification.categories.spam": "Nexwestî (Spam)",
   "report_notification.categories.violation": "Binpêkirina rêzîkê",
@@ -470,6 +487,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.filtered": "Parzûnkirî",
   "status.hide": "Şandiyê veşêre",
   "status.history.created": "{name} {date} afirand",
@@ -492,13 +510,13 @@
   "status.remove_bookmark": "Şûnpêlê jê rake",
   "status.reply": "Bersivê bide",
   "status.replyAll": "Mijarê bibersivîne",
-  "status.report": "{name} gilî bike",
+  "status.report": "@{name} ragihîne",
   "status.sensitive_warning": "Naveroka hestiyarî",
   "status.share": "Parve bike",
   "status.show_filter_reason": "Bi her awayî nîşan bide",
   "status.show_less": "Kêmtir nîşan bide",
   "status.show_less_all": "Ji bo hemîyan kêmtir nîşan bide",
-  "status.show_more": "Hêj zehftir 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_thread": "Mijarê nîşan bide",
   "status.uncached_media_warning": "Tune ye",
@@ -507,7 +525,7 @@
   "suggestions.dismiss": "Pêşniyarê paşguh bike",
   "suggestions.header": "Dibe ku bala te bikşîne…",
   "tabs_bar.federated_timeline": "Giştî",
-  "tabs_bar.home": "Serrûpel",
+  "tabs_bar.home": "Rûpela sereke",
   "tabs_bar.local_timeline": "Herêmî",
   "tabs_bar.notifications": "Agahdarî",
   "tabs_bar.search": "Bigere",
diff --git a/app/javascript/mastodon/locales/kw.json b/app/javascript/mastodon/locales/kw.json
index 988655921..f6a85a932 100644
--- a/app/javascript/mastodon/locales/kw.json
+++ b/app/javascript/mastodon/locales/kw.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Oups!",
   "announcement.announcement": "Deklaryans",
   "attachments_list.unprocessed": "(unprocessed)",
+  "audio.hide": "Hide audio",
   "autosuggest_hashtag.per_week": "{count} an seythen",
   "boost_modal.combo": "Hwi a yll gwaska {combo} dhe woheles hemma an nessa tro",
   "bundle_column_error.body": "Neppyth eth yn kamm ow karga'n elven ma.",
@@ -196,6 +197,22 @@
   "explore.trending_links": "News",
   "explore.trending_statuses": "Posts",
   "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",
   "follow_recommendations.done": "Gwrys",
   "follow_recommendations.heading": "Holyewgh tus a vynnowgh gweles postow anedha! Ottomma nebes profyansow.",
   "follow_recommendations.lead": "Postow a dus a holyewgh a wra omdhiskwedhes omma yn aray termynel yn agas lin dre. Na borthewgh own a gammwul, hwi a yll p'eurpynag anholya tus mar es poran!",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "Edited {count, plural, one {{count} time} other {{count} times}}",
   "status.embed": "Staga",
   "status.favourite": "Merkya vel drudh",
+  "status.filter": "Filter this post",
   "status.filtered": "Sidhlys",
   "status.hide": "Hide toot",
   "status.history.created": "{name} created {date}",
diff --git a/app/javascript/mastodon/locales/lt.json b/app/javascript/mastodon/locales/lt.json
index 3df14c833..4e238273e 100644
--- a/app/javascript/mastodon/locales/lt.json
+++ b/app/javascript/mastodon/locales/lt.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Oi!",
   "announcement.announcement": "Announcement",
   "attachments_list.unprocessed": "(unprocessed)",
+  "audio.hide": "Hide audio",
   "autosuggest_hashtag.per_week": "{count} per week",
   "boost_modal.combo": "You can press {combo} to skip this next time",
   "bundle_column_error.body": "Something went wrong while loading this component.",
@@ -196,6 +197,22 @@
   "explore.trending_links": "News",
   "explore.trending_statuses": "Posts",
   "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",
   "follow_recommendations.done": "Done",
   "follow_recommendations.heading": "Follow people you'd like to see posts from! Here are some suggestions.",
   "follow_recommendations.lead": "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!",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "Edited {count, plural, one {{count} time} other {{count} times}}",
   "status.embed": "Embed",
   "status.favourite": "Favourite",
+  "status.filter": "Filter this post",
   "status.filtered": "Filtered",
   "status.hide": "Hide toot",
   "status.history.created": "{name} created {date}",
diff --git a/app/javascript/mastodon/locales/lv.json b/app/javascript/mastodon/locales/lv.json
index 1cb0095b1..1912dd7db 100644
--- a/app/javascript/mastodon/locales/lv.json
+++ b/app/javascript/mastodon/locales/lv.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Ups!",
   "announcement.announcement": "Paziņojums",
   "attachments_list.unprocessed": "(neapstrādāti)",
+  "audio.hide": "Slēpt audio",
   "autosuggest_hashtag.per_week": "{count} nedēļā",
   "boost_modal.combo": "Nospied {combo} lai izlaistu šo nākamreiz",
   "bundle_column_error.body": "Kaut kas nogāja greizi ielādējot šo komponenti.",
@@ -196,6 +197,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",
   "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ā!",
@@ -220,9 +237,9 @@
   "hashtag.column_settings.tag_mode.any": "Kāds no šiem",
   "hashtag.column_settings.tag_mode.none": "Neviens no šiem",
   "hashtag.column_settings.tag_toggle": "Iekļaut šai kolonnai papildu tagus",
-  "hashtag.follow": "Follow hashtag",
+  "hashtag.follow": "Seko mirkļbirkai",
   "hashtag.total_volume": "Kopējais apjoms par {days, plural, one {dienu} other {{days} dienām}}",
-  "hashtag.unfollow": "Unfollow hashtag",
+  "hashtag.unfollow": "Pārstāj sekot mirkļbirkai",
   "home.column_settings.basic": "Pamata",
   "home.column_settings.show_reblogs": "Rādīt palielinājumus",
   "home.column_settings.show_replies": "Rādīt atbildes",
@@ -470,6 +487,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.filtered": "Filtrēts",
   "status.hide": "Slēpt",
   "status.history.created": "{name} izveidots {date}",
diff --git a/app/javascript/mastodon/locales/mk.json b/app/javascript/mastodon/locales/mk.json
index faf4174f9..d782dff64 100644
--- a/app/javascript/mastodon/locales/mk.json
+++ b/app/javascript/mastodon/locales/mk.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Упс!",
   "announcement.announcement": "Announcement",
   "attachments_list.unprocessed": "(unprocessed)",
+  "audio.hide": "Hide audio",
   "autosuggest_hashtag.per_week": "{count} неделно",
   "boost_modal.combo": "Кликни {combo} за да го прескокниш ова нареден пат",
   "bundle_column_error.body": "Се случи проблем при вчитувањето.",
@@ -196,6 +197,22 @@
   "explore.trending_links": "News",
   "explore.trending_statuses": "Posts",
   "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",
   "follow_recommendations.done": "Done",
   "follow_recommendations.heading": "Follow people you'd like to see posts from! Here are some suggestions.",
   "follow_recommendations.lead": "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!",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "Edited {count, plural, one {{count} time} other {{count} times}}",
   "status.embed": "Embed",
   "status.favourite": "Favourite",
+  "status.filter": "Filter this post",
   "status.filtered": "Filtered",
   "status.hide": "Hide toot",
   "status.history.created": "{name} created {date}",
diff --git a/app/javascript/mastodon/locales/ml.json b/app/javascript/mastodon/locales/ml.json
index 175316e84..37969475d 100644
--- a/app/javascript/mastodon/locales/ml.json
+++ b/app/javascript/mastodon/locales/ml.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "ശ്ശോ!",
   "announcement.announcement": "അറിയിപ്പ്",
   "attachments_list.unprocessed": "(unprocessed)",
+  "audio.hide": "Hide audio",
   "autosuggest_hashtag.per_week": "ആഴ്ച തോറും {count}",
   "boost_modal.combo": "അടുത്ത തവണ ഇത് ഒഴിവാക്കുവാൻ {combo} ഞെക്കാവുന്നതാണ്",
   "bundle_column_error.body": "ഈ ഘടകം പ്രദശിപ്പിക്കുമ്പോൾ എന്തോ കുഴപ്പം സംഭവിച്ചു.",
@@ -196,6 +197,22 @@
   "explore.trending_links": "News",
   "explore.trending_statuses": "Posts",
   "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",
   "follow_recommendations.done": "പൂര്‍ത്തിയായീ",
   "follow_recommendations.heading": "Follow people you'd like to see posts from! Here are some suggestions.",
   "follow_recommendations.lead": "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!",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "Edited {count, plural, one {{count} time} other {{count} times}}",
   "status.embed": "ഉൾച്ചേർക്കുക",
   "status.favourite": "പ്രിയപ്പെട്ടത്",
+  "status.filter": "Filter this post",
   "status.filtered": "ഫിൽട്ടർ ചെയ്‌തു",
   "status.hide": "Hide toot",
   "status.history.created": "{name} created {date}",
diff --git a/app/javascript/mastodon/locales/mr.json b/app/javascript/mastodon/locales/mr.json
index 762d94c40..09eaea3f9 100644
--- a/app/javascript/mastodon/locales/mr.json
+++ b/app/javascript/mastodon/locales/mr.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "अरेरे!",
   "announcement.announcement": "Announcement",
   "attachments_list.unprocessed": "(unprocessed)",
+  "audio.hide": "Hide audio",
   "autosuggest_hashtag.per_week": "{count} प्रतिसप्ताह",
   "boost_modal.combo": "You can press {combo} to skip this next time",
   "bundle_column_error.body": "हा घटक लोड करतांना काहीतरी चुकले आहे.",
@@ -196,6 +197,22 @@
   "explore.trending_links": "News",
   "explore.trending_statuses": "Posts",
   "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",
   "follow_recommendations.done": "Done",
   "follow_recommendations.heading": "Follow people you'd like to see posts from! Here are some suggestions.",
   "follow_recommendations.lead": "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!",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "Edited {count, plural, one {{count} time} other {{count} times}}",
   "status.embed": "Embed",
   "status.favourite": "Favourite",
+  "status.filter": "Filter this post",
   "status.filtered": "Filtered",
   "status.hide": "Hide toot",
   "status.history.created": "{name} created {date}",
diff --git a/app/javascript/mastodon/locales/ms.json b/app/javascript/mastodon/locales/ms.json
index 13a1e3345..6a1302329 100644
--- a/app/javascript/mastodon/locales/ms.json
+++ b/app/javascript/mastodon/locales/ms.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Alamak!",
   "announcement.announcement": "Pengumuman",
   "attachments_list.unprocessed": "(unprocessed)",
+  "audio.hide": "Hide audio",
   "autosuggest_hashtag.per_week": "{count} seminggu",
   "boost_modal.combo": "Anda boleh tekan {combo} untuk melangkauinya pada waktu lain",
   "bundle_column_error.body": "Terdapat kesilapan ketika memuatkan komponen ini.",
@@ -196,6 +197,22 @@
   "explore.trending_links": "News",
   "explore.trending_statuses": "Posts",
   "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",
   "follow_recommendations.done": "Selesai",
   "follow_recommendations.heading": "Ikuti orang yang anda ingin lihat hantarannya! Di sini ada beberapa cadangan.",
   "follow_recommendations.lead": "Hantaran daripada orang yang anda ikuti akan muncul dalam susunan kronologi di suapan rumah anda. Jangan takut melakukan kesilapan, anda boleh nyahikuti orang dengan mudah pada bila-bila masa!",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "Edited {count, plural, one {{count} time} other {{count} times}}",
   "status.embed": "Benaman",
   "status.favourite": "Kegemaran",
+  "status.filter": "Filter this post",
   "status.filtered": "Ditapis",
   "status.hide": "Hide toot",
   "status.history.created": "{name} created {date}",
diff --git a/app/javascript/mastodon/locales/nl.json b/app/javascript/mastodon/locales/nl.json
index e98dc6379..df59ee3f7 100644
--- a/app/javascript/mastodon/locales/nl.json
+++ b/app/javascript/mastodon/locales/nl.json
@@ -51,7 +51,7 @@
   "admin.dashboard.daily_retention": "Retentiegraad van gebruikers per dag, vanaf registratie",
   "admin.dashboard.monthly_retention": "Retentiegraad van gebruikers per maand, vanaf registratie",
   "admin.dashboard.retention.average": "Gemiddelde",
-  "admin.dashboard.retention.cohort": "Aanmeldingsmaand",
+  "admin.dashboard.retention.cohort": "Maand van registratie",
   "admin.dashboard.retention.cohort_size": "Nieuwe gebruikers",
   "alert.rate_limited.message": "Probeer het nog een keer na {retry_time, time, medium}.",
   "alert.rate_limited.title": "Beperkt te gebruiken",
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Oeps!",
   "announcement.announcement": "Mededeling",
   "attachments_list.unprocessed": "(niet verwerkt)",
+  "audio.hide": "Audio verbergen",
   "autosuggest_hashtag.per_week": "{count} per week",
   "boost_modal.combo": "Je kunt {combo} klikken om dit de volgende keer over te slaan",
   "bundle_column_error.body": "Tijdens het laden van dit onderdeel is er iets fout gegaan.",
@@ -172,8 +173,8 @@
   "empty_column.direct": "Je hebt nog geen directe berichten. Wanneer je er een verzend of ontvangt, komt deze hier te staan.",
   "empty_column.domain_blocks": "Er zijn nog geen geblokkeerde domeinen.",
   "empty_column.explore_statuses": "Momenteel zijn er geen trends. Kom later terug!",
-  "empty_column.favourited_statuses": "Jij hebt nog geen favoriete berichten. Wanneer je er een aan jouw favorieten toevoegt, valt deze hier te zien.",
-  "empty_column.favourites": "Niemand heeft dit bericht nog aan diens favorieten toegevoegd. Wanneer iemand dit doet, valt dat hier te zien.",
+  "empty_column.favourited_statuses": "Jij hebt nog geen favoriete berichten. Wanneer je een bericht als favoriet markeert, valt deze hier te zien.",
+  "empty_column.favourites": "Niemand heeft dit bericht nog als favoriet gemarkeerd. Wanneer iemand dit doet, valt dat hier te zien.",
   "empty_column.follow_recommendations": "Het lijkt er op dat er geen aanbevelingen voor jou aangemaakt kunnen worden. Je kunt proberen te zoeken naar mensen die je wellicht kent, zoeken op hashtags, de lokale en globale tijdlijnen bekijken of de gebruikersgids doorbladeren.",
   "empty_column.follow_requests": "Jij hebt nog enkel volgverzoek ontvangen. Wanneer je er eentje ontvangt, valt dat hier te zien.",
   "empty_column.hashtag": "Er is nog niks te vinden onder deze hashtag.",
@@ -196,6 +197,22 @@
   "explore.trending_links": "Nieuws",
   "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.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",
   "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!",
@@ -220,9 +237,9 @@
   "hashtag.column_settings.tag_mode.any": "Een van deze",
   "hashtag.column_settings.tag_mode.none": "Geen van deze",
   "hashtag.column_settings.tag_toggle": "Additionele tags aan deze kolom toevoegen",
-  "hashtag.follow": "Follow hashtag",
+  "hashtag.follow": "Hashtag volgen",
   "hashtag.total_volume": "Total volume in the last {days, plural, one {day} other {{days} days}}",
-  "hashtag.unfollow": "Unfollow hashtag",
+  "hashtag.unfollow": "Hashtag ontvolgen",
   "home.column_settings.basic": "Algemeen",
   "home.column_settings.show_reblogs": "Boosts tonen",
   "home.column_settings.show_replies": "Reacties tonen",
@@ -240,7 +257,7 @@
   "keyboard_shortcuts.direct": "Directe berichten tonen",
   "keyboard_shortcuts.down": "Naar beneden in de lijst bewegen",
   "keyboard_shortcuts.enter": "Volledig bericht tonen",
-  "keyboard_shortcuts.favourite": "Aan jouw favorieten toevoegen",
+  "keyboard_shortcuts.favourite": "Als favoriet markeren",
   "keyboard_shortcuts.favourites": "Favorieten tonen",
   "keyboard_shortcuts.federated": "Globale tijdlijn tonen",
   "keyboard_shortcuts.heading": "Sneltoetsen",
@@ -318,8 +335,8 @@
   "navigation_bar.public_timeline": "Globale tijdlijn",
   "navigation_bar.security": "Beveiliging",
   "notification.admin.report": "{name} heeft {target} geapporteerd",
-  "notification.admin.sign_up": "{name} heeft zich aangemeld",
-  "notification.favourite": "{name} voegde jouw bericht als favoriet toe",
+  "notification.admin.sign_up": "{name} heeft zich geregistreerd",
+  "notification.favourite": "{name} markeerde jouw bericht als favoriet",
   "notification.follow": "{name} volgt jou nu",
   "notification.follow_request": "{name} wil jou graag volgen",
   "notification.mention": "{name} vermeldde jou",
@@ -331,7 +348,7 @@
   "notifications.clear": "Meldingen verwijderen",
   "notifications.clear_confirmation": "Weet je het zeker dat je al jouw meldingen wilt verwijderen?",
   "notifications.column_settings.admin.report": "Nieuwe rapportages:",
-  "notifications.column_settings.admin.sign_up": "Nieuwe aanmeldingen:",
+  "notifications.column_settings.admin.sign_up": "Nieuwe registraties:",
   "notifications.column_settings.alert": "Desktopmeldingen",
   "notifications.column_settings.favourite": "Favorieten:",
   "notifications.column_settings.filter_bar.advanced": "Alle categorieën tonen",
@@ -470,6 +487,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.filtered": "Gefilterd",
   "status.hide": "Bericht verbergen",
   "status.history.created": "{name} plaatste dit {date}",
diff --git a/app/javascript/mastodon/locales/nn.json b/app/javascript/mastodon/locales/nn.json
index 1a8904cd2..33c06e11e 100644
--- a/app/javascript/mastodon/locales/nn.json
+++ b/app/javascript/mastodon/locales/nn.json
@@ -41,24 +41,25 @@
   "account.statuses_counter": "{count, plural, one {{counter} tut} other {{counter} tut}}",
   "account.unblock": "Slutt å blokera @{name}",
   "account.unblock_domain": "Vis {domain}",
-  "account.unblock_short": "Opphev blokkering",
+  "account.unblock_short": "Avblokker",
   "account.unendorse": "Ikkje framhev på profil",
   "account.unfollow": "Slutt å fylgja",
-  "account.unmute": "Av-demp @{name}",
+  "account.unmute": "Opphev målbinding av @{name}",
   "account.unmute_notifications": "Vis varsel frå @{name}",
-  "account.unmute_short": "Opphev demping",
+  "account.unmute_short": "Opphev målbinding",
   "account_note.placeholder": "Klikk for å leggja til merknad",
   "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": "Gjennomsnitt",
   "admin.dashboard.retention.cohort": "Sign-up month",
-  "admin.dashboard.retention.cohort_size": "Nye brukere",
+  "admin.dashboard.retention.cohort_size": "Nye brukarar",
   "alert.rate_limited.message": "Ver venleg å prøva igjen etter {retry_time, time, medium}.",
   "alert.rate_limited.title": "Begrensa rate",
   "alert.unexpected.message": "Eit uventa problem oppstod.",
   "alert.unexpected.title": "Oi sann!",
   "announcement.announcement": "Kunngjering",
   "attachments_list.unprocessed": "(unprocessed)",
+  "audio.hide": "Hide audio",
   "autosuggest_hashtag.per_week": "{count} per veke",
   "boost_modal.combo": "Du kan trykkja {combo} for å hoppa over dette neste gong",
   "bundle_column_error.body": "Noko gjekk gale mens denne komponenten vart lasta ned.",
@@ -70,7 +71,7 @@
   "column.blocks": "Blokkerte brukarar",
   "column.bookmarks": "Bokmerke",
   "column.community": "Lokal tidsline",
-  "column.direct": "Direct messages",
+  "column.direct": "Direktemeldingar",
   "column.directory": "Sjå gjennom profilar",
   "column.domain_blocks": "Gøymde domene",
   "column.favourites": "Favorittar",
@@ -92,10 +93,10 @@
   "community.column_settings.local_only": "Berre lokalt",
   "community.column_settings.media_only": "Berre media",
   "community.column_settings.remote_only": "Berre eksternt",
-  "compose.language.change": "Change language",
+  "compose.language.change": "Byt språk",
   "compose.language.search": "Search languages...",
   "compose_form.direct_message_warning_learn_more": "Lær meir",
-  "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": "Innlegg på Mastodon er ikkje ende-til-ende-krypterte. Ikkje del eventuell sensitiv informasjon via Mastodon.",
   "compose_form.hashtag_warning": "Dette tutet vert ikkje oppført under nokon emneknagg sidan det ikkje er oppført. Berre offentlege tut kan verta søkt etter med emneknagg.",
   "compose_form.lock_disclaimer": "Kontoen din er ikkje {locked}. Kven som helst kan fylgja deg for å sjå innlegga dine som berre visast til fylgjarar.",
   "compose_form.lock_disclaimer.lock": "låst",
@@ -108,7 +109,7 @@
   "compose_form.poll.switch_to_single": "Endra avstemninga til tillate berre eitt val",
   "compose_form.publish": "Publish",
   "compose_form.publish_loud": "{publish}!",
-  "compose_form.save_changes": "Save changes",
+  "compose_form.save_changes": "Lagre endringar",
   "compose_form.sensitive.hide": "Merk medium som sensitivt",
   "compose_form.sensitive.marked": "Medium er markert som sensitivt",
   "compose_form.sensitive.unmarked": "Medium er ikkje merka som sensitivt",
@@ -124,7 +125,7 @@
   "confirmations.delete_list.confirm": "Slett",
   "confirmations.delete_list.message": "Er du sikker på at du vil sletta denne lista for alltid?",
   "confirmations.discard_edit_media.confirm": "Forkast",
-  "confirmations.discard_edit_media.message": "You have unsaved changes to the media description or preview, discard them anyway?",
+  "confirmations.discard_edit_media.message": "Du har ulagra endringar i mediabeskrivinga eller førehandsvisinga. Vil du forkaste dei likevel?",
   "confirmations.domain_block.confirm": "Gøym heile domenet",
   "confirmations.domain_block.message": "Er du heilt, heilt sikker på at du vil blokkera heile {domain}? I dei fleste tilfelle er det godt nok og føretrekt med nokre få målretta blokkeringar eller målbindingar. Du kjem ikkje til å sjå innhald frå det domenet i nokon fødererte tidsliner eller i varsla dine. Fylgjarane dine frå det domenet vert fjerna.",
   "confirmations.logout.confirm": "Logg ut",
@@ -178,7 +179,7 @@
   "empty_column.follow_requests": "Du har ingen følgjeførespurnadar ennå. Når du får ein, så vil den dukke opp her.",
   "empty_column.hashtag": "Det er ingenting i denne emneknaggen ennå.",
   "empty_column.home": "Heime-tidslinja di er tom! Besøk {public} eller søk for å starte og å møte andre brukarar.",
-  "empty_column.home.suggestions": "Se noen forslag",
+  "empty_column.home.suggestions": "Sjå nokre forslag",
   "empty_column.list": "Det er ingenting i denne lista enno. Når medlemer av denne lista legg ut nye statusar, så dukkar dei opp her.",
   "empty_column.lists": "Du har ingen lister enno. Når du lagar ei, så dukkar ho opp her.",
   "empty_column.mutes": "Du har ikkje målbunde nokon brukarar enno.",
@@ -190,14 +191,30 @@
   "error.unexpected_crash.next_steps_addons": "Prøv å deaktivere dem og laste siden på nytt. Hvis det ikke hjelper, kan du fremdeles bruke Mastodon via en annen nettleser eller en annen app.",
   "errors.unexpected_crash.copy_stacktrace": "Kopier stacktrace til utklippstavla",
   "errors.unexpected_crash.report_issue": "Rapporter problem",
-  "explore.search_results": "Søkeresultater",
+  "explore.search_results": "Søkeresultat",
   "explore.suggested_follows": "For deg",
   "explore.title": "Utforsk",
-  "explore.trending_links": "Nyheter",
+  "explore.trending_links": "Nyheiter",
   "explore.trending_statuses": "Innlegg",
-  "explore.trending_tags": "Hashtags",
+  "explore.trending_tags": "Emneknaggar",
+  "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",
   "follow_recommendations.done": "Ferdig",
-  "follow_recommendations.heading": "Følg folk du ønsker å se innlegg fra! Her er noen forslag.",
+  "follow_recommendations.heading": "Fylg folk du ønsker å sjå innlegg frå! Her er nokre forslag.",
   "follow_recommendations.lead": "Innlegg fra mennesker du følger vil vises i kronologisk rekkefølge på hjemmefeed. Ikke vær redd for å gjøre feil, du kan slutte å følge folk like enkelt som alt!",
   "follow_request.authorize": "Autoriser",
   "follow_request.reject": "Avvis",
@@ -220,9 +237,9 @@
   "hashtag.column_settings.tag_mode.any": "Kva som helst av desse",
   "hashtag.column_settings.tag_mode.none": "Ikkje nokon av disse",
   "hashtag.column_settings.tag_toggle": "Inkluder ekstra emneknaggar for denne kolonna",
-  "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": "Fylg emneknagg",
+  "hashtag.total_volume": "Totalt volum siste {days, plural, one {dag} other {{days} dagar}}",
+  "hashtag.unfollow": "Slutt å fylgje emneknaggen",
   "home.column_settings.basic": "Enkelt",
   "home.column_settings.show_reblogs": "Vis framhevingar",
   "home.column_settings.show_replies": "Vis svar",
@@ -270,8 +287,8 @@
   "lightbox.expand": "Ekspander bildevisning boks",
   "lightbox.next": "Neste",
   "lightbox.previous": "Førre",
-  "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": "Vis profilen likevel",
+  "limited_account_hint.title": "Denne profilen har vorte skjult av moderatorane på tenaren din.",
   "lists.account.add": "Legg til i liste",
   "lists.account.remove": "Fjern frå liste",
   "lists.delete": "Slett liste",
@@ -280,7 +297,7 @@
   "lists.new.create": "Legg til liste",
   "lists.new.title_placeholder": "Ny listetittel",
   "lists.replies_policy.followed": "Enhver fulgt bruker",
-  "lists.replies_policy.list": "Medlemmer i listen",
+  "lists.replies_policy.list": "Medlem i lista",
   "lists.replies_policy.none": "Ikkje nokon",
   "lists.replies_policy.title": "Vis svar på:",
   "lists.search": "Søk gjennom folk du følgjer",
@@ -298,7 +315,7 @@
   "navigation_bar.bookmarks": "Bokmerke",
   "navigation_bar.community_timeline": "Lokal tidsline",
   "navigation_bar.compose": "Lag eit nytt tut",
-  "navigation_bar.direct": "Direct messages",
+  "navigation_bar.direct": "Direktemeldingar",
   "navigation_bar.discover": "Oppdag",
   "navigation_bar.domain_blocks": "Skjulte domene",
   "navigation_bar.edit_profile": "Rediger profil",
@@ -317,7 +334,7 @@
   "navigation_bar.preferences": "Innstillingar",
   "navigation_bar.public_timeline": "Føderert tidsline",
   "navigation_bar.security": "Tryggleik",
-  "notification.admin.report": "{name} reported {target}",
+  "notification.admin.report": "{name} rapporterte {target}",
   "notification.admin.sign_up": "{name} signed up",
   "notification.favourite": "{name} merkte statusen din som favoritt",
   "notification.follow": "{name} fylgde deg",
@@ -327,10 +344,10 @@
   "notification.poll": "Ei rundspørjing du har røysta i er ferdig",
   "notification.reblog": "{name} framheva statusen din",
   "notification.status": "{name} la nettopp ut",
-  "notification.update": "{name} edited a post",
+  "notification.update": "{name} redigerte eit innlegg",
   "notifications.clear": "Tøm varsel",
   "notifications.clear_confirmation": "Er du sikker på at du vil fjerna alle varsla dine for alltid?",
-  "notifications.column_settings.admin.report": "New reports:",
+  "notifications.column_settings.admin.report": "Nye rapportar:",
   "notifications.column_settings.admin.sign_up": "New sign-ups:",
   "notifications.column_settings.alert": "Skrivebordsvarsel",
   "notifications.column_settings.favourite": "Favorittar:",
@@ -346,9 +363,9 @@
   "notifications.column_settings.show": "Vis i kolonne",
   "notifications.column_settings.sound": "Spel av lyd",
   "notifications.column_settings.status": "Nye tuter:",
-  "notifications.column_settings.unread_notifications.category": "Unread notifications",
-  "notifications.column_settings.unread_notifications.highlight": "Highlight unread notifications",
-  "notifications.column_settings.update": "Redigeringer:",
+  "notifications.column_settings.unread_notifications.category": "Uleste varsel",
+  "notifications.column_settings.unread_notifications.highlight": "Marker uleste varsel",
+  "notifications.column_settings.update": "Redigeringar:",
   "notifications.filter.all": "Alle",
   "notifications.filter.boosts": "Framhevingar",
   "notifications.filter.favourites": "Favorittar",
@@ -372,15 +389,15 @@
   "poll.total_votes": "{count, plural, one {# røyst} other {# røyster}}",
   "poll.vote": "Røyst",
   "poll.voted": "Du røysta på dette svaret",
-  "poll.votes": "{votes, plural, one {# vote} other {# votes}}",
+  "poll.votes": "{votes, plural, one {# stemme} other {# stemmer}}",
   "poll_button.add_poll": "Start ei meiningsmåling",
   "poll_button.remove_poll": "Fjern røyst",
   "privacy.change": "Juster status-synlegheit",
   "privacy.direct.long": "Legg berre ut for nemnde brukarar",
-  "privacy.direct.short": "Direct",
+  "privacy.direct.short": "Kun nemnde personar",
   "privacy.private.long": "Post kun til følgjarar",
-  "privacy.private.short": "Followers-only",
-  "privacy.public.long": "Visible for all",
+  "privacy.private.short": "Kun fylgjarar",
+  "privacy.public.long": "Synleg for alle",
   "privacy.public.short": "Offentleg",
   "privacy.unlisted.long": "Visible for all, but opted-out of discovery features",
   "privacy.unlisted.short": "Uoppført",
@@ -388,11 +405,11 @@
   "regeneration_indicator.label": "Lastar…",
   "regeneration_indicator.sublabel": "Heimetidslinja di vert førebudd!",
   "relative_time.days": "{number}dg",
-  "relative_time.full.days": "{number, plural, one {# day} other {# days}} ago",
-  "relative_time.full.hours": "{number, plural, one {# hour} other {# hours}} ago",
-  "relative_time.full.just_now": "just now",
-  "relative_time.full.minutes": "{number, plural, one {# minute} other {# minutes}} ago",
-  "relative_time.full.seconds": "{number, plural, one {# second} other {# seconds}} ago",
+  "relative_time.full.days": "{number, plural, one {# dag} other {# dagar}} sidan",
+  "relative_time.full.hours": "{number, plural, one {# time} other {# timar}} sidan",
+  "relative_time.full.just_now": "nettopp nå",
+  "relative_time.full.minutes": "{number, plural, one {# minutt} other {# minutt}} sidan",
+  "relative_time.full.seconds": "{number, plural, one {# sekund} other {# sekund}} sidan",
   "relative_time.hours": "{number}t",
   "relative_time.just_now": "nå",
   "relative_time.minutes": "{number}min",
@@ -400,46 +417,46 @@
   "relative_time.today": "i dag",
   "reply_indicator.cancel": "Avbryt",
   "report.block": "Blokker",
-  "report.block_explanation": "You will not see their posts. They will not be able to see your posts or follow you. They will be able to tell that they are blocked.",
-  "report.categories.other": "Other",
+  "report.block_explanation": "Du vil ikkje kunne sjå innlegga deira. Dei vil ikkje kunne sjå innlegga dine eller fylgje deg. Dei kan sjå at dei er blokkert.",
+  "report.categories.other": "Anna",
   "report.categories.spam": "Søppelpost",
-  "report.categories.violation": "Content violates one or more server rules",
-  "report.category.subtitle": "Choose the best match",
-  "report.category.title": "Tell us what's going on with this {type}",
+  "report.categories.violation": "Innhaldet bryt ei eller fleire regler for tenaren",
+  "report.category.subtitle": "Vel det som passar best",
+  "report.category.title": "Fortel oss kva som skjer med denne {type}",
   "report.category.title_account": "profil",
   "report.category.title_status": "innlegg",
-  "report.close": "Utført",
-  "report.comment.title": "Is there anything else you think we should know?",
+  "report.close": "Ferdig",
+  "report.comment.title": "Er det noko anna du meiner me bør vite?",
   "report.forward": "Vidaresend til {target}",
   "report.forward_hint": "Kontoen er frå ein annan tenar. Vil du senda ein anonymisert kopi av rapporten dit òg?",
-  "report.mute": "Demp",
+  "report.mute": "Målbind",
   "report.mute_explanation": "You will not see their posts. They can still follow you and see your posts and will not know that they are muted.",
   "report.next": "Neste",
   "report.placeholder": "Tilleggskommentarar",
-  "report.reasons.dislike": "Jeg liker det ikke",
-  "report.reasons.dislike_description": "It is not something you want to see",
-  "report.reasons.other": "It's something else",
-  "report.reasons.other_description": "The issue does not fit into other categories",
-  "report.reasons.spam": "Det er spam",
-  "report.reasons.spam_description": "Malicious links, fake engagement, or repetitive replies",
-  "report.reasons.violation": "It violates server rules",
-  "report.reasons.violation_description": "You are aware that it breaks specific rules",
+  "report.reasons.dislike": "Eg likar det ikkje",
+  "report.reasons.dislike_description": "Det er ikkje noko du ønsker å sjå",
+  "report.reasons.other": "Det er noko anna",
+  "report.reasons.other_description": "Problemet passar ikkje inn i dei andre kategoriane",
+  "report.reasons.spam": "Det er søppelpost",
+  "report.reasons.spam_description": "Skadelege lenker, falskt engasjement og gjentakande svar",
+  "report.reasons.violation": "Det bryt tenaren sine reglar",
+  "report.reasons.violation_description": "Du veit at den bryt spesifikke reglar",
   "report.rules.subtitle": "Select all that apply",
-  "report.rules.title": "Which rules are being violated?",
+  "report.rules.title": "Kva reglar vert brotne?",
   "report.statuses.subtitle": "Select all that apply",
   "report.statuses.title": "Are there any posts that back up this report?",
   "report.submit": "Send inn",
   "report.target": "Rapporterer {target}",
   "report.thanks.take_action": "Here are your options for controlling what you see on Mastodon:",
   "report.thanks.take_action_actionable": "While we review this, you can take action against @{name}:",
-  "report.thanks.title": "Don't want to see this?",
-  "report.thanks.title_actionable": "Thanks for reporting, we'll look into this.",
+  "report.thanks.title": "Vil du ikkje sjå dette?",
+  "report.thanks.title_actionable": "Takk for at du rapporterer, me skal sjå på dette.",
   "report.unfollow": "Unfollow @{name}",
   "report.unfollow_explanation": "You are following this account. To not see their posts in your home feed anymore, unfollow them.",
-  "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.violation": "Rule violation",
+  "report_notification.attached_statuses": "{count, plural, one {{count} innlegg} other {{count} innlegg}} lagt ved",
+  "report_notification.categories.other": "Anna",
+  "report_notification.categories.spam": "Søppelpost",
+  "report_notification.categories.violation": "Regelbrot",
   "report_notification.open": "Open report",
   "search.placeholder": "Søk",
   "search_popout.search_format": "Avansert søkeformat",
@@ -451,7 +468,7 @@
   "search_results.accounts": "Folk",
   "search_results.all": "All",
   "search_results.hashtags": "Emneknaggar",
-  "search_results.nothing_found": "Could not find anything for these search terms",
+  "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.total": "{count, number} {count, plural, one {treff} other {treff}}",
@@ -465,15 +482,16 @@
   "status.delete": "Slett",
   "status.detailed_status": "Detaljert samtalevisning",
   "status.direct": "Send melding til @{name}",
-  "status.edit": "Edit",
-  "status.edited": "Edited {date}",
-  "status.edited_x_times": "Edited {count, plural, one {{count} time} other {{count} times}}",
+  "status.edit": "Rediger",
+  "status.edited": "Redigert {date}",
+  "status.edited_x_times": "Redigert {count, plural, one {{count} gong} other {{count} gonger}}",
   "status.embed": "Bygg inn",
   "status.favourite": "Favoritt",
+  "status.filter": "Filter this post",
   "status.filtered": "Filtrert",
-  "status.hide": "Hide toot",
-  "status.history.created": "{name} created {date}",
-  "status.history.edited": "{name} edited {date}",
+  "status.hide": "Gøym innlegg",
+  "status.history.created": "{name} oppretta {date}",
+  "status.history.edited": "{name} redigerte {date}",
   "status.load_more": "Last inn meir",
   "status.media_hidden": "Medium gøymd",
   "status.mention": "Nemn @{name}",
@@ -495,7 +513,7 @@
   "status.report": "Rapporter @{name}",
   "status.sensitive_warning": "Sensitivt innhald",
   "status.share": "Del",
-  "status.show_filter_reason": "Show anyway",
+  "status.show_filter_reason": "Vis likevel",
   "status.show_less": "Vis mindre",
   "status.show_less_all": "Vis mindre for alle",
   "status.show_more": "Vis meir",
@@ -532,7 +550,7 @@
   "upload_error.poll": "Filopplasting ikkje tillate med meiningsmålingar.",
   "upload_form.audio_description": "Grei ut for folk med nedsett høyrsel",
   "upload_form.description": "Skildr for synshemja",
-  "upload_form.description_missing": "Ingen beskrivelse lagt til",
+  "upload_form.description_missing": "Inga beskriving er lagt til",
   "upload_form.edit": "Rediger",
   "upload_form.thumbnail": "Bytt miniatyrbilete",
   "upload_form.undo": "Slett",
diff --git a/app/javascript/mastodon/locales/no.json b/app/javascript/mastodon/locales/no.json
index 829be51a5..6e2783713 100644
--- a/app/javascript/mastodon/locales/no.json
+++ b/app/javascript/mastodon/locales/no.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Oi!",
   "announcement.announcement": "Kunngjøring",
   "attachments_list.unprocessed": "(unprocessed)",
+  "audio.hide": "Hide audio",
   "autosuggest_hashtag.per_week": "{count} per uke",
   "boost_modal.combo": "You kan trykke {combo} for å hoppe over dette neste gang",
   "bundle_column_error.body": "Noe gikk galt mens denne komponenten lastet.",
@@ -196,6 +197,22 @@
   "explore.trending_links": "Nyheter",
   "explore.trending_statuses": "Innlegg",
   "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",
   "follow_recommendations.done": "Utført",
   "follow_recommendations.heading": "Følg folk du ønsker å se innlegg fra! Her er noen forslag.",
   "follow_recommendations.lead": "Innlegg fra mennesker du følger vil vises i kronologisk rekkefølge på hjemmefeed. Ikke vær redd for å gjøre feil, du kan slutte å følge folk like enkelt som alt!",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "Edited {count, plural, one {{count} time} other {{count} times}}",
   "status.embed": "Bygge inn",
   "status.favourite": "Lik",
+  "status.filter": "Filter this post",
   "status.filtered": "Filtrert",
   "status.hide": "Hide toot",
   "status.history.created": "{name} created {date}",
diff --git a/app/javascript/mastodon/locales/oc.json b/app/javascript/mastodon/locales/oc.json
index b065b4e8f..fa3ef3967 100644
--- a/app/javascript/mastodon/locales/oc.json
+++ b/app/javascript/mastodon/locales/oc.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Ops !",
   "announcement.announcement": "Anóncia",
   "attachments_list.unprocessed": "(pas tractat)",
+  "audio.hide": "Hide audio",
   "autosuggest_hashtag.per_week": "{count} per setmana",
   "boost_modal.combo": "Podètz botar {combo} per passar aquò lo còp que ven",
   "bundle_column_error.body": "Quicòm a fach mèuca pendent lo cargament d’aqueste compausant.",
@@ -196,6 +197,22 @@
   "explore.trending_links": "Novèlas",
   "explore.trending_statuses": "Publicacions",
   "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",
   "follow_recommendations.done": "Acabat",
   "follow_recommendations.heading": "Follow people you'd like to see posts from! Here are some suggestions.",
   "follow_recommendations.lead": "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!",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "Modificat {count, plural, un {{count} còp} other {{count} còps}}",
   "status.embed": "Embarcar",
   "status.favourite": "Apondre als favorits",
+  "status.filter": "Filter this post",
   "status.filtered": "Filtrat",
   "status.hide": "Hide toot",
   "status.history.created": "{name} o creèt lo {date}",
diff --git a/app/javascript/mastodon/locales/pa.json b/app/javascript/mastodon/locales/pa.json
index 99fdcfd45..c77444bff 100644
--- a/app/javascript/mastodon/locales/pa.json
+++ b/app/javascript/mastodon/locales/pa.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Oops!",
   "announcement.announcement": "Announcement",
   "attachments_list.unprocessed": "(unprocessed)",
+  "audio.hide": "Hide audio",
   "autosuggest_hashtag.per_week": "{count} per week",
   "boost_modal.combo": "You can press {combo} to skip this next time",
   "bundle_column_error.body": "Something went wrong while loading this component.",
@@ -196,6 +197,22 @@
   "explore.trending_links": "News",
   "explore.trending_statuses": "Posts",
   "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",
   "follow_recommendations.done": "Done",
   "follow_recommendations.heading": "Follow people you'd like to see posts from! Here are some suggestions.",
   "follow_recommendations.lead": "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!",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "Edited {count, plural, one {{count} time} other {{count} times}}",
   "status.embed": "Embed",
   "status.favourite": "Favourite",
+  "status.filter": "Filter this post",
   "status.filtered": "Filtered",
   "status.hide": "Hide toot",
   "status.history.created": "{name} created {date}",
diff --git a/app/javascript/mastodon/locales/pl.json b/app/javascript/mastodon/locales/pl.json
index df7b5cb0d..9550b5b7f 100644
--- a/app/javascript/mastodon/locales/pl.json
+++ b/app/javascript/mastodon/locales/pl.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "O nie!",
   "announcement.announcement": "Ogłoszenie",
   "attachments_list.unprocessed": "(nieprzetworzone)",
+  "audio.hide": "Ukryj dźwięk",
   "autosuggest_hashtag.per_week": "{count} co tydzień",
   "boost_modal.combo": "Naciśnij {combo}, aby pominąć to następnym razem",
   "bundle_column_error.body": "Coś poszło nie tak podczas ładowania tego składnika.",
@@ -200,6 +201,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",
   "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!",
@@ -224,9 +241,9 @@
   "hashtag.column_settings.tag_mode.any": "Dowolne",
   "hashtag.column_settings.tag_mode.none": "Żadne",
   "hashtag.column_settings.tag_toggle": "Include additional tags in this column",
-  "hashtag.follow": "Follow hashtag",
+  "hashtag.follow": "Obserwuj hasztag",
   "hashtag.total_volume": "Całkowity wolumen w ciągu {days, plural, one {ostatniego dnia} other {ostatnich {days} dni}}",
-  "hashtag.unfollow": "Unfollow hashtag",
+  "hashtag.unfollow": "Przestań obserwować hashtag",
   "home.column_settings.basic": "Podstawowe",
   "home.column_settings.show_reblogs": "Pokazuj podbicia",
   "home.column_settings.show_replies": "Pokazuj odpowiedzi",
@@ -475,6 +492,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.filtered": "Filtrowany(-a)",
   "status.hide": "Schowaj toota",
   "status.history.created": "{name} utworzył(a) {date}",
diff --git a/app/javascript/mastodon/locales/pt-BR.json b/app/javascript/mastodon/locales/pt-BR.json
index 268b100d7..395ef4b86 100644
--- a/app/javascript/mastodon/locales/pt-BR.json
+++ b/app/javascript/mastodon/locales/pt-BR.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Eita!",
   "announcement.announcement": "Comunicados",
   "attachments_list.unprocessed": "(não processado)",
+  "audio.hide": "Hide audio",
   "autosuggest_hashtag.per_week": "{count} por semana",
   "boost_modal.combo": "Pressione {combo} para pular isso na próxima vez",
   "bundle_column_error.body": "Erro ao carregar este componente.",
@@ -196,6 +197,22 @@
   "explore.trending_links": "Notícias",
   "explore.trending_statuses": "Posts",
   "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",
   "follow_recommendations.done": "Salvar",
   "follow_recommendations.heading": "Siga pessoas que você gostaria de acompanhar! Aqui estão algumas sugestões.",
   "follow_recommendations.lead": "Toots de pessoas que você segue aparecerão em ordem cronológica na página inicial. Não tenha medo de cometer erros, você pode facilmente deixar de seguir a qualquer momento!",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "Editado {count, plural, one {{count} hora} other {{count} vezes}}",
   "status.embed": "Incorporar",
   "status.favourite": "Favoritar",
+  "status.filter": "Filter this post",
   "status.filtered": "Filtrado",
   "status.hide": "Hide toot",
   "status.history.created": "{name} criou {date}",
diff --git a/app/javascript/mastodon/locales/pt-PT.json b/app/javascript/mastodon/locales/pt-PT.json
index 643ef1c6e..ef097b380 100644
--- a/app/javascript/mastodon/locales/pt-PT.json
+++ b/app/javascript/mastodon/locales/pt-PT.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Bolas!",
   "announcement.announcement": "Anúncio",
   "attachments_list.unprocessed": "(não processado)",
+  "audio.hide": "Ocultar áudio",
   "autosuggest_hashtag.per_week": "{count} por semana",
   "boost_modal.combo": "Pode clicar {combo} para não voltar a ver",
   "bundle_column_error.body": "Algo de errado aconteceu enquanto este componente era carregado.",
@@ -196,6 +197,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",
   "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!",
@@ -220,9 +237,9 @@
   "hashtag.column_settings.tag_mode.any": "Qualquer destes",
   "hashtag.column_settings.tag_mode.none": "Nenhum destes",
   "hashtag.column_settings.tag_toggle": "Incluir etiquetas adicionais para esta coluna",
-  "hashtag.follow": "Follow hashtag",
+  "hashtag.follow": "Seguir hashtag",
   "hashtag.total_volume": "Volume total {days, plural, one {no último dia} other {nos últimos {days} dias}}",
-  "hashtag.unfollow": "Unfollow hashtag",
+  "hashtag.unfollow": "Parar de seguir hashtag",
   "home.column_settings.basic": "Básico",
   "home.column_settings.show_reblogs": "Mostrar boosts",
   "home.column_settings.show_replies": "Mostrar respostas",
@@ -470,6 +487,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.filtered": "Filtrada",
   "status.hide": "Esconder publicação",
   "status.history.created": "{name} criado em {date}",
diff --git a/app/javascript/mastodon/locales/ro.json b/app/javascript/mastodon/locales/ro.json
index a3188f553..ff5ec9b2a 100644
--- a/app/javascript/mastodon/locales/ro.json
+++ b/app/javascript/mastodon/locales/ro.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Ups!",
   "announcement.announcement": "Anunț",
   "attachments_list.unprocessed": "(neprocesate)",
+  "audio.hide": "Hide audio",
   "autosuggest_hashtag.per_week": "{count} pe săptămână",
   "boost_modal.combo": "Poți apăsa {combo} pentru a sări peste asta data viitoare",
   "bundle_column_error.body": "A apărut o eroare la încărcarea acestui element.",
@@ -196,6 +197,22 @@
   "explore.trending_links": "News",
   "explore.trending_statuses": "Posts",
   "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",
   "follow_recommendations.done": "Terminat",
   "follow_recommendations.heading": "Urmărește persoanele ale căror postări te-ar interesa! Iată câteva sugestii.",
   "follow_recommendations.lead": "Postările de la persoanele la care te-ai abonat vor apărea în ordine cronologică în cronologia principală. Nu-ți fie teamă să faci greșeli, poți să te dezabonezi oricând de la ei la fel de ușor!",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "Edited {count, plural, one {{count} time} other {{count} times}}",
   "status.embed": "Înglobează",
   "status.favourite": "Favorite",
+  "status.filter": "Filter this post",
   "status.filtered": "Sortate",
   "status.hide": "Hide toot",
   "status.history.created": "{name} created {date}",
diff --git a/app/javascript/mastodon/locales/ru.json b/app/javascript/mastodon/locales/ru.json
index 30268a41d..9a03a9ef7 100644
--- a/app/javascript/mastodon/locales/ru.json
+++ b/app/javascript/mastodon/locales/ru.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Упс!",
   "announcement.announcement": "Объявление",
   "attachments_list.unprocessed": "(не обработан)",
+  "audio.hide": "Скрыть аудио",
   "autosuggest_hashtag.per_week": "{count} / неделю",
   "boost_modal.combo": "{combo}, чтобы пропустить это в следующий раз",
   "bundle_column_error.body": "Что-то пошло не так при загрузке этого компонента.",
@@ -196,6 +197,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",
   "follow_recommendations.done": "Готово",
   "follow_recommendations.heading": "Подпишитесь на людей, чьи посты вы бы хотели видеть. Вот несколько предложений.",
   "follow_recommendations.lead": "Посты от людей, на которых вы подписаны, будут отображаться в вашей домашней ленте в хронологическом порядке. Не бойтесь ошибиться — вы так же легко сможете отписаться от них в любое время!",
@@ -220,9 +237,9 @@
   "hashtag.column_settings.tag_mode.any": "Любой из списка",
   "hashtag.column_settings.tag_mode.none": "Ни один из списка",
   "hashtag.column_settings.tag_toggle": "Включить дополнительные теги для этой колонки",
-  "hashtag.follow": "Follow hashtag",
+  "hashtag.follow": "Подписаться на новые посты",
   "hashtag.total_volume": "Общий объем за {days, plural, =1 {последний день} one {последний {days} день} few {последних {days} дня} many {последних {days} дней} other {последних {days} дней}}",
-  "hashtag.unfollow": "Unfollow hashtag",
+  "hashtag.unfollow": "Отписаться",
   "home.column_settings.basic": "Основные",
   "home.column_settings.show_reblogs": "Показывать продвижения",
   "home.column_settings.show_replies": "Показывать ответы",
@@ -470,10 +487,11 @@
   "status.edited_x_times": "{count, plural, one {{count} изменение} many {{count} изменений} other {{count} изменения}}",
   "status.embed": "Встроить на свой сайт",
   "status.favourite": "В избранное",
+  "status.filter": "Filter this post",
   "status.filtered": "Отфильтровано",
   "status.hide": "Скрыть пост",
   "status.history.created": "{name} создал {date}",
-  "status.history.edited": "{name} отредактировал {date}",
+  "status.history.edited": "{name} отредактировал(а) {date}",
   "status.load_more": "Загрузить остальное",
   "status.media_hidden": "Файл скрыт",
   "status.mention": "Упомянуть @{name}",
diff --git a/app/javascript/mastodon/locales/sa.json b/app/javascript/mastodon/locales/sa.json
index ecbdf816c..2ebda63cd 100644
--- a/app/javascript/mastodon/locales/sa.json
+++ b/app/javascript/mastodon/locales/sa.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "अरे !",
   "announcement.announcement": "उद्घोषणा",
   "attachments_list.unprocessed": "(unprocessed)",
+  "audio.hide": "Hide audio",
   "autosuggest_hashtag.per_week": "{count} प्रतिसप्ताहे",
   "boost_modal.combo": "{combo} अत्र स्प्रष्टुं शक्यते, त्यक्तुमेतमन्यस्मिन् समये",
   "bundle_column_error.body": "विषयस्याऽऽरोपणे कश्चिद्दोषो जातः",
@@ -196,6 +197,22 @@
   "explore.trending_links": "News",
   "explore.trending_statuses": "Posts",
   "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",
   "follow_recommendations.done": "Done",
   "follow_recommendations.heading": "Follow people you'd like to see posts from! Here are some suggestions.",
   "follow_recommendations.lead": "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!",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "Edited {count, plural, one {{count} time} other {{count} times}}",
   "status.embed": "Embed",
   "status.favourite": "Favourite",
+  "status.filter": "Filter this post",
   "status.filtered": "Filtered",
   "status.hide": "Hide toot",
   "status.history.created": "{name} created {date}",
diff --git a/app/javascript/mastodon/locales/sc.json b/app/javascript/mastodon/locales/sc.json
index aaecfd8e1..7482d15fe 100644
--- a/app/javascript/mastodon/locales/sc.json
+++ b/app/javascript/mastodon/locales/sc.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Oh!",
   "announcement.announcement": "Annùntziu",
   "attachments_list.unprocessed": "(unprocessed)",
+  "audio.hide": "Hide audio",
   "autosuggest_hashtag.per_week": "{count} a sa chida",
   "boost_modal.combo": "Podes incarcare {combo} pro brincare custu sa borta chi benit",
   "bundle_column_error.body": "Faddina in su carrigamentu de custu cumponente.",
@@ -196,6 +197,22 @@
   "explore.trending_links": "News",
   "explore.trending_statuses": "Posts",
   "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",
   "follow_recommendations.done": "Fatu",
   "follow_recommendations.heading": "Sighi gente de chie boles bìdere is publicatziones! Càstia custos cussìgios.",
   "follow_recommendations.lead": "Is messàgios de gente a sa chi ses sighende ant a èssere ammustrados in òrdine cronològicu in sa lìnia de tempus printzipale tua. Non timas de fàghere errores, acabbare de sighire gente est fàtzile in cale si siat momentu!",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "Edited {count, plural, one {{count} time} other {{count} times}}",
   "status.embed": "Afissa",
   "status.favourite": "Preferidos",
+  "status.filter": "Filter this post",
   "status.filtered": "Filtradu",
   "status.hide": "Hide toot",
   "status.history.created": "{name} created {date}",
diff --git a/app/javascript/mastodon/locales/si.json b/app/javascript/mastodon/locales/si.json
index e50ea9135..170c34b57 100644
--- a/app/javascript/mastodon/locales/si.json
+++ b/app/javascript/mastodon/locales/si.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "අපොයි!",
   "announcement.announcement": "නිවේදනය",
   "attachments_list.unprocessed": "(සැකසුම් නොකළ)",
+  "audio.hide": "Hide audio",
   "autosuggest_hashtag.per_week": "සතියකට {count}",
   "boost_modal.combo": "ඊළඟ වතාවේ මෙය මඟ හැරීමට ඔබට {combo} එබිය හැක",
   "bundle_column_error.body": "මෙම සංරචකය පූරණය කිරීමේදී යම් දෙයක් වැරදී ඇත.",
@@ -196,6 +197,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",
   "follow_recommendations.done": "කළා",
   "follow_recommendations.heading": "ඔබ පළ කිරීම් බැලීමට කැමති පුද්ගලයින් අනුගමනය කරන්න! මෙන්න යෝජනා කිහිපයක්.",
   "follow_recommendations.lead": "ඔබ අනුගමන කරන පුද්ගලයින්ගේ පළ කිරීම් ඔබගේ නිවසේ සංග්‍රහයේ කාලානුක්‍රමික අනුපිළිවෙලට පෙන්වනු ඇත. වැරදි කිරීමට බිය නොවන්න, ඔබට ඕනෑම වේලාවක පහසුවෙන් මිනිසුන් අනුගමනය කළ නොහැක!",
@@ -470,6 +487,7 @@
   "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}",
diff --git a/app/javascript/mastodon/locales/sk.json b/app/javascript/mastodon/locales/sk.json
index 3454fe7d2..8aeb2aec6 100644
--- a/app/javascript/mastodon/locales/sk.json
+++ b/app/javascript/mastodon/locales/sk.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Ups!",
   "announcement.announcement": "Oboznámenie",
   "attachments_list.unprocessed": "(nespracované)",
+  "audio.hide": "Hide audio",
   "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.",
@@ -196,6 +197,22 @@
   "explore.trending_links": "Novinky",
   "explore.trending_statuses": "Príspevky",
   "explore.trending_tags": "Haštagy",
+  "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",
   "follow_recommendations.done": "Hotovo",
   "follow_recommendations.heading": "Následuj ľudí od ktorých by si chcel/a vidieť príspevky! Tu sú nejaké návrhy.",
   "follow_recommendations.lead": "Príspevky od ľudi ktorých sledujete sa zobrazia v chronologickom poradí na Vašej nástenke. Nebojte sa spraviť chyby, vždy môžete zrušiť sledovanie konkrétnych ľudí!",
@@ -220,9 +237,9 @@
   "hashtag.column_settings.tag_mode.any": "Hociktorý z týchto",
   "hashtag.column_settings.tag_mode.none": "Žiaden z týchto",
   "hashtag.column_settings.tag_toggle": "Vlož dodatočné haštagy pre tento stĺpec",
-  "hashtag.follow": "Follow hashtag",
+  "hashtag.follow": "Nasleduj haštag",
   "hashtag.total_volume": "Total volume in the last {days, plural, one {day} other {{days} days}}",
-  "hashtag.unfollow": "Unfollow hashtag",
+  "hashtag.unfollow": "Nesleduj haštag",
   "home.column_settings.basic": "Základné",
   "home.column_settings.show_reblogs": "Ukáž vyzdvihnuté",
   "home.column_settings.show_replies": "Ukáž odpovede",
@@ -401,7 +418,7 @@
   "reply_indicator.cancel": "Zrušiť",
   "report.block": "Blokuj",
   "report.block_explanation": "You will not see their posts. They will not be able to see your posts or follow you. They will be able to tell that they are blocked.",
-  "report.categories.other": "Other",
+  "report.categories.other": "Ostatné",
   "report.categories.spam": "Spam",
   "report.categories.violation": "Content violates one or more server rules",
   "report.category.subtitle": "Choose the best match",
@@ -437,7 +454,7 @@
   "report.unfollow": "Nesleduj @{name}",
   "report.unfollow_explanation": "You are following this account. To not see their posts in your home feed anymore, unfollow them.",
   "report_notification.attached_statuses": "{count, plural, one {{count} post} other {{count} posts}} attached",
-  "report_notification.categories.other": "Other",
+  "report_notification.categories.other": "Ostatné",
   "report_notification.categories.spam": "Spam",
   "report_notification.categories.violation": "Rule violation",
   "report_notification.open": "Open report",
@@ -470,8 +487,9 @@
   "status.edited_x_times": "Edited {count, plural, one {{count} time} other {{count} times}}",
   "status.embed": "Vložiť",
   "status.favourite": "Páči sa mi",
+  "status.filter": "Filter this post",
   "status.filtered": "Filtrované",
-  "status.hide": "Hide toot",
+  "status.hide": "Skry príspevok",
   "status.history.created": "{name} vytvoril/a {date}",
   "status.history.edited": "{name} upravil/a {date}",
   "status.load_more": "Ukáž viac",
@@ -495,7 +513,7 @@
   "status.report": "Nahlás @{name}",
   "status.sensitive_warning": "Chúlostivý obsah",
   "status.share": "Zdieľaj",
-  "status.show_filter_reason": "Show anyway",
+  "status.show_filter_reason": "Ukáž aj tak",
   "status.show_less": "Zobraz menej",
   "status.show_less_all": "Všetkým ukáž menej",
   "status.show_more": "Ukáž viac",
diff --git a/app/javascript/mastodon/locales/sl.json b/app/javascript/mastodon/locales/sl.json
index 733614f3e..c793d9de8 100644
--- a/app/javascript/mastodon/locales/sl.json
+++ b/app/javascript/mastodon/locales/sl.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Uups!",
   "announcement.announcement": "Objava",
   "attachments_list.unprocessed": "(neobdelano)",
+  "audio.hide": "Skrij zvok",
   "autosuggest_hashtag.per_week": "{count} na teden",
   "boost_modal.combo": "Če želite preskočiti to, lahko pritisnete {combo}",
   "bundle_column_error.body": "Med nalaganjem te komponente je prišlo do napake.",
@@ -196,6 +197,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",
   "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!",
@@ -220,9 +237,9 @@
   "hashtag.column_settings.tag_mode.any": "Karkoli od naštetega",
   "hashtag.column_settings.tag_mode.none": "Nič od naštetega",
   "hashtag.column_settings.tag_toggle": "Za ta stolpec vključi dodatne oznake",
-  "hashtag.follow": "Follow hashtag",
+  "hashtag.follow": "Sledi ključniku",
   "hashtag.total_volume": "Skupen obseg v {days, plural, one {zadnjem {day} dnevu} two {zadnjih {days} dneh} few {zadnjih {days} dneh} other {zadnjih {days} dneh}}",
-  "hashtag.unfollow": "Unfollow hashtag",
+  "hashtag.unfollow": "Nehaj slediti ključniku",
   "home.column_settings.basic": "Osnovno",
   "home.column_settings.show_reblogs": "Pokaži izpostavitve",
   "home.column_settings.show_replies": "Pokaži odgovore",
@@ -470,6 +487,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.filtered": "Filtrirano",
   "status.hide": "Skrij tut",
   "status.history.created": "{name}: ustvarjeno {date}",
diff --git a/app/javascript/mastodon/locales/sq.json b/app/javascript/mastodon/locales/sq.json
index 8bc440503..0b7fabb45 100644
--- a/app/javascript/mastodon/locales/sq.json
+++ b/app/javascript/mastodon/locales/sq.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Hëm!",
   "announcement.announcement": "Lajmërim",
   "attachments_list.unprocessed": "(e papërpunuar)",
+  "audio.hide": "Fshihe audion",
   "autosuggest_hashtag.per_week": "{count} për javë",
   "boost_modal.combo": "Që kjo të anashkalohet herës tjetër, mund të shtypni {combo}",
   "bundle_column_error.body": "Diç shkoi ters teksa ngarkohej ky përbërës.",
@@ -196,6 +197,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",
   "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!",
@@ -220,9 +237,9 @@
   "hashtag.column_settings.tag_mode.any": "Cilindo prej këtyre",
   "hashtag.column_settings.tag_mode.none": "Asnjë prej këtyre",
   "hashtag.column_settings.tag_toggle": "Përfshi etiketa shtesë për këtë shtyllë",
-  "hashtag.follow": "Follow hashtag",
+  "hashtag.follow": "Ndiqe hashtag-un",
   "hashtag.total_volume": "Vëllim gjithsej {days, plural, një {day} other {{days} ditët}} e fundit",
-  "hashtag.unfollow": "Unfollow hashtag",
+  "hashtag.unfollow": "Hiqe ndjekjen e hashtag-ut",
   "home.column_settings.basic": "Bazë",
   "home.column_settings.show_reblogs": "Shfaq përforcime",
   "home.column_settings.show_replies": "Shfaq përgjigje",
@@ -470,6 +487,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.filtered": "I filtruar",
   "status.hide": "Fshihe mesazhin",
   "status.history.created": "{name} u krijua më {date}",
diff --git a/app/javascript/mastodon/locales/sr-Latn.json b/app/javascript/mastodon/locales/sr-Latn.json
index 131af97e1..8e955727d 100644
--- a/app/javascript/mastodon/locales/sr-Latn.json
+++ b/app/javascript/mastodon/locales/sr-Latn.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Oops!",
   "announcement.announcement": "Announcement",
   "attachments_list.unprocessed": "(unprocessed)",
+  "audio.hide": "Hide audio",
   "autosuggest_hashtag.per_week": "{count} per week",
   "boost_modal.combo": "Možete pritisnuti {combo} da preskočite ovo sledeći put",
   "bundle_column_error.body": "Nešto je pošlo po zlu prilikom učitavanja ove komponente.",
@@ -196,6 +197,22 @@
   "explore.trending_links": "News",
   "explore.trending_statuses": "Posts",
   "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",
   "follow_recommendations.done": "Done",
   "follow_recommendations.heading": "Follow people you'd like to see posts from! Here are some suggestions.",
   "follow_recommendations.lead": "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!",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "Edited {count, plural, one {{count} time} other {{count} times}}",
   "status.embed": "Ugradi na sajt",
   "status.favourite": "Omiljeno",
+  "status.filter": "Filter this post",
   "status.filtered": "Filtered",
   "status.hide": "Hide toot",
   "status.history.created": "{name} created {date}",
diff --git a/app/javascript/mastodon/locales/sr.json b/app/javascript/mastodon/locales/sr.json
index a2409e957..442e7ee3d 100644
--- a/app/javascript/mastodon/locales/sr.json
+++ b/app/javascript/mastodon/locales/sr.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Упс!",
   "announcement.announcement": "Најава",
   "attachments_list.unprocessed": "(unprocessed)",
+  "audio.hide": "Hide audio",
   "autosuggest_hashtag.per_week": "{count} недељно",
   "boost_modal.combo": "Можете притиснути {combo} да прескочите ово следећи пут",
   "bundle_column_error.body": "Нешто је пошло по злу приликом учитавања ове компоненте.",
@@ -196,6 +197,22 @@
   "explore.trending_links": "News",
   "explore.trending_statuses": "Posts",
   "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",
   "follow_recommendations.done": "Done",
   "follow_recommendations.heading": "Follow people you'd like to see posts from! Here are some suggestions.",
   "follow_recommendations.lead": "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!",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "Edited {count, plural, one {{count} time} other {{count} times}}",
   "status.embed": "Угради на сајт",
   "status.favourite": "Омиљено",
+  "status.filter": "Filter this post",
   "status.filtered": "Филтрирано",
   "status.hide": "Hide toot",
   "status.history.created": "{name} created {date}",
diff --git a/app/javascript/mastodon/locales/sv.json b/app/javascript/mastodon/locales/sv.json
index 9cc1c326a..7fb445b9e 100644
--- a/app/javascript/mastodon/locales/sv.json
+++ b/app/javascript/mastodon/locales/sv.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Hoppsan!",
   "announcement.announcement": "Meddelande",
   "attachments_list.unprocessed": "(obearbetad)",
+  "audio.hide": "Dölj audio",
   "autosuggest_hashtag.per_week": "{count} per vecka",
   "boost_modal.combo": "Du kan trycka {combo} för att slippa detta nästa gång",
   "bundle_column_error.body": "Något gick fel medan denna komponent laddades.",
@@ -196,6 +197,22 @@
   "explore.trending_links": "Nyheter",
   "explore.trending_statuses": "Inlägg",
   "explore.trending_tags": "Hashtaggar",
+  "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",
   "follow_recommendations.done": "Klar",
   "follow_recommendations.heading": "Följ personer som du skulle vilja se inlägg från! Här finns det några förslag.",
   "follow_recommendations.lead": "Inlägg från personer du följer kommer att dyka upp i kronologisk ordning i ditt hem-flöde. Var inte rädd för att göra misstag, du kan sluta följa människor lika enkelt när som helst!",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "Redigerad {count, plural, one {{count} gång} other {{count} gånger}}",
   "status.embed": "Bädda in",
   "status.favourite": "Favorit",
+  "status.filter": "Filter this post",
   "status.filtered": "Filtrerat",
   "status.hide": "Hide toot",
   "status.history.created": "{name} skapade {date}",
diff --git a/app/javascript/mastodon/locales/szl.json b/app/javascript/mastodon/locales/szl.json
index 99fdcfd45..c77444bff 100644
--- a/app/javascript/mastodon/locales/szl.json
+++ b/app/javascript/mastodon/locales/szl.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Oops!",
   "announcement.announcement": "Announcement",
   "attachments_list.unprocessed": "(unprocessed)",
+  "audio.hide": "Hide audio",
   "autosuggest_hashtag.per_week": "{count} per week",
   "boost_modal.combo": "You can press {combo} to skip this next time",
   "bundle_column_error.body": "Something went wrong while loading this component.",
@@ -196,6 +197,22 @@
   "explore.trending_links": "News",
   "explore.trending_statuses": "Posts",
   "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",
   "follow_recommendations.done": "Done",
   "follow_recommendations.heading": "Follow people you'd like to see posts from! Here are some suggestions.",
   "follow_recommendations.lead": "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!",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "Edited {count, plural, one {{count} time} other {{count} times}}",
   "status.embed": "Embed",
   "status.favourite": "Favourite",
+  "status.filter": "Filter this post",
   "status.filtered": "Filtered",
   "status.hide": "Hide toot",
   "status.history.created": "{name} created {date}",
diff --git a/app/javascript/mastodon/locales/ta.json b/app/javascript/mastodon/locales/ta.json
index cc7241bad..728cfac11 100644
--- a/app/javascript/mastodon/locales/ta.json
+++ b/app/javascript/mastodon/locales/ta.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "அச்சச்சோ!",
   "announcement.announcement": "அறிவிப்பு",
   "attachments_list.unprocessed": "(unprocessed)",
+  "audio.hide": "Hide audio",
   "autosuggest_hashtag.per_week": "ஒவ்வொரு வாரம் {count}",
   "boost_modal.combo": "நீங்கள் இதை அடுத்தமுறை தவிர்க்க {combo} வை அழுத்தவும்",
   "bundle_column_error.body": "இக்கூற்றை ஏற்றம் செய்யும்பொழுது ஏதோ தவறு ஏற்பட்டுள்ளது.",
@@ -196,6 +197,22 @@
   "explore.trending_links": "News",
   "explore.trending_statuses": "Posts",
   "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",
   "follow_recommendations.done": "Done",
   "follow_recommendations.heading": "Follow people you'd like to see posts from! Here are some suggestions.",
   "follow_recommendations.lead": "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!",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "Edited {count, plural, one {{count} time} other {{count} times}}",
   "status.embed": "கிடத்து",
   "status.favourite": "விருப்பத்துக்குகந்த",
+  "status.filter": "Filter this post",
   "status.filtered": "வடிகட்டு",
   "status.hide": "Hide toot",
   "status.history.created": "{name} created {date}",
diff --git a/app/javascript/mastodon/locales/tai.json b/app/javascript/mastodon/locales/tai.json
index 17b0e1ed1..beba8e333 100644
--- a/app/javascript/mastodon/locales/tai.json
+++ b/app/javascript/mastodon/locales/tai.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Oops!",
   "announcement.announcement": "Announcement",
   "attachments_list.unprocessed": "(unprocessed)",
+  "audio.hide": "Hide audio",
   "autosuggest_hashtag.per_week": "{count} per week",
   "boost_modal.combo": "You can press {combo} to skip this next time",
   "bundle_column_error.body": "Something went wrong while loading this component.",
@@ -196,6 +197,22 @@
   "explore.trending_links": "News",
   "explore.trending_statuses": "Posts",
   "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",
   "follow_recommendations.done": "Done",
   "follow_recommendations.heading": "Follow people you'd like to see posts from! Here are some suggestions.",
   "follow_recommendations.lead": "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!",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "Edited {count, plural, one {{count} time} other {{count} times}}",
   "status.embed": "Embed",
   "status.favourite": "Favourite",
+  "status.filter": "Filter this post",
   "status.filtered": "Filtered",
   "status.hide": "Hide toot",
   "status.history.created": "{name} created {date}",
diff --git a/app/javascript/mastodon/locales/te.json b/app/javascript/mastodon/locales/te.json
index bbe99b4a6..d5cc02b10 100644
--- a/app/javascript/mastodon/locales/te.json
+++ b/app/javascript/mastodon/locales/te.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "అయ్యో!",
   "announcement.announcement": "Announcement",
   "attachments_list.unprocessed": "(unprocessed)",
+  "audio.hide": "Hide audio",
   "autosuggest_hashtag.per_week": "{count} per week",
   "boost_modal.combo": "మీరు తదుపరిసారి దీనిని దాటవేయడానికి {combo} నొక్కవచ్చు",
   "bundle_column_error.body": "ఈ భాగం లోడ్ అవుతున్నప్పుడు ఏదో తప్పు జరిగింది.",
@@ -196,6 +197,22 @@
   "explore.trending_links": "News",
   "explore.trending_statuses": "Posts",
   "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",
   "follow_recommendations.done": "Done",
   "follow_recommendations.heading": "Follow people you'd like to see posts from! Here are some suggestions.",
   "follow_recommendations.lead": "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!",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "Edited {count, plural, one {{count} time} other {{count} times}}",
   "status.embed": "ఎంబెడ్",
   "status.favourite": "ఇష్టపడు",
+  "status.filter": "Filter this post",
   "status.filtered": "వడకట్టబడిన",
   "status.hide": "Hide toot",
   "status.history.created": "{name} created {date}",
diff --git a/app/javascript/mastodon/locales/th.json b/app/javascript/mastodon/locales/th.json
index 0bff3caab..38539d512 100644
--- a/app/javascript/mastodon/locales/th.json
+++ b/app/javascript/mastodon/locales/th.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "อุปส์!",
   "announcement.announcement": "ประกาศ",
   "attachments_list.unprocessed": "(ยังไม่ได้ประมวลผล)",
+  "audio.hide": "ซ่อนเสียง",
   "autosuggest_hashtag.per_week": "{count} ต่อสัปดาห์",
   "boost_modal.combo": "คุณสามารถกด {combo} เพื่อข้ามสิ่งนี้ในครั้งถัดไป",
   "bundle_column_error.body": "มีบางอย่างผิดพลาดขณะโหลดส่วนประกอบนี้",
@@ -196,6 +197,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",
   "follow_recommendations.done": "เสร็จสิ้น",
   "follow_recommendations.heading": "ติดตามผู้คนที่คุณต้องการเห็นโพสต์! นี่คือข้อเสนอแนะบางส่วน",
   "follow_recommendations.lead": "โพสต์จากผู้คนที่คุณติดตามจะแสดงตามลำดับเวลาในฟีดหน้าแรกของคุณ อย่ากลัวที่จะทำผิดพลาด คุณสามารถเลิกติดตามผู้คนได้อย่างง่ายดายเมื่อใดก็ตาม!",
@@ -220,9 +237,9 @@
   "hashtag.column_settings.tag_mode.any": "ใดก็ตามนี้",
   "hashtag.column_settings.tag_mode.none": "ไม่ใช่ทั้งหมดนี้",
   "hashtag.column_settings.tag_toggle": "รวมแท็กเพิ่มเติมสำหรับคอลัมน์นี้",
-  "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, other {{days} วัน}}ที่ผ่านมา",
+  "hashtag.unfollow": "เลิกติดตามแฮชแท็ก",
   "home.column_settings.basic": "พื้นฐาน",
   "home.column_settings.show_reblogs": "แสดงการดัน",
   "home.column_settings.show_replies": "แสดงการตอบกลับ",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "แก้ไข {count, plural, other {{count} ครั้ง}}",
   "status.embed": "ฝัง",
   "status.favourite": "ชื่นชอบ",
+  "status.filter": "Filter this post",
   "status.filtered": "กรองอยู่",
   "status.hide": "ซ่อนโพสต์",
   "status.history.created": "{name} ได้สร้างเมื่อ {date}",
@@ -520,7 +538,7 @@
   "timeline_hint.resources.followers": "ผู้ติดตาม",
   "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.counter_by_accounts": "{count, plural, other {{counter} คน}}ใน {days, plural, other {{days} วัน}}ที่ผ่านมา",
   "trends.trending_now": "กำลังนิยม",
   "ui.beforeunload": "แบบร่างของคุณจะหายไปหากคุณออกจาก Mastodon",
   "units.short.billion": "{count} พันล้าน",
diff --git a/app/javascript/mastodon/locales/tr.json b/app/javascript/mastodon/locales/tr.json
index 3948bde5e..35c888e47 100644
--- a/app/javascript/mastodon/locales/tr.json
+++ b/app/javascript/mastodon/locales/tr.json
@@ -12,7 +12,7 @@
   "account.disable_notifications": "@{name} kişisinin gönderi bildirimlerini kapat",
   "account.domain_blocked": "Alan adı engellendi",
   "account.edit_profile": "Profili düzenle",
-  "account.enable_notifications": "@{name} kişisinin gönderi bildirimlerini aç",
+  "account.enable_notifications": "@{name}'in gönderilerini bana bildir",
   "account.endorse": "Profilimde öne çıkar",
   "account.follow": "Takip et",
   "account.followers": "Takipçi",
@@ -20,23 +20,23 @@
   "account.followers_counter": "{count, plural, one {{counter} Takipçi} other {{counter} Takipçi}}",
   "account.following": "Takip Ediliyor",
   "account.following_counter": "{count, plural, one {{counter} Takip Edilen} other {{counter} Takip Edilen}}",
-  "account.follows.empty": "Bu kullanıcı henüz kimseyi takip etmiyor.",
+  "account.follows.empty": "Bu kullanıcı henüz hiçkimseyi takip etmiyor.",
   "account.follows_you": "Seni takip ediyor",
   "account.hide_reblogs": "@{name} kişisinin boostlarını gizle",
   "account.joined": "{date} tarihinde katıldı",
   "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",
-  "account.mention": "@{name} kişisinden bahset",
+  "account.mention": "@{name}'i an",
   "account.moved_to": "{name} şuraya taşındı:",
-  "account.mute": "@{name} adlı kişiyi sessize al",
-  "account.mute_notifications": "@{name} adlı kişinin bildirimlerini kapat",
+  "account.mute": "@{name}'i susstur",
+  "account.mute_notifications": "@{name}'in bildirimlerini sustur",
   "account.muted": "Susturuldu",
   "account.posts": "Gönderiler",
   "account.posts_with_replies": "Gönderiler ve yanıtlar",
-  "account.report": "@{name} adlı kişiyi bildir",
+  "account.report": "@{name}'i şikayet et",
   "account.requested": "Onay bekleniyor. Takip isteğini iptal etmek için tıklayın",
-  "account.share": "@{name} adlı kişinin profilini paylaş",
+  "account.share": "@{name}'in profilini paylaş",
   "account.show_reblogs": "@{name} kişisinin boostlarını göster",
   "account.statuses_counter": "{count, plural, one {{counter} Gönderi} other {{counter} Gönderi}}",
   "account.unblock": "@{name} adlı kişinin engelini kaldır",
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Hay aksi!",
   "announcement.announcement": "Duyuru",
   "attachments_list.unprocessed": "(işlenmemiş)",
+  "audio.hide": "Sesi gizle",
   "autosuggest_hashtag.per_week": "Haftada {count}",
   "boost_modal.combo": "Bir daha ki sefere {combo} tuşuna basabilirsin",
   "bundle_column_error.body": "Bu bileşen yüklenirken bir şeyler ters gitti.",
@@ -196,6 +197,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",
   "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!",
@@ -220,9 +237,9 @@
   "hashtag.column_settings.tag_mode.any": "Herhangi biri",
   "hashtag.column_settings.tag_mode.none": "Bunların hiçbiri",
   "hashtag.column_settings.tag_toggle": "Bu sütundaki ek etiketleri içer",
-  "hashtag.follow": "Follow hashtag",
+  "hashtag.follow": "Etiketi takip et",
   "hashtag.total_volume": "Son {days, plural, one {gündeki} other {{days} gündeki}} toplam hacim",
-  "hashtag.unfollow": "Unfollow hashtag",
+  "hashtag.unfollow": "Etiketi takibi bırak",
   "home.column_settings.basic": "Temel",
   "home.column_settings.show_reblogs": "Boostları göster",
   "home.column_settings.show_replies": "Yanıtları göster",
@@ -470,6 +487,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.filtered": "Filtrelenmiş",
   "status.hide": "Gönderiyi sakla",
   "status.history.created": "{name} oluşturdu {date}",
diff --git a/app/javascript/mastodon/locales/tt.json b/app/javascript/mastodon/locales/tt.json
index c9a48d37c..c2739e181 100644
--- a/app/javascript/mastodon/locales/tt.json
+++ b/app/javascript/mastodon/locales/tt.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Ой!",
   "announcement.announcement": "Announcement",
   "attachments_list.unprocessed": "(unprocessed)",
+  "audio.hide": "Hide audio",
   "autosuggest_hashtag.per_week": "{count} per week",
   "boost_modal.combo": "You can press {combo} to skip this next time",
   "bundle_column_error.body": "Something went wrong while loading this component.",
@@ -196,6 +197,22 @@
   "explore.trending_links": "News",
   "explore.trending_statuses": "Posts",
   "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",
   "follow_recommendations.done": "Done",
   "follow_recommendations.heading": "Follow people you'd like to see posts from! Here are some suggestions.",
   "follow_recommendations.lead": "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!",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "Edited {count, plural, one {{count} time} other {{count} times}}",
   "status.embed": "Embed",
   "status.favourite": "Favourite",
+  "status.filter": "Filter this post",
   "status.filtered": "Filtered",
   "status.hide": "Hide toot",
   "status.history.created": "{name} created {date}",
diff --git a/app/javascript/mastodon/locales/ug.json b/app/javascript/mastodon/locales/ug.json
index 99fdcfd45..c77444bff 100644
--- a/app/javascript/mastodon/locales/ug.json
+++ b/app/javascript/mastodon/locales/ug.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Oops!",
   "announcement.announcement": "Announcement",
   "attachments_list.unprocessed": "(unprocessed)",
+  "audio.hide": "Hide audio",
   "autosuggest_hashtag.per_week": "{count} per week",
   "boost_modal.combo": "You can press {combo} to skip this next time",
   "bundle_column_error.body": "Something went wrong while loading this component.",
@@ -196,6 +197,22 @@
   "explore.trending_links": "News",
   "explore.trending_statuses": "Posts",
   "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",
   "follow_recommendations.done": "Done",
   "follow_recommendations.heading": "Follow people you'd like to see posts from! Here are some suggestions.",
   "follow_recommendations.lead": "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!",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "Edited {count, plural, one {{count} time} other {{count} times}}",
   "status.embed": "Embed",
   "status.favourite": "Favourite",
+  "status.filter": "Filter this post",
   "status.filtered": "Filtered",
   "status.hide": "Hide toot",
   "status.history.created": "{name} created {date}",
diff --git a/app/javascript/mastodon/locales/uk.json b/app/javascript/mastodon/locales/uk.json
index 727b0b994..e1b10445d 100644
--- a/app/javascript/mastodon/locales/uk.json
+++ b/app/javascript/mastodon/locales/uk.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Ой!",
   "announcement.announcement": "Оголошення",
   "attachments_list.unprocessed": "(не оброблено)",
+  "audio.hide": "Сховати аудіо",
   "autosuggest_hashtag.per_week": "{count} в тиждень",
   "boost_modal.combo": "Ви можете натиснути {combo}, щоб пропустити це наступного разу",
   "bundle_column_error.body": "Щось пішло не так під час завантаження цього компоненту.",
@@ -196,6 +197,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",
   "follow_recommendations.done": "Готово",
   "follow_recommendations.heading": "Підпишіться на людей, чиї дописи ви хочете бачити! Ось деякі пропозиції.",
   "follow_recommendations.lead": "Дописи від людей, за якими ви стежите, з'являться в хронологічному порядку у вашій домашній стрічці. Не бійся помилятися, ви можете відписатися від людей так само легко в будь-який час!",
@@ -220,9 +237,9 @@
   "hashtag.column_settings.tag_mode.any": "Який-небудь зі списку",
   "hashtag.column_settings.tag_mode.none": "Жоден зі списку",
   "hashtag.column_settings.tag_toggle": "Додати додаткові теґи до цього стовпчика",
-  "hashtag.follow": "Follow hashtag",
+  "hashtag.follow": "Стежити за хештегом",
   "hashtag.total_volume": "Загальний обсяг за останні(й) {days, plural, one {день} few {{days} дні} other {{days} днів}}",
-  "hashtag.unfollow": "Unfollow hashtag",
+  "hashtag.unfollow": "Не стежити за хештегом",
   "home.column_settings.basic": "Основні",
   "home.column_settings.show_reblogs": "Показувати поширення",
   "home.column_settings.show_replies": "Показувати відповіді",
@@ -470,6 +487,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.filtered": "Відфільтровано",
   "status.hide": "Сховати дмух",
   "status.history.created": "{name} створює {date}",
diff --git a/app/javascript/mastodon/locales/ur.json b/app/javascript/mastodon/locales/ur.json
index b3e3fd771..19cee9c2a 100644
--- a/app/javascript/mastodon/locales/ur.json
+++ b/app/javascript/mastodon/locales/ur.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "ا رے!",
   "announcement.announcement": "اعلان",
   "attachments_list.unprocessed": "(unprocessed)",
+  "audio.hide": "Hide audio",
   "autosuggest_hashtag.per_week": "{count} فی ہفتہ",
   "boost_modal.combo": "آئیندہ یہ نہ دیکھنے کیلئے آپ {combo} دبا سکتے ہیں",
   "bundle_column_error.body": "اس عنصر کو برآمد کرتے وقت کچھ خرابی پیش آئی ہے.",
@@ -196,6 +197,22 @@
   "explore.trending_links": "News",
   "explore.trending_statuses": "Posts",
   "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",
   "follow_recommendations.done": "Done",
   "follow_recommendations.heading": "Follow people you'd like to see posts from! Here are some suggestions.",
   "follow_recommendations.lead": "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!",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "Edited {count, plural, one {{count} time} other {{count} times}}",
   "status.embed": "Embed",
   "status.favourite": "Favourite",
+  "status.filter": "Filter this post",
   "status.filtered": "Filtered",
   "status.hide": "Hide toot",
   "status.history.created": "{name} created {date}",
diff --git a/app/javascript/mastodon/locales/vi.json b/app/javascript/mastodon/locales/vi.json
index 4cdb1e53d..3dc6db112 100644
--- a/app/javascript/mastodon/locales/vi.json
+++ b/app/javascript/mastodon/locales/vi.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Ốiii!",
   "announcement.announcement": "Có gì mới?",
   "attachments_list.unprocessed": "(chưa xử lí)",
+  "audio.hide": "Ẩn âm thanh",
   "autosuggest_hashtag.per_week": "{count} mỗi tuần",
   "boost_modal.combo": "Nhấn {combo} để bỏ qua bước này",
   "bundle_column_error.body": "Đã có lỗi xảy ra trong khi tải nội dung này.",
@@ -196,6 +197,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",
   "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!",
@@ -220,9 +237,9 @@
   "hashtag.column_settings.tag_mode.any": "Một phần",
   "hashtag.column_settings.tag_mode.none": "Không chọn",
   "hashtag.column_settings.tag_toggle": "Bao gồm thêm hashtag cho cột này",
-  "hashtag.follow": "Follow hashtag",
+  "hashtag.follow": "Theo dõi hashtag",
   "hashtag.total_volume": "Tổng số lần sử dụng {days, plural, other {{days} ngày}} qua",
-  "hashtag.unfollow": "Unfollow hashtag",
+  "hashtag.unfollow": "Ngưng theo dõi hashtag",
   "home.column_settings.basic": "Tùy chỉnh",
   "home.column_settings.show_reblogs": "Hiện những lượt đăng lại",
   "home.column_settings.show_replies": "Hiện những tút dạng trả lời",
@@ -470,6 +487,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.filtered": "Bộ lọc",
   "status.hide": "Ẩn tút",
   "status.history.created": "{name} tạo lúc {date}",
diff --git a/app/javascript/mastodon/locales/zgh.json b/app/javascript/mastodon/locales/zgh.json
index 898cc22a9..92201375d 100644
--- a/app/javascript/mastodon/locales/zgh.json
+++ b/app/javascript/mastodon/locales/zgh.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "Oops!",
   "announcement.announcement": "Announcement",
   "attachments_list.unprocessed": "(unprocessed)",
+  "audio.hide": "Hide audio",
   "autosuggest_hashtag.per_week": "{count} ⵙ ⵉⵎⴰⵍⴰⵙⵙ",
   "boost_modal.combo": "You can press {combo} to skip this next time",
   "bundle_column_error.body": "Something went wrong while loading this component.",
@@ -196,6 +197,22 @@
   "explore.trending_links": "News",
   "explore.trending_statuses": "Posts",
   "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",
   "follow_recommendations.done": "Done",
   "follow_recommendations.heading": "Follow people you'd like to see posts from! Here are some suggestions.",
   "follow_recommendations.lead": "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!",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "Edited {count, plural, one {{count} time} other {{count} times}}",
   "status.embed": "Embed",
   "status.favourite": "Favourite",
+  "status.filter": "Filter this post",
   "status.filtered": "Filtered",
   "status.hide": "Hide toot",
   "status.history.created": "{name} created {date}",
diff --git a/app/javascript/mastodon/locales/zh-CN.json b/app/javascript/mastodon/locales/zh-CN.json
index 334b93034..9241eeec8 100644
--- a/app/javascript/mastodon/locales/zh-CN.json
+++ b/app/javascript/mastodon/locales/zh-CN.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "哎呀!",
   "announcement.announcement": "公告",
   "attachments_list.unprocessed": "(未处理)",
+  "audio.hide": "隐藏音频",
   "autosuggest_hashtag.per_week": "每星期 {count} 条",
   "boost_modal.combo": "下次按住 {combo} 即可跳过此提示",
   "bundle_column_error.body": "载入这个组件时发生了错误。",
@@ -109,8 +110,8 @@
   "compose_form.publish": "发布",
   "compose_form.publish_loud": "{publish}!",
   "compose_form.save_changes": "保存更改",
-  "compose_form.sensitive.hide": "{count, plural, one {将媒体标记为敏感内容} other {将媒体标记为敏感内容}}",
-  "compose_form.sensitive.marked": "{count, plural, one {媒体已被标记为敏感内容} other {媒体已被标记为敏感内容}}",
+  "compose_form.sensitive.hide": "标记媒体为敏感内容",
+  "compose_form.sensitive.marked": "媒体已被标记为敏感内容",
   "compose_form.sensitive.unmarked": "媒体未被标记为敏感内容",
   "compose_form.spoiler.marked": "移除内容警告",
   "compose_form.spoiler.unmarked": "添加内容警告",
@@ -196,6 +197,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",
   "follow_recommendations.done": "完成",
   "follow_recommendations.heading": "关注你感兴趣的用户!这里有一些推荐。",
   "follow_recommendations.lead": "你关注的人的嘟文将按时间顺序在你的主页上显示。 别担心,你可以随时取消关注!",
@@ -203,8 +220,8 @@
   "follow_request.reject": "拒绝",
   "follow_requests.unlocked_explanation": "尽管你没有锁嘟,但是 {domain} 的工作人员认为你也许会想手动审核审核这些账号的关注请求。",
   "generic.saved": "已保存",
-  "getting_started.developers": "开发",
-  "getting_started.directory": "用户目录",
+  "getting_started.developers": "开发者",
+  "getting_started.directory": "个人资料目录",
   "getting_started.documentation": "文档",
   "getting_started.heading": "开始使用",
   "getting_started.invite": "邀请用户",
@@ -220,9 +237,9 @@
   "hashtag.column_settings.tag_mode.any": "任一",
   "hashtag.column_settings.tag_mode.none": "无一",
   "hashtag.column_settings.tag_toggle": "在此栏加入额外的标签",
-  "hashtag.follow": "Follow hashtag",
+  "hashtag.follow": "关注哈希标签",
   "hashtag.total_volume": "在过去的{days, plural,one {day}other {{days}days}}的总数量",
-  "hashtag.unfollow": "Unfollow hashtag",
+  "hashtag.unfollow": "取消关注哈希标签",
   "home.column_settings.basic": "基本设置",
   "home.column_settings.show_reblogs": "显示转嘟",
   "home.column_settings.show_replies": "显示回复",
@@ -436,7 +453,7 @@
   "report.thanks.title_actionable": "感谢提交举报,我们将会进行处理。",
   "report.unfollow": "取消关注 @{name}",
   "report.unfollow_explanation": "你正在关注此账户。如果要想在你的主页上不再看到他们的帖子,取消对他们的关注即可。",
-  "report_notification.attached_statuses": "{count, plural, one {{count} 嘟文} other {{count} 嘟文}} 附件",
+  "report_notification.attached_statuses": "附上 {count} 条嘟文",
   "report_notification.categories.other": "其他",
   "report_notification.categories.spam": "骚扰",
   "report_notification.categories.violation": "违反规则",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "共编辑 {count, plural, one {{count} 次} other {{count} 次}}",
   "status.embed": "嵌入",
   "status.favourite": "喜欢",
+  "status.filter": "Filter this post",
   "status.filtered": "已过滤",
   "status.hide": "屏蔽嘟文",
   "status.history.created": "{name} 创建于 {date}",
@@ -520,7 +538,7 @@
   "timeline_hint.resources.followers": "关注者",
   "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.counter_by_accounts": "过去 {day} 天有 {counter} 人讨论",
   "trends.trending_now": "现在流行",
   "ui.beforeunload": "如果你现在离开 Mastodon,你的草稿内容将会丢失。",
   "units.short.billion": "{count} B",
diff --git a/app/javascript/mastodon/locales/zh-HK.json b/app/javascript/mastodon/locales/zh-HK.json
index e3c65cdab..fdc206800 100644
--- a/app/javascript/mastodon/locales/zh-HK.json
+++ b/app/javascript/mastodon/locales/zh-HK.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "噢!",
   "announcement.announcement": "公告",
   "attachments_list.unprocessed": "(unprocessed)",
+  "audio.hide": "Hide audio",
   "autosuggest_hashtag.per_week": "{count} / 週",
   "boost_modal.combo": "如你想在下次路過這顯示,請按{combo},",
   "bundle_column_error.body": "加載本組件出錯。",
@@ -196,6 +197,22 @@
   "explore.trending_links": "News",
   "explore.trending_statuses": "Posts",
   "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",
   "follow_recommendations.done": "完成",
   "follow_recommendations.heading": "跟隨人們以看到來自他們的嘟文!這裡有些建議。",
   "follow_recommendations.lead": "您跟隨對象知嘟文將會以時間順序顯示於您的 home feed 上。別擔心犯下錯誤,您隨時可以取消跟隨人們!",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "Edited {count, plural, one {{count} time} other {{count} times}}",
   "status.embed": "嵌入",
   "status.favourite": "最愛",
+  "status.filter": "Filter this post",
   "status.filtered": "已過濾",
   "status.hide": "Hide toot",
   "status.history.created": "{name} created {date}",
diff --git a/app/javascript/mastodon/locales/zh-TW.json b/app/javascript/mastodon/locales/zh-TW.json
index 99814b30d..13eee62de 100644
--- a/app/javascript/mastodon/locales/zh-TW.json
+++ b/app/javascript/mastodon/locales/zh-TW.json
@@ -59,6 +59,7 @@
   "alert.unexpected.title": "哎呀!",
   "announcement.announcement": "公告",
   "attachments_list.unprocessed": "(未經處理)",
+  "audio.hide": "隱藏音訊",
   "autosuggest_hashtag.per_week": "{count} / 週",
   "boost_modal.combo": "下次您可以按 {combo} 跳過",
   "bundle_column_error.body": "載入此元件時發生錯誤。",
@@ -196,6 +197,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",
   "follow_recommendations.done": "完成",
   "follow_recommendations.heading": "跟隨您想檢視其嘟文的人!這裡有一些建議。",
   "follow_recommendations.lead": "來自您跟隨的人之嘟文將會按時間順序顯示在您的首頁時間軸上。不要害怕犯錯,您隨時都可以取消跟隨其他人!",
@@ -220,9 +237,9 @@
   "hashtag.column_settings.tag_mode.any": "任一",
   "hashtag.column_settings.tag_mode.none": "全不",
   "hashtag.column_settings.tag_toggle": "將額外標籤加入到這個欄位",
-  "hashtag.follow": "Follow hashtag",
+  "hashtag.follow": "追蹤主題標籤",
   "hashtag.total_volume": "過去 {days, plural, one {日} other {{days} 日}} 之總量",
-  "hashtag.unfollow": "Unfollow hashtag",
+  "hashtag.unfollow": "取消追蹤主題標籤",
   "home.column_settings.basic": "基本",
   "home.column_settings.show_reblogs": "顯示轉嘟",
   "home.column_settings.show_replies": "顯示回覆",
@@ -470,6 +487,7 @@
   "status.edited_x_times": "已編輯 {count, plural, one {{count} 次} other {{count} 次}}",
   "status.embed": "內嵌",
   "status.favourite": "最愛",
+  "status.filter": "Filter this post",
   "status.filtered": "已過濾",
   "status.hide": "隱藏嘟文",
   "status.history.created": "{name} 於 {date} 建立",
diff --git a/app/javascript/mastodon/reducers/filters.js b/app/javascript/mastodon/reducers/filters.js
index 14b704027..f4f97cd3a 100644
--- a/app/javascript/mastodon/reducers/filters.js
+++ b/app/javascript/mastodon/reducers/filters.js
@@ -1,4 +1,5 @@
 import { FILTERS_IMPORT } from '../actions/importer';
+import { FILTERS_FETCH_SUCCESS, FILTERS_CREATE_SUCCESS } from '../actions/filters';
 import { Map as ImmutableMap, is, fromJS } from 'immutable';
 
 const normalizeFilter = (state, filter) => {
@@ -7,13 +8,17 @@ const normalizeFilter = (state, filter) => {
     title: filter.title,
     context: filter.context,
     filter_action: filter.filter_action,
+    keywords: filter.keywords,
     expires_at: filter.expires_at ? Date.parse(filter.expires_at) : null,
   });
 
   if (is(state.get(filter.id), normalizedFilter)) {
     return state;
   } else {
-    return state.set(filter.id, normalizedFilter);
+    // Do not overwrite keywords when receiving a partial filter
+    return state.update(filter.id, ImmutableMap(), (old) => (
+      old.mergeWith(((old_value, new_value) => (new_value === undefined ? old_value : new_value)), normalizedFilter)
+    ));
   }
 };
 
@@ -27,6 +32,10 @@ const normalizeFilters = (state, filters) => {
 
 export default function filters(state = ImmutableMap(), action) {
   switch(action.type) {
+  case FILTERS_CREATE_SUCCESS:
+    return normalizeFilter(state, action.filter);
+  case FILTERS_FETCH_SUCCESS:
+    return normalizeFilters(ImmutableMap(), action.filters);
   case FILTERS_IMPORT:
     return normalizeFilters(state, action.filters);
   default:
diff --git a/app/javascript/mastodon/reducers/notifications.js b/app/javascript/mastodon/reducers/notifications.js
index 4b460bc10..eb34edb63 100644
--- a/app/javascript/mastodon/reducers/notifications.js
+++ b/app/javascript/mastodon/reducers/notifications.js
@@ -41,7 +41,7 @@ const initialState = ImmutableMap({
   lastReadId: '0',
   readMarkerId: '0',
   isTabVisible: true,
-  isLoading: false,
+  isLoading: 0,
   browserSupport: false,
   browserPermission: 'default',
 });
@@ -115,7 +115,7 @@ const expandNormalizedNotifications = (state, notifications, next, isLoadingRece
       }
     }
 
-    mutable.set('isLoading', false);
+    mutable.update('isLoading', (nbLoading) => nbLoading - 1);
   });
 };
 
@@ -214,9 +214,9 @@ export default function notifications(state = initialState, action) {
   case NOTIFICATIONS_LOAD_PENDING:
     return state.update('items', list => state.get('pendingItems').concat(list.take(40))).set('pendingItems', ImmutableList()).set('unread', 0);
   case NOTIFICATIONS_EXPAND_REQUEST:
-    return state.set('isLoading', true);
+    return state.update('isLoading', (nbLoading) => nbLoading + 1);
   case NOTIFICATIONS_EXPAND_FAIL:
-    return state.set('isLoading', false);
+    return state.update('isLoading', (nbLoading) => nbLoading - 1);
   case NOTIFICATIONS_FILTER_SET:
     return state.set('items', ImmutableList()).set('pendingItems', ImmutableList()).set('hasMore', true);
   case NOTIFICATIONS_SCROLL_TOP:
@@ -234,8 +234,6 @@ export default function notifications(state = initialState, action) {
   case FOLLOW_REQUEST_AUTHORIZE_SUCCESS:
   case FOLLOW_REQUEST_REJECT_SUCCESS:
     return filterNotifications(state, [action.id], 'follow_request');
-  case ACCOUNT_MUTE_SUCCESS:
-    return action.relationship.muting_notifications ? filterNotifications(state, [action.relationship.id]) : state;
   case NOTIFICATIONS_CLEAR:
     return state.set('items', ImmutableList()).set('pendingItems', ImmutableList()).set('hasMore', false);
   case TIMELINE_DELETE:
diff --git a/app/javascript/mastodon/selectors/index.js b/app/javascript/mastodon/selectors/index.js
index 187e3306d..3dd7f4897 100644
--- a/app/javascript/mastodon/selectors/index.js
+++ b/app/javascript/mastodon/selectors/index.js
@@ -1,5 +1,6 @@
 import { createSelector } from 'reselect';
 import { List as ImmutableList, Map as ImmutableMap } from 'immutable';
+import { toServerSideType } from 'mastodon/utils/filters';
 import { me } from '../initial_state';
 
 const getAccountBase         = (state, id) => state.getIn(['accounts', id], null);
@@ -20,23 +21,6 @@ export const makeGetAccount = () => {
   });
 };
 
-const toServerSideType = columnType => {
-  switch (columnType) {
-  case 'home':
-  case 'notifications':
-  case 'public':
-  case 'thread':
-  case 'account':
-    return columnType;
-  default:
-    if (columnType.indexOf('list:') > -1) {
-      return 'home';
-    } else {
-      return 'public'; // community, account, hashtag
-    }
-  }
-};
-
 const getFilters = (state, { contextType }) => {
   if (!contextType) return null;
 
@@ -73,6 +57,7 @@ export const makeGetStatus = () => {
         if (filterResults.some((result) => filters.getIn([result.get('filter'), 'filter_action']) === 'hide')) {
           return null;
         }
+        filterResults = filterResults.filter(result => filters.has(result.get('filter')));
         if (!filterResults.isEmpty()) {
           filtered = filterResults.map(result => filters.getIn([result.get('filter'), 'title']));
         }
diff --git a/app/javascript/mastodon/utils/filters.js b/app/javascript/mastodon/utils/filters.js
new file mode 100644
index 000000000..97b433a99
--- /dev/null
+++ b/app/javascript/mastodon/utils/filters.js
@@ -0,0 +1,16 @@
+export const toServerSideType = columnType => {
+  switch (columnType) {
+  case 'home':
+  case 'notifications':
+  case 'public':
+  case 'thread':
+  case 'account':
+    return columnType;
+  default:
+    if (columnType.indexOf('list:') > -1) {
+      return 'home';
+    } else {
+      return 'public'; // community, account, hashtag
+    }
+  }
+};
diff --git a/app/javascript/mastodon/utils/icons.js b/app/javascript/mastodon/utils/icons.js
new file mode 100644
index 000000000..be566032e
--- /dev/null
+++ b/app/javascript/mastodon/utils/icons.js
@@ -0,0 +1,13 @@
+// Copied from emoji-mart for consistency with emoji picker and since
+// they don't export the icons in the package
+export const loupeIcon = (
+  <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' width='13' height='13'>
+    <path d='M12.9 14.32a8 8 0 1 1 1.41-1.41l5.35 5.33-1.42 1.42-5.33-5.34zM8 14A6 6 0 1 0 8 2a6 6 0 0 0 0 12z' />
+  </svg>
+);
+
+export const deleteIcon = (
+  <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' width='13' height='13'>
+    <path d='M10 8.586L2.929 1.515 1.515 2.929 8.586 10l-7.071 7.071 1.414 1.414L10 11.414l7.071 7.071 1.414-1.414L11.414 10l7.071-7.071-1.414-1.414L10 8.586z' />
+  </svg>
+);
diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss
index e9e9a2faa..00f654082 100644
--- a/app/javascript/styles/mastodon/components.scss
+++ b/app/javascript/styles/mastodon/components.scss
@@ -5233,6 +5233,16 @@ a.status-card.compact:hover {
     line-height: 22px;
     color: lighten($inverted-text-color, 16%);
     margin-bottom: 30px;
+
+    a {
+      text-decoration: none;
+      color: $inverted-text-color;
+      font-weight: 500;
+
+      &:hover {
+        text-decoration: underline;
+      }
+    }
   }
 
   &__actions {
@@ -5379,6 +5389,14 @@ a.status-card.compact:hover {
     background: transparent;
     margin: 15px 0;
   }
+
+  .emoji-mart-search {
+    padding-right: 10px;
+  }
+
+  .emoji-mart-search-icon {
+    right: 10px + 5px;
+  }
 }
 
 .report-modal__container {
@@ -5939,6 +5957,13 @@ a.status-card.compact:hover {
     height: 100%;
   }
 
+  &.inactive {
+    audio,
+    .video-player__controls {
+      visibility: hidden;
+    }
+  }
+
   .video-player__volume::before,
   .video-player__seek::before {
     background: currentColor;