Merge remote-tracking branch 'origin/master' into gs-master

th-downstream
David Yip 7 years ago
commit ec18363c3b

@ -22,3 +22,11 @@
/app/views/user_mailer/*.fr.text.erb @aldarone
/config/locales/*.fr.yml @aldarone
/config/locales/fr.yml @aldarone
# Dutch
/app/javascript/mastodon/locales/nl.json @jeroenpraat
/app/javascript/mastodon/locales/whitelist_nl.json @jeroenpraat
/app/views/user_mailer/*.nl.html.erb @jeroenpraat
/app/views/user_mailer/*.nl.text.erb @jeroenpraat
/config/locales/*.nl.yml @jeroenpraat
/config/locales/nl.yml @jeroenpraat

@ -193,7 +193,7 @@ GEM
railties (>= 4.0.1)
hamster (3.0.0)
concurrent-ruby (~> 1.0)
hashdiff (0.3.6)
hashdiff (0.3.7)
highline (1.7.8)
hiredis (0.6.1)
hkdf (0.3.0)
@ -513,7 +513,7 @@ GEM
uniform_notifier (1.10.0)
warden (1.2.7)
rack (>= 1.0)
webmock (3.0.1)
webmock (3.1.0)
addressable (>= 2.3.6)
crack (>= 0.3.2)
hashdiff

@ -31,10 +31,12 @@ module Admin
emoji = CustomEmoji.new(domain: nil, shortcode: @custom_emoji.shortcode, image: @custom_emoji.image)
if emoji.save
redirect_to admin_custom_emojis_path, notice: I18n.t('admin.custom_emojis.copied_msg')
flash[:notice] = I18n.t('admin.custom_emojis.copied_msg')
else
redirect_to admin_custom_emojis_path, alert: I18n.t('admin.custom_emojis.copy_failed_msg')
flash[:alert] = I18n.t('admin.custom_emojis.copy_failed_msg')
end
redirect_to admin_custom_emojis_path(params[:page])
end
def enable

@ -6,7 +6,7 @@ class Auth::RegistrationsController < Devise::RegistrationsController
before_action :check_enabled_registrations, only: [:new, :create]
before_action :configure_sign_up_params, only: [:create]
before_action :set_sessions, only: [:edit, :update]
before_action :set_instance_presenter, only: [:new, :update]
before_action :set_instance_presenter, only: [:new, :create, :update]
def destroy
not_found

@ -7,12 +7,14 @@ module UserTrackingConcern
UPDATE_SIGN_IN_HOURS = 24
included do
before_action :set_user_activity, if: %i(user_signed_in? user_needs_sign_in_update?)
before_action :set_user_activity
end
private
def set_user_activity
return unless user_needs_sign_in_update?
# Mark as signed-in today
current_user.update_tracked_fields!(request)
@ -21,7 +23,7 @@ module UserTrackingConcern
end
def user_needs_sign_in_update?
current_user.current_sign_in_at.nil? || current_user.current_sign_in_at < UPDATE_SIGN_IN_HOURS.hours.ago
user_signed_in? && (current_user.current_sign_in_at.nil? || current_user.current_sign_in_at < UPDATE_SIGN_IN_HOURS.hours.ago)
end
def user_needs_feed_update?

@ -122,7 +122,7 @@ export function unfollowAccount(id) {
dispatch(unfollowAccountRequest(id));
api(getState).post(`/api/v1/accounts/${id}/unfollow`).then(response => {
dispatch(unfollowAccountSuccess(response.data));
dispatch(unfollowAccountSuccess(response.data, getState().get('statuses')));
}).catch(error => {
dispatch(unfollowAccountFail(error));
});
@ -157,10 +157,11 @@ export function unfollowAccountRequest(id) {
};
};
export function unfollowAccountSuccess(relationship) {
export function unfollowAccountSuccess(relationship, statuses) {
return {
type: ACCOUNT_UNFOLLOW_SUCCESS,
relationship,
statuses,
};
};

@ -94,6 +94,10 @@ export default class RelativeTimestamp extends React.Component {
this._scheduleNextUpdate(nextProps, nextState);
}
componentWillUnmount () {
clearTimeout(this._timer);
}
_scheduleNextUpdate (props, state) {
clearTimeout(this._timer);

@ -5,5 +5,5 @@ const urlPlaceholder = 'xxxxxxxxxxxxxxxxxxxxxxx';
export function countableText(inputText) {
return inputText
.replace(urlRegex, urlPlaceholder)
.replace(/(?:^|[^\/\w])@(([a-z0-9_]+)@[a-z0-9\.\-]+)/ig, '@$2');
.replace(/(?:^|[^\/\w])@(([a-z0-9_]+)@[a-z0-9\.\-]+[a-z0-9]+)/ig, '@$2');
};

@ -16,7 +16,6 @@ const messages = defineMessages({
const mapStateToProps = state => ({
hasUnread: state.getIn(['timelines', 'home', 'unread']) > 0,
hasFollows: state.getIn(['accounts_counters', state.getIn(['meta', 'me']), 'following_count']) > 0,
});
@connect(mapStateToProps)
@ -27,7 +26,6 @@ export default class HomeTimeline extends React.PureComponent {
dispatch: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired,
hasUnread: PropTypes.bool,
hasFollows: PropTypes.bool,
columnId: PropTypes.string,
multiColumn: PropTypes.bool,
};
@ -60,17 +58,9 @@ export default class HomeTimeline extends React.PureComponent {
}
render () {
const { intl, hasUnread, hasFollows, columnId, multiColumn } = this.props;
const { intl, hasUnread, columnId, multiColumn } = this.props;
const pinned = !!columnId;
let emptyMessage;
if (hasFollows) {
emptyMessage = <FormattedMessage id='empty_column.home.inactivity' defaultMessage='Your home feed is empty. If you have been inactive for a while, it will be regenerated for you soon.' />;
} else {
emptyMessage = <FormattedMessage id='empty_column.home' defaultMessage="You aren't following anyone yet. Visit {public} or use search to get started and meet other users." values={{ public: <Link to='/timelines/public'><FormattedMessage id='empty_column.home.public_timeline' defaultMessage='the public timeline' /></Link> }} />;
}
return (
<Column ref={this.setRef} name='home'>
<ColumnHeader
@ -91,7 +81,7 @@ export default class HomeTimeline extends React.PureComponent {
scrollKey={`home_timeline-${columnId}`}
loadMore={this.handleLoadMore}
timelineId='home'
emptyMessage={emptyMessage}
emptyMessage={<FormattedMessage id='empty_column.home' defaultMessage='Your home timeline is empty! Visit {public} or use search to get started and meet other users.' values={{ public: <Link to='/timelines/public'><FormattedMessage id='empty_column.home.public_timeline' defaultMessage='the public timeline' /></Link> }} />}
/>
</Column>
);

@ -81,7 +81,7 @@
"emoji_button.travel": "Travel & Places",
"empty_column.community": "The local timeline is empty. Write something publicly to get the ball rolling!",
"empty_column.hashtag": "There is nothing in this hashtag yet.",
"empty_column.home": "You aren't following anyone yet. Visit {public} or use search to get started and meet other users.",
"empty_column.home": "Your home timeline is empty! Visit {public} or use search to get started and meet other users.",
"empty_column.home.inactivity": "Your home feed is empty. If you have been inactive for a while, it will be regenerated for you soon.",
"empty_column.home.public_timeline": "the public timeline",
"empty_column.notifications": "You don't have any notifications yet. Interact with others to start the conversation.",

@ -1,7 +1,7 @@
{
"account.block": "Bloquejar @{name}",
"account.block_domain": "Amagar tot de {domain}",
"account.disclaimer_full": "Information below may reflect the user's profile incompletely.",
"account.disclaimer_full": "La informació següent pot reflectir incompleta el perfil de l'usuari.",
"account.edit_profile": "Editar perfil",
"account.follow": "Seguir",
"account.followers": "Seguidors",
@ -13,19 +13,19 @@
"account.posts": "Publicacions",
"account.report": "Informe @{name}",
"account.requested": "Esperant aprovació",
"account.share": "Share @{name}'s profile",
"account.share": "Compartir el perfil de @{name}",
"account.unblock": "Desbloquejar @{name}",
"account.unblock_domain": "Mostra {domain}",
"account.unfollow": "Deixar de seguir",
"account.unmute": "Treure silenci de @{name}",
"account.view_full_profile": "View full profile",
"account.view_full_profile": "Veure el perfil complet",
"boost_modal.combo": "Pots premer {combo} per saltar-te això el proper cop",
"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",
"bundle_column_error.body": "S'ha produït un error en carregar aquest component.",
"bundle_column_error.retry": "Torna-ho a provar",
"bundle_column_error.title": "Error de connexió",
"bundle_modal_error.close": "Tanca",
"bundle_modal_error.message": "S'ha produït un error en carregar aquest component.",
"bundle_modal_error.retry": "Torna-ho a provar",
"column.blocks": "Usuaris bloquejats",
"column.community": "Línia de temps local",
"column.favourites": "Favorits",
@ -33,15 +33,15 @@
"column.home": "Inici",
"column.mutes": "Usuaris silenciats",
"column.notifications": "Notificacions",
"column.pins": "Pinned toot",
"column.pins": "Toot fixat",
"column.public": "Línia de temps federada",
"column_back_button.label": "Enrere",
"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_header.hide_settings": "Amaga la configuració",
"column_header.moveLeft_settings": "Mou la columna cap a l'esquerra",
"column_header.moveRight_settings": "Mou la columna cap a la dreta",
"column_header.pin": "Fixar",
"column_header.show_settings": "Mostra la configuració",
"column_header.unpin": "Deslligar",
"column_subheading.navigation": "Navegació",
"column_subheading.settings": "Configuració",
"compose_form.lock_disclaimer": "El teu compte no està bloquejat {locked}. Tothom pot seguir-te i veure els teus missatges a seguidors.",
@ -61,22 +61,22 @@
"confirmations.domain_block.message": "Estàs realment, realment segur que vols bloquejar totalment {domain}? En la majoria dels casos bloquejar o silenciar és suficient i preferible.",
"confirmations.mute.confirm": "Silenciar",
"confirmations.mute.message": "Estàs segur que vols silenciar {name}?",
"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:",
"confirmations.unfollow.confirm": "Deixar de seguir",
"confirmations.unfollow.message": "Estàs segur que vols deixar de seguir {name}?",
"embed.instructions": "Incrusta aquest estat al lloc web copiant el codi a continuació.",
"embed.preview": "A continuació s'explica com:",
"emoji_button.activity": "Activitat",
"emoji_button.custom": "Custom",
"emoji_button.custom": "Personalitzat",
"emoji_button.flags": "Flags",
"emoji_button.food": "Menjar i Beure",
"emoji_button.label": "Inserir emoji",
"emoji_button.nature": "Natura",
"emoji_button.not_found": "No emojos!! (╯°□°)╯︵ ┻━┻",
"emoji_button.not_found": "Emojos no!! (╯°□°)╯︵ ┻━┻",
"emoji_button.objects": "Objectes",
"emoji_button.people": "Gent",
"emoji_button.recent": "Frequently used",
"emoji_button.recent": "Freqüentment utilitzat",
"emoji_button.search": "Cercar...",
"emoji_button.search_results": "Search results",
"emoji_button.search_results": "Resultats de la cerca",
"emoji_button.symbols": "Símbols",
"emoji_button.travel": "Viatges i Llocs",
"empty_column.community": "La línia de temps local és buida. Escriu alguna cosa públicament per fer rodar la pilota!",
@ -88,7 +88,7 @@
"empty_column.public": "No hi ha res aquí! Escriu alguna cosa públicament o segueix manualment usuaris d'altres instàncies per omplir-ho",
"follow_request.authorize": "Autoritzar",
"follow_request.reject": "Rebutjar",
"getting_started.appsshort": "Apps",
"getting_started.appsshort": "Aplicacions",
"getting_started.faq": "PMF",
"getting_started.heading": "Començant",
"getting_started.open_source_notice": "Mastodon és un programari de codi obert. Pots contribuir o informar de problemes a GitHub de {github}.",
@ -100,8 +100,8 @@
"home.column_settings.show_replies": "Mostrar respostes",
"home.settings": "Ajustos de columna",
"lightbox.close": "Tancar",
"lightbox.next": "Next",
"lightbox.previous": "Previous",
"lightbox.next": "Següent",
"lightbox.previous": "Anterior",
"loading_indicator.label": "Carregant...",
"media_gallery.toggle_visible": "Alternar visibilitat",
"missing_indicator.label": "No trobat",
@ -113,7 +113,7 @@
"navigation_bar.info": "Informació addicional",
"navigation_bar.logout": "Tancar sessió",
"navigation_bar.mutes": "Usuaris silenciats",
"navigation_bar.pins": "Pinned toots",
"navigation_bar.pins": "Toots fixats",
"navigation_bar.preferences": "Preferències",
"navigation_bar.public_timeline": "Línia de temps federada",
"notification.favourite": "{name} ha afavorit el teu estat",
@ -126,8 +126,8 @@
"notifications.column_settings.favourite": "Favorits:",
"notifications.column_settings.follow": "Nous seguidors:",
"notifications.column_settings.mention": "Mencions:",
"notifications.column_settings.push": "Push notifications",
"notifications.column_settings.push_meta": "This device",
"notifications.column_settings.push": "Push notificacions",
"notifications.column_settings.push_meta": "Aquest dispositiu",
"notifications.column_settings.reblog": "Boosts:",
"notifications.column_settings.show": "Mostrar en la columna",
"notifications.column_settings.sound": "Reproduïr so",
@ -160,28 +160,33 @@
"privacy.public.short": "Públic",
"privacy.unlisted.long": "No publicar en línies de temps públiques",
"privacy.unlisted.short": "No llistat",
"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·lar",
"report.placeholder": "Comentaris addicionals",
"report.submit": "Enviar",
"report.target": "Informes",
"search.placeholder": "Cercar",
"search_popout.search_format": "Advanced search format",
"search_popout.search_format": "Format de cerca avançada",
"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.total": "{count, number} {count, plural, one {result} other {results}}",
"standalone.public_title": "A look inside...",
"search_popout.tips.text": "El text simple retorna coincidències amb els noms de visualització, els noms d'usuari i els hashtags",
"search_popout.tips.user": "usuari",
"search_results.total": "{count, number} {count, plural, un {result} altres {results}}",
"standalone.public_title": "Una mirada a l'interior ...",
"status.cannot_reblog": "Aquesta publicació no pot ser retootejada",
"status.delete": "Esborrar",
"status.embed": "Embed",
"status.embed": "Incrustar",
"status.favourite": "Favorit",
"status.load_more": "Carrega més",
"status.media_hidden": "Multimèdia amagat",
"status.mention": "Esmentar @{name}",
"status.mute_conversation": "Silenciar conversació",
"status.open": "Ampliar aquest estat",
"status.pin": "Pin on profile",
"status.pin": "Fixat en el perfil",
"status.reblog": "Boost",
"status.reblogged_by": "{name} ha retootejat",
"status.reply": "Respondre",
@ -189,11 +194,11 @@
"status.report": "Informar sobre @{name}",
"status.sensitive_toggle": "Clic per veure",
"status.sensitive_warning": "Contingut sensible",
"status.share": "Share",
"status.share": "Compartir",
"status.show_less": "Mostra menys",
"status.show_more": "Mostra més",
"status.unmute_conversation": "Activar conversació",
"status.unpin": "Unpin from profile",
"status.unpin": "Deslliga del perfil",
"tabs_bar.compose": "Compondre",
"tabs_bar.federated_timeline": "Federada",
"tabs_bar.home": "Inici",
@ -201,16 +206,16 @@
"tabs_bar.notifications": "Notificacions",
"upload_area.title": "Arrossega i deixa anar per carregar",
"upload_button.label": "Afegir multimèdia",
"upload_form.description": "Describe for the visually impaired",
"upload_form.description": "Descriure els problemes visuals",
"upload_form.undo": "Desfer",
"upload_progress.label": "Pujant...",
"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"
"video.close": "Tancar el vídeo",
"video.exit_fullscreen": "Surt de pantalla completa",
"video.expand": "Ampliar el vídeo",
"video.fullscreen": "Pantalla completa",
"video.hide": "Amaga vídeo",
"video.mute": "Silenciar el so",
"video.pause": "Pausa",
"video.play": "Reproduir",
"video.unmute": "Activar so"
}

@ -81,7 +81,7 @@
"emoji_button.travel": "Reisen und Orte",
"empty_column.community": "Die lokale Zeitleiste ist leer. Schreibe einen öffentlichen Beitrag, um den Ball ins Rollen zu bringen!",
"empty_column.hashtag": "Unter diesem Hashtag gibt es noch nichts.",
"empty_column.home": "Du folgst noch niemandem. Besuche {public} oder nutze die Suche, um loszulegen und andere Leute zu finden.",
"empty_column.home": "Deine Startseite ist leer! Besuche {public} oder nutze die Suche, um loszulegen und andere Leute zu finden.",
"empty_column.home.inactivity": "Deine Zeitleiste ist leer. Falls du eine längere Zeit inaktiv warst, wird sie für dich so schnell wie möglich neu erstellt.",
"empty_column.home.public_timeline": "die öffentliche Zeitleiste",
"empty_column.notifications": "Du hast noch keine Mitteilungen. Interagiere mit anderen, um ins Gespräch zu kommen.",
@ -143,7 +143,7 @@
"onboarding.page_six.almost_done": "Fast fertig …",
"onboarding.page_six.appetoot": "Guten Appetröt!",
"onboarding.page_six.apps_available": "Es gibt verschiedene {apps} für iOS, Android und weitere Plattformen.",
"onboarding.page_six.github": "Mastodon ist freie, quelloffene Software. Du kannst auf GitHub unter {github} dazu beitragen, Probleme melden und Wünsche äußern.",
"onboarding.page_six.github": "Mastodon ist freie, quelloffene Software. Du kannst auf {github} dazu beitragen, Probleme melden und Wünsche äußern.",
"onboarding.page_six.guidelines": "Richtlinien",
"onboarding.page_six.read_guidelines": "Bitte mach dich mit den {guidelines} von {domain} vertraut.",
"onboarding.page_six.various_app": "Apps",

@ -912,7 +912,7 @@
"id": "empty_column.home.inactivity"
},
{
"defaultMessage": "You aren't following anyone yet. Visit {public} or use search to get started and meet other users.",
"defaultMessage": "Your home timeline is empty! Visit {public} or use search to get started and meet other users.",
"id": "empty_column.home"
},
{

@ -81,7 +81,7 @@
"emoji_button.travel": "Travel & Places",
"empty_column.community": "The local timeline is empty. Write something publicly to get the ball rolling!",
"empty_column.hashtag": "There is nothing in this hashtag yet.",
"empty_column.home": "You aren't following anyone yet. Visit {public} or use search to get started and meet other users.",
"empty_column.home": "Your home timeline is empty! Visit {public} or use search to get started and meet other users.",
"empty_column.home.inactivity": "Your home feed is empty. If you have been inactive for a while, it will be regenerated for you soon.",
"empty_column.home.public_timeline": "the public timeline",
"empty_column.notifications": "You don't have any notifications yet. Interact with others to start the conversation.",

@ -81,7 +81,7 @@
"emoji_button.travel": "Travel & Places",
"empty_column.community": "The local timeline is empty. Write something publicly to get the ball rolling!",
"empty_column.hashtag": "There is nothing in this hashtag yet.",
"empty_column.home": "You aren't following anyone yet. Visit {public} or use search to get started and meet other users.",
"empty_column.home": "Your home timeline is empty! Visit {public} or use search to get started and meet other users.",
"empty_column.home.inactivity": "Your home feed is empty. If you have been inactive for a while, it will be regenerated for you soon.",
"empty_column.home.public_timeline": "the public timeline",
"empty_column.notifications": "You don't have any notifications yet. Interact with others to start the conversation.",

@ -66,17 +66,17 @@
"embed.instructions": "برای جاگذاری این نوشته در سایت خودتان، کد زیر را کپی کنید.",
"embed.preview": "نوشتهٔ جاگذاری‌شده این گونه به نظر خواهد رسید:",
"emoji_button.activity": "فعالیت",
"emoji_button.custom": "Custom",
"emoji_button.custom": "سفارشی",
"emoji_button.flags": "پرچم‌ها",
"emoji_button.food": "غذا و نوشیدنی",
"emoji_button.label": "افزودن شکلک",
"emoji_button.nature": "طبیعت",
"emoji_button.not_found": "No emojos!! (╯°□°)╯︵ ┻━┻",
"emoji_button.not_found": "این‌جا شکلکی نیست!! (╯°□°)╯︵ ┻━┻",
"emoji_button.objects": "اشیا",
"emoji_button.people": "مردم",
"emoji_button.recent": "Frequently used",
"emoji_button.recent": "زیاد به‌کاررفته",
"emoji_button.search": "جستجو...",
"emoji_button.search_results": "Search results",
"emoji_button.search_results": "نتایج جستجو",
"emoji_button.symbols": "نمادها",
"emoji_button.travel": "سفر و مکان",
"empty_column.community": "فهرست نوشته‌های محلی خالی است. چیزی بنویسید تا چرخش بچرخد!",
@ -165,11 +165,11 @@
"report.submit": "بفرست",
"report.target": "گزارش‌دادن",
"search.placeholder": "جستجو",
"search_popout.search_format": "Advanced search format",
"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_popout.search_format": "راهنمای جستجوی پیشرفته",
"search_popout.tips.hashtag": "هشتگ",
"search_popout.tips.status": "نوشته",
"search_popout.tips.text": "جستجوی متنی ساده برای نام‌ها، نام‌های کاربری، و هشتگ‌ها",
"search_popout.tips.user": "کاربر",
"search_results.total": "{count, number} {count, plural, one {نتیجه} other {نتیجه}}",
"standalone.public_title": "نگاهی به کاربران این سرور...",
"status.cannot_reblog": "این نوشته را نمی‌شود بازبوقید",
@ -201,7 +201,7 @@
"tabs_bar.notifications": "اعلان‌ها",
"upload_area.title": "برای بارگذاری به این‌جا بکشید",
"upload_button.label": "افزودن تصویر",
"upload_form.description": "Describe for the visually impaired",
"upload_form.description": "نوشتهٔ توضیحی برای کم‌بینایان و نابینایان",
"upload_form.undo": "واگردانی",
"upload_progress.label": "بارگذاری...",
"video.close": "بستن ویدیو",

@ -81,7 +81,7 @@
"emoji_button.travel": "Travel & Places",
"empty_column.community": "The local timeline is empty. Write something publicly to get the ball rolling!",
"empty_column.hashtag": "There is nothing in this hashtag yet.",
"empty_column.home": "You aren't following anyone yet. Visit {public} or use search to get started and meet other users.",
"empty_column.home": "Your home timeline is empty! Visit {public} or use search to get started and meet other users.",
"empty_column.home.inactivity": "Your home feed is empty. If you have been inactive for a while, it will be regenerated for you soon.",
"empty_column.home.public_timeline": "the public timeline",
"empty_column.notifications": "You don't have any notifications yet. Interact with others to start the conversation.",

@ -54,13 +54,13 @@
"compose_form.spoiler_placeholder": "Écrivez ici votre avertissement",
"confirmation_modal.cancel": "Annuler",
"confirmations.block.confirm": "Bloquer",
"confirmations.block.message": "Confirmez vous le blocage de {name}?",
"confirmations.block.message": "Confirmez-vous le blocage de {name}?",
"confirmations.delete.confirm": "Supprimer",
"confirmations.delete.message": "Confirmez vous la suppression de ce pouet?",
"confirmations.delete.message": "Confirmez-vous la suppression de ce pouet?",
"confirmations.domain_block.confirm": "Masquer le domaine entier",
"confirmations.domain_block.message": "Êtes-vous vraiment, vraiment sûr⋅e de vouloir bloquer {domain} en entier? Dans la plupart des cas, quelques blocages ou masquages ciblés sont suffisants et préférables.",
"confirmations.mute.confirm": "Masquer",
"confirmations.mute.message": "Confirmez vous le masquage de {name}?",
"confirmations.mute.message": "Confirmez-vous le masquage de {name}?",
"confirmations.unfollow.confirm": "Ne plus suivre",
"confirmations.unfollow.message": "Voulez-vous arrêter de suivre {name}?",
"embed.instructions": "Intégrez ce statut à votre site en copiant ce code ci-dessous.",
@ -69,7 +69,7 @@
"emoji_button.custom": "Personnalisés",
"emoji_button.flags": "Drapeaux",
"emoji_button.food": "Boire et manger",
"emoji_button.label": "Insérer un emoji",
"emoji_button.label": "Insérer un émoji",
"emoji_button.nature": "Nature",
"emoji_button.not_found": "No emojos!! (╯°□°)╯︵ ┻━┻",
"emoji_button.objects": "Objets",
@ -79,7 +79,7 @@
"emoji_button.search_results": "Résultats de la recherche",
"emoji_button.symbols": "Symboles",
"emoji_button.travel": "Lieux et voyages",
"empty_column.community": "Le fil public local est vide. Écrivez-donc quelque chose pour le remplir!",
"empty_column.community": "Le fil public local est vide. Écrivez donc quelque chose pour le remplir!",
"empty_column.hashtag": "Il ny a encore aucun contenu associé à ce hashtag",
"empty_column.home": "Vous ne suivez encore personne. Visitez {public} ou bien utilisez la recherche pour vous connecter à dautres utilisateur⋅ice⋅s.",
"empty_column.home.inactivity": "Votre accueil est vide. Si vous ne vous êtes pas connecté⋅e depuis un moment, il se remplira automatiquement très bientôt.",
@ -124,7 +124,7 @@
"notifications.clear_confirmation": "Voulez-vous vraiment supprimer toutes vos notifications?",
"notifications.column_settings.alert": "Notifications locales",
"notifications.column_settings.favourite": "Favoris:",
"notifications.column_settings.follow": "Nouveaux⋅elles abonn⋅é⋅s:",
"notifications.column_settings.follow": "Nouveaux⋅elles abonné⋅e⋅s:",
"notifications.column_settings.mention": "Mentions:",
"notifications.column_settings.push": "Notifications push",
"notifications.column_settings.push_meta": "Cet appareil",
@ -139,7 +139,7 @@
"onboarding.page_one.federation": "Mastodon est un réseau social qui appartient à tou⋅te⋅s.",
"onboarding.page_one.handle": "Vous êtes sur {domain}, une des nombreuses instances indépendantes de Mastodon. Votre nom dutilisateur⋅ice complet est {handle}",
"onboarding.page_one.welcome": "Bienvenue sur Mastodon!",
"onboarding.page_six.admin": "Ladministrateur⋅trice de votre instance est {admin}",
"onboarding.page_six.admin": "Ladministrateur⋅ice de votre instance est {admin}",
"onboarding.page_six.almost_done": "Nous y sommes presque…",
"onboarding.page_six.appetoot": "Bon appouétit!",
"onboarding.page_six.apps_available": "De nombreuses {apps} sont disponibles pour iOS, Android et autres. Et maintenant… Bon appouétit!",

@ -81,7 +81,7 @@
"emoji_button.travel": "Travel & Places",
"empty_column.community": "The local timeline is empty. Write something publicly to get the ball rolling!",
"empty_column.hashtag": "There is nothing in this hashtag yet.",
"empty_column.home": "You aren't following anyone yet. Visit {public} or use search to get started and meet other users.",
"empty_column.home": "Your home timeline is empty! Visit {public} or use search to get started and meet other users.",
"empty_column.home.inactivity": "Your home feed is empty. If you have been inactive for a while, it will be regenerated for you soon.",
"empty_column.home.public_timeline": "the public timeline",
"empty_column.notifications": "You don't have any notifications yet. Interact with others to start the conversation.",

@ -151,8 +151,8 @@
"onboarding.page_three.search": "Gebruik de zoekbalk linksboven om andere mensen op Mastodon te vinden en om te zoeken op hashtags, zoals {illustration} en {introductions}. Om iemand te vinden die niet op deze Mastodon-server zit, moet je het volledige Mastodon-adres van deze persoon invoeren.",
"onboarding.page_two.compose": "Schrijf berichten (wij noemen dit toots) in het tekstvak in de linkerkolom. Je kan met de pictogrammen daaronder afbeeldingen uploaden, privacy-instellingen veranderen en je tekst een waarschuwing meegeven.",
"onboarding.skip": "Overslaan",
"privacy.change": "Privacy toot aanpassen",
"privacy.direct.long": "Toot alleen naar vermelde gebruikers",
"privacy.change": "Zichtbaarheid toot aanpassen",
"privacy.direct.long": "Alleen aan vermelde gebruikers tonen",
"privacy.direct.short": "Direct",
"privacy.private.long": "Alleen aan volgers tonen",
"privacy.private.short": "Alleen volgers",

@ -81,7 +81,7 @@
"emoji_button.travel": "Viatges & lòcs",
"empty_column.community": "Lo flux public local es void. Escrivètz quicòm per lo garnir!",
"empty_column.hashtag": "I a pas encara de contengut ligat a aqueste hashtag",
"empty_column.home": "Pel moment seguètz pas degun. Visitatz {public} o utilizatz la recèrca per vos connectar a dautras personas.",
"empty_column.home": "Vòstre flux dacuèlh es void. Visitatz {public} o utilizatz la recèrca per vos connectar a dautras personas.",
"empty_column.home.inactivity": "Vòstra pagina dacuèlh es voida. Se sètz estat inactiu per un moment, serà tornada generar per vos dins una estona.",
"empty_column.home.public_timeline": "lo flux public",
"empty_column.notifications": "Avètz pas encara de notificacions. Respondètz a qualquun per començar una conversacion.",
@ -201,7 +201,7 @@
"tabs_bar.notifications": "Notificacions",
"upload_area.title": "Lisatz e depausatz per mandar",
"upload_button.label": "Ajustar un mèdia",
"upload_form.description": "Descripcion se per cas i aja un problèma",
"upload_form.description": "Descripcion pels mal vesents",
"upload_form.undo": "Anullar",
"upload_progress.label": "Mandadís…",
"video.close": "Tampar la vidèo",

@ -45,7 +45,7 @@
"column_subheading.navigation": "Navegação",
"column_subheading.settings": "Configurações",
"compose_form.lock_disclaimer": "A sua conta não está {locked}. Qualquer pessoa pode te seguir e visualizar postagens direcionadas a apenas seguidores.",
"compose_form.lock_disclaimer.lock": "trancado",
"compose_form.lock_disclaimer.lock": "trancada",
"compose_form.placeholder": "No que você está pensando?",
"compose_form.publish": "Publicar",
"compose_form.publish_loud": "{publish}!",
@ -66,17 +66,17 @@
"embed.instructions": "Incorpore esta postagem em seu site copiando o código abaixo:",
"embed.preview": "Aqui está uma previsão de como ficará:",
"emoji_button.activity": "Atividades",
"emoji_button.custom": "Custom",
"emoji_button.custom": "Customizados",
"emoji_button.flags": "Bandeiras",
"emoji_button.food": "Comidas & Bebidas",
"emoji_button.label": "Inserir Emoji",
"emoji_button.nature": "Natureza",
"emoji_button.not_found": "No emojos!! (╯°□°)╯︵ ┻━┻",
"emoji_button.not_found": "Não tem emojos! (╯°□°)╯︵ ┻━┻",
"emoji_button.objects": "Objetos",
"emoji_button.people": "Pessoas",
"emoji_button.recent": "Frequently used",
"emoji_button.recent": "Usados frequentemente",
"emoji_button.search": "Buscar...",
"emoji_button.search_results": "Search results",
"emoji_button.search_results": "Resultados da busca",
"emoji_button.symbols": "Símbolos",
"emoji_button.travel": "Viagens & Lugares",
"empty_column.community": "A timeline local está vazia. Escreva algo publicamente para começar!",
@ -148,7 +148,7 @@
"onboarding.page_six.read_guidelines": "Por favor, leia as {guidelines} do {domain}!",
"onboarding.page_six.various_app": "aplicativos móveis",
"onboarding.page_three.profile": "Edite o seu perfil para mudar o seu o seu avatar, bio e nome de exibição. No menu de configurações, você também encontrará outras preferências.",
"onboarding.page_three.search": "Use a barra de buscas para encontrar pessoas e consultar hashtahs, como #illustrations e #introductions. Para procurar por uma pessoa que não estiver nesta instância, use o nome de usuário completo dela.",
"onboarding.page_three.search": "Use a barra de buscas para encontrar pessoas e consultar hashtags, como #illustrations e #introductions. Para procurar por uma pessoa que não estiver nesta instância, use o nome de usuário completo dela.",
"onboarding.page_two.compose": "Escreva postagens na coluna de escrita. Você pode hospedar imagens, mudar as configurações de privacidade e adicionar alertas de conteúdo através dos ícones abaixo.",
"onboarding.skip": "Pular",
"privacy.change": "Ajustar a privacidade da mensagem",
@ -168,12 +168,12 @@
"search_popout.search_format": "Advanced search format",
"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.text": "Texto simples retorna nomes de exibição, usuários e hashtags correspondentes",
"search_popout.tips.user": "user",
"search_results.total": "{count, number} {count, plural, one {resultado} other {resultados}}",
"standalone.public_title": "Dê uma espiada...",
"status.cannot_reblog": "Esta postagem não pode ser compartilhada",
"status.delete": "Eliminar",
"status.delete": "Excluir",
"status.embed": "Incorporar",
"status.favourite": "Adicionar aos favoritos",
"status.load_more": "Carregar mais",
@ -201,15 +201,15 @@
"tabs_bar.notifications": "Notificações",
"upload_area.title": "Arraste e solte para enviar",
"upload_button.label": "Adicionar mídia",
"upload_form.description": "Describe for the visually impaired",
"upload_form.undo": "Anular",
"upload_form.description": "Descreva a imagem para deficientes visuais",
"upload_form.undo": "Desfazer",
"upload_progress.label": "Salvando...",
"video.close": "Fechar vídeo",
"video.exit_fullscreen": "Sair da tela cheia",
"video.expand": "Expandir vídeo",
"video.fullscreen": "Tela cheia",
"video.hide": "Esconder vídeo",
"video.mute": "Silenciar vídeo",
"video.mute": "Silenciar",
"video.pause": "Parar",
"video.play": "Reproduzir",
"video.unmute": "Retirar silêncio"

@ -81,7 +81,7 @@
"emoji_button.travel": "Travel & Places",
"empty_column.community": "The local timeline is empty. Write something publicly to get the ball rolling!",
"empty_column.hashtag": "There is nothing in this hashtag yet.",
"empty_column.home": "You aren't following anyone yet. Visit {public} or use search to get started and meet other users.",
"empty_column.home": "Your home timeline is empty! Visit {public} or use search to get started and meet other users.",
"empty_column.home.inactivity": "Your home feed is empty. If you have been inactive for a while, it will be regenerated for you soon.",
"empty_column.home.public_timeline": "the public timeline",
"empty_column.notifications": "You don't have any notifications yet. Interact with others to start the conversation.",

@ -14,6 +14,7 @@ import {
import {
ACCOUNT_BLOCK_SUCCESS,
ACCOUNT_MUTE_SUCCESS,
ACCOUNT_UNFOLLOW_SUCCESS,
} from '../actions/accounts';
import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable';
@ -108,6 +109,12 @@ const filterTimelines = (state, relationship, statuses) => {
return state;
};
const filterTimeline = (timeline, state, relationship, statuses) =>
state.updateIn([timeline, 'items'], ImmutableList(), list =>
list.filterNot(statusId =>
statuses.getIn([statusId, 'account']) === relationship.id
));
const updateTop = (state, timeline, top) => {
return state.update(timeline, initialTimeline, map => map.withMutations(mMap => {
if (top) mMap.set('unread', 0);
@ -134,6 +141,8 @@ export default function timelines(state = initialState, action) {
case ACCOUNT_BLOCK_SUCCESS:
case ACCOUNT_MUTE_SUCCESS:
return filterTimelines(state, action.relationship, action.statuses);
case ACCOUNT_UNFOLLOW_SUCCESS:
return filterTimeline('home', state, action.relationship, action.statuses);
case TIMELINE_SCROLL_TOP:
return updateTop(state, action.timeline, action.top);
case TIMELINE_CONNECT:

@ -702,7 +702,6 @@
.features #mastodon-timeline {
height: 70vh;
width: 100%;
min-width: 330px;
margin-bottom: 50px;
.column {
@ -716,6 +715,23 @@
}
&.tag-page {
.features {
padding: 30px 0;
.container {
max-width: 820px;
#mastodon-timeline {
margin-right: 0;
border-top-right-radius: 0;
}
.about-mastodon {
.about-hashtag {
background: darken($ui-base-color, 4%);
padding: 0 20px 20px 30px;
border-radius: 0 5px 5px 0;
.brand {
padding-top: 20px;
margin-bottom: 20px;
@ -726,74 +742,68 @@
}
}
.container {
max-width: 690px;
p {
strong {
color: $ui-secondary-color;
font-weight: 700;
}
}
.cta {
margin: 40px 0;
margin-bottom: 80px;
margin: 0;
.button {
margin-right: 4px;
}
}
}
.about-mastodon {
max-width: 330px;
p {
strong {
color: $ui-secondary-color;
font-weight: 700;
.features-list {
margin-left: 30px;
margin-right: 10px;
}
}
}
}
@media screen and (max-width: 675px) {
.features {
padding: 10px 0;
.container {
display: flex;
flex-direction: column;
}
.features {
padding: 20px 0;
#mastodon-timeline {
order: 2;
flex: 0 0 auto;
height: 60vh;
margin-bottom: 20px;
border-top-right-radius: 4px;
}
.about-mastodon {
order: 1;
flex: 0 0 auto;
max-width: 100%;
}
#mastodon-timeline {
order: 2;
flex: 0 0 auto;
height: 60vh;
}
.about-hashtag {
background: unset;
padding: 0;
border-radius: 0;
.cta {
margin: 20px 0;
margin-bottom: 30px;
}
}
.features-list {
display: none;
}
.stripe {
display: none;
}
}
}
.stripe {
width: 100%;
height: 360px;
overflow: hidden;
background: darken($ui-base-color, 4%);
position: absolute;
z-index: -1;
}
}
}

@ -18,6 +18,7 @@ class ActivityPub::Activity::Undo < ActivityPub::Activity
def undo_announce
status = Status.find_by(uri: object_uri, account: @account)
status ||= Status.find_by(uri: @object['atomUri'], account: @account) if @object.is_a?(Hash) && @object['atomUri'].present?
if status.nil?
delete_later!(object_uri)

@ -85,7 +85,7 @@ class FeedManager
oldest_home_score = redis.zrange(timeline_key, 0, 0, with_scores: true)&.first&.last&.to_i || 0
from_account.statuses.select('id, reblog_of_id').where('id > ?', oldest_home_score).reorder(nil).find_each do |status|
unpush(:home, into_account, status)
remove_from_feed(:home, into_account, status)
end
end
@ -121,6 +121,7 @@ class FeedManager
#return true if reggie === status.content || reggie === status.spoiler_text
# extremely violent filtering code END
return false if receiver_id == status.account_id
return true if status.reply? && (status.in_reply_to_id.nil? || status.in_reply_to_account_id.nil?)
check_for_mutes = [status.account_id]

@ -23,7 +23,7 @@ class OStatus::AtomSerializer
append_element(author, 'name', account.username)
append_element(author, 'email', account.local? ? account.local_username_and_domain : account.acct)
append_element(author, 'summary', Formatter.instance.simplified_format(account).to_str, type: :html) if account.note?
append_element(author, 'link', nil, rel: :alternate, type: 'text/html', href: TagManager.instance.url_for(account))
append_element(author, 'link', nil, rel: :alternate, type: 'text/html', href: ::TagManager.instance.url_for(account))
append_element(author, 'link', nil, rel: :avatar, type: account.avatar_content_type, 'media:width': 120, 'media:height': 120, href: full_asset_url(account.avatar.url(:original))) if account.avatar?
append_element(author, 'link', nil, rel: :header, type: account.header_content_type, 'media:width': 700, 'media:height': 335, href: full_asset_url(account.header.url(:original))) if account.header?
append_element(author, 'poco:preferredUsername', account.username)
@ -47,7 +47,7 @@ class OStatus::AtomSerializer
feed << author(account)
append_element(feed, 'link', nil, rel: :alternate, type: 'text/html', href: TagManager.instance.url_for(account))
append_element(feed, 'link', nil, rel: :alternate, type: 'text/html', href: ::TagManager.instance.url_for(account))
append_element(feed, 'link', nil, rel: :self, type: 'application/atom+xml', href: account_url(account, format: 'atom'))
append_element(feed, 'link', nil, rel: :next, type: 'application/atom+xml', href: account_url(account, format: 'atom', max_id: stream_entries.last.id)) if stream_entries.size == 20
append_element(feed, 'link', nil, rel: :hub, href: api_push_url)
@ -86,9 +86,9 @@ class OStatus::AtomSerializer
serialize_status_attributes(entry, stream_entry.status)
end
append_element(entry, 'link', nil, rel: :alternate, type: 'text/html', href: TagManager.instance.url_for(stream_entry.status))
append_element(entry, 'link', nil, rel: :alternate, type: 'text/html', href: ::TagManager.instance.url_for(stream_entry.status))
append_element(entry, 'link', nil, rel: :self, type: 'application/atom+xml', href: account_stream_entry_url(stream_entry.account, stream_entry, format: 'atom'))
append_element(entry, 'thr:in-reply-to', nil, ref: OStatus::TagManager.instance.uri_for(stream_entry.thread), href: TagManager.instance.url_for(stream_entry.thread)) if stream_entry.threaded?
append_element(entry, 'thr:in-reply-to', nil, ref: OStatus::TagManager.instance.uri_for(stream_entry.thread), href: ::TagManager.instance.url_for(stream_entry.thread)) if stream_entry.threaded?
append_element(entry, 'ostatus:conversation', nil, ref: conversation_uri(stream_entry.status.conversation)) unless stream_entry&.status&.conversation_id.nil?
entry
@ -109,8 +109,8 @@ class OStatus::AtomSerializer
serialize_status_attributes(object, status)
append_element(object, 'link', nil, rel: :alternate, type: 'text/html', href: TagManager.instance.url_for(status))
append_element(object, 'thr:in-reply-to', nil, ref: OStatus::TagManager.instance.uri_for(status.thread), href: TagManager.instance.url_for(status.thread)) unless status.thread.nil?
append_element(object, 'link', nil, rel: :alternate, type: 'text/html', href: ::TagManager.instance.url_for(status))
append_element(object, 'thr:in-reply-to', nil, ref: OStatus::TagManager.instance.uri_for(status.thread), href: ::TagManager.instance.url_for(status.thread)) unless status.thread.nil?
append_element(object, 'ostatus:conversation', nil, ref: conversation_uri(status.conversation)) unless status.conversation_id.nil?
object
@ -290,7 +290,7 @@ class OStatus::AtomSerializer
entry << object(favourite.status)
append_element(entry, 'thr:in-reply-to', nil, ref: OStatus::TagManager.instance.uri_for(favourite.status), href: TagManager.instance.url_for(favourite.status))
append_element(entry, 'thr:in-reply-to', nil, ref: OStatus::TagManager.instance.uri_for(favourite.status), href: ::TagManager.instance.url_for(favourite.status))
entry
end
@ -312,7 +312,7 @@ class OStatus::AtomSerializer
entry << object(favourite.status)
append_element(entry, 'thr:in-reply-to', nil, ref: OStatus::TagManager.instance.uri_for(favourite.status), href: TagManager.instance.url_for(favourite.status))
append_element(entry, 'thr:in-reply-to', nil, ref: OStatus::TagManager.instance.uri_for(favourite.status), href: ::TagManager.instance.url_for(favourite.status))
entry
end

@ -68,6 +68,9 @@ class Notification < ApplicationRecord
class << self
def reload_stale_associations!(cached_items)
account_ids = cached_items.map(&:from_account_id).uniq
return if account_ids.empty?
accounts = Account.where(id: account_ids).map { |a| [a.id, a] }.to_h
cached_items.each do |item|

@ -134,7 +134,7 @@ class Status < ApplicationRecord
CustomEmoji.from_text([spoiler_text, text].join(' '), account.domain)
end
after_create :store_uri, if: :local?
after_create_commit :store_uri, if: :local?
around_create Mastodon::Snowflake::Callbacks
@ -194,7 +194,11 @@ class Status < ApplicationRecord
account_ids << item.reblog.account_id if item.reblog?
end
accounts = Account.where(id: account_ids.uniq).map { |a| [a.id, a] }.to_h
account_ids.uniq!
return if account_ids.empty?
accounts = Account.where(id: account_ids).map { |a| [a.id, a] }.to_h
cached_items.each do |item|
item.account = accounts[item.account_id]
@ -216,9 +220,7 @@ class Status < ApplicationRecord
# non-followers can see everything that isn't private/direct, but can see stuff they are mentioned in.
visibility.push(:private) if account.following?(target_account)
joins("LEFT OUTER JOIN mentions ON statuses.id = mentions.status_id AND mentions.account_id = #{account.id}")
.where(arel_table[:visibility].in(visibility).or(Mention.arel_table[:id].not_eq(nil)))
.order(visibility: :desc)
where(visibility: visibility).or(where(id: account.mentions.select(:status_id)))
end
end

@ -5,6 +5,7 @@ class ActivityPub::ActivitySerializer < ActiveModel::Serializer
has_one :proper, key: :object, serializer: ActivityPub::NoteSerializer, unless: :announce?
attribute :proper_uri, key: :object, if: :announce?
attribute :atom_uri, if: :announce?
def id
ActivityPub::TagManager.instance.activity_uri_for(object)
@ -34,6 +35,10 @@ class ActivityPub::ActivitySerializer < ActiveModel::Serializer
ActivityPub::TagManager.instance.uri_for(object.proper)
end
def atom_uri
OStatus::TagManager.instance.uri_for(object)
end
def announce?
object.reblog?
end

@ -72,6 +72,8 @@ class FetchLinkCardService < BaseService
def attempt_oembed
response = OEmbed::Providers.get(@url)
return false unless response.respond_to?(:type)
@card.type = response.type
@card.title = response.respond_to?(:title) ? response.title : ''
@card.author_name = response.respond_to?(:author_name) ? response.author_name : ''
@ -113,7 +115,7 @@ class FetchLinkCardService < BaseService
detector.strip_tags = true
guess = detector.detect(html, response.charset)
page = Nokogiri::HTML(html, nil, guess&.fetch(:encoding))
page = Nokogiri::HTML(html, nil, guess&.fetch(:encoding, nil))
if meta_property(page, 'twitter:player')
@card.type = :video

@ -40,6 +40,6 @@ class FetchRemoteStatusService < BaseService
end
def confirmed_domain?(domain, account)
account.domain.nil? || domain.casecmp(account.domain).zero? || domain.casecmp(Addressable::URI.parse(account.remote_url).normalized_host).zero?
account.domain.nil? || domain.casecmp(account.domain).zero? || domain.casecmp(Addressable::URI.parse(account.remote_url || account.uri).normalized_host).zero?
end
end

@ -12,9 +12,11 @@ class SendInteractionService < BaseService
return if !target_account.ostatus? || block_notification?
delivery = build_request.perform.flush
delivery = build_request.perform
raise Mastodon::UnexpectedResponseError, delivery unless delivery.code > 199 && delivery.code < 300
delivery.connection&.close
end
private

@ -6,7 +6,7 @@ class SubscribeService < BaseService
@account = account
@account.secret = SecureRandom.hex
@response = build_request.perform.flush
@response = build_request.perform
if response_failed_permanently?
# We're not allowed to subscribe. Fail and move on.
@ -20,6 +20,7 @@ class SubscribeService < BaseService
# We need to retry at a later time. Fail loudly!
raise Mastodon::UnexpectedResponseError, @response
end
@response.connection&.close
end
private

@ -7,9 +7,10 @@ class UnsubscribeService < BaseService
@account = account
begin
@response = build_request.perform.flush
@response = build_request.perform
Rails.logger.debug "PuSH unsubscribe for #{@account.acct} failed: #{@response.status}" unless @response.status.success?
@response.connection&.close
rescue HTTP::Error, OpenSSL::SSL::SSLError => e
Rails.logger.debug "PuSH unsubscribe for #{@account.acct} failed: #{e}"
end

@ -10,7 +10,7 @@
= custom_emoji.domain
%td
- unless custom_emoji.local?
= table_link_to 'copy', t('admin.custom_emojis.copy'), copy_admin_custom_emoji_path(custom_emoji), method: :post
= table_link_to 'copy', t('admin.custom_emojis.copy'), copy_admin_custom_emoji_path(custom_emoji, page: params[:page]), method: :post
%td
- if custom_emoji.disabled?
= table_link_to 'power-off', t('admin.custom_emojis.enable'), enable_admin_custom_emoji_path(custom_emoji), method: :post, data: { confirm: t('admin.accounts.are_you_sure') }

@ -7,12 +7,12 @@
= render 'og'
.landing-page.tag-page
.stripe
.features
.container
#mastodon-timeline{ data: { props: Oj.dump(default_props.merge(hashtag: @tag.name)) } }
.about-mastodon
.about-hashtag
.brand
= link_to root_url do
= image_tag asset_pack_path('logo_full.svg'), alt: 'Mastodon'
@ -24,12 +24,24 @@
= link_to t('about.learn_more'), root_url, class: 'button button-alternative'
.features-list
.features-list__row
.text
%h6= t 'about.features.real_conversation_title'
= t 'about.features.real_conversation_body'
.visual
= fa_icon 'fw comments'
.features-list__row
.text
%h6= t 'about.features.not_a_product_title'
= t 'about.features.not_a_product_body'
.visual
= fa_icon 'fw users'
.features-list__row
.text
%h6= t 'about.features.within_reach_title'
= t 'about.features.within_reach_body'
.visual
= fa_icon 'fw mobile'
.features-list__row
.text
%h6= t 'about.features.humane_approach_title'

@ -16,6 +16,7 @@ class ActivityPub::DeliveryWorker
raise Mastodon::UnexpectedResponseError, @response unless response_successful?
@response.connection&.close
failure_tracker.track_success!
rescue => e
failure_tracker.track_failure!
@ -31,7 +32,7 @@ class ActivityPub::DeliveryWorker
end
def perform_request
@response = build_request.perform.flush
@response = build_request.perform
end
def response_successful?

@ -27,6 +27,7 @@ class Pubsubhubbub::DeliveryWorker
raise Mastodon::UnexpectedResponseError, payload_delivery unless response_successful?
payload_delivery.connection&.close
subscription.touch(:last_successful_delivery_at)
end
@ -37,7 +38,7 @@ class Pubsubhubbub::DeliveryWorker
def callback_post_payload
request = Request.new(:post, subscription.callback_url, body: payload)
request.add_headers(headers)
request.perform.flush
request.perform
end
def blocked_domain?

@ -0,0 +1,13 @@
---
pt-BR:
activerecord:
errors:
models:
account:
attributes:
username:
invalid: apenas letras, números e underscores
status:
attributes:
reblog:
taken: do status já existe

@ -357,11 +357,11 @@ ca:
truncate: "&hellip;"
push_notifications:
favourite:
title: "%{name} favourited your status"
title: "%{name} ha afavorit el teu estat"
follow:
title: "%{name} is now following you"
title: "%{name} ara et segueix"
group:
title: "%{count} notifications"
title: "%{count} notificacions"
mention:
action_boost: Boost
action_expand: Mostra més
@ -450,13 +450,13 @@ ca:
description_html: Si habilites la <strong>autenticació de dos factors</strong>, et caldrà tenir el teu telèfon, que generarà tokens per a que puguis iniciar sessió.
disable: Deshabilitarr
enable: Habilitar
enabled: Two-factor authentication is enabled
enabled: Autenticació de dos factors activada
enabled_success: Autenticació de dos factors activada amb èxit
generate_recovery_codes: Generar codis de recuperació
instructions_html: "<strong>Escaneja aquest codi QR desde Google Authenticator o una aplicació similar del teu telèfon</strong>. Desde ara, aquesta aplicació generarà tokens que tens que ingresar quan volguis iniciar sessió."
lost_recovery_codes: Els codis de recuperació et permeten recuperar l'accés al teu compte si perds el telèfon. Si has perdut els teus codis de recuperació els pots regenerar aquí. Els codis de recuperació anteriors seran anul·lats.
manual_instructions: 'Si no pots escanejar el codi QR code i necessites introduir-lo manualment, aquí tens el secret en text plà:'
recovery_codes: Backup recovery codes
recovery_codes: Codis de recuperació de còpia de seguretat
recovery_codes_regenerated: Codis de recuperació regenerats amb èxit
recovery_instructions_html: Si alguna vegada perds l'accéss al telèfon pots utilitzar un dels codis de recuperació a continuació per recuperar l'accés al teu compte. Cal mantenir els codis de recuperació en lloc segur, per exemple imprimint-los i guardar-los amb altres documents importants.
setup: Establir

@ -3,8 +3,8 @@ fr:
devise:
confirmations:
confirmed: Votre compte a été validé.
send_instructions: Vous allez recevoir les instructions nécessaires à la confirmation de votre compte dans quelques minutes. Sil vous plaît, dans le cas où vous ne recevriez pas ce message, vérifiez votre dossier dindésirables.
send_paranoid_instructions: Si votre adresse électronique existe dans notre base de données, vous allez bientôt recevoir un courriel contenant les instructions de confirmation de votre compte. Sil vous plaît, dans le cas où vous ne recevriez pas ce message, vérifiez votre dossier dindésirables.
send_instructions: Vous allez recevoir les instructions nécessaires à la confirmation de votre compte dans quelques minutes. Veuillez, dans le cas où vous ne recevriez pas ce message, vérifier votre dossier dindésirables.
send_paranoid_instructions: Si votre adresse électronique existe dans notre base de données, vous allez bientôt recevoir un courriel contenant les instructions de confirmation de votre compte. Veuillez, dans le cas où vous ne recevriez pas ce message, vérifier votre dossier dindésirables.
failure:
already_authenticated: Vous êtes déjà connecté⋅e
inactive: Votre compte nest pas encore activé.
@ -29,8 +29,8 @@ fr:
success: Authentifié avec succès via %{kind}.
passwords:
no_token: Vous ne pouvez accéder à cette page sans passer par un courriel de réinitialisation de mot de passe. Si vous êtes passé⋅e par un courriel de ce type, assurez-vous dutiliser lURL complète.
send_instructions: Vous allez recevoir les instructions de réinitialisation du mot de passe dans quelques instants. Sil vous plaît, dans le cas où vous ne recevriez pas ce message, vérifiez votre dossier dindésirables.
send_paranoid_instructions: Si votre addresse électronique existe dans notre base de données, vous allez recevoir un lien de réinitialisation par courriel. Sil vous plaît, dans le cas où vous ne recevriez pas ce message, vérifiez votre dossier dindésirables.
send_instructions: Vous allez recevoir les instructions de réinitialisation du mot de passe dans quelques instants. Veuillez, dans le cas où vous ne recevriez pas ce message, vérifier votre dossier dindésirables.
send_paranoid_instructions: Si votre adresse électronique existe dans notre base de données, vous allez recevoir un lien de réinitialisation par courriel. Veuillez, dans le cas où vous ne recevriez pas ce message, vérifier votre dossier dindésirables.
updated: Votre mot de passe a été modifié avec succès, vous êtes maintenant connecté⋅e
updated_not_active: Votre mot de passe a été modifié avec succès.
registrations:
@ -46,8 +46,8 @@ fr:
signed_in: Connecté.
signed_out: Déconnecté.
unlocks:
send_instructions: Vous allez recevoir les instructions nécessaires au déverrouillage de votre compte dans quelques instants. Sil vous plaît, dans le cas où vous ne recevriez pas ce message, vérifiez votre dossier dindésirables.
send_paranoid_instructions: Si votre compte existe, vous allez bientôt recevoir un courriel contenant les instructions pour le déverrouiller. Sil vous plaît, dans le cas où vous ne recevriez pas ce message, vérifiez votre dossier dindésirables.
send_instructions: Vous allez recevoir les instructions nécessaires au déverrouillage de votre compte dans quelques instants. Veuillez, dans le cas où vous ne recevriez pas ce message, vérifier votre dossier dindésirables.
send_paranoid_instructions: Si votre compte existe, vous allez bientôt recevoir un courriel contenant les instructions pour le déverrouiller. Veuillez, dans le cas où vous ne recevriez pas ce message, vérifier votre dossier dindésirables.
unlocked: Votre compte a été déverrouillé avec succès, vous êtes maintenant connecté⋅e.
errors:
messages:

@ -6,7 +6,7 @@ fr:
name: Nom
redirect_uri: LURL de redirection
scope: Portée
website: Site Web de l'application
website: Site web de l'application
errors:
models:
doorkeeper/application:

@ -2,6 +2,7 @@
fa:
about:
about_mastodon_html: ماستدون (Mastodon) یک شبکهٔ اجتماعی است که بر اساس پروتکل‌های آزاد وب و نرم‌افزارهای آزاد و کدباز ساخته شده است. این شبکه مانند ایمیل غیرمتمرکز است.
about_hashtag_html: این‌ها نوشته‌های عمومی هستند که برچسب (هشتگ) <strong>#%{hashtag}</strong> را دارند. اگر شما روی هر سروری حساب داشته باشید می‌توانید به این نوشته‌ها واکنش نشان دهید.
about_this: درباره
closed_registrations: ثبت‌نام روی این سرور هم‌اینک فعال نیست. اما شما می‌توانید سرور دیگری بیابید و با حسابی که آن‌جا می‌سازید دقیقاً به همین شبکه دسترسی داشته باشید.
contact: تماس
@ -75,6 +76,7 @@ fa:
silenced: بی‌صدا شده
suspended: معلق شده
title: مدیریت
moderation_notes: یادداشت مدیر
most_recent_activity: آخرین فعالیت‌ها
most_recent_ip: آخرین IP ها
not_subscribed: عضو نیست
@ -108,6 +110,34 @@ fa:
unsubscribe: لغو اشتراک
username: نام کاربری
web: وب
account_moderation_notes:
account: مدیر
created_at: تاریخ
create: نوشتن
created_msg: یادداشت مدیر با موفقیت ساخته شد!
delete: پاک کردن
destroyed_msg: یادداشت مدیر با موفقیت پاک شد!
custom_emojis:
copied_msg: نسخهٔ محلی شکلک با موفقیت ساخته شد
copy: نسخه‌برداری
copy_failed_msg: نشد که نسخهٔ محلی این شکلک ساخته شود
created_msg: این شکلک با موفقیت ساخته شد!
delete: پاک کردن
destroyed_msg: این شکلک با موفقیت پاک شد!
disable: غیرفعال‌سازی
disabled_msg: این شکلک با موفقیت غیرفعال شد
emoji: شکلک
enable: فعال‌سازی
enabled_msg: این شکلک با موفقیت فعال شد
image_hint: پروندهٔ PNG حداکثر 50KB
new:
title: افزودن شکلک سفارشی
shortcode: کد کوتاه
shortcode_hint: دست‌کم ۲ نویسه و تنها شامل حروف، اعداد و زیرخط
title: شکلک‌های سفارشی
upload: بارگذاری
domain_blocks:
add_new: افزودن تازه
created_msg: مسدودکردن دامین در حال انجام است
@ -140,9 +170,21 @@ fa:
undo: واگردانی
title: دامین‌های مسدودشده
undo: واگردانی
email_domain_blocks:
add_new: افزودن تازه
created_msg: مسدودسازی دامین ایمیل با موفقیت ساخته شد
delete: Delete
destroyed_msg: مسدودسازی دامین ایمیل با موفقیت پاک شد
domain: دامین
new:
create: ساختن مسدودسازی
title: مسدودسازی دامین ایمیل تازه
title: مسدودسازی دامین‌های ایمیل
instances:
account_count: حساب‌های شناخته‌شده
domain_name: دامین
reset: بازنشانی
search: جستجو
title: سرورهای شناخته‌شده
reports:
action_taken_by: انجام‌دهنده
@ -294,8 +336,11 @@ fa:
'410': صفحه‌ای که به دنبالش بودید دیگر وجود ندارد.
'422':
content: تأیید امنیتی انجام نشد. آیا مرورگر شما کوکی‌ها را مسدود می‌کند؟
title: تأیید امنیتی شکست خورد
title: تأیید امنیتی کار نکرد
'429': درخواست‌های بیش از حد
'500':
content: شرمنده، یک چیزی از سمت ما اشتباه شده.
title: این صفحه درست نیست
noscript_html: برای استفاده از نسخهٔ تحت وب ماستدون، لطفاً جاوااسکریپت را فعال کنید. یا به جایش می‌توانید یک اپ ماستدون را به‌کار ببرید.
exports:
blocks: حساب‌های مسدودشده
@ -376,6 +421,11 @@ fa:
next: بعدی
prev: قبلی
truncate: "&hellip;"
preferences:
languages: زبان‌ها
other: سایر
publishing: انتشار
web: وب
push_notifications:
favourite:
title: "%{name} نوشتهٔ شما را پسندید"
@ -443,6 +493,7 @@ fa:
export: برون‌سپاری داده‌ها
followers: پیگیران مورد تأیید
import: درون‌ریزی
notifications: اعلان‌ها
preferences: ترجیحات
settings: تنظیمات
two_factor_authentication: ورود دومرحله‌ای
@ -538,6 +589,8 @@ fa:
<p>این نوشته اقتباسی است از <a href="https://github.com/discourse/discourse">سیاست رازداری Discourse</a>.</p>
title: شرایط استفاده و سیاست رازداری %{instance}
themes:
default: Mastodon
time:
formats:
default: "%d %b %Y, %H:%M"

File diff suppressed because one or more lines are too long

@ -1,6 +1,7 @@
---
ja:
about:
about_hashtag_html: ハッシュタグ <strong>#%{hashtag}</strong> の付いた公開トゥートです。どこでもいいので、連合に参加しているSNS上にアカウントを作れば会話に参加することができます。
about_mastodon_html: Mastodon は、オープンなウェブプロトコルを採用した、自由でオープンソースなソーシャルネットワークです。電子メールのような分散型の仕組みを採っています。
about_this: 詳細情報
closed_registrations: 現在このインスタンスでの新規登録は受け付けていません。しかし、他のインスタンスにアカウントを作成しても全く同じネットワークに参加することができます。
@ -49,6 +50,13 @@ ja:
admin: Admin
unfollow: フォロー解除
admin:
account_moderation_notes:
account: モデレータ
create: 書き込む
created_at: 日付
created_msg: モデレーションメモを書き込みました
delete: 削除
destroyed_msg: モデレーションメモを削除しました
accounts:
are_you_sure: 本当に実行しますか?
confirm: 確認
@ -75,6 +83,7 @@ ja:
silenced: サイレンス中
suspended: 停止中
title: モデレーション
moderation_notes: モデレーションメモ
most_recent_activity: 直近の活動
most_recent_ip: 直近のIP
not_subscribed: 購読していない
@ -109,10 +118,17 @@ ja:
username: ユーザー名
web: Web
custom_emojis:
copied_msg: 絵文字のコピーをローカルに作成しました
copy: コピー
copy_failed_msg: 絵文字のコピーをローカルに作成できませんでした
created_msg: 絵文字の追加に成功しました
delete: 削除
destroyed_msg: 絵文字の削除に成功しました
disable: 無効化
disabled_msg: 絵文字を無効化しました
emoji: 絵文字
enable: 有効化
enabled_msg: 絵文字を有効化しました
image_hint: 50KBまでのPNG画像を利用できます。
new:
title: 新規カスタム絵文字の追加

@ -1,7 +1,8 @@
---
ko:
about:
about_mastodon_html: Mastodon은 <em>오픈 소스 기반의</em> 소셜 네트워크 서비스 입니다. 상용 플랫폼의 대체로서 <em>분산형 구조</em>를 채택해, 여러분의 대화가 한 회사에 독점되는 것을 방지합니다. 신뢰할 수 있는 인스턴스를 선택하세요 &mdash; 어떤 인스턴스를 고르더라도, 누구와도 대화할 수 있습니다. 누구나 자신만의 Mastodon 인스턴스를 만들 수 있으며, Seamless하게 <em>소셜 네트워크</em>에 참가할 수 있습니다.
about_hashtag_html: <strong>#%{hashtag}</strong> 라는 해시태그가 붙은 공개 툿 입니다. 같은 연합에 속한 임의의 인스턴스에 계정을 생성하면 당신도 대화에 참여할 수 있습니다.
about_mastodon_html: Mastodon은 <em>오픈 소스 기반의</em> 소셜 네트워크 서비스 입니다. 상용 플랫폼의 대체로서 <em>분산형 구조</em>를 채택해, 여러분의 대화가 한 회사에 독점되는 것을 방지합니다. 신뢰할 수 있는 인스턴스를 선택하세요 &mdash; 어떤 인스턴스를 고르더라도, 누구와도 대화할 수 있습니다. 누구나 자신만의 Mastodon 인스턴스를 만들 수 있으며, 아주 매끄럽게 <em>소셜 네트워크</em>에 참가할 수 있습니다.
about_this: 이 인스턴스에 대해서
closed_registrations: 현재 이 인스턴스에서는 신규 등록을 받고 있지 않습니다.
contact: 연락처
@ -49,6 +50,13 @@ ko:
admin: Admin
unfollow: 팔로우 해제
admin:
account_moderation_notes:
account: 모더레이터
create: 작성하기
created_at: 작성 날짜
created_msg: 모더레이션 기록이 성공적으로 작성되었습니다.
delete: 삭제
destroyed_msg: 모더레이션 기록이 성공적으로 삭제되었습니다.
accounts:
are_you_sure: 정말로 실행하시겠습니까?
confirm: 확인
@ -75,6 +83,7 @@ ko:
silenced: 침묵 중
suspended: 정지 중
title: 모더레이션
moderation_notes: 모더레이션 기록
most_recent_activity: 최근 활동
most_recent_ip: 최근 IP
not_subscribed: 구독하지 않음
@ -109,13 +118,13 @@ ko:
username: 아이디
web: Web
custom_emojis:
copied_msg: 성공적으로 emoji의 로컬 복사본을 생성했습니다
copied_msg: 성공적으로 에모지의 로컬 복사본을 생성했습니다
copy: 복사
copy_failed_msg: Emoji의 로컬 복사본을 만드는 데 실패하였습니다
copy_failed_msg: 에모지의 로컬 복사본을 만드는 데 실패하였습니다
created_msg: 에모지가 성공적으로 생성되었습니다!
delete: 삭제
destroyed_msg: 에모지가 성공적으로 삭제되었습니다!
disable: Disable
disable: 비활성화
disabled_msg: 성공적으로 비활성화하였습니다
emoji: 에모지
enable: 활성화
@ -265,8 +274,8 @@ ko:
signature: Mastodon %{instance} 인스턴스로에서 알림
view: 'View:'
applications:
created: 플리케이션이 작성되었습니다.
destroyed: 플리케이션이 삭제되었습니다.
created: 플리케이션이 작성되었습니다.
destroyed: 플리케이션이 삭제되었습니다.
invalid_url: 올바르지 않은 URL입니다
regenerate_token: 토큰 재생성
token_regenerated: 액세스 토큰이 재생성되었습니다.
@ -473,7 +482,7 @@ ko:
revoke_success: 세션이 삭제되었습니다.
title: 세션
settings:
authorized_apps: 인증된 플리케이션
authorized_apps: 인증된 플리케이션
back: 돌아가기
delete: 계정 삭제
development: 개발
@ -500,7 +509,7 @@ ko:
private_long: 팔로워에게만 공개됩니다
public: 공개
public_long: 누구나 볼 수 있으며, 공개 타임라인에 표시됩니다
unlisted: Unlisted
unlisted: 공개 타임라인 비공개
unlisted_long: 누구나 볼 수 있지만, 공개 타임라인에는 표시되지 않습니다
stream_entries:
click_to_show: 클릭해서 표시
@ -515,14 +524,14 @@ ko:
formats:
default: "%Y년 %m월 %d일 %H:%M"
two_factor_authentication:
code_hint: 확인하기 위해서 인증 플리케이션에서 표시된 코드를 입력해 주십시오
code_hint: 확인하기 위해서 인증 플리케이션에서 표시된 코드를 입력해 주십시오
description_html: "<strong>2단계 인증</strong>을 활성화 하면 로그인 시 전화로 인증 코드를 받을 필요가 있습니다."
disable: 비활성화
enable: 활성화
enabled: 2단계 인증이 활성화 되어 있습니다
enabled_success: 2단계 인증이 활성화 되었습니다
generate_recovery_codes: 복구 코드 생성
instructions_html: "<strong>Google Authenticator, 또는 타 TOTP 플리케이션에서 이 QR 코드를 스캔해 주십시오.</strong> 이후 로그인 시에는 이 플리케이션에서 생성되는 코드가 필요합니다."
instructions_html: "<strong>Google Authenticator, 또는 타 TOTP 플리케이션에서 이 QR 코드를 스캔해 주십시오.</strong> 이후 로그인 시에는 이 플리케이션에서 생성되는 코드가 필요합니다."
lost_recovery_codes: 복구 코드를 사용하면 휴대전화를 분실한 경우에도 계정에 접근할 수 있게 됩니다. 복구 코드를 분실한 경우에도 여기서 다시 생성할 수 있지만, 예전 복구 코드는 비활성화 됩니다.
manual_instructions: 'QR 코드를 스캔할 수 없어 수동으로 등록을 원하시는 경우 이 비밀 코드를 사용해 주십시오: '
recovery_codes: 복구 코드

@ -2,6 +2,7 @@
nl:
about:
about_mastodon_html: Mastodon is een <em>vrij, gratis en open-source</em> sociaal netwerk. Een <em>gedecentraliseerd</em> alternatief voor commerciële platforms. Het voorkomt de risico's van een enkel bedrijf dat jouw communicatie monopoliseert. Kies een server die je vertrouwt &mdash; welke je ook kiest, je kunt met elke andere server communiceren. Iedereen kan een eigen Mastodon-server draaien en naadloos deelnemen in het <em>sociale netwerk</em>.
about_hashtag_html: Dit zijn openbare toots die getagged zijn met <strong>#%{hashtag}</strong>. Je kunt er op reageren of iets anders mee doen als je op Mastodon (of ergens anders in de fediverse) een account hebt.
about_this: Over deze server
closed_registrations: Registreren op deze server is momenteel uitgeschakeld.
contact: Contact
@ -37,6 +38,7 @@ nl:
follow: Volgen
followers: Volgers
following: Volgend
media: Media
nothing_here: Hier is niets!
people_followed_by: Mensen die %{name} volgt
people_who_follow: Mensen die %{name} volgen
@ -74,15 +76,18 @@ nl:
silenced: Genegeerd
suspended: Opgeschort
title: Moderatie
moderation_notes: Opmerkingen voor moderatoren
most_recent_activity: Laatst actief
most_recent_ip: Laatst gebruikt IP-adres
not_subscribed: Niet geabonneerd
order:
alphabetic: Alfabetisch
most_recent: Meest recent
title:
title: Sorteren
outbox_url: Outbox-URL
perform_full_suspension: Volledig opschorten
profile_url: Profiel-URL
protocol: Protocol
public: Openbaar
push_subscription_expires: PuSH-abonnement verloopt op
redownload: Avatar vernieuwen
@ -105,6 +110,34 @@ nl:
unsubscribe: Opzeggen
username: Gebruikersnaam
web: Webapp
account_moderation_notes:
account: Moderator
created_at: Datum
create: Aanmaken
created_msg: Aanmaken van opmerking voor moderatoren geslaagd!
delete: Verwijderen
destroyed_msg: Verwijderen van opmerking voor moderatoren geslaagd!
custom_emojis:
copied_msg: Lokale kopie van emoji maken geslaagd
copy: Kopiëren
copy_failed_msg: Kan geen lokale kopie van deze emoji maken
created_msg: Aanmaken van emoji geslaagd!
delete: Verwijderen
destroyed_msg: Verwijderen van emoji geslaagd!
disable: Uitschakelen
disabled_msg: Uitschakelen van deze emoji geslaagd
emoji: Emoji
enable: Inschakelen
enabled_msg: Inschakelen van deze emoji geslaagd
image_hint: PNG van max. 50KB
new:
title: Lokale emoji toevoegen
shortcode: Shortcode
shortcode_hint: Tenminste 2 tekens (alleen alfanumeriek en underscores)
title: Lokale emojis
upload: Uploaden
domain_blocks:
add_new: Nieuwe toevoegen
created_msg: Domeinblokkade wordt nu verwerkt
@ -137,9 +170,21 @@ nl:
undo: Ongedaan maken
title: Domeinblokkades
undo: Ongedaan maken
email_domain_blocks:
add_new: Nieuwe toevoegen
created_msg: Blokkeren e-maildomein geslaagd
delete: Verwijderen
destroyed_msg: Deblokkeren e-maildomein geslaagd
domain: Domein
new:
create: Blokkeren
title: Nieuw e-maildomein blokkeren
title: E-maildomeinen blokkeren
instances:
account_count: Bekende accounts
domain_name: Domein
reset: Opnieuw
search: Zoeken
title: Bekende servers
reports:
action_taken_by: Actie uitgevoerd door
@ -213,6 +258,7 @@ nl:
title: Media
no_media: Geen media
title: Toots van account
with_media: Met media
subscriptions:
callback_url: Callback-URL
confirmed: Bevestigd
@ -226,11 +272,18 @@ nl:
body: "%{reporter} heeft %{target} gerapporteerd"
subject: Nieuwe toots gerapporteerd op %{instance} (#%{id})
application_mailer:
salutation: "%{name},"
settings: 'E-mailvoorkeuren wijzigen: %{link}'
signature: Mastodon-meldingen van %{instance}
view: 'Bekijk:'
applications:
created: Aanmaken toepassing geslaagd
destroyed: Verwijderen toepassing geslaagd
invalid_url: De opgegeven URL is ongeldig
regenerate_token: Toegangscode opnieuw aanmaken
token_regenerated: Opnieuw aanmaken toegangscode geslaagd
warning: Wees voorzichtig met deze gegevens. Deel het nooit met iemand anders!
your_token: Jouw toegangscode
auth:
agreement_html: Wanneer je op registreren klikt ga je akkoord met <a href="%{rules_path}">onze gebruikersvoorwaarden</a> en <a href="%{terms_path}">ons privacybeleid</a>.
change_password: Beveiliging
@ -238,6 +291,7 @@ nl:
delete_account_html: Wanneer je jouw account graag wilt verwijderen, kan je dat <a href="%{path}">hier doen</a>. We vragen jou daar om een bevestiging.
didnt_get_confirmation: Geen bevestigingsinstructies ontvangen?
forgot_password: Wachtwoord vergeten?
invalid_reset_password_token: De code om jouw wachtwoord opnieuw in te stellen is verlopen. Vraag een nieuwe aan.
login: Aanmelden
logout: Afmelden
register: Registreren
@ -284,6 +338,9 @@ nl:
content: Veiligheidsverificatie mislukt. Blokkeer je toevallig cookies?
title: Veiligheidsverificatie mislukt
'429': Te veel verbindingsaanvragen.
'500':
content: Het spijt ons, er is aan onze kant iets fout gegaan.
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="https://github.com/tootsuite/documentation/blob/master/Using-Mastodon/Apps.md">Mastodon-app</a> zoeken voor jouw platform.
exports:
blocks: Jij blokkeert
@ -318,7 +375,7 @@ nl:
following: Volglijst
muting: Negeerlijst
upload: Uploaden
landing_strip_html: "<strong>%{name}</strong> is een gebruiker op %{link_to_root_path}. Je kunt deze volgen en ermee communiceren als je ergens in deze fediverse een account hebt."
landing_strip_html: "<strong>%{name}</strong> is een gebruiker op %{link_to_root_path}. Je kunt deze volgen en ermee communiceren als je op Mastodon (of ergens anders in de fediverse) een account hebt."
landing_strip_signup_html: Als je dat niet hebt, kun je je <a href="%{sign_up_path}">hier registreren</a>.
media_attachments:
validations:
@ -364,11 +421,18 @@ nl:
next: Volgende
prev: Vorige
truncate: "&hellip;"
preferences:
languages: Talen
other: Overig
publishing: Publiceren
web: Webapp
push_notifications:
favourite:
title: "%{name} markeerde jouw toot als favoriet"
follow:
title: "%{name} volgt jou nu"
group:
title: "%{count} meldingen"
mention:
action_boost: Boost
action_expand: Meer tonen
@ -423,12 +487,13 @@ nl:
settings:
authorized_apps: Geautoriseerde apps
back: Terug naar Mastodon
delete: Account deletion
delete: Account verwijderen
development: Ontwikkelaars
edit_profile: Profiel bewerken
export: Export
export: Exporteren
followers: Geautoriseerde volgers
import: Import
import: Importeren
notifications: Meldingen
preferences: Voorkeuren
settings: Instellingen
two_factor_authentication: Tweestapsverificatie
@ -524,6 +589,8 @@ nl:
<p>Originally adapted from the <a href="https://github.com/discourse/discourse">Discourse privacy policy</a>.</p>
title: "%{instance} Terms of Service and Privacy Policy"
themes:
default: Mastodon
time:
formats:
default: "%d %B %Y om %H:%M"
@ -546,3 +613,4 @@ nl:
users:
invalid_email: E-mailadres is ongeldig
invalid_otp_token: Ongeldige tweestaps-aanmeldcode
signed_in_as: 'Ingelogd als:'

@ -66,9 +66,9 @@ oc:
inbox_url: URL de recepcion
ip: IP
location:
all: Tot
local: Local
remote: Alonhat
all: Totes
local: Locals
remote: Alonhats
title: Emplaçament
media_attachments: Mèdias ajustats
moderation:
@ -76,6 +76,7 @@ oc:
silenced: Rescondut
suspended: Suspendut
title: Moderacion
moderation_notes: Nòtas de moderacion
most_recent_activity: Activitat mai recenta
most_recent_ip: IP mai recenta
not_subscribed: Pas seguidor
@ -109,6 +110,15 @@ oc:
unsubscribe: Se desabonar
username: Nom dutilizaire
web: Web
account_moderation_notes:
account: Moderator
created_at: Data
create: Crear
created_msg: Nòta de moderacion ben creada!
delete: Suprimir
destroyed_msg: Nòta de moderacion ben suprimida!
custom_emojis:
copied_msg: Còpia locale de lemoji ben creada
copy: Copiar
@ -331,8 +341,8 @@ oc:
- dissabte
formats:
default: "%e/%m/%Y"
long: Lo %-d %b de %Y
short: "%e %B"
long: Lo %e %B de %Y
short: "%e %b. de %Y"
month_names:
-
- de genièr

@ -84,8 +84,10 @@ pl:
alphabetic: Alfabetycznie
most_recent: Najnowsze
title: Kolejność
outbox_url: Adres skrzynki nadawczej
perform_full_suspension: Całkowicie zawieś
profile_url: Adres profilu
protocol: Protokół
public: Publiczne
push_subscription_expires: Subskrypcja PuSH wygasa
redownload: Odśwież awatar
@ -180,6 +182,8 @@ pl:
instances:
account_count: Znane konta
domain_name: Domena
reset: Przywróć
search: Szukaj
title: Znane instancje
reports:
action_taken_by: Działanie podjęte przez

@ -2,6 +2,7 @@
pt-BR:
about:
about_mastodon_html: Mastodon é uma rede social baseada em protocolos abertos e software gratuito e de código aberto. É descentralizada como e-mail.
about_hashtag_html: Estes são toots públicos com a hashtag <strong>#%{hashtag}</strong>. Voce pode interagir com eles se tiver uma conta em qualquer lugar no fediverso.
about_this: Sobre
closed_registrations: Cadastros estão atualmente fechados nesta instância. No entanto! Você pode procurar uma instância diferente na qual possa criar uma conta e acessar a mesma rede por lá.
contact: Contato
@ -10,7 +11,9 @@ pt-BR:
description_headline: O que é %{domain}?
domain_count_after: outras instâncias
domain_count_before: Conectado a
extended_description_html: "<h3>Um bom lugar para as regras</h3> <p>A descrição extendida ainda não foi definida.</p>"
extended_description_html:
<h3>Um bom lugar para regras</h3>
<p>A descrição da instância ainda não foi feita.</p>
features:
humane_approach_body: Aprendendo com erros de outras redes, Mastodon tem como objetivo fazer decisões éticas de design para combater o desuso de redes sociais.
humane_approach_title: Uma abordagem mais humana
@ -56,8 +59,9 @@ pt-BR:
domain: Domínio
edit: Editar
email: E-mail
feed_url: Feed URL
feed_url: URL do feed
followers: Seguidores
followers_url: URL de seguidores
follows: Segue
inbox_url: Inbox URL
ip: IP
@ -72,6 +76,7 @@ pt-BR:
silenced: Silenciados
suspended: Suspensos
title: Moderação
moderation_notes: Notas de moderação
most_recent_activity: Atividade mais recente
most_recent_ip: IP mais recente
not_subscribed: Não inscrito
@ -79,7 +84,7 @@ pt-BR:
alphabetic: Alfabética
most_recent: Mais recente
title: Ordem
outbox_url: Outbox URL
outbox_url: URL da Outbox
perform_full_suspension: Efetue suspensão total
profile_url: URL do perfil
protocol: Protocolo
@ -91,6 +96,7 @@ pt-BR:
resubscribe: Reinscrever-se
salmon_url: Salmon URL
search: Pesquisar
shared_inbox_url: URL da Inbox Compartilhada
show:
created_reports: Relatórios criados por esta conta
report: relatórios
@ -104,6 +110,34 @@ pt-BR:
unsubscribe: Desinscrever-se
username: Nome de usuário
web: Web
account_moderation_notes:
account: Moderador
created_at: Data
create: Criar
created_msg: Nota de moderação criada com sucesso!
delete: Excluir
destroyed_msg: Nota de moderação excluída com sucesso!
custom_emojis:
copied_msg: Cópia local do emoji criada com sucesso!
copy: Copiar
copy_failed_msg: Não foi possível criar uma cópia local deste emoji
created_msg: Emoji criado com sucesso!
delete: Excluir
destroyed_msg: Emoji deletado com sucesso!
disable: Desabilitar
disabled_msg: Emoji desabilitado com sucesso!
emoji: Emoji
enable: Habilitar
enabled_msg: Emoji habilitado com sucesso!
image_hint: PNG de até 50KB
new:
title: Adicionar novo emoji customizado
shortcode: Atalho
shortcode_hint: Pelo menos 2 caracteres, apenas caracteres alfanuméricos e underscores
title: Emojis customizados
upload: Enviar
domain_blocks:
add_new: Adicionar novo
created_msg: Bloqueio de domínio está sendo processado
@ -136,9 +170,21 @@ pt-BR:
undo: Retirar
title: Bloqueios de domínio
undo: Retirar
email_domain_blocks:
add_new: Adicionar novo
created_msg: Bloqueio de domínio de e-mail criado com sucesso
delete: Excluir
destroyed_msg: Bloqueio de domínio de e-mail excluído com sucesso
domain: Domínio
new:
create: Criar bloqueio
title: Novo bloqueio de domínio de e-mail
title: Bloqueio de Domínio de E-mail
instances:
account_count: Contas conhecidas
domain_name: Domínio
reset: Resetar
search: Buscar
title: Instâncias conhecidas
reports:
action_taken_by: Ação realizada por
@ -191,6 +237,9 @@ pt-BR:
desc_html: Você pode escrever a sua própria política de privacidade, termos de serviço, entre outras coisas.Você pode usar tags HTML.
title: Termos de serviço customizados
site_title: Nome da instância
thumbnail:
desc_html: Usada para prévias via OpenGraph e API. Recomenda-se 1200x630px
title: Thumbnail da instância
timeline_preview:
desc_html: Exibir a timeline pública na página inicial
title: Prévia da timeline
@ -199,8 +248,8 @@ pt-BR:
back_to_account: Voltar para página da conta
batch:
delete: Deletar
nsfw_off: NSFW OFF
nsfw_on: NSFW ON
nsfw_off: NSFW ATIVADO
nsfw_on: NSFW DESATIVADO
execute: Executar
failed_to_execute: Falha em executar
media:
@ -224,7 +273,7 @@ pt-BR:
subject: Nova denúncia sobre %{instance} (#%{id})
application_mailer:
salutation: "%{name},"
settings: 'Change e-mail preferences: %{link}'
settings: 'Mudar e-mail de preferência: %{link}'
signature: Notificações do Mastodon de %{instance}
view: 'Visualizar:'
applications:
@ -289,7 +338,10 @@ pt-BR:
content: A verificação de segurança falhou. Você desativou o uso de cookies?
title: Falha na verificação de segurança
'429': Muitas requisições
noscript_html: Para usar o aplicativo web do Mastodon, por favor ative o JavaScript. Alternativamente, experimente um dos <a href="https://github.com/tootsuite/documentation/blob/master/Using-Mastodon/Apps.md">apps nativos</a> para o Mastodon para a sua plataforma.
'500':
content: Desculpe, algo deu errado.
title: Esta página não está certa
noscript_html: Para usar o aplicativo web do Mastodon, por favor ative o JavaScript. Ou, se quiser, experimente um dos <a href="https://github.com/tootsuite/documentation/blob/master/Using-Mastodon/Apps.md">apps nativos</a> para o Mastodon em sua plataforma.
exports:
blocks: Você bloqueou
csv: CSV
@ -369,6 +421,11 @@ pt-BR:
next: Próximo
prev: Anterior
truncate: "&hellip;"
preferences:
languages: Idiomas
other: Outro
publishing: Publicação
web: Web
push_notifications:
favourite:
title: "%{name} favoritou a sua postagem"
@ -420,7 +477,7 @@ pt-BR:
ios: iOS
linux: Linux
mac: Mac
other: unknown platform
other: Plataforma desconhecida
windows: Windows
windows_mobile: Windows Mobile
windows_phone: Windows Phone
@ -436,6 +493,7 @@ pt-BR:
export: Exportar dados
followers: Seguidores autorizados
import: Importar
notifications: Notificações
preferences: Preferências
settings: Configurações
two_factor_authentication: Autenticação em dois passos
@ -444,6 +502,7 @@ pt-BR:
open_in_web: Abrir na web
over_character_limit: limite de caracteres de %{max} excedido
pin_errors:
limit: Muitos toots fixados
ownership: Toots de outras pessoas não podem ser fixados
private: Toot não-público não pode ser fixado
reblog: Um compartilhamento não pode ser fixado
@ -461,7 +520,7 @@ pt-BR:
reblogged: compartilhado
sensitive_content: Conteúdo sensível
terms:
body_html: |
body_html:
<h2>Política de privacidade</h2>
<h3 id="collect">Que informações nós coletamos?</h3>
@ -530,6 +589,8 @@ pt-BR:
<p>Originalmente adaptado da <a href="https://github.com/discourse/discourse">política de privacidade do Discourse</a>.</p>
title: "%{instance} Termos de Serviço e Política de Privacidade"
themes:
default: Mastodon
time:
formats:
default: "%b %d, %Y, %H:%M"

@ -4,6 +4,7 @@ fa:
hints:
defaults:
avatar: یکی از قالب‌های PNG یا GIF یا JPG. بیشترین اندازه ۲ مگابایت. تصویر به اندازهٔ ۱۲۰×۱۲۰ پیکسل تبدیل خواهد شد.
digest: پس از مدت طولانی عدم فعالیت فرستاده می‌شود، شامل خلاصه‌ای از مواردی که در نبودتان از شما نام برده شده
display_name:
one: <span class="name-counter">1</span> حرف باقی مانده
other: <span class="name-counter">%{count}</span> حرف باقی مانده
@ -13,6 +14,7 @@ fa:
one: <span class="note-counter">1</span> حرف باقی مانده
other: <span class="note-counter">%{count}</span> حرف باقی مانده
setting_noindex: روی نمایهٔ عمومی و صفحهٔ نوشته‌های شما تأثیر می‌گذارد
setting_theme: ظاهر ماستدون را وقتی که از هر دستگاهی به آن وارد می‌شوید تعیین می‌کند.
imports:
data: پروندهٔ CSV که از سرور ماستدون دیگری برون‌سپاری شده
sessions:
@ -43,6 +45,7 @@ fa:
setting_delete_modal: پیش از پاک کردن یک نوشته پیغام تأیید نشان بده
setting_noindex: درخواست از موتورهای جستجو برای لغو فهرست‌سازی
setting_system_font_ui: به‌کاربردن قلم پیش‌فرض سیستم
setting_theme: تم سایت
setting_unfollow_modal: نمایش پیغام تأیید پیش از لغو پیگیری دیگران
severity: شدت
type: نوع درون‌ریزی

@ -3,12 +3,12 @@ fr:
simple_form:
hints:
defaults:
avatar: Au format PNG, GIF ou JPG. 2Mo maximum. Sera réduit à 120x120px
avatar: Au format PNG, GIF ou JPG. 2Mo maximum. Sera réduit à 120x120px
digest: Envoyé après une longue période dinactivité et contient un résumé des notifications que vous avez reçues pendant votre absence
display_name:
one: <span class="name-counter">1</span> caractère restant
other: <span class="name-counter">%{count}</span> caractères restants
header: Au format PNG, GIF ou JPG. 2Mo maximum. Sera réduit à 700x335px
header: Au format PNG, GIF ou JPG. 2Mo maximum. Sera réduit à 700x335px
locked: Vous devrez approuver chaque abonné⋅e et vos statuts ne safficheront quà vos abonné⋅es
note:
one: <span class="note-counter">1</span> caractère restant
@ -39,14 +39,14 @@ fr:
otp_attempt: Code didentification à deux facteurs
password: Mot de passe
setting_auto_play_gif: Lire automatiquement les GIFs animés
setting_boost_modal: Afficher un dialogue de confirmation avant de partager
setting_boost_modal: Afficher une fenêtre de confirmation avant de partager
setting_default_privacy: Confidentialité des statuts
setting_default_sensitive: Toujours marquer les médias comme sensibles
setting_delete_modal: Afficher un dialogue de confirmation avant de supprimer un pouet
setting_delete_modal: Afficher une fenêtre de confirmation avant de supprimer un pouet
setting_noindex: Demander aux moteurs de recherche de ne pas indexer vos informations personnelles
setting_system_font_ui: Utiliser la police par défaut du système
setting_theme: Thème du site
setting_unfollow_modal: Afficher un dialogue de confirmation avant de vous désabonner dun compte
setting_unfollow_modal: Afficher une fenêtre de confirmation avant de vous désabonner dun compte
severity: Séverité
type: Type dimport
username: Identifiant

@ -4,6 +4,7 @@ ja:
hints:
defaults:
avatar: 2MBまでのPNGやGIF、JPGが利用可能です。120x120pxまで縮小されます。
digest: 長期間ログインしなかった際、その期間に受け取った返信の要約を受け取ることができます。
display_name: あと<span class="name-counter">%{count}</span>文字入力できます。
header: 2MBまでのPNGやGIF、JPGが利用可能です。 700x335pxまで縮小されます。
locked: フォロワーを手動で承認する必要があります

@ -8,10 +8,12 @@ ko:
one: <span class="name-counter">1</span> 글자 남음
other: <span class="name-counter">%{count}</span> 글자 남음
header: PNG, GIF 혹은 JPG. 최대 2MB. 700x335px로 다운스케일 됨
locked: 수동으로 팔로워를 승인하고, 기본 Toot 프라이버시 설정을 팔로워 전용으로 변경
locked: 수동으로 팔로워를 승인하고, 기본 프라이버시 설정을 팔로워 전용으로 변경
note:
one: <span class="note-counter">1</span> 글자 남음
other: <span class="note-counter">%{count}</span> 글자 남음
setting_noindex: 공개 프로필 및 각 툿페이지에 영향을 미칩니다
setting_theme: 로그인중인 모든 디바이스에 적용되는 디자인입니다.
imports:
data: 다른 마스토돈 인스턴스에서 추출된 CSV 파일
sessions:
@ -35,9 +37,14 @@ ko:
otp_attempt: 2단계 인증 코드
password: 비밀번호
setting_auto_play_gif: 애니메이션 GIF를 자동 재생
setting_boost_modal: 부스트 전 확인 창을 보여주기
setting_default_privacy: Toot 프라이버시
setting_delete_modal: Toot 삭제 전 확인 창을 보여주기
setting_boost_modal: 부스트 전 확인 창을 표시
setting_default_privacy: 툿 프라이버시
setting_default_sensitive: 미디어를 언제나 민감한 컨텐츠로 설정
setting_delete_modal: 툿 삭제 전 확인 창을 표시
setting_noindex: 검색엔진의 인덱싱을 거절
setting_system_font_ui: 시스템의 초기 설정 폰트를 사용
setting_theme: 사이트 테마
setting_unfollow_modal: 언팔로우 전 언팔로우 확인 표시
severity: 심각도
type: 불러오기 종류
username: 유저 이름
@ -50,7 +57,7 @@ ko:
follow: 누군가 나를 팔로우 했을 때 이메일 보내기
follow_request: 누군가 나를 팔로우 하길 원할 때 이메일 보내기
mention: 누군가 나에게 답장했을 때 이메일 보내기
reblog: 누군가 내 Toot을 부스트 했을 때 이메일 보내기
reblog: 누군가 내 을 부스트 했을 때 이메일 보내기
'no': 아니오
required:
mark: "*"

@ -5,6 +5,7 @@ require 'rails_helper'
describe ApplicationController, type: :controller do
controller do
include UserTrackingConcern
def show
render plain: 'show'
end
@ -49,6 +50,7 @@ describe ApplicationController, type: :controller do
get :show
expect_updated_sign_in_at(user)
expect(Redis.current.get("account:#{user.account_id}:regeneration")).to eq 'true'
expect(RegenerationWorker).to have_received(:perform_async)
end

@ -25,9 +25,11 @@ RSpec.describe ActivityPub::Activity::Undo do
type: 'Announce',
actor: ActivityPub::TagManager.instance.uri_for(sender),
object: ActivityPub::TagManager.instance.uri_for(status),
atomUri: 'barbar',
}
end
context do
before do
Fabricate(:status, reblog: status, account: sender, uri: 'bar')
end
@ -38,6 +40,18 @@ RSpec.describe ActivityPub::Activity::Undo do
end
end
context 'with atomUri' do
before do
Fabricate(:status, reblog: status, account: sender, uri: 'barbar')
end
it 'deletes the reblog by atomUri' do
subject.perform
expect(sender.reblogged?(status)).to be false
end
end
end
context 'with Block' do
let(:recipient) { Fabricate(:account) }

@ -1,21 +1,45 @@
require 'rails_helper'
RSpec.describe Feed, type: :model do
let(:account) { Fabricate(:account) }
subject { described_class.new(:home, account) }
describe '#get' do
it 'gets statuses with ids in the range' do
account = Fabricate(:account)
before do
Fabricate(:status, account: account, id: 1)
Fabricate(:status, account: account, id: 2)
Fabricate(:status, account: account, id: 3)
Fabricate(:status, account: account, id: 10)
Redis.current.zadd(FeedManager.instance.key(:home, account.id),
[[4, 4], [3, 3], [2, 2], [1, 1]])
end
feed = Feed.new(:home, account)
results = feed.get(3)
context 'when feed is generated' do
before do
Redis.current.zadd(
FeedManager.instance.key(:home, account.id),
[[4, 4], [3, 3], [2, 2], [1, 1]]
)
end
it 'gets statuses with ids in the range from redis' do
results = subject.get(3)
expect(results.map(&:id)).to eq [3, 2]
expect(results.first.attributes.keys).to eq %w(id updated_at)
end
end
context 'when feed is being generated' do
before do
Redis.current.set("account:#{account.id}:regeneration", true)
end
it 'gets statuses with ids in the range from database' do
results = subject.get(3)
expect(results.map(&:id)).to eq [10, 3, 2]
expect(results.first.attributes.keys).to include('id', 'updated_at')
end
end
end
end

@ -39,6 +39,12 @@ RSpec.describe ReblogService do
expect(status.reblogs.count).to eq 1
end
describe 'after_create_commit :store_uri' do
it 'keeps consistent reblog count' do
expect(status.reblogs.count).to eq 1
end
end
it 'distributes to followers' do
expect(ActivityPub::DistributionWorker).to have_received(:perform_async)
end

Loading…
Cancel
Save