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

Merge upstream changes
This commit is contained in:
ThibG 2019-04-22 23:06:54 +02:00 committed by GitHub
commit b2f73231a4
29 changed files with 540 additions and 70 deletions

View file

@ -29,7 +29,7 @@ gem 'browser'
gem 'charlock_holmes', '~> 0.7.6' gem 'charlock_holmes', '~> 0.7.6'
gem 'iso-639' gem 'iso-639'
gem 'chewy', '~> 5.0' gem 'chewy', '~> 5.0'
gem 'cld3', '~> 3.2.3' gem 'cld3', '~> 3.2.4'
gem 'devise', '~> 4.6' gem 'devise', '~> 4.6'
gem 'devise-two-factor', '~> 3.0' gem 'devise-two-factor', '~> 3.0'
@ -42,7 +42,7 @@ gem 'omniauth-cas', '~> 1.1'
gem 'omniauth-saml', '~> 1.10' gem 'omniauth-saml', '~> 1.10'
gem 'omniauth', '~> 1.9' gem 'omniauth', '~> 1.9'
gem 'doorkeeper', '~> 5.0' gem 'doorkeeper', '~> 5.1'
gem 'fast_blank', '~> 1.0' gem 'fast_blank', '~> 1.0'
gem 'fastimage' gem 'fastimage'
gem 'goldfinger', '~> 2.1' gem 'goldfinger', '~> 2.1'
@ -143,7 +143,7 @@ group :development do
end end
group :production do group :production do
gem 'lograge', '~> 0.10' gem 'lograge', '~> 0.11'
gem 'redis-rails', '~> 5.0' gem 'redis-rails', '~> 5.0'
end end

View file

@ -76,16 +76,16 @@ GEM
av (0.9.0) av (0.9.0)
cocaine (~> 0.5.3) cocaine (~> 0.5.3)
aws-eventstream (1.0.2) aws-eventstream (1.0.2)
aws-partitions (1.147.0) aws-partitions (1.151.0)
aws-sdk-core (3.48.3) aws-sdk-core (3.48.4)
aws-eventstream (~> 1.0, >= 1.0.2) aws-eventstream (~> 1.0, >= 1.0.2)
aws-partitions (~> 1.0) aws-partitions (~> 1.0)
aws-sigv4 (~> 1.1) aws-sigv4 (~> 1.1)
jmespath (~> 1.0) jmespath (~> 1.0)
aws-sdk-kms (1.16.0) aws-sdk-kms (1.17.0)
aws-sdk-core (~> 3, >= 3.48.2) aws-sdk-core (~> 3, >= 3.48.2)
aws-sigv4 (~> 1.1) aws-sigv4 (~> 1.1)
aws-sdk-s3 (1.36.0) aws-sdk-s3 (1.36.1)
aws-sdk-core (~> 3, >= 3.48.2) aws-sdk-core (~> 3, >= 3.48.2)
aws-sdk-kms (~> 1) aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.0) aws-sigv4 (~> 1.0)
@ -143,8 +143,8 @@ GEM
elasticsearch (>= 2.0.0) elasticsearch (>= 2.0.0)
elasticsearch-dsl elasticsearch-dsl
chunky_png (1.3.10) chunky_png (1.3.10)
cld3 (3.2.3) cld3 (3.2.4)
ffi (>= 1.1.0, < 1.10.0) ffi (>= 1.1.0, < 1.11.0)
climate_control (0.2.0) climate_control (0.2.0)
cocaine (0.5.8) cocaine (0.5.8)
climate_control (>= 0.0.3, < 1.0) climate_control (>= 0.0.3, < 1.0)
@ -184,8 +184,8 @@ GEM
docile (1.3.0) docile (1.3.0)
domain_name (0.5.20180417) domain_name (0.5.20180417)
unf (>= 0.0.5, < 1.0.0) unf (>= 0.0.5, < 1.0.0)
doorkeeper (5.0.2) doorkeeper (5.1.0)
railties (>= 4.2) railties (>= 5)
dotenv (2.7.2) dotenv (2.7.2)
dotenv-rails (2.7.2) dotenv-rails (2.7.2)
dotenv (= 2.7.2) dotenv (= 2.7.2)
@ -212,7 +212,7 @@ GEM
multipart-post (>= 1.2, < 3) multipart-post (>= 1.2, < 3)
fast_blank (1.0.0) fast_blank (1.0.0)
fastimage (2.1.5) fastimage (2.1.5)
ffi (1.9.25) ffi (1.10.0)
fog-core (2.1.0) fog-core (2.1.0)
builder builder
excon (~> 0.58) excon (~> 0.58)
@ -320,7 +320,7 @@ GEM
letter_opener (~> 1.0) letter_opener (~> 1.0)
railties (>= 3.2) railties (>= 3.2)
link_header (0.0.8) link_header (0.0.8)
lograge (0.10.0) lograge (0.11.0)
actionpack (>= 4) actionpack (>= 4)
activesupport (>= 4) activesupport (>= 4)
railties (>= 4) railties (>= 4)
@ -642,7 +642,7 @@ GEM
activesupport (>= 4.2) activesupport (>= 4.2)
rack-proxy (>= 0.6.1) rack-proxy (>= 0.6.1)
railties (>= 4.2) railties (>= 4.2)
webpush (0.3.7) webpush (0.3.8)
hkdf (~> 0.2) hkdf (~> 0.2)
jwt (~> 2.0) jwt (~> 2.0)
websocket-driver (0.7.0) websocket-driver (0.7.0)
@ -675,14 +675,14 @@ DEPENDENCIES
capybara (~> 3.16) capybara (~> 3.16)
charlock_holmes (~> 0.7.6) charlock_holmes (~> 0.7.6)
chewy (~> 5.0) chewy (~> 5.0)
cld3 (~> 3.2.3) cld3 (~> 3.2.4)
climate_control (~> 0.2) climate_control (~> 0.2)
concurrent-ruby concurrent-ruby
derailed_benchmarks derailed_benchmarks
devise (~> 4.6) devise (~> 4.6)
devise-two-factor (~> 3.0) devise-two-factor (~> 3.0)
devise_pam_authenticatable2 (~> 9.2) devise_pam_authenticatable2 (~> 9.2)
doorkeeper (~> 5.0) doorkeeper (~> 5.1)
dotenv-rails (~> 2.7) dotenv-rails (~> 2.7)
fabrication (~> 2.20) fabrication (~> 2.20)
faker (~> 1.9) faker (~> 1.9)
@ -709,7 +709,7 @@ DEPENDENCIES
letter_opener (~> 1.7) letter_opener (~> 1.7)
letter_opener_web (~> 1.3) letter_opener_web (~> 1.3)
link_header (~> 0.0) link_header (~> 0.0)
lograge (~> 0.10) lograge (~> 0.11)
makara (~> 0.4) makara (~> 0.4)
mario-redis-lock (~> 1.2) mario-redis-lock (~> 1.2)
memory_profiler memory_profiler

View file

@ -41,3 +41,26 @@ delegate(document, '.modal-button', 'click', e => {
window.open(href, 'mastodon-intent', 'width=445,height=600,resizable=no,menubar=no,status=no,scrollbars=yes'); window.open(href, 'mastodon-intent', 'width=445,height=600,resizable=no,menubar=no,status=no,scrollbars=yes');
}); });
const getProfileAvatarAnimationHandler = (swapTo) => {
//animate avatar gifs on the profile page when moused over
return ({ target }) => {
const swapSrc = target.getAttribute(swapTo);
//only change the img source if autoplay is off and the image src is actually different
if(target.getAttribute('data-autoplay') === 'false' && target.src !== swapSrc) {
target.src = swapSrc;
}
};
};
delegate(document, 'img#profile_page_avatar', 'mouseover', getProfileAvatarAnimationHandler('data-original'));
delegate(document, 'img#profile_page_avatar', 'mouseout', getProfileAvatarAnimationHandler('data-static'));
delegate(document, '#account_header', 'change', ({ target }) => {
const header = document.querySelector('.card .card__img img');
const [file] = target.files || [];
const url = file ? URL.createObjectURL(file) : header.dataset.originalSrc;
header.src = url;
});

View file

@ -114,7 +114,7 @@ export default class ActionsModal extends ImmutablePureComponent {
<div className='modal-root__modal actions-modal'> <div className='modal-root__modal actions-modal'>
{status} {status}
<ul> <ul className={classNames({ 'with-status': !!status })}>
{this.props.actions.map(this.renderAction)} {this.props.actions.map(this.renderAction)}
</ul> </ul>
</div> </div>

View file

@ -621,6 +621,11 @@
ul { ul {
overflow-y: auto; overflow-y: auto;
flex-shrink: 0; flex-shrink: 0;
max-height: 80vh;
&.with-status {
max-height: calc(80vh - 75px);
}
li:empty { li:empty {
margin: 0; margin: 0;

View file

@ -41,17 +41,16 @@ class ComposeForm extends ImmutablePureComponent {
static propTypes = { static propTypes = {
intl: PropTypes.object.isRequired, intl: PropTypes.object.isRequired,
text: PropTypes.string.isRequired, text: PropTypes.string.isRequired,
suggestion_token: PropTypes.string,
suggestions: ImmutablePropTypes.list, suggestions: ImmutablePropTypes.list,
spoiler: PropTypes.bool, spoiler: PropTypes.bool,
privacy: PropTypes.string, privacy: PropTypes.string,
spoiler_text: PropTypes.string, spoilerText: PropTypes.string,
focusDate: PropTypes.instanceOf(Date), focusDate: PropTypes.instanceOf(Date),
caretPosition: PropTypes.number, caretPosition: PropTypes.number,
preselectDate: PropTypes.instanceOf(Date), preselectDate: PropTypes.instanceOf(Date),
is_submitting: PropTypes.bool, isSubmitting: PropTypes.bool,
is_changing_upload: PropTypes.bool, isChangingUpload: PropTypes.bool,
is_uploading: PropTypes.bool, isUploading: PropTypes.bool,
onChange: PropTypes.func.isRequired, onChange: PropTypes.func.isRequired,
onSubmit: PropTypes.func.isRequired, onSubmit: PropTypes.func.isRequired,
onClearSuggestions: PropTypes.func.isRequired, onClearSuggestions: PropTypes.func.isRequired,
@ -86,10 +85,10 @@ class ComposeForm extends ImmutablePureComponent {
} }
// Submit disabled: // Submit disabled:
const { is_submitting, is_changing_upload, is_uploading, anyMedia } = this.props; const { isSubmitting, isChangingUpload, isUploading, anyMedia } = this.props;
const fulltext = [this.props.spoiler_text, countableText(this.props.text)].join(''); const fulltext = [this.props.spoilerText, countableText(this.props.text)].join('');
if (is_submitting || is_uploading || is_changing_upload || length(fulltext) > maxChars || (fulltext.length !== 0 && fulltext.trim().length === 0 && !anyMedia)) { if (isSubmitting || isUploading || isChangingUpload || length(fulltext) > maxChars || (fulltext.length !== 0 && fulltext.trim().length === 0 && !anyMedia)) {
return; return;
} }
@ -134,7 +133,7 @@ class ComposeForm extends ImmutablePureComponent {
this.autosuggestTextarea.textarea.setSelectionRange(selectionStart, selectionEnd); this.autosuggestTextarea.textarea.setSelectionRange(selectionStart, selectionEnd);
this.autosuggestTextarea.textarea.focus(); this.autosuggestTextarea.textarea.focus();
} else if(prevProps.is_submitting && !this.props.is_submitting) { } else if(prevProps.isSubmitting && !this.props.isSubmitting) {
this.autosuggestTextarea.textarea.focus(); this.autosuggestTextarea.textarea.focus();
} else if (this.props.spoiler !== prevProps.spoiler) { } else if (this.props.spoiler !== prevProps.spoiler) {
if (this.props.spoiler) { if (this.props.spoiler) {
@ -163,9 +162,9 @@ class ComposeForm extends ImmutablePureComponent {
render () { render () {
const { intl, onPaste, showSearch, anyMedia } = this.props; const { intl, onPaste, showSearch, anyMedia } = this.props;
const disabled = this.props.is_submitting; const disabled = this.props.isSubmitting;
const text = [this.props.spoiler_text, countableText(this.props.text)].join(''); const text = [this.props.spoilerText, countableText(this.props.text)].join('');
const disabledButton = disabled || this.props.is_uploading || this.props.is_changing_upload || length(text) > maxChars || (text.length !== 0 && text.trim().length === 0 && !anyMedia); const disabledButton = disabled || this.props.isUploading || this.props.isChangingUpload || length(text) > maxChars || (text.length !== 0 && text.trim().length === 0 && !anyMedia);
let publishText = ''; let publishText = '';
if (this.props.privacy === 'private' || this.props.privacy === 'direct') { if (this.props.privacy === 'private' || this.props.privacy === 'direct') {
@ -183,7 +182,7 @@ class ComposeForm extends ImmutablePureComponent {
<div className={`spoiler-input ${this.props.spoiler ? 'spoiler-input--visible' : ''}`}> <div className={`spoiler-input ${this.props.spoiler ? 'spoiler-input--visible' : ''}`}>
<label> <label>
<span style={{ display: 'none' }}>{intl.formatMessage(messages.spoiler_placeholder)}</span> <span style={{ display: 'none' }}>{intl.formatMessage(messages.spoiler_placeholder)}</span>
<input placeholder={intl.formatMessage(messages.spoiler_placeholder)} value={this.props.spoiler_text} onChange={this.handleChangeSpoilerText} onKeyDown={this.handleKeyDown} tabIndex={this.props.spoiler ? 0 : -1} type='text' className='spoiler-input__input' id='cw-spoiler-input' ref={this.setSpoilerText} /> <input placeholder={intl.formatMessage(messages.spoiler_placeholder)} value={this.props.spoilerText} onChange={this.handleChangeSpoilerText} onKeyDown={this.handleKeyDown} tabIndex={this.props.spoiler ? 0 : -1} type='text' className='spoiler-input__input' id='cw-spoiler-input' ref={this.setSpoilerText} />
</label> </label>
</div> </div>

View file

@ -26,6 +26,7 @@ class Option extends React.PureComponent {
isPollMultiple: PropTypes.bool, isPollMultiple: PropTypes.bool,
onChange: PropTypes.func.isRequired, onChange: PropTypes.func.isRequired,
onRemove: PropTypes.func.isRequired, onRemove: PropTypes.func.isRequired,
onToggleMultiple: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired, intl: PropTypes.object.isRequired,
}; };
@ -37,13 +38,24 @@ class Option extends React.PureComponent {
this.props.onRemove(this.props.index); this.props.onRemove(this.props.index);
}; };
handleToggleMultiple = e => {
this.props.onToggleMultiple();
e.preventDefault();
e.stopPropagation();
};
render () { render () {
const { isPollMultiple, title, index, intl } = this.props; const { isPollMultiple, title, index, intl } = this.props;
return ( return (
<li> <li>
<label className='poll__text editable'> <label className='poll__text editable'>
<span className={classNames('poll__input', { checkbox: isPollMultiple })} /> <span
className={classNames('poll__input', { checkbox: isPollMultiple })}
onClick={this.handleToggleMultiple}
role='button'
tabIndex='0'
/>
<input <input
type='text' type='text'
@ -86,6 +98,10 @@ class PollForm extends ImmutablePureComponent {
this.props.onChangeSettings(e.target.value, this.props.isMultiple); this.props.onChangeSettings(e.target.value, this.props.isMultiple);
}; };
handleToggleMultiple = () => {
this.props.onChangeSettings(this.props.expiresIn, !this.props.isMultiple);
};
render () { render () {
const { options, expiresIn, isMultiple, onChangeOption, onRemoveOption, intl } = this.props; const { options, expiresIn, isMultiple, onChangeOption, onRemoveOption, intl } = this.props;
@ -96,7 +112,7 @@ class PollForm extends ImmutablePureComponent {
return ( return (
<div className='compose-form__poll-wrapper'> <div className='compose-form__poll-wrapper'>
<ul> <ul>
{options.map((title, i) => <Option title={title} key={i} index={i} onChange={onChangeOption} onRemove={onRemoveOption} isPollMultiple={isMultiple} />)} {options.map((title, i) => <Option title={title} key={i} index={i} onChange={onChangeOption} onRemove={onRemoveOption} isPollMultiple={isMultiple} onToggleMultiple={this.handleToggleMultiple} />)}
</ul> </ul>
<div className='poll__footer'> <div className='poll__footer'>

View file

@ -73,7 +73,7 @@ class Search extends React.PureComponent {
} }
} }
handleKeyDown = (e) => { handleKeyUp = (e) => {
if (e.key === 'Enter') { if (e.key === 'Enter') {
e.preventDefault(); e.preventDefault();
this.props.onSubmit(); this.props.onSubmit();
@ -82,10 +82,6 @@ class Search extends React.PureComponent {
} }
} }
noop () {
}
handleFocus = () => { handleFocus = () => {
this.setState({ expanded: true }); this.setState({ expanded: true });
this.props.onShow(); this.props.onShow();
@ -110,7 +106,7 @@ class Search extends React.PureComponent {
placeholder={intl.formatMessage(messages.placeholder)} placeholder={intl.formatMessage(messages.placeholder)}
value={value} value={value}
onChange={this.handleChange} onChange={this.handleChange}
onKeyUp={this.handleKeyDown} onKeyUp={this.handleKeyUp}
onFocus={this.handleFocus} onFocus={this.handleFocus}
onBlur={this.handleBlur} onBlur={this.handleBlur}
/> />

View file

@ -1,6 +1,5 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import ComposeForm from '../components/compose_form'; import ComposeForm from '../components/compose_form';
import { uploadCompose } from '../../../actions/compose';
import { import {
changeCompose, changeCompose,
submitCompose, submitCompose,
@ -9,21 +8,21 @@ import {
selectComposeSuggestion, selectComposeSuggestion,
changeComposeSpoilerText, changeComposeSpoilerText,
insertEmojiCompose, insertEmojiCompose,
uploadCompose,
} from '../../../actions/compose'; } from '../../../actions/compose';
const mapStateToProps = state => ({ const mapStateToProps = state => ({
text: state.getIn(['compose', 'text']), text: state.getIn(['compose', 'text']),
suggestion_token: state.getIn(['compose', 'suggestion_token']),
suggestions: state.getIn(['compose', 'suggestions']), suggestions: state.getIn(['compose', 'suggestions']),
spoiler: state.getIn(['compose', 'spoiler']), spoiler: state.getIn(['compose', 'spoiler']),
spoiler_text: state.getIn(['compose', 'spoiler_text']), spoilerText: state.getIn(['compose', 'spoiler_text']),
privacy: state.getIn(['compose', 'privacy']), privacy: state.getIn(['compose', 'privacy']),
focusDate: state.getIn(['compose', 'focusDate']), focusDate: state.getIn(['compose', 'focusDate']),
caretPosition: state.getIn(['compose', 'caretPosition']), caretPosition: state.getIn(['compose', 'caretPosition']),
preselectDate: state.getIn(['compose', 'preselectDate']), preselectDate: state.getIn(['compose', 'preselectDate']),
is_submitting: state.getIn(['compose', 'is_submitting']), is_submitting: state.getIn(['compose', 'is_submitting']),
is_changing_upload: state.getIn(['compose', 'is_changing_upload']), isChangingUpload: state.getIn(['compose', 'is_changing_upload']),
is_uploading: state.getIn(['compose', 'is_uploading']), isUploading: state.getIn(['compose', 'is_uploading']),
showSearch: state.getIn(['search', 'submitted']) && !state.getIn(['search', 'hidden']), showSearch: state.getIn(['search', 'submitted']) && !state.getIn(['search', 'hidden']),
anyMedia: state.getIn(['compose', 'media_attachments']).size > 0, anyMedia: state.getIn(['compose', 'media_attachments']).size > 0,
}); });
@ -46,8 +45,8 @@ const mapDispatchToProps = (dispatch) => ({
dispatch(fetchComposeSuggestions(token)); dispatch(fetchComposeSuggestions(token));
}, },
onSuggestionSelected (position, token, accountId) { onSuggestionSelected (position, token, suggestion) {
dispatch(selectComposeSuggestion(position, token, accountId)); dispatch(selectComposeSuggestion(position, token, suggestion));
}, },
onChangeSpoilerText (checked) { onChangeSpoilerText (checked) {

View file

@ -7,7 +7,7 @@ import { connect } from 'react-redux';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component'; import ImmutablePureComponent from 'react-immutable-pure-component';
import { me, invitesEnabled, version, profile_directory } from '../../initial_state'; import { me, invitesEnabled, version, profile_directory, repository, source_url } from '../../initial_state';
import { fetchFollowRequests } from '../../actions/accounts'; import { fetchFollowRequests } from '../../actions/accounts';
import { List as ImmutableList } from 'immutable'; import { List as ImmutableList } from 'immutable';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
@ -172,7 +172,7 @@ class GettingStarted extends ImmutablePureComponent {
<FormattedMessage <FormattedMessage
id='getting_started.open_source_notice' id='getting_started.open_source_notice'
defaultMessage='Mastodon is open source software. You can contribute or report issues on GitHub at {github}.' defaultMessage='Mastodon is open source software. You can contribute or report issues on GitHub at {github}.'
values={{ github: <span><a href='https://github.com/tootsuite/mastodon' rel='noopener' target='_blank'>tootsuite/mastodon</a> (v{version})</span> }} values={{ github: <span><a href={source_url} rel='noopener' target='_blank'>{repository}</a> (v{version})</span> }}
/> />
</p> </p>
</div> </div>

View file

@ -64,7 +64,7 @@ export default class ActionsModal extends ImmutablePureComponent {
<div className='modal-root__modal actions-modal'> <div className='modal-root__modal actions-modal'>
{status} {status}
<ul> <ul className={classNames({ 'with-status': !!status })}>
{this.props.actions.map(this.renderAction)} {this.props.actions.map(this.renderAction)}
</ul> </ul>
</div> </div>

View file

@ -14,6 +14,8 @@ export const me = getMeta('me');
export const searchEnabled = getMeta('search_enabled'); export const searchEnabled = getMeta('search_enabled');
export const maxChars = (initialState && initialState.max_toot_chars) || 500; export const maxChars = (initialState && initialState.max_toot_chars) || 500;
export const invitesEnabled = getMeta('invites_enabled'); export const invitesEnabled = getMeta('invites_enabled');
export const repository = getMeta('repository');
export const source_url = getMeta('source_url');
export const version = getMeta('version'); export const version = getMeta('version');
export const mascot = getMeta('mascot'); export const mascot = getMeta('mascot');
export const profile_directory = getMeta('profile_directory'); export const profile_directory = getMeta('profile_directory');

View file

@ -0,0 +1,384 @@
{
"account.add_or_remove_from_list": "Add or Remove from lists",
"account.badges.bot": "Bot",
"account.block": "Block @{name}",
"account.block_domain": "Hide everything from {domain}",
"account.blocked": "Blocked",
"account.direct": "Direct message @{name}",
"account.domain_blocked": "Domain hidden",
"account.edit_profile": "Edit profile",
"account.endorse": "Feature on profile",
"account.follow": "Follow",
"account.followers": "Followers",
"account.followers.empty": "No one follows this user yet.",
"account.follows": "Follows",
"account.follows.empty": "This user doesn't follow anyone yet.",
"account.follows_you": "Follows you",
"account.hide_reblogs": "Hide boosts from @{name}",
"account.link_verified_on": "Ownership of this link was checked on {date}",
"account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.",
"account.media": "Media",
"account.mention": "Mention @{name}",
"account.moved_to": "{name} has moved to:",
"account.mute": "Mute @{name}",
"account.mute_notifications": "Mute notifications from @{name}",
"account.muted": "Muted",
"account.posts": "Toots",
"account.posts_with_replies": "Toots and replies",
"account.report": "Report @{name}",
"account.requested": "Awaiting approval. Click to cancel follow request",
"account.share": "Share @{name}'s profile",
"account.show_reblogs": "Show boosts from @{name}",
"account.unblock": "Unblock @{name}",
"account.unblock_domain": "Unhide {domain}",
"account.unendorse": "Don't feature on profile",
"account.unfollow": "Unfollow",
"account.unmute": "Unmute @{name}",
"account.unmute_notifications": "Unmute notifications from @{name}",
"alert.unexpected.message": "An unexpected error occurred.",
"alert.unexpected.title": "Oops!",
"boost_modal.combo": "You can press {combo} to skip this next time",
"bundle_column_error.body": "Something went wrong while loading this component.",
"bundle_column_error.retry": "Try again",
"bundle_column_error.title": "Network error",
"bundle_modal_error.close": "Close",
"bundle_modal_error.message": "Something went wrong while loading this component.",
"bundle_modal_error.retry": "Try again",
"column.blocks": "Blocked users",
"column.community": "Local timeline",
"column.direct": "Direct messages",
"column.domain_blocks": "Hidden domains",
"column.favourites": "Favourites",
"column.follow_requests": "Follow requests",
"column.home": "Home",
"column.lists": "Lists",
"column.mutes": "Muted users",
"column.notifications": "Notifications",
"column.pins": "Pinned toot",
"column.public": "Federated timeline",
"column_back_button.label": "Back",
"column_header.hide_settings": "Hide settings",
"column_header.moveLeft_settings": "Move column to the left",
"column_header.moveRight_settings": "Move column to the right",
"column_header.pin": "Pin",
"column_header.show_settings": "Show settings",
"column_header.unpin": "Unpin",
"column_subheading.settings": "Settings",
"community.column_settings.media_only": "Media Only",
"compose_form.direct_message_warning": "This toot will only be sent to all the mentioned users.",
"compose_form.direct_message_warning_learn_more": "Learn more",
"compose_form.hashtag_warning": "This toot won't be listed under any hashtag as it is unlisted. Only public toots can be searched by hashtag.",
"compose_form.lock_disclaimer": "Your account is not {locked}. Anyone can follow you to view your follower-only posts.",
"compose_form.lock_disclaimer.lock": "locked",
"compose_form.placeholder": "What is on your mind?",
"compose_form.poll.add_option": "Add a choice",
"compose_form.poll.duration": "Poll duration",
"compose_form.poll.option_placeholder": "Choice {number}",
"compose_form.poll.remove_option": "Remove this choice",
"compose_form.publish": "Toot",
"compose_form.publish_loud": "{publish}!",
"compose_form.sensitive.marked": "Media is marked as sensitive",
"compose_form.sensitive.unmarked": "Media is not marked as sensitive",
"compose_form.spoiler.marked": "Text is hidden behind warning",
"compose_form.spoiler.unmarked": "Text is not hidden",
"compose_form.spoiler_placeholder": "Write your warning here",
"confirmation_modal.cancel": "Cancel",
"confirmations.block.block_and_report": "Block & Report",
"confirmations.block.confirm": "Block",
"confirmations.block.message": "Are you sure you want to block {name}?",
"confirmations.delete.confirm": "Delete",
"confirmations.delete.message": "Are you sure you want to delete this status?",
"confirmations.delete_list.confirm": "Delete",
"confirmations.delete_list.message": "Are you sure you want to permanently delete this list?",
"confirmations.domain_block.confirm": "Hide entire domain",
"confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable. You will not see content from that domain in any public timelines or your notifications. Your followers from that domain will be removed.",
"confirmations.mute.confirm": "Mute",
"confirmations.mute.message": "Are you sure you want to mute {name}?",
"confirmations.redraft.confirm": "Delete & redraft",
"confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? Favourites and boosts will be lost, and replies to the original post will be orphaned.",
"confirmations.reply.confirm": "Reply",
"confirmations.reply.message": "Replying now will overwrite the message you are currently composing. Are you sure you want to proceed?",
"confirmations.unfollow.confirm": "Unfollow",
"confirmations.unfollow.message": "Are you sure you want to unfollow {name}?",
"embed.instructions": "Embed this status on your website by copying the code below.",
"embed.preview": "Here is what it will look like:",
"emoji_button.activity": "Activity",
"emoji_button.custom": "Custom",
"emoji_button.flags": "Flags",
"emoji_button.food": "Food & Drink",
"emoji_button.label": "Insert emoji",
"emoji_button.nature": "Nature",
"emoji_button.not_found": "No emojos!! (╯°□°)╯︵ ┻━┻",
"emoji_button.objects": "Objects",
"emoji_button.people": "People",
"emoji_button.recent": "Frequently used",
"emoji_button.search": "Search...",
"emoji_button.search_results": "Search results",
"emoji_button.symbols": "Symbols",
"emoji_button.travel": "Travel & Places",
"empty_column.account_timeline": "No toots here!",
"empty_column.account_unavailable": "Profile unavailable",
"empty_column.blocks": "You haven't blocked any users yet.",
"empty_column.community": "The local timeline is empty. Write something publicly to get the ball rolling!",
"empty_column.direct": "You don't have any direct messages yet. When you send or receive one, it will show up here.",
"empty_column.domain_blocks": "There are no hidden domains yet.",
"empty_column.favourited_statuses": "You don't have any favourite toots yet. When you favourite one, it will show up here.",
"empty_column.favourites": "No one has favourited this toot yet. When someone does, they will show up here.",
"empty_column.follow_requests": "You don't have any follow requests yet. When you receive one, it will show up here.",
"empty_column.hashtag": "There is nothing in this hashtag yet.",
"empty_column.home": "Your home timeline is empty! Visit {public} or use search to get started and meet other users.",
"empty_column.home.public_timeline": "the public timeline",
"empty_column.list": "There is nothing in this list yet. When members of this list post new statuses, they will appear here.",
"empty_column.lists": "You don't have any lists yet. When you create one, it will show up here.",
"empty_column.mutes": "You haven't muted any users yet.",
"empty_column.notifications": "You don't have any notifications yet. Interact with others to start the conversation.",
"empty_column.public": "There is nothing here! Write something publicly, or manually follow users from other servers to fill it up",
"follow_request.authorize": "Authorize",
"follow_request.reject": "Reject",
"getting_started.developers": "Developers",
"getting_started.directory": "Profile directory",
"getting_started.documentation": "Documentation",
"getting_started.heading": "Getting started",
"getting_started.invite": "Invite people",
"getting_started.open_source_notice": "Mastodon is open source software. You can contribute or report issues on GitHub at {github}.",
"getting_started.security": "Security",
"getting_started.terms": "Terms of service",
"hashtag.column_header.tag_mode.all": "and {additional}",
"hashtag.column_header.tag_mode.any": "or {additional}",
"hashtag.column_header.tag_mode.none": "without {additional}",
"hashtag.column_settings.select.no_options_message": "No suggestions found",
"hashtag.column_settings.select.placeholder": "Enter hashtags…",
"hashtag.column_settings.tag_mode.all": "All of these",
"hashtag.column_settings.tag_mode.any": "Any of these",
"hashtag.column_settings.tag_mode.none": "None of these",
"hashtag.column_settings.tag_toggle": "Include additional tags in this column",
"home.column_settings.basic": "Basic",
"home.column_settings.show_reblogs": "Show boosts",
"home.column_settings.show_replies": "Show replies",
"intervals.full.days": "{number, plural, one {# day} other {# days}}",
"intervals.full.hours": "{number, plural, one {# hour} other {# hours}}",
"intervals.full.minutes": "{number, plural, one {# minute} other {# minutes}}",
"introduction.federation.action": "Next",
"introduction.federation.federated.headline": "Federated",
"introduction.federation.federated.text": "Public posts from other servers of the fediverse will appear in the federated timeline.",
"introduction.federation.home.headline": "Home",
"introduction.federation.home.text": "Posts from people you follow will appear in your home feed. You can follow anyone on any server!",
"introduction.federation.local.headline": "Local",
"introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.",
"introduction.interactions.action": "Finish toot-orial!",
"introduction.interactions.favourite.headline": "Favourite",
"introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favouriting it.",
"introduction.interactions.reblog.headline": "Boost",
"introduction.interactions.reblog.text": "You can share other people's toots with your followers by boosting them.",
"introduction.interactions.reply.headline": "Reply",
"introduction.interactions.reply.text": "You can reply to other people's and your own toots, which will chain them together in a conversation.",
"introduction.welcome.action": "Let's go!",
"introduction.welcome.headline": "First steps",
"introduction.welcome.text": "Welcome to the fediverse! In a few moments, you'll be able to broadcast messages and talk to your friends across a wide variety of servers. But this server, {domain}, is special—it hosts your profile, so remember its name.",
"keyboard_shortcuts.back": "to navigate back",
"keyboard_shortcuts.blocked": "to open blocked users list",
"keyboard_shortcuts.boost": "to boost",
"keyboard_shortcuts.column": "to focus a status in one of the columns",
"keyboard_shortcuts.compose": "to focus the compose textarea",
"keyboard_shortcuts.description": "Description",
"keyboard_shortcuts.direct": "to open direct messages column",
"keyboard_shortcuts.down": "to move down in the list",
"keyboard_shortcuts.enter": "to open status",
"keyboard_shortcuts.favourite": "to favourite",
"keyboard_shortcuts.favourites": "to open favourites list",
"keyboard_shortcuts.federated": "to open federated timeline",
"keyboard_shortcuts.heading": "Keyboard Shortcuts",
"keyboard_shortcuts.home": "to open home timeline",
"keyboard_shortcuts.hotkey": "Hotkey",
"keyboard_shortcuts.legend": "to display this legend",
"keyboard_shortcuts.local": "to open local timeline",
"keyboard_shortcuts.mention": "to mention author",
"keyboard_shortcuts.muted": "to open muted users list",
"keyboard_shortcuts.my_profile": "to open your profile",
"keyboard_shortcuts.notifications": "to open notifications column",
"keyboard_shortcuts.pinned": "to open pinned toots list",
"keyboard_shortcuts.profile": "to open author's profile",
"keyboard_shortcuts.reply": "to reply",
"keyboard_shortcuts.requests": "to open follow requests list",
"keyboard_shortcuts.search": "to focus search",
"keyboard_shortcuts.start": "to open \"get started\" column",
"keyboard_shortcuts.toggle_hidden": "to show/hide text behind CW",
"keyboard_shortcuts.toot": "to start a brand new toot",
"keyboard_shortcuts.unfocus": "to un-focus compose textarea/search",
"keyboard_shortcuts.up": "to move up in the list",
"lightbox.close": "Close",
"lightbox.next": "Next",
"lightbox.previous": "Previous",
"lists.account.add": "Add to list",
"lists.account.remove": "Remove from list",
"lists.delete": "Delete list",
"lists.edit": "Edit list",
"lists.edit.submit": "Change title",
"lists.new.create": "Add list",
"lists.new.title_placeholder": "New list title",
"lists.search": "Search among people you follow",
"lists.subheading": "Your lists",
"loading_indicator.label": "Loading...",
"media_gallery.toggle_visible": "Toggle visibility",
"missing_indicator.label": "Not found",
"missing_indicator.sublabel": "This resource could not be found",
"mute_modal.hide_notifications": "Hide notifications from this user?",
"navigation_bar.apps": "Mobile apps",
"navigation_bar.blocks": "Blocked users",
"navigation_bar.community_timeline": "Local timeline",
"navigation_bar.compose": "Compose new toot",
"navigation_bar.direct": "Direct messages",
"navigation_bar.discover": "Discover",
"navigation_bar.domain_blocks": "Hidden domains",
"navigation_bar.edit_profile": "Edit profile",
"navigation_bar.favourites": "Favourites",
"navigation_bar.filters": "Muted words",
"navigation_bar.follow_requests": "Follow requests",
"navigation_bar.info": "About this server",
"navigation_bar.keyboard_shortcuts": "Hotkeys",
"navigation_bar.lists": "Lists",
"navigation_bar.logout": "Logout",
"navigation_bar.mutes": "Muted users",
"navigation_bar.personal": "Personal",
"navigation_bar.pins": "Pinned toots",
"navigation_bar.preferences": "Preferences",
"navigation_bar.public_timeline": "Federated timeline",
"navigation_bar.security": "Security",
"notification.favourite": "{name} favourited your status",
"notification.follow": "{name} followed you",
"notification.mention": "{name} mentioned you",
"notification.poll": "A poll you have voted in has ended",
"notification.reblog": "{name} boosted your status",
"notifications.clear": "Clear notifications",
"notifications.clear_confirmation": "Are you sure you want to permanently clear all your notifications?",
"notifications.column_settings.alert": "Desktop notifications",
"notifications.column_settings.favourite": "Favourites:",
"notifications.column_settings.filter_bar.advanced": "Display all categories",
"notifications.column_settings.filter_bar.category": "Quick filter bar",
"notifications.column_settings.filter_bar.show": "Show",
"notifications.column_settings.follow": "New followers:",
"notifications.column_settings.mention": "Mentions:",
"notifications.column_settings.poll": "Poll results:",
"notifications.column_settings.push": "Push notifications",
"notifications.column_settings.reblog": "Boosts:",
"notifications.column_settings.show": "Show in column",
"notifications.column_settings.sound": "Play sound",
"notifications.filter.all": "All",
"notifications.filter.boosts": "Boosts",
"notifications.filter.favourites": "Favourites",
"notifications.filter.follows": "Follows",
"notifications.filter.mentions": "Mentions",
"notifications.filter.polls": "Poll results",
"notifications.group": "{count} notifications",
"poll.closed": "Closed",
"poll.refresh": "Refresh",
"poll.total_votes": "{count, plural, one {# vote} other {# votes}}",
"poll.vote": "Vote",
"poll_button.add_poll": "Add a poll",
"poll_button.remove_poll": "Remove poll",
"privacy.change": "Adjust status privacy",
"privacy.direct.long": "Post to mentioned users only",
"privacy.direct.short": "Direct",
"privacy.private.long": "Post to followers only",
"privacy.private.short": "Followers-only",
"privacy.public.long": "Post to public timelines",
"privacy.public.short": "Public",
"privacy.unlisted.long": "Do not show in public timelines",
"privacy.unlisted.short": "Unlisted",
"regeneration_indicator.label": "Loading…",
"regeneration_indicator.sublabel": "Your home feed is being prepared!",
"relative_time.days": "{number}d",
"relative_time.hours": "{number}h",
"relative_time.just_now": "now",
"relative_time.minutes": "{number}m",
"relative_time.seconds": "{number}s",
"reply_indicator.cancel": "Cancel",
"report.forward": "Forward to {target}",
"report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?",
"report.hint": "The report will be sent to your server moderators. You can provide an explanation of why you are reporting this account below:",
"report.placeholder": "Additional comments",
"report.submit": "Submit",
"report.target": "Report {target}",
"search.placeholder": "Search",
"search_popout.search_format": "Advanced search format",
"search_popout.tips.full_text": "Simple text returns statuses you have written, favourited, boosted, or have been mentioned in, as well as matching usernames, display names, and hashtags.",
"search_popout.tips.hashtag": "hashtag",
"search_popout.tips.status": "status",
"search_popout.tips.text": "Simple text returns matching display names, usernames and hashtags",
"search_popout.tips.user": "user",
"search_results.accounts": "People",
"search_results.hashtags": "Hashtags",
"search_results.statuses": "Toots",
"search_results.total": "{count, number} {count, plural, one {result} other {results}}",
"status.admin_account": "Open moderation interface for @{name}",
"status.admin_status": "Open this status in the moderation interface",
"status.block": "Block @{name}",
"status.cancel_reblog_private": "Unboost",
"status.cannot_reblog": "This post cannot be boosted",
"status.copy": "Copy link to status",
"status.delete": "Delete",
"status.detailed_status": "Detailed conversation view",
"status.direct": "Direct message @{name}",
"status.embed": "Embed",
"status.favourite": "Favourite",
"status.filtered": "Filtered",
"status.load_more": "Load more",
"status.media_hidden": "Media hidden",
"status.mention": "Mention @{name}",
"status.more": "More",
"status.mute": "Mute @{name}",
"status.mute_conversation": "Mute conversation",
"status.open": "Expand this status",
"status.pin": "Pin on profile",
"status.pinned": "Pinned toot",
"status.read_more": "Read more",
"status.reblog": "Boost",
"status.reblog_private": "Boost to original audience",
"status.reblogged_by": "{name} boosted",
"status.reblogs.empty": "No one has boosted this toot yet. When someone does, they will show up here.",
"status.redraft": "Delete & re-draft",
"status.reply": "Reply",
"status.replyAll": "Reply to thread",
"status.report": "Report @{name}",
"status.sensitive_toggle": "Click to view",
"status.sensitive_warning": "Sensitive content",
"status.share": "Share",
"status.show_less": "Show less",
"status.show_less_all": "Show less for all",
"status.show_more": "Show more",
"status.show_more_all": "Show more for all",
"status.show_thread": "Show thread",
"status.unmute_conversation": "Unmute conversation",
"status.unpin": "Unpin from profile",
"suggestions.dismiss": "Dismiss suggestion",
"suggestions.header": "You might be interested in…",
"tabs_bar.federated_timeline": "Federated",
"tabs_bar.home": "Home",
"tabs_bar.local_timeline": "Local",
"tabs_bar.notifications": "Notifications",
"tabs_bar.search": "Search",
"time_remaining.days": "{number, plural, one {# day} other {# days}} left",
"time_remaining.hours": "{number, plural, one {# hour} other {# hours}} left",
"time_remaining.minutes": "{number, plural, one {# minute} other {# minutes}} left",
"time_remaining.moments": "Moments remaining",
"time_remaining.seconds": "{number, plural, one {# second} other {# seconds}} left",
"trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
"ui.beforeunload": "Your draft will be lost if you leave Mastodon.",
"upload_area.title": "Drag & drop to upload",
"upload_button.label": "Add media (JPEG, PNG, GIF, WebM, MP4, MOV)",
"upload_error.limit": "File upload limit exceeded.",
"upload_error.poll": "File upload not allowed with polls.",
"upload_form.description": "Describe for the visually impaired",
"upload_form.focus": "Crop",
"upload_form.undo": "Delete",
"upload_progress.label": "Uploading...",
"video.close": "Close video",
"video.exit_fullscreen": "Exit full screen",
"video.expand": "Expand video",
"video.fullscreen": "Full screen",
"video.hide": "Hide video",
"video.mute": "Mute sound",
"video.pause": "Pause",
"video.play": "Play",
"video.unmute": "Unmute sound"
}

View file

@ -239,7 +239,7 @@
"navigation_bar.lists": "Ցանկեր", "navigation_bar.lists": "Ցանկեր",
"navigation_bar.logout": "Դուրս գալ", "navigation_bar.logout": "Դուրս գալ",
"navigation_bar.mutes": "Լռեցրած օգտատերեր", "navigation_bar.mutes": "Լռեցրած օգտատերեր",
"navigation_bar.personal": "Personal", "navigation_bar.personal": "Անձնական",
"navigation_bar.pins": "Ամրացված թթեր", "navigation_bar.pins": "Ամրացված թթեր",
"navigation_bar.preferences": "Նախապատվություններ", "navigation_bar.preferences": "Նախապատվություններ",
"navigation_bar.public_timeline": "Դաշնային հոսք", "navigation_bar.public_timeline": "Դաշնային հոսք",

View file

@ -11,7 +11,7 @@
"account.follow": "Volgen", "account.follow": "Volgen",
"account.followers": "Volgers", "account.followers": "Volgers",
"account.followers.empty": "Niemand volgt nog deze gebruiker.", "account.followers.empty": "Niemand volgt nog deze gebruiker.",
"account.follows": "Volgt", "account.follows": "Volgend",
"account.follows.empty": "Deze gebruiker volgt nog niemand.", "account.follows.empty": "Deze gebruiker volgt nog niemand.",
"account.follows_you": "Volgt jou", "account.follows_you": "Volgt jou",
"account.hide_reblogs": "Verberg boosts van @{name}", "account.hide_reblogs": "Verberg boosts van @{name}",

View file

@ -118,7 +118,6 @@
"emoji_button.travel": "Путешествия", "emoji_button.travel": "Путешествия",
"empty_column.account_timeline": "Статусов нет!", "empty_column.account_timeline": "Статусов нет!",
"empty_column.account_unavailable": "Профиль недоступен", "empty_column.account_unavailable": "Профиль недоступен",
"empty_column.account_timeline_blocked": "Вы заблокированы",
"empty_column.blocks": "Вы ещё никого не заблокировали.", "empty_column.blocks": "Вы ещё никого не заблокировали.",
"empty_column.community": "Локальная лента пуста. Напишите что-нибудь, чтобы разогреть народ!", "empty_column.community": "Локальная лента пуста. Напишите что-нибудь, чтобы разогреть народ!",
"empty_column.direct": "У Вас пока нет личных сообщений. Когда Вы начнёте их отправлять или получать, они появятся здесь.", "empty_column.direct": "У Вас пока нет личных сообщений. Когда Вы начнёте их отправлять или получать, они появятся здесь.",

View file

@ -0,0 +1,2 @@
[
]

View file

@ -10,7 +10,7 @@
@font-face { @font-face {
font-family: 'mastodon-font-display'; font-family: 'mastodon-font-display';
src: local('Montserrat'), src: local('Montserrat Medium'),
url('~fonts/montserrat/Montserrat-Medium.ttf') format('truetype'); url('~fonts/montserrat/Montserrat-Medium.ttf') format('truetype');
font-weight: 500; font-weight: 500;
font-style: normal; font-style: normal;

View file

@ -1,6 +1,6 @@
@font-face { @font-face {
font-family: 'mastodon-font-sans-serif'; font-family: 'mastodon-font-sans-serif';
src: local('Roboto'), src: local('Roboto Italic'),
url('~fonts/roboto/roboto-italic-webfont.woff2') format('woff2'), url('~fonts/roboto/roboto-italic-webfont.woff2') format('woff2'),
url('~fonts/roboto/roboto-italic-webfont.woff') format('woff'), url('~fonts/roboto/roboto-italic-webfont.woff') format('woff'),
url('~fonts/roboto/roboto-italic-webfont.ttf') format('truetype'), url('~fonts/roboto/roboto-italic-webfont.ttf') format('truetype'),
@ -11,7 +11,7 @@
@font-face { @font-face {
font-family: 'mastodon-font-sans-serif'; font-family: 'mastodon-font-sans-serif';
src: local('Roboto'), src: local('Roboto Bold'),
url('~fonts/roboto/roboto-bold-webfont.woff2') format('woff2'), url('~fonts/roboto/roboto-bold-webfont.woff2') format('woff2'),
url('~fonts/roboto/roboto-bold-webfont.woff') format('woff'), url('~fonts/roboto/roboto-bold-webfont.woff') format('woff'),
url('~fonts/roboto/roboto-bold-webfont.ttf') format('truetype'), url('~fonts/roboto/roboto-bold-webfont.ttf') format('truetype'),
@ -22,7 +22,7 @@
@font-face { @font-face {
font-family: 'mastodon-font-sans-serif'; font-family: 'mastodon-font-sans-serif';
src: local('Roboto'), src: local('Roboto Medium'),
url('~fonts/roboto/roboto-medium-webfont.woff2') format('woff2'), url('~fonts/roboto/roboto-medium-webfont.woff2') format('woff2'),
url('~fonts/roboto/roboto-medium-webfont.woff') format('woff'), url('~fonts/roboto/roboto-medium-webfont.woff') format('woff'),
url('~fonts/roboto/roboto-medium-webfont.ttf') format('truetype'), url('~fonts/roboto/roboto-medium-webfont.ttf') format('truetype'),

View file

@ -4085,6 +4085,11 @@ a.status-card.compact:hover {
ul { ul {
overflow-y: auto; overflow-y: auto;
flex-shrink: 0; flex-shrink: 0;
max-height: 80vh;
&.with-status {
max-height: calc(80vh - 75px);
}
li:empty { li:empty {
margin: 0; margin: 0;

View file

@ -2,7 +2,7 @@
class ProofProvider::Keybase class ProofProvider::Keybase
BASE_URL = ENV.fetch('KEYBASE_BASE_URL', 'https://keybase.io') BASE_URL = ENV.fetch('KEYBASE_BASE_URL', 'https://keybase.io')
DOMAIN = ENV.fetch('KEYBASE_DOMAIN', Rails.configuration.x.local_domain) DOMAIN = ENV.fetch('KEYBASE_DOMAIN', Rails.configuration.x.web_domain)
class Error < StandardError; end class Error < StandardError; end

View file

@ -28,6 +28,8 @@ class InitialStateSerializer < ActiveModel::Serializer
domain: Rails.configuration.x.local_domain, domain: Rails.configuration.x.local_domain,
admin: object.admin&.id&.to_s, admin: object.admin&.id&.to_s,
search_enabled: Chewy.enabled?, search_enabled: Chewy.enabled?,
repository: Mastodon::Version.repository,
source_url: Mastodon::Version.source_url,
version: Mastodon::Version.to_s, version: Mastodon::Version.to_s,
invites_enabled: Setting.min_invite_role == 'user', invites_enabled: Setting.min_invite_role == 'user',
mascot: instance_presenter.mascot&.file&.url, mascot: instance_presenter.mascot&.file&.url,

View file

@ -165,7 +165,7 @@ class FetchLinkCardService < BaseService
end end
def meta_property(page, property) def meta_property(page, property)
page.at_xpath("//meta[@property=\"#{property}\"]")&.attribute('content')&.value || page.at_xpath("//meta[@name=\"#{property}\"]")&.attribute('content')&.value page.at_xpath("//meta[contains(concat(' ', normalize-space(@property), ' '), ' #{property} ')]")&.attribute('content')&.value || page.at_xpath("//meta[@name=\"#{property}\"]")&.attribute('content')&.value
end end
def lock_options def lock_options

View file

@ -3,7 +3,7 @@
= image_tag (current_account&.user&.setting_auto_play_gif ? account.header_original_url : account.header_static_url), class: 'parallax' = image_tag (current_account&.user&.setting_auto_play_gif ? account.header_original_url : account.header_static_url), class: 'parallax'
.public-account-header__bar .public-account-header__bar
= link_to short_account_url(account), class: 'avatar' do = link_to short_account_url(account), class: 'avatar' do
= image_tag (current_account&.user&.setting_auto_play_gif ? account.avatar_original_url : account.avatar_static_url) = image_tag (current_account&.user&.setting_auto_play_gif ? account.avatar_original_url : account.avatar_static_url), id: 'profile_page_avatar', data: {original: full_asset_url(account.avatar_original_url), static: full_asset_url(account.avatar_static_url), autoplay: current_account&.user&.setting_auto_play_gif}
.public-account-header__tabs .public-account-header__tabs
.public-account-header__tabs__name .public-account-header__tabs__name
%h1 %h1

View file

@ -68,6 +68,7 @@ ca:
admin: Administrador admin: Administrador
bot: Bot bot: Bot
moderator: Moderador moderator: Moderador
unavailable: Perfil inaccessible
unfollow: Deixa de seguir unfollow: Deixa de seguir
admin: admin:
account_actions: account_actions:
@ -80,6 +81,7 @@ ca:
destroyed_msg: Nota de moderació destruïda amb èxit! destroyed_msg: Nota de moderació destruïda amb èxit!
accounts: accounts:
approve: Aprova approve: Aprova
approve_all: Aprova'ls tots
are_you_sure: N'estàs segur? are_you_sure: N'estàs segur?
avatar: Avatar avatar: Avatar
by_domain: Domini by_domain: Domini
@ -132,6 +134,7 @@ ca:
moderation_notes: Notes de moderació moderation_notes: Notes de moderació
most_recent_activity: Activitat més recent most_recent_activity: Activitat més recent
most_recent_ip: IP més recent most_recent_ip: IP més recent
no_account_selected: No s'han canviat els comptes perque no s'han seleccionat
no_limits_imposed: Sense límits imposats no_limits_imposed: Sense límits imposats
not_subscribed: No subscrit not_subscribed: No subscrit
outbox_url: URL de la bústia de sortida outbox_url: URL de la bústia de sortida
@ -144,6 +147,7 @@ ca:
push_subscription_expires: La subscripció PuSH expira push_subscription_expires: La subscripció PuSH expira
redownload: Actualitza el perfil redownload: Actualitza el perfil
reject: Rebutja reject: Rebutja
reject_all: Rebutja'ls tots
remove_avatar: Eliminar avatar remove_avatar: Eliminar avatar
remove_header: Treu la capçalera remove_header: Treu la capçalera
resend_confirmation: resend_confirmation:
@ -330,6 +334,8 @@ ca:
expired: Caducat expired: Caducat
title: Filtre title: Filtre
title: Convida title: Convida
pending_accounts:
title: Comptes pendents (%{count})
relays: relays:
add_new: Afegiu un nou relay add_new: Afegiu un nou relay
delete: Esborra delete: Esborra
@ -854,18 +860,23 @@ ca:
revoke_success: S'ha revocat la sessió amb èxit revoke_success: S'ha revocat la sessió amb èxit
title: Sessions title: Sessions
settings: settings:
account: Compte
account_settings: Ajustos del compte
appearance: Aparènça
authorized_apps: Aplicacions autoritzades authorized_apps: Aplicacions autoritzades
back: Torna a l'inici back: Torna a Mastodon
delete: Eliminació del compte delete: Eliminació del compte
development: Desenvolupament development: Desenvolupament
edit_profile: Editar perfil edit_profile: Editar perfil
export: Exportar informació export: Exportar dades
featured_tags: Etiquetes destacades featured_tags: Etiquetes destacades
identity_proofs: Proves d'identitat identity_proofs: Proves d'identitat
import: Importar import: Importar
import_and_export: Importar i exportar
migrate: Migració del compte migrate: Migració del compte
notifications: Notificacions notifications: Notificacions
preferences: Preferències preferences: Preferències
profile: Perfil
relationships: Seguits i seguidors relationships: Seguits i seguidors
two_factor_authentication: Autenticació de dos factors two_factor_authentication: Autenticació de dos factors
statuses: statuses:
@ -1040,7 +1051,7 @@ ca:
welcome: welcome:
edit_profile_action: Configurar perfil edit_profile_action: Configurar perfil
edit_profile_step: Pots personalitzar el teu perfil penjant un avatar, un encapçalament, canviant el teu nom de visualització i molt més. Si prefereixes revisar els seguidors nous abans de que et puguin seguir, pots blocar el teu compte. edit_profile_step: Pots personalitzar el teu perfil penjant un avatar, un encapçalament, canviant el teu nom de visualització i molt més. Si prefereixes revisar els seguidors nous abans de que et puguin seguir, pots blocar el teu compte.
explanation: Aquests són alguns consells per començar explanation: Aquests són alguns consells per a començar
final_action: Comença a publicar final_action: Comença a publicar
final_step: 'Comença a publicar! Fins i tot sense seguidors, els altres poden veure els teus missatges públics, per exemple, a la línia de temps local i a les etiquetes ("hashtags"). És possible que vulguis presentar-te amb l''etiqueta #introductions.' final_step: 'Comença a publicar! Fins i tot sense seguidors, els altres poden veure els teus missatges públics, per exemple, a la línia de temps local i a les etiquetes ("hashtags"). És possible que vulguis presentar-te amb l''etiqueta #introductions.'
full_handle: El teu nom d'usuari sencer full_handle: El teu nom d'usuari sencer

View file

@ -68,6 +68,7 @@ nl:
admin: Beheerder admin: Beheerder
bot: Bot bot: Bot
moderator: Moderator moderator: Moderator
unavailable: Profiel niet beschikbaar
unfollow: Ontvolgen unfollow: Ontvolgen
admin: admin:
account_actions: account_actions:
@ -80,6 +81,7 @@ nl:
destroyed_msg: Verwijderen van opmerking voor moderatoren geslaagd! destroyed_msg: Verwijderen van opmerking voor moderatoren geslaagd!
accounts: accounts:
approve: Goedkeuren approve: Goedkeuren
approve_all: Alles goedkeuren
are_you_sure: Weet je het zeker? are_you_sure: Weet je het zeker?
avatar: Avatar avatar: Avatar
by_domain: Domein by_domain: Domein
@ -132,6 +134,7 @@ nl:
moderation_notes: Opmerkingen voor moderatoren moderation_notes: Opmerkingen voor moderatoren
most_recent_activity: Laatst actief most_recent_activity: Laatst actief
most_recent_ip: Laatst gebruikt IP-adres most_recent_ip: Laatst gebruikt IP-adres
no_account_selected: Er zijn geen accounts veranderd, omdat er geen een was geselecteerd
no_limits_imposed: Geen limieten ingesteld no_limits_imposed: Geen limieten ingesteld
not_subscribed: Niet geabonneerd not_subscribed: Niet geabonneerd
outbox_url: Outbox-URL outbox_url: Outbox-URL
@ -144,6 +147,7 @@ nl:
push_subscription_expires: PuSH-abonnement verloopt op push_subscription_expires: PuSH-abonnement verloopt op
redownload: Profiel vernieuwen redownload: Profiel vernieuwen
reject: Afkeuren reject: Afkeuren
reject_all: Alles afkeuren
remove_avatar: Avatar verwijderen remove_avatar: Avatar verwijderen
remove_header: Omslagfoto verwijderen remove_header: Omslagfoto verwijderen
resend_confirmation: resend_confirmation:
@ -245,6 +249,7 @@ nl:
feature_profile_directory: Gebruikersgids feature_profile_directory: Gebruikersgids
feature_registrations: Registraties feature_registrations: Registraties
feature_relay: Federatierelay feature_relay: Federatierelay
feature_timeline_preview: Voorvertoning van tijdlijn
features: Functies features: Functies
hidden_service: Federatie met verborgen diensten hidden_service: Federatie met verborgen diensten
open_reports: onopgeloste rapportages open_reports: onopgeloste rapportages
@ -329,6 +334,8 @@ nl:
expired: Verlopen expired: Verlopen
title: Filter title: Filter
title: Uitnodigingen title: Uitnodigingen
pending_accounts:
title: Accounts in afwachting (%{count})
relays: relays:
add_new: Nieuwe relayserver toevoegen add_new: Nieuwe relayserver toevoegen
delete: Verwijderen delete: Verwijderen
@ -428,14 +435,14 @@ nl:
desc_html: Medewerkersbadge op profielpagina tonen desc_html: Medewerkersbadge op profielpagina tonen
title: Medewerkersbadge tonen title: Medewerkersbadge tonen
site_description: site_description:
desc_html: Dit wordt als een alinea op de voorpagina getoond. Beschrijf wat er speciaal is aan deze server en andere zaken die van belang zijn. Je kan HTML gebruiken, zoals <code>&lt;a&gt;</code> en <code>&lt;em&gt;</code>. desc_html: Introductie-alinea voor de API. Beschrijf wat er speciaal is aan deze server en andere zaken die van belang zijn. Je kan HTML gebruiken, zoals <code>&lt;a&gt;</code> en <code>&lt;em&gt;</code>.
title: Omschrijving Mastodonserver title: Omschrijving Mastodonserver (API)
site_description_extended: site_description_extended:
desc_html: Een goede plek voor je gedragscode, regels, richtlijnen en andere zaken die jouw server uniek maken. Je kan ook hier HTML gebruiken desc_html: Een goede plek voor je gedragscode, regels, richtlijnen en andere zaken die jouw server uniek maken. Je kan ook hier HTML gebruiken
title: Uitgebreide omschrijving Mastodonserver title: Uitgebreide omschrijving Mastodonserver
site_short_description: site_short_description:
desc_html: Dit wordt in de zijbalk getoond als en als metatag in de paginabron. Beschrijf in één alinea wat Mastodon is en wat deze server speciaal maakt. De (langere) omschrijving van de Mastodonserver wordt gebruikt wanneer dit veld wordt leeg gelaten. desc_html: Dit wordt gebruikt op de voorpagina, in de zijbalk op profielpagina's en als metatag in de paginabron. Beschrijf in één alinea wat Mastodon is en wat deze server speciaal maakt.
title: Korte omschrijving Mastodonserver title: Omschrijving Mastodonserver (website)
site_terms: site_terms:
desc_html: Je kan hier jouw eigen privacybeleid, gebruiksvoorwaarden en ander juridisch jargon kwijt. Je kan HTML gebruiken desc_html: Je kan hier jouw eigen privacybeleid, gebruiksvoorwaarden en ander juridisch jargon kwijt. Je kan HTML gebruiken
title: Aangepaste gebruiksvoorwaarden title: Aangepaste gebruiksvoorwaarden
@ -585,6 +592,9 @@ nl:
content: Het spijt ons, er is aan onze kant iets fout gegaan. content: Het spijt ons, er is aan onze kant iets fout gegaan.
title: Er is iets mis title: Er is iets mis
noscript_html: Schakel JavaScript in om de webapp van Mastodon te kunnen gebruiken. Als alternatief kan je een <a href="%{apps_path}">Mastodon-app</a> zoeken voor jouw platform. noscript_html: Schakel JavaScript in om de webapp van Mastodon te kunnen gebruiken. Als alternatief kan je een <a href="%{apps_path}">Mastodon-app</a> zoeken voor jouw platform.
existing_username_validator:
not_found: Kon geen lokale gebruiker met die gebruikersnaam vinden
not_found_multiple: Kon %{usernames} niet vinden
exports: exports:
archive_takeout: archive_takeout:
date: Datum date: Datum
@ -628,10 +638,13 @@ nl:
all: Alles all: Alles
changes_saved_msg: Wijzigingen succesvol opgeslagen! changes_saved_msg: Wijzigingen succesvol opgeslagen!
copy: Kopiëren copy: Kopiëren
order_by: Sorteer op
save_changes: Wijzigingen opslaan save_changes: Wijzigingen opslaan
validation_errors: validation_errors:
one: Er is iets niet helemaal goed! Bekijk onderstaande fout one: Er is iets niet helemaal goed! Bekijk onderstaande fout
other: Er is iets niet helemaal goed! Bekijk onderstaande %{count} fouten other: Er is iets niet helemaal goed! Bekijk onderstaande %{count} fouten
html_validator:
invalid_markup: 'bevat ongeldige HTML-opmaak: %{error}'
identity_proofs: identity_proofs:
active: Actief active: Actief
authorize: Ja, autoriseren authorize: Ja, autoriseren
@ -646,6 +659,8 @@ nl:
i_am_html: Ik ben %{username} op %{service}. i_am_html: Ik ben %{username} op %{service}.
identity: Identiteit identity: Identiteit
inactive: Inactief inactive: Inactief
publicize_checkbox: 'En toot dit:'
publicize_toot: 'Het is bewezen! Ik ben %{username} op %{service}: %{url}'
status: Verificatiestatus status: Verificatiestatus
view_proof: Bekijk bewijs view_proof: Bekijk bewijs
imports: imports:
@ -768,6 +783,8 @@ nl:
relationships: relationships:
activity: Accountactiviteit activity: Accountactiviteit
dormant: Sluimerend dormant: Sluimerend
last_active: Laatst actief
most_recent: Recentelijk gevolgd
moved: Verhuisd moved: Verhuisd
mutual: Wederzijds mutual: Wederzijds
primary: Primair primary: Primair
@ -843,6 +860,9 @@ nl:
revoke_success: Sessie succesvol ingetrokken revoke_success: Sessie succesvol ingetrokken
title: Sessies title: Sessies
settings: settings:
account: Account
account_settings: Accountinstellingen
appearance: Uiterlijk
authorized_apps: Geautoriseerde apps authorized_apps: Geautoriseerde apps
back: Terug naar Mastodon back: Terug naar Mastodon
delete: Account verwijderen delete: Account verwijderen
@ -852,9 +872,11 @@ nl:
featured_tags: Uitgelichte hashtags featured_tags: Uitgelichte hashtags
identity_proofs: Identiteitsbewijzen identity_proofs: Identiteitsbewijzen
import: Importeren import: Importeren
import_and_export: Importeren en exporteren
migrate: Accountmigratie migrate: Accountmigratie
notifications: Meldingen notifications: Meldingen
preferences: Voorkeuren preferences: Voorkeuren
profile: Profiel
relationships: Volgers en gevolgden relationships: Volgers en gevolgden
two_factor_authentication: Tweestapsverificatie two_factor_authentication: Tweestapsverificatie
statuses: statuses:

View file

@ -41,6 +41,8 @@ nl:
name: 'Je wilt misschien een van deze gebruiken:' name: 'Je wilt misschien een van deze gebruiken:'
imports: imports:
data: CSV-bestand dat op een andere Mastodonserver werd geëxporteerd data: CSV-bestand dat op een andere Mastodonserver werd geëxporteerd
invite_request:
text: Dit helpt ons om jouw aanvraag te beoordelen
sessions: sessions:
otp: 'Voer de tweestaps-aanmeldcode vanaf jouw mobiele telefoon in of gebruik een van jouw herstelcodes:' otp: 'Voer de tweestaps-aanmeldcode vanaf jouw mobiele telefoon in of gebruik een van jouw herstelcodes:'
user: user:
@ -118,12 +120,15 @@ nl:
must_be_follower: Meldingen van mensen die jou niet volgen blokkeren must_be_follower: Meldingen van mensen die jou niet volgen blokkeren
must_be_following: Meldingen van mensen die jij niet volgt blokkeren must_be_following: Meldingen van mensen die jij niet volgt blokkeren
must_be_following_dm: Directe berichten van mensen die jij niet volgt blokkeren must_be_following_dm: Directe berichten van mensen die jij niet volgt blokkeren
invite_request:
text: Waarom wil jij je aanmelden?
notification_emails: notification_emails:
digest: Periodiek e-mails met een samenvatting versturen digest: Periodiek e-mails met een samenvatting versturen
favourite: Een e-mail versturen wanneer iemand jouw toot aan hun favorieten heeft toegevoegd favourite: Een e-mail versturen wanneer iemand jouw toot aan hun favorieten heeft toegevoegd
follow: Een e-mail versturen wanneer iemand jou volgt follow: Een e-mail versturen wanneer iemand jou volgt
follow_request: Een e-mail versturen wanneer iemand jou wil volgen follow_request: Een e-mail versturen wanneer iemand jou wil volgen
mention: Een e-mail versturen wanneer iemand jou vermeld mention: Een e-mail versturen wanneer iemand jou vermeld
pending_account: Een e-mail verzenden wanneer een nieuw account moet worden beoordeeld
reblog: Een e-mail versturen wanneer iemand jouw toot heeft geboost reblog: Een e-mail versturen wanneer iemand jouw toot heeft geboost
report: Verstuur een e-mail wanneer een nieuw rapportage is ingediend report: Verstuur een e-mail wanneer een nieuw rapportage is ingediend
'no': Nee 'no': Nee

View file

@ -29,8 +29,8 @@ pl:
setting_aggregate_reblogs: Nie pokazuj nowych podbić dla wpisów, które zostały niedawno podbite (dotyczy tylko nowo otrzymanych podbić) setting_aggregate_reblogs: Nie pokazuj nowych podbić dla wpisów, które zostały niedawno podbite (dotyczy tylko nowo otrzymanych podbić)
setting_default_language: Język Twoich wpisów może być wykrywany automatycznie, ale nie zawsze jest to dokładne setting_default_language: Język Twoich wpisów może być wykrywany automatycznie, ale nie zawsze jest to dokładne
setting_display_media_default: Ukrywaj zawartość oznaczoną jako wrażliwa setting_display_media_default: Ukrywaj zawartość oznaczoną jako wrażliwa
setting_display_media_hide_all: Zawsze ukrywaj zawartość multimedialną setting_display_media_hide_all: Zawsze oznaczaj zawartość multimedialną jako wrażliwą
setting_display_media_show_all: Zawsze pokazuj zawartość multimedialną jako wrażliwą setting_display_media_show_all: Nie ukrywaj zawartości multimedialnej oznaczonej jako wrażliwa
setting_hide_network: Informacje o tym, kto Cię śledzi i kogo śledzisz nie będą widoczne setting_hide_network: Informacje o tym, kto Cię śledzi i kogo śledzisz nie będą widoczne
setting_noindex: Wpływa na widoczność strony profilu i Twoich wpisów setting_noindex: Wpływa na widoczność strony profilu i Twoich wpisów
setting_show_application: W informacjach o wpisie będzie widoczna informacja o aplikacji, z której został wysłany setting_show_application: W informacjach o wpisie będzie widoczna informacja o aplikacji, z której został wysłany

View file

@ -37,11 +37,11 @@ module Mastodon
end end
def repository def repository
'glitch-soc/mastodon' ENV.fetch('GITHUB_REPOSITORY') { 'glitch-soc/mastodon' }
end end
def source_base_url def source_base_url
"https://github.com/#{repository}" ENV.fetch('SOURCE_BASE_URL') { "https://github.com/#{repository}" }
end end
# specify git tag or commit hash here # specify git tag or commit hash here