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

Merge upstream changes
rebase/4.0.0rc2
ThibG 2018-08-11 15:28:06 +02:00 committed by GitHub
commit d787bcdeb1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
92 changed files with 1582 additions and 658 deletions

View File

@ -10,9 +10,13 @@ class AboutController < ApplicationController
@initial_state_json = serializable_resource.to_json
end
def more; end
def more
render layout: 'public'
end
def terms; end
def terms
render layout: 'public'
end
private

View File

@ -11,8 +11,9 @@ class AccountsController < ApplicationController
respond_to do |format|
format.html do
use_pack 'public'
@body_classes = 'with-modals'
@pinned_statuses = []
@body_classes = 'with-modals'
@pinned_statuses = []
@endorsed_accounts = @account.endorsed_accounts.to_a.sample(4)
if current_account && @account.blocking?(current_account)
@statuses = []

View File

@ -0,0 +1,32 @@
# frozen_string_literal: true
class Api::V1::Accounts::PinsController < Api::BaseController
include Authorization
before_action -> { doorkeeper_authorize! :write, :'write:accounts' }
before_action :require_user!
before_action :set_account
respond_to :json
def create
AccountPin.create!(account: current_account, target_account: @account)
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships_presenter
end
def destroy
pin = AccountPin.find_by(account: current_account, target_account: @account)
pin&.destroy!
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships_presenter
end
private
def set_account
@account = Account.find(params[:account_id])
end
def relationships_presenter
AccountRelationshipsPresenter.new([@account.id], current_user.account_id)
end
end

View File

@ -6,4 +6,36 @@ module HomeHelper
locale: I18n.locale,
}
end
def account_link_to(account, button = '')
content_tag(:div, class: 'account') do
content_tag(:div, class: 'account__wrapper') do
section = if account.nil?
content_tag(:div, class: 'account__display-name') do
content_tag(:div, class: 'account__avatar-wrapper') do
content_tag(:div, '', class: 'account__avatar', style: "background-image: url(#{full_asset_url('avatars/original/missing.png', skip_pipeline: true)})")
end +
content_tag(:span, class: 'display-name') do
content_tag(:strong, t('about.contact_missing')) +
content_tag(:span, t('about.contact_unavailable'), class: 'display-name__account')
end
end
else
link_to(TagManager.instance.url_for(account), class: 'account__display-name') do
content_tag(:div, class: 'account__avatar-wrapper') do
content_tag(:div, '', class: 'account__avatar', style: "background-image: url(#{account.avatar.url})")
end +
content_tag(:span, class: 'display-name') do
content_tag(:bdi) do
content_tag(:strong, display_name(account, custom_emojify: true), class: 'display-name__html emojify')
end +
content_tag(:span, "@#{account.acct}", class: 'display-name__account')
end
end
end
section + button
end
end
end
end

View File

@ -28,6 +28,14 @@ export const ACCOUNT_UNMUTE_REQUEST = 'ACCOUNT_UNMUTE_REQUEST';
export const ACCOUNT_UNMUTE_SUCCESS = 'ACCOUNT_UNMUTE_SUCCESS';
export const ACCOUNT_UNMUTE_FAIL = 'ACCOUNT_UNMUTE_FAIL';
export const ACCOUNT_PIN_REQUEST = 'ACCOUNT_PIN_REQUEST';
export const ACCOUNT_PIN_SUCCESS = 'ACCOUNT_PIN_SUCCESS';
export const ACCOUNT_PIN_FAIL = 'ACCOUNT_PIN_FAIL';
export const ACCOUNT_UNPIN_REQUEST = 'ACCOUNT_UNPIN_REQUEST';
export const ACCOUNT_UNPIN_SUCCESS = 'ACCOUNT_UNPIN_SUCCESS';
export const ACCOUNT_UNPIN_FAIL = 'ACCOUNT_UNPIN_FAIL';
export const FOLLOWERS_FETCH_REQUEST = 'FOLLOWERS_FETCH_REQUEST';
export const FOLLOWERS_FETCH_SUCCESS = 'FOLLOWERS_FETCH_SUCCESS';
export const FOLLOWERS_FETCH_FAIL = 'FOLLOWERS_FETCH_FAIL';
@ -659,3 +667,69 @@ export function rejectFollowRequestFail(id, error) {
error,
};
};
export function pinAccount(id) {
return (dispatch, getState) => {
dispatch(pinAccountRequest(id));
api(getState).post(`/api/v1/accounts/${id}/pin`).then(response => {
dispatch(pinAccountSuccess(response.data));
}).catch(error => {
dispatch(pinAccountFail(error));
});
};
};
export function unpinAccount(id) {
return (dispatch, getState) => {
dispatch(unpinAccountRequest(id));
api(getState).post(`/api/v1/accounts/${id}/unpin`).then(response => {
dispatch(unpinAccountSuccess(response.data));
}).catch(error => {
dispatch(unpinAccountFail(error));
});
};
};
export function pinAccountRequest(id) {
return {
type: ACCOUNT_PIN_REQUEST,
id,
};
};
export function pinAccountSuccess(relationship) {
return {
type: ACCOUNT_PIN_SUCCESS,
relationship,
};
};
export function pinAccountFail(error) {
return {
type: ACCOUNT_PIN_FAIL,
error,
};
};
export function unpinAccountRequest(id) {
return {
type: ACCOUNT_UNPIN_REQUEST,
id,
};
};
export function unpinAccountSuccess(relationship) {
return {
type: ACCOUNT_UNPIN_SUCCESS,
relationship,
};
};
export function unpinAccountFail(error) {
return {
type: ACCOUNT_UNPIN_FAIL,
error,
};
};

View File

@ -23,6 +23,8 @@ const messages = defineMessages({
unblockDomain: { id: 'account.unblock_domain', defaultMessage: 'Unhide {domain}' },
hideReblogs: { id: 'account.hide_reblogs', defaultMessage: 'Hide boosts from @{name}' },
showReblogs: { id: 'account.show_reblogs', defaultMessage: 'Show boosts from @{name}' },
endorse: { id: 'account.endorse', defaultMessage: 'Feature on profile' },
unendorse: { id: 'account.unendorse', defaultMessage: 'Don\'t feature on profile' },
});
@injectIntl
@ -39,6 +41,7 @@ export default class ActionBar extends React.PureComponent {
onMute: PropTypes.func.isRequired,
onBlockDomain: PropTypes.func.isRequired,
onUnblockDomain: PropTypes.func.isRequired,
onEndorseToggle: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired,
};
@ -72,6 +75,9 @@ export default class ActionBar extends React.PureComponent {
} else {
menu.push({ text: intl.formatMessage(messages.showReblogs, { name: account.get('username') }), action: this.props.onReblogToggle });
}
menu.push({ text: intl.formatMessage(account.getIn(['relationship', 'endorsed']) ? messages.unendorse : messages.endorse), action: this.props.onEndorseToggle });
menu.push(null);
}
if (account.getIn(['relationship', 'muting'])) {

View File

@ -22,6 +22,7 @@ export default class Header extends ImmutablePureComponent {
onMute: PropTypes.func.isRequired,
onBlockDomain: PropTypes.func.isRequired,
onUnblockDomain: PropTypes.func.isRequired,
onEndorseToggle: PropTypes.func.isRequired,
hideTabs: PropTypes.bool,
};
@ -73,6 +74,10 @@ export default class Header extends ImmutablePureComponent {
this.props.onUnblockDomain(domain);
}
handleEndorseToggle = () => {
this.props.onEndorseToggle(this.props.account);
}
render () {
const { account, hideTabs } = this.props;
@ -100,6 +105,7 @@ export default class Header extends ImmutablePureComponent {
onMute={this.handleMute}
onBlockDomain={this.handleBlockDomain}
onUnblockDomain={this.handleUnblockDomain}
onEndorseToggle={this.handleEndorseToggle}
/>
{!hideTabs && (

View File

@ -8,6 +8,8 @@ import {
blockAccount,
unblockAccount,
unmuteAccount,
pinAccount,
unpinAccount,
} from 'flavours/glitch/actions/accounts';
import {
mentionCompose,
@ -86,6 +88,14 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
}
},
onEndorseToggle (account) {
if (account.getIn(['relationship', 'endorsed'])) {
dispatch(unpinAccount(account.get('id')));
} else {
dispatch(pinAccount(account.get('id')));
}
},
onReport (account) {
dispatch(initReport(account));
},

View File

@ -5,6 +5,8 @@ import {
ACCOUNT_UNBLOCK_SUCCESS,
ACCOUNT_MUTE_SUCCESS,
ACCOUNT_UNMUTE_SUCCESS,
ACCOUNT_PIN_SUCCESS,
ACCOUNT_UNPIN_SUCCESS,
RELATIONSHIPS_FETCH_SUCCESS,
} from 'flavours/glitch/actions/accounts';
import {
@ -41,6 +43,8 @@ export default function relationships(state = initialState, action) {
case ACCOUNT_UNBLOCK_SUCCESS:
case ACCOUNT_MUTE_SUCCESS:
case ACCOUNT_UNMUTE_SUCCESS:
case ACCOUNT_PIN_SUCCESS:
case ACCOUNT_UNPIN_SUCCESS:
return normalizeRelationship(state, action.relationship);
case RELATIONSHIPS_FETCH_SUCCESS:
return normalizeRelationships(state, action.relationships);

View File

@ -15,6 +15,278 @@ $small-breakpoint: 960px;
}
}
.rich-formatting {
font-family: 'mastodon-font-sans-serif', sans-serif;
font-size: 16px;
font-weight: 400;
font-size: 16px;
line-height: 30px;
color: $darker-text-color;
padding-right: 10px;
a {
color: $highlight-text-color;
text-decoration: underline;
}
p,
li {
font-family: 'mastodon-font-sans-serif', sans-serif;
font-size: 16px;
font-weight: 400;
font-size: 16px;
line-height: 30px;
margin-bottom: 12px;
color: $darker-text-color;
a {
color: $highlight-text-color;
text-decoration: underline;
}
&:last-child {
margin-bottom: 0;
}
}
em {
display: inline;
margin: 0;
padding: 0;
font-weight: 700;
background: transparent;
font-family: inherit;
font-size: inherit;
line-height: inherit;
color: lighten($darker-text-color, 10%);
}
h1 {
font-family: 'mastodon-font-display', sans-serif;
font-size: 26px;
line-height: 30px;
font-weight: 500;
margin-bottom: 20px;
color: $secondary-text-color;
small {
font-family: 'mastodon-font-sans-serif', sans-serif;
display: block;
font-size: 18px;
font-weight: 400;
color: lighten($darker-text-color, 10%);
}
}
h2 {
font-family: 'mastodon-font-display', sans-serif;
font-size: 22px;
line-height: 26px;
font-weight: 500;
margin-bottom: 20px;
color: $secondary-text-color;
}
h3 {
font-family: 'mastodon-font-display', sans-serif;
font-size: 18px;
line-height: 24px;
font-weight: 500;
margin-bottom: 20px;
color: $secondary-text-color;
}
h4 {
font-family: 'mastodon-font-display', sans-serif;
font-size: 16px;
line-height: 24px;
font-weight: 500;
margin-bottom: 20px;
color: $secondary-text-color;
}
h5 {
font-family: 'mastodon-font-display', sans-serif;
font-size: 14px;
line-height: 24px;
font-weight: 500;
margin-bottom: 20px;
color: $secondary-text-color;
}
h6 {
font-family: 'mastodon-font-display', sans-serif;
font-size: 12px;
line-height: 24px;
font-weight: 500;
margin-bottom: 20px;
color: $secondary-text-color;
}
ul,
ol {
margin-left: 20px;
&[type='a'] {
list-style-type: lower-alpha;
}
&[type='i'] {
list-style-type: lower-roman;
}
}
ul {
list-style: disc;
}
ol {
list-style: decimal;
}
li > ol,
li > ul {
margin-top: 6px;
}
hr {
width: 100%;
height: 0;
border: 0;
border-bottom: 1px solid rgba($ui-base-lighter-color, .6);
margin: 20px 0;
&.spacer {
height: 1px;
border: 0;
}
}
}
.information-board {
background: darken($ui-base-color, 4%);
padding: 20px 0;
.container-alt {
position: relative;
padding-right: 280px + 15px;
}
&__sections {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
&__section {
flex: 1 0 0;
font-family: 'mastodon-font-sans-serif', sans-serif;
font-size: 16px;
line-height: 28px;
color: $primary-text-color;
text-align: right;
padding: 10px 15px;
span,
strong {
display: block;
}
span {
&:last-child {
color: $secondary-text-color;
}
}
strong {
font-weight: 500;
font-size: 32px;
line-height: 48px;
}
@media screen and (max-width: $column-breakpoint) {
text-align: center;
}
}
.panel {
position: absolute;
width: 280px;
box-sizing: border-box;
background: darken($ui-base-color, 8%);
padding: 20px;
padding-top: 10px;
border-radius: 4px 4px 0 0;
right: 0;
bottom: -40px;
.panel-header {
font-family: 'mastodon-font-display', sans-serif;
font-size: 14px;
line-height: 24px;
font-weight: 500;
color: $darker-text-color;
padding-bottom: 5px;
margin-bottom: 15px;
border-bottom: 1px solid lighten($ui-base-color, 4%);
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
a,
span {
font-weight: 400;
color: darken($darker-text-color, 10%);
}
a {
text-decoration: none;
}
}
}
.owner {
text-align: center;
.avatar {
width: 80px;
height: 80px;
@include avatar-size(80px);
margin: 0 auto;
margin-bottom: 15px;
img {
display: block;
width: 80px;
height: 80px;
border-radius: 48px;
@include avatar-radius();
}
}
.name {
font-size: 14px;
a {
display: block;
color: $primary-text-color;
text-decoration: none;
&:hover {
.display_name {
text-decoration: underline;
}
}
}
.username {
display: block;
color: $darker-text-color;
}
}
}
}
.landing-page {
.grid {
display: grid;
@ -396,7 +668,7 @@ $small-breakpoint: 960px;
display: flex;
justify-content: center;
align-items: center;
color: $ui-primary-color;
color: $darker-text-color;
text-decoration: none;
padding: 12px 16px;
line-height: 32px;
@ -486,130 +758,6 @@ $small-breakpoint: 960px;
}
}
.information-board {
background: darken($ui-base-color, 4%);
padding: 20px 0;
.container-alt {
position: relative;
padding-right: 280px + 15px;
}
&__sections {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
&__section {
flex: 1 0 0;
font-family: 'mastodon-font-sans-serif', sans-serif;
font-size: 16px;
line-height: 28px;
color: $primary-text-color;
text-align: right;
padding: 10px 15px;
span,
strong {
display: block;
}
span {
&:last-child {
color: $secondary-text-color;
}
}
strong {
font-weight: 500;
font-size: 32px;
line-height: 48px;
}
@media screen and (max-width: $column-breakpoint) {
text-align: center;
}
}
.panel {
position: absolute;
width: 280px;
box-sizing: border-box;
background: darken($ui-base-color, 8%);
padding: 20px;
padding-top: 10px;
border-radius: 4px 4px 0 0;
right: 0;
bottom: -40px;
.panel-header {
font-family: 'mastodon-font-display', sans-serif;
font-size: 14px;
line-height: 24px;
font-weight: 500;
color: $darker-text-color;
padding-bottom: 5px;
margin-bottom: 15px;
border-bottom: 1px solid lighten($ui-base-color, 4%);
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
a,
span {
font-weight: 400;
color: darken($darker-text-color, 10%);
}
a {
text-decoration: none;
}
}
}
.owner {
text-align: center;
.avatar {
width: 80px;
height: 80px;
@include avatar-size(80px);
margin: 0 auto;
margin-bottom: 15px;
img {
display: block;
width: 80px;
height: 80px;
border-radius: 48px;
@include avatar-radius();
}
}
.name {
font-size: 14px;
a {
display: block;
color: $primary-text-color;
text-decoration: none;
&:hover {
.display_name {
text-decoration: underline;
}
}
}
.username {
display: block;
color: $darker-text-color;
}
}
}
}
&.alternative {
padding: 10px 0;
@ -644,8 +792,10 @@ $small-breakpoint: 960px;
border-radius: 4px;
padding: 25px 40px;
overflow: hidden;
box-sizing: border-box;
.row {
width: 100%;
display: flex;
flex-direction: row-reverse;
flex-wrap: wrap;
@ -662,11 +812,20 @@ $small-breakpoint: 960px;
flex: 1 0 auto;
padding: 0 10px;
}
@media screen and (max-width: $no-gap-breakpoint) {
width: 100%;
justify-content: space-between;
}
}
.row__mascot {
flex: 1;
margin: 10px -50px 0 0;
@media screen and (max-width: $no-gap-breakpoint) {
display: none;
}
}
}
@ -718,8 +877,8 @@ $small-breakpoint: 960px;
&__avatar {
width: 44px;
height: 44px;
@include avatar-size(48px);
background-size: 44px 44px;
@include avatar-size(44px);
}
.display-name {
@ -904,8 +1063,29 @@ $small-breakpoint: 960px;
}
}
.attachment-list__list {
margin-left: 0;
list-style: none;
li {
font-size: inherit;
line-height: inherit;
font-weight: inherit;
margin-bottom: 0;
a {
color: $dark-text-color;
text-decoration: none;
&:hover {
text-decoration: underline;
}
}
}
}
@media screen and (max-width: $column-breakpoint) {
height: 90vh;
display: none;
}
}
@ -965,21 +1145,6 @@ $small-breakpoint: 960px;
}
}
.extended-description {
padding: 50px 0;
font-family: 'mastodon-font-sans-serif', sans-serif;
font-size: 16px;
font-weight: 400;
font-size: 16px;
line-height: 30px;
color: $darker-text-color;
a {
color: $highlight-text-color;
text-decoration: underline;
}
}
.footer-links {
padding-bottom: 50px;
text-align: right;

View File

@ -117,6 +117,83 @@
}
}
.grid-3 {
display: grid;
grid-gap: 10px;
grid-template-columns: 3fr 1fr;
grid-auto-columns: 25%;
grid-auto-rows: max-content;
.column-0 {
grid-column: 1/3;
grid-row: 1;
}
.column-1 {
grid-column: 1;
grid-row: 2;
}
.column-2 {
grid-column: 2;
grid-row: 2;
}
.column-3 {
grid-column: 1/3;
grid-row: 3;
}
.landing-page__call-to-action {
min-height: 100%;
}
@media screen and (max-width: 738px) {
grid-template-columns: minmax(0, 50%) minmax(0, 50%);
.landing-page__call-to-action {
padding: 20px;
display: flex;
align-items: center;
justify-content: center;
}
.row__information-board {
width: 100%;
justify-content: center;
align-items: center;
}
.row__mascot {
display: none;
}
}
@media screen and (max-width: $no-gap-breakpoint) {
grid-gap: 0;
grid-template-columns: minmax(0, 100%);
.column-0 {
grid-column: 1;
}
.column-1 {
grid-column: 1;
grid-row: 3;
}
.column-2 {
grid-column: 1;
grid-row: 2;
}
.column-3 {
grid-column: 1;
grid-row: 4;
}
}
}
.public-layout {
@media screen and (max-width: $no-gap-breakpoint) {
padding-top: 48px;
@ -302,6 +379,19 @@
}
}
&--no-bar {
margin-bottom: 0;
.public-account-header__image,
.public-account-header__image img {
border-radius: 4px;
@media screen and (max-width: $no-gap-breakpoint) {
border-radius: 0;
}
}
}
@media screen and (max-width: $no-gap-breakpoint) {
margin-bottom: 0;
box-shadow: none;

View File

@ -71,6 +71,84 @@
}
}
.endorsements-widget {
margin-bottom: 10px;
padding-bottom: 10px;
h4 {
padding: 10px;
text-transform: uppercase;
font-weight: 700;
font-size: 13px;
color: $darker-text-color;
}
.account {
padding: 10px 0;
&:last-child {
border-bottom: 0;
}
.account__display-name {
display: flex;
align-items: center;
}
.account__avatar {
width: 44px;
height: 44px;
background-size: 44px 44px;
}
}
}
.box-widget {
padding: 20px;
border-radius: 4px;
background: $ui-base-color;
box-shadow: 0 0 15px rgba($base-shadow-color, 0.2);
}
.contact-widget,
.landing-page__information.contact-widget {
box-sizing: border-box;
padding: 20px;
min-height: 100%;
border-radius: 4px;
background: $ui-base-color;
box-shadow: 0 0 15px rgba($base-shadow-color, 0.2);
}
.contact-widget {
font-size: 15px;
color: $darker-text-color;
line-height: 20px;
word-wrap: break-word;
font-weight: 400;
strong {
font-weight: 500;
}
p {
margin-bottom: 10px;
&:last-child {
margin-bottom: 0;
}
}
&__mail {
margin-top: 10px;
a {
color: $primary-text-color;
text-decoration: none;
}
}
}
.moved-account-widget {
padding: 15px;
padding-bottom: 20px;
@ -152,7 +230,10 @@
}
.moved-account-widget,
.memoriam-widget {
.memoriam-widget,
.box-widget,
.contact-widget,
.landing-page__information.contact-widget {
@media screen and (max-width: $no-gap-breakpoint) {
margin-bottom: 0;
box-shadow: none;

View File

@ -30,6 +30,14 @@ export const ACCOUNT_UNMUTE_REQUEST = 'ACCOUNT_UNMUTE_REQUEST';
export const ACCOUNT_UNMUTE_SUCCESS = 'ACCOUNT_UNMUTE_SUCCESS';
export const ACCOUNT_UNMUTE_FAIL = 'ACCOUNT_UNMUTE_FAIL';
export const ACCOUNT_PIN_REQUEST = 'ACCOUNT_PIN_REQUEST';
export const ACCOUNT_PIN_SUCCESS = 'ACCOUNT_PIN_SUCCESS';
export const ACCOUNT_PIN_FAIL = 'ACCOUNT_PIN_FAIL';
export const ACCOUNT_UNPIN_REQUEST = 'ACCOUNT_UNPIN_REQUEST';
export const ACCOUNT_UNPIN_SUCCESS = 'ACCOUNT_UNPIN_SUCCESS';
export const ACCOUNT_UNPIN_FAIL = 'ACCOUNT_UNPIN_FAIL';
export const FOLLOWERS_FETCH_REQUEST = 'FOLLOWERS_FETCH_REQUEST';
export const FOLLOWERS_FETCH_SUCCESS = 'FOLLOWERS_FETCH_SUCCESS';
export const FOLLOWERS_FETCH_FAIL = 'FOLLOWERS_FETCH_FAIL';
@ -694,3 +702,69 @@ export function rejectFollowRequestFail(id, error) {
error,
};
};
export function pinAccount(id) {
return (dispatch, getState) => {
dispatch(pinAccountRequest(id));
api(getState).post(`/api/v1/accounts/${id}/pin`).then(response => {
dispatch(pinAccountSuccess(response.data));
}).catch(error => {
dispatch(pinAccountFail(error));
});
};
};
export function unpinAccount(id) {
return (dispatch, getState) => {
dispatch(unpinAccountRequest(id));
api(getState).post(`/api/v1/accounts/${id}/unpin`).then(response => {
dispatch(unpinAccountSuccess(response.data));
}).catch(error => {
dispatch(unpinAccountFail(error));
});
};
};
export function pinAccountRequest(id) {
return {
type: ACCOUNT_PIN_REQUEST,
id,
};
};
export function pinAccountSuccess(relationship) {
return {
type: ACCOUNT_PIN_SUCCESS,
relationship,
};
};
export function pinAccountFail(error) {
return {
type: ACCOUNT_PIN_FAIL,
error,
};
};
export function unpinAccountRequest(id) {
return {
type: ACCOUNT_UNPIN_REQUEST,
id,
};
};
export function unpinAccountSuccess(relationship) {
return {
type: ACCOUNT_UNPIN_SUCCESS,
relationship,
};
};
export function unpinAccountFail(error) {
return {
type: ACCOUNT_UNPIN_FAIL,
error,
};
};

View File

@ -38,13 +38,6 @@ export default class Mastodon extends React.PureComponent {
window.setTimeout(() => Notification.requestPermission(), 60 * 1000);
}
// Protocol handler
// Ask after 5 minutes
if (typeof navigator.registerProtocolHandler !== 'undefined') {
const handlerUrl = window.location.protocol + '//' + window.location.host + '/intent?uri=%s';
window.setTimeout(() => navigator.registerProtocolHandler('web+mastodon', handlerUrl, 'Mastodon'), 5 * 60 * 1000);
}
store.dispatch(showOnboardingOnce());
}

View File

@ -32,6 +32,8 @@ const messages = defineMessages({
blocks: { id: 'navigation_bar.blocks', defaultMessage: 'Blocked users' },
domain_blocks: { id: 'navigation_bar.domain_blocks', defaultMessage: 'Hidden domains' },
mutes: { id: 'navigation_bar.mutes', defaultMessage: 'Muted users' },
endorse: { id: 'account.endorse', defaultMessage: 'Feature on profile' },
unendorse: { id: 'account.unendorse', defaultMessage: 'Don\'t feature on profile' },
});
@injectIntl
@ -48,6 +50,7 @@ export default class ActionBar extends React.PureComponent {
onMute: PropTypes.func.isRequired,
onBlockDomain: PropTypes.func.isRequired,
onUnblockDomain: PropTypes.func.isRequired,
onEndorseToggle: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired,
};
@ -93,6 +96,9 @@ export default class ActionBar extends React.PureComponent {
} else {
menu.push({ text: intl.formatMessage(messages.showReblogs, { name: account.get('username') }), action: this.props.onReblogToggle });
}
menu.push({ text: intl.formatMessage(account.getIn(['relationship', 'endorsed']) ? messages.unendorse : messages.endorse), action: this.props.onEndorseToggle });
menu.push(null);
}
if (account.getIn(['relationship', 'muting'])) {

View File

@ -22,6 +22,7 @@ export default class Header extends ImmutablePureComponent {
onMute: PropTypes.func.isRequired,
onBlockDomain: PropTypes.func.isRequired,
onUnblockDomain: PropTypes.func.isRequired,
onEndorseToggle: PropTypes.func.isRequired,
hideTabs: PropTypes.bool,
};
@ -73,6 +74,10 @@ export default class Header extends ImmutablePureComponent {
this.props.onUnblockDomain(domain);
}
handleEndorseToggle = () => {
this.props.onEndorseToggle(this.props.account);
}
render () {
const { account, hideTabs } = this.props;
@ -100,6 +105,7 @@ export default class Header extends ImmutablePureComponent {
onMute={this.handleMute}
onBlockDomain={this.handleBlockDomain}
onUnblockDomain={this.handleUnblockDomain}
onEndorseToggle={this.handleEndorseToggle}
/>
{!hideTabs && (

View File

@ -8,6 +8,8 @@ import {
blockAccount,
unblockAccount,
unmuteAccount,
pinAccount,
unpinAccount,
} from '../../../actions/accounts';
import {
mentionCompose,
@ -82,6 +84,14 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
}
},
onEndorseToggle (account) {
if (account.getIn(['relationship', 'endorsed'])) {
dispatch(unpinAccount(account.get('id')));
} else {
dispatch(pinAccount(account.get('id')));
}
},
onReport (account) {
dispatch(initReport(account));
},

View File

@ -2,7 +2,7 @@
"account.badges.bot": "Bot",
"account.block": "Blokuj @{name}",
"account.block_domain": "Blokuj wszystko z {domain}",
"account.blocked": "Zablokowany",
"account.blocked": "Zablokowany(-a)",
"account.direct": "Wyślij wiadomość bezpośrednią do @{name}",
"account.disclaimer_full": "Poniższe informacje mogą nie odwzorowywać bezbłędnie profilu użytkownika.",
"account.domain_blocked": "Ukryto domenę",
@ -14,7 +14,7 @@
"account.hide_reblogs": "Ukryj podbicia od @{name}",
"account.media": "Zawartość multimedialna",
"account.mention": "Wspomnij o @{name}",
"account.moved_to": "{name} przeniósł się do:",
"account.moved_to": "{name} przeniósł(-osła) się do:",
"account.mute": "Wycisz @{name}",
"account.mute_notifications": "Wycisz powiadomienia o @{name}",
"account.muted": "Wyciszony",
@ -109,8 +109,8 @@
"emoji_button.symbols": "Symbole",
"emoji_button.travel": "Podróże i miejsca",
"empty_column.community": "Lokalna oś czasu jest pusta. Napisz coś publicznie, aby zagaić!",
"empty_column.direct": "Nie masz żadnych wiadomości bezpośrednich. Jeżeli wyślesz lub otrzymasz jakąś, będzie tu widoczna.",
"empty_column.hashtag": "Nie ma wpisów oznaczonych tym hashtagiem. Możesz napisać pierwszy!",
"empty_column.direct": "Nie masz żadnych wiadomości bezpośrednich. Kiedy dostaniesz lub wyślesz jakąś, pojawi się ona tutaj.",
"empty_column.hashtag": "Nie ma wpisów oznaczonych tym hashtagiem. Możesz napisać pierwszy(-a)!",
"empty_column.home": "Nie śledzisz nikogo. Odwiedź globalną oś czasu lub użyj wyszukiwarki, aby znaleźć interesujące Cię profile.",
"empty_column.home.public_timeline": "globalna oś czasu",
"empty_column.list": "Nie ma nic na tej liście. Kiedy członkowie listy dodadzą nowe wpisy, pojawia się one tutaj.",
@ -139,7 +139,7 @@
"keyboard_shortcuts.favourite": "aby dodać do ulubionych",
"keyboard_shortcuts.heading": "Skróty klawiszowe",
"keyboard_shortcuts.hotkey": "Klawisz",
"keyboard_shortcuts.legend": "aby wyświetlić tą legendę",
"keyboard_shortcuts.legend": "aby wyświetlić tę legendę",
"keyboard_shortcuts.mention": "aby wspomnieć o autorze",
"keyboard_shortcuts.profile": "aby przejść do profilu autora wpisu",
"keyboard_shortcuts.reply": "aby odpowiedzieć",
@ -184,10 +184,10 @@
"navigation_bar.preferences": "Preferencje",
"navigation_bar.public_timeline": "Globalna oś czasu",
"navigation_bar.security": "Bezpieczeństwo",
"notification.favourite": "{name} dodał Twój wpis do ulubionych",
"notification.follow": "{name} zaczął Cię śledzić",
"notification.mention": "{name} wspomniał o tobie",
"notification.reblog": "{name} podbił Twój wpis",
"notification.favourite": "{name} dodał(a) Twój wpis do ulubionych",
"notification.follow": "{name} zaczął(-ęła) Cię śledzić",
"notification.mention": "{name} wspomniał(a) o tobie",
"notification.reblog": "{name} podbił(a) Twój wpis",
"notifications.clear": "Wyczyść powiadomienia",
"notifications.clear_confirmation": "Czy na pewno chcesz bezpowrotnie usunąć wszystkie powiadomienia?",
"notifications.column_settings.alert": "Powiadomienia na pulpicie",
@ -246,7 +246,7 @@
"report.target": "Zgłaszanie {target}",
"search.placeholder": "Szukaj",
"search_popout.search_format": "Zaawansowane wyszukiwanie",
"search_popout.tips.full_text": "Pozwala na wyszukiwanie wpisów które napisałeś, dodałeś do ulubionych, podbiłeś w których o Tobie wspomniano, oraz pasujące nazwy użytkowników, pełne nazwy i hashtagi.",
"search_popout.tips.full_text": "Pozwala na wyszukiwanie wpisów które napisałeś(-aś), dodałeś(-aś) do ulubionych lub podbiłeś(-aś), w których o Tobie wspomniano, oraz pasujące nazwy użytkowników, pełne nazwy i hashtagi.",
"search_popout.tips.hashtag": "hashtag",
"search_popout.tips.status": "wpis",
"search_popout.tips.text": "Proste wyszukiwanie pasujących pseudonimów, nazw użytkowników i hashtagów",
@ -263,7 +263,7 @@
"status.direct": "Wyślij wiadomość bezpośrednią do @{name}",
"status.embed": "Osadź",
"status.favourite": "Dodaj do ulubionych",
"status.filtered": "Filtrowany",
"status.filtered": "Filtrowany(-a)",
"status.load_more": "Załaduj więcej",
"status.media_hidden": "Zawartość multimedialna ukryta",
"status.mention": "Wspomnij o @{name}",
@ -275,7 +275,7 @@
"status.pinned": "Przypięty wpis",
"status.reblog": "Podbij",
"status.reblog_private": "Podbij dla odbiorców oryginalnego wpisu",
"status.reblogged_by": "{name} podbił",
"status.reblogged_by": "{name} podbił(a)",
"status.redraft": "Usuń i przeredaguj",
"status.reply": "Odpowiedz",
"status.replyAll": "Odpowiedz na wątek",

View File

@ -12,7 +12,7 @@
"account.follows": "Подписки",
"account.follows_you": "Подписан(а) на Вас",
"account.hide_reblogs": "Скрыть продвижения от @{name}",
"account.media": "Медиаконтент",
"account.media": "Медиа",
"account.mention": "Упомянуть",
"account.moved_to": "Ищите {name} здесь:",
"account.mute": "Заглушить",
@ -59,9 +59,9 @@
"column_header.show_settings": "Показать настройки",
"column_header.unpin": "Открепить",
"column_subheading.settings": "Настройки",
"community.column_settings.media_only": "Media Only",
"community.column_settings.media_only": "Только медиа",
"compose_form.direct_message_warning": "Этот статус будет виден только упомянутым пользователям.",
"compose_form.direct_message_warning_learn_more": "Learn more",
"compose_form.direct_message_warning_learn_more": "Узнать больше",
"compose_form.hashtag_warning": "Этот пост не будет показывается в поиске по хэштегу, т.к. он непубличный. Только публичные посты можно найти в поиске по хэштегу.",
"compose_form.lock_disclaimer": "Ваш аккаунт не {locked}. Любой человек может подписаться на Вас и просматривать посты для подписчиков.",
"compose_form.lock_disclaimer.lock": "закрыт",
@ -84,8 +84,8 @@
"confirmations.domain_block.message": "Вы на самом деле уверены, что хотите блокировать весь {domain}? В большинстве случаев нескольких отдельных блокировок или глушений достаточно.",
"confirmations.mute.confirm": "Заглушить",
"confirmations.mute.message": "Вы уверены, что хотите заглушить {name}?",
"confirmations.redraft.confirm": "Delete & redraft",
"confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.",
"confirmations.redraft.confirm": "Удалить и исправить",
"confirmations.redraft.message": "Вы уверены, что хотите удалить этот статус и превратить в черновик? Вы потеряете все ответы, продвижения и отметки 'нравится' к нему.",
"confirmations.unfollow.confirm": "Отписаться",
"confirmations.unfollow.message": "Вы уверены, что хотите отписаться от {name}?",
"embed.instructions": "Встройте этот статус на Вашем сайте, скопировав код внизу.",
@ -114,14 +114,14 @@
"empty_column.public": "Здесь ничего нет! Опубликуйте что-нибудь или подпишитесь на пользователей с других узлов, чтобы заполнить ленту.",
"follow_request.authorize": "Авторизовать",
"follow_request.reject": "Отказать",
"getting_started.developers": "Developers",
"getting_started.documentation": "Documentation",
"getting_started.find_friends": "Find friends from Twitter",
"getting_started.developers": "Для разработчиков",
"getting_started.documentation": "Документация",
"getting_started.find_friends": "Найти друзей из Twitter",
"getting_started.heading": "Добро пожаловать",
"getting_started.invite": "Invite people",
"getting_started.open_source_notice": "Mastodon - программа с открытым исходным кодом. Вы можете помочь проекту или сообщить о проблемах на GitHub по адресу {github}.",
"getting_started.security": "Security",
"getting_started.terms": "Terms of service",
"getting_started.invite": "Пригласить людей",
"getting_started.open_source_notice": "Mastodon - сервис с открытым исходным кодом. Вы можете помочь проекту или сообщить о проблемах на GitHub по адресу {github}.",
"getting_started.security": "Безопасность",
"getting_started.terms": "Условия использования",
"home.column_settings.basic": "Основные",
"home.column_settings.show_reblogs": "Показывать продвижения",
"home.column_settings.show_replies": "Показывать ответы",
@ -137,7 +137,7 @@
"keyboard_shortcuts.hotkey": "Гор. клавиша",
"keyboard_shortcuts.legend": "показать это окно",
"keyboard_shortcuts.mention": "упомянуть автора поста",
"keyboard_shortcuts.profile": "to open author's profile",
"keyboard_shortcuts.profile": "перейти к профилю автора",
"keyboard_shortcuts.reply": "ответить",
"keyboard_shortcuts.search": "перейти к поиску",
"keyboard_shortcuts.toggle_hidden": "показать/скрыть текст за предупреждением",
@ -163,22 +163,22 @@
"navigation_bar.blocks": "Список блокировки",
"navigation_bar.community_timeline": "Локальная лента",
"navigation_bar.direct": "Личные сообщения",
"navigation_bar.discover": "Discover",
"navigation_bar.discover": "Изучайте",
"navigation_bar.domain_blocks": "Скрытые домены",
"navigation_bar.edit_profile": "Изменить профиль",
"navigation_bar.favourites": "Понравившееся",
"navigation_bar.filters": "Muted words",
"navigation_bar.filters": "Заглушенные слова",
"navigation_bar.follow_requests": "Запросы на подписку",
"navigation_bar.info": "Об узле",
"navigation_bar.keyboard_shortcuts": "Сочетания клавиш",
"navigation_bar.lists": "Списки",
"navigation_bar.logout": "Выйти",
"navigation_bar.mutes": "Список глушения",
"navigation_bar.personal": "Personal",
"navigation_bar.personal": "Личное",
"navigation_bar.pins": "Закреплённые посты",
"navigation_bar.preferences": "Опции",
"navigation_bar.public_timeline": "Глобальная лента",
"navigation_bar.security": "Security",
"navigation_bar.security": "Безопасность",
"notification.favourite": "{name} понравился Ваш статус",
"notification.follow": "{name} подписался(-лась) на Вас",
"notification.mention": "{name} упомянул(а) Вас",
@ -194,7 +194,7 @@
"notifications.column_settings.reblog": "Продвижения:",
"notifications.column_settings.show": "Показывать в колонке",
"notifications.column_settings.sound": "Проигрывать звук",
"notifications.group": "{count} notifications",
"notifications.group": "{count} уведомл.",
"onboarding.done": "Готово",
"onboarding.next": "Далее",
"onboarding.page_five.public_timelines": "Локальная лента показывает публичные посты всех пользователей {domain}. Глобальная лента показывает публичные посты всех людей, на которых подписаны пользователи {domain}. Это - публичные ленты, отличный способ найти новые знакомства.",
@ -258,9 +258,9 @@
"status.direct": "Написать @{name}",
"status.embed": "Встроить",
"status.favourite": "Нравится",
"status.filtered": "Filtered",
"status.filtered": "Отфильтровано",
"status.load_more": "Показать еще",
"status.media_hidden": "Медиаконтент скрыт",
"status.media_hidden": "Медиа скрыто",
"status.mention": "Упомянуть @{name}",
"status.more": "Больше",
"status.mute": "Заглушить @{name}",
@ -271,7 +271,7 @@
"status.reblog": "Продвинуть",
"status.reblog_private": "Продвинуть для своей аудитории",
"status.reblogged_by": "{name} продвинул(а)",
"status.redraft": "Delete & re-draft",
"status.redraft": "Удалить и повторить",
"status.reply": "Ответить",
"status.replyAll": "Ответить на тред",
"status.report": "Пожаловаться",
@ -289,7 +289,7 @@
"tabs_bar.local_timeline": "Локальная",
"tabs_bar.notifications": "Уведомления",
"tabs_bar.search": "Поиск",
"trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
"trends.count_by_accounts": "Популярно у {count} {rawCount, plural, one {человека} few {человек} many {человек} other {человек}}",
"ui.beforeunload": "Ваш черновик будет утерян, если вы покинете Mastodon.",
"upload_area.title": "Перетащите сюда, чтобы загрузить",
"upload_button.label": "Добавить медиаконтент",

View File

@ -5,6 +5,8 @@ import {
ACCOUNT_UNBLOCK_SUCCESS,
ACCOUNT_MUTE_SUCCESS,
ACCOUNT_UNMUTE_SUCCESS,
ACCOUNT_PIN_SUCCESS,
ACCOUNT_UNPIN_SUCCESS,
RELATIONSHIPS_FETCH_SUCCESS,
} from '../actions/accounts';
import {
@ -41,6 +43,8 @@ export default function relationships(state = initialState, action) {
case ACCOUNT_UNBLOCK_SUCCESS:
case ACCOUNT_MUTE_SUCCESS:
case ACCOUNT_UNMUTE_SUCCESS:
case ACCOUNT_PIN_SUCCESS:
case ACCOUNT_UNPIN_SUCCESS:
return normalizeRelationship(state, action.relationship);
case RELATIONSHIPS_FETCH_SUCCESS:
return normalizeRelationships(state, action.relationships);

View File

@ -15,6 +15,7 @@ function main() {
const React = require('react');
const ReactDOM = require('react-dom');
const Rellax = require('rellax');
const createHistory = require('history').createBrowserHistory;
ready(() => {
const locale = document.documentElement.lang;
@ -70,6 +71,14 @@ function main() {
}
new Rellax('.parallax', { speed: -1 });
const history = createHistory();
const detailedStatuses = document.querySelectorAll('.public-layout .detailed-status');
const location = history.location;
if (detailedStatuses.length === 1 && (!location.state || !location.state.scrolledToDetailedStatus)) {
detailedStatuses[0].scrollIntoView();
history.replace(location.pathname, { ...location.state, scrolledToDetailedStatus: true });
}
});
}

View File

@ -15,6 +15,276 @@ $small-breakpoint: 960px;
}
}
.rich-formatting {
font-family: 'mastodon-font-sans-serif', sans-serif;
font-size: 16px;
font-weight: 400;
font-size: 16px;
line-height: 30px;
color: $darker-text-color;
padding-right: 10px;
a {
color: $highlight-text-color;
text-decoration: underline;
}
p,
li {
font-family: 'mastodon-font-sans-serif', sans-serif;
font-size: 16px;
font-weight: 400;
font-size: 16px;
line-height: 30px;
margin-bottom: 12px;
color: $darker-text-color;
a {
color: $highlight-text-color;
text-decoration: underline;
}
&:last-child {
margin-bottom: 0;
}
}
em {
display: inline;
margin: 0;
padding: 0;
font-weight: 700;
background: transparent;
font-family: inherit;
font-size: inherit;
line-height: inherit;
color: lighten($darker-text-color, 10%);
}
h1 {
font-family: 'mastodon-font-display', sans-serif;
font-size: 26px;
line-height: 30px;
font-weight: 500;
margin-bottom: 20px;
color: $secondary-text-color;
small {
font-family: 'mastodon-font-sans-serif', sans-serif;
display: block;
font-size: 18px;
font-weight: 400;
color: lighten($darker-text-color, 10%);
}
}
h2 {
font-family: 'mastodon-font-display', sans-serif;
font-size: 22px;
line-height: 26px;
font-weight: 500;
margin-bottom: 20px;
color: $secondary-text-color;
}
h3 {
font-family: 'mastodon-font-display', sans-serif;
font-size: 18px;
line-height: 24px;
font-weight: 500;
margin-bottom: 20px;
color: $secondary-text-color;
}
h4 {
font-family: 'mastodon-font-display', sans-serif;
font-size: 16px;
line-height: 24px;
font-weight: 500;
margin-bottom: 20px;
color: $secondary-text-color;
}
h5 {
font-family: 'mastodon-font-display', sans-serif;
font-size: 14px;
line-height: 24px;
font-weight: 500;
margin-bottom: 20px;
color: $secondary-text-color;
}
h6 {
font-family: 'mastodon-font-display', sans-serif;
font-size: 12px;
line-height: 24px;
font-weight: 500;
margin-bottom: 20px;
color: $secondary-text-color;
}
ul,
ol {
margin-left: 20px;
&[type='a'] {
list-style-type: lower-alpha;
}
&[type='i'] {
list-style-type: lower-roman;
}
}
ul {
list-style: disc;
}
ol {
list-style: decimal;
}
li > ol,
li > ul {
margin-top: 6px;
}
hr {
width: 100%;
height: 0;
border: 0;
border-bottom: 1px solid rgba($ui-base-lighter-color, .6);
margin: 20px 0;
&.spacer {
height: 1px;
border: 0;
}
}
}
.information-board {
background: darken($ui-base-color, 4%);
padding: 20px 0;
.container-alt {
position: relative;
padding-right: 280px + 15px;
}
&__sections {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
&__section {
flex: 1 0 0;
font-family: 'mastodon-font-sans-serif', sans-serif;
font-size: 16px;
line-height: 28px;
color: $primary-text-color;
text-align: right;
padding: 10px 15px;
span,
strong {
display: block;
}
span {
&:last-child {
color: $secondary-text-color;
}
}
strong {
font-weight: 500;
font-size: 32px;
line-height: 48px;
}
@media screen and (max-width: $column-breakpoint) {
text-align: center;
}
}
.panel {
position: absolute;
width: 280px;
box-sizing: border-box;
background: darken($ui-base-color, 8%);
padding: 20px;
padding-top: 10px;
border-radius: 4px 4px 0 0;
right: 0;
bottom: -40px;
.panel-header {
font-family: 'mastodon-font-display', sans-serif;
font-size: 14px;
line-height: 24px;
font-weight: 500;
color: $darker-text-color;
padding-bottom: 5px;
margin-bottom: 15px;
border-bottom: 1px solid lighten($ui-base-color, 4%);
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
a,
span {
font-weight: 400;
color: darken($darker-text-color, 10%);
}
a {
text-decoration: none;
}
}
}
.owner {
text-align: center;
.avatar {
width: 80px;
height: 80px;
margin: 0 auto;
margin-bottom: 15px;
img {
display: block;
width: 80px;
height: 80px;
border-radius: 48px;
}
}
.name {
font-size: 14px;
a {
display: block;
color: $primary-text-color;
text-decoration: none;
&:hover {
.display_name {
text-decoration: underline;
}
}
}
.username {
display: block;
color: $darker-text-color;
}
}
}
}
.landing-page {
.grid {
display: grid;
@ -486,128 +756,6 @@ $small-breakpoint: 960px;
}
}
.information-board {
background: darken($ui-base-color, 4%);
padding: 20px 0;
.container-alt {
position: relative;
padding-right: 280px + 15px;
}
&__sections {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
&__section {
flex: 1 0 0;
font-family: 'mastodon-font-sans-serif', sans-serif;
font-size: 16px;
line-height: 28px;
color: $primary-text-color;
text-align: right;
padding: 10px 15px;
span,
strong {
display: block;
}
span {
&:last-child {
color: $secondary-text-color;
}
}
strong {
font-weight: 500;
font-size: 32px;
line-height: 48px;
}
@media screen and (max-width: $column-breakpoint) {
text-align: center;
}
}
.panel {
position: absolute;
width: 280px;
box-sizing: border-box;
background: darken($ui-base-color, 8%);
padding: 20px;
padding-top: 10px;
border-radius: 4px 4px 0 0;
right: 0;
bottom: -40px;
.panel-header {
font-family: 'mastodon-font-display', sans-serif;
font-size: 14px;
line-height: 24px;
font-weight: 500;
color: $darker-text-color;
padding-bottom: 5px;
margin-bottom: 15px;
border-bottom: 1px solid lighten($ui-base-color, 4%);
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
a,
span {
font-weight: 400;
color: darken($darker-text-color, 10%);
}
a {
text-decoration: none;
}
}
}
.owner {
text-align: center;
.avatar {
width: 80px;
height: 80px;
margin: 0 auto;
margin-bottom: 15px;
img {
display: block;
width: 80px;
height: 80px;
border-radius: 48px;
}
}
.name {
font-size: 14px;
a {
display: block;
color: $primary-text-color;
text-decoration: none;
&:hover {
.display_name {
text-decoration: underline;
}
}
}
.username {
display: block;
color: $darker-text-color;
}
}
}
}
&.alternative {
padding: 10px 0;
@ -642,8 +790,10 @@ $small-breakpoint: 960px;
border-radius: 4px;
padding: 25px 40px;
overflow: hidden;
box-sizing: border-box;
.row {
width: 100%;
display: flex;
flex-direction: row-reverse;
flex-wrap: wrap;
@ -660,11 +810,20 @@ $small-breakpoint: 960px;
flex: 1 0 auto;
padding: 0 10px;
}
@media screen and (max-width: $no-gap-breakpoint) {
width: 100%;
justify-content: space-between;
}
}
.row__mascot {
flex: 1;
margin: 10px -50px 0 0;
@media screen and (max-width: $no-gap-breakpoint) {
display: none;
}
}
}
@ -983,21 +1142,6 @@ $small-breakpoint: 960px;
}
}
.extended-description {
padding: 50px 0;
font-family: 'mastodon-font-sans-serif', sans-serif;
font-size: 16px;
font-weight: 400;
font-size: 16px;
line-height: 30px;
color: $darker-text-color;
a {
color: $highlight-text-color;
text-decoration: underline;
}
}
.footer-links {
padding-bottom: 50px;
text-align: right;

View File

@ -115,6 +115,83 @@
}
}
.grid-3 {
display: grid;
grid-gap: 10px;
grid-template-columns: 3fr 1fr;
grid-auto-columns: 25%;
grid-auto-rows: max-content;
.column-0 {
grid-column: 1/3;
grid-row: 1;
}
.column-1 {
grid-column: 1;
grid-row: 2;
}
.column-2 {
grid-column: 2;
grid-row: 2;
}
.column-3 {
grid-column: 1/3;
grid-row: 3;
}
.landing-page__call-to-action {
min-height: 100%;
}
@media screen and (max-width: 738px) {
grid-template-columns: minmax(0, 50%) minmax(0, 50%);
.landing-page__call-to-action {
padding: 20px;
display: flex;
align-items: center;
justify-content: center;
}
.row__information-board {
width: 100%;
justify-content: center;
align-items: center;
}
.row__mascot {
display: none;
}
}
@media screen and (max-width: $no-gap-breakpoint) {
grid-gap: 0;
grid-template-columns: minmax(0, 100%);
.column-0 {
grid-column: 1;
}
.column-1 {
grid-column: 1;
grid-row: 3;
}
.column-2 {
grid-column: 1;
grid-row: 2;
}
.column-3 {
grid-column: 1;
grid-row: 4;
}
}
}
.public-layout {
@media screen and (max-width: $no-gap-breakpoint) {
padding-top: 48px;
@ -300,6 +377,19 @@
}
}
&--no-bar {
margin-bottom: 0;
.public-account-header__image,
.public-account-header__image img {
border-radius: 4px;
@media screen and (max-width: $no-gap-breakpoint) {
border-radius: 0;
}
}
}
@media screen and (max-width: $no-gap-breakpoint) {
margin-bottom: 0;
box-shadow: none;

View File

@ -71,6 +71,84 @@
}
}
.endorsements-widget {
margin-bottom: 10px;
padding-bottom: 10px;
h4 {
padding: 10px;
text-transform: uppercase;
font-weight: 700;
font-size: 13px;
color: $darker-text-color;
}
.account {
padding: 10px 0;
&:last-child {
border-bottom: 0;
}
.account__display-name {
display: flex;
align-items: center;
}
.account__avatar {
width: 44px;
height: 44px;
background-size: 44px 44px;
}
}
}
.box-widget {
padding: 20px;
border-radius: 4px;
background: $ui-base-color;
box-shadow: 0 0 15px rgba($base-shadow-color, 0.2);
}
.contact-widget,
.landing-page__information.contact-widget {
box-sizing: border-box;
padding: 20px;
min-height: 100%;
border-radius: 4px;
background: $ui-base-color;
box-shadow: 0 0 15px rgba($base-shadow-color, 0.2);
}
.contact-widget {
font-size: 15px;
color: $darker-text-color;
line-height: 20px;
word-wrap: break-word;
font-weight: 400;
strong {
font-weight: 500;
}
p {
margin-bottom: 10px;
&:last-child {
margin-bottom: 0;
}
}
&__mail {
margin-top: 10px;
a {
color: $primary-text-color;
text-decoration: none;
}
}
}
.moved-account-widget {
padding: 15px;
padding-bottom: 20px;
@ -152,7 +230,10 @@
}
.moved-account-widget,
.memoriam-widget {
.memoriam-widget,
.box-widget,
.contact-widget,
.landing-page__information.contact-widget {
@media screen and (max-width: $no-gap-breakpoint) {
margin-bottom: 0;
box-shadow: none;

View File

@ -352,7 +352,7 @@ class OStatus::AtomSerializer
append_element(entry, 'link', nil, rel: :alternate, type: 'application/activity+json', href: ActivityPub::TagManager.instance.uri_for(status)) if status.account.local?
append_element(entry, 'summary', status.spoiler_text, 'xml:lang': status.language) if status.spoiler_text?
append_element(entry, 'content', Formatter.instance.format(status).to_str, type: 'html', 'xml:lang': status.language)
append_element(entry, 'content', Formatter.instance.format(status).to_str || '.', type: 'html', 'xml:lang': status.language)
status.mentions.sort_by(&:id).each do |mentioned|
append_element(entry, 'link', nil, rel: :mentioned, 'ostatus:object-type': OStatus::TagManager::TYPES[:person], href: OStatus::TagManager.instance.uri_for(mentioned.account))

View File

@ -92,6 +92,10 @@ class Account < ApplicationRecord
has_many :status_pins, inverse_of: :account, dependent: :destroy
has_many :pinned_statuses, -> { reorder('status_pins.created_at DESC') }, through: :status_pins, class_name: 'Status', source: :status
# Endorsements
has_many :account_pins, inverse_of: :account, dependent: :destroy
has_many :endorsed_accounts, through: :account_pins, class_name: 'Account', source: :target_account
# Media
has_many :media_attachments, dependent: :destroy

26
app/models/account_pin.rb Normal file
View File

@ -0,0 +1,26 @@
# frozen_string_literal: true
# == Schema Information
#
# Table name: account_pins
#
# id :bigint(8) not null, primary key
# account_id :bigint(8)
# target_account_id :bigint(8)
# created_at :datetime not null
# updated_at :datetime not null
#
class AccountPin < ApplicationRecord
include RelationshipCacheable
belongs_to :account
belongs_to :target_account, class_name: 'Account'
validate :validate_follow_relationship
private
def validate_follow_relationship
errors.add(:base, I18n.t('accounts.pin_errors.following')) unless account.following?(target_account)
end
end

View File

@ -40,6 +40,10 @@ module AccountInteractions
end
end
def endorsed_map(target_account_ids, account_id)
follow_mapping(AccountPin.where(account_id: account_id, target_account_id: target_account_ids), :target_account_id)
end
def domain_blocking_map(target_account_ids, account_id)
accounts_map = Account.where(id: target_account_ids).select('id, domain').map { |a| [a.id, a.domain] }.to_h
blocked_domains = domain_blocking_map_by_domain(accounts_map.values.compact, account_id)
@ -194,6 +198,10 @@ module AccountInteractions
status_pins.where(status: status).exists?
end
def endorsed?(account)
account_pins.where(target_account: account).exists?
end
def followers_for_local_distribution
followers.local
.joins(:user)

View File

@ -33,10 +33,15 @@ class Follow < ApplicationRecord
end
before_validation :set_uri, only: :create
after_destroy :remove_endorsements
private
def set_uri
self.uri = ActivityPub::TagManager.instance.generate_uri_for(self) if uri.nil?
end
def remove_endorsements
AccountPin.where(target_account_id: target_account_id, account_id: account_id).delete_all
end
end

View File

@ -2,7 +2,8 @@
class AccountRelationshipsPresenter
attr_reader :following, :followed_by, :blocking,
:muting, :requested, :domain_blocking
:muting, :requested, :domain_blocking,
:endorsed
def initialize(account_ids, current_account_id, **options)
@account_ids = account_ids.map { |a| a.is_a?(Account) ? a.id : a }
@ -14,6 +15,7 @@ class AccountRelationshipsPresenter
@muting = cached[:muting].merge(Account.muting_map(@uncached_account_ids, @current_account_id))
@requested = cached[:requested].merge(Account.requested_map(@uncached_account_ids, @current_account_id))
@domain_blocking = cached[:domain_blocking].merge(Account.domain_blocking_map(@uncached_account_ids, @current_account_id))
@endorsed = cached[:endorsed].merge(Account.endorsed_map(@uncached_account_ids, @current_account_id))
cache_uncached!
@ -23,6 +25,7 @@ class AccountRelationshipsPresenter
@muting.merge!(options[:muting_map] || {})
@requested.merge!(options[:requested_map] || {})
@domain_blocking.merge!(options[:domain_blocking_map] || {})
@endorsed.merge!(options[:endorsed_map] || {})
end
private
@ -37,6 +40,7 @@ class AccountRelationshipsPresenter
muting: {},
requested: {},
domain_blocking: {},
endorsed: {},
}
@uncached_account_ids = []
@ -63,6 +67,7 @@ class AccountRelationshipsPresenter
muting: { account_id => muting[account_id] },
requested: { account_id => requested[account_id] },
domain_blocking: { account_id => domain_blocking[account_id] },
endorsed: { account_id => endorsed[account_id] },
}
Rails.cache.write("relationship:#{@current_account_id}:#{account_id}", maps_for_account, expires_in: 1.day)

View File

@ -2,7 +2,8 @@
class REST::RelationshipSerializer < ActiveModel::Serializer
attributes :id, :following, :showing_reblogs, :followed_by, :blocking,
:muting, :muting_notifications, :requested, :domain_blocking
:muting, :muting_notifications, :requested, :domain_blocking,
:endorsed
def id
object.id.to_s
@ -41,4 +42,8 @@ class REST::RelationshipSerializer < ActiveModel::Serializer
def domain_blocking
instance_options[:relationships].domain_blocking[object.id] || false
end
def endorsed
instance_options[:relationships].endorsed[object.id] || false
end
end

View File

@ -1,19 +0,0 @@
.account
.account__wrapper
- if @instance_presenter.contact_account
= link_to TagManager.instance.url_for(@instance_presenter.contact_account), class: 'account__display-name' do
.account__avatar-wrapper
.account__avatar{ style: "background-image: url(#{@instance_presenter.contact_account.avatar.url})" }
%span.display-name
%bdi
%strong.display-name__html.emojify= display_name(@instance_presenter.contact_account, custom_emojify: true)
%span.display-name__account @#{@instance_presenter.contact_account.acct}
- else
.account__display-name
.account__avatar-wrapper
.account__avatar{ style: "background-image: url(#{full_asset_url('avatars/original/missing.png', skip_pipeline: true)})" }
%span.display-name
%strong= t 'about.contact_missing'
%span.display-name__account= t 'about.contact_unavailable'
= link_to t('about.learn_more'), about_more_path, class: 'button button-alternative'

View File

@ -1,22 +0,0 @@
.panel
.panel-header
= succeed ':' do
= t 'about.contact'
- if contact.site_contact_email.present?
= mail_to contact.site_contact_email, nil, title: contact.site_contact_email
- else
%span= t 'about.contact_unavailable'
.panel-body
- if contact.contact_account
.owner
.avatar= image_tag contact.contact_account.avatar.url
.name
= link_to TagManager.instance.url_for(contact.contact_account) do
%span.display_name.emojify= display_name(contact.contact_account, custom_emojify: true)
%span.username @#{contact.contact_account.acct}
- else
.owner
.avatar= image_tag full_asset_url('avatars/original/missing.png', skip_pipeline: true)
.name
%span.display_name= t 'about.contact_missing'
%span.username= t 'about.contact_unavailable'

View File

@ -4,43 +4,43 @@
- content_for :header_tags do
= render partial: 'shared/og'
.landing-page
.header-wrapper.compact
.header
= render 'links'
.grid-3
.column-0
.public-account-header.public-account-header--no-bar
.public-account-header__image
= image_tag @instance_presenter.hero&.file&.url || @instance_presenter.thumbnail&.file&.url || asset_pack_path('preview.jpg'), alt: @instance_presenter.site_title, class: 'parallax'
.container-alt.hero
.heading
%h3= t('about.description_headline', domain: site_hostname)
%p= @instance_presenter.site_description.html_safe.presence || t('about.generic_description', domain: site_hostname)
.column-1
.landing-page__call-to-action{ dir: 'ltr' }
.row
.row__information-board
.information-board__section
%span= t 'about.user_count_before'
%strong= number_with_delimiter @instance_presenter.user_count
%span= t 'about.user_count_after'
.information-board__section
%span= t 'about.status_count_before'
%strong= number_with_delimiter @instance_presenter.status_count
%span= t 'about.status_count_after'
.row__mascot
.landing-page__mascot
= image_tag asset_pack_path('elephant_ui_plane.svg')
.information-board
.container-alt
.information-board__sections
.information-board__section
%span= t 'about.user_count_before'
%strong= number_with_delimiter @instance_presenter.user_count
%span= t 'about.user_count_after'
.information-board__section
%span= t 'about.status_count_before'
%strong= number_with_delimiter @instance_presenter.status_count
%span= t 'about.status_count_after'
.information-board__section
%span= t 'about.domain_count_before'
%strong= number_with_delimiter @instance_presenter.domain_count
%span= t 'about.domain_count_after'
= render 'contact', contact: @instance_presenter
.extended-description
.container-alt
= @instance_presenter.site_extended_description.html_safe.presence || t('about.extended_description_html')
.footer-links
.container-alt
.column-2
.landing-page__information.contact-widget
%p
= link_to t('about.source_code'), @instance_presenter.source_url
- if @instance_presenter.commit_hash == ""
%strong= " (#{@instance_presenter.version_number})"
- else
%strong= "#{@instance_presenter.version_number}, "
%strong= "#{@instance_presenter.commit_hash}"
%strong= t 'about.administered_by'
= account_link_to(@instance_presenter.contact_account)
- if @instance_presenter.site_contact_email.present?
%p.contact-widget__mail
%strong
= succeed ':' do
= t 'about.contact'
%br/
= mail_to @instance_presenter.site_contact_email, nil, title: @instance_presenter.site_contact_email
.column-3
.box-widget
.rich-formatting= @instance_presenter.site_extended_description.html_safe.presence || t('about.extended_description_html')

View File

@ -109,7 +109,7 @@
%p= t 'about.about_mastodon_html'
%div.contact
%h3= t 'about.administered_by'
= render 'administration'
= account_link_to(@instance_presenter.contact_account, link_to(t('about.learn_more'), about_more_path, class: 'button button-alternative'))
= render 'features'
@ -130,7 +130,7 @@
%p= t 'about.about_mastodon_html'
%div.contact
%h3= t 'about.administered_by'
= render 'administration'
= account_link_to(@instance_presenter.contact_account, link_to(t('about.learn_more'), about_more_path, class: 'button button-alternative'))
= render 'features'

View File

@ -1,11 +1,9 @@
- content_for :page_title do
= t('terms.title', instance: site_hostname)
.landing-page
.header-wrapper.compact
.header
= render 'links'
.extended-description
.container-alt
= @instance_presenter.site_terms.html_safe.presence || t('terms.body_html')
.grid
.column-0
.box-widget
.rich-formatting= @instance_presenter.site_terms.html_safe.presence || t('terms.body_html')
.column-1
= render 'application/sidebar'

View File

@ -7,7 +7,7 @@
.public-account-header__tabs
.public-account-header__tabs__name
%h1
= display_name(account)
= display_name(account, custom_emojify: true)
%small
= acct(account)
= fa_icon('lock') if account.locked?

View File

@ -55,4 +55,12 @@
= render 'moved', account: @account
= render 'bio', account: @account
- unless @endorsed_accounts.empty?
.endorsements-widget
%h4= t 'accounts.choices_html', name: content_tag(:bdi, display_name(@account, custom_emojify: true))
- @endorsed_accounts.each do |account|
= account_link_to account
= render 'application/sidebar'

View File

@ -9,9 +9,6 @@ ar:
contact: للتواصل معنا
contact_missing: غير محدد
contact_unavailable: غير متوفر
description_headline: ما هو %{domain}?
domain_count_after: خوادم أخرى
domain_count_before: متصل بـ
extended_description_html: |
<h3>مكان جيد للقواعد</h3>
<p>لا يوجد تفصيل طويل حتى الآن.</p>

View File

@ -3,8 +3,6 @@ ast:
about:
about_mastodon_html: Mastodon ye una rede social basada en protocolos abiertos y software de códigu llibre. Ye descentralizada, como'l corréu electrónicu.
contact_unavailable: N/D
description_headline: "¿Qué ye %{domain}?"
domain_count_after: otres instancies
features:
not_a_product_title: Yes una persona, non un productu
source_code: Códigu fonte

View File

@ -5,9 +5,6 @@ bg:
about_this: За тази инстанция
closed_registrations: В момента регистрациите за тази инстанция са затворени.
contact: За контакти
description_headline: Какво е %{domain}?
domain_count_after: други инстанции
domain_count_before: Свързани към
other_instances: Други инстанции
source_code: Програмен код
status_count_after: публикации

View File

@ -9,9 +9,6 @@ ca:
contact: Contacte
contact_missing: No configurat
contact_unavailable: N/D
description_headline: Què es %{domain}?
domain_count_after: altres instàncies
domain_count_before: Connectada a
extended_description_html: |
<h3>Un bon lloc per les regles</h3>
<p>Encara no s'ha configurat la descripció ampliada.</p>

View File

@ -9,9 +9,6 @@ co:
contact: Cuntattu
contact_missing: Mancante
contact_unavailable: Micca dispunibule
description_headline: Quale hè %{domain} ?
domain_count_after: altre istanze
domain_count_before: Cunnettati à
extended_description_html: |
<h3>Una bona piazza per e regule</h3>
<p>A descrizzione stesa ùn hè micca stata riempiuta.</p>

View File

@ -9,9 +9,6 @@ cs:
contact: Kontakt
contact_missing: Nenastaveno
contact_unavailable: Neuvedeno
description_headline: Co je %{domain}?
domain_count_after: dalším instancím
domain_count_before: Připojeno k
extended_description_html: |
<h3>Dobré místo pro pravidla</h3>
<p>Rozšířený popis ještě nebyl nastaven.</p>

View File

@ -9,9 +9,6 @@ da:
contact: Kontakt
contact_missing: Ikke sat
contact_unavailable: Ikke tilgængeligt
description_headline: Hvad er %{domain}?
domain_count_after: andre instanser
domain_count_before: Forbundet til
extended_description_html: |
<h3>Et godt sted for regler</h3>
<p>Den udvidede beskrivelse er endnu ikke blevet opsat.</p>

View File

@ -9,9 +9,6 @@ de:
contact: Kontakt
contact_missing: Nicht angegeben
contact_unavailable: N/A
description_headline: Was ist %{domain}?
domain_count_after: anderen Instanzen
domain_count_before: Vernetzt mit
extended_description_html: |
<h3>Ein guter Platz für Regeln</h3>
<p>Die erweiterte Beschreibung wurde noch nicht aufgesetzt.</p>

View File

@ -6,7 +6,7 @@ pl:
send_instructions: W ciągu kilku minut otrzymasz wiadomosć e-mail z instrukcją jak potwierdzić Twój adres e-mail. Jeżeli nie otrzymano wiadomości, sprawdź folder ze spamem.
send_paranoid_instructions: Jeśli Twój adres e-mail już istnieje w naszej bazie danych, w ciągu kilku minut otrzymasz wiadomość e-mail z instrukcją jak potwierdzić Twój adres e-mail. Jeżeli nie otrzymano wiadomości, sprawdź folder ze spamem.
failure:
already_authenticated: Jesteś już zalogowany/zalogowana.
already_authenticated: Jesteś już zalogowany(-a).
inactive: Twoje konto nie zostało jeszcze aktywowane.
invalid: Nieprawidłowy %{authentication_keys} lub hasło.
last_attempt: Masz jeszcze jedną próbę; Twoje konto zostanie zablokowane jeśli się nie powiedzie.
@ -18,28 +18,28 @@ pl:
mailer:
confirmation_instructions:
action: Zweryfikuj adres e-mail
explanation: Utworzyłeś konto na %{host} podając ten adres e-mail. Jedno kliknięcie dzieli Cię od aktywacji tego konta. Jeżeli to nie Ty, zignoruj ten e-mail.
explanation: Utworzyłeś(-aś) konto na %{host} podając ten adres e-mail. Jedno kliknięcie dzieli Cię od aktywacji tego konta. Jeżeli to nie Ty, zignoruj ten e-mail.
extra_html: Przeczytaj też <a href="%{terms_path}">regulamin instancji</a> i <a href="%{policy_path}">nasze zasady użytkowania</a>.
subject: 'Mastodon: Instrukcje weryfikacji adresu e-mail'
title: Zweryfikuj adres e-mail
email_changed:
explanation: 'Adres e-mail dla Twojego konta zostanie zmieniony na:'
extra: Jeżeli nie próbowałeś zmienić adresu e-mail, prawdopodobnie ktoś uzyskał dostęp do Twojego konta. Zmień natychmiastowo hasło lub skontaktuj się z administratorem isntancji, jeżeli nie masz dostępu do konta.
extra: Jeżeli nie próbowałeś(-aś) zmienić adresu e-mail, prawdopodobnie ktoś uzyskał dostęp do Twojego konta. Zmień natychmiastowo hasło lub skontaktuj się z administratorem isntancji, jeżeli nie masz dostępu do konta.
subject: 'Mastodon: Zmieniono adres e-mail'
title: Nowy adres e-mail
password_change:
explanation: Hasło do Twojego konta zostało zmienione.
extra: Jeżeli nie zmieniałeś hasła, prawdopodobnie ktoś uzyskał dostęp do Twojego konta. Zmień hasło natychmiastowo lub skontaktuj się z administratorem instancji, jeżeli nie masz dostępu do konta.
extra: Jeżeli nie zmieniałeś(-aś) hasła, prawdopodobnie ktoś uzyskał dostęp do Twojego konta. Zmień hasło natychmiastowo lub skontaktuj się z administratorem instancji, jeżeli nie masz dostępu do konta.
subject: 'Mastodon: Zmieniono hasło'
title: Zmieniono hasło
reconfirmation_instructions:
explanation: Potwierdź nowy adres aby zmienić e-mail.
extra: Jeżeli nie próbowałeś zmienić e-maila, zignoruj tą wiadomość. Adres e-mail przypisany do konta Mastodona nie ulegnie zmianie, jeżeli nie użyjesz powyższego odnośniku.
extra: Jeżeli nie próbowałeś(-aś) zmienić e-maila, zignoruj tą wiadomość. Adres e-mail przypisany do konta Mastodona nie ulegnie zmianie, jeżeli nie użyjesz powyższego odnośniku.
subject: 'Mastodon: Potwierdź adres e-mail na &{instance}'
title: Zweryfikuj adres e-mail
reset_password_instructions:
action: Zmień hasło
explanation: Próbowałeś uzyskać nowe hasło do swojego konta.
explanation: Próbowałeś(-aś) uzyskać nowe hasło do swojego konta.
extra: Jeżeli to nie Ty, zignoruj tą wiadomość. Twoje hasło nie ulegnie zmianie, jeżeli nie wykorzystasz powyższego odnośnika i nie utworzysz nowego hasła.
subject: 'Mastodon: Instrukcje ustawienia nowego hasła'
title: Przywracanie hasła
@ -49,10 +49,10 @@ pl:
failure: 'Uwierzytelnienie przez %{kind} nie powiodło się, ponieważ: "%{reason}".'
success: Uwierzytelnienie przez %{kind} powiodło się.
passwords:
no_token: Dostęp do tej strony możliwy jest wyłącznie za pomocą odnośnika z e-maila z instrukcjami ustawienia nowego hasła. Jeśli skorzystałeś/aś z takiego odnośnika, upewnij się, że został wykorzystany/skopiowany cały odnośnik.
no_token: Dostęp do tej strony możliwy jest wyłącznie za pomocą odnośnika z e-maila z instrukcjami ustawienia nowego hasła. Jeśli skorzystałeś(-aś) z takiego odnośnika, upewnij się, że został wykorzystany/skopiowany cały odnośnik.
send_instructions: W ciągu kilku minut otrzymasz wiadomość e-mail z instrukcją ustawienia nowego hasła. Jeżeli nie otrzymano wiadomości, sprawdź folder ze spamem.
send_paranoid_instructions: Jeśli Twój adres e-mail już istnieje w naszej bazie danych, w ciągu kilku minut otrzymasz wiadomość e-mail zawierającą odnośnik pozwalający na ustawienie nowego hasła. Jeżeli nie otrzymano wiadomości, sprawdź folder ze spamem.
updated: Twoje hasło zostało zmienione. Jesteś zalogowany/a.
updated: Twoje hasło zostało zmienione. Jesteś zalogowany(-a).
updated_not_active: Twoje hasło zostało zmienione.
registrations:
destroyed: Twoje konto zostało zawieszone. Mamy jednak nadzieję, że do nas wrócisz. Do zobaczenia!
@ -63,9 +63,9 @@ pl:
update_needs_confirmation: Konto zostało zaktualizowane, musimy jednak zweryfikować Twój nowy adres e-mail. Została na niego wysłana wiadomość z odnośnikiem potwierdzającym. Jeżeli nie otrzymano wiadomości, sprawdź folder ze spamem.
updated: Konto zostało zaktualizowane.
sessions:
already_signed_out: Zostałeś/aś wylogowany/a.
signed_in: Zostałeś/aś zalogowany/a.
signed_out: Zostałeś/aś wylogowany/a.
already_signed_out: Zostałeś(-aś) wylogowany(-a).
signed_in: Zostałeś(-aś) zalogowany(-a).
signed_out: Zostałeś(-aś) wylogowany(-a).
unlocks:
send_instructions: W ciągu kilku minut otrzymasz wiadomość e-mail z instrukcjami odblokowania konta. Jeżeli nie otrzymano wiadomości, sprawdź folder ze spamem.
send_paranoid_instructions: Jeśli Twoje konto istnieje, instrukcje odblokowania go otrzymasz w wiadomości e-mail w ciągu kilku minut. Jeżeli nie otrzymano wiadomości, sprawdź folder ze spamem.

View File

@ -90,7 +90,7 @@ pl:
revoked: Token dostępowy został unieważniony
unknown: Token dostępowy jest błędny
resource_owner_authenticator_not_configured: Wyszukiwanie właściciela zasobu nie powiodło się, ponieważ Doorkeeper.configure.resource_owner_authenticator nie został skonfigurowany.
server_error: Serwer uwierzytelniający napotkał nieoczekiwand warunki, które uniemożliwiły obsłużenie żądania.
server_error: Serwer uwierzytelniający napotkał nieoczekiwane warunki, które uniemożliwiły obsłużenie żądania.
temporarily_unavailable: Serwer uwierzytelniający nie jest obecnie w stanie obsłużyć żądania z powodu tymczasowego przeciążenia lub prac konserwacyjnych.
unauthorized_client: Klient nie jest uprawniony do wykonania tego żądania przy pomocy tej metody.
unsupported_grant_type: Ten typ grantu uwierzytelniającego nie jest wspierany przez serwer uwierzytelniający.

View File

@ -72,7 +72,7 @@ ru:
index:
application: Приложение
created_at: Авторизовано
date_format: "%Y-%m-%d %H:%M:%S"
date_format: "%d.%m.%Y %H:%M:%S"
scopes: Разрешения
title: Ваши авторизованные приложения
errors:
@ -117,4 +117,26 @@ ru:
follow: подписываться, отписываться, блокировать и разблокировать аккаунты
push: принимать push-уведомления для Вашего аккаунта
read: читать данные Вашего аккаунта
write: отправлять за Вас посты
read:accounts: видеть информацию об аккаунтах
read:blocks: видеть ваших заблокированных
read:favourites: видеть ваше избранное
read:filters: видеть ваши фильтры
read:follows: видеть, на кого вы подписаны
read:lists: видеть ваши списки
read:mutes: видеть список заглушенных
read:notifications: видеть ваши уведомления
read:reports: видеть ваши жалобы
read:search: использовать поиск
read:statuses: видеть все статусы
write: изменять все данные вашего аккаунта
write:accounts: редактировать ваш профиль
write:blocks: блокировать аккаунты и домены
write:favourites: отмечать статусы как избранные
write:filters: создавать фильтры
write:follows: подписываться на людей
write:lists: создавать списки
write:media: выкладывать медиаконтент
write:mutes: заглушать людей и обсуждения
write:notifications: очищать список уведомлений
write:reports: отправлять жалобы на других
write:statuses: публиковать статусы

View File

@ -9,9 +9,6 @@ el:
contact: Επικοινωνία
contact_missing: Δεν έχει οριστεί
contact_unavailable: Μ
description_headline: Τι είναι το %{domain};
domain_count_after: άλλους διακομιστές
domain_count_before: Συνδέεται με
extended_description_html: |
<h3>Ένα καλό σημείο για κανόνες</h3>
<p>Η αναλυτική περιγραφή δεν έχει ακόμα οριστεί</p>

View File

@ -10,10 +10,7 @@ en:
contact: Contact
contact_missing: Not set
contact_unavailable: N/A
description_headline: What is %{domain}?
documentation: Documentation
domain_count_after: other instances
domain_count_before: Connected to
extended_description_html: |
<h3>A good place for rules</h3>
<p>The extended description has not been set up yet.</p>
@ -39,6 +36,7 @@ en:
user_count_before: Home to
what_is_mastodon: What is Mastodon?
accounts:
choices_html: "%{name}'s choices:"
follow: Follow
followers: Followers
following: Following
@ -49,6 +47,8 @@ en:
nothing_here: There is nothing here!
people_followed_by: People whom %{name} follows
people_who_follow: People who follow %{name}
pin_errors:
following: You must be already following the person you want to endorse
posts: Toots
posts_with_replies: Toots and replies
reserved_username: The username is reserved

View File

@ -9,9 +9,6 @@ eo:
contact: Kontakti
contact_missing: Ne elektita
contact_unavailable: Ne disponebla
description_headline: Kio estas %{domain}?
domain_count_after: aliaj nodoj
domain_count_before: Konektita al
extended_description_html: |
<h3>Bona loko por reguloj</h3>
<p>La detala priskribo ne estis elektita.</p>

View File

@ -9,9 +9,6 @@ es:
contact: Contacto
contact_missing: No especificado
contact_unavailable: N/A
description_headline: "¿Qué es %{domain}?"
domain_count_after: otras instancias
domain_count_before: Conectado a
extended_description_html: |
<h3>Un buen lugar para las reglas</h3>
<p>La descripción extendida no se ha colocado aún.</p>

View File

@ -9,9 +9,6 @@ eu:
contact: Kontaktua
contact_missing: Ezarri gabe
contact_unavailable: E/E
description_headline: Zer da %{domain}?
domain_count_after: instantzia desberdinetara
domain_count_before: Konektatuta
extended_description_html: |
<h3>Arauentzako toki egoki bat</h3>
<p>Azalpen luzea ez da ezarri oraindik.</p>

View File

@ -9,9 +9,6 @@ fa:
contact: تماس
contact_missing: تعیین نشده
contact_unavailable: موجود نیست
description_headline: "%{domain} چیست؟"
domain_count_after: سرور دیگر
domain_count_before: متصل به
extended_description_html: |
<h3>جای خوبی برای قانون‌ها</h3>
<p>توضیحات تکمیلی نوشته نشده است.</p>

View File

@ -9,9 +9,6 @@ fi:
contact: Ota yhteyttä
contact_missing: Ei asetettu
contact_unavailable: Ei saatavilla
description_headline: Mikä on %{domain}?
domain_count_after: muuhun instanssiin
domain_count_before: Yhdistyneenä
extended_description_html: |
<h3>Hyvä paikka säännöille</h3>
<p>Pidempää kuvausta ei ole vielä laadittu.</p>

View File

@ -9,18 +9,15 @@ fr:
contact: Contact
contact_missing: Manquant
contact_unavailable: Non disponible
description_headline: Quest-ce que %{domain}?
domain_count_after: autres instances
domain_count_before: Connecté⋅e⋅s à
extended_description_html: |
<h3>Un bon endroit pour les règles</h3>
<p>La description étendue na pas été remplie.</p>
features:
humane_approach_body: Ayant appris des échecs dautres réseaux, Mastodon à lambition de combattre labus des médias sociaux en effectuant des choix de conception éthiques.
humane_approach_title: Une approche plus humaine
not_a_product_body: Mastodon nest pas un réseau commercial. Ici, pas de publicités, pas de prospection de données et pas denvironnement fermés. Il ny existe aucune autorité centrale.
not_a_product_body: Mastodon nest pas un réseau commercial. Ici, pas de publicités, pas de prospection de données et pas denvironnements fermés. Il ny existe aucune autorité centrale.
not_a_product_title: Vous êtes une personne, pas un produit
real_conversation_body: Avec 500 caractères à votre dispostion, une grande granularité en terme de diffusion et la possibilité de masquer vos messages derrières des avertissements, vous êtes libre de vous exprimer de la manière qui vous plaît.
real_conversation_body: Avec 500 caractères à votre disposition, une grande granularité en termes de diffusion et la possibilité de masquer vos messages derrières des avertissements, vous êtes libre de vous exprimer de la manière qui vous plaît.
real_conversation_title: Construit pour de vraies conversations
within_reach_body: Grâce à lexistence dun environnement API accueillant pour les développeur·se·s, de multiples applications pour iOS, Android et dautres plateformes vous permettent de rester en contact avec vos ami·e·s où que vous soyez.
within_reach_title: Toujours à portée de main
@ -40,7 +37,7 @@ fr:
following: Abonnements
media: Médias
moved_html: "%{name} a changé de compte pour %{new_profile_link} :"
network_hidden: Cette information n'est pas disponible
network_hidden: Cette information nest pas disponible
nothing_here: Rien à voir ici!
people_followed_by: Personnes suivies par %{name}
people_who_follow: Personnes qui suivent %{name}

View File

@ -9,9 +9,6 @@ gl:
contact: Contacto
contact_missing: Non establecido
contact_unavailable: N/A
description_headline: Qué é %{domain}?
domain_count_after: outras instancias
domain_count_before: Conectada a
extended_description_html: |
<h3>Un bo lugar para regras</h3>
<p>A descrición extendida aínda non se proporcionou.</p>

View File

@ -8,9 +8,6 @@ he:
contact: צור קשר
contact_missing: אין
contact_unavailable: לא רלוונטי/חסר
description_headline: מהו %{domain}?
domain_count_after: שרתים אחרים
domain_count_before: מחובר אל
extended_description_html: |
<h3>מקום טוב לכללים</h3>
<p>התיאור המורחב טרם הוגדר.</p>

View File

@ -5,9 +5,6 @@ hr:
about_this: O ovoj instanci
closed_registrations: Registracije na ovoj instanci su trenutno zatvorene.
contact: Kontakt
description_headline: Što je %{domain}?
domain_count_after: druge instance
domain_count_before: Spojen na
other_instances: Druge instance
source_code: Izvorni kod
status_count_after: statusi

View File

@ -8,9 +8,6 @@ hu:
contact: Kapcsolat
contact_missing: Nincs megadva
contact_unavailable: N/A
description_headline: Mi az a %{domain}?
domain_count_after: további instanciával
domain_count_before: Kapcsolatban
extended_description_html: |
<h3>Ez itt a szabályzat helye</h3>
<p>Még nem állítottál be bővebb leírást.</p>

View File

@ -5,9 +5,6 @@ id:
about_this: Tentang server ini
closed_registrations: Pendaftaran untuk server ini sedang ditutup.
contact: Kontak
description_headline: Apa itu %{domain}?
domain_count_after: server lain
domain_count_before: Terhubung dengan
other_instances: Server lain
source_code: Kode sumber
status_count_after: status

View File

@ -5,9 +5,6 @@ io:
about_this: Pri ta instaluro
closed_registrations: Membresko ne nun esas posible en ta instaluro.
contact: Kontaktar
description_headline: Quo esas %{domain}?
domain_count_after: altra instaluri
domain_count_before: Konektita ad
other_instances: Altra instaluri
source_code: Fontkodexo
status_count_after: mesaji

View File

@ -9,9 +9,6 @@ it:
contact: Contatti
contact_missing: Non impostato
contact_unavailable: N/D
description_headline: Cos'è %{domain}?
domain_count_after: altri server
domain_count_before: Connesso a
extended_description_html: |
<h3>Un buon posto per le regole</h3>
<p>La descrizione estesa non è ancora stata preparata.</p>

View File

@ -9,9 +9,6 @@ ja:
contact: 連絡先
contact_missing: 未設定
contact_unavailable: N/A
description_headline: "%{domain} とは?"
domain_count_after: 個のインスタンス
domain_count_before: 接続中
extended_description_html: |
<h3>ルールを書くのに適した場所</h3>
<p>詳細説明が設定されていません。</p>

View File

@ -9,9 +9,6 @@ ko:
contact: 연락처
contact_missing: 미설정
contact_unavailable: N/A
description_headline: "%{domain} (은)는 무엇인가요?"
domain_count_after: 개의 인스턴스
domain_count_before: 연결된
extended_description_html: |
<h3>룰을 작성하는 장소</h3>
<p>아직 설명이 작성되지 않았습니다.</p>

View File

@ -9,9 +9,6 @@ nl:
contact: Contact
contact_missing: Niet ingesteld
contact_unavailable: n.v.t
description_headline: Wat is %{domain}?
domain_count_after: andere servers
domain_count_before: Verbonden met
extended_description_html: |
<h3>Een goede plek voor richtlijnen</h3>
<p>De uitgebreide omschrijving is nog niet ingevuld.</p>

View File

@ -8,9 +8,6 @@
contact: Kontakt
contact_missing: Ikke innstilt
contact_unavailable: Ikke tilgjengelig
description_headline: Hva er %{domain}?
domain_count_after: andre instanser
domain_count_before: Koblet til
extended_description_html: |
<h3>En god plassering for regler</h3>
<p>En utvidet beskrivelse er ikke satt opp ennå.</p>

View File

@ -9,9 +9,6 @@ oc:
contact: Contacte
contact_missing: Pas parametrat
contact_unavailable: Pas disponible
description_headline: Qué es %{domain}?
domain_count_after: autras instàncias
domain_count_before: Connectat a
extended_description_html: |
<h3>Una bona plaça per las règlas</h3>
<p>La descripcion longa es pas estada causida pel moment.</p>

View File

@ -5,13 +5,12 @@ pl:
about_mastodon_html: Mastodon jest wolną i otwartą siecią społecznościową, zdecentralizowaną alternatywą dla zamkniętych, komercyjnych platform.
about_this: O tej instancji
administered_by: 'Administrowana przez:'
api: API
closed_registrations: Rejestracja na tej instancji jest obecnie zamknięta. Możesz jednak zarejestrować się na innej instancji, uzyskując dostęp do tej samej sieci.
contact: Kontakt
contact_missing: Nie ustawiono
contact_unavailable: Nie dotyczy
description_headline: Czym jest %{domain}?
domain_count_after: instancjami
domain_count_before: Serwer połączony z
documentation: Dokumentacja
extended_description_html: |
<h3>Dobre miejsce na zasady użytkowania</h3>
<p>Nie ustawiono jeszcze szczegółowego opisu</p>
@ -28,9 +27,11 @@ pl:
hosted_on: Mastodon uruchomiony na %{domain}
learn_more: Dowiedz się więcej
other_instances: Lista instancji
privacy_policy: Polityka prywatności
source_code: Kod źródłowy
status_count_after: wpisów
status_count_before: Są autorami
terms: Zasady użytkowania
user_count_after: użytkowników
user_count_before: Z serwera korzysta
what_is_mastodon: Czym jest Mastodon?
@ -38,6 +39,7 @@ pl:
follow: Śledź
followers: Śledzący
following: Śledzeni
joined: Dołączył(a) %{date}
media: Zawartość multimedialna
moved_html: "%{name} korzysta teraz z konta %{new_profile_link}:"
network_hidden: Ta informacja nie jest dostępna
@ -151,34 +153,34 @@ pl:
web: Sieć
action_logs:
actions:
assigned_to_self_report: "%{name} przypisał sobie zgłoszenie %{target}"
change_email_user: "%{name} zmienił adres-email użytkownika %{target}"
confirm_user: "%{name} potwierdził adres e-mail użytkownika %{target}"
create_custom_emoji: "%{name} dodał nowe emoji %{target}"
create_domain_block: "%{name} zablokował domenę %{target}"
create_email_domain_block: "%{name} dodał domenę e-mail %{target} na czarną listę"
demote_user: "%{name} zdegradował użytkownika %{target}"
destroy_domain_block: "%{name} odblokował domenę %{target}"
destroy_email_domain_block: "%{name} usunął domenę e-mail %{target} z czarnej listy"
destroy_status: "%{name} usunął wpis użytkownika %{target}"
disable_2fa_user: "%{name} wyłączył uwierzytelnianie dwustopniowe użytkownikowi %{target}"
disable_custom_emoji: "%{name} wyłączył emoji %{target}"
disable_user: "%{name} zablokował możliwość logowania użytkownikowi %{target}"
enable_custom_emoji: "%{name} włączył emoji %{target}"
enable_user: "%{name} przywrócił możliwość logowania użytkownikowi %{target}"
memorialize_account: "%{name} nadał kontu %{target} status in memoriam"
promote_user: "%{name} podniósł uprawnienia użytkownikowi %{target}"
remove_avatar_user: "%{name} usunął awatar użytkownikowi %{target}"
reopen_report: "%{name} otworzył ponownie zgłoszenie %{target}"
reset_password_user: "%{name} przywrócił hasło użytkownikowi %{target}"
resolve_report: "%{name} rozwiązał zgłoszenie %{target}"
silence_account: "%{name} wyciszył konto %{target}"
suspend_account: "%{name} zawiesił konto %{target}"
unassigned_report: "%{name} cofnął przypisanie zgłoszenia %{target}"
unsilence_account: "%{name} cofnął wyciszenie konta %{target}"
unsuspend_account: "%{name} cofnął zawieszenie konta %{target}"
update_custom_emoji: "%{name} zaktualizował emoji %{target}"
update_status: "%{name} zaktualizował wpis użytkownika %{target}"
assigned_to_self_report: "%{name} przypisał(a) sobie zgłoszenie %{target}"
change_email_user: "%{name} zmienił(a) adres e-mail użytkownika %{target}"
confirm_user: "%{name} potwierdził(a) adres e-mail użytkownika %{target}"
create_custom_emoji: "%{name} dodał(a) nowe emoji %{target}"
create_domain_block: "%{name} zablokował(a) domenę %{target}"
create_email_domain_block: "%{name} dodał(a) domenę e-mail %{target} na czarną listę"
demote_user: "%{name} zdegradował(a) użytkownika %{target}"
destroy_domain_block: "%{name} odblokował(a) domenę %{target}"
destroy_email_domain_block: "%{name} usunął(-ęła) domenę e-mail %{target} z czarnej listy"
destroy_status: "%{name} usunął(-ęła) wpis użytkownika %{target}"
disable_2fa_user: "%{name} wyłączył(a) uwierzytelnianie dwustopniowe użytkownikowi %{target}"
disable_custom_emoji: "%{name} wyłączył(a) emoji %{target}"
disable_user: "%{name} zablokował(a) możliwość logowania użytkownikowi %{target}"
enable_custom_emoji: "%{name} włączył(a) emoji %{target}"
enable_user: "%{name} przywrócił(a) możliwość logowania użytkownikowi %{target}"
memorialize_account: "%{name} nadał(a) kontu %{target} status in memoriam"
promote_user: "%{name} podniósł(a) uprawnienia użytkownikowi %{target}"
remove_avatar_user: "%{name} usunął(-ęła) awatar użytkownikowi %{target}"
reopen_report: "%{name} otworzył(a) ponownie zgłoszenie %{target}"
reset_password_user: "%{name} przywrócił(a) hasło użytkownikowi %{target}"
resolve_report: "%{name} rozwiązał(a) zgłoszenie %{target}"
silence_account: "%{name} wyciszył(a) konto %{target}"
suspend_account: "%{name} zawiesił(a) konto %{target}"
unassigned_report: "%{name} cofnął(-ęła) przypisanie zgłoszenia %{target}"
unsilence_account: "%{name} cofnął(-ęła) wyciszenie konta %{target}"
unsuspend_account: "%{name} cofnął(-ęła) zawieszenie konta %{target}"
update_custom_emoji: "%{name} zaktualizował(a) emoji %{target}"
update_status: "%{name} zaktualizował(a) wpis użytkownika %{target}"
title: Dziennik działań administracyjnych
custom_emojis:
by_domain: Domeny
@ -368,13 +370,16 @@ pl:
desc_html: Pokazuj odznakę uprawnień na stronie profilu użytkownika
title: Pokazuj odznakę administracji
site_description:
desc_html: Akapit wprowadzający, widoczny na stronie głównej i znacznikach meta. Możesz korzystać z tagów HTML, w szczególności <code>&lt;a&gt;</code> i <code>&lt;em&gt;</code>.
desc_html: Akapit wprowadzający, widoczny na stronie głównej. Opisz, co czyni tę instancję wyjątkową. Możesz korzystać ze znaczników HTML, w szczególności <code>&lt;a&gt;</code> i <code>&lt;em&gt;</code>.
title: Opis instancji
site_description_extended:
desc_html: Dobre miejsce na zasady użytkowania, wprowadzenie i inne rzeczy, które wyróżniają tę instancję. Możesz korzystać z tagów HTML
desc_html: Dobre miejsce na zasady użytkowania, wprowadzenie i inne rzeczy, które wyróżniają tę instancję. Możesz korzystać ze znaczników HTML
title: Niestandardowy opis strony
site_short_description:
desc_html: Wyświetlany na pasku bocznym i w znacznikach meta. Opisz, czym jest Mastodon i czym wyróżnia się ta instancja w jednym akapicie. Jeżeli pusty, zostanie użyty opis instancji.
title: Krótki opis instancji
site_terms:
desc_html: Miejsce na własną politykę prywatności, zasady użytkowania i inne unormowania prawne. Możesz korzystać z tagów HTML
desc_html: Miejsce na własną politykę prywatności, zasady użytkowania i inne unormowania prawne. Możesz korzystać ze znaczników HTML
title: Niestandardowe zasady użytkowania
site_title: Nazwa instancji
thumbnail:
@ -406,8 +411,8 @@ pl:
title: Administracja
admin_mailer:
new_report:
body: Użytkownik %{reporter} zgłosił %{target}
body_remote: Użytkownik instancji %{domain} zgłosił %{target}
body: Użytkownik %{reporter} zgłosił(a) %{target}
body_remote: Użytkownik instancji %{domain} zgłosił(a) %{target}
subject: Nowe zgłoszenie na %{instance} (#%{id})
application_mailer:
notification_preferences: Zmień ustawienia e-maili
@ -425,18 +430,18 @@ pl:
warning: Przechowuj te dane ostrożnie. Nie udostępniaj ich nikomu!
your_token: Twój token dostępu
auth:
agreement_html: Rejestrując się, oświadczasz, że zapoznałeś się z <a href="%{rules_path}">informacjami o instancji</a> i <a href="%{terms_path}">zasadami korzystania z usługi</a>.
agreement_html: Rejestrując się, oświadczasz, że zapoznałeś(-aś) się z <a href="%{rules_path}">informacjami o instancji</a> i <a href="%{terms_path}">zasadami korzystania z usługi</a>.
change_password: Hasło
confirm_email: Potwierdź adres e-mail
delete_account: Usunięcie konta
delete_account_html: Jeżeli chcesz usunąć konto, <a href="%{path}">przejdź tutaj</a>. Otrzymasz prośbę o potwierdzenie.
didnt_get_confirmation: Nie otrzymałeś instrukcji weryfikacji?
didnt_get_confirmation: Nie otrzymałeś(-aś) instrukcji weryfikacji?
forgot_password: Nie pamiętasz hasła?
invalid_reset_password_token: Token do resetowania hasła jest nieprawidłowy lub utracił ważność. Spróbuj uzyskać nowy.
login: Zaloguj się
logout: Wyloguj się
migrate_account: Przenieś konto
migrate_account_html: Jeżeli chcesz skonfigurować przekierowanie z obecnego konta na inne, możesz <a href="%{path}">skonfigurować to tutaj</a>.
migrate_account_html: Jeżeli chcesz skonfigurować przekierowanie z obecnego konta na inne, możesz <a href="%{path}">zrobić to tutaj</a>.
or: lub
or_log_in_with: Lub zaloguj się z użyciem
providers:
@ -534,6 +539,10 @@ pl:
true_privacy_html: Pamiętaj, że <strong>rzeczywista prywatność może zostać uzyskana wyłącznie dzięki szyfrowaniu end-to-end</strong>.
unlocked_warning_html: Każdy może Cię śledzić, dzięki czemu może zobaczyć Twoje niepubliczne wpisy. %{lock_link} aby móc kontrolować, kto Cię śledzi.
unlocked_warning_title: Twoje konto nie jest zablokowane
footer:
developers: Dla programistów
more: Więcej…
resources: Zasoby
generic:
changes_saved_msg: Ustawienia zapisane!
save_changes: Zapisz zmiany
@ -564,7 +573,7 @@ pl:
'86400': dobie
expires_in_prompt: Nigdy
generate: Wygeneruj
invited_by: 'Zostałeś zaproszony przez:'
invited_by: 'Zostałeś(-aś) zaproszony(-a) przez:'
max_uses:
few: "%{count} użycia"
many: "%{count} użyć"
@ -616,13 +625,13 @@ pl:
title: Nowy śledzący
follow_request:
action: Zarządzaj prośbami o możliwość śledzenia
body: "%{name} poprosił o możliwość śledzenia Cię"
body: "%{name} poprosił(a) o możliwość śledzenia Cię"
subject: 'Prośba o możliwość śledzenia: %{name}'
title: Nowa prośba o możliwość śledzenia
mention:
action: Odpowiedz
body: "%{name} wspomniał o Tobie w:"
subject: "%{name} wspomniał o Tobie"
body: "%{name} wspomniał(a) o Tobie w:"
subject: "%{name} wspomniał(a) o Tobie"
title: Nowe wspomnienie o Tobie
reblog:
body: 'Twój wpis został podbity przez %{name}:'
@ -762,9 +771,9 @@ pl:
<h3 id="collect">Jakie informacje zbieramy?</h3>
<ul>
<li><em>Podstawowe informacje o koncie</em>: Podczas rejestracji na tym serwerze, możesz zostać poproszony o wprowadzenie nazwy użytkownika, adresu e-mail i hasła. Możesz także wprowadzić dodatkowe informacje o profilu, takie jak nazwa wyświetlana i biografia oraz wysłać awatar i obraz nagłówka. Nazwa użytkownika, nazwa wyświetlana, biografia, awatar i obraz nagłówka są zawsze widoczne dla wszystkich.</li>
<li><em>Podstawowe informacje o koncie</em>: Podczas rejestracji na tym serwerze, możesz zostać poproszony(-a) o wprowadzenie nazwy użytkownika, adresu e-mail i hasła. Możesz także wprowadzić dodatkowe informacje o profilu, takie jak nazwa wyświetlana i biografia oraz wysłać awatar i obraz nagłówka. Nazwa użytkownika, nazwa wyświetlana, biografia, awatar i obraz nagłówka są zawsze widoczne dla wszystkich.</li>
<li><em>Wpisy, śledzenie i inne publiczne informacje</em>: Lista osób które śledzisz jest widoczna publicznie, tak jak lista osób, które Cię śledzą. Jeżeli dodasz wpis, data i czas jego utworzenia i aplikacja, z której go wysłano są przechowywane. Wiadomości mogą zawierać załączniki multimedialne, takie jak zdjęcia i filmy. Publiczne i niewidoczne wpisy są dostępne publicznie. Udostępniony wpis również jest widoczny publicznie. Twoje wpisy są dostarczane obserwującym, co oznacza że jego kopie mogą zostać dostarczone i być przechowywane na innych serwerach. Kiedy usuniesz wpis, przestaje być widoczny również dla osób śledzących Cię. „Podbijanie” i dodanie do ulubionych jest zawsze publiczne.</li>
<li><em>Wpisy bezpośrednie i tylko dla śledzących</em>: Wszystkie wpisy są przechowywane i przetwarzane na serwerze. Wpisy przeznaczone tylko dla śledzących są widoczne tylko dla nich i osób wspomnianych we wpisie, a wpisy bezpośrednie tylko dla wspimnianych. W wielu przypadkach oznacza to, że ich kopie są dostarczane i przechowywane na innych serwerach. Staramy się ograniczać zasięg tych wpisów wyłącznie do właściwych odbiorców, ale inne serwery mogą tego nie robić. Ważne jest, aby sprawdzać jakich serwerów używają osoby, które Cię śledzą. Możesz aktywować opcję pozwalającą na ręczne akceptowanie i odrzucanie nowych śledzących. <em>Pamiętaj, że właściciele serwerów mogą zobaczyć te wiadomości</em>, a odbiorcy mogą wykonać zrzut ekranu, skopiować lub udostępniać ten wpis. <em>Nie udostępniaj wrażliwych danych z użyciem Mastodona.</em></li>
<li><em>Wpisy bezpośrednie i tylko dla śledzących</em>: Wszystkie wpisy są przechowywane i przetwarzane na serwerze. Wpisy przeznaczone tylko dla śledzących są widoczne tylko dla nich i osób wspomnianych we wpisie, a wpisy bezpośrednie tylko dla wspomnianych. W wielu przypadkach oznacza to, że ich kopie są dostarczane i przechowywane na innych serwerach. Staramy się ograniczać zasięg tych wpisów wyłącznie do właściwych odbiorców, ale inne serwery mogą tego nie robić. Ważne jest, aby sprawdzać jakich serwerów używają osoby, które Cię śledzą. Możesz aktywować opcję pozwalającą na ręczne akceptowanie i odrzucanie nowych śledzących. <em>Pamiętaj, że właściciele serwerów mogą zobaczyć te wiadomości</em>, a odbiorcy mogą wykonać zrzut ekranu, skopiować lub udostępniać ten wpis. <em>Nie udostępniaj wrażliwych danych z użyciem Mastodona.</em></li>
<li><em>Adresy IP i inne metadane</em>: Kiedy zalogujesz się, przechowujemy adres IP użyty w trakcie logowania wraz z nazwą używanej przeglądarki. Wszystkie aktywne sesje możesz zobaczyć (i wygasić) w ustawieniach. Ostatnio używany adres IP jest przechowywany przez nas do 12 miesięcy. Możemy również przechowywać adresy IP wykorzystywane przy każdym działaniu na serwerze.</li>
</ul>
@ -805,15 +814,15 @@ pl:
<h3 id="cookies">Czy używany plików cookies?</h3>
<p>Tak. Pliki cookies są małymi plikami, które strona lub dostawca jej usługi dostarcza na dysk twardy komputera z użyciem przeglądarki internetowej (jeżeli na to pozwoli). Pliki cookies pozwalają na rozpoznanie przeglądarki i jeśli jesteś zarejestrowany przypisanie jej do konta.</p>
<p>Tak. Pliki cookies są małymi plikami, które strona lub dostawca jej usługi dostarcza na dysk twardy komputera z użyciem przeglądarki internetowej (jeżeli na to pozwoli). Pliki cookies pozwalają na rozpoznanie przeglądarki i jeśli jesteś zarejestrowany(-a) przypisanie jej do konta.</p>
<p>Wykorzystujemy pliki cookies, aby przechowywać preferencję użytkowników na przyszłe wizyty.</p>
<p>Wykorzystujemy pliki cookies, aby przechowywać preferencje użytkowników na przyszłe wizyty.</p>
<hr class="spacer" />
<h3 id="disclose">Czy przekazujemy informacje osobom trzecim?</h3>
<p>Nie sprzedajemy, nie wymieniamy i nie przekazujemy osobom trzecim informacji pozwalających na identyfikację Ciebie. Nie dotyczy to zaufanym dostawcom pomagającym w prowadzeniu lub obsługiwaniu użytkowników, jeżeli zgadzają się, aby nie przekazywać dalej tych informacji. Możemy również udostępnić informacje, jeżeli uważany to za wymagane przez prawo, konieczne do wypełnienia polityki strony, przestrzegania naszych lub cudzych praw, własności i bezpieczeństwa.</p>
<p>Nie sprzedajemy, nie wymieniamy i nie przekazujemy osobom trzecim informacji pozwalających na identyfikację Ciebie. Nie dotyczy to zaufanych dostawców pomagających w prowadzeniu strony lub obsługiwaniu użytkowników, jeżeli zgadzają się, aby nie przekazywać dalej tych informacji. Możemy również udostępnić informacje, jeżeli uważany to za wymagane przez prawo, konieczne do wypełnienia polityki strony, przestrzegania naszych lub cudzych praw, własności i bezpieczeństwa.</p>
<p>Twoja publiczna zawartość może zostać pobrana przez inne serwery w sieci. Wpisy publiczne i tylko dla śledzących są dostarczane na serwery, na których znajdują się śledzący Cię, a wiadomości bezpośrednie trafiają na serwery adresatów, jeżeli są oni użytkownikami innego serwera.</p>
@ -823,9 +832,9 @@ pl:
<h3 id="children">Korzystanie ze strony przez dzieci</h3>
<p>Jeżeli serwer znajduje się w UE lub w EOG: Ta strona, produkty i usługi są przeznaczone dla osób, które ukończyły 16 lat. Jeżeli nie ukończyłeś 16 roku życia, zgodnie z wymogami COPPA (<a href="https://pl.wikipedia.org/wiki/Children%27s_Online_Privacy_Protection_Act">Prawo o Ochronie Prywatności Dzieci w Internecie</a>), nie używaj tej strony.</p>
<p>Jeżeli serwer znajduje się w UE lub w EOG: Ta strona, produkty i usługi są przeznaczone dla osób, które ukończyły 16 lat. Jeżeli nie ukończyłeś(-aś) 16 roku życia, zgodnie z wymogami COPPA (<a href="https://pl.wikipedia.org/wiki/Children%27s_Online_Privacy_Protection_Act">Prawo o Ochronie Prywatności Dzieci w Internecie</a>), nie używaj tej strony.</p>
<p>Jeżeli serwer znajduje się w USA: Ta strona, produkty i usługi są przeznaczone dla osób, które ukończyły 13 lat. Jeżeli nie ukończyłeś 13 roku życia, zgodnie z wymogami RODO (<a href="https://pl.wikipedia.org/wiki/Ogólne_rozporządzenie_o_ochronie_danych">Ogólne rozporządzenie o ochronie danych</a>), nie używaj tej strony.</p>
<p>Jeżeli serwer znajduje się w USA: Ta strona, produkty i usługi są przeznaczone dla osób, które ukończyły 13 lat. Jeżeli nie ukończyłeś(-aś) 13 roku życia, zgodnie z wymogami RODO (<a href="https://pl.wikipedia.org/wiki/Ogólne_rozporządzenie_o_ochronie_danych">Ogólne rozporządzenie o ochronie danych</a>), nie używaj tej strony.</p>
<p>Wymogi mogą być inne, jeżeli serwer znajduje się w innym kraju.</p>
@ -872,7 +881,7 @@ pl:
full_handle: Twój pełny adres
full_handle_hint: Ten adres możesz podać znajomym, aby mogli skontaktować się z Tobą lub zacząć śledzić z innej instancji.
review_preferences_action: Zmień ustawienia
review_preferences_step: Upewnij się, że zmieniłeś ustawienia, takie jak maile, które chciałbyś otrzymywać lub domyślne opcje prywatności. Jeżeli nie masz choroby lokomocyjnej, możesz włączyć automatyczne odtwarzanie animacji GIF.
review_preferences_step: Upewnij się, że zmieniłeś(-aś) ustawienia, takie jak maile, które chciałbyś otrzymywać lub domyślne opcje prywatności. Jeżeli nie masz choroby lokomocyjnej, możesz włączyć automatyczne odtwarzanie animacji GIF.
subject: Witaj w Mastodonie
tip_bridge_html: Jeżeli przybywasz z Twittera, możesz znaleźć znajomych na Mastodonie używając <a href="%{bridge_url}">aplikacji mostku</a>. Działa to tylko, jeżeli oni również z niej korzystali!
tip_federated_timeline: Oś czasu federacji przedstawia całą sieć Mastodona. Wyświetla tylko wpisy osób, które śledzą użytkownicy Twojej instancji, więc nie jest kompletna.

View File

@ -9,9 +9,6 @@ pt-BR:
contact: Contato
contact_missing: Não definido
contact_unavailable: N/A
description_headline: O que é %{domain}?
domain_count_after: outras instâncias
domain_count_before: Conectado a
extended_description_html: |
<h3>Um bom lugar para regras</h3>
<p>A descrição da instância ainda não foi feita.</p>

View File

@ -8,9 +8,6 @@ pt:
contact: Contacto
contact_missing: Não configurado
contact_unavailable: n.d.
description_headline: O que é o %{domain}?
domain_count_after: outras instâncias
domain_count_before: Ligado a
extended_description_html: |
<h3>Um bom lugar para regras</h3>
<p>A descrição estendida ainda não foi configurada.</p>

View File

@ -5,13 +5,10 @@ ru:
about_mastodon_html: Mastodon - это <em>свободная</em> социальная сеть с <em>открытым исходным кодом</em>. Как <em>децентрализованная</em> альтернатива коммерческим платформам, Mastodon предотвращает риск монополизации Вашего общения одной компанией. Выберите сервер, которому Вы доверяете &mdash; что бы Вы ни выбрали, Вы сможете общаться со всеми остальными. Любой может запустить свой собственный узел Mastodon и участвовать в <em>социальной сети</em> совершенно бесшовно.
about_this: Об этом узле
administered_by: 'Администратор узла:'
closed_registrations: В данный момент регистрация на этом узле закрыта.
closed_registrations: В данный момент регистрация на этом узле закрыта. Но вы можете найти другой узел, создать на нём учётную запись и получить доступ к той же сети оттуда.
contact: Связаться
contact_missing: Не установлено
contact_unavailable: Недоступен
description_headline: Что такое %{domain}?
domain_count_after: другими узлами
domain_count_before: Связан с
extended_description_html: |
<h3>Хорошее место для правил</h3>
<p>Расширенное описание еще не настроено.</p>
@ -28,9 +25,11 @@ ru:
hosted_on: Mastodon размещен на %{domain}
learn_more: Узнать больше
other_instances: Другие узлы
privacy_policy: Политика конфиденциальности
source_code: Исходный код
status_count_after: статусов
status_count_before: Опубликовано
terms: Условия использования
user_count_after: пользователей
user_count_before: Здесь живет
what_is_mastodon: Что такое Mastodon?
@ -38,7 +37,8 @@ ru:
follow: Подписаться
followers: Подписчики
following: Подписан(а)
media: Медиаконтент
joined: 'Дата регистрации: %{date}'
media: Медиа
moved_html: "%{name} переехал(а) на %{new_profile_link}:"
network_hidden: Эта информация недоступна
nothing_here: Здесь ничего нет!
@ -205,6 +205,27 @@ ru:
update_failed_msg: Невозможно обновить этот эмодзи
updated_msg: Эмодзи обновлён!
upload: Загрузить
dashboard:
backlog: задачи
config: Конфигурация
feature_deletions: Аккаунтов удалено
feature_invites: Пригласительные ссылки
feature_registrations: Регистрации
feature_relay: Ретрансляторов сети
features: Нововведения
hidden_service: Федерация со скрытыми сервисами
open_reports: открытых жалоб
recent_users: Недавние пользователи
search: Полнотекстовый поиск
single_user_mode: Однопользовательский режим
software: Программное обеспечение
space: Использовано места
title: Панель управления
total_users: всего пользователей
trends: Тренды
week_interactions: взаимодействий на этой неделе
week_users_active: активно на этой неделе
week_users_new: пользователей на этой неделе
domain_blocks:
add_new: Добавить новую
created_msg: Блокировка домена обрабатывается
@ -262,6 +283,14 @@ ru:
expired: Истёкшие
title: Фильтр
title: Приглашения
relays:
add_new: Добавить ретранслятор
description_html: "<strong>Федеративный ретранслятор</strong> это промежуточный сервер, который передаёт большие объёмы публичных статусов между серверами, которые подписываются и публикуют туда. <strong>Это может помочь небольшим и средним серверам находить записи со всей федерации</strong>, ведь в противном случае пользователям нужно будет вручную подписываться на людей с удалённых узлов."
enable_hint: Если включено, ваш сервер будет подписан на все публичные статусы с этого ретранслятора и начнёт туда отправлять публичные статусы со своего узла.
inbox_url: URL ретранслятора
setup: Настроте соединение с ретранслятором
status: Состояние
title: Ретрансляторы
report_notes:
created_msg: Примечание жалобы создано!
destroyed_msg: Примечание жалобы удалено!
@ -281,8 +310,8 @@ ru:
mark_as_unresolved: Отметить как неразрешённую
notes:
create: Добавить заметку
create_and_resolve: Разрешить с заметкой
create_and_unresolve: Переоткрыть с заметкой
create_and_resolve: Разрешить с примечанием
create_and_unresolve: Переоткрыть с примечанием
delete: Удалить
placeholder: Опишите, какие действия были приняты, или любые другие подробности…
reopen: Переоткрыть жалобу
@ -317,6 +346,9 @@ ru:
peers_api_enabled:
desc_html: Домены, которые были замечены этим узлом среди всей федерации
title: Публикация списка обнаруженных узлов
preview_sensitive_media:
desc_html: Предпросмотр ссылок с остальных веб-сайтов будет показан даже если медиаконтент отмечен как чувствительный
title: Показывать чувствительный медиаконтент в предпросмотре OpenGraph
registrations:
closed_message:
desc_html: Отображается на титульной странице, когда закрыта регистрация<br>Можно использовать HTML-теги
@ -341,7 +373,10 @@ ru:
title: Описание сайта
site_description_extended:
desc_html: Отображается на странице дополнительной информации<br>Можно использовать HTML-теги
title: Расширенное описание сайта
title: Расширенное описание узла
site_short_description:
desc_html: Отображается в боковой панели и в тегах. Опишите, что такое Mastodon и что делает именно этот узел особенным. Если пусто, используется описание узла по умолчанию.
title: Короткое описание узла
site_terms:
desc_html: Вы можете добавить сюда собственную политику конфиденциальности, пользовательское соглашение и другие документы. Можно использовать теги HTML.
title: Условия использования
@ -475,6 +510,22 @@ ru:
follows: Подписки
mutes: Список глушения
storage: Ваш медиаконтент
filters:
contexts:
home: Домашняя лента
notifications: Уведомления
public: Публичные ленты
thread: Диалоги
edit:
title: Изменить фильтр
errors:
invalid_context: Некорректный контекст или ничего
invalid_irreversible: Необратимая фильтрация работает только с лентой уведомлений и домашней лентой
index:
delete: Удалить
title: Фильтры
new:
title: Добавить фильтр
followers:
domain: Домен
explanation_html: Если Вы хотите быть уверены в приватности Ваших статусов, Вы должны иметь четкое представление о том, кто на Вас подписан. <strong>Ваши приватные статусы отправляются всем узлам, на которых у Вас есть подписчики</strong>. Рекомендуем удалить из подписчиков пользователей узлов, администрации или программному обеспечению которых Вы не доверяете.
@ -489,6 +540,10 @@ ru:
true_privacy_html: Пожалуйста, заметьте, что <strong>настоящая конфиденциальность может быть достигнута только при помощи end-to-end шифрования</strong>.
unlocked_warning_html: Кто угодно может подписаться на Вас и получить доступ к просмотру Ваших приватных статусов. %{lock_link}, чтобы получить возможность рассматривать и вручную подтверждать запросы о подписке.
unlocked_warning_title: Ваш аккаунт не закрыт для подписки
footer:
developers: Разработчики
more: Ещё…
resources: Ссылки
generic:
changes_saved_msg: Изменения успешно сохранены!
save_changes: Сохранить изменения
@ -606,6 +661,7 @@ ru:
remote_follow:
acct: Введите username@domain, откуда Вы хотите подписаться
missing_resource: Поиск требуемого перенаправления URL для Вашего аккаунта завершился неудачей
no_account_html: Нет учётной записи? Вы можете <a href='%{sign_up_path}' target='_blank'>зарегистрироваться здесь</a>
proceed: Продолжить подписку
prompt: 'Вы хотите подписаться на:'
remote_unfollow:
@ -688,6 +744,7 @@ ru:
many: 'содержались запрещённые хэштеги: %{tags}'
one: 'содержался запрещённый хэштег: %{tags}'
other: 'содержались запрещённые хэштеги: %{tags}'
language_detection: Определять язык автоматически
open_in_web: Открыть в WWW
over_character_limit: превышен лимит символов (%{max})
pin_errors:
@ -705,7 +762,7 @@ ru:
unlisted: Скрывать из лент
unlisted_long: Показывать всем, но не отображать в публичных лентах
stream_entries:
pinned: Закреплённое сообщение
pinned: Закреплённый статус
reblogged: продвинул(а)
sensitive_content: Чувствительный контент
terms:

View File

@ -3,8 +3,10 @@ ru:
simple_form:
hints:
defaults:
autofollow: Люди, пришедшие по этому приглашению автоматически будут подписаны на Вас
avatar: PNG, GIF или JPG. Максимально %{size}. Будет уменьшено до %{dimensions}px
bot: Этот аккаунт обычно выполяет автоматизированные действия и может не просматриваться владельцем
context: Один или несколько контекстов, к которым должны быть применены фильтры
digest: Отсылается лишь после длительной неактивности, если Вы в это время получали личные сообщения
display_name:
few: Осталось <span class="name-counter">%{count}</span> символа
@ -13,15 +15,22 @@ ru:
other: Осталось <span class="name-counter">%{count}</span> символов
fields: В профиле можно отобразить до 4 пунктов как таблицу
header: PNG, GIF или JPG. Максимально %{size}. Будет уменьшено до %{dimensions}px
inbox_url: Копировать URL с главной страницы ретранслятора, который Вы хотите использовать
irreversible: Отфильтрованные статусы будут утеряны навсегда, даже если в будущем фильтр будет убран
locale: Язык интерфейса, e-mail писем и push-уведомлений
locked: Потребует от Вас ручного подтверждения подписчиков, изменит приватность постов по умолчанию на "только для подписчиков"
note:
few: Осталось <span class="name-counter">%{count}</span> символа
many: Осталось <span class="name-counter">%{count}</span> символов
one: Остался <span class="name-counter">1</span> символ
other: Осталось <span class="name-counter">%{count}</span> символов
phrase: Будет сопоставлено независимо от присутствия в тексте или предупреждения о содержании статуса
scopes: Какие API приложению будет позволено использовать. Если Вы выберите самый верхний, нижестоящие будут выбраны автоматически.
setting_default_language: Язык Ваших статусов может быть определён автоматически, но не всегда правильно
setting_hide_network: Те, на кого Вы подписаны и кто подписан на Вас, не будут отображены в Вашем профиле
setting_noindex: Относится к Вашему публичному профилю и страницам статусов
setting_theme: Влияет на внешний вид Mastodon при выполненном входе в аккаунт.
whole_word: Если слово или фраза состоит только из букв и цифр, сопоставление произойдёт только по полному совпадению
imports:
data: Файл CSV, экспортированный с другого узла Mastodon
sessions:
@ -32,10 +41,13 @@ ru:
name: Пункт
value: Значение
defaults:
autofollow: Пригласите подписаться на Ваш аккаунт
avatar: Аватар
bot: Это аккаунт бота
chosen_languages: Фильтр языков
confirm_new_password: Повторите новый пароль
confirm_password: Повторите пароль
context: Контекст фильтра
current_password: Текущий пароль
data: Данные
display_name: Показываемое имя
@ -43,15 +55,19 @@ ru:
expires_in: Срок действия
fields: Метаданные профиля
header: Заголовок
locale: Язык
inbox_url: URL для входящих от ретрансляторов
irreversible: Удалять, а не скрывать
locale: Язык интерфейса
locked: Сделать аккаунт закрытым
max_uses: Макс. число использований
new_password: Новый пароль
note: О Вас
otp_attempt: Двухфакторный код
password: Пароль
phrase: Слово или фраза
setting_auto_play_gif: Автоматически проигрывать анимированные GIF
setting_boost_modal: Показывать диалог подтверждения перед продвижением
setting_default_language: Язык отправляемых статусов
setting_default_privacy: Видимость постов
setting_default_sensitive: Всегда отмечать медиаконтент как чувствительный
setting_delete_modal: Показывать диалог подтверждения перед удалением
@ -66,6 +82,7 @@ ru:
type: Тип импорта
username: Имя пользователя
username_or_email: Имя пользователя или e-mail
whole_word: Слово целиком
interactions:
must_be_follower: Заблокировать уведомления не от подписчиков
must_be_following: Заблокировать уведомления от людей, на которых Вы не подписаны

View File

@ -9,9 +9,6 @@ sk:
contact: Kontakt
contact_missing: Nezadané
contact_unavailable: Neuvedené
description_headline: Čo je %{domain}?
domain_count_after: ďalším instanciám
domain_count_before: Pripojený k
extended_description_html: |
<h3>Pravidlá</h3>
<p>Žiadne zatiaľ nie sú</p>

View File

@ -9,9 +9,6 @@ sl:
contact: Kontakt
contact_missing: Ni nastavljeno
contact_unavailable: Ni na voljo
description_headline: Kaj je %{domain}?
domain_count_after: ostala vozlišča
domain_count_before: Povezan z
extended_description_html: |
<h3>Dober prostor za pravila</h3>
<p>Razširjen opis še ni bil nastavljen.</p>

View File

@ -8,9 +8,6 @@ sr-Latn:
contact: Kontakt
contact_missing: Nije postavljeno
contact_unavailable: N/A
description_headline: Šta je %{domain}?
domain_count_after: ostale instance
domain_count_before: Povezan na
extended_description_html: |
<h3>Dobro mesto za pravila</h3>
<p>Prošireni opis koji još nije postavljen.</p>

View File

@ -9,9 +9,6 @@ sr:
contact: Контакт
contact_missing: Није постављено
contact_unavailable: N/A
description_headline: Шта је %{domain}?
domain_count_after: остале инстанце
domain_count_before: Повезан на
extended_description_html: |
<h3>Добро место за правила</h3>
<p>Проширени опис који још није постављен.</p>

View File

@ -9,9 +9,6 @@ sv:
contact: Kontakt
contact_missing: Inte inställd
contact_unavailable: N/A
description_headline: Vad är %{domain}?
domain_count_after: andra instanser
domain_count_before: Uppkopplad mot
extended_description_html: |
<h3>En bra plats för regler</h3>
<p>Den utökade beskrivningen har inte konfigurerats ännu.</p>

View File

@ -5,9 +5,6 @@ th:
about_this: เกี่ยวกับอินซะแตนซ์นี้
closed_registrations: อินซะแตนซ์นี้ปิดรับลงทะเบียนแล้ว.
contact: ติดต่อ
description_headline: โดเมนคือ %{domain} ?
domain_count_after: อินซะแตนซ์อื่นๆ
domain_count_before: เชื่อมต่อกับ
other_instances: อินซะแตนซ์อื่นๆ
source_code: ซอร์สโค๊ด
status_count_after: สถานะ

View File

@ -5,9 +5,6 @@ tr:
about_this: Bu sunucu hakkında
closed_registrations: Bu sunucu şu anda yeni kayıt almamaktadır.
contact: İletişim
description_headline: Peki %{domain} nedir?
domain_count_after: sunucu var.
domain_count_before: Bağlı olduğu
other_instances: Diğer sunucular
source_code: Kaynak kodu
status_count_after: adet gönderi yazıldı.

View File

@ -7,9 +7,6 @@ uk:
closed_registrations: На даний момент реєстрація на цій інстанції закрита.
contact: Зв'язатися
contact_missing: Не зазначено
description_headline: Що таке %{domain}?
domain_count_after: іншими інстанціями
domain_count_before: Зв'язаний з
features:
humane_approach_title: Більш людський підхід
real_conversation_title: Побудований для справжньої розмови

View File

@ -9,9 +9,6 @@ zh-CN:
contact: 联系方式
contact_missing: 未设定
contact_unavailable: 未公开
description_headline: 关于 %{domain}
domain_count_after: 个其它实例
domain_count_before: 现已接入
extended_description_html: |
<h3>这里可以写一些规定</h3>
<p>本站尚未设置详细介绍。</p>

View File

@ -9,9 +9,6 @@ zh-HK:
contact: 聯絡
contact_missing: 未設定
contact_unavailable: 未公開
description_headline: 甚麼是 %{domain}
domain_count_after: 個其他服務站
domain_count_before: 已連接至
extended_description_html: |
<h3>這裡可以寫一些網站規則</h3>
<p>本站未有詳細介紹</p>

View File

@ -9,9 +9,6 @@ zh-TW:
contact: 聯絡我們
contact_missing: 未設定
contact_unavailable: 未公開
description_headline: 關於 %{domain}
domain_count_after: 個站點相連
domain_count_before: 與其他
extended_description_html: |
<h3>這裡可以寫一些網站規則</h3>
<p>本站點未有詳細介紹</p>

View File

@ -321,6 +321,9 @@ Rails.application.routes.draw do
post :mute
post :unmute
end
resource :pin, only: :create, controller: 'accounts/pins'
post :unpin, to: 'accounts/pins#destroy'
end
resources :lists, only: [:index, :create, :show, :update, :destroy] do

View File

@ -0,0 +1,12 @@
class CreateAccountPins < ActiveRecord::Migration[5.2]
def change
create_table :account_pins do |t|
t.belongs_to :account, foreign_key: { on_delete: :cascade }
t.belongs_to :target_account, foreign_key: { on_delete: :cascade, to_table: :accounts }
t.timestamps
end
add_index :account_pins, [:account_id, :target_account_id], unique: true
end
end

View File

@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2018_07_11_152640) do
ActiveRecord::Schema.define(version: 2018_08_08_175627) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@ -33,6 +33,16 @@ ActiveRecord::Schema.define(version: 2018_07_11_152640) do
t.index ["target_account_id"], name: "index_account_moderation_notes_on_target_account_id"
end
create_table "account_pins", force: :cascade do |t|
t.bigint "account_id"
t.bigint "target_account_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["account_id", "target_account_id"], name: "index_account_pins_on_account_id_and_target_account_id", unique: true
t.index ["account_id"], name: "index_account_pins_on_account_id"
t.index ["target_account_id"], name: "index_account_pins_on_target_account_id"
end
create_table "accounts", force: :cascade do |t|
t.string "username", default: "", null: false
t.string "domain"
@ -159,9 +169,9 @@ ActiveRecord::Schema.define(version: 2018_07_11_152640) do
t.text "phrase", default: "", null: false
t.string "context", default: [], null: false, array: true
t.boolean "irreversible", default: false, null: false
t.boolean "whole_word", default: true, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.boolean "whole_word", default: true, null: false
t.index ["account_id"], name: "index_custom_filters_on_account_id"
end
@ -586,6 +596,8 @@ ActiveRecord::Schema.define(version: 2018_07_11_152640) do
add_foreign_key "account_domain_blocks", "accounts", name: "fk_206c6029bd", on_delete: :cascade
add_foreign_key "account_moderation_notes", "accounts"
add_foreign_key "account_moderation_notes", "accounts", column: "target_account_id"
add_foreign_key "account_pins", "accounts", column: "target_account_id", on_delete: :cascade
add_foreign_key "account_pins", "accounts", on_delete: :cascade
add_foreign_key "accounts", "accounts", column: "moved_to_account_id", on_delete: :nullify
add_foreign_key "admin_action_logs", "accounts", on_delete: :cascade
add_foreign_key "backups", "users", on_delete: :nullify

View File

@ -46,8 +46,6 @@ services:
- redis
# - es
volumes:
- ./public/assets:/mastodon/public/assets
- ./public/packs:/mastodon/public/packs
- ./public/system:/mastodon/public/system
streaming:
@ -78,7 +76,6 @@ services:
- external_network
- internal_network
volumes:
- ./public/packs:/mastodon/public/packs
- ./public/system:/mastodon/public/system
## Uncomment to enable federation with tor instances along with adding the following ENV variables
## http_proxy=http://privoxy:8118

View File

@ -0,0 +1,4 @@
Fabricator(:account_pin) do
account nil
target_account nil
end

View File

@ -0,0 +1,5 @@
require 'rails_helper'
RSpec.describe AccountPin, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
end

View File

@ -1,35 +0,0 @@
# frozen_string_literal: true
require 'rails_helper'
describe 'about/_contact.html.haml' do
describe 'the contact account', without_verify_partial_doubles: true do
before do
allow(view).to receive(:display_name).and_return('Display Name!')
end
it 'shows info when account is present' do
account = Account.new(username: 'admin')
contact = double(contact_account: account, site_contact_email: '')
render 'about/contact', contact: contact
expect(rendered).to have_content('@admin')
end
it 'does not show info when account is missing' do
contact = double(contact_account: nil, site_contact_email: '')
render 'about/contact', contact: contact
expect(rendered).not_to have_content('@')
end
end
describe 'the contact email' do
it 'show info when email is present' do
contact = double(site_contact_email: 'admin@example.com', contact_account: nil)
render 'about/contact', contact: contact
expect(rendered).to have_content('admin@example.com')
end
end
end