aboutsummaryrefslogtreecommitdiff
path: root/src/components
diff options
context:
space:
mode:
Diffstat (limited to 'src/components')
-rw-r--r--src/components/attachment/attachment.vue2
-rw-r--r--src/components/interface_language_switcher/interface_language_switcher.vue38
-rw-r--r--src/components/notification/notification.vue11
-rw-r--r--src/components/notifications/notifications.js28
-rw-r--r--src/components/notifications/notifications.scss49
-rw-r--r--src/components/notifications/notifications.vue11
-rw-r--r--src/components/post_status_form/post_status_form.js6
-rw-r--r--src/components/post_status_form/post_status_form.vue5
-rw-r--r--src/components/settings/settings.js8
-rw-r--r--src/components/settings/settings.vue14
-rw-r--r--src/components/status/status.js58
-rw-r--r--src/components/status/status.vue8
-rw-r--r--src/components/user_card_content/user_card_content.vue10
-rw-r--r--src/components/who_to_follow_panel/who_to_follow_panel.js48
-rw-r--r--src/components/who_to_follow_panel/who_to_follow_panel.vue4
15 files changed, 235 insertions, 65 deletions
diff --git a/src/components/attachment/attachment.vue b/src/components/attachment/attachment.vue
index d01c8566..bbb43679 100644
--- a/src/components/attachment/attachment.vue
+++ b/src/components/attachment/attachment.vue
@@ -10,7 +10,7 @@
<a href="#" @click.prevent="toggleHidden()">Hide</a>
</div>
- <a v-if="type === 'image' && !hidden" class="image-attachment" :href="attachment.url" target="_blank">
+ <a v-if="type === 'image' && !hidden" class="image-attachment" :href="attachment.url" target="_blank" :title="attachment.description">
<StillImage :class="{'small': isSmall}" referrerpolicy="no-referrer" :mimetype="attachment.mimetype" :src="attachment.large_thumb_url || attachment.url"/>
</a>
diff --git a/src/components/interface_language_switcher/interface_language_switcher.vue b/src/components/interface_language_switcher/interface_language_switcher.vue
new file mode 100644
index 00000000..4b541888
--- /dev/null
+++ b/src/components/interface_language_switcher/interface_language_switcher.vue
@@ -0,0 +1,38 @@
+<template>
+ <div>
+ <label for="interface-language-switcher" class='select'>
+ <select id="interface-language-switcher" v-model="language">
+ <option v-for="(langCode, i) in languageCodes" :value="langCode">
+ {{ languageNames[i] }}
+ </option>
+ </select>
+ <i class="icon-down-open"/>
+ </label>
+ </div>
+</template>
+
+<script>
+ import languagesObject from '../../i18n/messages'
+ import ISO6391 from 'iso-639-1'
+ import _ from 'lodash'
+
+ export default {
+ computed: {
+ languageCodes () {
+ return Object.keys(languagesObject)
+ },
+
+ languageNames () {
+ return _.map(this.languageCodes, ISO6391.getName)
+ },
+
+ language: {
+ get: function () { return this.$store.state.config.interfaceLanguage },
+ set: function (val) {
+ this.$store.dispatch('setOption', { name: 'interfaceLanguage', value: val })
+ this.$i18n.locale = val
+ }
+ }
+ }
+ }
+</script>
diff --git a/src/components/notification/notification.vue b/src/components/notification/notification.vue
index bb76ddf8..72c1ca69 100644
--- a/src/components/notification/notification.vue
+++ b/src/components/notification/notification.vue
@@ -12,7 +12,7 @@
<div class="name-and-action">
<span class="username" v-if="!!notification.action.user.name_html" :title="'@'+notification.action.user.screen_name" v-html="notification.action.user.name_html"></span>
<span class="username" v-else :title="'@'+notification.action.user.screen_name">{{ notification.action.user.name }}</span>
- <span v-if="notification.type === 'favorite'">
+ <span v-if="notification.type === 'like'">
<i class="fa icon-star lit"></i>
<small>{{$t('notifications.favorited_you')}}</small>
</span>
@@ -25,12 +25,17 @@
<small>{{$t('notifications.followed_you')}}</small>
</span>
</div>
- <small class="timeago"><router-link :to="{ name: 'conversation', params: { id: notification.status.id } }"><timeago :since="notification.action.created_at" :auto-update="240"></timeago></router-link></small>
+ <small class="timeago"><router-link v-if="notification.status" :to="{ name: 'conversation', params: { id: notification.status.id } }"><timeago :since="notification.action.created_at" :auto-update="240"></timeago></router-link></small>
</span>
<div class="follow-text" v-if="notification.type === 'follow'">
<router-link :to="{ name: 'user-profile', params: { id: notification.action.user.id } }">@{{notification.action.user.screen_name}}</router-link>
</div>
- <status v-else class="faint" :compact="true" :statusoid="notification.status" :noHeading="true"></status>
+ <template v-else>
+ <status v-if="notification.status" class="faint" :compact="true" :statusoid="notification.status" :noHeading="true"></status>
+ <div class="broken-favorite" v-else>
+ {{$t('notifications.broken_favorite')}}
+ </div>
+ </template>
</div>
</div>
</template>
diff --git a/src/components/notifications/notifications.js b/src/components/notifications/notifications.js
index f8314bfc..b24250b0 100644
--- a/src/components/notifications/notifications.js
+++ b/src/components/notifications/notifications.js
@@ -1,16 +1,21 @@
import Notification from '../notification/notification.vue'
+import notificationsFetcher from '../../services/notifications_fetcher/notifications_fetcher.service.js'
-import { sortBy, take, filter } from 'lodash'
+import { sortBy, filter } from 'lodash'
const Notifications = {
- data () {
- return {
- visibleNotificationCount: 20
- }
+ created () {
+ const store = this.$store
+ const credentials = store.state.users.currentUser.credentials
+
+ notificationsFetcher.startFetching({ store, credentials })
},
computed: {
notifications () {
- return this.$store.state.statuses.notifications
+ return this.$store.state.statuses.notifications.data
+ },
+ error () {
+ return this.$store.state.statuses.notifications.error
},
unseenNotifications () {
return filter(this.notifications, ({seen}) => !seen)
@@ -19,7 +24,7 @@ const Notifications = {
// Don't know why, but sortBy([seen, -action.id]) doesn't work.
let sortedNotifications = sortBy(this.notifications, ({action}) => -action.id)
sortedNotifications = sortBy(sortedNotifications, 'seen')
- return take(sortedNotifications, this.visibleNotificationCount)
+ return sortedNotifications
},
unseenCount () {
return this.unseenNotifications.length
@@ -40,6 +45,15 @@ const Notifications = {
methods: {
markAsSeen () {
this.$store.commit('markNotificationsAsSeen', this.visibleNotifications)
+ },
+ fetchOlderNotifications () {
+ const store = this.$store
+ const credentials = store.state.users.currentUser.credentials
+ notificationsFetcher.fetchAndUpdate({
+ store,
+ credentials,
+ older: true
+ })
}
}
}
diff --git a/src/components/notifications/notifications.scss b/src/components/notifications/notifications.scss
index 5853c68e..5b09685b 100644
--- a/src/components/notifications/notifications.scss
+++ b/src/components/notifications/notifications.scss
@@ -4,6 +4,10 @@
// a bit of a hack to allow scrolling below notifications
padding-bottom: 15em;
+ .title {
+ display: inline-block;
+ }
+
.panel {
background: $fallback--bg;
background: var(--bg, $fallback--bg)
@@ -22,6 +26,8 @@
background: var(--btn, $fallback--btn);
color: $fallback--fg;
color: var(--fg, $fallback--fg);
+ display: flex;
+ align-items: baseline;
.read-button {
position: absolute;
right: 0.7em;
@@ -44,6 +50,19 @@
line-height: 1.3em;
}
+ .loadmore-error {
+ position: absolute;
+ right: 0.6em;
+ font-size: 14px;
+ min-width: 6em;
+ font-family: sans-serif;
+ text-align: center;
+ padding: 0 0.25em 0 0.25em;
+ margin: 0;
+ color: $fallback--fg;
+ color: var(--fg, $fallback--fg);
+ }
+
.unseen {
box-shadow: inset 4px 0 0 var(--cRed, $fallback--cRed);
padding-left: 0;
@@ -56,6 +75,16 @@
border-bottom: 1px solid;
border-bottom-color: inherit;
+ .broken-favorite {
+ border-radius: $fallback--tooltipRadius;
+ border-radius: var(--tooltipRadius, $fallback--tooltipRadius);
+ color: $fallback--faint;
+ color: var(--faint, $fallback--faint);
+ background-color: $fallback--cAlertRed;
+ background-color: var(--cAlertRed, $fallback--cAlertRed);
+ padding: 2px .5em
+ }
+
.avatar-compact {
width: 32px;
height: 32px;
@@ -69,7 +98,7 @@
}
}
- &:hover .animated.avatar {
+ &:hover .animated.avatar-compact {
canvas {
display: none;
}
@@ -145,6 +174,13 @@
max-width: 100%;
text-overflow: ellipsis;
white-space: nowrap;
+
+ img {
+ width: 14px;
+ height: 14px;
+ vertical-align: middle;
+ object-fit: contain
+ }
}
.timeago {
float: right;
@@ -194,15 +230,4 @@
margin-bottom: 0.3em;
}
}
-
- // ugly as heck
- &:last-child {
- border-bottom: none;
- border-radius: 0 0 $fallback--panelRadius $fallback--panelRadius;
- border-radius: 0 0 var(--panelRadius, $fallback--panelRadius) var(--panelRadius, $fallback--panelRadius);
- .status-el {
- border-radius: 0 0 $fallback--panelRadius $fallback--panelRadius;
- border-radius: 0 0 var(--panelRadius, $fallback--panelRadius) var(--panelRadius, $fallback--panelRadius);
- }
- }
}
diff --git a/src/components/notifications/notifications.vue b/src/components/notifications/notifications.vue
index 4fa6e925..a0b0e5f5 100644
--- a/src/components/notifications/notifications.vue
+++ b/src/components/notifications/notifications.vue
@@ -3,7 +3,10 @@
<div class="panel panel-default">
<div class="panel-heading">
<span class="unseen-count" v-if="unseenCount">{{unseenCount}}</span>
- {{$t('notifications.notifications')}}
+ <div class="title"> {{$t('notifications.notifications')}}</div>
+ <div @click.prevent class="loadmore-error alert error" v-if="error">
+ {{$t('timeline.error_fetching')}}
+ </div>
<button v-if="unseenCount" @click.prevent="markAsSeen" class="read-button">{{$t('notifications.read')}}</button>
</div>
<div class="panel-body">
@@ -11,6 +14,12 @@
<notification :notification="notification"></notification>
</div>
</div>
+ <div class="panel-footer">
+ <a href="#" v-on:click.prevent='fetchOlderNotifications()' v-if="!notifications.loading">
+ <div class="new-status-notification text-center panel-footer">{{$t('notifications.load_older')}}</div>
+ </a>
+ <div class="new-status-notification text-center panel-footer" v-else>...</div>
+ </div>
</div>
</div>
</template>
diff --git a/src/components/post_status_form/post_status_form.js b/src/components/post_status_form/post_status_form.js
index ff3bb906..7d40bc3c 100644
--- a/src/components/post_status_form/post_status_form.js
+++ b/src/components/post_status_form/post_status_form.js
@@ -24,7 +24,8 @@ const PostStatusForm = {
'replyTo',
'repliedUser',
'attentions',
- 'messageScope'
+ 'messageScope',
+ 'subject'
],
components: {
MediaUpload
@@ -52,7 +53,9 @@ const PostStatusForm = {
posting: false,
highlighted: 0,
newStatus: {
+ spoilerText: this.subject,
status: statusText,
+ nsfw: false,
files: [],
visibility: this.messageScope || this.$store.state.users.currentUser.default_scope
},
@@ -204,6 +207,7 @@ const PostStatusForm = {
status: newStatus.status,
spoilerText: newStatus.spoilerText || null,
visibility: newStatus.visibility,
+ sensitive: newStatus.nsfw,
media: newStatus.files,
store: this.$store,
inReplyToStatusId: this.replyTo
diff --git a/src/components/post_status_form/post_status_form.vue b/src/components/post_status_form/post_status_form.vue
index 2b84758b..9f8b2661 100644
--- a/src/components/post_status_form/post_status_form.vue
+++ b/src/components/post_status_form/post_status_form.vue
@@ -75,6 +75,11 @@
</div>
</div>
</div>
+ <div class="upload_settings" v-if="newStatus.files.length > 0">
+ <input type="checkbox" id="filesSensitive" v-model="newStatus.nsfw">
+ <label for="filesSensitive" v-if="newStatus.nsfw">{{$t('post_status.attachments_sensitive')}}</label>
+ <label for="filesSensitive" v-else v-html="$t('post_status.attachments_not_sensitive')"></label>
+ </div>
</form>
</div>
</template>
diff --git a/src/components/settings/settings.js b/src/components/settings/settings.js
index c85ef59f..f8eaad00 100644
--- a/src/components/settings/settings.js
+++ b/src/components/settings/settings.js
@@ -1,5 +1,6 @@
/* eslint-env browser */
import StyleSwitcher from '../style_switcher/style_switcher.vue'
+import InterfaceLanguageSwitcher from '../interface_language_switcher/interface_language_switcher.vue'
import { filter, trim } from 'lodash'
const settings = {
@@ -8,6 +9,7 @@ const settings = {
hideAttachmentsLocal: this.$store.state.config.hideAttachments,
hideAttachmentsInConvLocal: this.$store.state.config.hideAttachmentsInConv,
hideNsfwLocal: this.$store.state.config.hideNsfw,
+ replyVisibilityLocal: this.$store.state.config.replyVisibility,
loopVideoLocal: this.$store.state.config.loopVideo,
loopVideoSilentOnlyLocal: this.$store.state.config.loopVideoSilentOnly,
muteWordsString: this.$store.state.config.muteWords.join('\n'),
@@ -27,7 +29,8 @@ const settings = {
}
},
components: {
- StyleSwitcher
+ StyleSwitcher,
+ InterfaceLanguageSwitcher
},
computed: {
user () {
@@ -44,6 +47,9 @@ const settings = {
hideNsfwLocal (value) {
this.$store.dispatch('setOption', { name: 'hideNsfw', value })
},
+ replyVisibilityLocal (value) {
+ this.$store.dispatch('setOption', { name: 'replyVisibility', value })
+ },
loopVideoLocal (value) {
this.$store.dispatch('setOption', { name: 'loopVideo', value })
},
diff --git a/src/components/settings/settings.vue b/src/components/settings/settings.vue
index 415317f0..f500a1b0 100644
--- a/src/components/settings/settings.vue
+++ b/src/components/settings/settings.vue
@@ -38,6 +38,16 @@
<input type="checkbox" id="hoverPreview" v-model="hoverPreviewLocal">
<label for="hoverPreview">{{$t('settings.reply_link_preview')}}</label>
</li>
+ <li>
+ <label for="replyVisibility" class="select">
+ <select id="replyVisibility" v-model="replyVisibilityLocal">
+ <option value="all" selected>{{$t('settings.reply_visibility_all')}}</option>
+ <option value="following">{{$t('settings.reply_visibility_following')}}</option>
+ <option value="self">{{$t('settings.reply_visibility_self')}}</option>
+ </select>
+ <i class="icon-down-open"/>
+ </label>
+ </li>
</ul>
</div>
<div class="setting-item">
@@ -74,6 +84,10 @@
</li>
</ul>
</div>
+ <div class="setting-item">
+ <h2>{{ $t('settings.interfaceLanguage') }}</h2>
+ <interface-language-switcher />
+ </div>
</div>
</div>
</template>
diff --git a/src/components/status/status.js b/src/components/status/status.js
index 9670f69d..a6c49f7c 100644
--- a/src/components/status/status.js
+++ b/src/components/status/status.js
@@ -83,7 +83,6 @@ const Status = {
return hits
},
muted () { return !this.unmuted && (this.status.user.muted || this.muteWordHits.length > 0) },
- isReply () { return !!this.status.in_reply_to_status_id },
isFocused () {
// retweet or root of an expanded conversation
if (this.focused) {
@@ -105,6 +104,48 @@ const Status = {
const lengthScore = this.status.statusnet_html.split(/<p|<br/).length + this.status.text.length / 80
return lengthScore > 20
},
+ isReply () {
+ if (this.status.in_reply_to_status_id) {
+ return true
+ }
+ // For private replies where we can't see the OP, in_reply_to_status_id will be null.
+ // So instead, check that the post starts with a @mention.
+ if (this.status.visibility === 'private') {
+ var textBody = this.status.text
+ if (this.status.summary !== null) {
+ textBody = textBody.substring(this.status.summary.length, textBody.length)
+ }
+ return textBody.startsWith('@')
+ }
+ return false
+ },
+ hideReply () {
+ if (this.$store.state.config.replyVisibility === 'all') {
+ return false
+ }
+ if (this.inlineExpanded || this.expanded || this.inConversation || !this.isReply) {
+ return false
+ }
+ if (this.status.user.id === this.$store.state.users.currentUser.id) {
+ return false
+ }
+ if (this.status.activity_type === 'repeat') {
+ return false
+ }
+ var checkFollowing = this.$store.state.config.replyVisibility === 'following'
+ for (var i = 0; i < this.status.attentions.length; ++i) {
+ if (this.status.user.id === this.status.attentions[i].id) {
+ continue
+ }
+ if (checkFollowing && this.status.attentions[i].following) {
+ return false
+ }
+ if (this.status.attentions[i].id === this.$store.state.users.currentUser.id) {
+ return false
+ }
+ }
+ return this.status.attentions.length > 0
+ },
hideSubjectStatus () {
if (this.tallStatus && !this.$store.state.config.collapseMessageWithSubject) {
return false
@@ -123,6 +164,21 @@ const Status = {
showingMore () {
return this.showingTall || (this.status.summary && this.expandingSubject)
},
+ nsfwClickthrough () {
+ if (!this.status.nsfw) {
+ return false
+ }
+ if (this.status.summary && this.$store.state.config.collapseMessageWithSubject) {
+ return false
+ }
+ return true
+ },
+ replySubject () {
+ if (this.status.summary && !this.status.summary.match(/^re[: ]/i)) {
+ return 're: '.concat(this.status.summary)
+ }
+ return this.status.summary
+ },
attachmentSize () {
if ((this.$store.state.config.hideAttachments && !this.inConversation) ||
(this.$store.state.config.hideAttachmentsInConv && this.inConversation)) {
diff --git a/src/components/status/status.vue b/src/components/status/status.vue
index e7d5ed7a..123b0cc2 100644
--- a/src/components/status/status.vue
+++ b/src/components/status/status.vue
@@ -1,5 +1,5 @@
<template>
- <div class="status-el" :class="[{ 'status-el_focused': isFocused }, { 'status-conversation': inlineExpanded }]">
+ <div class="status-el" v-if="!hideReply" :class="[{ 'status-el_focused': isFocused }, { 'status-conversation': inlineExpanded }]">
<template v-if="muted && !noReplyLinks">
<div class="media status container muted">
<small><router-link :to="{ name: 'user-profile', params: { id: status.user.id } }">{{status.user.screen_name}}</router-link></small>
@@ -83,8 +83,8 @@
<a v-if="showingMore" href="#" class="status-unhider" @click.prevent="toggleShowMore">Show less</a>
</div>
- <div v-if='status.attachments' class='attachments media-body'>
- <attachment :size="attachmentSize" :status-id="status.id" :nsfw="status.nsfw" :attachment="attachment" v-for="attachment in status.attachments" :key="attachment.id">
+ <div v-if='status.attachments && !hideSubjectStatus' class='attachments media-body'>
+ <attachment :size="attachmentSize" :status-id="status.id" :nsfw="nsfwClickthrough" :attachment="attachment" v-for="attachment in status.attachments" :key="attachment.id">
</attachment>
</div>
@@ -102,7 +102,7 @@
</div>
<div class="container" v-if="replying">
<div class="reply-left"/>
- <post-status-form class="reply-body" :reply-to="status.id" :attentions="status.attentions" :repliedUser="status.user" :message-scope="status.visibility" v-on:posted="toggleReplying"/>
+ <post-status-form class="reply-body" :reply-to="status.id" :attentions="status.attentions" :repliedUser="status.user" :message-scope="status.visibility" :subject="replySubject" v-on:posted="toggleReplying"/>
</div>
</template>
</div>
diff --git a/src/components/user_card_content/user_card_content.vue b/src/components/user_card_content/user_card_content.vue
index 71222d15..59358040 100644
--- a/src/components/user_card_content/user_card_content.vue
+++ b/src/components/user_card_content/user_card_content.vue
@@ -105,8 +105,8 @@
<span>{{user.followers_count}}</span>
</div>
</div>
- <p v-if="!hideBio && user.description_html" v-html="user.description_html"></p>
- <p v-else-if="!hideBio">{{ user.description }}</p>
+ <p v-if="!hideBio && user.description_html" class="profile-bio" v-html="user.description_html"></p>
+ <p v-else-if="!hideBio" class="profile-bio">{{ user.description }}</p>
</div>
</div>
</template>
@@ -130,7 +130,11 @@
.profile-panel-body {
word-wrap: break-word;
background: linear-gradient(to bottom, rgba(0, 0, 0, 0), $fallback--bg 80%);
- background: linear-gradient(to bottom, rgba(0, 0, 0, 0), var(--bg, $fallback--bg) 80%)
+ background: linear-gradient(to bottom, rgba(0, 0, 0, 0), var(--bg, $fallback--bg) 80%);
+
+ .profile-bio {
+ text-align: center;
+ }
}
.user-info {
diff --git a/src/components/who_to_follow_panel/who_to_follow_panel.js b/src/components/who_to_follow_panel/who_to_follow_panel.js
index 51b9f469..6766e561 100644
--- a/src/components/who_to_follow_panel/who_to_follow_panel.js
+++ b/src/components/who_to_follow_panel/who_to_follow_panel.js
@@ -1,5 +1,7 @@
-function showWhoToFollow (panel, reply, aHost, aUser) {
- var users = reply.ids
+import apiService from '../../services/api/api.service.js'
+
+function showWhoToFollow (panel, reply) {
+ var users = reply
var cn
var index = 0
var random = Math.floor(Math.random() * 10)
@@ -7,12 +9,12 @@ function showWhoToFollow (panel, reply, aHost, aUser) {
var user
user = users[cn]
var img
- if (user.icon) {
- img = user.icon
+ if (user.avatar) {
+ img = user.avatar
} else {
img = '/images/avi.png'
}
- var name = user.to_id
+ var name = user.acct
if (index === 0) {
panel.img1 = img
panel.name1 = name
@@ -52,27 +54,15 @@ function showWhoToFollow (panel, reply, aHost, aUser) {
}
function getWhoToFollow (panel) {
- var user = panel.$store.state.users.currentUser.screen_name
- if (user) {
+ var credentials = panel.$store.state.users.currentUser.credentials
+ if (credentials) {
panel.name1 = 'Loading...'
panel.name2 = 'Loading...'
panel.name3 = 'Loading...'
- var host = window.location.hostname
- var whoToFollowProvider = panel.$store.state.config.whoToFollowProvider
- var url
- url = whoToFollowProvider.replace(/{{host}}/g, encodeURIComponent(host))
- url = url.replace(/{{user}}/g, encodeURIComponent(user))
- window.fetch(url, {mode: 'cors'}).then(function (response) {
- if (response.ok) {
- return response.json()
- } else {
- panel.name1 = ''
- panel.name2 = ''
- panel.name3 = ''
- }
- }).then(function (reply) {
- showWhoToFollow(panel, reply, host, user)
- })
+ apiService.suggestions({credentials: credentials})
+ .then((reply) => {
+ showWhoToFollow(panel, reply)
+ })
}
}
@@ -95,26 +85,26 @@ const WhoToFollowPanel = {
moreUrl: function () {
var host = window.location.hostname
var user = this.user
- var whoToFollowLink = this.$store.state.config.whoToFollowLink
+ var suggestionsWeb = this.$store.state.config.suggestionsWeb
var url
- url = whoToFollowLink.replace(/{{host}}/g, encodeURIComponent(host))
+ url = suggestionsWeb.replace(/{{host}}/g, encodeURIComponent(host))
url = url.replace(/{{user}}/g, encodeURIComponent(user))
return url
},
- showWhoToFollowPanel () {
- return this.$store.state.config.showWhoToFollowPanel
+ suggestionsEnabled () {
+ return this.$store.state.config.suggestionsEnabled
}
},
watch: {
user: function (user, oldUser) {
- if (this.showWhoToFollowPanel) {
+ if (this.suggestionsEnabled) {
getWhoToFollow(this)
}
}
},
mounted:
function () {
- if (this.showWhoToFollowPanel) {
+ if (this.suggestionsEnabled) {
getWhoToFollow(this)
}
}
diff --git a/src/components/who_to_follow_panel/who_to_follow_panel.vue b/src/components/who_to_follow_panel/who_to_follow_panel.vue
index 5af6d0d5..8b3abe70 100644
--- a/src/components/who_to_follow_panel/who_to_follow_panel.vue
+++ b/src/components/who_to_follow_panel/who_to_follow_panel.vue
@@ -3,7 +3,7 @@
<div class="panel panel-default base01-background">
<div class="panel-heading timeline-heading base02-background base04">
<div class="title">
- Who to follow
+ {{$t('who_to_follow.who_to_follow')}}
</div>
</div>
<div class="panel-body who-to-follow">
@@ -11,7 +11,7 @@
<img v-bind:src="img1"/> <router-link :to="{ name: 'user-profile', params: { id: id1 } }">{{ name1 }}</router-link><br>
<img v-bind:src="img2"/> <router-link :to="{ name: 'user-profile', params: { id: id2 } }">{{ name2 }}</router-link><br>
<img v-bind:src="img3"/> <router-link :to="{ name: 'user-profile', params: { id: id3 } }">{{ name3 }}</router-link><br>
- <img v-bind:src="$store.state.config.logo"> <a v-bind:href="moreUrl" target="_blank">More</a>
+ <img v-bind:src="$store.state.config.logo"> <a v-bind:href="moreUrl" target="_blank">{{$t('who_to_follow.more')}}</a>
</p>
</div>
</div>