Merge pull request #1265 from ThibG/glitch-soc/merge-upstream

Merge upstream changes
remotes/1727458204337373841/tmp_refs/heads/signup-info-prompt
ThibG 2020-01-24 17:28:22 +01:00 committed by GitHub
commit 0be67df4f0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
272 changed files with 3839 additions and 797 deletions

View File

@ -275,3 +275,13 @@ STREAMING_CLUSTER_NUM=1
# http_proxy=http://gateway.local:8118 # http_proxy=http://gateway.local:8118
# Access control for hidden service. # Access control for hidden service.
# ALLOW_ACCESS_TO_HIDDEN_SERVICE=true # ALLOW_ACCESS_TO_HIDDEN_SERVICE=true
# Authorized fetch mode (optional)
# Require remote servers to authentify when fetching toots, see
# https://docs.joinmastodon.org/admin/config/#authorized_fetch
# AUTHORIZED_FETCH=true
# Whitelist mode (optional)
# Only allow federation with whitelisted domains, see
# https://docs.joinmastodon.org/admin/config/#whitelist_mode
# WHITELIST_MODE=true

2
.nvmrc
View File

@ -1 +1 @@
8 12

View File

@ -0,0 +1,69 @@
# frozen_string_literal: true
class Admin::AnnouncementsController < Admin::BaseController
before_action :set_announcements, only: :index
before_action :set_announcement, except: [:index, :new, :create]
def index
authorize :announcement, :index?
end
def new
authorize :announcement, :create?
@announcement = Announcement.new
end
def create
authorize :announcement, :create?
@announcement = Announcement.new(resource_params)
if @announcement.save
log_action :create, @announcement
redirect_to admin_announcements_path
else
render :new
end
end
def edit
authorize :announcement, :update?
end
def update
authorize :announcement, :update?
if @announcement.update(resource_params)
log_action :update, @announcement
redirect_to admin_announcements_path
else
render :edit
end
end
def destroy
authorize :announcement, :destroy?
@announcement.destroy!
log_action :destroy, @announcement
redirect_to admin_announcements_path
end
private
def set_announcements
@announcements = AnnouncementFilter.new(filter_params).results.page(params[:page])
end
def set_announcement
@announcement = Announcement.find(params[:id])
end
def filter_params
params.slice(*AnnouncementFilter::KEYS).permit(*AnnouncementFilter::KEYS)
end
def resource_params
params.require(:announcement).permit(:text, :scheduled_at, :starts_at, :ends_at, :all_day)
end
end

View File

@ -1,18 +0,0 @@
# frozen_string_literal: true
module Admin
class FollowersController < BaseController
before_action :set_account
PER_PAGE = 40
def index
authorize :account, :index?
@followers = @account.followers.local.recent.page(params[:page]).per(PER_PAGE)
end
def set_account
@account = Account.find(params[:account_id])
end
end
end

View File

@ -0,0 +1,25 @@
# frozen_string_literal: true
module Admin
class RelationshipsController < BaseController
before_action :set_account
PER_PAGE = 40
def index
authorize :account, :index?
@accounts = RelationshipFilter.new(@account, filter_params).results.page(params[:page]).per(PER_PAGE)
end
private
def set_account
@account = Account.find(params[:account_id])
end
def filter_params
params.slice(*RelationshipFilter::KEYS).permit(*RelationshipFilter::KEYS)
end
end
end

View File

@ -85,7 +85,7 @@ class Api::BaseController < ApplicationController
end end
def require_authenticated_user! def require_authenticated_user!
render json: { error: 'This API requires an authenticated user' }, status: 401 unless current_user render json: { error: 'This method requires an authenticated user' }, status: 401 unless current_user
end end
def require_user! def require_user!

View File

@ -1,17 +1,25 @@
# frozen_string_literal: true # frozen_string_literal: true
class Api::OEmbedController < Api::BaseController class Api::OEmbedController < Api::BaseController
respond_to :json
skip_before_action :require_authenticated_user! skip_before_action :require_authenticated_user!
before_action :set_status
before_action :require_public_status!
def show def show
@status = status_finder.status
render json: @status, serializer: OEmbedSerializer, width: maxwidth_or_default, height: maxheight_or_default render json: @status, serializer: OEmbedSerializer, width: maxwidth_or_default, height: maxheight_or_default
end end
private private
def set_status
@status = status_finder.status
end
def require_public_status!
not_found if @status.hidden?
end
def status_finder def status_finder
StatusFinder.new(params[:url]) StatusFinder.new(params[:url])
end end

View File

@ -0,0 +1,29 @@
# frozen_string_literal: true
class Api::V1::Announcements::ReactionsController < Api::BaseController
before_action -> { doorkeeper_authorize! :write, :'write:favourites' }
before_action :require_user!
before_action :set_announcement
before_action :set_reaction, except: :update
def update
@announcement.announcement_reactions.create!(account: current_account, name: params[:id])
render_empty
end
def destroy
@reaction.destroy!
render_empty
end
private
def set_reaction
@reaction = @announcement.announcement_reactions.where(account: current_account).find_by!(name: params[:id])
end
def set_announcement
@announcement = Announcement.published.find(params[:announcement_id])
end
end

View File

@ -0,0 +1,33 @@
# frozen_string_literal: true
class Api::V1::AnnouncementsController < Api::BaseController
before_action -> { doorkeeper_authorize! :write, :'write:accounts' }, only: :dismiss
before_action :require_user!
before_action :set_announcements, only: :index
before_action :set_announcement, except: :index
def index
render json: @announcements, each_serializer: REST::AnnouncementSerializer
end
def dismiss
AnnouncementMute.create!(account: current_account, announcement: @announcement)
render_empty
end
private
def set_announcements
@announcements = begin
scope = Announcement.published
scope.merge!(Announcement.without_muted(current_account)) unless truthy_param?(:with_dismissed)
scope.chronological
end
end
def set_announcement
@announcement = Announcement.published.find(params[:id])
end
end

View File

@ -7,6 +7,12 @@ class Auth::PasswordsController < Devise::PasswordsController
layout 'auth' layout 'auth'
def update
super do |resource|
resource.session_activations.destroy_all if resource.errors.empty?
end
end
private private
def check_validity_of_reset_password_token def check_validity_of_reset_password_token

View File

@ -23,10 +23,17 @@ class Auth::RegistrationsController < Devise::RegistrationsController
not_found not_found
end end
def update
super do |resource|
resource.clear_other_sessions(current_session.session_id) if resource.saved_change_to_encrypted_password?
end
end
protected protected
def update_resource(resource, params) def update_resource(resource, params)
params[:password] = nil if Devise.pam_authentication && resource.encrypted_password.blank? params[:password] = nil if Devise.pam_authentication && resource.encrypted_password.blank?
super super
end end

View File

@ -20,53 +20,13 @@ class RelationshipsController < ApplicationController
rescue ActionController::ParameterMissing rescue ActionController::ParameterMissing
# Do nothing # Do nothing
ensure ensure
redirect_to relationships_path(current_params) redirect_to relationships_path(filter_params)
end end
private private
def set_accounts def set_accounts
@accounts = relationships_scope.page(params[:page]).per(40) @accounts = RelationshipFilter.new(current_account, filter_params).results.page(params[:page]).per(40)
end
def relationships_scope
scope = begin
if following_relationship?
current_account.following.eager_load(:account_stat).reorder(nil)
else
current_account.followers.eager_load(:account_stat).reorder(nil)
end
end
scope.merge!(Follow.recent) if params[:order].blank? || params[:order] == 'recent'
scope.merge!(Account.by_recent_status) if params[:order] == 'active'
scope.merge!(mutual_relationship_scope) if mutual_relationship?
scope.merge!(moved_account_scope) if params[:status] == 'moved'
scope.merge!(primary_account_scope) if params[:status] == 'primary'
scope.merge!(by_domain_scope) if params[:by_domain].present?
scope.merge!(dormant_account_scope) if params[:activity] == 'dormant'
scope
end
def mutual_relationship_scope
Account.where(id: current_account.following)
end
def moved_account_scope
Account.where.not(moved_to_account_id: nil)
end
def primary_account_scope
Account.where(moved_to_account_id: nil)
end
def dormant_account_scope
AccountStat.where(last_status_at: nil).or(AccountStat.where(AccountStat.arel_table[:last_status_at].lt(1.month.ago)))
end
def by_domain_scope
Account.where(domain: params[:by_domain])
end end
def form_account_batch_params def form_account_batch_params
@ -85,7 +45,7 @@ class RelationshipsController < ApplicationController
params[:relationship] == 'followed_by' params[:relationship] == 'followed_by'
end end
def current_params def filter_params
params.slice(:page, *RelationshipFilter::KEYS).permit(:page, *RelationshipFilter::KEYS) params.slice(:page, *RelationshipFilter::KEYS).permit(:page, *RelationshipFilter::KEYS)
end end

View File

@ -49,7 +49,7 @@ class StatusesController < ApplicationController
def embed def embed
use_pack 'embed' use_pack 'embed'
raise ActiveRecord::RecordNotFound if @status.hidden? return not_found if @status.hidden?
expires_in 180, public: true expires_in 180, public: true
response.headers['X-Frame-Options'] = 'ALLOWALL' response.headers['X-Frame-Options'] = 'ALLOWALL'
@ -71,7 +71,7 @@ class StatusesController < ApplicationController
@status = @account.statuses.find(params[:id]) @status = @account.statuses.find(params[:id])
authorize @status, :show? authorize @status, :show?
rescue Mastodon::NotPermittedError rescue Mastodon::NotPermittedError
raise ActiveRecord::RecordNotFound not_found
end end
def set_instance_presenter def set_instance_presenter

View File

@ -22,6 +22,8 @@ module Admin::ActionLogsHelper
log.recorded_changes.slice('severity', 'reject_media') log.recorded_changes.slice('severity', 'reject_media')
elsif log.target_type == 'Status' && log.action == :update elsif log.target_type == 'Status' && log.action == :update
log.recorded_changes.slice('sensitive') log.recorded_changes.slice('sensitive')
elsif log.target_type == 'Announcement' && log.action == :update
log.recorded_changes.slice('text', 'starts_at', 'ends_at', 'all_day')
end end
end end
@ -52,6 +54,8 @@ module Admin::ActionLogsHelper
'pencil' 'pencil'
when 'AccountWarning' when 'AccountWarning'
'warning' 'warning'
when 'Announcement'
'bullhorn'
end end
end end
@ -94,6 +98,8 @@ module Admin::ActionLogsHelper
link_to record.account.acct, ActivityPub::TagManager.instance.url_for(record) link_to record.account.acct, ActivityPub::TagManager.instance.url_for(record)
when 'AccountWarning' when 'AccountWarning'
link_to record.target_account.acct, admin_account_path(record.target_account_id) link_to record.target_account.acct, admin_account_path(record.target_account_id)
when 'Announcement'
link_to "##{record.id}", edit_admin_announcement_path(record.id)
end end
end end
@ -111,6 +117,8 @@ module Admin::ActionLogsHelper
else else
I18n.t('admin.action_logs.deleted_status') I18n.t('admin.action_logs.deleted_status')
end end
when 'Announcement'
"##{attributes['id']}"
end end
end end
end end

View File

@ -0,0 +1,11 @@
# frozen_string_literal: true
module Admin::AnnouncementsHelper
def time_range(announcement)
if announcement.all_day?
safe_join([l(announcement.starts_at.to_date), ' - ', l(announcement.ends_at.to_date)])
else
safe_join([l(announcement.starts_at), ' - ', l(announcement.ends_at)])
end
end
end

View File

@ -9,6 +9,7 @@ module Admin::FilterHelper
InstanceFilter::KEYS, InstanceFilter::KEYS,
InviteFilter::KEYS, InviteFilter::KEYS,
RelationshipFilter::KEYS, RelationshipFilter::KEYS,
AnnouncementFilter::KEYS,
].flatten.freeze ].flatten.freeze
def filter_link_to(text, link_to_params, link_class_params = link_to_params) def filter_link_to(text, link_to_params, link_class_params = link_to_params)

View File

@ -0,0 +1,133 @@
import api from 'flavours/glitch/util/api';
import { normalizeAnnouncement } from './importer/normalizer';
export const ANNOUNCEMENTS_FETCH_REQUEST = 'ANNOUNCEMENTS_FETCH_REQUEST';
export const ANNOUNCEMENTS_FETCH_SUCCESS = 'ANNOUNCEMENTS_FETCH_SUCCESS';
export const ANNOUNCEMENTS_FETCH_FAIL = 'ANNOUNCEMENTS_FETCH_FAIL';
export const ANNOUNCEMENTS_UPDATE = 'ANNOUNCEMENTS_UPDATE';
export const ANNOUNCEMENTS_DISMISS = 'ANNOUNCEMENTS_DISMISS';
export const ANNOUNCEMENTS_REACTION_ADD_REQUEST = 'ANNOUNCEMENTS_REACTION_ADD_REQUEST';
export const ANNOUNCEMENTS_REACTION_ADD_SUCCESS = 'ANNOUNCEMENTS_REACTION_ADD_SUCCESS';
export const ANNOUNCEMENTS_REACTION_ADD_FAIL = 'ANNOUNCEMENTS_REACTION_ADD_FAIL';
export const ANNOUNCEMENTS_REACTION_REMOVE_REQUEST = 'ANNOUNCEMENTS_REACTION_REMOVE_REQUEST';
export const ANNOUNCEMENTS_REACTION_REMOVE_SUCCESS = 'ANNOUNCEMENTS_REACTION_REMOVE_SUCCESS';
export const ANNOUNCEMENTS_REACTION_REMOVE_FAIL = 'ANNOUNCEMENTS_REACTION_REMOVE_FAIL';
export const ANNOUNCEMENTS_REACTION_UPDATE = 'ANNOUNCEMENTS_REACTION_UPDATE';
const noOp = () => {};
export const fetchAnnouncements = (done = noOp) => (dispatch, getState) => {
dispatch(fetchAnnouncementsRequest());
api(getState).get('/api/v1/announcements').then(response => {
dispatch(fetchAnnouncementsSuccess(response.data.map(x => normalizeAnnouncement(x))));
}).catch(error => {
dispatch(fetchAnnouncementsFail(error));
}).finally(() => {
done();
});
};
export const fetchAnnouncementsRequest = () => ({
type: ANNOUNCEMENTS_FETCH_REQUEST,
skipLoading: true,
});
export const fetchAnnouncementsSuccess = announcements => ({
type: ANNOUNCEMENTS_FETCH_SUCCESS,
announcements,
skipLoading: true,
});
export const fetchAnnouncementsFail= error => ({
type: ANNOUNCEMENTS_FETCH_FAIL,
error,
skipLoading: true,
skipAlert: true,
});
export const updateAnnouncements = announcement => ({
type: ANNOUNCEMENTS_UPDATE,
announcement: normalizeAnnouncement(announcement),
});
export const dismissAnnouncement = announcementId => (dispatch, getState) => {
dispatch({
type: ANNOUNCEMENTS_DISMISS,
id: announcementId,
});
api(getState).post(`/api/v1/announcements/${announcementId}/dismiss`);
};
export const addReaction = (announcementId, name) => (dispatch, getState) => {
dispatch(addReactionRequest(announcementId, name));
api(getState).put(`/api/v1/announcements/${announcementId}/reactions/${name}`).then(() => {
dispatch(addReactionSuccess(announcementId, name));
}).catch(err => {
dispatch(addReactionFail(announcementId, name, err));
});
};
export const addReactionRequest = (announcementId, name) => ({
type: ANNOUNCEMENTS_REACTION_ADD_REQUEST,
id: announcementId,
name,
skipLoading: true,
});
export const addReactionSuccess = (announcementId, name) => ({
type: ANNOUNCEMENTS_REACTION_ADD_SUCCESS,
id: announcementId,
name,
skipLoading: true,
});
export const addReactionFail = (announcementId, name, error) => ({
type: ANNOUNCEMENTS_REACTION_ADD_FAIL,
id: announcementId,
name,
error,
skipLoading: true,
});
export const removeReaction = (announcementId, name) => (dispatch, getState) => {
dispatch(removeReactionRequest(announcementId, name));
api(getState).delete(`/api/v1/announcements/${announcementId}/reactions/${name}`).then(() => {
dispatch(removeReactionSuccess(announcementId, name));
}).catch(err => {
dispatch(removeReactionFail(announcementId, name, err));
});
};
export const removeReactionRequest = (announcementId, name) => ({
type: ANNOUNCEMENTS_REACTION_REMOVE_REQUEST,
id: announcementId,
name,
skipLoading: true,
});
export const removeReactionSuccess = (announcementId, name) => ({
type: ANNOUNCEMENTS_REACTION_REMOVE_SUCCESS,
id: announcementId,
name,
skipLoading: true,
});
export const removeReactionFail = (announcementId, name, error) => ({
type: ANNOUNCEMENTS_REACTION_REMOVE_FAIL,
id: announcementId,
name,
error,
skipLoading: true,
});
export const updateReaction = reaction => ({
type: ANNOUNCEMENTS_REACTION_UPDATE,
reaction,
});

View File

@ -74,7 +74,6 @@ export function normalizeStatus(status, normalOldStatus) {
export function normalizePoll(poll) { export function normalizePoll(poll) {
const normalPoll = { ...poll }; const normalPoll = { ...poll };
const emojiMap = makeEmojiMap(normalPoll); const emojiMap = makeEmojiMap(normalPoll);
normalPoll.options = poll.options.map((option, index) => ({ normalPoll.options = poll.options.map((option, index) => ({
@ -85,3 +84,12 @@ export function normalizePoll(poll) {
return normalPoll; return normalPoll;
} }
export function normalizeAnnouncement(announcement) {
const normalAnnouncement = { ...announcement };
const emojiMap = makeEmojiMap(normalAnnouncement);
normalAnnouncement.contentHtml = emojify(normalAnnouncement.content, emojiMap);
return normalAnnouncement;
}

View File

@ -168,9 +168,9 @@ export function expandNotifications({ maxId } = {}, done = noOp) {
dispatch(expandNotificationsSuccess(response.data, next ? next.uri : null, isLoadingMore, isLoadingRecent, isLoadingRecent && preferPendingItems)); dispatch(expandNotificationsSuccess(response.data, next ? next.uri : null, isLoadingMore, isLoadingRecent, isLoadingRecent && preferPendingItems));
fetchRelatedRelationships(dispatch, response.data); fetchRelatedRelationships(dispatch, response.data);
done();
}).catch(error => { }).catch(error => {
dispatch(expandNotificationsFail(error, isLoadingMore)); dispatch(expandNotificationsFail(error, isLoadingMore));
}).finally(() => {
done(); done();
}); });
}; };
@ -199,6 +199,7 @@ export function expandNotificationsFail(error, isLoadingMore) {
type: NOTIFICATIONS_EXPAND_FAIL, type: NOTIFICATIONS_EXPAND_FAIL,
error, error,
skipLoading: !isLoadingMore, skipLoading: !isLoadingMore,
skipAlert: !isLoadingMore,
}; };
}; };

View File

@ -8,6 +8,7 @@ import {
} from './timelines'; } from './timelines';
import { updateNotifications, expandNotifications } from './notifications'; import { updateNotifications, expandNotifications } from './notifications';
import { updateConversations } from './conversations'; import { updateConversations } from './conversations';
import { fetchAnnouncements, updateAnnouncements, updateReaction as updateAnnouncementsReaction } from './announcements';
import { fetchFilters } from './filters'; import { fetchFilters } from './filters';
import { getLocale } from 'mastodon/locales'; import { getLocale } from 'mastodon/locales';
@ -44,6 +45,12 @@ export function connectTimelineStream (timelineId, path, pollingRefresh = null,
case 'filters_changed': case 'filters_changed':
dispatch(fetchFilters()); dispatch(fetchFilters());
break; break;
case 'announcement':
dispatch(updateAnnouncements(JSON.parse(data.payload)));
break;
case 'announcement.reaction':
dispatch(updateAnnouncementsReaction(JSON.parse(data.payload)));
break;
} }
}, },
}; };
@ -51,7 +58,9 @@ export function connectTimelineStream (timelineId, path, pollingRefresh = null,
} }
const refreshHomeTimelineAndNotification = (dispatch, done) => { const refreshHomeTimelineAndNotification = (dispatch, done) => {
dispatch(expandHomeTimeline({}, () => dispatch(expandNotifications({}, done)))); dispatch(expandHomeTimeline({}, () =>
dispatch(expandNotifications({}, () =>
dispatch(fetchAnnouncements(done))))));
}; };
export const connectUserStream = () => connectTimelineStream('home', 'user', refreshHomeTimelineAndNotification); export const connectUserStream = () => connectTimelineStream('home', 'user', refreshHomeTimelineAndNotification);

View File

@ -112,9 +112,9 @@ export function expandTimeline(timelineId, path, params = {}, done = noOp) {
dispatch(importFetchedStatuses(response.data)); dispatch(importFetchedStatuses(response.data));
dispatch(expandTimelineSuccess(timelineId, response.data, next ? next.uri : null, response.status === 206, isLoadingRecent, isLoadingMore, isLoadingRecent && preferPendingItems)); dispatch(expandTimelineSuccess(timelineId, response.data, next ? next.uri : null, response.status === 206, isLoadingRecent, isLoadingMore, isLoadingRecent && preferPendingItems));
done();
}).catch(error => { }).catch(error => {
dispatch(expandTimelineFail(timelineId, error, isLoadingMore)); dispatch(expandTimelineFail(timelineId, error, isLoadingMore));
}).finally(() => {
done(); done();
}); });
}; };

View File

@ -112,6 +112,7 @@ class AccountTimeline extends ImmutablePureComponent {
onLoadMore={this.handleLoadMore} onLoadMore={this.handleLoadMore}
emptyMessage={<FormattedMessage id='empty_column.account_timeline' defaultMessage='No toots here!' />} emptyMessage={<FormattedMessage id='empty_column.account_timeline' defaultMessage='No toots here!' />}
bindToDocument={!multiColumn} bindToDocument={!multiColumn}
timelineId='account'
/> />
</Column> </Column>
); );

View File

@ -22,6 +22,7 @@ const messages = defineMessages({
requested: { id: 'account.requested', defaultMessage: 'Awaiting approval' }, requested: { id: 'account.requested', defaultMessage: 'Awaiting approval' },
unblock: { id: 'account.unblock', defaultMessage: 'Unblock @{name}' }, unblock: { id: 'account.unblock', defaultMessage: 'Unblock @{name}' },
unmute: { id: 'account.unmute', defaultMessage: 'Unmute @{name}' }, unmute: { id: 'account.unmute', defaultMessage: 'Unmute @{name}' },
unfollowConfirm: { id: 'confirmations.unfollow.confirm', defaultMessage: 'Unfollow' },
}); });
const makeMapStateToProps = () => { const makeMapStateToProps = () => {

View File

@ -372,6 +372,7 @@ class EmojiPickerDropdown extends React.PureComponent {
onPickEmoji: PropTypes.func.isRequired, onPickEmoji: PropTypes.func.isRequired,
onSkinTone: PropTypes.func.isRequired, onSkinTone: PropTypes.func.isRequired,
skinTone: PropTypes.number.isRequired, skinTone: PropTypes.number.isRequired,
button: PropTypes.node,
}; };
state = { state = {
@ -432,18 +433,18 @@ class EmojiPickerDropdown extends React.PureComponent {
} }
render () { render () {
const { intl, onPickEmoji, onSkinTone, skinTone, frequentlyUsedEmojis } = this.props; const { intl, onPickEmoji, onSkinTone, skinTone, frequentlyUsedEmojis, button } = this.props;
const title = intl.formatMessage(messages.emoji); const title = intl.formatMessage(messages.emoji);
const { active, loading, placement } = this.state; const { active, loading, placement } = this.state;
return ( return (
<div className='emoji-picker-dropdown' onKeyDown={this.handleKeyDown}> <div className='emoji-picker-dropdown' onKeyDown={this.handleKeyDown}>
<div ref={this.setTargetRef} className='emoji-button' title={title} aria-label={title} aria-expanded={active} role='button' onClick={this.onToggle} onKeyDown={this.onToggle} tabIndex={0}> <div ref={this.setTargetRef} className='emoji-button' title={title} aria-label={title} aria-expanded={active} role='button' onClick={this.onToggle} onKeyDown={this.onToggle} tabIndex={0}>
<img {button || <img
className={classNames('emojione', { 'pulse-loading': active && loading })} className={classNames('emojione', { 'pulse-loading': active && loading })}
alt='🙂' alt='🙂'
src={`${assetHost}/emoji/1f602.svg`} src={`${assetHost}/emoji/1f602.svg`}
/> />}
</div> </div>
<Overlay show={active} placement={placement} target={this.findTarget}> <Overlay show={active} placement={placement} target={this.findTarget}>

View File

@ -0,0 +1,395 @@
import React from 'react';
import ImmutablePureComponent from 'react-immutable-pure-component';
import ReactSwipeableViews from 'react-swipeable-views';
import ImmutablePropTypes from 'react-immutable-proptypes';
import PropTypes from 'prop-types';
import IconButton from 'flavours/glitch/components/icon_button';
import Icon from 'flavours/glitch/components/icon';
import { defineMessages, injectIntl, FormattedMessage, FormattedDate, FormattedNumber } from 'react-intl';
import { autoPlayGif } from 'flavours/glitch/util/initial_state';
import elephantUIPlane from 'mastodon/../images/elephant_ui_plane.svg';
import { mascot } from 'flavours/glitch/util/initial_state';
import unicodeMapping from 'flavours/glitch/util/emoji/emoji_unicode_mapping_light';
import classNames from 'classnames';
import EmojiPickerDropdown from 'flavours/glitch/features/emoji_picker';
const messages = defineMessages({
close: { id: 'lightbox.close', defaultMessage: 'Close' },
previous: { id: 'lightbox.previous', defaultMessage: 'Previous' },
next: { id: 'lightbox.next', defaultMessage: 'Next' },
});
class Content extends ImmutablePureComponent {
static contextTypes = {
router: PropTypes.object,
};
static propTypes = {
announcement: ImmutablePropTypes.map.isRequired,
};
setRef = c => {
this.node = c;
}
componentDidMount () {
this._updateLinks();
this._updateEmojis();
}
componentDidUpdate () {
this._updateLinks();
this._updateEmojis();
}
_updateEmojis () {
const node = this.node;
if (!node || autoPlayGif) {
return;
}
const emojis = node.querySelectorAll('.custom-emoji');
for (var i = 0; i < emojis.length; i++) {
let emoji = emojis[i];
if (emoji.classList.contains('status-emoji')) {
continue;
}
emoji.classList.add('status-emoji');
emoji.addEventListener('mouseenter', this.handleEmojiMouseEnter, false);
emoji.addEventListener('mouseleave', this.handleEmojiMouseLeave, false);
}
}
_updateLinks () {
const node = this.node;
if (!node) {
return;
}
const links = node.querySelectorAll('a');
for (var i = 0; i < links.length; ++i) {
let link = links[i];
if (link.classList.contains('status-link')) {
continue;
}
link.classList.add('status-link');
let mention = this.props.announcement.get('mentions').find(item => link.href === item.get('url'));
if (mention) {
link.addEventListener('click', this.onMentionClick.bind(this, mention), false);
link.setAttribute('title', mention.get('acct'));
} else if (link.textContent[0] === '#' || (link.previousSibling && link.previousSibling.textContent && link.previousSibling.textContent[link.previousSibling.textContent.length - 1] === '#')) {
link.addEventListener('click', this.onHashtagClick.bind(this, link.text), false);
} else {
link.setAttribute('title', link.href);
link.classList.add('unhandled-link');
}
link.setAttribute('target', '_blank');
link.setAttribute('rel', 'noopener noreferrer');
}
}
onMentionClick = (mention, e) => {
if (this.context.router && e.button === 0 && !(e.ctrlKey || e.metaKey)) {
e.preventDefault();
this.context.router.history.push(`/accounts/${mention.get('id')}`);
}
}
onHashtagClick = (hashtag, e) => {
hashtag = hashtag.replace(/^#/, '');
if (this.context.router && e.button === 0 && !(e.ctrlKey || e.metaKey)) {
e.preventDefault();
this.context.router.history.push(`/timelines/tag/${hashtag}`);
}
}
handleEmojiMouseEnter = ({ target }) => {
target.src = target.getAttribute('data-original');
}
handleEmojiMouseLeave = ({ target }) => {
target.src = target.getAttribute('data-static');
}
render () {
const { announcement } = this.props;
return (
<div
className='announcements__item__content'
ref={this.setRef}
dangerouslySetInnerHTML={{ __html: announcement.get('contentHtml') }}
/>
);
}
}
const assetHost = process.env.CDN_HOST || '';
class Emoji extends React.PureComponent {
static propTypes = {
emoji: PropTypes.string.isRequired,
emojiMap: ImmutablePropTypes.map.isRequired,
hovered: PropTypes.bool.isRequired,
};
render () {
const { emoji, emojiMap, hovered } = this.props;
if (unicodeMapping[emoji]) {
const { filename, shortCode } = unicodeMapping[this.props.emoji];
const title = shortCode ? `:${shortCode}:` : '';
return (
<img
draggable='false'
className='emojione'
alt={emoji}
title={title}
src={`${assetHost}/emoji/${filename}.svg`}
/>
);
} else if (emojiMap.get(emoji)) {
const filename = (autoPlayGif || hovered) ? emojiMap.getIn([emoji, 'url']) : emojiMap.getIn([emoji, 'static_url']);
const shortCode = `:${emoji}:`;
return (
<img
draggable='false'
className='emojione custom-emoji'
alt={shortCode}
title={shortCode}
src={filename}
/>
);
} else {
return null;
}
}
}
class Reaction extends ImmutablePureComponent {
static propTypes = {
announcementId: PropTypes.string.isRequired,
reaction: ImmutablePropTypes.map.isRequired,
addReaction: PropTypes.func.isRequired,
removeReaction: PropTypes.func.isRequired,
emojiMap: ImmutablePropTypes.map.isRequired,
};
state = {
hovered: false,
};
handleClick = () => {
const { reaction, announcementId, addReaction, removeReaction } = this.props;
if (reaction.get('me')) {
removeReaction(announcementId, reaction.get('name'));
} else {
addReaction(announcementId, reaction.get('name'));
}
}
handleMouseEnter = () => this.setState({ hovered: true })
handleMouseLeave = () => this.setState({ hovered: false })
render () {
const { reaction } = this.props;
let shortCode = reaction.get('name');
if (unicodeMapping[shortCode]) {
shortCode = unicodeMapping[shortCode].shortCode;
}
return (
<button className={classNames('reactions-bar__item', { active: reaction.get('me') })} onClick={this.handleClick} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave} title={`:${shortCode}:`}>
<span className='reactions-bar__item__emoji'><Emoji hovered={this.state.hovered} emoji={reaction.get('name')} emojiMap={this.props.emojiMap} /></span>
<span className='reactions-bar__item__count'><FormattedNumber value={reaction.get('count')} /></span>
</button>
);
}
}
class ReactionsBar extends ImmutablePureComponent {
static propTypes = {
announcementId: PropTypes.string.isRequired,
reactions: ImmutablePropTypes.list.isRequired,
addReaction: PropTypes.func.isRequired,
removeReaction: PropTypes.func.isRequired,
emojiMap: ImmutablePropTypes.map.isRequired,
};
handleEmojiPick = data => {
const { addReaction, announcementId } = this.props;
addReaction(announcementId, data.native.replace(/:/g, ''));
}
render () {
const { reactions } = this.props;
const visibleReactions = reactions.filter(x => x.get('count') > 0);
return (
<div className={classNames('reactions-bar', { 'reactions-bar--empty': visibleReactions.isEmpty() })}>
{visibleReactions.map(reaction => (
<Reaction
key={reaction.get('name')}
reaction={reaction}
announcementId={this.props.announcementId}
addReaction={this.props.addReaction}
removeReaction={this.props.removeReaction}
emojiMap={this.props.emojiMap}
/>
))}
<EmojiPickerDropdown onPickEmoji={this.handleEmojiPick} button={<Icon id='plus' />} />
</div>
);
}
}
class Announcement extends ImmutablePureComponent {
static propTypes = {
announcement: ImmutablePropTypes.map.isRequired,
emojiMap: ImmutablePropTypes.map.isRequired,
dismissAnnouncement: PropTypes.func.isRequired,
addReaction: PropTypes.func.isRequired,
removeReaction: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired,
};
handleDismissClick = () => {
const { dismissAnnouncement, announcement } = this.props;
dismissAnnouncement(announcement.get('id'));
}
render () {
const { announcement, intl } = this.props;
const startsAt = announcement.get('starts_at') && new Date(announcement.get('starts_at'));
const endsAt = announcement.get('ends_at') && new Date(announcement.get('ends_at'));
const now = new Date();
const hasTimeRange = startsAt && endsAt;
const skipYear = hasTimeRange && startsAt.getFullYear() === endsAt.getFullYear() && endsAt.getFullYear() === now.getFullYear();
const skipEndDate = hasTimeRange && startsAt.getDate() === endsAt.getDate() && startsAt.getMonth() === endsAt.getMonth() && startsAt.getFullYear() === endsAt.getFullYear();
const skipTime = announcement.get('all_day');
return (
<div className='announcements__item'>
<strong className='announcements__item__range'>
<FormattedMessage id='announcement.announcement' defaultMessage='Announcement' />
{hasTimeRange && <span> · <FormattedDate value={startsAt} hour12={false} year={(skipYear || startsAt.getFullYear() === now.getFullYear()) ? undefined : 'numeric'} month='short' day='2-digit' hour={skipTime ? undefined : '2-digit'} minute={skipTime ? undefined : '2-digit'} /> - <FormattedDate value={endsAt} hour12={false} year={(skipYear || endsAt.getFullYear() === now.getFullYear()) ? undefined : 'numeric'} month={skipEndDate ? undefined : 'short'} day={skipEndDate ? undefined : '2-digit'} hour={skipTime ? undefined : '2-digit'} minute={skipTime ? undefined : '2-digit'} /></span>}
</strong>
<Content announcement={announcement} />
<ReactionsBar
reactions={announcement.get('reactions')}
announcementId={announcement.get('id')}
addReaction={this.props.addReaction}
removeReaction={this.props.removeReaction}
emojiMap={this.props.emojiMap}
/>
<IconButton title={intl.formatMessage(messages.close)} icon='times' className='announcements__item__dismiss-icon' onClick={this.handleDismissClick} />
</div>
);
}
}
export default @injectIntl
class Announcements extends ImmutablePureComponent {
static propTypes = {
announcements: ImmutablePropTypes.list,
emojiMap: ImmutablePropTypes.map.isRequired,
fetchAnnouncements: PropTypes.func.isRequired,
dismissAnnouncement: PropTypes.func.isRequired,
addReaction: PropTypes.func.isRequired,
removeReaction: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired,
};
state = {
index: 0,
};
componentDidMount () {
const { fetchAnnouncements } = this.props;
fetchAnnouncements();
}
handleChangeIndex = index => {
this.setState({ index: index % this.props.announcements.size });
}
handleNextClick = () => {
this.setState({ index: (this.state.index + 1) % this.props.announcements.size });
}
handlePrevClick = () => {
this.setState({ index: (this.props.announcements.size + this.state.index - 1) % this.props.announcements.size });
}
render () {
const { announcements, intl } = this.props;
const { index } = this.state;
if (announcements.isEmpty()) {
return null;
}
return (
<div className='announcements'>
<img className='announcements__mastodon' alt='' draggable='false' src={mascot || elephantUIPlane} />
<div className='announcements__container'>
<ReactSwipeableViews index={index} onChangeIndex={this.handleChangeIndex}>
{announcements.map(announcement => (
<Announcement
key={announcement.get('id')}
announcement={announcement}
emojiMap={this.props.emojiMap}
dismissAnnouncement={this.props.dismissAnnouncement}
addReaction={this.props.addReaction}
removeReaction={this.props.removeReaction}
intl={intl}
/>
))}
</ReactSwipeableViews>
<div className='announcements__pagination'>
<IconButton disabled={announcements.size === 1} title={intl.formatMessage(messages.previous)} icon='chevron-left' onClick={this.handlePrevClick} size={13} />
<span>{index + 1} / {announcements.size}</span>
<IconButton disabled={announcements.size === 1} title={intl.formatMessage(messages.next)} icon='chevron-right' onClick={this.handleNextClick} size={13} />
</div>
</div>
</div>
);
}
}

View File

@ -0,0 +1,21 @@
import { connect } from 'react-redux';
import { fetchAnnouncements, dismissAnnouncement, addReaction, removeReaction } from 'mastodon/actions/announcements';
import Announcements from '../components/announcements';
import { createSelector } from 'reselect';
import { Map as ImmutableMap } from 'immutable';
const customEmojiMap = createSelector([state => state.get('custom_emojis')], items => items.reduce((map, emoji) => map.set(emoji.get('shortcode'), emoji), ImmutableMap()));
const mapStateToProps = state => ({
announcements: state.getIn(['announcements', 'items']),
emojiMap: customEmojiMap(state),
});
const mapDispatchToProps = dispatch => ({
fetchAnnouncements: () => dispatch(fetchAnnouncements()),
dismissAnnouncement: id => dispatch(dismissAnnouncement(id)),
addReaction: (id, name) => dispatch(addReaction(id, name)),
removeReaction: (id, name) => dispatch(removeReaction(id, name)),
});
export default connect(mapStateToProps, mapDispatchToProps)(Announcements);

View File

@ -1,5 +1,5 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { fetchTrends } from '../../../actions/trends'; import { fetchTrends } from 'mastodon/actions/trends';
import Trends from '../components/trends'; import Trends from '../components/trends';
const mapStateToProps = state => ({ const mapStateToProps = state => ({

View File

@ -9,6 +9,7 @@ import { addColumn, removeColumn, moveColumn } from 'flavours/glitch/actions/col
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import ColumnSettingsContainer from './containers/column_settings_container'; import ColumnSettingsContainer from './containers/column_settings_container';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import AnnouncementsContainer from 'flavours/glitch/features/getting_started/containers/announcements_container';
const messages = defineMessages({ const messages = defineMessages({
title: { id: 'column.home', defaultMessage: 'Home' }, title: { id: 'column.home', defaultMessage: 'Home' },
@ -112,6 +113,8 @@ class HomeTimeline extends React.PureComponent {
</ColumnHeader> </ColumnHeader>
<StatusListContainer <StatusListContainer
prepend={<AnnouncementsContainer />}
alwaysPrepend
trackScroll={!pinned} trackScroll={!pinned}
scrollKey={`home_timeline-${columnId}`} scrollKey={`home_timeline-${columnId}`}
onLoadMore={this.handleLoadMore} onLoadMore={this.handleLoadMore}

View File

@ -191,7 +191,6 @@ class MediaModal extends ImmutablePureComponent {
style={swipeableViewsStyle} style={swipeableViewsStyle}
containerStyle={containerStyle} containerStyle={containerStyle}
onChangeIndex={this.handleSwipe} onChangeIndex={this.handleSwipe}
onSwitching={this.handleSwitching}
index={index} index={index}
> >
{content} {content}

View File

@ -0,0 +1,72 @@
import {
ANNOUNCEMENTS_FETCH_REQUEST,
ANNOUNCEMENTS_FETCH_SUCCESS,
ANNOUNCEMENTS_FETCH_FAIL,
ANNOUNCEMENTS_UPDATE,
ANNOUNCEMENTS_DISMISS,
ANNOUNCEMENTS_REACTION_UPDATE,
ANNOUNCEMENTS_REACTION_ADD_REQUEST,
ANNOUNCEMENTS_REACTION_ADD_FAIL,
ANNOUNCEMENTS_REACTION_REMOVE_REQUEST,
ANNOUNCEMENTS_REACTION_REMOVE_FAIL,
} from '../actions/announcements';
import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable';
const initialState = ImmutableMap({
items: ImmutableList(),
isLoading: false,
});
const updateReaction = (state, id, name, updater) => state.update('items', list => list.map(announcement => {
if (announcement.get('id') === id) {
return announcement.update('reactions', reactions => {
if (reactions.find(reaction => reaction.get('name') === name)) {
return reactions.map(reaction => {
if (reaction.get('name') === name) {
return updater(reaction);
}
return reaction;
});
}
return reactions.push(updater(fromJS({ name, count: 0 })));
});
}
return announcement;
}));
const updateReactionCount = (state, reaction) => updateReaction(state, reaction.announcement_id, reaction.name, x => x.set('count', reaction.count));
const addReaction = (state, id, name) => updateReaction(state, id, name, x => x.set('me', true).update('count', y => y + 1));
const removeReaction = (state, id, name) => updateReaction(state, id, name, x => x.set('me', false).update('count', y => y - 1));
export default function announcementsReducer(state = initialState, action) {
switch(action.type) {
case ANNOUNCEMENTS_FETCH_REQUEST:
return state.set('isLoading', true);
case ANNOUNCEMENTS_FETCH_SUCCESS:
return state.withMutations(map => {
map.set('items', fromJS(action.announcements));
map.set('isLoading', false);
});
case ANNOUNCEMENTS_FETCH_FAIL:
return state.set('isLoading', false);
case ANNOUNCEMENTS_UPDATE:
return state.update('items', list => list.unshift(fromJS(action.announcement)).sortBy(announcement => announcement.get('starts_at')));
case ANNOUNCEMENTS_DISMISS:
return state.update('items', list => list.filterNot(announcement => announcement.get('id') === action.id));
case ANNOUNCEMENTS_REACTION_UPDATE:
return updateReactionCount(state, action.reaction);
case ANNOUNCEMENTS_REACTION_ADD_REQUEST:
case ANNOUNCEMENTS_REACTION_REMOVE_FAIL:
return addReaction(state, action.id, action.name);
case ANNOUNCEMENTS_REACTION_REMOVE_REQUEST:
case ANNOUNCEMENTS_REACTION_ADD_FAIL:
return removeReaction(state, action.id, action.name);
default:
return state;
}
};

View File

@ -35,8 +35,10 @@ import pinnedAccountsEditor from './pinned_accounts_editor';
import polls from './polls'; import polls from './polls';
import identity_proofs from './identity_proofs'; import identity_proofs from './identity_proofs';
import trends from './trends'; import trends from './trends';
import announcements from './announcements';
const reducers = { const reducers = {
announcements,
dropdown_menu, dropdown_menu,
timelines, timelines,
meta, meta,

View File

@ -27,6 +27,7 @@ export const toServerSideType = columnType => {
case 'notifications': case 'notifications':
case 'public': case 'public':
case 'thread': case 'thread':
case 'account':
return columnType; return columnType;
default: default:
if (columnType.indexOf('list:') > -1) { if (columnType.indexOf('list:') > -1) {

View File

@ -0,0 +1,212 @@
.announcements__item__content {
word-wrap: break-word;
.emojione {
width: 20px;
height: 20px;
margin: -3px 0 0;
}
p {
margin-bottom: 10px;
white-space: pre-wrap;
&:last-child {
margin-bottom: 0;
}
}
a {
color: $highlight-text-color;
text-decoration: none;
&:hover {
text-decoration: underline;
}
&.mention {
&:hover {
text-decoration: none;
span {
text-decoration: underline;
}
}
}
}
}
.announcements {
background: lighten($ui-base-color, 4%);
border-top: 1px solid $ui-base-color;
font-size: 13px;
display: flex;
align-items: flex-end;
&__mastodon {
width: 124px;
flex: 0 0 auto;
@media screen and (max-width: 124px + 300px) {
display: none;
}
}
&__container {
width: calc(100% - 124px);
flex: 0 0 auto;
position: relative;
@media screen and (max-width: 124px + 300px) {
width: 100%;
}
}
&__item {
box-sizing: border-box;
width: 100%;
padding: 15px;
padding-right: 15px + 18px;
position: relative;
&__range {
display: block;
font-weight: 500;
margin-bottom: 10px;
}
&__dismiss-icon {
position: absolute;
top: 12px;
right: 12px;
}
}
&__pagination {
padding: 15px;
color: $darker-text-color;
position: absolute;
bottom: 3px;
right: 0;
}
}
.layout-multiple-columns .announcements__mastodon {
display: none;
}
.layout-multiple-columns .announcements__container {
width: 100%;
}
.reactions-bar {
display: flex;
flex-wrap: wrap;
align-items: center;
margin-top: 15px;
margin-left: -2px;
width: calc(100% - (90px - 33px));
&__item {
flex-shrink: 0;
background: lighten($ui-base-color, 12%);
border: 0;
border-radius: 3px;
margin: 2px;
cursor: pointer;
user-select: none;
padding: 0 6px;
display: flex;
align-items: center;
transition: all 100ms ease-in;
transition-property: background-color, color;
&__emoji {
display: block;
margin: 3px 0;
width: 16px;
height: 16px;
img {
display: block;
margin: 0;
width: 100%;
height: 100%;
min-width: auto;
min-height: auto;
vertical-align: bottom;
object-fit: contain;
}
}
&__count {
display: block;
min-width: 9px;
font-size: 13px;
font-weight: 500;
text-align: center;
margin-left: 6px;
color: $darker-text-color;
}
&:hover,
&:focus,
&:active {
background: lighten($ui-base-color, 16%);
transition: all 200ms ease-out;
transition-property: background-color, color;
&__count {
color: lighten($darker-text-color, 4%);
}
}
&.active {
transition: all 100ms ease-in;
transition-property: background-color, color;
background-color: mix(lighten($ui-base-color, 12%), $ui-highlight-color, 90%);
.reactions-bar__item__count {
color: $highlight-text-color;
}
}
}
.emoji-picker-dropdown {
margin: 2px;
}
&:hover .emoji-button {
opacity: 0.85;
}
.emoji-button {
color: $darker-text-color;
margin: 0;
font-size: 16px;
width: auto;
flex-shrink: 0;
padding: 0 6px;
height: 22px;
display: flex;
align-items: center;
opacity: 0.5;
transition: all 100ms ease-in;
transition-property: background-color, color;
&:hover,
&:active,
&:focus {
opacity: 1;
color: lighten($darker-text-color, 4%);
transition: all 200ms ease-out;
transition-property: background-color, color;
}
}
&--empty {
.emoji-button {
padding: 0;
}
}
}

View File

@ -1,5 +1,16 @@
.composer { .composer {
padding: 10px; padding: 10px;
.emoji-picker-dropdown {
position: absolute;
right: 5px;
top: 5px;
::-webkit-scrollbar-track:hover,
::-webkit-scrollbar-track:active {
background-color: rgba($base-overlay-background, 0.3);
}
}
} }
.character-counter { .character-counter {
@ -235,17 +246,6 @@
} }
} }
.emoji-picker-dropdown {
position: absolute;
right: 5px;
top: 5px;
::-webkit-scrollbar-track:hover,
::-webkit-scrollbar-track:active {
background-color: rgba($base-overlay-background, 0.3);
}
}
.compose-form__autosuggest-wrapper, .compose-form__autosuggest-wrapper,
.autosuggest-input { .autosuggest-input {
position: relative; position: relative;

View File

@ -1649,3 +1649,4 @@ noscript {
@import 'local_settings'; @import 'local_settings';
@import 'error_boundary'; @import 'error_boundary';
@import 'single_column'; @import 'single_column';
@import 'announcements';

View File

@ -213,6 +213,12 @@ code {
} }
} }
.input.datetime .label_input select {
display: inline-block;
width: auto;
flex: 0;
}
.required abbr { .required abbr {
text-decoration: none; text-decoration: none;
color: lighten($error-value-color, 12%); color: lighten($error-value-color, 12%);

View File

@ -2,6 +2,14 @@ import WebSocketClient from '@gamestdio/websocket';
const randomIntUpTo = max => Math.floor(Math.random() * Math.floor(max)); const randomIntUpTo = max => Math.floor(Math.random() * Math.floor(max));
const knownEventTypes = [
'update',
'delete',
'notification',
'conversation',
'filters_changed',
];
export function connectStream(path, pollingRefresh = null, callbacks = () => ({ onConnect() {}, onDisconnect() {}, onReceive() {} })) { export function connectStream(path, pollingRefresh = null, callbacks = () => ({ onConnect() {}, onDisconnect() {}, onReceive() {} })) {
return (dispatch, getState) => { return (dispatch, getState) => {
const streamingAPIBaseURL = getState().getIn(['meta', 'streaming_api_base_url']); const streamingAPIBaseURL = getState().getIn(['meta', 'streaming_api_base_url']);
@ -69,8 +77,11 @@ export function connectStream(path, pollingRefresh = null, callbacks = () => ({
export default function getStream(streamingAPIBaseURL, accessToken, stream, { connected, received, disconnected, reconnected }) { export default function getStream(streamingAPIBaseURL, accessToken, stream, { connected, received, disconnected, reconnected }) {
const params = [ `stream=${stream}` ]; const params = stream.split('&');
stream = params.shift();
if (streamingAPIBaseURL.startsWith('ws')) {
params.unshift(`stream=${stream}`);
const ws = new WebSocketClient(`${streamingAPIBaseURL}/api/v1/streaming/?${params.join('&')}`, accessToken); const ws = new WebSocketClient(`${streamingAPIBaseURL}/api/v1/streaming/?${params.join('&')}`, accessToken);
ws.onopen = connected; ws.onopen = connected;
@ -79,4 +90,29 @@ export default function getStream(streamingAPIBaseURL, accessToken, stream, { co
ws.onreconnect = reconnected; ws.onreconnect = reconnected;
return ws; return ws;
}
params.push(`access_token=${accessToken}`);
const es = new EventSource(`${streamingAPIBaseURL}/api/v1/streaming/${stream}?${params.join('&')}`);
let firstConnect = true;
es.onopen = () => {
if (firstConnect) {
firstConnect = false;
connected();
} else {
reconnected();
}
};
for (let type of knownEventTypes) {
es.addEventListener(type, (e) => {
received({
event: e.type,
payload: e.data,
});
});
}
es.onerror = disconnected;
return es;
}; };

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -0,0 +1,133 @@
import api from '../api';
import { normalizeAnnouncement } from './importer/normalizer';
export const ANNOUNCEMENTS_FETCH_REQUEST = 'ANNOUNCEMENTS_FETCH_REQUEST';
export const ANNOUNCEMENTS_FETCH_SUCCESS = 'ANNOUNCEMENTS_FETCH_SUCCESS';
export const ANNOUNCEMENTS_FETCH_FAIL = 'ANNOUNCEMENTS_FETCH_FAIL';
export const ANNOUNCEMENTS_UPDATE = 'ANNOUNCEMENTS_UPDATE';
export const ANNOUNCEMENTS_DISMISS = 'ANNOUNCEMENTS_DISMISS';
export const ANNOUNCEMENTS_REACTION_ADD_REQUEST = 'ANNOUNCEMENTS_REACTION_ADD_REQUEST';
export const ANNOUNCEMENTS_REACTION_ADD_SUCCESS = 'ANNOUNCEMENTS_REACTION_ADD_SUCCESS';
export const ANNOUNCEMENTS_REACTION_ADD_FAIL = 'ANNOUNCEMENTS_REACTION_ADD_FAIL';
export const ANNOUNCEMENTS_REACTION_REMOVE_REQUEST = 'ANNOUNCEMENTS_REACTION_REMOVE_REQUEST';
export const ANNOUNCEMENTS_REACTION_REMOVE_SUCCESS = 'ANNOUNCEMENTS_REACTION_REMOVE_SUCCESS';
export const ANNOUNCEMENTS_REACTION_REMOVE_FAIL = 'ANNOUNCEMENTS_REACTION_REMOVE_FAIL';
export const ANNOUNCEMENTS_REACTION_UPDATE = 'ANNOUNCEMENTS_REACTION_UPDATE';
const noOp = () => {};
export const fetchAnnouncements = (done = noOp) => (dispatch, getState) => {
dispatch(fetchAnnouncementsRequest());
api(getState).get('/api/v1/announcements').then(response => {
dispatch(fetchAnnouncementsSuccess(response.data.map(x => normalizeAnnouncement(x))));
}).catch(error => {
dispatch(fetchAnnouncementsFail(error));
}).finally(() => {
done();
});
};
export const fetchAnnouncementsRequest = () => ({
type: ANNOUNCEMENTS_FETCH_REQUEST,
skipLoading: true,
});
export const fetchAnnouncementsSuccess = announcements => ({
type: ANNOUNCEMENTS_FETCH_SUCCESS,
announcements,
skipLoading: true,
});
export const fetchAnnouncementsFail= error => ({
type: ANNOUNCEMENTS_FETCH_FAIL,
error,
skipLoading: true,
skipAlert: true,
});
export const updateAnnouncements = announcement => ({
type: ANNOUNCEMENTS_UPDATE,
announcement: normalizeAnnouncement(announcement),
});
export const dismissAnnouncement = announcementId => (dispatch, getState) => {
dispatch({
type: ANNOUNCEMENTS_DISMISS,
id: announcementId,
});
api(getState).post(`/api/v1/announcements/${announcementId}/dismiss`);
};
export const addReaction = (announcementId, name) => (dispatch, getState) => {
dispatch(addReactionRequest(announcementId, name));
api(getState).put(`/api/v1/announcements/${announcementId}/reactions/${name}`).then(() => {
dispatch(addReactionSuccess(announcementId, name));
}).catch(err => {
dispatch(addReactionFail(announcementId, name, err));
});
};
export const addReactionRequest = (announcementId, name) => ({
type: ANNOUNCEMENTS_REACTION_ADD_REQUEST,
id: announcementId,
name,
skipLoading: true,
});
export const addReactionSuccess = (announcementId, name) => ({
type: ANNOUNCEMENTS_REACTION_ADD_SUCCESS,
id: announcementId,
name,
skipLoading: true,
});
export const addReactionFail = (announcementId, name, error) => ({
type: ANNOUNCEMENTS_REACTION_ADD_FAIL,
id: announcementId,
name,
error,
skipLoading: true,
});
export const removeReaction = (announcementId, name) => (dispatch, getState) => {
dispatch(removeReactionRequest(announcementId, name));
api(getState).delete(`/api/v1/announcements/${announcementId}/reactions/${name}`).then(() => {
dispatch(removeReactionSuccess(announcementId, name));
}).catch(err => {
dispatch(removeReactionFail(announcementId, name, err));
});
};
export const removeReactionRequest = (announcementId, name) => ({
type: ANNOUNCEMENTS_REACTION_REMOVE_REQUEST,
id: announcementId,
name,
skipLoading: true,
});
export const removeReactionSuccess = (announcementId, name) => ({
type: ANNOUNCEMENTS_REACTION_REMOVE_SUCCESS,
id: announcementId,
name,
skipLoading: true,
});
export const removeReactionFail = (announcementId, name, error) => ({
type: ANNOUNCEMENTS_REACTION_REMOVE_FAIL,
id: announcementId,
name,
error,
skipLoading: true,
});
export const updateReaction = reaction => ({
type: ANNOUNCEMENTS_REACTION_UPDATE,
reaction,
});

View File

@ -76,7 +76,6 @@ export function normalizeStatus(status, normalOldStatus) {
export function normalizePoll(poll) { export function normalizePoll(poll) {
const normalPoll = { ...poll }; const normalPoll = { ...poll };
const emojiMap = makeEmojiMap(normalPoll); const emojiMap = makeEmojiMap(normalPoll);
normalPoll.options = poll.options.map((option, index) => ({ normalPoll.options = poll.options.map((option, index) => ({
@ -87,3 +86,12 @@ export function normalizePoll(poll) {
return normalPoll; return normalPoll;
} }
export function normalizeAnnouncement(announcement) {
const normalAnnouncement = { ...announcement };
const emojiMap = makeEmojiMap(normalAnnouncement);
normalAnnouncement.contentHtml = emojify(normalAnnouncement.content, emojiMap);
return normalAnnouncement;
}

View File

@ -157,9 +157,9 @@ export function expandNotifications({ maxId } = {}, done = noOp) {
dispatch(expandNotificationsSuccess(response.data, next ? next.uri : null, isLoadingMore, isLoadingRecent, isLoadingRecent && preferPendingItems)); dispatch(expandNotificationsSuccess(response.data, next ? next.uri : null, isLoadingMore, isLoadingRecent, isLoadingRecent && preferPendingItems));
fetchRelatedRelationships(dispatch, response.data); fetchRelatedRelationships(dispatch, response.data);
done();
}).catch(error => { }).catch(error => {
dispatch(expandNotificationsFail(error, isLoadingMore)); dispatch(expandNotificationsFail(error, isLoadingMore));
}).finally(() => {
done(); done();
}); });
}; };
@ -188,6 +188,7 @@ export function expandNotificationsFail(error, isLoadingMore) {
type: NOTIFICATIONS_EXPAND_FAIL, type: NOTIFICATIONS_EXPAND_FAIL,
error, error,
skipLoading: !isLoadingMore, skipLoading: !isLoadingMore,
skipAlert: !isLoadingMore,
}; };
}; };

View File

@ -8,6 +8,7 @@ import {
} from './timelines'; } from './timelines';
import { updateNotifications, expandNotifications } from './notifications'; import { updateNotifications, expandNotifications } from './notifications';
import { updateConversations } from './conversations'; import { updateConversations } from './conversations';
import { fetchAnnouncements, updateAnnouncements, updateReaction as updateAnnouncementsReaction } from './announcements';
import { fetchFilters } from './filters'; import { fetchFilters } from './filters';
import { getLocale } from '../locales'; import { getLocale } from '../locales';
@ -44,6 +45,12 @@ export function connectTimelineStream (timelineId, path, pollingRefresh = null,
case 'filters_changed': case 'filters_changed':
dispatch(fetchFilters()); dispatch(fetchFilters());
break; break;
case 'announcement':
dispatch(updateAnnouncements(JSON.parse(data.payload)));
break;
case 'announcement.reaction':
dispatch(updateAnnouncementsReaction(JSON.parse(data.payload)));
break;
} }
}, },
}; };
@ -51,7 +58,9 @@ export function connectTimelineStream (timelineId, path, pollingRefresh = null,
} }
const refreshHomeTimelineAndNotification = (dispatch, done) => { const refreshHomeTimelineAndNotification = (dispatch, done) => {
dispatch(expandHomeTimeline({}, () => dispatch(expandNotifications({}, done)))); dispatch(expandHomeTimeline({}, () =>
dispatch(expandNotifications({}, () =>
dispatch(fetchAnnouncements(done))))));
}; };
export const connectUserStream = () => connectTimelineStream('home', 'user', refreshHomeTimelineAndNotification); export const connectUserStream = () => connectTimelineStream('home', 'user', refreshHomeTimelineAndNotification);

View File

@ -98,9 +98,9 @@ export function expandTimeline(timelineId, path, params = {}, done = noOp) {
const next = getLinks(response).refs.find(link => link.rel === 'next'); const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedStatuses(response.data)); dispatch(importFetchedStatuses(response.data));
dispatch(expandTimelineSuccess(timelineId, response.data, next ? next.uri : null, response.status === 206, isLoadingRecent, isLoadingMore, isLoadingRecent && preferPendingItems)); dispatch(expandTimelineSuccess(timelineId, response.data, next ? next.uri : null, response.status === 206, isLoadingRecent, isLoadingMore, isLoadingRecent && preferPendingItems));
done();
}).catch(error => { }).catch(error => {
dispatch(expandTimelineFail(timelineId, error, isLoadingMore)); dispatch(expandTimelineFail(timelineId, error, isLoadingMore));
}).finally(() => {
done(); done();
}); });
}; };

View File

@ -58,7 +58,7 @@ export default class ErrorBoundary extends React.PureComponent {
<div> <div>
<p className='error-boundary__error'><FormattedMessage id='error.unexpected_crash.explanation' defaultMessage='Due to a bug in our code or a browser compatibility issue, this page could not be displayed correctly.' /></p> <p className='error-boundary__error'><FormattedMessage id='error.unexpected_crash.explanation' defaultMessage='Due to a bug in our code or a browser compatibility issue, this page could not be displayed correctly.' /></p>
<p><FormattedMessage id='error.unexpected_crash.next_steps' defaultMessage='Try refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.' /></p> <p><FormattedMessage id='error.unexpected_crash.next_steps' defaultMessage='Try refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.' /></p>
<p className='error-boundary__footer'>Mastodon v{version} · <a href={source_url} rel='noopener noreferrer' target='_blank'><FormattedMessage id='errors.unexpected_crash.report_issue' defaultMessage='Report issue' /></a> · <button onClick={this.handleCopyStackTrace} className={copied && 'copied'}><FormattedMessage id='errors.unexpected_crash.copy_stacktrace' defaultMessage='Copy stacktrace to clipboard' /></button></p> <p className='error-boundary__footer'>Mastodon v{version} · <a href={source_url} rel='noopener noreferrer' target='_blank'><FormattedMessage id='errors.unexpected_crash.report_issue' defaultMessage='Report issue' /></a> · <button onClick={this.handleCopyStackTrace} className={copied ? 'copied' : ''}><FormattedMessage id='errors.unexpected_crash.copy_stacktrace' defaultMessage='Copy stacktrace to clipboard' /></button></p>
</div> </div>
</div> </div>
); );

View File

@ -115,6 +115,7 @@ class AccountTimeline extends ImmutablePureComponent {
shouldUpdateScroll={shouldUpdateScroll} shouldUpdateScroll={shouldUpdateScroll}
emptyMessage={emptyMessage} emptyMessage={emptyMessage}
bindToDocument={!multiColumn} bindToDocument={!multiColumn}
timelineId='account'
/> />
</Column> </Column>
); );

View File

@ -290,6 +290,7 @@ class EmojiPickerDropdown extends React.PureComponent {
onPickEmoji: PropTypes.func.isRequired, onPickEmoji: PropTypes.func.isRequired,
onSkinTone: PropTypes.func.isRequired, onSkinTone: PropTypes.func.isRequired,
skinTone: PropTypes.number.isRequired, skinTone: PropTypes.number.isRequired,
button: PropTypes.node,
}; };
state = { state = {
@ -350,18 +351,18 @@ class EmojiPickerDropdown extends React.PureComponent {
} }
render () { render () {
const { intl, onPickEmoji, onSkinTone, skinTone, frequentlyUsedEmojis } = this.props; const { intl, onPickEmoji, onSkinTone, skinTone, frequentlyUsedEmojis, button } = this.props;
const title = intl.formatMessage(messages.emoji); const title = intl.formatMessage(messages.emoji);
const { active, loading, placement } = this.state; const { active, loading, placement } = this.state;
return ( return (
<div className='emoji-picker-dropdown' onKeyDown={this.handleKeyDown}> <div className='emoji-picker-dropdown' onKeyDown={this.handleKeyDown}>
<div ref={this.setTargetRef} className='emoji-button' title={title} aria-label={title} aria-expanded={active} role='button' onClick={this.onToggle} onKeyDown={this.onToggle} tabIndex={0}> <div ref={this.setTargetRef} className='emoji-button' title={title} aria-label={title} aria-expanded={active} role='button' onClick={this.onToggle} onKeyDown={this.onToggle} tabIndex={0}>
<img {button || <img
className={classNames('emojione', { 'pulse-loading': active && loading })} className={classNames('emojione', { 'pulse-loading': active && loading })}
alt='🙂' alt='🙂'
src={`${assetHost}/emoji/1f602.svg`} src={`${assetHost}/emoji/1f602.svg`}
/> />}
</div> </div>
<Overlay show={active} placement={placement} target={this.findTarget}> <Overlay show={active} placement={placement} target={this.findTarget}>

View File

@ -22,6 +22,7 @@ const messages = defineMessages({
requested: { id: 'account.requested', defaultMessage: 'Awaiting approval' }, requested: { id: 'account.requested', defaultMessage: 'Awaiting approval' },
unblock: { id: 'account.unblock', defaultMessage: 'Unblock @{name}' }, unblock: { id: 'account.unblock', defaultMessage: 'Unblock @{name}' },
unmute: { id: 'account.unmute', defaultMessage: 'Unmute @{name}' }, unmute: { id: 'account.unmute', defaultMessage: 'Unmute @{name}' },
unfollowConfirm: { id: 'confirmations.unfollow.confirm', defaultMessage: 'Unfollow' },
}); });
const makeMapStateToProps = () => { const makeMapStateToProps = () => {

View File

@ -0,0 +1,395 @@
import React from 'react';
import ImmutablePureComponent from 'react-immutable-pure-component';
import ReactSwipeableViews from 'react-swipeable-views';
import ImmutablePropTypes from 'react-immutable-proptypes';
import PropTypes from 'prop-types';
import IconButton from 'mastodon/components/icon_button';
import Icon from 'mastodon/components/icon';
import { defineMessages, injectIntl, FormattedMessage, FormattedDate, FormattedNumber } from 'react-intl';
import { autoPlayGif } from 'mastodon/initial_state';
import elephantUIPlane from 'mastodon/../images/elephant_ui_plane.svg';
import { mascot } from 'mastodon/initial_state';
import unicodeMapping from 'mastodon/features/emoji/emoji_unicode_mapping_light';
import classNames from 'classnames';
import EmojiPickerDropdown from 'mastodon/features/compose/containers/emoji_picker_dropdown_container';
const messages = defineMessages({
close: { id: 'lightbox.close', defaultMessage: 'Close' },
previous: { id: 'lightbox.previous', defaultMessage: 'Previous' },
next: { id: 'lightbox.next', defaultMessage: 'Next' },
});
class Content extends ImmutablePureComponent {
static contextTypes = {
router: PropTypes.object,
};
static propTypes = {
announcement: ImmutablePropTypes.map.isRequired,
};
setRef = c => {
this.node = c;
}
componentDidMount () {
this._updateLinks();
this._updateEmojis();
}
componentDidUpdate () {
this._updateLinks();
this._updateEmojis();
}
_updateEmojis () {
const node = this.node;
if (!node || autoPlayGif) {
return;
}
const emojis = node.querySelectorAll('.custom-emoji');
for (var i = 0; i < emojis.length; i++) {
let emoji = emojis[i];
if (emoji.classList.contains('status-emoji')) {
continue;
}
emoji.classList.add('status-emoji');
emoji.addEventListener('mouseenter', this.handleEmojiMouseEnter, false);
emoji.addEventListener('mouseleave', this.handleEmojiMouseLeave, false);
}
}
_updateLinks () {
const node = this.node;
if (!node) {
return;
}
const links = node.querySelectorAll('a');
for (var i = 0; i < links.length; ++i) {
let link = links[i];
if (link.classList.contains('status-link')) {
continue;
}
link.classList.add('status-link');
let mention = this.props.announcement.get('mentions').find(item => link.href === item.get('url'));
if (mention) {
link.addEventListener('click', this.onMentionClick.bind(this, mention), false);
link.setAttribute('title', mention.get('acct'));
} else if (link.textContent[0] === '#' || (link.previousSibling && link.previousSibling.textContent && link.previousSibling.textContent[link.previousSibling.textContent.length - 1] === '#')) {
link.addEventListener('click', this.onHashtagClick.bind(this, link.text), false);
} else {
link.setAttribute('title', link.href);
link.classList.add('unhandled-link');
}
link.setAttribute('target', '_blank');
link.setAttribute('rel', 'noopener noreferrer');
}
}
onMentionClick = (mention, e) => {
if (this.context.router && e.button === 0 && !(e.ctrlKey || e.metaKey)) {
e.preventDefault();
this.context.router.history.push(`/accounts/${mention.get('id')}`);
}
}
onHashtagClick = (hashtag, e) => {
hashtag = hashtag.replace(/^#/, '');
if (this.context.router && e.button === 0 && !(e.ctrlKey || e.metaKey)) {
e.preventDefault();
this.context.router.history.push(`/timelines/tag/${hashtag}`);
}
}
handleEmojiMouseEnter = ({ target }) => {
target.src = target.getAttribute('data-original');
}
handleEmojiMouseLeave = ({ target }) => {
target.src = target.getAttribute('data-static');
}
render () {
const { announcement } = this.props;
return (
<div
className='announcements__item__content'
ref={this.setRef}
dangerouslySetInnerHTML={{ __html: announcement.get('contentHtml') }}
/>
);
}
}
const assetHost = process.env.CDN_HOST || '';
class Emoji extends React.PureComponent {
static propTypes = {
emoji: PropTypes.string.isRequired,
emojiMap: ImmutablePropTypes.map.isRequired,
hovered: PropTypes.bool.isRequired,
};
render () {
const { emoji, emojiMap, hovered } = this.props;
if (unicodeMapping[emoji]) {
const { filename, shortCode } = unicodeMapping[this.props.emoji];
const title = shortCode ? `:${shortCode}:` : '';
return (
<img
draggable='false'
className='emojione'
alt={emoji}
title={title}
src={`${assetHost}/emoji/${filename}.svg`}
/>
);
} else if (emojiMap.get(emoji)) {
const filename = (autoPlayGif || hovered) ? emojiMap.getIn([emoji, 'url']) : emojiMap.getIn([emoji, 'static_url']);
const shortCode = `:${emoji}:`;
return (
<img
draggable='false'
className='emojione custom-emoji'
alt={shortCode}
title={shortCode}
src={filename}
/>
);
} else {
return null;
}
}
}
class Reaction extends ImmutablePureComponent {
static propTypes = {
announcementId: PropTypes.string.isRequired,
reaction: ImmutablePropTypes.map.isRequired,
addReaction: PropTypes.func.isRequired,
removeReaction: PropTypes.func.isRequired,
emojiMap: ImmutablePropTypes.map.isRequired,
};
state = {
hovered: false,
};
handleClick = () => {
const { reaction, announcementId, addReaction, removeReaction } = this.props;
if (reaction.get('me')) {
removeReaction(announcementId, reaction.get('name'));
} else {
addReaction(announcementId, reaction.get('name'));
}
}
handleMouseEnter = () => this.setState({ hovered: true })
handleMouseLeave = () => this.setState({ hovered: false })
render () {
const { reaction } = this.props;
let shortCode = reaction.get('name');
if (unicodeMapping[shortCode]) {
shortCode = unicodeMapping[shortCode].shortCode;
}
return (
<button className={classNames('reactions-bar__item', { active: reaction.get('me') })} onClick={this.handleClick} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave} title={`:${shortCode}:`}>
<span className='reactions-bar__item__emoji'><Emoji hovered={this.state.hovered} emoji={reaction.get('name')} emojiMap={this.props.emojiMap} /></span>
<span className='reactions-bar__item__count'><FormattedNumber value={reaction.get('count')} /></span>
</button>
);
}
}
class ReactionsBar extends ImmutablePureComponent {
static propTypes = {
announcementId: PropTypes.string.isRequired,
reactions: ImmutablePropTypes.list.isRequired,
addReaction: PropTypes.func.isRequired,
removeReaction: PropTypes.func.isRequired,
emojiMap: ImmutablePropTypes.map.isRequired,
};
handleEmojiPick = data => {
const { addReaction, announcementId } = this.props;
addReaction(announcementId, data.native.replace(/:/g, ''));
}
render () {
const { reactions } = this.props;
const visibleReactions = reactions.filter(x => x.get('count') > 0);
return (
<div className={classNames('reactions-bar', { 'reactions-bar--empty': visibleReactions.isEmpty() })}>
{visibleReactions.map(reaction => (
<Reaction
key={reaction.get('name')}
reaction={reaction}
announcementId={this.props.announcementId}
addReaction={this.props.addReaction}
removeReaction={this.props.removeReaction}
emojiMap={this.props.emojiMap}
/>
))}
<EmojiPickerDropdown onPickEmoji={this.handleEmojiPick} button={<Icon id='plus' />} />
</div>
);
}
}
class Announcement extends ImmutablePureComponent {
static propTypes = {
announcement: ImmutablePropTypes.map.isRequired,
emojiMap: ImmutablePropTypes.map.isRequired,
dismissAnnouncement: PropTypes.func.isRequired,
addReaction: PropTypes.func.isRequired,
removeReaction: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired,
};
handleDismissClick = () => {
const { dismissAnnouncement, announcement } = this.props;
dismissAnnouncement(announcement.get('id'));
}
render () {
const { announcement, intl } = this.props;
const startsAt = announcement.get('starts_at') && new Date(announcement.get('starts_at'));
const endsAt = announcement.get('ends_at') && new Date(announcement.get('ends_at'));
const now = new Date();
const hasTimeRange = startsAt && endsAt;
const skipYear = hasTimeRange && startsAt.getFullYear() === endsAt.getFullYear() && endsAt.getFullYear() === now.getFullYear();
const skipEndDate = hasTimeRange && startsAt.getDate() === endsAt.getDate() && startsAt.getMonth() === endsAt.getMonth() && startsAt.getFullYear() === endsAt.getFullYear();
const skipTime = announcement.get('all_day');
return (
<div className='announcements__item'>
<strong className='announcements__item__range'>
<FormattedMessage id='announcement.announcement' defaultMessage='Announcement' />
{hasTimeRange && <span> · <FormattedDate value={startsAt} hour12={false} year={(skipYear || startsAt.getFullYear() === now.getFullYear()) ? undefined : 'numeric'} month='short' day='2-digit' hour={skipTime ? undefined : '2-digit'} minute={skipTime ? undefined : '2-digit'} /> - <FormattedDate value={endsAt} hour12={false} year={(skipYear || endsAt.getFullYear() === now.getFullYear()) ? undefined : 'numeric'} month={skipEndDate ? undefined : 'short'} day={skipEndDate ? undefined : '2-digit'} hour={skipTime ? undefined : '2-digit'} minute={skipTime ? undefined : '2-digit'} /></span>}
</strong>
<Content announcement={announcement} />
<ReactionsBar
reactions={announcement.get('reactions')}
announcementId={announcement.get('id')}
addReaction={this.props.addReaction}
removeReaction={this.props.removeReaction}
emojiMap={this.props.emojiMap}
/>
<IconButton title={intl.formatMessage(messages.close)} icon='times' className='announcements__item__dismiss-icon' onClick={this.handleDismissClick} />
</div>
);
}
}
export default @injectIntl
class Announcements extends ImmutablePureComponent {
static propTypes = {
announcements: ImmutablePropTypes.list,
emojiMap: ImmutablePropTypes.map.isRequired,
fetchAnnouncements: PropTypes.func.isRequired,
dismissAnnouncement: PropTypes.func.isRequired,
addReaction: PropTypes.func.isRequired,
removeReaction: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired,
};
state = {
index: 0,
};
componentDidMount () {
const { fetchAnnouncements } = this.props;
fetchAnnouncements();
}
handleChangeIndex = index => {
this.setState({ index: index % this.props.announcements.size });
}
handleNextClick = () => {
this.setState({ index: (this.state.index + 1) % this.props.announcements.size });
}
handlePrevClick = () => {
this.setState({ index: (this.props.announcements.size + this.state.index - 1) % this.props.announcements.size });
}
render () {
const { announcements, intl } = this.props;
const { index } = this.state;
if (announcements.isEmpty()) {
return null;
}
return (
<div className='announcements'>
<img className='announcements__mastodon' alt='' draggable='false' src={mascot || elephantUIPlane} />
<div className='announcements__container'>
<ReactSwipeableViews index={index} onChangeIndex={this.handleChangeIndex}>
{announcements.map(announcement => (
<Announcement
key={announcement.get('id')}
announcement={announcement}
emojiMap={this.props.emojiMap}
dismissAnnouncement={this.props.dismissAnnouncement}
addReaction={this.props.addReaction}
removeReaction={this.props.removeReaction}
intl={intl}
/>
))}
</ReactSwipeableViews>
<div className='announcements__pagination'>
<IconButton disabled={announcements.size === 1} title={intl.formatMessage(messages.previous)} icon='chevron-left' onClick={this.handlePrevClick} size={13} />
<span>{index + 1} / {announcements.size}</span>
<IconButton disabled={announcements.size === 1} title={intl.formatMessage(messages.next)} icon='chevron-right' onClick={this.handleNextClick} size={13} />
</div>
</div>
</div>
);
}
}

View File

@ -0,0 +1,21 @@
import { connect } from 'react-redux';
import { fetchAnnouncements, dismissAnnouncement, addReaction, removeReaction } from 'mastodon/actions/announcements';
import Announcements from '../components/announcements';
import { createSelector } from 'reselect';
import { Map as ImmutableMap } from 'immutable';
const customEmojiMap = createSelector([state => state.get('custom_emojis')], items => items.reduce((map, emoji) => map.set(emoji.get('shortcode'), emoji), ImmutableMap()));
const mapStateToProps = state => ({
announcements: state.getIn(['announcements', 'items']),
emojiMap: customEmojiMap(state),
});
const mapDispatchToProps = dispatch => ({
fetchAnnouncements: () => dispatch(fetchAnnouncements()),
dismissAnnouncement: id => dispatch(dismissAnnouncement(id)),
addReaction: (id, name) => dispatch(addReaction(id, name)),
removeReaction: (id, name) => dispatch(removeReaction(id, name)),
});
export default connect(mapStateToProps, mapDispatchToProps)(Announcements);

View File

@ -1,5 +1,5 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { fetchTrends } from '../../../actions/trends'; import { fetchTrends } from 'mastodon/actions/trends';
import Trends from '../components/trends'; import Trends from '../components/trends';
const mapStateToProps = state => ({ const mapStateToProps = state => ({

View File

@ -9,6 +9,7 @@ import { addColumn, removeColumn, moveColumn } from '../../actions/columns';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import ColumnSettingsContainer from './containers/column_settings_container'; import ColumnSettingsContainer from './containers/column_settings_container';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import AnnouncementsContainer from 'mastodon/features/getting_started/containers/announcements_container';
const messages = defineMessages({ const messages = defineMessages({
title: { id: 'column.home', defaultMessage: 'Home' }, title: { id: 'column.home', defaultMessage: 'Home' },
@ -113,6 +114,8 @@ class HomeTimeline extends React.PureComponent {
</ColumnHeader> </ColumnHeader>
<StatusListContainer <StatusListContainer
prepend={<AnnouncementsContainer />}
alwaysPrepend
trackScroll={!pinned} trackScroll={!pinned}
scrollKey={`home_timeline-${columnId}`} scrollKey={`home_timeline-${columnId}`}
onLoadMore={this.handleLoadMore} onLoadMore={this.handleLoadMore}

View File

@ -211,7 +211,6 @@ class MediaModal extends ImmutablePureComponent {
style={swipeableViewsStyle} style={swipeableViewsStyle}
containerStyle={containerStyle} containerStyle={containerStyle}
onChangeIndex={this.handleSwipe} onChangeIndex={this.handleSwipe}
onSwitching={this.handleSwitching}
index={index} index={index}
> >
{content} {content}

View File

@ -43,6 +43,7 @@
"alert.rate_limited.title": "المعدل محدود", "alert.rate_limited.title": "المعدل محدود",
"alert.unexpected.message": "لقد طرأ هناك خطأ غير متوقّع.", "alert.unexpected.message": "لقد طرأ هناك خطأ غير متوقّع.",
"alert.unexpected.title": "المعذرة!", "alert.unexpected.title": "المعذرة!",
"announcement.announcement": "Announcement",
"autosuggest_hashtag.per_week": "{count} في الأسبوع", "autosuggest_hashtag.per_week": "{count} في الأسبوع",
"boost_modal.combo": "يمكنك/ي ضغط {combo} لتخطّي هذه في المرّة القادمة", "boost_modal.combo": "يمكنك/ي ضغط {combo} لتخطّي هذه في المرّة القادمة",
"bundle_column_error.body": "لقد وقع هناك خطأ أثناء عملية تحميل هذا العنصر.", "bundle_column_error.body": "لقد وقع هناك خطأ أثناء عملية تحميل هذا العنصر.",
@ -84,8 +85,8 @@
"compose_form.poll.duration": "مدة استطلاع الرأي", "compose_form.poll.duration": "مدة استطلاع الرأي",
"compose_form.poll.option_placeholder": "الخيار {number}", "compose_form.poll.option_placeholder": "الخيار {number}",
"compose_form.poll.remove_option": "إزالة هذا الخيار", "compose_form.poll.remove_option": "إزالة هذا الخيار",
"compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", "compose_form.poll.switch_to_multiple": "عدّل استطلاع الرأي وغيّره لإتاحة الخيارات المتعددة",
"compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.poll.switch_to_single": "عدّل استطلاع الرأي وغيّره لإتاحة خيار واحد فقط",
"compose_form.publish": "بوّق", "compose_form.publish": "بوّق",
"compose_form.publish_loud": "{publish}!", "compose_form.publish_loud": "{publish}!",
"compose_form.sensitive.hide": "تحديد الوسائط كحساسة", "compose_form.sensitive.hide": "تحديد الوسائط كحساسة",
@ -142,7 +143,7 @@
"empty_column.account_timeline": "ليس هناك تبويقات!", "empty_column.account_timeline": "ليس هناك تبويقات!",
"empty_column.account_unavailable": "الملف التعريفي غير متوفر", "empty_column.account_unavailable": "الملف التعريفي غير متوفر",
"empty_column.blocks": "لم تقم بحظر أي مستخدِم بعد.", "empty_column.blocks": "لم تقم بحظر أي مستخدِم بعد.",
"empty_column.bookmarked_statuses": "You don't have any bookmarked toots yet. When you bookmark one, it will show up here.", "empty_column.bookmarked_statuses": "ليس لديك أية تبويقات في الفواصل المرجعية بعد. عندما ستقوم بإضافة البعض منها، ستظهر هنا.",
"empty_column.community": "الخط العام المحلي فارغ. أكتب شيئا ما للعامة كبداية!", "empty_column.community": "الخط العام المحلي فارغ. أكتب شيئا ما للعامة كبداية!",
"empty_column.direct": "لم تتلق أية رسالة خاصة مباشِرة بعد. سوف يتم عرض الرسائل المباشرة هنا إن قمت بإرسال واحدة أو تلقيت البعض منها.", "empty_column.direct": "لم تتلق أية رسالة خاصة مباشِرة بعد. سوف يتم عرض الرسائل المباشرة هنا إن قمت بإرسال واحدة أو تلقيت البعض منها.",
"empty_column.domain_blocks": "ليس هناك نطاقات مخفية بعد.", "empty_column.domain_blocks": "ليس هناك نطاقات مخفية بعد.",

View File

@ -43,9 +43,10 @@
"alert.rate_limited.title": "Rate limited", "alert.rate_limited.title": "Rate limited",
"alert.unexpected.message": "Asocedió un fallu inesperáu.", "alert.unexpected.message": "Asocedió un fallu inesperáu.",
"alert.unexpected.title": "¡Meca!", "alert.unexpected.title": "¡Meca!",
"announcement.announcement": "Announcement",
"autosuggest_hashtag.per_week": "{count} per selmana", "autosuggest_hashtag.per_week": "{count} per selmana",
"boost_modal.combo": "Pues primir {combo} pa saltar esto la próxima vegada", "boost_modal.combo": "Pues primir {combo} pa saltar esto la próxima vegada",
"bundle_column_error.body": "Something went wrong while loading this component.", "bundle_column_error.body": "Asocedió daqué malo mentanto se cargaba esti componente.",
"bundle_column_error.retry": "Try again", "bundle_column_error.retry": "Try again",
"bundle_column_error.title": "Network error", "bundle_column_error.title": "Network error",
"bundle_modal_error.close": "Close", "bundle_modal_error.close": "Close",

View File

@ -43,6 +43,7 @@
"alert.rate_limited.title": "Rate limited", "alert.rate_limited.title": "Rate limited",
"alert.unexpected.message": "An unexpected error occurred.", "alert.unexpected.message": "An unexpected error occurred.",
"alert.unexpected.title": "Oops!", "alert.unexpected.title": "Oops!",
"announcement.announcement": "Announcement",
"autosuggest_hashtag.per_week": "{count} per week", "autosuggest_hashtag.per_week": "{count} per week",
"boost_modal.combo": "You can press {combo} to skip this next time", "boost_modal.combo": "You can press {combo} to skip this next time",
"bundle_column_error.body": "Something went wrong while loading this component.", "bundle_column_error.body": "Something went wrong while loading this component.",

View File

@ -43,6 +43,7 @@
"alert.rate_limited.title": "হার সীমিত", "alert.rate_limited.title": "হার সীমিত",
"alert.unexpected.message": "সমস্যা অপ্রত্যাশিত.", "alert.unexpected.message": "সমস্যা অপ্রত্যাশিত.",
"alert.unexpected.title": "ওহো!", "alert.unexpected.title": "ওহো!",
"announcement.announcement": "Announcement",
"autosuggest_hashtag.per_week": "প্রতি সপ্তাহে {count}", "autosuggest_hashtag.per_week": "প্রতি সপ্তাহে {count}",
"boost_modal.combo": "পরেরবার আপনি {combo} টিপলে এটি আর আসবে না", "boost_modal.combo": "পরেরবার আপনি {combo} টিপলে এটি আর আসবে না",
"bundle_column_error.body": "এই অংশটি দেখতে যেয়ে কোনো সমস্যা হয়েছে।.", "bundle_column_error.body": "এই অংশটি দেখতে যেয়ে কোনো সমস্যা হয়েছে।.",

View File

@ -43,6 +43,7 @@
"alert.rate_limited.title": "Rate limited", "alert.rate_limited.title": "Rate limited",
"alert.unexpected.message": "Ur fazi dic'hortozet zo degouezhet.", "alert.unexpected.message": "Ur fazi dic'hortozet zo degouezhet.",
"alert.unexpected.title": "C'hem !", "alert.unexpected.title": "C'hem !",
"announcement.announcement": "Announcement",
"autosuggest_hashtag.per_week": "{count} bep sizhun", "autosuggest_hashtag.per_week": "{count} bep sizhun",
"boost_modal.combo": "You can press {combo} to skip this next time", "boost_modal.combo": "You can press {combo} to skip this next time",
"bundle_column_error.body": "Something went wrong while loading this component.", "bundle_column_error.body": "Something went wrong while loading this component.",

View File

@ -43,6 +43,7 @@
"alert.rate_limited.title": "Límit de freqüència", "alert.rate_limited.title": "Límit de freqüència",
"alert.unexpected.message": "S'ha produït un error inesperat.", "alert.unexpected.message": "S'ha produït un error inesperat.",
"alert.unexpected.title": "Vaja!", "alert.unexpected.title": "Vaja!",
"announcement.announcement": "Announcement",
"autosuggest_hashtag.per_week": "{count} per setmana", "autosuggest_hashtag.per_week": "{count} per setmana",
"boost_modal.combo": "Pots premer {combo} per saltar-te això el proper cop", "boost_modal.combo": "Pots premer {combo} per saltar-te això el proper cop",
"bundle_column_error.body": "S'ha produït un error en carregar aquest component.", "bundle_column_error.body": "S'ha produït un error en carregar aquest component.",
@ -84,8 +85,8 @@
"compose_form.poll.duration": "Durada de l'enquesta", "compose_form.poll.duration": "Durada de l'enquesta",
"compose_form.poll.option_placeholder": "Opció {number}", "compose_form.poll.option_placeholder": "Opció {number}",
"compose_form.poll.remove_option": "Elimina aquesta opció", "compose_form.poll.remove_option": "Elimina aquesta opció",
"compose_form.poll.switch_to_multiple": "Canvía lenquesta per a permetre diverses opcions", "compose_form.poll.switch_to_multiple": "Canvia lenquesta per a permetre diverses opcions",
"compose_form.poll.switch_to_single": "Canvía lenquesta per a permetre una sola opció", "compose_form.poll.switch_to_single": "Canvia lenquesta per a permetre una única opció",
"compose_form.publish": "Tut", "compose_form.publish": "Tut",
"compose_form.publish_loud": "{publish}!", "compose_form.publish_loud": "{publish}!",
"compose_form.sensitive.hide": "Marcar mèdia com a sensible", "compose_form.sensitive.hide": "Marcar mèdia com a sensible",

View File

@ -43,6 +43,7 @@
"alert.rate_limited.title": "Ghjettu limitatu", "alert.rate_limited.title": "Ghjettu limitatu",
"alert.unexpected.message": "Un prublemu inaspettatu hè accadutu.", "alert.unexpected.message": "Un prublemu inaspettatu hè accadutu.",
"alert.unexpected.title": "Uups!", "alert.unexpected.title": "Uups!",
"announcement.announcement": "Announcement",
"autosuggest_hashtag.per_week": "{count} per settimana", "autosuggest_hashtag.per_week": "{count} per settimana",
"boost_modal.combo": "Pudete appughjà nant'à {combo} per saltà quessa a prussima volta", "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.", "bundle_column_error.body": "C'hè statu un prublemu caricandu st'elementu.",

View File

@ -43,6 +43,7 @@
"alert.rate_limited.title": "Rychlost omezena", "alert.rate_limited.title": "Rychlost omezena",
"alert.unexpected.message": "Objevila se neočekávaná chyba.", "alert.unexpected.message": "Objevila se neočekávaná chyba.",
"alert.unexpected.title": "Jejda!", "alert.unexpected.title": "Jejda!",
"announcement.announcement": "Announcement",
"autosuggest_hashtag.per_week": "{count} za týden", "autosuggest_hashtag.per_week": "{count} za týden",
"boost_modal.combo": "Příště můžete pro přeskočení stisknout {combo}", "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.", "bundle_column_error.body": "Při načítání této komponenty se něco pokazilo.",
@ -84,8 +85,8 @@
"compose_form.poll.duration": "Doba trvání ankety", "compose_form.poll.duration": "Doba trvání ankety",
"compose_form.poll.option_placeholder": "Volba {number}", "compose_form.poll.option_placeholder": "Volba {number}",
"compose_form.poll.remove_option": "Odstranit tuto volbu", "compose_form.poll.remove_option": "Odstranit tuto volbu",
"compose_form.poll.switch_to_multiple": "Povolit u ankety více možností", "compose_form.poll.switch_to_multiple": "Povolit u ankety výběr více možností",
"compose_form.poll.switch_to_single": "Povolit u ankety jedinou možnost", "compose_form.poll.switch_to_single": "Povolit u ankety výběr jediné možnosti",
"compose_form.publish": "Tootnout", "compose_form.publish": "Tootnout",
"compose_form.publish_loud": "{publish}!", "compose_form.publish_loud": "{publish}!",
"compose_form.sensitive.hide": "Označit média jako citlivá", "compose_form.sensitive.hide": "Označit média jako citlivá",

View File

@ -1,7 +1,7 @@
{ {
"account.add_or_remove_from_list": "Ychwanegu neu Dileu o'r rhestrau", "account.add_or_remove_from_list": "Ychwanegu neu Dileu o'r rhestrau",
"account.badges.bot": "Bot", "account.badges.bot": "Bot",
"account.badges.group": "Group", "account.badges.group": "Grŵp",
"account.block": "Blocio @{name}", "account.block": "Blocio @{name}",
"account.block_domain": "Cuddio popeth rhag {domain}", "account.block_domain": "Cuddio popeth rhag {domain}",
"account.blocked": "Blociwyd", "account.blocked": "Blociwyd",
@ -43,6 +43,7 @@
"alert.rate_limited.title": "Cyfradd gyfyngedig", "alert.rate_limited.title": "Cyfradd gyfyngedig",
"alert.unexpected.message": "Digwyddodd gwall annisgwyl.", "alert.unexpected.message": "Digwyddodd gwall annisgwyl.",
"alert.unexpected.title": "Wps!", "alert.unexpected.title": "Wps!",
"announcement.announcement": "Announcement",
"autosuggest_hashtag.per_week": "{count} yr wythnos", "autosuggest_hashtag.per_week": "{count} yr wythnos",
"boost_modal.combo": "Mae modd gwasgu {combo} er mwyn sgipio hyn tro nesa", "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.", "bundle_column_error.body": "Aeth rhywbeth o'i le tra'n llwytho'r elfen hon.",
@ -84,8 +85,8 @@
"compose_form.poll.duration": "Cyfnod pleidlais", "compose_form.poll.duration": "Cyfnod pleidlais",
"compose_form.poll.option_placeholder": "Dewisiad {number}", "compose_form.poll.option_placeholder": "Dewisiad {number}",
"compose_form.poll.remove_option": "Tynnu'r dewisiad", "compose_form.poll.remove_option": "Tynnu'r dewisiad",
"compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", "compose_form.poll.switch_to_multiple": "Newid pleidlais i adael mwy nag un dewis",
"compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.poll.switch_to_single": "Newid pleidlais i gyfyngu i un dewis",
"compose_form.publish": "Tŵt", "compose_form.publish": "Tŵt",
"compose_form.publish_loud": "{publish}!", "compose_form.publish_loud": "{publish}!",
"compose_form.sensitive.hide": "Marcio cyfryngau fel eu bod yn sensitif", "compose_form.sensitive.hide": "Marcio cyfryngau fel eu bod yn sensitif",

View File

@ -43,6 +43,7 @@
"alert.rate_limited.title": "Gradsbegrænset", "alert.rate_limited.title": "Gradsbegrænset",
"alert.unexpected.message": "Der opstod en uventet fejl.", "alert.unexpected.message": "Der opstod en uventet fejl.",
"alert.unexpected.title": "Ups!", "alert.unexpected.title": "Ups!",
"announcement.announcement": "Announcement",
"autosuggest_hashtag.per_week": "{count} per uge", "autosuggest_hashtag.per_week": "{count} per uge",
"boost_modal.combo": "Du kan trykke {combo} for at springe dette over næste gang", "boost_modal.combo": "Du kan trykke {combo} for at springe dette over næste gang",
"bundle_column_error.body": "Noget gik galt under indlæsningen af dette komponent.", "bundle_column_error.body": "Noget gik galt under indlæsningen af dette komponent.",

View File

@ -1,7 +1,7 @@
{ {
"account.add_or_remove_from_list": "Hinzufügen oder Entfernen von Listen", "account.add_or_remove_from_list": "Hinzufügen oder Entfernen von Listen",
"account.badges.bot": "Bot", "account.badges.bot": "Bot",
"account.badges.group": "Group", "account.badges.group": "Gruppe",
"account.block": "@{name} blockieren", "account.block": "@{name} blockieren",
"account.block_domain": "Alles von {domain} verstecken", "account.block_domain": "Alles von {domain} verstecken",
"account.blocked": "Blockiert", "account.blocked": "Blockiert",
@ -43,6 +43,7 @@
"alert.rate_limited.title": "Anfragelimit überschritten", "alert.rate_limited.title": "Anfragelimit überschritten",
"alert.unexpected.message": "Ein unerwarteter Fehler ist aufgetreten.", "alert.unexpected.message": "Ein unerwarteter Fehler ist aufgetreten.",
"alert.unexpected.title": "Hoppla!", "alert.unexpected.title": "Hoppla!",
"announcement.announcement": "Ankündigung",
"autosuggest_hashtag.per_week": "{count} pro Woche", "autosuggest_hashtag.per_week": "{count} pro Woche",
"boost_modal.combo": "Drücke {combo}, um dieses Fenster zu überspringen", "boost_modal.combo": "Drücke {combo}, um dieses Fenster zu überspringen",
"bundle_column_error.body": "Etwas ist beim Laden schiefgelaufen.", "bundle_column_error.body": "Etwas ist beim Laden schiefgelaufen.",
@ -84,8 +85,8 @@
"compose_form.poll.duration": "Umfragedauer", "compose_form.poll.duration": "Umfragedauer",
"compose_form.poll.option_placeholder": "Wahl {number}", "compose_form.poll.option_placeholder": "Wahl {number}",
"compose_form.poll.remove_option": "Wahl entfernen", "compose_form.poll.remove_option": "Wahl entfernen",
"compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", "compose_form.poll.switch_to_multiple": "Umfrage ändern, um mehrere Optionen zu erlauben",
"compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.poll.switch_to_single": "Umfrage ändern, um eine einzige Wahl zu ermöglichen",
"compose_form.publish": "Tröt", "compose_form.publish": "Tröt",
"compose_form.publish_loud": "{publish}!", "compose_form.publish_loud": "{publish}!",
"compose_form.sensitive.hide": "Medien als heikel markieren", "compose_form.sensitive.hide": "Medien als heikel markieren",

View File

@ -1407,6 +1407,10 @@
"defaultMessage": "Unmute @{name}", "defaultMessage": "Unmute @{name}",
"id": "account.unmute" "id": "account.unmute"
}, },
{
"defaultMessage": "Unfollow",
"id": "confirmations.unfollow.confirm"
},
{ {
"defaultMessage": "Are you sure you want to unfollow {name}?", "defaultMessage": "Are you sure you want to unfollow {name}?",
"id": "confirmations.unfollow.message" "id": "confirmations.unfollow.message"
@ -1563,6 +1567,10 @@
{ {
"defaultMessage": "Next", "defaultMessage": "Next",
"id": "lightbox.next" "id": "lightbox.next"
},
{
"defaultMessage": "Announcement",
"id": "announcement.announcement"
} }
], ],
"path": "app/javascript/mastodon/features/getting_started/components/announcements.json" "path": "app/javascript/mastodon/features/getting_started/components/announcements.json"

View File

@ -1,9 +1,9 @@
{ {
"account.add_or_remove_from_list": "Προσθήκη ή Αφαίρεση από λίστες", "account.add_or_remove_from_list": "Προσθήκη ή Αφαίρεση από λίστες",
"account.badges.bot": "Μποτ", "account.badges.bot": "Μποτ",
"account.badges.group": "Group", "account.badges.group": "Ομάδα",
"account.block": "Αποκλεισμός @{name}", "account.block": "Αποκλεισμός @{name}",
"account.block_domain": "Απόκρυψε τα πάντα από το {domain}", "account.block_domain": "Απόκρυψη όλων από {domain}",
"account.blocked": "Αποκλεισμένος/η", "account.blocked": "Αποκλεισμένος/η",
"account.cancel_follow_request": "Ακύρωση αιτήματος παρακολούθησης", "account.cancel_follow_request": "Ακύρωση αιτήματος παρακολούθησης",
"account.direct": "Προσωπικό μήνυμα προς @{name}", "account.direct": "Προσωπικό μήνυμα προς @{name}",
@ -43,6 +43,7 @@
"alert.rate_limited.title": "Περιορισμός συχνότητας", "alert.rate_limited.title": "Περιορισμός συχνότητας",
"alert.unexpected.message": "Προέκυψε απροσδόκητο σφάλμα.", "alert.unexpected.message": "Προέκυψε απροσδόκητο σφάλμα.",
"alert.unexpected.title": "Εεπ!", "alert.unexpected.title": "Εεπ!",
"announcement.announcement": "Announcement",
"autosuggest_hashtag.per_week": "{count} ανα εβδομάδα", "autosuggest_hashtag.per_week": "{count} ανα εβδομάδα",
"boost_modal.combo": "Μπορείς να πατήσεις {combo} για να το προσπεράσεις αυτό την επόμενη φορά", "boost_modal.combo": "Μπορείς να πατήσεις {combo} για να το προσπεράσεις αυτό την επόμενη φορά",
"bundle_column_error.body": "Κάτι πήγε στραβά ενώ φορτωνόταν αυτό το στοιχείο.", "bundle_column_error.body": "Κάτι πήγε στραβά ενώ φορτωνόταν αυτό το στοιχείο.",
@ -84,8 +85,8 @@
"compose_form.poll.duration": "Διάρκεια δημοσκόπησης", "compose_form.poll.duration": "Διάρκεια δημοσκόπησης",
"compose_form.poll.option_placeholder": "Επιλογή {number}", "compose_form.poll.option_placeholder": "Επιλογή {number}",
"compose_form.poll.remove_option": "Αφαίρεση επιλογής", "compose_form.poll.remove_option": "Αφαίρεση επιλογής",
"compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", "compose_form.poll.switch_to_multiple": "Ενημέρωση δημοσκόπησης με πολλαπλές επιλογές",
"compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.poll.switch_to_single": "Ενημέρωση δημοσκόπησης με μοναδική επιλογή",
"compose_form.publish": "Τουτ", "compose_form.publish": "Τουτ",
"compose_form.publish_loud": "{publish}!", "compose_form.publish_loud": "{publish}!",
"compose_form.sensitive.hide": "Σημείωσε τα πολυμέσα ως ευαίσθητα", "compose_form.sensitive.hide": "Σημείωσε τα πολυμέσα ως ευαίσθητα",

View File

@ -43,6 +43,7 @@
"alert.rate_limited.title": "Rate limited", "alert.rate_limited.title": "Rate limited",
"alert.unexpected.message": "An unexpected error occurred.", "alert.unexpected.message": "An unexpected error occurred.",
"alert.unexpected.title": "Oops!", "alert.unexpected.title": "Oops!",
"announcement.announcement": "Announcement",
"autosuggest_hashtag.per_week": "{count} per week", "autosuggest_hashtag.per_week": "{count} per week",
"boost_modal.combo": "You can press {combo} to skip this next time", "boost_modal.combo": "You can press {combo} to skip this next time",
"bundle_column_error.body": "Something went wrong while loading this component.", "bundle_column_error.body": "Something went wrong while loading this component.",

View File

@ -43,6 +43,7 @@
"alert.rate_limited.title": "Mesaĝkvante limigita", "alert.rate_limited.title": "Mesaĝkvante limigita",
"alert.unexpected.message": "Neatendita eraro okazis.", "alert.unexpected.message": "Neatendita eraro okazis.",
"alert.unexpected.title": "Ups!", "alert.unexpected.title": "Ups!",
"announcement.announcement": "Announcement",
"autosuggest_hashtag.per_week": "{count} semajne", "autosuggest_hashtag.per_week": "{count} semajne",
"boost_modal.combo": "Vi povas premi {combo} por preterpasi sekvafoje", "boost_modal.combo": "Vi povas premi {combo} por preterpasi sekvafoje",
"bundle_column_error.body": "Io misfunkciis en la ŝargado de ĉi tiu elemento.", "bundle_column_error.body": "Io misfunkciis en la ŝargado de ĉi tiu elemento.",

View File

@ -43,6 +43,7 @@
"alert.rate_limited.title": "Tarifa limitada", "alert.rate_limited.title": "Tarifa limitada",
"alert.unexpected.message": "Ocurrió un error.", "alert.unexpected.message": "Ocurrió un error.",
"alert.unexpected.title": "¡Epa!", "alert.unexpected.title": "¡Epa!",
"announcement.announcement": "Announcement",
"autosuggest_hashtag.per_week": "{count} por semana", "autosuggest_hashtag.per_week": "{count} por semana",
"boost_modal.combo": "Podés hacer clic en {combo} para saltar esto la próxima vez", "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.", "bundle_column_error.body": "Algo salió mal al cargar este componente.",

View File

@ -43,6 +43,7 @@
"alert.rate_limited.title": "Tasa limitada", "alert.rate_limited.title": "Tasa limitada",
"alert.unexpected.message": "Hubo un error inesperado.", "alert.unexpected.message": "Hubo un error inesperado.",
"alert.unexpected.title": "¡Ups!", "alert.unexpected.title": "¡Ups!",
"announcement.announcement": "Announcement",
"autosuggest_hashtag.per_week": "{count} por semana", "autosuggest_hashtag.per_week": "{count} por semana",
"boost_modal.combo": "Puedes hacer clic en {combo} para saltar este aviso la próxima vez", "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.", "bundle_column_error.body": "Algo salió mal al cargar este componente.",
@ -57,7 +58,7 @@
"column.direct": "Mensajes directos", "column.direct": "Mensajes directos",
"column.directory": "Buscar perfiles", "column.directory": "Buscar perfiles",
"column.domain_blocks": "Dominios ocultados", "column.domain_blocks": "Dominios ocultados",
"column.favourites": "Levantar la trompa", "column.favourites": "Favoritos",
"column.follow_requests": "Solicitudes de seguimiento", "column.follow_requests": "Solicitudes de seguimiento",
"column.home": "Inicio", "column.home": "Inicio",
"column.lists": "Listas", "column.lists": "Listas",
@ -86,7 +87,7 @@
"compose_form.poll.remove_option": "Eliminar esta opción", "compose_form.poll.remove_option": "Eliminar esta opción",
"compose_form.poll.switch_to_multiple": "Modificar encuesta para permitir múltiples opciones", "compose_form.poll.switch_to_multiple": "Modificar encuesta para permitir múltiples opciones",
"compose_form.poll.switch_to_single": "Modificar encuesta para permitir una única opción", "compose_form.poll.switch_to_single": "Modificar encuesta para permitir una única opción",
"compose_form.publish": "Ipoxta", "compose_form.publish": "Ipotxa",
"compose_form.publish_loud": "{publish}!", "compose_form.publish_loud": "{publish}!",
"compose_form.sensitive.hide": "Marcar multimedia como sensible", "compose_form.sensitive.hide": "Marcar multimedia como sensible",
"compose_form.sensitive.marked": "Material marcado como sensible", "compose_form.sensitive.marked": "Material marcado como sensible",
@ -131,7 +132,7 @@
"emoji_button.food": "Comida y bebida", "emoji_button.food": "Comida y bebida",
"emoji_button.label": "Insertar emoji", "emoji_button.label": "Insertar emoji",
"emoji_button.nature": "Naturaleza", "emoji_button.nature": "Naturaleza",
"emoji_button.not_found": "No hay emojos!! (╯°□°)╯︵ ┻━┻", "emoji_button.not_found": "No hay emojis!! ¯\\_(ツ)_/¯",
"emoji_button.objects": "Objetos", "emoji_button.objects": "Objetos",
"emoji_button.people": "Gente", "emoji_button.people": "Gente",
"emoji_button.recent": "Usados frecuentemente", "emoji_button.recent": "Usados frecuentemente",
@ -205,7 +206,7 @@
"introduction.welcome.text": "¡Bienvenido al fediverso! En unos momentos, podrás transmitir mensajes y hablar con tus amigos a través de una amplia variedad de servidores. Pero este servidor, {domain}, es especial, alberga tu perfil, así que recuerda su nombre.", "introduction.welcome.text": "¡Bienvenido al fediverso! En unos momentos, podrás transmitir mensajes y hablar con tus amigos a través de una amplia variedad de servidores. Pero este servidor, {domain}, es especial, alberga tu perfil, así que recuerda su nombre.",
"keyboard_shortcuts.back": "volver atrás", "keyboard_shortcuts.back": "volver atrás",
"keyboard_shortcuts.blocked": "abrir una lista de usuarios bloqueados", "keyboard_shortcuts.blocked": "abrir una lista de usuarios bloqueados",
"keyboard_shortcuts.boost": "reipoxta", "keyboard_shortcuts.boost": "retootear",
"keyboard_shortcuts.column": "enfocar un estado en una de las columnas", "keyboard_shortcuts.column": "enfocar un estado en una de las columnas",
"keyboard_shortcuts.compose": "enfocar el área de texto de redacción", "keyboard_shortcuts.compose": "enfocar el área de texto de redacción",
"keyboard_shortcuts.description": "Descripción", "keyboard_shortcuts.description": "Descripción",
@ -356,7 +357,7 @@
"status.block": "Bloquear a @{name}", "status.block": "Bloquear a @{name}",
"status.bookmark": "Marcador", "status.bookmark": "Marcador",
"status.cancel_reblog_private": "Des-impulsar", "status.cancel_reblog_private": "Des-impulsar",
"status.cannot_reblog": "Este bramido no puede rebarritarse", "status.cannot_reblog": "Este toot no puede retootearse",
"status.copy": "Copiar enlace al estado", "status.copy": "Copiar enlace al estado",
"status.delete": "Borrar", "status.delete": "Borrar",
"status.detailed_status": "Vista de conversación detallada", "status.detailed_status": "Vista de conversación detallada",
@ -374,7 +375,7 @@
"status.pin": "Fijar", "status.pin": "Fijar",
"status.pinned": "Toot fijado", "status.pinned": "Toot fijado",
"status.read_more": "Leer más", "status.read_more": "Leer más",
"status.reblog": "ReIpoxta", "status.reblog": "Retootear",
"status.reblog_private": "Implusar a la audiencia original", "status.reblog_private": "Implusar a la audiencia original",
"status.reblogged_by": "Retooteado por {name}", "status.reblogged_by": "Retooteado por {name}",
"status.reblogs.empty": "Nadie impulsó este toot todavía. Cuando alguien lo haga, aparecerá aqui.", "status.reblogs.empty": "Nadie impulsó este toot todavía. Cuando alguien lo haga, aparecerá aqui.",

View File

@ -43,6 +43,7 @@
"alert.rate_limited.title": "Piiratud", "alert.rate_limited.title": "Piiratud",
"alert.unexpected.message": "Tekkis ootamatu viga.", "alert.unexpected.message": "Tekkis ootamatu viga.",
"alert.unexpected.title": "Oih!", "alert.unexpected.title": "Oih!",
"announcement.announcement": "Announcement",
"autosuggest_hashtag.per_week": "{count} nädalas", "autosuggest_hashtag.per_week": "{count} nädalas",
"boost_modal.combo": "Võite vajutada {combo}, et see järgmine kord vahele jätta", "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.", "bundle_column_error.body": "Midagi läks valesti selle komponendi laadimisel.",

View File

@ -1,7 +1,7 @@
{ {
"account.add_or_remove_from_list": "Gehitu edo kendu zerrendetatik", "account.add_or_remove_from_list": "Gehitu edo kendu zerrendetatik",
"account.badges.bot": "Bot-a", "account.badges.bot": "Bot-a",
"account.badges.group": "Group", "account.badges.group": "Taldea",
"account.block": "Blokeatu @{name}", "account.block": "Blokeatu @{name}",
"account.block_domain": "Ezkutatu {domain} domeinuko guztia", "account.block_domain": "Ezkutatu {domain} domeinuko guztia",
"account.blocked": "Blokeatuta", "account.blocked": "Blokeatuta",
@ -43,6 +43,7 @@
"alert.rate_limited.title": "Abiadura mugatua", "alert.rate_limited.title": "Abiadura mugatua",
"alert.unexpected.message": "Ustekabeko errore bat gertatu da.", "alert.unexpected.message": "Ustekabeko errore bat gertatu da.",
"alert.unexpected.title": "Ene!", "alert.unexpected.title": "Ene!",
"announcement.announcement": "Announcement",
"autosuggest_hashtag.per_week": "{count} asteko", "autosuggest_hashtag.per_week": "{count} asteko",
"boost_modal.combo": "{combo} sakatu dezakezu hurrengoan hau saltatzeko", "boost_modal.combo": "{combo} sakatu dezakezu hurrengoan hau saltatzeko",
"bundle_column_error.body": "Zerbait okerra gertatu da osagai hau kargatzean.", "bundle_column_error.body": "Zerbait okerra gertatu da osagai hau kargatzean.",
@ -84,8 +85,8 @@
"compose_form.poll.duration": "Inkestaren iraupena", "compose_form.poll.duration": "Inkestaren iraupena",
"compose_form.poll.option_placeholder": "{number}. aukera", "compose_form.poll.option_placeholder": "{number}. aukera",
"compose_form.poll.remove_option": "Kendu aukera hau", "compose_form.poll.remove_option": "Kendu aukera hau",
"compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", "compose_form.poll.switch_to_multiple": "Aldatu inkesta hainbat aukera onartzeko",
"compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.poll.switch_to_single": "Aldatu inkesta aukera bakarra onartzeko",
"compose_form.publish": "Toot", "compose_form.publish": "Toot",
"compose_form.publish_loud": "{publish}!", "compose_form.publish_loud": "{publish}!",
"compose_form.sensitive.hide": "Markatu multimedia hunkigarri gisa", "compose_form.sensitive.hide": "Markatu multimedia hunkigarri gisa",

View File

@ -1,7 +1,7 @@
{ {
"account.add_or_remove_from_list": "افزودن یا برداشتن از فهرست", "account.add_or_remove_from_list": "افزودن یا برداشتن از فهرست",
"account.badges.bot": "ربات", "account.badges.bot": "ربات",
"account.badges.group": "Group", "account.badges.group": "گروه",
"account.block": "مسدودسازی @{name}", "account.block": "مسدودسازی @{name}",
"account.block_domain": "پنهان‌سازی همه چیز از سرور {domain}", "account.block_domain": "پنهان‌سازی همه چیز از سرور {domain}",
"account.blocked": "مسدود", "account.blocked": "مسدود",
@ -43,6 +43,7 @@
"alert.rate_limited.title": "محدود شده", "alert.rate_limited.title": "محدود شده",
"alert.unexpected.message": "خطایی غیرمنتظره رخ داد.", "alert.unexpected.message": "خطایی غیرمنتظره رخ داد.",
"alert.unexpected.title": "وای!", "alert.unexpected.title": "وای!",
"announcement.announcement": "Announcement",
"autosuggest_hashtag.per_week": "{count} در هفته", "autosuggest_hashtag.per_week": "{count} در هفته",
"boost_modal.combo": "دکمهٔ {combo} را بزنید تا دیگر این را نبینید", "boost_modal.combo": "دکمهٔ {combo} را بزنید تا دیگر این را نبینید",
"bundle_column_error.body": "هنگام بازکردن این بخش خطایی رخ داد.", "bundle_column_error.body": "هنگام بازکردن این بخش خطایی رخ داد.",
@ -84,8 +85,8 @@
"compose_form.poll.duration": "مدت نظرسنجی", "compose_form.poll.duration": "مدت نظرسنجی",
"compose_form.poll.option_placeholder": "گزینهٔ {number}", "compose_form.poll.option_placeholder": "گزینهٔ {number}",
"compose_form.poll.remove_option": "برداشتن این گزینه", "compose_form.poll.remove_option": "برداشتن این گزینه",
"compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", "compose_form.poll.switch_to_multiple": "تبدیل به نظرسنجی چندگزینه‌ای",
"compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.poll.switch_to_single": "تبدیل به نظرسنجی تک‌گزینه‌ای",
"compose_form.publish": "بوق", "compose_form.publish": "بوق",
"compose_form.publish_loud": "{publish}!", "compose_form.publish_loud": "{publish}!",
"compose_form.sensitive.hide": "علامت‌گذاری رسانه به عنوان حساس", "compose_form.sensitive.hide": "علامت‌گذاری رسانه به عنوان حساس",

View File

@ -43,6 +43,7 @@
"alert.rate_limited.title": "Määrää rajoitettu", "alert.rate_limited.title": "Määrää rajoitettu",
"alert.unexpected.message": "Tapahtui odottamaton virhe.", "alert.unexpected.message": "Tapahtui odottamaton virhe.",
"alert.unexpected.title": "Hups!", "alert.unexpected.title": "Hups!",
"announcement.announcement": "Announcement",
"autosuggest_hashtag.per_week": "{count} viikossa", "autosuggest_hashtag.per_week": "{count} viikossa",
"boost_modal.combo": "Ensi kerralla voit ohittaa tämän painamalla {combo}", "boost_modal.combo": "Ensi kerralla voit ohittaa tämän painamalla {combo}",
"bundle_column_error.body": "Jokin meni vikaan komponenttia ladattaessa.", "bundle_column_error.body": "Jokin meni vikaan komponenttia ladattaessa.",

View File

@ -43,6 +43,7 @@
"alert.rate_limited.title": "Débit limité", "alert.rate_limited.title": "Débit limité",
"alert.unexpected.message": "Une erreur inattendue sest produite.", "alert.unexpected.message": "Une erreur inattendue sest produite.",
"alert.unexpected.title": "Oups!", "alert.unexpected.title": "Oups!",
"announcement.announcement": "Annonce",
"autosuggest_hashtag.per_week": "{count} par semaine", "autosuggest_hashtag.per_week": "{count} par semaine",
"boost_modal.combo": "Vous pouvez appuyer sur {combo} pour passer ceci, la prochaine fois", "boost_modal.combo": "Vous pouvez appuyer sur {combo} pour passer ceci, la prochaine fois",
"bundle_column_error.body": "Une erreur sest produite lors du chargement de ce composant.", "bundle_column_error.body": "Une erreur sest produite lors du chargement de ce composant.",

View File

@ -43,6 +43,7 @@
"alert.rate_limited.title": "Rate limited", "alert.rate_limited.title": "Rate limited",
"alert.unexpected.message": "An unexpected error occurred.", "alert.unexpected.message": "An unexpected error occurred.",
"alert.unexpected.title": "Oops!", "alert.unexpected.title": "Oops!",
"announcement.announcement": "Announcement",
"autosuggest_hashtag.per_week": "{count} per week", "autosuggest_hashtag.per_week": "{count} per week",
"boost_modal.combo": "You can press {combo} to skip this next time", "boost_modal.combo": "You can press {combo} to skip this next time",
"bundle_column_error.body": "Something went wrong while loading this component.", "bundle_column_error.body": "Something went wrong while loading this component.",

View File

@ -4,32 +4,32 @@
"account.badges.group": "Grupo", "account.badges.group": "Grupo",
"account.block": "Bloquear @{name}", "account.block": "Bloquear @{name}",
"account.block_domain": "Agochar todo de {domain}", "account.block_domain": "Agochar todo de {domain}",
"account.blocked": "Bloqueado", "account.blocked": "Bloqueada",
"account.cancel_follow_request": "Desbotar solicitude de seguimento", "account.cancel_follow_request": "Desbotar solicitude de seguimento",
"account.direct": "Mensaxe directa @{name}", "account.direct": "Mensaxe directa @{name}",
"account.domain_blocked": "Dominio agochado", "account.domain_blocked": "Dominio agochado",
"account.edit_profile": "Editar perfil", "account.edit_profile": "Editar perfil",
"account.endorse": "Amosar no perfil", "account.endorse": "Amosar no perfil",
"account.follow": "Seguir", "account.follow": "Seguir",
"account.followers": "Seguidores", "account.followers": "Seguidoras",
"account.followers.empty": "Aínda ninguén segue este usuario.", "account.followers.empty": "Aínda ninguén segue esta usuaria.",
"account.follows": "Seguindo", "account.follows": "Seguindo",
"account.follows.empty": "Este usuario aínda non segue a ninguén.", "account.follows.empty": "Esta usuaria aínda non segue a ninguén.",
"account.follows_you": "Séguete", "account.follows_you": "Séguete",
"account.hide_reblogs": "Agochar compartidos de @{name}", "account.hide_reblogs": "Agochar repeticións de @{name}",
"account.last_status": "Última actividade", "account.last_status": "Última actividade",
"account.link_verified_on": "A propiedade desta ligazón foi verificada o {date}", "account.link_verified_on": "A propiedade desta ligazón foi verificada o {date}",
"account.locked_info": "Esta é unha conta privada. O dono revisa de xeito manual quen pode seguilo.", "account.locked_info": "Esta é unha conta privada. A propietaria revisa de xeito manual quen pode seguila.",
"account.media": "Multimedia", "account.media": "Multimedia",
"account.mention": "Mencionar @{name}", "account.mention": "Mencionar @{name}",
"account.moved_to": "{name} mudouse a:", "account.moved_to": "{name} mudouse a:",
"account.mute": "Silenciar @{name}", "account.mute": "Acalar @{name}",
"account.mute_notifications": "Silenciar notificacións de @{name}", "account.mute_notifications": "Acalar as notificacións de @{name}",
"account.muted": "Silenciado", "account.muted": "Acalada",
"account.never_active": "Nunca", "account.never_active": "Nunca",
"account.posts": "Toots", "account.posts": "Toots",
"account.posts_with_replies": "Toots e respostas", "account.posts_with_replies": "Toots e respostas",
"account.report": "Denunciar @{name}", "account.report": "Informar sobre @{name}",
"account.requested": "Agardando aprovación. Preme para desbotar a solicitude de seguimento", "account.requested": "Agardando aprovación. Preme para desbotar a solicitude de seguimento",
"account.share": "Compartir o perfil de @{name}", "account.share": "Compartir o perfil de @{name}",
"account.show_reblogs": "Amosar compartidos de @{name}", "account.show_reblogs": "Amosar compartidos de @{name}",
@ -43,15 +43,16 @@
"alert.rate_limited.title": "Límite de intentos", "alert.rate_limited.title": "Límite de intentos",
"alert.unexpected.message": "Ocorreu un erro non agardado.", "alert.unexpected.message": "Ocorreu un erro non agardado.",
"alert.unexpected.title": "Vaites!", "alert.unexpected.title": "Vaites!",
"announcement.announcement": "Anuncio",
"autosuggest_hashtag.per_week": "{count} por semana", "autosuggest_hashtag.per_week": "{count} por semana",
"boost_modal.combo": "Preme {combo} para ignorar isto na seguinte vez", "boost_modal.combo": "Preme {combo} para ignorar isto na seguinte vez",
"bundle_column_error.body": "Ocorreu un erro ó cargar este compoñente.", "bundle_column_error.body": "Ocorreu un erro ó cargar este compoñente.",
"bundle_column_error.retry": "Téntao de novo", "bundle_column_error.retry": "Téntao de novo",
"bundle_column_error.title": "Erro na rede", "bundle_column_error.title": "Fallo na rede",
"bundle_modal_error.close": "Pechar", "bundle_modal_error.close": "Pechar",
"bundle_modal_error.message": "Ocorreu un erro ó cargar este compoñente.", "bundle_modal_error.message": "Ocorreu un erro ó cargar este compoñente.",
"bundle_modal_error.retry": "Téntao de novo", "bundle_modal_error.retry": "Téntao de novo",
"column.blocks": "Usuarios bloqueados", "column.blocks": "Usuarias bloqueadas",
"column.bookmarks": "Marcadores", "column.bookmarks": "Marcadores",
"column.community": "Cronoloxía local", "column.community": "Cronoloxía local",
"column.direct": "Mensaxes directas", "column.direct": "Mensaxes directas",
@ -59,9 +60,9 @@
"column.domain_blocks": "Dominios agochados", "column.domain_blocks": "Dominios agochados",
"column.favourites": "Favoritos", "column.favourites": "Favoritos",
"column.follow_requests": "Peticións de seguimento", "column.follow_requests": "Peticións de seguimento",
"column.home": "Páxina inicial", "column.home": "Inicio",
"column.lists": "Listaxes", "column.lists": "Listaxes",
"column.mutes": "Usuarios silenciados", "column.mutes": "Usuarias acaladas",
"column.notifications": "Notificacións", "column.notifications": "Notificacións",
"column.pins": "Toots fixados", "column.pins": "Toots fixados",
"column.public": "Cronoloxía federada", "column.public": "Cronoloxía federada",
@ -74,7 +75,7 @@
"column_header.unpin": "Desafixar", "column_header.unpin": "Desafixar",
"column_subheading.settings": "Axustes", "column_subheading.settings": "Axustes",
"community.column_settings.media_only": "Só multimedia", "community.column_settings.media_only": "Só multimedia",
"compose_form.direct_message_warning": "Este toot só será enviado ós usuarios mencionados.", "compose_form.direct_message_warning": "Este toot só será enviado ás usuarias mencionadas.",
"compose_form.direct_message_warning_learn_more": "Coñecer máis", "compose_form.direct_message_warning_learn_more": "Coñecer máis",
"compose_form.hashtag_warning": "Este toot non se amosará baixo cancelos (hashtags) porque non é público. Só os toots públicos poden ser procurados por cancelos.", "compose_form.hashtag_warning": "Este toot non se amosará baixo cancelos (hashtags) porque non é público. Só os toots públicos poden ser procurados por cancelos.",
"compose_form.lock_disclaimer": "A túa conta non está {locked}. Todos poden seguirche para ollar os teus toots só para seguidores.", "compose_form.lock_disclaimer": "A túa conta non está {locked}. Todos poden seguirche para ollar os teus toots só para seguidores.",
@ -86,7 +87,7 @@
"compose_form.poll.remove_option": "Eliminar esta opción", "compose_form.poll.remove_option": "Eliminar esta opción",
"compose_form.poll.switch_to_multiple": "Mudar a enquisa para permitir múltiples escollas", "compose_form.poll.switch_to_multiple": "Mudar a enquisa para permitir múltiples escollas",
"compose_form.poll.switch_to_single": "Mudar a enquisa para permitir unha soa escolla", "compose_form.poll.switch_to_single": "Mudar a enquisa para permitir unha soa escolla",
"compose_form.publish": "Toot", "compose_form.publish": "Tootear",
"compose_form.publish_loud": "{publish}!", "compose_form.publish_loud": "{publish}!",
"compose_form.sensitive.hide": "Marcar coma contido multimedia sensíbel", "compose_form.sensitive.hide": "Marcar coma contido multimedia sensíbel",
"compose_form.sensitive.marked": "Contido multimedia marcado coma sensíbel", "compose_form.sensitive.marked": "Contido multimedia marcado coma sensíbel",
@ -111,7 +112,7 @@
"confirmations.mute.message": "Tes a certeza de querer silenciar a {name}?", "confirmations.mute.message": "Tes a certeza de querer silenciar a {name}?",
"confirmations.redraft.confirm": "Eliminar e reescribir", "confirmations.redraft.confirm": "Eliminar e reescribir",
"confirmations.redraft.message": "Tes a certeza de querer eliminar este estado e reescribilo? Perderás os compartidos e favoritos, e as respostas á publicación orixinal ficarán orfas.", "confirmations.redraft.message": "Tes a certeza de querer eliminar este estado e reescribilo? Perderás os compartidos e favoritos, e as respostas á publicación orixinal ficarán orfas.",
"confirmations.reply.confirm": "Respostar", "confirmations.reply.confirm": "Responder",
"confirmations.reply.message": "Respostar agora sobrescribirá a mensaxe que estás a compor. Tes a certeza de que queres continuar?", "confirmations.reply.message": "Respostar agora sobrescribirá a mensaxe que estás a compor. Tes a certeza de que queres continuar?",
"confirmations.unfollow.confirm": "Deixar de seguir", "confirmations.unfollow.confirm": "Deixar de seguir",
"confirmations.unfollow.message": "Desexas deixar de seguir a {name}?", "confirmations.unfollow.message": "Desexas deixar de seguir a {name}?",
@ -141,7 +142,7 @@
"emoji_button.travel": "Viaxes e lugares", "emoji_button.travel": "Viaxes e lugares",
"empty_column.account_timeline": "Non hai toots aquí!", "empty_column.account_timeline": "Non hai toots aquí!",
"empty_column.account_unavailable": "Perfil non dispoñíbel", "empty_column.account_unavailable": "Perfil non dispoñíbel",
"empty_column.blocks": "Aínda non bloqueaches a ningún usuario.", "empty_column.blocks": "Aínda non bloqueaches a ningún usuaria.",
"empty_column.bookmarked_statuses": "Aínda non marcaches ningún toot. Cando o fagas, amosaranse aquí.", "empty_column.bookmarked_statuses": "Aínda non marcaches ningún toot. Cando o fagas, amosaranse aquí.",
"empty_column.community": "A cronoloxía local está baleira. Escribe algo de xeito público para espallalo!", "empty_column.community": "A cronoloxía local está baleira. Escribe algo de xeito público para espallalo!",
"empty_column.direct": "Aínda non tes mensaxes directas. Cando envíes ou recibas unha, amosarase aquí.", "empty_column.direct": "Aínda non tes mensaxes directas. Cando envíes ou recibas unha, amosarase aquí.",
@ -150,13 +151,13 @@
"empty_column.favourites": "A ninguén lle gostou este toot polo momento. Cando a alguén lle goste, aparecerá aquí.", "empty_column.favourites": "A ninguén lle gostou este toot polo momento. Cando a alguén lle goste, aparecerá aquí.",
"empty_column.follow_requests": "Non tes peticións de seguimento. Cando recibas unha, amosarase aquí.", "empty_column.follow_requests": "Non tes peticións de seguimento. Cando recibas unha, amosarase aquí.",
"empty_column.hashtag": "Aínda non hai nada con este cancelo.", "empty_column.hashtag": "Aínda non hai nada con este cancelo.",
"empty_column.home": "A túa cronoloxía inicial está baleira! Visita {public} ou emprega a procura para atopar outros usuarios.", "empty_column.home": "A túa cronoloxía inicial está baleira! Visita {public} ou emprega a procura para atopar outras usuarias.",
"empty_column.home.public_timeline": "a cronoloxía pública", "empty_column.home.public_timeline": "a cronoloxía pública",
"empty_column.list": "Aínda non hai nada nesta listaxe. Cando os usuarios incluídas na listaxe publiquen mensaxes, amosaranse aquí.", "empty_column.list": "Aínda non hai nada en esta lista. Cando as usuarias incluídas na lista publiquen mensaxes, aparecerán aquí.",
"empty_column.lists": "Aínda non tes listaxes. Cando crees unha, amosarase aquí.", "empty_column.lists": "Aínda non tes listaxes. Cando crees unha, amosarase aquí.",
"empty_column.mutes": "Aínda non silenciaches a ningún usuario.", "empty_column.mutes": "Aínda non silenciaches a ningúnha usuaria.",
"empty_column.notifications": "Aínda non tes notificacións. Interactúa con outros para comezar unha conversa.", "empty_column.notifications": "Aínda non tes notificacións. Interactúa con outros para comezar unha conversa.",
"empty_column.public": "Nada por aquí! Escribe algo de xeito público, ou sigue de xeito manual usuarios doutros servidores para ir enchéndoo", "empty_column.public": "Nada por aquí! Escribe algo de xeito público, ou segue de xeito manual usuarias doutros servidores para ir enchéndoo",
"error.unexpected_crash.explanation": "Debido a un erro no noso código ou a unha compatilidade co teu navegador, esta páxina non pode ser amosada correctamente.", "error.unexpected_crash.explanation": "Debido a un erro no noso código ou a unha compatilidade co teu navegador, esta páxina non pode ser amosada correctamente.",
"error.unexpected_crash.next_steps": "Tenta actualizar a páxina. Se esto non axuda podes tamén empregar o Mastodon noutro navegador ou aplicación nativa.", "error.unexpected_crash.next_steps": "Tenta actualizar a páxina. Se esto non axuda podes tamén empregar o Mastodon noutro navegador ou aplicación nativa.",
"errors.unexpected_crash.copy_stacktrace": "Copiar trazas (stacktrace) ó portapapeis", "errors.unexpected_crash.copy_stacktrace": "Copiar trazas (stacktrace) ó portapapeis",
@ -196,16 +197,16 @@
"introduction.interactions.action": "Rematar titorial!", "introduction.interactions.action": "Rematar titorial!",
"introduction.interactions.favourite.headline": "Favorito", "introduction.interactions.favourite.headline": "Favorito",
"introduction.interactions.favourite.text": "Podes gardar un toot para depois e facer saber ó autor que che gostou marcandoo coma favorito.", "introduction.interactions.favourite.text": "Podes gardar un toot para depois e facer saber ó autor que che gostou marcandoo coma favorito.",
"introduction.interactions.reblog.headline": "Compartir na cronoloxía", "introduction.interactions.reblog.headline": "Promover",
"introduction.interactions.reblog.text": "Podes compartir os toots doutras persoas cos teus seguidores.", "introduction.interactions.reblog.text": "Podes compartir os toots doutras persoas coas túas seguidoras.",
"introduction.interactions.reply.headline": "Respostar", "introduction.interactions.reply.headline": "Respostar",
"introduction.interactions.reply.text": "Podes respostar ós toots doutras persoas e ós teus propios, así ficarán encadeados nunha conversa.", "introduction.interactions.reply.text": "Podes respostar ós toots doutras persoas e ós teus propios, así ficarán encadeados nunha conversa.",
"introduction.welcome.action": "Imos!", "introduction.welcome.action": "Imos!",
"introduction.welcome.headline": "Primeiros pasos", "introduction.welcome.headline": "Primeiros pasos",
"introduction.welcome.text": "Benvido ó fediverso! Nun intre poderás difundir mensaxes e falar coas túas amizades nun grande número de servidores. Mais este servidor, {domain}, é especial—hospeda o teu perfil, por iso lémbrate do seu nome.", "introduction.welcome.text": "Benvido ó fediverso! Nun intre poderás difundir mensaxes e falar coas túas amizades nun grande número de servidores. Mais este servidor, {domain}, é especial—hospeda o teu perfil, por iso lémbrate do seu nome.",
"keyboard_shortcuts.back": "para voltar atrás", "keyboard_shortcuts.back": "para voltar atrás",
"keyboard_shortcuts.blocked": "para abrir a listaxe de usuarios bloqueados", "keyboard_shortcuts.blocked": "abrir lista de usuarias bloqueadas",
"keyboard_shortcuts.boost": "para compartir na cronoloxía", "keyboard_shortcuts.boost": "promover",
"keyboard_shortcuts.column": "para destacar un estado nunha das columnas", "keyboard_shortcuts.column": "para destacar un estado nunha das columnas",
"keyboard_shortcuts.compose": "para destacar a área de escritura", "keyboard_shortcuts.compose": "para destacar a área de escritura",
"keyboard_shortcuts.description": "Descrición", "keyboard_shortcuts.description": "Descrición",
@ -221,7 +222,7 @@
"keyboard_shortcuts.legend": "para amosar esta lenda", "keyboard_shortcuts.legend": "para amosar esta lenda",
"keyboard_shortcuts.local": "para abrir a cronoloxía local", "keyboard_shortcuts.local": "para abrir a cronoloxía local",
"keyboard_shortcuts.mention": "para mencionar ó autor", "keyboard_shortcuts.mention": "para mencionar ó autor",
"keyboard_shortcuts.muted": "para abrir a listaxe dos usuarios silenciados", "keyboard_shortcuts.muted": "abrir lista de usuarias acaladas",
"keyboard_shortcuts.my_profile": "para abrir o teu perfil", "keyboard_shortcuts.my_profile": "para abrir o teu perfil",
"keyboard_shortcuts.notifications": "para abrir a columna das notificacións", "keyboard_shortcuts.notifications": "para abrir a columna das notificacións",
"keyboard_shortcuts.open_media": "para abrir o contido multimedia", "keyboard_shortcuts.open_media": "para abrir o contido multimedia",
@ -254,9 +255,9 @@
"media_gallery.toggle_visible": "Trocar visibilidade", "media_gallery.toggle_visible": "Trocar visibilidade",
"missing_indicator.label": "Non atopado", "missing_indicator.label": "Non atopado",
"missing_indicator.sublabel": "Este recurso non foi atopado", "missing_indicator.sublabel": "Este recurso non foi atopado",
"mute_modal.hide_notifications": "Agochar notificacións deste usuario?", "mute_modal.hide_notifications": "Agochar notificacións desta usuaria?",
"navigation_bar.apps": "Aplicacións móbiles", "navigation_bar.apps": "Aplicacións móbiles",
"navigation_bar.blocks": "Usuarios bloqueados", "navigation_bar.blocks": "Usuarias bloqueadas",
"navigation_bar.bookmarks": "Marcadores", "navigation_bar.bookmarks": "Marcadores",
"navigation_bar.community_timeline": "Cronoloxía local", "navigation_bar.community_timeline": "Cronoloxía local",
"navigation_bar.compose": "Escribir un novo toot", "navigation_bar.compose": "Escribir un novo toot",
@ -272,7 +273,7 @@
"navigation_bar.keyboard_shortcuts": "Atallos do teclado", "navigation_bar.keyboard_shortcuts": "Atallos do teclado",
"navigation_bar.lists": "Listaxes", "navigation_bar.lists": "Listaxes",
"navigation_bar.logout": "Pechar sesión", "navigation_bar.logout": "Pechar sesión",
"navigation_bar.mutes": "Usuarios silenciados", "navigation_bar.mutes": "Usuarias silenciadas",
"navigation_bar.personal": "Persoal", "navigation_bar.personal": "Persoal",
"navigation_bar.pins": "Toots fixados", "navigation_bar.pins": "Toots fixados",
"navigation_bar.preferences": "Preferencias", "navigation_bar.preferences": "Preferencias",
@ -284,7 +285,7 @@
"notification.mention": "{name} mencionoute", "notification.mention": "{name} mencionoute",
"notification.own_poll": "A túa enquisa rematou", "notification.own_poll": "A túa enquisa rematou",
"notification.poll": "Unha enquisa na que votaches rematou", "notification.poll": "Unha enquisa na que votaches rematou",
"notification.reblog": "{name} compartiu o teu estado", "notification.reblog": "{name} promoveu o teu estado",
"notifications.clear": "Limpar notificacións", "notifications.clear": "Limpar notificacións",
"notifications.clear_confirmation": "Tes a certeza de querer limpar de xeito permanente todas as túas notificacións?", "notifications.clear_confirmation": "Tes a certeza de querer limpar de xeito permanente todas as túas notificacións?",
"notifications.column_settings.alert": "Notificacións de escritorio", "notifications.column_settings.alert": "Notificacións de escritorio",
@ -297,7 +298,7 @@
"notifications.column_settings.mention": "Mencións:", "notifications.column_settings.mention": "Mencións:",
"notifications.column_settings.poll": "Resultados da enquisa:", "notifications.column_settings.poll": "Resultados da enquisa:",
"notifications.column_settings.push": "Notificacións emerxentes", "notifications.column_settings.push": "Notificacións emerxentes",
"notifications.column_settings.reblog": "Compartidos:", "notifications.column_settings.reblog": "Promocións:",
"notifications.column_settings.show": "Amosar en columna", "notifications.column_settings.show": "Amosar en columna",
"notifications.column_settings.sound": "Reproducir son", "notifications.column_settings.sound": "Reproducir son",
"notifications.filter.all": "Todo", "notifications.filter.all": "Todo",
@ -316,7 +317,7 @@
"poll_button.add_poll": "Engadir unha enquisa", "poll_button.add_poll": "Engadir unha enquisa",
"poll_button.remove_poll": "Eliminar enquisa", "poll_button.remove_poll": "Eliminar enquisa",
"privacy.change": "Axustar privacidade", "privacy.change": "Axustar privacidade",
"privacy.direct.long": "Só para os usuarios mencionados", "privacy.direct.long": "Só para as usuarias mencionadas",
"privacy.direct.short": "Directo", "privacy.direct.short": "Directo",
"privacy.private.long": "Só para os seguidores", "privacy.private.long": "Só para os seguidores",
"privacy.private.short": "Só seguidores", "privacy.private.short": "Só seguidores",
@ -341,11 +342,11 @@
"report.target": "Denunciar a {target}", "report.target": "Denunciar a {target}",
"search.placeholder": "Procurar", "search.placeholder": "Procurar",
"search_popout.search_format": "Formato de procura avanzada", "search_popout.search_format": "Formato de procura avanzada",
"search_popout.tips.full_text": "Texto sinxelo que devolve estados que ti escribiches, compartiches, marcaches favorito, ou foches mencionado, así como nomes de usuario coincidentes, nomes públicos e cancelos.", "search_popout.tips.full_text": "Texto simple devolve estados que ti escribiches, promoviches, marcaches favoritos, ou foches mencionada, así como nomes de usuaria coincidentes, nomes públicos e etiquetas.",
"search_popout.tips.hashtag": "cancelo", "search_popout.tips.hashtag": "cancelo",
"search_popout.tips.status": "estado", "search_popout.tips.status": "estado",
"search_popout.tips.text": "Texto sinxelo que devolve coincidencias con nomes públicos, nomes de usuario e cancelos", "search_popout.tips.text": "Texto simple devolve coincidencias con nomes públicos, nomes de usuaria e etiquetas",
"search_popout.tips.user": "usuario", "search_popout.tips.user": "usuaria",
"search_results.accounts": "Persoas", "search_results.accounts": "Persoas",
"search_results.hashtags": "Cancelos", "search_results.hashtags": "Cancelos",
"search_results.statuses": "Toots", "search_results.statuses": "Toots",
@ -356,7 +357,7 @@
"status.block": "Bloquear @{name}", "status.block": "Bloquear @{name}",
"status.bookmark": "Marcar", "status.bookmark": "Marcar",
"status.cancel_reblog_private": "Desfacer compartido", "status.cancel_reblog_private": "Desfacer compartido",
"status.cannot_reblog": "Esta publicación non pode ser compartida", "status.cannot_reblog": "Esta publicación non pode ser promovida",
"status.copy": "Copiar ligazón ó estado", "status.copy": "Copiar ligazón ó estado",
"status.delete": "Eliminar", "status.delete": "Eliminar",
"status.detailed_status": "Vista detallada da conversa", "status.detailed_status": "Vista detallada da conversa",
@ -374,10 +375,10 @@
"status.pin": "Fixar no perfil", "status.pin": "Fixar no perfil",
"status.pinned": "Toot fixado", "status.pinned": "Toot fixado",
"status.read_more": "Ler máis", "status.read_more": "Ler máis",
"status.reblog": "Compartir", "status.reblog": "Promover",
"status.reblog_private": "Compartir á audiencia orixinal", "status.reblog_private": "Compartir á audiencia orixinal",
"status.reblogged_by": "{name} compartiu", "status.reblogged_by": "{name} promoveu",
"status.reblogs.empty": "Aínda ninguén compartiu este toot. Cando alguén o faga, amosarase aquí.", "status.reblogs.empty": "Aínda ninguén promoveu este toot. Cando alguén o faga, amosarase aquí.",
"status.redraft": "Eliminar e reescribir", "status.redraft": "Eliminar e reescribir",
"status.remove_bookmark": "Eliminar marcador", "status.remove_bookmark": "Eliminar marcador",
"status.reply": "Respostar", "status.reply": "Respostar",

View File

@ -43,6 +43,7 @@
"alert.rate_limited.title": "Rate limited", "alert.rate_limited.title": "Rate limited",
"alert.unexpected.message": "אירעה שגיאה בלתי צפויה.", "alert.unexpected.message": "אירעה שגיאה בלתי צפויה.",
"alert.unexpected.title": "אופס!", "alert.unexpected.title": "אופס!",
"announcement.announcement": "Announcement",
"autosuggest_hashtag.per_week": "{count} per week", "autosuggest_hashtag.per_week": "{count} per week",
"boost_modal.combo": "ניתן להקיש {combo} כדי לדלג בפעם הבאה", "boost_modal.combo": "ניתן להקיש {combo} כדי לדלג בפעם הבאה",
"bundle_column_error.body": "משהו השתבש בעת הצגת הרכיב הזה.", "bundle_column_error.body": "משהו השתבש בעת הצגת הרכיב הזה.",

View File

@ -43,6 +43,7 @@
"alert.rate_limited.title": "सीमित दर", "alert.rate_limited.title": "सीमित दर",
"alert.unexpected.message": "एक अप्रत्याशित त्रुटि हुई है!", "alert.unexpected.message": "एक अप्रत्याशित त्रुटि हुई है!",
"alert.unexpected.title": "उफ़!", "alert.unexpected.title": "उफ़!",
"announcement.announcement": "Announcement",
"autosuggest_hashtag.per_week": "{count} हर सप्ताह", "autosuggest_hashtag.per_week": "{count} हर सप्ताह",
"boost_modal.combo": "अगली बार स्किप करने के लिए आप {combo} दबा सकते है", "boost_modal.combo": "अगली बार स्किप करने के लिए आप {combo} दबा सकते है",
"bundle_column_error.body": "इस कॉम्पोनेन्ट को लोड करते वक्त कुछ गलत हो गया", "bundle_column_error.body": "इस कॉम्पोनेन्ट को लोड करते वक्त कुछ गलत हो गया",

View File

@ -43,6 +43,7 @@
"alert.rate_limited.title": "Rate limited", "alert.rate_limited.title": "Rate limited",
"alert.unexpected.message": "An unexpected error occurred.", "alert.unexpected.message": "An unexpected error occurred.",
"alert.unexpected.title": "Oops!", "alert.unexpected.title": "Oops!",
"announcement.announcement": "Announcement",
"autosuggest_hashtag.per_week": "{count} per week", "autosuggest_hashtag.per_week": "{count} per week",
"boost_modal.combo": "Možeš pritisnuti {combo} kako bi ovo preskočio sljedeći put", "boost_modal.combo": "Možeš pritisnuti {combo} kako bi ovo preskočio sljedeći put",
"bundle_column_error.body": "Something went wrong while loading this component.", "bundle_column_error.body": "Something went wrong while loading this component.",

View File

@ -1,7 +1,7 @@
{ {
"account.add_or_remove_from_list": "Hozzáadás vagy eltávolítás a listáról", "account.add_or_remove_from_list": "Hozzáadás vagy eltávolítás a listáról",
"account.badges.bot": "Bot", "account.badges.bot": "Bot",
"account.badges.group": "Group", "account.badges.group": "Csoport",
"account.block": "@{name} letiltása", "account.block": "@{name} letiltása",
"account.block_domain": "Minden elrejtése innen: {domain}", "account.block_domain": "Minden elrejtése innen: {domain}",
"account.blocked": "Letiltva", "account.blocked": "Letiltva",
@ -43,6 +43,7 @@
"alert.rate_limited.title": "Forgalomkorlátozás", "alert.rate_limited.title": "Forgalomkorlátozás",
"alert.unexpected.message": "Váratlan hiba történt.", "alert.unexpected.message": "Váratlan hiba történt.",
"alert.unexpected.title": "Hoppá!", "alert.unexpected.title": "Hoppá!",
"announcement.announcement": "Announcement",
"autosuggest_hashtag.per_week": "{count}/hét", "autosuggest_hashtag.per_week": "{count}/hét",
"boost_modal.combo": "Hogy átugord ezt következő alkalommal, használd {combo}", "boost_modal.combo": "Hogy átugord ezt következő alkalommal, használd {combo}",
"bundle_column_error.body": "Hiba történt a komponens betöltése közben.", "bundle_column_error.body": "Hiba történt a komponens betöltése közben.",
@ -84,8 +85,8 @@
"compose_form.poll.duration": "Szavazás időtartama", "compose_form.poll.duration": "Szavazás időtartama",
"compose_form.poll.option_placeholder": "{number}. lehetőség", "compose_form.poll.option_placeholder": "{number}. lehetőség",
"compose_form.poll.remove_option": "Lehetőség törlése", "compose_form.poll.remove_option": "Lehetőség törlése",
"compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", "compose_form.poll.switch_to_multiple": "Szavazás megváltoztatása több választásosra",
"compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.poll.switch_to_single": "Szavazás megváltoztatása egyetlen választásosra",
"compose_form.publish": "Tülk", "compose_form.publish": "Tülk",
"compose_form.publish_loud": "{publish}!", "compose_form.publish_loud": "{publish}!",
"compose_form.sensitive.hide": "Média megjelölése szenzitívként", "compose_form.sensitive.hide": "Média megjelölése szenzitívként",

View File

@ -1,7 +1,7 @@
{ {
"account.add_or_remove_from_list": "Աւելացնել կամ հեռացնել ցանկերից", "account.add_or_remove_from_list": "Աւելացնել կամ հեռացնել ցանկերից",
"account.badges.bot": "Բոտ", "account.badges.bot": "Բոտ",
"account.badges.group": "Group", "account.badges.group": "Խումբ",
"account.block": "Արգելափակել @{name}֊ին", "account.block": "Արգելափակել @{name}֊ին",
"account.block_domain": "Թաքցնել ամենը հետեւյալ տիրույթից՝ {domain}", "account.block_domain": "Թաքցնել ամենը հետեւյալ տիրույթից՝ {domain}",
"account.blocked": "Արգելափակուած է", "account.blocked": "Արգելափակուած է",
@ -27,7 +27,7 @@
"account.mute_notifications": "Անջատել ծանուցումները @{name}֊ից", "account.mute_notifications": "Անջատել ծանուցումները @{name}֊ից",
"account.muted": "Լռեցուած", "account.muted": "Լռեցուած",
"account.never_active": "Երբեք", "account.never_active": "Երբեք",
"account.posts": "Գրառումներ", "account.posts": "Թութ",
"account.posts_with_replies": "Toots with replies", "account.posts_with_replies": "Toots with replies",
"account.report": "Բողոքել @{name}֊ից", "account.report": "Բողոքել @{name}֊ից",
"account.requested": "Հաստատման կարիք ունի։ Սեղմիր՝ հետեւելու հայցը չեղարկելու համար։", "account.requested": "Հաստատման կարիք ունի։ Սեղմիր՝ հետեւելու հայցը չեղարկելու համար։",
@ -43,6 +43,7 @@
"alert.rate_limited.title": "Rate limited", "alert.rate_limited.title": "Rate limited",
"alert.unexpected.message": "Անսպասելի սխալ տեղի ունեցաւ։", "alert.unexpected.message": "Անսպասելի սխալ տեղի ունեցաւ։",
"alert.unexpected.title": "Վա՜յ", "alert.unexpected.title": "Վա՜յ",
"announcement.announcement": "Announcement",
"autosuggest_hashtag.per_week": "շաբաթը՝ {count}", "autosuggest_hashtag.per_week": "շաբաթը՝ {count}",
"boost_modal.combo": "Կարող ես սեղմել {combo}՝ սա հաջորդ անգամ բաց թողնելու համար", "boost_modal.combo": "Կարող ես սեղմել {combo}՝ սա հաջորդ անգամ բաց թողնելու համար",
"bundle_column_error.body": "Այս բաղադրիչը բեռնելու ընթացքում ինչ֊որ բան խափանվեց։", "bundle_column_error.body": "Այս բաղադրիչը բեռնելու ընթացքում ինչ֊որ բան խափանվեց։",
@ -401,25 +402,25 @@
"tabs_bar.notifications": "Ծանուցումներ", "tabs_bar.notifications": "Ծանուցումներ",
"tabs_bar.search": "Փնտրել", "tabs_bar.search": "Փնտրել",
"time_remaining.days": "{number, plural, one {# day} other {# days}} left", "time_remaining.days": "{number, plural, one {# day} other {# days}} left",
"time_remaining.hours": "{number, plural, one {# hour} other {# hours}} left", "time_remaining.hours": "{number, plural, one {# ժամ} other {# ժամ}} անց",
"time_remaining.minutes": "{number, plural, one {# minute} other {# minutes}} left", "time_remaining.minutes": "{number, plural, one {# րոպե} other {# րոպե}} անց",
"time_remaining.moments": "Moments remaining", "time_remaining.moments": "Moments remaining",
"time_remaining.seconds": "{number, plural, one {# second} other {# seconds}} left", "time_remaining.seconds": "{number, plural, one {# վայրկյան} other {# վայրկյան}} անց",
"trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking", "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
"trends.trending_now": "Trending now", "trends.trending_now": "Այժմ արդիական",
"ui.beforeunload": "Քո սեւագիրը կկորի, եթե լքես Մաստոդոնը։", "ui.beforeunload": "Քո սեւագիրը կկորի, եթե լքես Մաստոդոնը։",
"upload_area.title": "Քաշիր ու նետիր՝ վերբեռնելու համար", "upload_area.title": "Քաշիր ու նետիր՝ վերբեռնելու համար",
"upload_button.label": "Ավելացնել մեդիա", "upload_button.label": "Ավելացնել մեդիա",
"upload_error.limit": "File upload limit exceeded.", "upload_error.limit": "Ֆայլի վերբեռնման սահմանաչափը գերազանցված է։",
"upload_error.poll": "File upload not allowed with polls.", "upload_error.poll": "File upload not allowed with polls.",
"upload_form.audio_description": "Describe for people with hearing loss", "upload_form.audio_description": "Describe for people with hearing loss",
"upload_form.description": "Նկարագրություն ավելացրու տեսողական խնդիրներ ունեցողների համար", "upload_form.description": "Նկարագրություն ավելացրու տեսողական խնդիրներ ունեցողների համար",
"upload_form.edit": "Խմբագրել", "upload_form.edit": "Խմբագրել",
"upload_form.undo": "Հետարկել", "upload_form.undo": "Հետարկել",
"upload_form.video_description": "Describe for people with hearing loss or visual impairment", "upload_form.video_description": "Describe for people with hearing loss or visual impairment",
"upload_modal.analyzing_picture": "Analyzing picture…", "upload_modal.analyzing_picture": "Լուսանկարի վերլուծում…",
"upload_modal.apply": "Կիրառել", "upload_modal.apply": "Կիրառել",
"upload_modal.description_placeholder": "A quick brown fox jumps over the lazy dog", "upload_modal.description_placeholder": "Ճկուն շագանակագույն աղվեսը ցատկում է ծույլ շան վրայով",
"upload_modal.detect_text": "Հայտնբերել տեքստը նկարից", "upload_modal.detect_text": "Հայտնբերել տեքստը նկարից",
"upload_modal.edit_media": "Խմբագրել մեդիան", "upload_modal.edit_media": "Խմբագրել մեդիան",
"upload_modal.hint": "Click or drag the circle on the preview to choose the focal point which will always be in view on all thumbnails.", "upload_modal.hint": "Click or drag the circle on the preview to choose the focal point which will always be in view on all thumbnails.",

View File

@ -43,6 +43,7 @@
"alert.rate_limited.title": "Batasan tingkat", "alert.rate_limited.title": "Batasan tingkat",
"alert.unexpected.message": "Terjadi kesalahan yang tidak terduga.", "alert.unexpected.message": "Terjadi kesalahan yang tidak terduga.",
"alert.unexpected.title": "Oops!", "alert.unexpected.title": "Oops!",
"announcement.announcement": "Announcement",
"autosuggest_hashtag.per_week": "{count} per minggu", "autosuggest_hashtag.per_week": "{count} per minggu",
"boost_modal.combo": "Anda dapat menekan {combo} untuk melewati ini", "boost_modal.combo": "Anda dapat menekan {combo} untuk melewati ini",
"bundle_column_error.body": "Kesalahan terjadi saat memuat komponen ini.", "bundle_column_error.body": "Kesalahan terjadi saat memuat komponen ini.",

View File

@ -43,6 +43,7 @@
"alert.rate_limited.title": "Rate limited", "alert.rate_limited.title": "Rate limited",
"alert.unexpected.message": "An unexpected error occurred.", "alert.unexpected.message": "An unexpected error occurred.",
"alert.unexpected.title": "Oops!", "alert.unexpected.title": "Oops!",
"announcement.announcement": "Announcement",
"autosuggest_hashtag.per_week": "{count} per week", "autosuggest_hashtag.per_week": "{count} per week",
"boost_modal.combo": "Tu povas presar sur {combo} por omisar co en la venonta foyo", "boost_modal.combo": "Tu povas presar sur {combo} por omisar co en la venonta foyo",
"bundle_column_error.body": "Something went wrong while loading this component.", "bundle_column_error.body": "Something went wrong while loading this component.",

View File

@ -10,10 +10,10 @@
"account.domain_blocked": "Lén falið", "account.domain_blocked": "Lén falið",
"account.edit_profile": "Breyta notandasniði", "account.edit_profile": "Breyta notandasniði",
"account.endorse": "Birta á notandasniði", "account.endorse": "Birta á notandasniði",
"account.follow": "Fylgja", "account.follow": "Fylgjast með",
"account.followers": "Fylgjendur", "account.followers": "Fylgjendur",
"account.followers.empty": "Ennþá fylgist enginn með þessum notanda.", "account.followers.empty": "Ennþá fylgist enginn með þessum notanda.",
"account.follows": "Fylgir", "account.follows": "Fylgist með",
"account.follows.empty": "Þessi notandi fylgist ennþá ekki með neinum.", "account.follows.empty": "Þessi notandi fylgist ennþá ekki með neinum.",
"account.follows_you": "Fylgir þér", "account.follows_you": "Fylgir þér",
"account.hide_reblogs": "Fela endurbirtingar fyrir @{name}", "account.hide_reblogs": "Fela endurbirtingar fyrir @{name}",
@ -43,6 +43,7 @@
"alert.rate_limited.title": "Með takmörkum", "alert.rate_limited.title": "Með takmörkum",
"alert.unexpected.message": "Upp kom óvænt villa.", "alert.unexpected.message": "Upp kom óvænt villa.",
"alert.unexpected.title": "Úbbs!", "alert.unexpected.title": "Úbbs!",
"announcement.announcement": "Announcement",
"autosuggest_hashtag.per_week": "{count} á viku", "autosuggest_hashtag.per_week": "{count} á viku",
"boost_modal.combo": "Þú getur ýtt á {combo} til að sleppa þessu næst", "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.", "bundle_column_error.body": "Eitthvað fór úrskeiðis við að hlaða inn þessari einingu.",
@ -266,7 +267,7 @@
"navigation_bar.edit_profile": "Breyta notandasniði", "navigation_bar.edit_profile": "Breyta notandasniði",
"navigation_bar.favourites": "Eftirlæti", "navigation_bar.favourites": "Eftirlæti",
"navigation_bar.filters": "Þögguð orð", "navigation_bar.filters": "Þögguð orð",
"navigation_bar.follow_requests": "Fylgja beiðnum", "navigation_bar.follow_requests": "Beiðnir um að fylgjast með",
"navigation_bar.follows_and_followers": "Fylgist með og fylgjendur", "navigation_bar.follows_and_followers": "Fylgist með og fylgjendur",
"navigation_bar.info": "Um þennan vefþjón", "navigation_bar.info": "Um þennan vefþjón",
"navigation_bar.keyboard_shortcuts": "Flýtilyklar", "navigation_bar.keyboard_shortcuts": "Flýtilyklar",
@ -279,7 +280,7 @@
"navigation_bar.public_timeline": "Sameiginleg tímalína", "navigation_bar.public_timeline": "Sameiginleg tímalína",
"navigation_bar.security": "Öryggi", "navigation_bar.security": "Öryggi",
"notification.favourite": "{name} setti stöðufærslu þína í eftirlæti", "notification.favourite": "{name} setti stöðufærslu þína í eftirlæti",
"notification.follow": "{name} fylgdist með þér", "notification.follow": "{name} fylgist með þér",
"notification.follow_request": "{name} hefur beðið um að fylgjast með þér", "notification.follow_request": "{name} hefur beðið um að fylgjast með þér",
"notification.mention": "{name} minntist á þig", "notification.mention": "{name} minntist á þig",
"notification.own_poll": "Könnuninni þinni er lokið", "notification.own_poll": "Könnuninni þinni er lokið",

View File

@ -1,7 +1,7 @@
{ {
"account.add_or_remove_from_list": "Aggiungi o togli dalle liste", "account.add_or_remove_from_list": "Aggiungi o togli dalle liste",
"account.badges.bot": "Bot", "account.badges.bot": "Bot",
"account.badges.group": "Group", "account.badges.group": "Gruppo",
"account.block": "Blocca @{name}", "account.block": "Blocca @{name}",
"account.block_domain": "Nascondi tutto da {domain}", "account.block_domain": "Nascondi tutto da {domain}",
"account.blocked": "Bloccato", "account.blocked": "Bloccato",
@ -43,6 +43,7 @@
"alert.rate_limited.title": "Numero massimo di richieste superato", "alert.rate_limited.title": "Numero massimo di richieste superato",
"alert.unexpected.message": "Si è verificato un errore inatteso.", "alert.unexpected.message": "Si è verificato un errore inatteso.",
"alert.unexpected.title": "Oops!", "alert.unexpected.title": "Oops!",
"announcement.announcement": "Announcement",
"autosuggest_hashtag.per_week": "{count} per settimana", "autosuggest_hashtag.per_week": "{count} per settimana",
"boost_modal.combo": "Puoi premere {combo} per saltare questo passaggio la prossima volta", "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.", "bundle_column_error.body": "E' avvenuto un errore durante il caricamento di questo componente.",

View File

@ -43,6 +43,7 @@
"alert.rate_limited.title": "制限に達しました", "alert.rate_limited.title": "制限に達しました",
"alert.unexpected.message": "不明なエラーが発生しました。", "alert.unexpected.message": "不明なエラーが発生しました。",
"alert.unexpected.title": "エラー!", "alert.unexpected.title": "エラー!",
"announcement.announcement": "告知",
"autosuggest_hashtag.per_week": "{count} 回 / 週", "autosuggest_hashtag.per_week": "{count} 回 / 週",
"boost_modal.combo": "次からは{combo}を押せばスキップできます", "boost_modal.combo": "次からは{combo}を押せばスキップできます",
"bundle_column_error.body": "コンポーネントの読み込み中に問題が発生しました。", "bundle_column_error.body": "コンポーネントの読み込み中に問題が発生しました。",

View File

@ -43,6 +43,7 @@
"alert.rate_limited.title": "Rate limited", "alert.rate_limited.title": "Rate limited",
"alert.unexpected.message": "წარმოიშვა მოულოდნელი შეცდომა.", "alert.unexpected.message": "წარმოიშვა მოულოდნელი შეცდომა.",
"alert.unexpected.title": "უპს!", "alert.unexpected.title": "უპს!",
"announcement.announcement": "Announcement",
"autosuggest_hashtag.per_week": "კვირაში {count}", "autosuggest_hashtag.per_week": "კვირაში {count}",
"boost_modal.combo": "შეგიძლიათ დააჭიროთ {combo}-ს რათა შემდეგ ჯერზე გამოტოვოთ ეს", "boost_modal.combo": "შეგიძლიათ დააჭიროთ {combo}-ს რათა შემდეგ ჯერზე გამოტოვოთ ეს",
"bundle_column_error.body": "ამ კომპონენტის ჩატვირთვისას რაღაც აირია.", "bundle_column_error.body": "ამ კომპონენტის ჩატვირთვისას რაღაც აირია.",

View File

@ -1,15 +1,15 @@
{ {
"account.add_or_remove_from_list": "Rnu neɣ kkes seg tebdarin", "account.add_or_remove_from_list": "Rnu neγ kkes seg tebdarin",
"account.badges.bot": "Aṛubut", "account.badges.bot": "Aṛubut",
"account.badges.group": "Group", "account.badges.group": "Agraw",
"account.block": "Seḥbes @{name}", "account.block": "Seḥbes @{name}",
"account.block_domain": "Ffer kra i d-yekkan seg {domain}", "account.block_domain": "Ffer kra i d-yekkan seg {domain}",
"account.blocked": "Yettuseḥbes", "account.blocked": "Yettuseḥbes",
"account.cancel_follow_request": "Sefsex asuter n weḍfaṛ", "account.cancel_follow_request": "Sefsex asuter n weḍfaṛ",
"account.direct": "Izen usrid i @{name}", "account.direct": "Izen usrid i @{name}",
"account.domain_blocked": "Taɣult yeffren", "account.domain_blocked": "Taγult yeffren",
"account.edit_profile": "Ẓreg amaɣnu", "account.edit_profile": "Ẓreg amaγnu",
"account.endorse": "Welleh fell-as deg umaɣnu-inek", "account.endorse": "Welleh fell-as deg umaγnu-inek",
"account.follow": "Ḍfeṛ", "account.follow": "Ḍfeṛ",
"account.followers": "Imeḍfaṛen", "account.followers": "Imeḍfaṛen",
"account.followers.empty": "Ar tura, ulac yiwen i yeṭṭafaṛen amseqdac-agi.", "account.followers.empty": "Ar tura, ulac yiwen i yeṭṭafaṛen amseqdac-agi.",
@ -18,33 +18,34 @@
"account.follows_you": "Yeṭṭafaṛ-ik", "account.follows_you": "Yeṭṭafaṛ-ik",
"account.hide_reblogs": "Ffer ayen i ibeṭṭu @{name}", "account.hide_reblogs": "Ffer ayen i ibeṭṭu @{name}",
"account.last_status": "Armud aneggaru", "account.last_status": "Armud aneggaru",
"account.link_verified_on": "Taɣara n useɣwen-a tettwasenqed de {date}", "account.link_verified_on": "Taγara n useγwen-a tettwasenqed ass n {date}",
"account.locked_info": "Amiḍan-agi uslig isekweṛ. D bab-is kan i izemren ad yeǧǧ, s ufus-is, win ara t-iḍefṛen.", "account.locked_info": "Amiḍan-agi uslig isekweṛ. D bab-is kan i izemren ad yeǧǧ, s ufus-is, win ara t-iḍefṛen.",
"account.media": "Allal n teywalt", "account.media": "Allal n teywalt",
"account.mention": "Bder-d @{name}", "account.mention": "Bder-d @{name}",
"account.moved_to": "{name} ibeddel ɣer:", "account.moved_to": "{name} ibeddel γer:",
"account.mute": "Sgugem @{name}", "account.mute": "Sgugem @{name}",
"account.mute_notifications": "Ḥbes ilɣa sɣur @{name}", "account.mute_notifications": "Susem ilγa sγur @{name}",
"account.muted": "Yettwasgugem", "account.muted": "Yettwasgugem",
"account.never_active": "Werǧin", "account.never_active": "Werǧin",
"account.posts": "Tiberraḥin", "account.posts": "Tiberraḥin",
"account.posts_with_replies": "Tibarraḥin d tririyin", "account.posts_with_replies": "Tibarraḥin d tririyin",
"account.report": "Sewɛed @{name}", "account.report": "Sewɛed @{name}",
"account.requested": "Di laɛḍil ad yettwaqbel. Ssit iwakken ad yefsex usuter n weḍfar", "account.requested": "Di laɛḍil ad yettwaqbel. Ssit iwakken ad yefsex usuter n weḍfar",
"account.share": "Bḍu amaɣnu n @{name}", "account.share": "Bḍu amaγnu n @{name}",
"account.show_reblogs": "Sken-d inebḍa n @{name}", "account.show_reblogs": "Sken-d inebḍa n @{name}",
"account.unblock": "Serreḥ i @{name}", "account.unblock": "Serreḥ i @{name}",
"account.unblock_domain": "Kkes tuffra i {domain}", "account.unblock_domain": "Kkes tuffra i {domain}",
"account.unendorse": "Ur ttwellih ara fell-as deg umaɣnu-inek", "account.unendorse": "Ur ttwellih ara fell-as deg umaγnu-inek",
"account.unfollow": "Ur ṭṭafaṛ ara", "account.unfollow": "Ur ṭṭafaṛ ara",
"account.unmute": "Kkes asgugem ɣef @{name}", "account.unmute": "Kkes asgugem γef @{name}",
"account.unmute_notifications": "Serreḥ ilɣa sɣur @{name}", "account.unmute_notifications": "Serreḥ ilγa sγur @{name}",
"alert.rate_limited.message": "Ma ulac aɣilif ɛreḍ tikelt-nniḍen mbeɛd {retry_time, time, medium}.", "alert.rate_limited.message": "Ma ulac aγilif ɛreḍ tikelt-nniḍen mbeɛd {retry_time, time, medium}.",
"alert.rate_limited.title": "Aktum s talast", "alert.rate_limited.title": "Aktum s talast",
"alert.unexpected.message": "Tella-d tuccḍa i ɣef ur nedmi ara.", "alert.unexpected.message": "Tella-d tuccḍa i ɣef ur nedmi ara.",
"alert.unexpected.title": "Ayhuh!", "alert.unexpected.title": "Ayhuh!",
"announcement.announcement": "Announcement",
"autosuggest_hashtag.per_week": "{count} i yimalas", "autosuggest_hashtag.per_week": "{count} i yimalas",
"boost_modal.combo": "Tzemreḍ ad tetekkiḍ ɣef {combo} akken ad tessurfeḍ aya tikelt-nniḍen", "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.", "bundle_column_error.body": "Tella-d kra n tuccḍa mi d-yettali ugbur-agi.",
"bundle_column_error.retry": "Ɛreḍ tikelt-nniḍen", "bundle_column_error.retry": "Ɛreḍ tikelt-nniḍen",
"bundle_column_error.title": "Tuccḍa deg uẓeṭṭa", "bundle_column_error.title": "Tuccḍa deg uẓeṭṭa",
@ -55,24 +56,24 @@
"column.bookmarks": "Ticraḍ", "column.bookmarks": "Ticraḍ",
"column.community": "Tasuddemt tadigant", "column.community": "Tasuddemt tadigant",
"column.direct": "Iznan usriden", "column.direct": "Iznan usriden",
"column.directory": "Qelleb deg yimaɣnuten", "column.directory": "Qelleb deg imaγnuten",
"column.domain_blocks": "Tiɣula yettwaffren", "column.domain_blocks": "Tiγula yettwaffren",
"column.favourites": "Ismenyifen", "column.favourites": "Ismenyifen",
"column.follow_requests": "Isuturen n teḍfeṛt", "column.follow_requests": "Isuturen n teḍfeṛt",
"column.home": "Agejdan", "column.home": "Agejdan",
"column.lists": "Tibdarin", "column.lists": "Tibdarin",
"column.mutes": "Imiḍanen yettwasgugmen", "column.mutes": "Imiḍanen yettwasgugmen",
"column.notifications": "Tilɣa", "column.notifications": "Tilγa",
"column.pins": "Tiberraḥin yettwasenṭḍen", "column.pins": "Tiberraḥin yettwasenṭḍen",
"column.public": "Tasuddemt tamatut", "column.public": "Tasuddemt tamatut",
"column_back_button.label": "Tuɣalin", "column_back_button.label": "Tuγalin",
"column_header.hide_settings": "Ffer iɣewwaṛen", "column_header.hide_settings": "Ffer iγewwaṛen",
"column_header.moveLeft_settings": "Err ajgu ɣer tama tazelmaḍt", "column_header.moveLeft_settings": "Err ajgu γer tama tazelmaḍt",
"column_header.moveRight_settings": "Err ajgu ɣer tama tayfust", "column_header.moveRight_settings": "Err ajgu γer tama tayfust",
"column_header.pin": "Senteḍ", "column_header.pin": "Senteḍ",
"column_header.show_settings": "Sken iɣewwaṛen", "column_header.show_settings": "Sken iγewwaṛen",
"column_header.unpin": "Kkes asenteḍ", "column_header.unpin": "Kkes asenteḍ",
"column_subheading.settings": "Iɣewwaṛen", "column_subheading.settings": "Iγewwaṛen",
"community.column_settings.media_only": "Allal n teywalt kan", "community.column_settings.media_only": "Allal n teywalt kan",
"compose_form.direct_message_warning": "Taberraḥt-a ad d-tettwasken kan i yimseqdacen i d-yettwabedren.", "compose_form.direct_message_warning": "Taberraḥt-a ad d-tettwasken kan i yimseqdacen i d-yettwabedren.",
"compose_form.direct_message_warning_learn_more": "Issin ugar", "compose_form.direct_message_warning_learn_more": "Issin ugar",
@ -91,39 +92,39 @@
"compose_form.sensitive.hide": "Creḍ allal n teywalt d anafri", "compose_form.sensitive.hide": "Creḍ allal n teywalt d anafri",
"compose_form.sensitive.marked": "Allal n teywalt yettwacreḍ d anafri", "compose_form.sensitive.marked": "Allal n teywalt yettwacreḍ d anafri",
"compose_form.sensitive.unmarked": "Allal n teywalt ur yettwacreḍ ara d anafri", "compose_form.sensitive.unmarked": "Allal n teywalt ur yettwacreḍ ara d anafri",
"compose_form.spoiler.marked": "Aḍris yeffer deffir n walɣu", "compose_form.spoiler.marked": "Aḍris yeffer deffir n walγu",
"compose_form.spoiler.unmarked": "Aḍris ur yettwaffer ara", "compose_form.spoiler.unmarked": "Aḍris ur yettwaffer ara",
"compose_form.spoiler_placeholder": "Aru alɣu-inek da", "compose_form.spoiler_placeholder": "Aru alγu-inek da",
"confirmation_modal.cancel": "Sefsex", "confirmation_modal.cancel": "Sefsex",
"confirmations.block.block_and_report": "Sewḥel & sewɛed", "confirmations.block.block_and_report": "Sewḥel & sewɛed",
"confirmations.block.confirm": "Sewḥel", "confirmations.block.confirm": "Sewḥel",
"confirmations.block.message": "Tebɣiḍ s tidet ad tesḥebseḍ {name}?", "confirmations.block.message": "Tebγiḍ s tidet ad tesḥebseḍ {name}?",
"confirmations.delete.confirm": "Kkes", "confirmations.delete.confirm": "Kkes",
"confirmations.delete.message": "Tebɣiḍ s tidet ad tekkseḍ tasuffeɣt-agi?", "confirmations.delete.message": "Tebγiḍ s tidet ad tekkseḍ tasuffeγt-agi?",
"confirmations.delete_list.confirm": "Kkes", "confirmations.delete_list.confirm": "Kkes",
"confirmations.delete_list.message": "Tebɣiḍ s tidet ad tekkseḍ tabdert-agi i lebda?", "confirmations.delete_list.message": "Tebγiḍ s tidet ad tekkseḍ tabdert-agi i lebda?",
"confirmations.domain_block.confirm": "Ffer taɣult meṛṛa", "confirmations.domain_block.confirm": "Ffer taγult meṛṛa",
"confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable. You will not see content from that domain in any public timelines or your notifications. Your followers from that domain will be removed.", "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable. You will not see content from that domain in any public timelines or your notifications. Your followers from that domain will be removed.",
"confirmations.logout.confirm": "Ffeɣ", "confirmations.logout.confirm": "Ffeγ",
"confirmations.logout.message": "D tidet tebɣiḍ ad teffɣeḍ?", "confirmations.logout.message": "D tidet tebγiḍ ad teffγeḍ?",
"confirmations.mute.confirm": "Sgugem", "confirmations.mute.confirm": "Sgugem",
"confirmations.mute.explanation": "Aya ad yeffer iznan-is d wid i deg d-yettwabder neɣ d-tettwabder, maca xas akka yezmer neɣ tezmer awali n yiznan-inek d uḍfaṛ-ik.", "confirmations.mute.explanation": "Aya ad yeffer iznan-is d wid i deg d-yettwabder neγ d-tettwabder, maca xas akka yezmer neγ tezmer awali n yiznan-inek d uḍfaṛ-ik.",
"confirmations.mute.message": "Tetḥeqqeḍ belli tebɣiḍ asɛuggen n {name}?", "confirmations.mute.message": "Tetḥeqqeḍ belli tebγiḍ asɛuggen n {name}?",
"confirmations.redraft.confirm": "Sfeḍ & Ɛiwed tira", "confirmations.redraft.confirm": "Sfeḍ & Ɛiwed tira",
"confirmations.redraft.message": "Tetḥeqqeḍ belli tebɣiḍ asfaḍ n waddad-agi iwakken ad s-tɛiwdeḍ tira? Ismenyifen d beḍḍuwat ad ṛuḥen, ma d tiririyin-is ad uɣalent d tigujilin.", "confirmations.redraft.message": "Tetḥeqqeḍ belli tebγiḍ asfaḍ n waddad-agi iwakken ad s-tɛiwdeḍ tira? Ismenyifen d beḍḍuwat ad ṛuḥen, ma d tiririyin-is ad uγalent d tigujilin.",
"confirmations.reply.confirm": "Err", "confirmations.reply.confirm": "Err",
"confirmations.reply.message": "Tiririt akka tura ad k-degger izen-agi i tettaruḍ. Tebɣiḍ ad tkemmleḍ?", "confirmations.reply.message": "Tiririt akka tura ad k-degger izen-agi i tettaruḍ. Tebγiḍ ad tkemmleḍ?",
"confirmations.unfollow.confirm": "Ur ḍḍafaṛ ara", "confirmations.unfollow.confirm": "Ur ḍḍafaṛ ara",
"confirmations.unfollow.message": "Tetḥeqqeḍ belli tebɣiḍ ur teḍḍafaṛeḍ ara {name}?", "confirmations.unfollow.message": "Tetḥeqqeḍ belli tebγiḍ ur teḍḍafaṛeḍ ara {name}?",
"conversation.delete": "Sfeḍ adiwenni", "conversation.delete": "Sfeḍ adiwenni",
"conversation.mark_as_read": "Creḍ yettwaɣṛa", "conversation.mark_as_read": "Creḍ yettwaγṛa",
"conversation.open": "Sken adiwenni", "conversation.open": "Sken adiwenni",
"conversation.with": "Akked {names}", "conversation.with": "Akked {names}",
"directory.federated": "Seg fedivers yettwasnen", "directory.federated": "Seg fedivers yettwasnen",
"directory.local": "Seg {domain} kan", "directory.local": "Seg {domain} kan",
"directory.new_arrivals": "Inebgawen imaynuten", "directory.new_arrivals": "Inebgawen imaynuten",
"directory.recently_active": "Yermed xas melmi kan", "directory.recently_active": "Yermed xas melmi kan",
"embed.instructions": "Ẓẓu addad-agi deg usmel-inek s wenɣal n tangalt yellan sdaw-agi.", "embed.instructions": "Ẓẓu addad-agi deg usmel-inek s wenγal n tangalt yellan sdaw-agi.",
"embed.preview": "Akka ara d-iban:", "embed.preview": "Akka ara d-iban:",
"emoji_button.activity": "Aqeddic", "emoji_button.activity": "Aqeddic",
"emoji_button.custom": "Udmawan", "emoji_button.custom": "Udmawan",
@ -132,7 +133,7 @@
"emoji_button.label": "Sekcem imuji", "emoji_button.label": "Sekcem imuji",
"emoji_button.nature": "Agama", "emoji_button.nature": "Agama",
"emoji_button.not_found": "Ulac izamulen n yiḥulfan !! (╯°□°)╯︵ ┻━┻", "emoji_button.not_found": "Ulac izamulen n yiḥulfan !! (╯°□°)╯︵ ┻━┻",
"emoji_button.objects": "Tiɣawsiwin", "emoji_button.objects": "Tiγawsiwin",
"emoji_button.people": "Medden", "emoji_button.people": "Medden",
"emoji_button.recent": "Wid yettuseqdacen s waṭas", "emoji_button.recent": "Wid yettuseqdacen s waṭas",
"emoji_button.search": "Nadi…", "emoji_button.search": "Nadi…",
@ -140,35 +141,35 @@
"emoji_button.symbols": "Izamulen", "emoji_button.symbols": "Izamulen",
"emoji_button.travel": "Imeḍqan d Yinigen", "emoji_button.travel": "Imeḍqan d Yinigen",
"empty_column.account_timeline": "Ulac tiberraḥin dagi!", "empty_column.account_timeline": "Ulac tiberraḥin dagi!",
"empty_column.account_unavailable": "Ur nufi ara amaɣnu-a", "empty_column.account_unavailable": "Ur nufi ara amaγnu-a",
"empty_column.blocks": "Ur tesḥebseḍ ula yiwen n umseqdac ar tura.", "empty_column.blocks": "Ur tesḥebseḍ ula yiwen n umseqdac ar tura.",
"empty_column.bookmarked_statuses": "Ulac tiberraḥin i terniḍ ɣer yismenyifen-ik ar tura. Ticki terniḍ yiwet, ad d-tettwasken da.", "empty_column.bookmarked_statuses": "Ulac tiberraḥin i terniḍ γer yismenyifen-ik ar tura. Ticki terniḍ yiwet, ad d-tettwasken da.",
"empty_column.community": "Tasuddemt tazayezt tadigant n yisallen d tilemt. Aru ihi kra akken ad tt-teččareḍ!", "empty_column.community": "Tasuddemt tazayezt tadigant n yisallen d tilemt. Aru ihi kra akken ad tt-teččareḍ!",
"empty_column.direct": "Ulac ɣur-k ula yiwen n yizen usrid. Ad d-yettwasken da, ticki tuzneḍ neɣ teṭṭfeḍ-d yiwen.", "empty_column.direct": "Ulac γur-k ula yiwen n yizen usrid. Ad d-yettwasken da, ticki tuzneḍ neγ teṭṭfeḍ-d yiwen.",
"empty_column.domain_blocks": "Ulac kra n taɣult yettwaffren ar tura.", "empty_column.domain_blocks": "Ulac kra n taγult yettwaffren ar tura.",
"empty_column.favourited_statuses": "Ulac ula yiwet n tberraḥt deg yismenyifen-ik ar tura. Ticki Tella-d yiwet, ad d-ban da.", "empty_column.favourited_statuses": "Ulac ula yiwet n tberraḥt deg yismenyifen-ik ar tura. Ticki Tella-d yiwet, ad d-ban da.",
"empty_column.favourites": "Ula yiwen ur yerri taberraḥt-agi deg yismenyifen-is. Melmi i d-yella waya, ad d-yettwasken da.", "empty_column.favourites": "Ula yiwen ur yerri taberraḥt-agi deg yismenyifen-is. Melmi i d-yella waya, ad d-yettwasken da.",
"empty_column.follow_requests": "Ulac ɣur-k ula yiwen n usuter n teḍfeṛt. Ticki teṭṭfeḍ-d yiwen ad d-yettwasken da.", "empty_column.follow_requests": "Ulac γur-k ula yiwen n usuter n teḍfeṛt. Ticki teṭṭfeḍ-d yiwen ad d-yettwasken da.",
"empty_column.hashtag": "Ar tura ulac kra n ugbur yesɛan assaɣ ɣer uhacṭag-agi.", "empty_column.hashtag": "Ar tura ulac kra n ugbur yesɛan assaγ γer uhacṭag-agi.",
"empty_column.home": "Tasuddemt tagejdant n yisallen d tilemt! Ẓer {public} neɣ nadi ad tafeḍ imseqdacen-nniḍen ad ten-ḍefṛeḍ.", "empty_column.home": "Tasuddemt tagejdant n yisallen d tilemt! Ẓer {public} neγ nadi ad tafeḍ imseqdacen-nniḍen ad ten-ḍefṛeḍ.",
"empty_column.home.public_timeline": "tasuddemt tazayezt n yisallen", "empty_column.home.public_timeline": "tasuddemt tazayezt n yisallen",
"empty_column.list": "Ar tura ur yelli kra deg tebdert-a. Ad d-yettwasken da ticki iɛeggalen n tebdert-a suffɣen-d kra.", "empty_column.list": "Ar tura ur yelli kra deg tebdert-a. Ad d-yettwasken da ticki iɛeggalen n tebdert-a suffγen-d kra.",
"empty_column.lists": "Ulac ɣur-k kra n tebdert yakan. Ad d-tettwasken da ticki tesluleḍ-d yiwet.", "empty_column.lists": "Ulac γur-k kra n tebdert yakan. Ad d-tettwasken da ticki tesluleḍ-d yiwet.",
"empty_column.mutes": "Ulac ɣur-k imseqdacen i yettwasgugmen.", "empty_column.mutes": "Ulac γur-k imseqdacen i yettwasgugmen.",
"empty_column.notifications": "Ulac ɣur-k tilɣa. Sedmer akked yemdanen-nniḍen akken ad tebduḍ adiwenni.", "empty_column.notifications": "Ulac γur-k tilγa. Sedmer akked yemdanen-nniḍen akken ad tebduḍ adiwenni.",
"empty_column.public": "Ulac kra da! Aru kra, neɣ ḍfeṛ imdanen i yellan deg yiqeddacen-nniḍen akken ad d-teččar tsuddemt tazayezt", "empty_column.public": "Ulac kra da! Aru kra, neγ ḍfeṛ imdanen i yellan deg yiqeddacen-nniḍen akken ad d-teččar tsuddemt tazayezt",
"error.unexpected_crash.explanation": "Due to a bug in our code or a browser compatibility issue, this page could not be displayed correctly.", "error.unexpected_crash.explanation": "Due to a bug in our code or a browser compatibility issue, this page could not be displayed correctly.",
"error.unexpected_crash.next_steps": "Smiren asebter-a, ma ur yekkis ara wugur, ẓer d akken tzemreḍ ad tesqedceḍ Mastudun deg yiminig-nniḍen neɣ deg usnas anaṣli.", "error.unexpected_crash.next_steps": "Smiren asebter-a, ma ur yekkis ara wugur, ẓer d akken tzemreḍ ad tesqedceḍ Masṭudun deg yiminig-nniḍen neγ deg usnas anaṣli.",
"errors.unexpected_crash.copy_stacktrace": "Copy stacktrace to clipboard", "errors.unexpected_crash.copy_stacktrace": "Copy stacktrace to clipboard",
"errors.unexpected_crash.report_issue": "Mmel ugur", "errors.unexpected_crash.report_issue": "Mmel ugur",
"follow_request.authorize": "Ssireg", "follow_request.authorize": "Ssireg",
"follow_request.reject": "Agi", "follow_request.reject": "Agi",
"getting_started.developers": "Ineflayen", "getting_started.developers": "Ineflayen",
"getting_started.directory": "Imaɣnuten", "getting_started.directory": "Imaγnuten",
"getting_started.documentation": "Amnir", "getting_started.documentation": "Amnir",
"getting_started.heading": "Bdu", "getting_started.heading": "Bdu",
"getting_started.invite": "Snebgi-d imdanen", "getting_started.invite": "Snebgi-d imdanen",
"getting_started.open_source_notice": "Mastudun d aseɣzan s uɣbalu yeldin. Tzemreḍ ad tɛiwneḍ neɣ ad temmleḍ uguren seg GitHub {github}.", "getting_started.open_source_notice": "Mastudun d aseγzan s uγbalu yeldin. Tzemreḍ ad tɛiwneḍ neγ ad temmleḍ uguren deg GitHub {github}.",
"getting_started.security": "Iγewwaṛen n umiḍan", "getting_started.security": "Iγewwaṛen n umiḍan",
"getting_started.terms": "Tiwetlin n useqdec", "getting_started.terms": "Tiwetlin n useqdec",
"hashtag.column_header.tag_mode.all": "d {additional}", "hashtag.column_header.tag_mode.all": "d {additional}",
@ -190,29 +191,29 @@
"introduction.federation.federated.headline": "Amatu", "introduction.federation.federated.headline": "Amatu",
"introduction.federation.federated.text": "Iznan izuyaz i d-yekkan seg yiqeddacen-nniḍen n fediverse ad banen deg tsuddemt tazayezt tamatut n yisallen.", "introduction.federation.federated.text": "Iznan izuyaz i d-yekkan seg yiqeddacen-nniḍen n fediverse ad banen deg tsuddemt tazayezt tamatut n yisallen.",
"introduction.federation.home.headline": "Agejdan", "introduction.federation.home.headline": "Agejdan",
"introduction.federation.home.text": "Iznan n yemdanen i teṭṭafaṛeḍ ad banen deg tsuddemt n umagger. Tzemreḍ ad tḍefṛeḍ win tebɣiḍ deg uqeddac i tebɣiḍ!", "introduction.federation.home.text": "Iznan n yemdanen i teṭṭafaṛeḍ ad banen deg tsuddemt n umagger. Tzemreḍ ad tḍefṛeḍ win tebγiḍ deg uqeddac i tebγiḍ!",
"introduction.federation.local.headline": "Adigan", "introduction.federation.local.headline": "Adigan",
"introduction.federation.local.text": "Iznan izuyaz n yemdanen i yellan deg yiwen uqeddac akked kečč ad d-banen deg tsuddemt tazayezt tadigant.", "introduction.federation.local.text": "Iznan izuyaz n yemdanen i yellan deg yiwen uqeddac akked kečč ad d-banen deg tsuddemt tazayezt tadigant.",
"introduction.interactions.action": "Fakk tameskant!", "introduction.interactions.action": "Fakk tameskant!",
"introduction.interactions.favourite.headline": "Ismenyifen", "introduction.interactions.favourite.headline": "Ismenyifen",
"introduction.interactions.favourite.text": "Tzemreḍ ad teǧǧeḍ kra n tberraḥt i ticki, daɣen ad tiniḍ i bab-is d akken taɛǧeb-ik, s tmerna-ines ɣer yismenyifen-ik.", "introduction.interactions.favourite.text": "Tzemreḍ ad teǧǧeḍ kra n tberraḥt i ticki, daγen ad tiniḍ i bab-is d akken taɛǧeb-ik, s tmerna-ines γer yismenyifen-ik.",
"introduction.interactions.reblog.headline": "Bḍu tikelt-nniḍen", "introduction.interactions.reblog.headline": "Bḍu tikelt-nniḍen",
"introduction.interactions.reblog.text": "Tzemreḍ ad tebḍuḍ akked yimeḍfaṛen-ik tiberraḥin n yemdanen-nniḍen s beṭṭu-nsent tikelt-nniḍen.", "introduction.interactions.reblog.text": "Tzemreḍ ad tebḍuḍ akked yimeḍfaṛen-ik tiberraḥin n yemdanen-nniḍen s beṭṭu-nsent tikelt-nniḍen.",
"introduction.interactions.reply.headline": "Err", "introduction.interactions.reply.headline": "Err",
"introduction.interactions.reply.text": "Tzemreḍ ad terreḍ ɣef tberraḥin-ik d tid n medden-nniḍen, d acu ara tent-id-iɛeqden ta deffir ta deg udiwenni.", "introduction.interactions.reply.text": "Tzemreḍ ad terreḍ γef tberraḥin-ik d tid n medden-nniḍen, d acu ara tent-id-iɛeqden ta deffir ta deg udiwenni.",
"introduction.welcome.action": "Bdu!", "introduction.welcome.action": "Bdu!",
"introduction.welcome.headline": "Isurifen imenza", "introduction.welcome.headline": "Isurifen imenza",
"introduction.welcome.text": "Anṣuf ɣer fediverse! Deg kra n yimiren, ad tizmireḍ ad tzzuzreḍ iznan neɣ ad tmeslayeḍ i yemddukkal deg waṭas n yiqeddacen. Maca aqeddac-agi, {domain}, mačči am wiyaḍ - deg-s i yella umaɣnu-ik, ihi cfu ɣef yisem-is.", "introduction.welcome.text": "Anṣuf γer fediverse! Deg kra n yimiren, ad tizmireḍ ad tzzuzreḍ iznan neɣ ad tmeslayeḍ i yemddukkal deg waṭas n yiqeddacen. Maca aqeddac-agi, {domain}, mačči am wiyaḍ - deg-s i yella umaγnu-ik, ihi cfu γef yisem-is.",
"keyboard_shortcuts.back": "uɣal ar deffir", "keyboard_shortcuts.back": "uγal ar deffir",
"keyboard_shortcuts.blocked": "akken ad teldiḍ tabdert n yimseqdacen yettwasḥebsen", "keyboard_shortcuts.blocked": "akken ad teldiḍ tabdert n yimseqdacen yettwasḥebsen",
"keyboard_shortcuts.boost": "i beṭṭu tikelt-nniḍen", "keyboard_shortcuts.boost": "i beṭṭu tikelt-nniḍen",
"keyboard_shortcuts.column": "to focus a status in one of the columns", "keyboard_shortcuts.column": "to focus a status in one of the columns",
"keyboard_shortcuts.compose": "to focus the compose textarea", "keyboard_shortcuts.compose": "to focus the compose textarea",
"keyboard_shortcuts.description": "Aglam", "keyboard_shortcuts.description": "Aglam",
"keyboard_shortcuts.direct": "akken ad teldiḍ ajgu n yiznan usriden", "keyboard_shortcuts.direct": "akken ad teldiḍ ajgu n yiznan usriden",
"keyboard_shortcuts.down": "i kennu ɣer wadda n tebdert", "keyboard_shortcuts.down": "i kennu γer wadda n tebdert",
"keyboard_shortcuts.enter": "i tildin n tsuffeɣt", "keyboard_shortcuts.enter": "i tildin n tsuffeγt",
"keyboard_shortcuts.favourite": "akken ad ternuḍ ɣer yismenyifen", "keyboard_shortcuts.favourite": "akken ad ternuḍ γer yismenyifen",
"keyboard_shortcuts.favourites": "i tildin n tebdert n yismenyifen", "keyboard_shortcuts.favourites": "i tildin n tebdert n yismenyifen",
"keyboard_shortcuts.federated": "i tildin n tsuddemt tamatut n yisallen", "keyboard_shortcuts.federated": "i tildin n tsuddemt tamatut n yisallen",
"keyboard_shortcuts.heading": "Inegzumen n unasiw", "keyboard_shortcuts.heading": "Inegzumen n unasiw",
@ -222,11 +223,11 @@
"keyboard_shortcuts.local": "i tildin n tsuddemt tadigant n yisallen", "keyboard_shortcuts.local": "i tildin n tsuddemt tadigant n yisallen",
"keyboard_shortcuts.mention": "akken ad d-bedreḍ ameskar", "keyboard_shortcuts.mention": "akken ad d-bedreḍ ameskar",
"keyboard_shortcuts.muted": "akken ad teldiḍ tabdert n yimseqdacen yettwasgugmen", "keyboard_shortcuts.muted": "akken ad teldiḍ tabdert n yimseqdacen yettwasgugmen",
"keyboard_shortcuts.my_profile": "akken ad d-teldiḍ amaɣnu-ik", "keyboard_shortcuts.my_profile": "akken ad d-teldiḍ amaγnu-ik",
"keyboard_shortcuts.notifications": "akken ad d-teldiḍ ajgu n tilɣa", "keyboard_shortcuts.notifications": "akken ad d-teldiḍ ajgu n tilγa",
"keyboard_shortcuts.open_media": "to open media", "keyboard_shortcuts.open_media": "to open media",
"keyboard_shortcuts.pinned": "i tildin n tebdert n tberraḥin yettwasentḍen", "keyboard_shortcuts.pinned": "i tildin n tebdert n tberraḥin yettwasentḍen",
"keyboard_shortcuts.profile": "akken ad d-teldiḍ amaɣnu n umeskar", "keyboard_shortcuts.profile": "akken ad d-teldiḍ amaγnu n umeskar",
"keyboard_shortcuts.reply": "i tririt", "keyboard_shortcuts.reply": "i tririt",
"keyboard_shortcuts.requests": "akken ad d-teldiḍ tabdert n yisuturen n teḍfeṛt", "keyboard_shortcuts.requests": "akken ad d-teldiḍ tabdert n yisuturen n teḍfeṛt",
"keyboard_shortcuts.search": "to focus search", "keyboard_shortcuts.search": "to focus search",
@ -235,7 +236,7 @@
"keyboard_shortcuts.toggle_sensitivity": "i teskent/tuffra n yimidyaten", "keyboard_shortcuts.toggle_sensitivity": "i teskent/tuffra n yimidyaten",
"keyboard_shortcuts.toot": "i beddu n tberraḥt tamaynut", "keyboard_shortcuts.toot": "i beddu n tberraḥt tamaynut",
"keyboard_shortcuts.unfocus": "to un-focus compose textarea/search", "keyboard_shortcuts.unfocus": "to un-focus compose textarea/search",
"keyboard_shortcuts.up": "i tulin ɣer ufella n tebdert", "keyboard_shortcuts.up": "i tulin γer ufella n tebdert",
"lightbox.close": "Mdel", "lightbox.close": "Mdel",
"lightbox.next": "Γer zdat", "lightbox.next": "Γer zdat",
"lightbox.previous": "Γer deffir", "lightbox.previous": "Γer deffir",
@ -253,8 +254,8 @@
"loading_indicator.label": "Asali...", "loading_indicator.label": "Asali...",
"media_gallery.toggle_visible": "Sken / Ffer", "media_gallery.toggle_visible": "Sken / Ffer",
"missing_indicator.label": "Ulac-it", "missing_indicator.label": "Ulac-it",
"missing_indicator.sublabel": "Ur nufi ara aɣbalu-a", "missing_indicator.sublabel": "Ur nufi ara aγbalu-a",
"mute_modal.hide_notifications": "Tebɣiḍ ad teffreḍ talɣutin n umseqdac-a?", "mute_modal.hide_notifications": "Tebγiḍ ad teffreḍ talγutin n umseqdac-a?",
"navigation_bar.apps": "Isnasen izirazen", "navigation_bar.apps": "Isnasen izirazen",
"navigation_bar.blocks": "Imseqdacen yettusḥebsen", "navigation_bar.blocks": "Imseqdacen yettusḥebsen",
"navigation_bar.bookmarks": "Ticraḍ", "navigation_bar.bookmarks": "Ticraḍ",
@ -262,13 +263,13 @@
"navigation_bar.compose": "Aru taberraḥt tamaynut", "navigation_bar.compose": "Aru taberraḥt tamaynut",
"navigation_bar.direct": "Iznan usridden", "navigation_bar.direct": "Iznan usridden",
"navigation_bar.discover": "Ẓer", "navigation_bar.discover": "Ẓer",
"navigation_bar.domain_blocks": "Tiɣula yeffren", "navigation_bar.domain_blocks": "Tiγula yeffren",
"navigation_bar.edit_profile": "Ẓreg amaɣnu", "navigation_bar.edit_profile": "Ẓreg amaγnu",
"navigation_bar.favourites": "Ismenyifen", "navigation_bar.favourites": "Ismenyifen",
"navigation_bar.filters": "Awalen i yettwasgugmen", "navigation_bar.filters": "Awalen i yettwasgugmen",
"navigation_bar.follow_requests": "Isuturen n teḍfeṛt", "navigation_bar.follow_requests": "Isuturen n teḍfeṛt",
"navigation_bar.follows_and_followers": "Imeḍfaṛen akked wid i teṭṭafaṛeḍ", "navigation_bar.follows_and_followers": "Imeḍfaṛen akked wid i teṭṭafaṛeḍ",
"navigation_bar.info": "Ɣef uqeddac-agi", "navigation_bar.info": "Γef uqeddac-a",
"navigation_bar.keyboard_shortcuts": "Inegzumen n unasiw", "navigation_bar.keyboard_shortcuts": "Inegzumen n unasiw",
"navigation_bar.lists": "Tibdarin", "navigation_bar.lists": "Tibdarin",
"navigation_bar.logout": "Ffeγ", "navigation_bar.logout": "Ffeγ",
@ -278,16 +279,16 @@
"navigation_bar.preferences": "Imenyafen", "navigation_bar.preferences": "Imenyafen",
"navigation_bar.public_timeline": "Tasuddemt tazayezt tamatut", "navigation_bar.public_timeline": "Tasuddemt tazayezt tamatut",
"navigation_bar.security": "Taγellist", "navigation_bar.security": "Taγellist",
"notification.favourite": "{name} yesmenyef tasuffeɣt-ik", "notification.favourite": "{name} yesmenyef tasuffeγt-ik",
"notification.follow": "{name} yeṭṭafaṛ-ik", "notification.follow": "{name} yeṭṭafaṛ-ik",
"notification.follow_request": "{name} yessuter-d ad k-yeḍfeṛ", "notification.follow_request": "{name} yessuter-d ad k-yeḍfeṛ",
"notification.mention": "{name} yebder-ik-id", "notification.mention": "{name} yebder-ik-id",
"notification.own_poll": "Your poll has ended", "notification.own_poll": "Your poll has ended",
"notification.poll": "A poll you have voted in has ended", "notification.poll": "A poll you have voted in has ended",
"notification.reblog": "{name} yebḍa taberraḥ-ik i tikelt-nniḍen", "notification.reblog": "{name} yebḍa taberraḥ-ik i tikelt-nniḍen",
"notifications.clear": "Sfeḍ tilɣa", "notifications.clear": "Sfeḍ tilγa",
"notifications.clear_confirmation": "Tebɣiḍ s tidet ad tekkseḍ akk tilɣa-ik i lebda?", "notifications.clear_confirmation": "Tebγiḍ s tidet ad tekkseḍ akk tilγa-ik i lebda?",
"notifications.column_settings.alert": "Tilɣa n tnarit", "notifications.column_settings.alert": "Tilγa n tnarit",
"notifications.column_settings.favourite": "Ismenyifen:", "notifications.column_settings.favourite": "Ismenyifen:",
"notifications.column_settings.filter_bar.advanced": "Sken-d meṛṛa tiggayin", "notifications.column_settings.filter_bar.advanced": "Sken-d meṛṛa tiggayin",
"notifications.column_settings.filter_bar.category": "Iri n usizdeg uzrib", "notifications.column_settings.filter_bar.category": "Iri n usizdeg uzrib",
@ -295,26 +296,26 @@
"notifications.column_settings.follow": "Imeḍfaṛen imaynuten:", "notifications.column_settings.follow": "Imeḍfaṛen imaynuten:",
"notifications.column_settings.follow_request": "Isuturen imaynuten n teḍfeṛt:", "notifications.column_settings.follow_request": "Isuturen imaynuten n teḍfeṛt:",
"notifications.column_settings.mention": "Abdar:", "notifications.column_settings.mention": "Abdar:",
"notifications.column_settings.poll": "Poll results:", "notifications.column_settings.poll": "Igemmaḍ n usenqed:",
"notifications.column_settings.push": "Tilɣa yettudemmren", "notifications.column_settings.push": "Tilγa yettudemmren",
"notifications.column_settings.reblog": "Boosts:", "notifications.column_settings.reblog": "Boosts:",
"notifications.column_settings.show": "Sken-d tilɣa deg ujgu", "notifications.column_settings.show": "Sken-d tilγa deg ujgu",
"notifications.column_settings.sound": "Rmed imesli", "notifications.column_settings.sound": "Rmed imesli",
"notifications.filter.all": "Akk", "notifications.filter.all": "Akk",
"notifications.filter.boosts": "Boosts", "notifications.filter.boosts": "Boosts",
"notifications.filter.favourites": "Ismenyifen", "notifications.filter.favourites": "Ismenyifen",
"notifications.filter.follows": "Yeṭafaṛ", "notifications.filter.follows": "Yeṭafaṛ",
"notifications.filter.mentions": "Abdar", "notifications.filter.mentions": "Abdar",
"notifications.filter.polls": "Poll results", "notifications.filter.polls": "Igemmaḍ n usenqed",
"notifications.group": "{count} n tilɣa", "notifications.group": "{count} n tilγa",
"poll.closed": "Ifukk", "poll.closed": "Ifukk",
"poll.refresh": "Smiren", "poll.refresh": "Smiren",
"poll.total_people": "{count, plural, one {# n wemdan} other {# n yemdanen}}", "poll.total_people": "{count, plural, one {# n wemdan} other {# n yemdanen}}",
"poll.total_votes": "{count, plural, one {# n udɣaṛ} other {# n yedɣaṛen}}", "poll.total_votes": "{count, plural, one {# n udγaṛ} other {# n yedγaṛen}}",
"poll.vote": "Dɣeṛ", "poll.vote": "Dγeṛ",
"poll.voted": "Tdeɣṛeḍ ɣef tririt-agi", "poll.voted": "Tdeγṛeḍ γef tririt-agi",
"poll_button.add_poll": "Add a poll", "poll_button.add_poll": "Rnu asenqed",
"poll_button.remove_poll": "Remove poll", "poll_button.remove_poll": "Kkes asenqed",
"privacy.change": "Adjust status privacy", "privacy.change": "Adjust status privacy",
"privacy.direct.long": "Bḍu gar yimseqdacen i tbedreḍ kan", "privacy.direct.long": "Bḍu gar yimseqdacen i tbedreḍ kan",
"privacy.direct.short": "Usrid", "privacy.direct.short": "Usrid",
@ -356,13 +357,13 @@
"status.block": "Seḥbes @{name}", "status.block": "Seḥbes @{name}",
"status.bookmark": "Creḍ", "status.bookmark": "Creḍ",
"status.cancel_reblog_private": "Sefsex beṭṭu", "status.cancel_reblog_private": "Sefsex beṭṭu",
"status.cannot_reblog": "Tasuffeɣt-a ur tezmir ara ad tettwabḍu tikelt-nniḍen", "status.cannot_reblog": "Tasuffeγt-a ur tezmir ara ad tettwabḍu tikelt-nniḍen",
"status.copy": "Nɣel assaɣ ɣer tasuffeɣt", "status.copy": "Nγel assaγ γer tasuffeγt",
"status.delete": "Kkes", "status.delete": "Kkes",
"status.detailed_status": "Detailed conversation view", "status.detailed_status": "Detailed conversation view",
"status.direct": "Izen usrid i @{name}", "status.direct": "Izen usrid i @{name}",
"status.embed": "Embed", "status.embed": "Embed",
"status.favourite": "Rnu ɣer yismenyifen", "status.favourite": "Rnu γer yismenyifen",
"status.filtered": "Yettwasizdeg", "status.filtered": "Yettwasizdeg",
"status.load_more": "Sali ugar", "status.load_more": "Sali ugar",
"status.media_hidden": "Media hidden", "status.media_hidden": "Media hidden",
@ -370,8 +371,8 @@
"status.more": "Ugar", "status.more": "Ugar",
"status.mute": "Sussem @{name}", "status.mute": "Sussem @{name}",
"status.mute_conversation": "Mute conversation", "status.mute_conversation": "Mute conversation",
"status.open": "Semɣeṛ tasuffeɣt-agi", "status.open": "Semγeṛ tasuffeγt-agi",
"status.pin": "Senteḍ-itt deg umaɣnu", "status.pin": "Senteḍ-itt deg umaγnu",
"status.pinned": "Tiberraḥin yettwasentḍen", "status.pinned": "Tiberraḥin yettwasentḍen",
"status.read_more": "Issin ugar", "status.read_more": "Issin ugar",
"status.reblog": "Bḍu", "status.reblog": "Bḍu",
@ -386,13 +387,13 @@
"status.sensitive_warning": "Agbur amḥulfu", "status.sensitive_warning": "Agbur amḥulfu",
"status.share": "Bḍu", "status.share": "Bḍu",
"status.show_less": "Sken-d drus", "status.show_less": "Sken-d drus",
"status.show_less_all": "Semẓi akk tisuffɣin", "status.show_less_all": "Semẓi akk tisuffγin",
"status.show_more": "Sken-ed ugar", "status.show_more": "Sken-ed ugar",
"status.show_more_all": "Ẓerr ugar lebda", "status.show_more_all": "Ẓerr ugar lebda",
"status.show_thread": "Show thread", "status.show_thread": "Show thread",
"status.uncached_media_warning": "Ulac-it", "status.uncached_media_warning": "Ulac-it",
"status.unmute_conversation": "Kkes asgugem n udiwenni", "status.unmute_conversation": "Kkes asgugem n udiwenni",
"status.unpin": "Kkes asenteḍ seg umaɣnu", "status.unpin": "Kkes asenteḍ seg umaγnu",
"suggestions.dismiss": "Dismiss suggestion", "suggestions.dismiss": "Dismiss suggestion",
"suggestions.header": "Ahat ad tcelgeḍ deg…", "suggestions.header": "Ahat ad tcelgeḍ deg…",
"tabs_bar.federated_timeline": "Amatu", "tabs_bar.federated_timeline": "Amatu",
@ -416,10 +417,10 @@
"upload_form.description": "Glem-d i yemdaneni yesɛan ugur deg yiẓri", "upload_form.description": "Glem-d i yemdaneni yesɛan ugur deg yiẓri",
"upload_form.edit": "Ẓreg", "upload_form.edit": "Ẓreg",
"upload_form.undo": "Kkes", "upload_form.undo": "Kkes",
"upload_form.video_description": "Glem-d i yemdanen i yesɛan ugur deg tmesliwt neɣ deg yiẓri", "upload_form.video_description": "Glem-d i yemdanen i yesɛan ugur deg tmesliwt neγ deg yiẓri",
"upload_modal.analyzing_picture": "Tasleḍt n tugna tetteddu…", "upload_modal.analyzing_picture": "Tasleḍt n tugna tetteddu…",
"upload_modal.apply": "Snes", "upload_modal.apply": "Snes",
"upload_modal.description_placeholder": "Aberraɣ arurad ineggez nnig n uqjun amuṭṭis", "upload_modal.description_placeholder": "Aberraγ arurad ineggez nnig n uqjun amuṭṭis",
"upload_modal.detect_text": "Detect text from picture", "upload_modal.detect_text": "Detect text from picture",
"upload_modal.edit_media": "Edit media", "upload_modal.edit_media": "Edit media",
"upload_modal.hint": "Click or drag the circle on the preview to choose the focal point which will always be in view on all thumbnails.", "upload_modal.hint": "Click or drag the circle on the preview to choose the focal point which will always be in view on all thumbnails.",
@ -427,8 +428,8 @@
"upload_progress.label": "Asali iteddu...", "upload_progress.label": "Asali iteddu...",
"video.close": "Mdel tabidyutt", "video.close": "Mdel tabidyutt",
"video.download": "Sidered afaylu", "video.download": "Sidered afaylu",
"video.exit_fullscreen": "Ffeɣ seg ugdil aččuran", "video.exit_fullscreen": "Ffeγ seg ugdil aččuran",
"video.expand": "Semɣeṛ tavidyut", "video.expand": "Semγeṛ tavidyut",
"video.fullscreen": "Agdil aččuran", "video.fullscreen": "Agdil aččuran",
"video.hide": "Ffer tabidyutt", "video.hide": "Ffer tabidyutt",
"video.mute": "Gzem imesli", "video.mute": "Gzem imesli",

View File

@ -43,6 +43,7 @@
"alert.rate_limited.title": "Бағалау шектеулі", "alert.rate_limited.title": "Бағалау шектеулі",
"alert.unexpected.message": "Бір нәрсе дұрыс болмады.", "alert.unexpected.message": "Бір нәрсе дұрыс болмады.",
"alert.unexpected.title": "Өй!", "alert.unexpected.title": "Өй!",
"announcement.announcement": "Announcement",
"autosuggest_hashtag.per_week": "{count} аптасына", "autosuggest_hashtag.per_week": "{count} аптасына",
"boost_modal.combo": "Келесіде өткізіп жіберу үшін басыңыз {combo}", "boost_modal.combo": "Келесіде өткізіп жіберу үшін басыңыз {combo}",
"bundle_column_error.body": "Бұл компонентті жүктеген кезде бір қате пайда болды.", "bundle_column_error.body": "Бұл компонентті жүктеген кезде бір қате пайда болды.",

View File

@ -43,6 +43,7 @@
"alert.rate_limited.title": "Rate limited", "alert.rate_limited.title": "Rate limited",
"alert.unexpected.message": "An unexpected error occurred.", "alert.unexpected.message": "An unexpected error occurred.",
"alert.unexpected.title": "Oops!", "alert.unexpected.title": "Oops!",
"announcement.announcement": "Announcement",
"autosuggest_hashtag.per_week": "{count} per week", "autosuggest_hashtag.per_week": "{count} per week",
"boost_modal.combo": "You can press {combo} to skip this next time", "boost_modal.combo": "You can press {combo} to skip this next time",
"bundle_column_error.body": "Something went wrong while loading this component.", "bundle_column_error.body": "Something went wrong while loading this component.",

View File

@ -43,6 +43,7 @@
"alert.rate_limited.title": "빈도 제한", "alert.rate_limited.title": "빈도 제한",
"alert.unexpected.message": "예측하지 못한 에러가 발생했습니다.", "alert.unexpected.message": "예측하지 못한 에러가 발생했습니다.",
"alert.unexpected.title": "앗!", "alert.unexpected.title": "앗!",
"announcement.announcement": "Announcement",
"autosuggest_hashtag.per_week": "주간 {count}회", "autosuggest_hashtag.per_week": "주간 {count}회",
"boost_modal.combo": "{combo}를 누르면 다음부터 이 과정을 건너뛸 수 있습니다", "boost_modal.combo": "{combo}를 누르면 다음부터 이 과정을 건너뛸 수 있습니다",
"bundle_column_error.body": "컴포넌트를 불러오는 과정에서 문제가 발생했습니다.", "bundle_column_error.body": "컴포넌트를 불러오는 과정에서 문제가 발생했습니다.",

View File

@ -43,6 +43,7 @@
"alert.rate_limited.title": "Rate limited", "alert.rate_limited.title": "Rate limited",
"alert.unexpected.message": "An unexpected error occurred.", "alert.unexpected.message": "An unexpected error occurred.",
"alert.unexpected.title": "Oops!", "alert.unexpected.title": "Oops!",
"announcement.announcement": "Announcement",
"autosuggest_hashtag.per_week": "{count} per week", "autosuggest_hashtag.per_week": "{count} per week",
"boost_modal.combo": "You can press {combo} to skip this next time", "boost_modal.combo": "You can press {combo} to skip this next time",
"bundle_column_error.body": "Something went wrong while loading this component.", "bundle_column_error.body": "Something went wrong while loading this component.",

View File

@ -43,6 +43,7 @@
"alert.rate_limited.title": "Rate limited", "alert.rate_limited.title": "Rate limited",
"alert.unexpected.message": "Negaidīta kļūda.", "alert.unexpected.message": "Negaidīta kļūda.",
"alert.unexpected.title": "Ups!", "alert.unexpected.title": "Ups!",
"announcement.announcement": "Announcement",
"autosuggest_hashtag.per_week": "{count} per week", "autosuggest_hashtag.per_week": "{count} per week",
"boost_modal.combo": "Nospied {combo} lai izlaistu šo nākamreiz", "boost_modal.combo": "Nospied {combo} lai izlaistu šo nākamreiz",
"bundle_column_error.body": "Kaut kas nogāja greizi ielādējot šo komponenti.", "bundle_column_error.body": "Kaut kas nogāja greizi ielādējot šo komponenti.",

View File

@ -43,6 +43,7 @@
"alert.rate_limited.title": "Rate limited", "alert.rate_limited.title": "Rate limited",
"alert.unexpected.message": "Неочекувана грешка.", "alert.unexpected.message": "Неочекувана грешка.",
"alert.unexpected.title": "Упс!", "alert.unexpected.title": "Упс!",
"announcement.announcement": "Announcement",
"autosuggest_hashtag.per_week": "{count} неделно", "autosuggest_hashtag.per_week": "{count} неделно",
"boost_modal.combo": "Кликни {combo} за да го прескокниш ова нареден пат", "boost_modal.combo": "Кликни {combo} за да го прескокниш ова нареден пат",
"bundle_column_error.body": "Се случи проблем при вчитувањето.", "bundle_column_error.body": "Се случи проблем при вчитувањето.",

View File

@ -43,6 +43,7 @@
"alert.rate_limited.title": "തോത് പരിമിതപ്പെടുത്തിയിരിക്കുന്നു", "alert.rate_limited.title": "തോത് പരിമിതപ്പെടുത്തിയിരിക്കുന്നു",
"alert.unexpected.message": "അപ്രതീക്ഷിതമായി എന്തോ സംഭവിച്ചു.", "alert.unexpected.message": "അപ്രതീക്ഷിതമായി എന്തോ സംഭവിച്ചു.",
"alert.unexpected.title": "ശ്ശോ!", "alert.unexpected.title": "ശ്ശോ!",
"announcement.announcement": "Announcement",
"autosuggest_hashtag.per_week": "ആഴ്ച തോറും {count}", "autosuggest_hashtag.per_week": "ആഴ്ച തോറും {count}",
"boost_modal.combo": "അടുത്ത തവണ ഇത് ഒഴിവാക്കുവാൻ {combo} ഞെക്കാവുന്നതാണ്", "boost_modal.combo": "അടുത്ത തവണ ഇത് ഒഴിവാക്കുവാൻ {combo} ഞെക്കാവുന്നതാണ്",
"bundle_column_error.body": "ഈ ഘടകം പ്രദശിപ്പിക്കുമ്പോൾ എന്തോ കുഴപ്പം സംഭവിച്ചു.", "bundle_column_error.body": "ഈ ഘടകം പ്രദശിപ്പിക്കുമ്പോൾ എന്തോ കുഴപ്പം സംഭവിച്ചു.",

View File

@ -43,6 +43,7 @@
"alert.rate_limited.title": "Rate limited", "alert.rate_limited.title": "Rate limited",
"alert.unexpected.message": "An unexpected error occurred.", "alert.unexpected.message": "An unexpected error occurred.",
"alert.unexpected.title": "अरेरे!", "alert.unexpected.title": "अरेरे!",
"announcement.announcement": "Announcement",
"autosuggest_hashtag.per_week": "{count} प्रतिसप्ताह", "autosuggest_hashtag.per_week": "{count} प्रतिसप्ताह",
"boost_modal.combo": "You can press {combo} to skip this next time", "boost_modal.combo": "You can press {combo} to skip this next time",
"bundle_column_error.body": "हा घटक लोड करतांना काहीतरी चुकले आहे.", "bundle_column_error.body": "हा घटक लोड करतांना काहीतरी चुकले आहे.",

View File

@ -43,6 +43,7 @@
"alert.rate_limited.title": "Rate limited", "alert.rate_limited.title": "Rate limited",
"alert.unexpected.message": "An unexpected error occurred.", "alert.unexpected.message": "An unexpected error occurred.",
"alert.unexpected.title": "Oops!", "alert.unexpected.title": "Oops!",
"announcement.announcement": "Announcement",
"autosuggest_hashtag.per_week": "{count} per week", "autosuggest_hashtag.per_week": "{count} per week",
"boost_modal.combo": "You can press {combo} to skip this next time", "boost_modal.combo": "You can press {combo} to skip this next time",
"bundle_column_error.body": "Something went wrong while loading this component.", "bundle_column_error.body": "Something went wrong while loading this component.",

View File

@ -43,6 +43,7 @@
"alert.rate_limited.title": "Beperkt te gebruiken", "alert.rate_limited.title": "Beperkt te gebruiken",
"alert.unexpected.message": "Er deed zich een onverwachte fout voor", "alert.unexpected.message": "Er deed zich een onverwachte fout voor",
"alert.unexpected.title": "Oeps!", "alert.unexpected.title": "Oeps!",
"announcement.announcement": "Announcement",
"autosuggest_hashtag.per_week": "{count} per week", "autosuggest_hashtag.per_week": "{count} per week",
"boost_modal.combo": "Je kunt {combo} klikken om dit de volgende keer over te slaan", "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.", "bundle_column_error.body": "Tijdens het laden van dit onderdeel is er iets fout gegaan.",

View File

@ -43,6 +43,7 @@
"alert.rate_limited.title": "Begrensa rate", "alert.rate_limited.title": "Begrensa rate",
"alert.unexpected.message": "Eit uventa problem oppstod.", "alert.unexpected.message": "Eit uventa problem oppstod.",
"alert.unexpected.title": "Oi sann!", "alert.unexpected.title": "Oi sann!",
"announcement.announcement": "Announcement",
"autosuggest_hashtag.per_week": "{count} per veke", "autosuggest_hashtag.per_week": "{count} per veke",
"boost_modal.combo": "Du kan trykkja {combo} for å hoppa over dette neste gong", "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.", "bundle_column_error.body": "Noko gjekk gale mens denne komponenten vart lasta ned.",
@ -170,7 +171,7 @@
"getting_started.invite": "Byd folk inn", "getting_started.invite": "Byd folk inn",
"getting_started.open_source_notice": "Mastodon er fri programvare. Du kan bidraga eller rapportera problem med GitHub på {github}.", "getting_started.open_source_notice": "Mastodon er fri programvare. Du kan bidraga eller rapportera problem med GitHub på {github}.",
"getting_started.security": "Kontoinnstillingar", "getting_started.security": "Kontoinnstillingar",
"getting_started.terms": "Brukarvillkår", "getting_started.terms": "Brukarvilkår",
"hashtag.column_header.tag_mode.all": "og {additional}", "hashtag.column_header.tag_mode.all": "og {additional}",
"hashtag.column_header.tag_mode.any": "eller {additional}", "hashtag.column_header.tag_mode.any": "eller {additional}",
"hashtag.column_header.tag_mode.none": "utan {additional}", "hashtag.column_header.tag_mode.none": "utan {additional}",
@ -354,7 +355,7 @@
"status.admin_account": "Opne moderasjonsgrensesnitt for @{name}", "status.admin_account": "Opne moderasjonsgrensesnitt for @{name}",
"status.admin_status": "Opne denne statusen i moderasjonsgrensesnittet", "status.admin_status": "Opne denne statusen i moderasjonsgrensesnittet",
"status.block": "Blokker @{name}", "status.block": "Blokker @{name}",
"status.bookmark": "Bokmerke", "status.bookmark": "Bokmerk",
"status.cancel_reblog_private": "Opphev framheving", "status.cancel_reblog_private": "Opphev framheving",
"status.cannot_reblog": "Denne posten kan ikkje framhevast", "status.cannot_reblog": "Denne posten kan ikkje framhevast",
"status.copy": "Kopier lenke til status", "status.copy": "Kopier lenke til status",

View File

@ -43,6 +43,7 @@
"alert.rate_limited.title": "Hastighetsbegrenset", "alert.rate_limited.title": "Hastighetsbegrenset",
"alert.unexpected.message": "En uventet feil oppstod.", "alert.unexpected.message": "En uventet feil oppstod.",
"alert.unexpected.title": "Oops!", "alert.unexpected.title": "Oops!",
"announcement.announcement": "Announcement",
"autosuggest_hashtag.per_week": "{count} per uke", "autosuggest_hashtag.per_week": "{count} per uke",
"boost_modal.combo": "You kan trykke {combo} for å hoppe over dette neste gang", "boost_modal.combo": "You kan trykke {combo} for å hoppe over dette neste gang",
"bundle_column_error.body": "Noe gikk galt mens denne komponenten lastet.", "bundle_column_error.body": "Noe gikk galt mens denne komponenten lastet.",

Some files were not shown because too many files have changed in this diff Show More