about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDavid Yip <yipdw@member.fsf.org>2018-01-21 18:00:08 -0600
committerGitHub <noreply@github.com>2018-01-21 18:00:08 -0600
commita90d0419d97db50cca034b9d30969f3d161a69b1 (patch)
tree86c6a4182cda85171caf2f5c1553c054ed7b7e1f
parent81b78fac542be867eedc7a0310e29de30b382770 (diff)
parent48d79007f616ba03f663d29536927f6ab14e4b53 (diff)
Merge pull request #343 from glitch-soc/merge-upstream-20180121
Merge upstream
-rw-r--r--Gemfile.lock2
-rw-r--r--app/controllers/settings/two_factor_authentication/confirmations_controller.rb6
-rw-r--r--app/helpers/settings_helper.rb1
-rw-r--r--app/javascript/mastodon/features/getting_started/index.js37
-rw-r--r--app/javascript/mastodon/features/ui/components/column_link.js7
-rw-r--r--app/javascript/mastodon/locales/hy.json263
-rw-r--r--app/javascript/mastodon/reducers/statuses.js2
-rw-r--r--app/javascript/styles/mastodon/components.scss11
-rw-r--r--app/views/notification_mailer/_status.html.haml2
-rw-r--r--config/application.rb1
-rw-r--r--config/webpack/configuration.js2
-rw-r--r--spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb7
12 files changed, 332 insertions, 9 deletions
diff --git a/Gemfile.lock b/Gemfile.lock
index 87298fc77..cb480ab6d 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -70,7 +70,7 @@ GEM
       coderay (>= 1.0.0)
       erubi (>= 1.0.0)
       rack (>= 0.9.0)
-    binding_of_caller (0.7.3)
+    binding_of_caller (0.8.0)
       debug_inspector (>= 0.0.1)
     bootsnap (1.1.5)
       msgpack (~> 1.0)
diff --git a/app/controllers/settings/two_factor_authentication/confirmations_controller.rb b/app/controllers/settings/two_factor_authentication/confirmations_controller.rb
index f1fa03f0a..8518c61ee 100644
--- a/app/controllers/settings/two_factor_authentication/confirmations_controller.rb
+++ b/app/controllers/settings/two_factor_authentication/confirmations_controller.rb
@@ -3,6 +3,8 @@
 module Settings
   module TwoFactorAuthentication
     class ConfirmationsController < BaseController
+      before_action :ensure_otp_secret
+
       def new
         prepare_two_factor_form
       end
@@ -34,6 +36,10 @@ module Settings
         @provision_url = current_user.otp_provisioning_uri(current_user.email, issuer: Rails.configuration.x.local_domain)
         @qrcode = RQRCode::QRCode.new(@provision_url)
       end
+
+      def ensure_otp_secret
+        redirect_to settings_two_factor_authentication_path unless current_user.otp_secret
+      end
     end
   end
 end
diff --git a/app/helpers/settings_helper.rb b/app/helpers/settings_helper.rb
index a63eb5e43..a2f5917f9 100644
--- a/app/helpers/settings_helper.rb
+++ b/app/helpers/settings_helper.rb
@@ -16,6 +16,7 @@ module SettingsHelper
     he: 'עברית',
     hr: 'Hrvatski',
     hu: 'Magyar',
+    hy: 'Հայերեն',
     id: 'Bahasa Indonesia',
     io: 'Ido',
     it: 'Italiano',
diff --git a/app/javascript/mastodon/features/getting_started/index.js b/app/javascript/mastodon/features/getting_started/index.js
index ee789e180..3a875169e 100644
--- a/app/javascript/mastodon/features/getting_started/index.js
+++ b/app/javascript/mastodon/features/getting_started/index.js
@@ -8,6 +8,8 @@ import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import ImmutablePureComponent from 'react-immutable-pure-component';
 import { me } from '../../initial_state';
+import { fetchFollowRequests } from '../../actions/accounts';
+import { List as ImmutableList } from 'immutable';
 
 const messages = defineMessages({
   heading: { id: 'getting_started.heading', defaultMessage: 'Getting started' },
@@ -32,9 +34,25 @@ const messages = defineMessages({
 const mapStateToProps = state => ({
   myAccount: state.getIn(['accounts', me]),
   columns: state.getIn(['settings', 'columns']),
+  unreadFollowRequests: state.getIn(['user_lists', 'follow_requests', 'items'], ImmutableList()).size,
+  unreadNotifications: state.getIn(['notifications', 'unread']),
 });
 
-@connect(mapStateToProps)
+const mapDispatchToProps = dispatch => ({
+  fetchFollowRequests: () => dispatch(fetchFollowRequests()),
+});
+
+const badgeDisplay = (number, limit) => {
+  if (number === 0) {
+    return undefined;
+  } else if (limit && number >= limit) {
+    return `${limit}+`;
+  } else {
+    return number;
+  }
+};
+
+@connect(mapStateToProps, mapDispatchToProps)
 @injectIntl
 export default class GettingStarted extends ImmutablePureComponent {
 
@@ -43,10 +61,21 @@ export default class GettingStarted extends ImmutablePureComponent {
     myAccount: ImmutablePropTypes.map.isRequired,
     columns: ImmutablePropTypes.list,
     multiColumn: PropTypes.bool,
+    fetchFollowRequests: PropTypes.func.isRequired,
+    unreadFollowRequests: PropTypes.number,
+    unreadNotifications: PropTypes.number,
   };
 
+  componentDidMount () {
+    const { myAccount, fetchFollowRequests } = this.props;
+
+    if (myAccount.get('locked')) {
+      fetchFollowRequests();
+    }
+  }
+
   render () {
-    const { intl, myAccount, columns, multiColumn } = this.props;
+    const { intl, myAccount, columns, multiColumn, unreadFollowRequests, unreadNotifications } = this.props;
 
     const navItems = [];
 
@@ -56,7 +85,7 @@ export default class GettingStarted extends ImmutablePureComponent {
       }
 
       if (!columns.find(item => item.get('id') === 'NOTIFICATIONS')) {
-        navItems.push(<ColumnLink key='1' icon='bell' text={intl.formatMessage(messages.notifications)} to='/notifications' />);
+        navItems.push(<ColumnLink key='1' icon='bell' text={intl.formatMessage(messages.notifications)} badge={badgeDisplay(unreadNotifications)} to='/notifications' />);
       }
 
       if (!columns.find(item => item.get('id') === 'COMMUNITY')) {
@@ -74,7 +103,7 @@ export default class GettingStarted extends ImmutablePureComponent {
     );
 
     if (myAccount.get('locked')) {
-      navItems.push(<ColumnLink key='6' icon='users' text={intl.formatMessage(messages.follow_requests)} to='/follow_requests' />);
+      navItems.push(<ColumnLink key='6' icon='users' text={intl.formatMessage(messages.follow_requests)} badge={badgeDisplay(unreadFollowRequests, 40)} to='/follow_requests' />);
     }
 
     if (multiColumn) {
diff --git a/app/javascript/mastodon/features/ui/components/column_link.js b/app/javascript/mastodon/features/ui/components/column_link.js
index a90616213..25c2d1cf8 100644
--- a/app/javascript/mastodon/features/ui/components/column_link.js
+++ b/app/javascript/mastodon/features/ui/components/column_link.js
@@ -2,12 +2,15 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import { Link } from 'react-router-dom';
 
-const ColumnLink = ({ icon, text, to, href, method }) => {
+const ColumnLink = ({ icon, text, to, href, method, badge }) => {
+  const badgeElement = typeof badge !== 'undefined' ? <span className='column-link__badge'>{badge}</span> : null;
+
   if (href) {
     return (
       <a href={href} className='column-link' data-method={method}>
         <i className={`fa fa-fw fa-${icon} column-link__icon`} />
         {text}
+        {badgeElement}
       </a>
     );
   } else {
@@ -15,6 +18,7 @@ const ColumnLink = ({ icon, text, to, href, method }) => {
       <Link to={to} className='column-link'>
         <i className={`fa fa-fw fa-${icon} column-link__icon`} />
         {text}
+        {badgeElement}
       </Link>
     );
   }
@@ -26,6 +30,7 @@ ColumnLink.propTypes = {
   to: PropTypes.string,
   href: PropTypes.string,
   method: PropTypes.string,
+  badge: PropTypes.node,
 };
 
 export default ColumnLink;
diff --git a/app/javascript/mastodon/locales/hy.json b/app/javascript/mastodon/locales/hy.json
new file mode 100644
index 000000000..152f0c525
--- /dev/null
+++ b/app/javascript/mastodon/locales/hy.json
@@ -0,0 +1,263 @@
+{
+  "account.block": "Արգելափակել @{name}֊ին",
+  "account.block_domain": "Թաքցնել ամենը հետեւյալ տիրույթից՝ {domain}",
+  "account.disclaimer_full": "Ներքոհիշյալը կարող է ոչ ամբողջությամբ արտացոլել օգտատիրոջ էջի տվյալները։",
+  "account.edit_profile": "Խմբագրել անձնական էջը",
+  "account.follow": "Հետեւել",
+  "account.followers": "Հետեւվողներ",
+  "account.follows": "Հետեւում է",
+  "account.follows_you": "Հետեւում է քեզ",
+  "account.hide_reblogs": "Թաքցնել @{name}֊ի տարածածները",
+  "account.media": "Մեդիա",
+  "account.mention": "Նշել @{name}֊ին",
+  "account.moved_to": "{name}֊ը տեղափոխվել է՝",
+  "account.mute": "Լռեցնել @{name}֊ին",
+  "account.mute_notifications": "Անջատել ծանուցումները @{name}֊ից",
+  "account.posts": "Գրառումներ",
+  "account.report": "Բողոքել @{name}֊ից",
+  "account.requested": "Հաստատման կարիք ունի։ Սեղմիր՝ հետեւելու հայցը չեղարկելու համար։",
+  "account.share": "Կիսվել @{name}֊ի էջով",
+  "account.show_reblogs": "Ցուցադրել @{name}֊ի տարածածները",
+  "account.unblock": "Ապաարգելափակել @{name}֊ին",
+  "account.unblock_domain": "Ցուցադրել {domain} թաքցված տիրույթի գրառումները",
+  "account.unfollow": "Չհետեւել",
+  "account.unmute": "Ապալռեցնել @{name}֊ին",
+  "account.unmute_notifications": "Միացնել ծանուցումները @{name}֊ից",
+  "account.view_full_profile": "Դիտել ամբողջական տարբերակը։",
+  "boost_modal.combo": "Կարող ես սեղմել {combo}՝ սա հաջորդ անգամ բաց թողնելու համար",
+  "bundle_column_error.body": "Այս բաղադրիչը բեռնելու ընթացքում ինչ֊որ բան խափանվեց։",
+  "bundle_column_error.retry": "Կրկին փորձել",
+  "bundle_column_error.title": "Ցանցային սխալ",
+  "bundle_modal_error.close": "Փակել",
+  "bundle_modal_error.message": "Այս բաղադրիչը բեռնելու ընթացքում ինչ֊որ բան խափանվեց։",
+  "bundle_modal_error.retry": "Կրկին փորձել",
+  "column.blocks": "Արգելափակված օգտատերեր",
+  "column.community": "Տեղական հոսք",
+  "column.favourites": "Հավանածներ",
+  "column.follow_requests": "Հետեւելու հայցեր",
+  "column.home": "Հիմնական",
+  "column.lists": "Ցանկեր",
+  "column.mutes": "Լռեցրած օգտատերեր",
+  "column.notifications": "Ծանուցումներ",
+  "column.pins": "Ամրացված թթեր",
+  "column.public": "Դաշնային հոսք",
+  "column_back_button.label": "Ետ",
+  "column_header.hide_settings": "Թաքցնել կարգավորումները",
+  "column_header.moveLeft_settings": "Տեղաշարժել սյունը ձախ",
+  "column_header.moveRight_settings": "Տեղաշարժել սյունը աջ",
+  "column_header.pin": "Ամրացնել",
+  "column_header.show_settings": "Ցուցադրել կարգավորումները",
+  "column_header.unpin": "Հանել",
+  "column_subheading.navigation": "Նավարկություն",
+  "column_subheading.settings": "Կարգավորումներ",
+  "compose_form.hashtag_warning": "Այս թութը չի հաշվառվի որեւէ պիտակի տակ, քանզի այն ծածուկ է։ Միայն հրապարակային թթերը հնարավոր է որոնել պիտակներով։",
+  "compose_form.lock_disclaimer": "Քո հաշիվը {locked} չէ։ Յուրաքանչյուր ոք կարող է հետեւել քեզ եւ տեսնել միայն հետեւողների համար նախատեսված գրառումները։",
+  "compose_form.lock_disclaimer.lock": "փակ",
+  "compose_form.placeholder": "Ի՞նչ կա մտքիդ",
+  "compose_form.publish": "Թթել",
+  "compose_form.publish_loud": "Թթե՜լ",
+  "compose_form.sensitive": "Նշել բովանդակությունը որպես կասկածելի",
+  "compose_form.spoiler": "Թաքցնել տեքստը նախազգուշացման ետեւում",
+  "compose_form.spoiler_placeholder": "Գրիր նախազգուշացումդ այստեղ",
+  "confirmation_modal.cancel": "Չեղարկել",
+  "confirmations.block.confirm": "Արգելափակել",
+  "confirmations.block.message": "Վստա՞հ ես, որ ուզում ես արգելափակել {name}֊ին։",
+  "confirmations.delete.confirm": "Ջնջել",
+  "confirmations.delete.message": "Վստա՞հ ես, որ ուզում ես ջնջել այս թութը։",
+  "confirmations.delete_list.confirm": "Ջնջել",
+  "confirmations.delete_list.message": "Վստա՞հ ես, որ ուզում ես մշտապես ջնջել այս ցանկը։",
+  "confirmations.domain_block.confirm": "Թաքցնել ամբողջ տիրույթը",
+  "confirmations.domain_block.message": "Հաստատ֊հաստա՞տ վստահ ես, որ ուզում ես արգելափակել ամբողջ {domain} տիրույթը։ Սովորաբար մի երկու թիրախավորված արգելափակում կամ լռեցում բավական է ու նախընտրելի։",
+  "confirmations.mute.confirm": "Լռեցնել",
+  "confirmations.mute.message": "Վստա՞հ ես, որ ուզում ես {name}֊ին լռեցնել։",
+  "confirmations.unfollow.confirm": "Ապահետեւել",
+  "confirmations.unfollow.message": "Վստա՞հ ես, որ ուզում ես այլեւս չհետեւել {name}֊ին։",
+  "embed.instructions": "Այս թութը քո կայքում ներդնելու համար կարող ես պատճենել ներքոհիշյալ կոդը։",
+  "embed.preview": "Ահա, թե ինչ տեսք կունենա այն՝",
+  "emoji_button.activity": "Զբաղմունքներ",
+  "emoji_button.custom": "Հատուկ",
+  "emoji_button.flags": "Դրոշներ",
+  "emoji_button.food": "Կերուխում",
+  "emoji_button.label": "Էմոջի ավելացնել",
+  "emoji_button.nature": "Բնություն",
+  "emoji_button.not_found": "Նման էմոջիներ դեռ չեն հայտնաբերվել։ (╯°□°)╯︵ ┻━┻",
+  "emoji_button.objects": "Առարկաներ",
+  "emoji_button.people": "Մարդիկ",
+  "emoji_button.recent": "Հաճախ օգտագործվող",
+  "emoji_button.search": "Որոնել…",
+  "emoji_button.search_results": "Որոնման արդյունքներ",
+  "emoji_button.symbols": "Նշաններ",
+  "emoji_button.travel": "Ուղեւորություն եւ տեղանքներ",
+  "empty_column.community": "Տեղական հոսքը դատա՛րկ է։ Հրապարակային մի բան գրիր շարժիչը խոդ տալու համար։",
+  "empty_column.hashtag": "Այս պիտակով դեռ ոչինչ չկա։",
+  "empty_column.home": "Քո հիմնական հոսքը դատա՛րկ է։ Այցելի՛ր {public}ը կամ օգտվիր որոնումից՝ այլ մարդկանց հանդիպելու համար։",
+  "empty_column.home.public_timeline": "հրապարակային հոսք",
+  "empty_column.list": "Այս ցանկում դեռ ոչինչ չկա։ Երբ ցանկի անդամներից որեւէ մեկը նոր թութ գրի, այն կհայտնվի այստեղ։",
+  "empty_column.notifications": "Ոչ մի ծանուցում դեռ չունես։ Բզիր մյուսներին՝ խոսակցությունը սկսելու համար։",
+  "empty_column.public": "Այստեղ բան չկա՛։ Հրապարակային մի բան գրիր կամ հետեւիր այլ հանգույցներից էակների՝ այն լցնելու համար։",
+  "follow_request.authorize": "Վավերացնել",
+  "follow_request.reject": "Մերժել",
+  "getting_started.appsshort": "Հավելվածներ",
+  "getting_started.faq": "ՀՏՀ",
+  "getting_started.heading": "Ինչպես սկսել",
+  "getting_started.open_source_notice": "Մաստոդոնը բաց ելատեքստով ծրագրակազմ է։ Կարող ես ներդրում անել կամ վրեպներ զեկուցել ԳիթՀաբում՝ {github}։",
+  "getting_started.userguide": "Ձեռնարկ",
+  "home.column_settings.advanced": "Առաջադեմ",
+  "home.column_settings.basic": "Հիմնական",
+  "home.column_settings.filter_regex": "Զտել օրինաչափ արտահայտությամբ",
+  "home.column_settings.show_reblogs": "Ցուցադրել տարածածները",
+  "home.column_settings.show_replies": "Ցուցադրել պատասխանները",
+  "home.settings": "Սյան կարգավորումներ",
+  "keyboard_shortcuts.back": "ետ նավարկելու համար",
+  "keyboard_shortcuts.boost": "տարածելու համար",
+  "keyboard_shortcuts.column": "սյուներից մեկի վրա սեւեռվելու համար",
+  "keyboard_shortcuts.compose": "շարադրման տիրույթին սեւեռվելու համար",
+  "keyboard_shortcuts.description": "Նկարագրություն",
+  "keyboard_shortcuts.down": "ցանկով ներքեւ շարժվելու համար",
+  "keyboard_shortcuts.enter": "թութը բացելու համար",
+  "keyboard_shortcuts.favourite": "հավանելու համար",
+  "keyboard_shortcuts.heading": "Ստեղնաշարի կարճատներ",
+  "keyboard_shortcuts.hotkey": "Հատուկ ստեղն",
+  "keyboard_shortcuts.legend": "այս ձեռնարկը ցուցադրելու համար",
+  "keyboard_shortcuts.mention": "հեղինակին նշելու համար",
+  "keyboard_shortcuts.reply": "պատասխանելու համար",
+  "keyboard_shortcuts.search": "որոնման դաշտին սեւեռվելու համար",
+  "keyboard_shortcuts.toot": "թարմ թութ սկսելու համար",
+  "keyboard_shortcuts.unfocus": "տեքստի/որոնման տիրույթից ապասեւեռվելու համար",
+  "keyboard_shortcuts.up": "ցանկով վերեւ շարժվելու համար",
+  "lightbox.close": "Փակել",
+  "lightbox.next": "Հաջորդ",
+  "lightbox.previous": "Նախորդ",
+  "lists.account.add": "Ավելացնել ցանկին",
+  "lists.account.remove": "Հանել ցանկից",
+  "lists.delete": "Ջնջել ցանկը",
+  "lists.edit": "Փոփոխել ցանկը",
+  "lists.new.create": "Ավելացնել ցանկ",
+  "lists.new.title_placeholder": "Նոր ցանկի վերնագիր",
+  "lists.search": "Փնտրել քո հետեւած մարդկանց մեջ",
+  "lists.subheading": "Քո ցանկերը",
+  "loading_indicator.label": "Բեռնվում է…",
+  "media_gallery.toggle_visible": "Ցուցադրել/թաքցնել",
+  "missing_indicator.label": "Չգտնվեց",
+  "mute_modal.hide_notifications": "Թաքցնե՞լ ցանուցումներն այս օգտատիրոջից։",
+  "navigation_bar.blocks": "Արգելափակված օգտատերեր",
+  "navigation_bar.community_timeline": "Տեղական հոսք",
+  "navigation_bar.edit_profile": "Խմբագրել անձնական էջը",
+  "navigation_bar.favourites": "Հավանածներ",
+  "navigation_bar.follow_requests": "Հետեւելու հայցեր",
+  "navigation_bar.info": "Այս հանգույցի մասին",
+  "navigation_bar.keyboard_shortcuts": "Ստեղնաշարի կարճատներ",
+  "navigation_bar.lists": "Ցանկեր",
+  "navigation_bar.logout": "Դուրս գալ",
+  "navigation_bar.mutes": "Լռեցրած օգտատերեր",
+  "navigation_bar.pins": "Ամրացված թթեր",
+  "navigation_bar.preferences": "Նախապատվություններ",
+  "navigation_bar.public_timeline": "Դաշնային հոսք",
+  "notification.favourite": "{name} հավանեց թութդ",
+  "notification.follow": "{name} սկսեց հետեւել քեզ",
+  "notification.mention": "{name} նշեց քեզ",
+  "notification.reblog": "{name} տարածեց թութդ",
+  "notifications.clear": "Մաքրել ծանուցումները",
+  "notifications.clear_confirmation": "Վստա՞հ ես, որ ուզում ես մշտապես մաքրել քո բոլոր ծանուցումները։",
+  "notifications.column_settings.alert": "Աշխատատիրույթի ծանուցումներ",
+  "notifications.column_settings.favourite": "Հավանածներից՝",
+  "notifications.column_settings.follow": "Նոր հետեւողներ՝",
+  "notifications.column_settings.mention": "Նշումներ՝",
+  "notifications.column_settings.push": "Հրելու ծանուցումներ",
+  "notifications.column_settings.push_meta": "Այս սարքը",
+  "notifications.column_settings.reblog": "Տարածածներից՝",
+  "notifications.column_settings.show": "Ցուցադրել սյունում",
+  "notifications.column_settings.sound": "Ձայն հանել",
+  "onboarding.done": "Պատրաստ է",
+  "onboarding.next": "Հաջորդ",
+  "onboarding.page_five.public_timelines": "Տեղական հոսքը ցույց է տալիս {domain} տիրույթից բոլորի հրապարակային թթերը։ Դաշնային հոսքը ցույց է տալիս հրապարակային թթերը բոլորից, ում {domain} տիրույթի մարդիկ հետեւում են։ Սրանք Հրապարակային հոսքերն են՝ նոր մարդկանց բացահայտելու հրաշալի միջոց։",
+  "onboarding.page_four.home": "Հիմնական հոսքը ցույց է տալիս այն մարդկանց թթերը, ում հետեւում ես։",
+  "onboarding.page_four.notifications": "Ծանուցումների սյունը ցույց է տալիս, երբ որեւէ մեկը փոխգործակցում է հետդ։",
+  "onboarding.page_one.federation": "Մաստոդոնը անկախ սպասարկիչների ցանց է, որոնք միասնական սոցիալական ցանց են կազմում։ Մենք կոչում ենք այդ սպասարկիչները հանգույցներ։",
+  "onboarding.page_one.full_handle": "Քո ամբողջական օգտանունը",
+  "onboarding.page_one.handle_hint": "Սա այն է, ինչ ասելու ես ընկերներիդ՝ քեզ փնտրելու համար։",
+  "onboarding.page_one.welcome": "Բարի գալուստ Մաստոդո՜ն",
+  "onboarding.page_six.admin": "Քո հանգույցի ադմինը նա է՝ {admin}։",
+  "onboarding.page_six.almost_done": "Գրեթե պատրաստ է…",
+  "onboarding.page_six.appetoot": "Հաջողութությո՜ւն",
+  "onboarding.page_six.apps_available": "Նաեւ կան այՕՍի, Անդրոիդի եւ այլ հարթակների համար {apps}։",
+  "onboarding.page_six.github": "Մաստոդոնն ազատ ու բաց ելատեքստով ծրագրակազմ է։ Կարող ես վրեպներ զեկուցել, նոր հատկություններ հայցել կամ ներդրում անել {github}֊ում։",
+  "onboarding.page_six.guidelines": "համայնքի կանոնակարգ",
+  "onboarding.page_six.read_guidelines": "Խնդրում ենք, կարդա {domain} տիրույթի {guidelines}ը։",
+  "onboarding.page_six.various_app": "հավելվածներ",
+  "onboarding.page_three.profile": "Թարմացրու անձնական էջդ՝ նկարդ, կենսագրությունդ ու անունդ փոխելու համար։ Այնտեղ նաեւ այլ նախապատվություններ կգտնես։",
+  "onboarding.page_three.search": "Օգտվիր որոնման դաշտից՝ մարդկանց գտնելու կամ պիտակներին՝ օրինակ {illustration} ու {introductions}, ծանոթանալու համար։ Ոչ այս հանգույցի բնակիչներին փնտրելու համար օգտագործիր նրանց ամբողջական օգտանունը։",
+  "onboarding.page_two.compose": "Գրիր թթերդ շարադրման սյունակում։ Կարող ես նկարներ վերբեռնել, փոփոխել գաղտնիության կարգավորումները եւ բովանդակության վերաբերյալ նախազգուշացումներ ավելացնել՝ օգտվելով ներքեւի պատկերակներից։",
+  "onboarding.skip": "Բաց թողնել",
+  "privacy.change": "Կարգավորել թթի գաղտնիությունը",
+  "privacy.direct.long": "Թթել միայն նշված օգտատերերի համար",
+  "privacy.direct.short": "Հասցեագրված",
+  "privacy.private.long": "Թթել միայն հետեւողների համար",
+  "privacy.private.short": "Միայն հետեւողներին",
+  "privacy.public.long": "Թթել հրապարակային հոսքերում",
+  "privacy.public.short": "Հրապարակային",
+  "privacy.unlisted.long": "Չթթել հրապարակային հոսքերում",
+  "privacy.unlisted.short": "Ծածուկ",
+  "relative_time.days": "{number}օր",
+  "relative_time.hours": "{number}ժ",
+  "relative_time.just_now": "նոր",
+  "relative_time.minutes": "{number}ր",
+  "relative_time.seconds": "{number}վ",
+  "reply_indicator.cancel": "Չեղարկել",
+  "report.placeholder": "Լրացուցիչ մեկնաբանություններ",
+  "report.submit": "Ուղարկել",
+  "report.target": "Բողոքել {target}֊ի մասին",
+  "search.placeholder": "Փնտրել",
+  "search_popout.search_format": "Փնտրելու առաջադեմ ձեւ",
+  "search_popout.tips.hashtag": "պիտակ",
+  "search_popout.tips.status": "թութ",
+  "search_popout.tips.text": "Հասարակ տեքստը կվերադարձնի համընկնող անուններ, օգտանուններ ու պիտակներ",
+  "search_popout.tips.user": "օգտատեր",
+  "search_results.total": "{count, number} {count, plural, one {result} other {results}}",
+  "standalone.public_title": "Այս պահին…",
+  "status.block": "Արգելափակել @{name}֊ին",
+  "status.cannot_reblog": "Այս թութը չի կարող տարածվել",
+  "status.delete": "Ջնջել",
+  "status.embed": "Ներդնել",
+  "status.favourite": "Հավանել",
+  "status.load_more": "Բեռնել ավելին",
+  "status.media_hidden": "մեդիաբովանդակությունը թաքցված է",
+  "status.mention": "Նշել @{name}֊ին",
+  "status.more": "Ավելին",
+  "status.mute": "Լռեցնել @{name}֊ին",
+  "status.mute_conversation": "Լռեցնել խոսակցությունը",
+  "status.open": "Ընդարձակել այս թութը",
+  "status.pin": "Ամրացնել անձնական էջում",
+  "status.reblog": "Տարածել",
+  "status.reblogged_by": "{name} տարածել է",
+  "status.reply": "Պատասխանել",
+  "status.replyAll": "Պատասխանել թելին",
+  "status.report": "Բողոքել @{name}֊ից",
+  "status.sensitive_toggle": "Կտացրու՝ դիտելու համար",
+  "status.sensitive_warning": "Կասկածելի բովանդակություն",
+  "status.share": "Կիսվել",
+  "status.show_less": "Պակաս",
+  "status.show_more": "Ավելին",
+  "status.unmute_conversation": "Ապալռեցնել խոսակցությունը",
+  "status.unpin": "Հանել անձնական էջից",
+  "tabs_bar.compose": "Շարադրել",
+  "tabs_bar.federated_timeline": "Դաշնային",
+  "tabs_bar.home": "Հիմնական",
+  "tabs_bar.local_timeline": "Տեղական",
+  "tabs_bar.notifications": "Ծանուցումներ",
+  "ui.beforeunload": "Քո սեւագիրը կկորի, եթե լքես Մաստոդոնը։",
+  "upload_area.title": "Քաշիր ու նետիր՝ վերբեռնելու համար",
+  "upload_button.label": "Ավելացնել մեդիա",
+  "upload_form.description": "Նկարագրություն ավելացրու տեսողական խնդիրներ ունեցողների համար",
+  "upload_form.undo": "Հետարկել",
+  "upload_progress.label": "Վերբեռնվում է…",
+  "video.close": "Փակել  տեսագրությունը",
+  "video.exit_fullscreen": "Անջատել լիաէկրան դիտումը",
+  "video.expand": "Ընդարձակել տեսագրությունը",
+  "video.fullscreen": "Լիաէկրան",
+  "video.hide": "Թաքցնել տեսագրությունը",
+  "video.mute": "Լռեցնել ձայնը",
+  "video.pause": "Դադար տալ",
+  "video.play": "Նվագել",
+  "video.unmute": "Միացնել ձայնը"
+}
\ No newline at end of file
diff --git a/app/javascript/mastodon/reducers/statuses.js b/app/javascript/mastodon/reducers/statuses.js
index 5120b2b67..cc0d4dacd 100644
--- a/app/javascript/mastodon/reducers/statuses.js
+++ b/app/javascript/mastodon/reducers/statuses.js
@@ -54,7 +54,7 @@ const normalizeStatus = (state, status) => {
     normalStatus.reblog = status.reblog.id;
   }
 
-  const searchContent = [status.spoiler_text, status.content].join('\n\n').replace(/<br \/>/g, '\n').replace(/<\/p><p>/g, '\n\n');
+  const searchContent = [status.spoiler_text, status.content].join('\n\n').replace(/<br\s*\/?>/g, '\n').replace(/<\/p><p>/g, '\n\n');
 
   const emojiMap = normalStatus.emojis.reduce((obj, emoji) => {
     obj[`:${emoji.shortcode}:`] = emoji;
diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss
index 75e37237b..3eb941a23 100644
--- a/app/javascript/styles/mastodon/components.scss
+++ b/app/javascript/styles/mastodon/components.scss
@@ -2070,6 +2070,17 @@
   margin-right: 5px;
 }
 
+.column-link__badge {
+  display: inline-block;
+  border-radius: 4px;
+  font-size: 12px;
+  line-height: 19px;
+  font-weight: 500;
+  background: $ui-base-color;
+  padding: 4px 8px;
+  margin: -6px 10px;
+}
+
 .column-subheading {
   background: $ui-base-color;
   color: $ui-base-lighter-color;
diff --git a/app/views/notification_mailer/_status.html.haml b/app/views/notification_mailer/_status.html.haml
index 85f9294e9..727e914dc 100644
--- a/app/views/notification_mailer/_status.html.haml
+++ b/app/views/notification_mailer/_status.html.haml
@@ -19,7 +19,7 @@
                                 %tbody
                                   %tr
                                     %td{ align: 'left', width: 48 }
-                                      = image_tag full_asset_url(status.account.avatar), alt:''
+                                      = image_tag full_asset_url(status.account.avatar.url), alt:''
                                     %td{ align: 'left' }
                                       %bdi= display_name(status.account)
                                       = "@#{status.account.acct}"
diff --git a/config/application.rb b/config/application.rb
index ef97dbc06..17bb02b3f 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -47,6 +47,7 @@ module Mastodon
       :he,
       :hr,
       :hu,
+      :hy,
       :id,
       :io,
       :it,
diff --git a/config/webpack/configuration.js b/config/webpack/configuration.js
index f6b4d4c61..c58d8028e 100644
--- a/config/webpack/configuration.js
+++ b/config/webpack/configuration.js
@@ -73,7 +73,7 @@ function formatPublicPath(host = '', path = '') {
 
 const output = {
   path: resolve('public', settings.public_output_path),
-  publicPath: formatPublicPath(env.ASSET_HOST || env.LOCAL_DOMAIN, settings.public_output_path),
+  publicPath: formatPublicPath(env.ASSET_HOST || env.WEB_DOMAIN || env.LOCAL_DOMAIN, settings.public_output_path),
 };
 
 module.exports = {
diff --git a/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb b/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb
index 0676d6161..aee82a3d8 100644
--- a/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb
+++ b/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb
@@ -6,6 +6,7 @@ describe Settings::TwoFactorAuthentication::ConfirmationsController do
   render_views
 
   let(:user) { Fabricate(:user, email: 'local-part@domain', otp_secret: 'thisisasecretforthespecofnewview') }
+  let(:user_without_otp_secret) { Fabricate(:user, email: 'local-part@domain') }
 
   shared_examples 'renders :new' do
     it 'renders the new view' do
@@ -33,6 +34,12 @@ describe Settings::TwoFactorAuthentication::ConfirmationsController do
       get :new
       expect(response).to redirect_to('/auth/sign_in')
     end
+
+    it 'redirects if user do not have otp_secret' do
+      sign_in user_without_otp_secret, scope: :user
+      get :new
+      expect(response).to redirect_to('/settings/two_factor_authentication')
+    end
   end
 
   describe 'POST #create' do