- {!onCloseVideo &&
}
+ {!onCloseVideo &&
}
{(!fullscreen && onOpenVideo) &&
}
{onCloseVideo &&
}
diff --git a/app/javascript/mastodon/initial_state.js b/app/javascript/mastodon/initial_state.js
index 8c2e9d2de49d9b..74bcfee5868123 100644
--- a/app/javascript/mastodon/initial_state.js
+++ b/app/javascript/mastodon/initial_state.js
@@ -13,6 +13,8 @@ export const deleteModal = getMeta('delete_modal');
export const me = getMeta('me');
export const searchEnabled = getMeta('search_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 mascot = getMeta('mascot');
export const profile_directory = getMeta('profile_directory');
diff --git a/app/javascript/mastodon/locales/cs.json b/app/javascript/mastodon/locales/cs.json
index f98ea7f26a4d2a..cbf303f3ca4bf6 100644
--- a/app/javascript/mastodon/locales/cs.json
+++ b/app/javascript/mastodon/locales/cs.json
@@ -77,6 +77,7 @@
"compose_form.poll.remove_option": "Odstranit tuto volbu",
"compose_form.publish": "Tootnout",
"compose_form.publish_loud": "{publish}!",
+ "compose_form.sensitive.hide": "Označit média jako citlivá",
"compose_form.sensitive.marked": "Média jsou označena jako citlivá",
"compose_form.sensitive.unmarked": "Média nejsou označena jako citlivá",
"compose_form.spoiler.marked": "Text je skrytý za varováním",
@@ -209,6 +210,7 @@
"lightbox.close": "Zavřít",
"lightbox.next": "Další",
"lightbox.previous": "Předchozí",
+ "lightbox.view_context": "Zobrazit kontext",
"lists.account.add": "Přidat do seznamu",
"lists.account.remove": "Odebrat ze seznamu",
"lists.delete": "Smazat seznam",
diff --git a/app/javascript/mastodon/locales/hi.json b/app/javascript/mastodon/locales/hi.json
new file mode 100644
index 00000000000000..9d507346a21a1c
--- /dev/null
+++ b/app/javascript/mastodon/locales/hi.json
@@ -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"
+}
diff --git a/app/javascript/mastodon/locales/hy.json b/app/javascript/mastodon/locales/hy.json
index c3971b09e58c0b..ca7732d8515b95 100644
--- a/app/javascript/mastodon/locales/hy.json
+++ b/app/javascript/mastodon/locales/hy.json
@@ -239,11 +239,11 @@
"navigation_bar.lists": "Ցանկեր",
"navigation_bar.logout": "Դուրս գալ",
"navigation_bar.mutes": "Լռեցրած օգտատերեր",
- "navigation_bar.personal": "Personal",
+ "navigation_bar.personal": "Անձնական",
"navigation_bar.pins": "Ամրացված թթեր",
"navigation_bar.preferences": "Նախապատվություններ",
"navigation_bar.public_timeline": "Դաշնային հոսք",
- "navigation_bar.security": "Security",
+ "navigation_bar.security": "Անվտանգություն",
"notification.favourite": "{name} հավանեց թութդ",
"notification.follow": "{name} սկսեց հետեւել քեզ",
"notification.mention": "{name} նշեց քեզ",
@@ -309,7 +309,7 @@
"search_results.accounts": "People",
"search_results.hashtags": "Hashtags",
"search_results.statuses": "Toots",
- "search_results.total": "{count, number} {count, plural, one {result} other {results}}",
+ "search_results.total": "{count, number} {count, plural, one {արդյունք} other {արդյունք}}",
"status.admin_account": "Open moderation interface for @{name}",
"status.admin_status": "Open this status in the moderation interface",
"status.block": "Արգելափակել @{name}֊ին",
diff --git a/app/javascript/mastodon/locales/nl.json b/app/javascript/mastodon/locales/nl.json
index 5fb445209cd4fb..96e39356b76c2e 100644
--- a/app/javascript/mastodon/locales/nl.json
+++ b/app/javascript/mastodon/locales/nl.json
@@ -11,7 +11,7 @@
"account.follow": "Volgen",
"account.followers": "Volgers",
"account.followers.empty": "Niemand volgt nog deze gebruiker.",
- "account.follows": "Volgt",
+ "account.follows": "Volgend",
"account.follows.empty": "Deze gebruiker volgt nog niemand.",
"account.follows_you": "Volgt jou",
"account.hide_reblogs": "Verberg boosts van @{name}",
diff --git a/app/javascript/mastodon/locales/pt-BR.json b/app/javascript/mastodon/locales/pt-BR.json
index 5b07c22952dc8c..e469344eca6293 100644
--- a/app/javascript/mastodon/locales/pt-BR.json
+++ b/app/javascript/mastodon/locales/pt-BR.json
@@ -117,7 +117,7 @@
"emoji_button.symbols": "Símbolos",
"emoji_button.travel": "Viagens & Lugares",
"empty_column.account_timeline": "Não há toots aqui!",
- "empty_column.account_unavailable": "Profile unavailable",
+ "empty_column.account_unavailable": "Perfil indisponível",
"empty_column.blocks": "Você ainda não bloqueou nenhum usuário.",
"empty_column.community": "A timeline local está vazia. Escreva algo publicamente para começar!",
"empty_column.direct": "Você não tem nenhuma mensagem direta ainda. Quando você enviar ou receber uma, as mensagens aparecerão por aqui.",
diff --git a/app/javascript/mastodon/locales/ru.json b/app/javascript/mastodon/locales/ru.json
index 13f511cbfaa990..47589979710223 100644
--- a/app/javascript/mastodon/locales/ru.json
+++ b/app/javascript/mastodon/locales/ru.json
@@ -118,7 +118,6 @@
"emoji_button.travel": "Путешествия",
"empty_column.account_timeline": "Статусов нет!",
"empty_column.account_unavailable": "Профиль недоступен",
- "empty_column.account_timeline_blocked": "Вы заблокированы",
"empty_column.blocks": "Вы ещё никого не заблокировали.",
"empty_column.community": "Локальная лента пуста. Напишите что-нибудь, чтобы разогреть народ!",
"empty_column.direct": "У Вас пока нет личных сообщений. Когда Вы начнёте их отправлять или получать, они появятся здесь.",
diff --git a/app/javascript/mastodon/locales/whitelist_hi.json b/app/javascript/mastodon/locales/whitelist_hi.json
new file mode 100644
index 00000000000000..0d4f101c7a37a4
--- /dev/null
+++ b/app/javascript/mastodon/locales/whitelist_hi.json
@@ -0,0 +1,2 @@
+[
+]
diff --git a/app/javascript/packs/public.js b/app/javascript/packs/public.js
index 6a8cf9c2f5b302..93379cdb3e1d78 100644
--- a/app/javascript/packs/public.js
+++ b/app/javascript/packs/public.js
@@ -173,6 +173,21 @@ function main() {
avatar.src = url;
});
+ 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 || [];
diff --git a/app/javascript/styles/fonts/montserrat.scss b/app/javascript/styles/fonts/montserrat.scss
index 206f1865e5e1e5..8079dc6fc9766d 100644
--- a/app/javascript/styles/fonts/montserrat.scss
+++ b/app/javascript/styles/fonts/montserrat.scss
@@ -10,7 +10,7 @@
@font-face {
font-family: 'mastodon-font-display';
- src: local('Montserrat'),
+ src: local('Montserrat Medium'),
url('../fonts/montserrat/Montserrat-Medium.ttf') format('truetype');
font-weight: 500;
font-style: normal;
diff --git a/app/javascript/styles/fonts/roboto.scss b/app/javascript/styles/fonts/roboto.scss
index 345d9ad50e29fc..f9c7c50fea4354 100644
--- a/app/javascript/styles/fonts/roboto.scss
+++ b/app/javascript/styles/fonts/roboto.scss
@@ -1,6 +1,6 @@
@font-face {
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.woff') format('woff'),
url('../fonts/roboto/roboto-italic-webfont.ttf') format('truetype'),
@@ -11,7 +11,7 @@
@font-face {
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.woff') format('woff'),
url('../fonts/roboto/roboto-bold-webfont.ttf') format('truetype'),
@@ -22,7 +22,7 @@
@font-face {
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.woff') format('woff'),
url('../fonts/roboto/roboto-medium-webfont.ttf') format('truetype'),
diff --git a/app/javascript/styles/mastodon/admin.scss b/app/javascript/styles/mastodon/admin.scss
index fd5c08f043ed86..dd3b47a8fa5bb9 100644
--- a/app/javascript/styles/mastodon/admin.scss
+++ b/app/javascript/styles/mastodon/admin.scss
@@ -50,6 +50,7 @@ $content-width: 840px;
color: $darker-text-color;
text-decoration: none;
transition: all 200ms linear;
+ transition-property: color, background-color;
border-radius: 4px 0 0 4px;
i.fa {
@@ -60,6 +61,7 @@ $content-width: 840px;
color: $primary-text-color;
background-color: darken($ui-base-color, 5%);
transition: all 100ms linear;
+ transition-property: color, background-color;
}
&.selected {
diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss
index 4b3f5153ccde8b..cf8fa9392be301 100644
--- a/app/javascript/styles/mastodon/components.scss
+++ b/app/javascript/styles/mastodon/components.scss
@@ -264,6 +264,16 @@
.compose-form {
padding: 10px;
+ &__sensitive-button {
+ padding: 10px;
+ padding-top: 0;
+
+ .icon-button {
+ font-size: 14px;
+ font-weight: 500;
+ }
+ }
+
.compose-form__warning {
color: $inverted-text-color;
margin-bottom: 10px;
@@ -1962,6 +1972,7 @@ a.account__display-name {
font-weight: 500;
border-bottom: 2px solid lighten($ui-base-color, 8%);
transition: all 50ms linear;
+ transition-property: border-bottom, background, color;
.fa {
font-weight: 400;
@@ -2127,7 +2138,7 @@ a.account__display-name {
padding: 0;
border-radius: 30px;
background-color: $ui-base-color;
- transition: all 0.2s ease;
+ transition: background-color 0.2s ease;
}
.react-toggle:hover:not(.react-toggle--disabled) .react-toggle-track {
@@ -2180,7 +2191,6 @@ a.account__display-name {
}
.react-toggle-thumb {
- transition: all 0.5s cubic-bezier(0.23, 1, 0.32, 1) 0ms;
position: absolute;
top: 1px;
left: 1px;
@@ -2191,6 +2201,7 @@ a.account__display-name {
background-color: darken($simple-background-color, 2%);
box-sizing: border-box;
transition: all 0.25s ease;
+ transition-property: border-color, left;
}
.react-toggle--checked .react-toggle-thumb {
@@ -2412,7 +2423,7 @@ a.account__display-name {
& > div {
background: rgba($base-shadow-color, 0.6);
- border-radius: 4px;
+ border-radius: 8px;
padding: 12px 9px;
flex: 0 0 auto;
display: flex;
@@ -2423,19 +2434,18 @@ a.account__display-name {
button,
a {
display: inline;
- color: $primary-text-color;
+ color: $secondary-text-color;
background: transparent;
border: 0;
- padding: 0 5px;
+ padding: 0 8px;
text-decoration: none;
- opacity: 0.6;
font-size: 18px;
line-height: 18px;
&:hover,
&:active,
&:focus {
- opacity: 1;
+ color: $primary-text-color;
}
}
@@ -2932,15 +2942,49 @@ a.status-card.compact:hover {
}
.spoiler-button {
- display: none;
- left: 4px;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
position: absolute;
- text-shadow: 0 1px 1px $base-shadow-color, 1px 0 1px $base-shadow-color;
- top: 4px;
z-index: 100;
- &.spoiler-button--visible {
+ &--minified {
+ display: block;
+ left: 4px;
+ top: 4px;
+ width: auto;
+ height: auto;
+ }
+
+ &--hidden {
+ display: none;
+ }
+
+ &__overlay {
display: block;
+ background: transparent;
+ width: 100%;
+ height: 100%;
+ border: 0;
+
+ &__label {
+ display: inline-block;
+ background: rgba($base-overlay-background, 0.5);
+ border-radius: 8px;
+ padding: 8px 12px;
+ color: $primary-text-color;
+ font-weight: 500;
+ font-size: 14px;
+ }
+
+ &:hover,
+ &:focus,
+ &:active {
+ .spoiler-button__overlay__label {
+ background: rgba($base-overlay-background, 0.8);
+ }
+ }
}
}
@@ -3509,6 +3553,7 @@ a.status-card.compact:hover {
display: inline-block;
opacity: 0;
transition: all 100ms linear;
+ transition-property: transform, opacity;
font-size: 18px;
width: 18px;
height: 18px;
@@ -3728,6 +3773,31 @@ a.status-card.compact:hover {
pointer-events: none;
}
+.media-modal__meta {
+ text-align: center;
+ position: absolute;
+ left: 0;
+ bottom: 20px;
+ width: 100%;
+ pointer-events: none;
+
+ &--shifted {
+ bottom: 62px;
+ }
+
+ a {
+ text-decoration: none;
+ font-weight: 500;
+ color: $ui-secondary-color;
+
+ &:hover,
+ &:focus,
+ &:active {
+ text-decoration: underline;
+ }
+ }
+}
+
.media-modal__page-dot {
display: inline-block;
}
@@ -3961,14 +4031,6 @@ a.status-card.compact:hover {
font-size: 14px;
}
-.confirmation-modal {
- max-width: 85vw;
-
- @media screen and (min-width: 480px) {
- max-width: 380px;
- }
-}
-
.mute-modal {
line-height: 24px;
}
@@ -4093,6 +4155,11 @@ a.status-card.compact:hover {
ul {
overflow-y: auto;
flex-shrink: 0;
+ max-height: 80vh;
+
+ &.with-status {
+ max-height: calc(80vh - 75px);
+ }
li:empty {
margin: 0;
@@ -4147,6 +4214,10 @@ a.status-card.compact:hover {
color: darken($lighter-text-color, 4%);
}
}
+
+ .confirmation-modal__secondary-button {
+ flex-shrink: 1;
+ }
}
.confirmation-modal__container,
@@ -4199,6 +4270,7 @@ a.status-card.compact:hover {
pointer-events: none;
opacity: 0.9;
transition: opacity 0.1s ease;
+ line-height: 18px;
}
.media-gallery__gifv {
@@ -4312,6 +4384,8 @@ a.status-card.compact:hover {
text-decoration: none;
color: $secondary-text-color;
line-height: 0;
+ position: relative;
+ z-index: 1;
&,
img {
@@ -4324,6 +4398,21 @@ a.status-card.compact:hover {
}
}
+.media-gallery__preview {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+ position: absolute;
+ top: 0;
+ left: 0;
+ z-index: 0;
+ background: $base-overlay-background;
+
+ &--hidden {
+ display: none;
+ }
+}
+
.media-gallery__gifv {
height: 100%;
overflow: hidden;
@@ -4619,6 +4708,23 @@ a.status-card.compact:hover {
}
}
+ &__link {
+ padding: 2px 10px;
+
+ a {
+ text-decoration: none;
+ font-size: 14px;
+ font-weight: 500;
+ color: $white;
+
+ &:hover,
+ &:active,
+ &:focus {
+ text-decoration: underline;
+ }
+ }
+ }
+
&__seek {
cursor: pointer;
height: 24px;
@@ -4711,62 +4817,18 @@ a.status-card.compact:hover {
.account-gallery__container {
display: flex;
- justify-content: center;
flex-wrap: wrap;
- padding: 2px;
+ padding: 4px 2px;
}
.account-gallery__item {
- flex-grow: 1;
- width: 50%;
- overflow: hidden;
+ border: none;
+ box-sizing: border-box;
+ display: block;
position: relative;
-
- &::before {
- content: "";
- display: block;
- padding-top: 100%;
- }
-
- a {
- display: block;
- width: calc(100% - 4px);
- height: calc(100% - 4px);
- margin: 2px;
- top: 0;
- left: 0;
- background-color: $base-overlay-background;
- background-size: cover;
- background-position: center;
- position: absolute;
- color: $darker-text-color;
- text-decoration: none;
- border-radius: 4px;
-
- &:hover,
- &:active,
- &:focus {
- outline: 0;
- color: $secondary-text-color;
-
- &::before {
- content: "";
- display: block;
- width: 100%;
- height: 100%;
- background: rgba($base-overlay-background, 0.3);
- border-radius: 4px;
- }
- }
- }
-
- &__icons {
- position: absolute;
- top: 50%;
- left: 50%;
- transform: translate(-50%, -50%);
- font-size: 24px;
- }
+ border-radius: 4px;
+ overflow: hidden;
+ margin: 2px;
}
.notification__filter-bar,
diff --git a/app/javascript/styles/mastodon/forms.scss b/app/javascript/styles/mastodon/forms.scss
index 91888d3059fed3..2b8d7a6825ff4a 100644
--- a/app/javascript/styles/mastodon/forms.scss
+++ b/app/javascript/styles/mastodon/forms.scss
@@ -533,6 +533,17 @@ code {
color: $error-value-color;
}
+ a {
+ display: inline-block;
+ color: $darker-text-color;
+ text-decoration: none;
+
+ &:hover {
+ color: $primary-text-color;
+ text-decoration: underline;
+ }
+ }
+
p {
margin-bottom: 15px;
}
diff --git a/app/javascript/styles/mastodon/widgets.scss b/app/javascript/styles/mastodon/widgets.scss
index e736d7a7ef3421..acaf5b02404a7b 100644
--- a/app/javascript/styles/mastodon/widgets.scss
+++ b/app/javascript/styles/mastodon/widgets.scss
@@ -4,7 +4,6 @@
&__img {
width: 100%;
- height: 167px;
position: relative;
overflow: hidden;
border-radius: 4px 4px 0 0;
diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb
index dabdcbcf7b2a20..6b16c998633416 100644
--- a/app/lib/activitypub/activity/create.rb
+++ b/app/lib/activitypub/activity/create.rb
@@ -194,7 +194,7 @@ def process_attachments
next if attachment['url'].blank?
href = Addressable::URI.parse(attachment['url']).normalize.to_s
- media_attachment = MediaAttachment.create(account: @account, remote_url: href, description: attachment['name'].presence, focus: attachment['focalPoint'])
+ media_attachment = MediaAttachment.create(account: @account, remote_url: href, description: attachment['name'].presence, focus: attachment['focalPoint'], blurhash: supported_blurhash?(attachment['blurhash']) ? attachment['blurhash'] : nil)
media_attachments << media_attachment
next if unsupported_media_type?(attachment['mediaType']) || skip_download?
@@ -369,6 +369,11 @@ def unsupported_media_type?(mime_type)
mime_type.present? && !(MediaAttachment::IMAGE_MIME_TYPES + MediaAttachment::VIDEO_MIME_TYPES).include?(mime_type)
end
+ def supported_blurhash?(blurhash)
+ components = blurhash.blank? ? nil : Blurhash.components(blurhash)
+ components.present? && components.none? { |comp| comp > 5 }
+ end
+
def skip_download?
return @skip_download if defined?(@skip_download)
@skip_download ||= DomainBlock.find_by(domain: @account.domain)&.reject_media?
diff --git a/app/lib/activitypub/adapter.rb b/app/lib/activitypub/adapter.rb
index 94eb2899c1bd60..c259c96f410fb8 100644
--- a/app/lib/activitypub/adapter.rb
+++ b/app/lib/activitypub/adapter.rb
@@ -19,6 +19,7 @@ class ActivityPub::Adapter < ActiveModelSerializers::Adapter::Base
conversation: { 'ostatus' => 'http://ostatus.org#', 'inReplyToAtomUri' => 'ostatus:inReplyToAtomUri', 'conversation' => 'ostatus:conversation' },
focal_point: { 'toot' => 'http://joinmastodon.org/ns#', 'focalPoint' => { '@container' => '@list', '@id' => 'toot:focalPoint' } },
identity_proof: { 'toot' => 'http://joinmastodon.org/ns#', 'IdentityProof' => 'toot:IdentityProof' },
+ blurhash: { 'toot' => 'http://joinmastodon.org/ns#', 'blurhash' => 'toot:blurhash' },
}.freeze
def self.default_key_transform
diff --git a/app/lib/proof_provider/keybase.rb b/app/lib/proof_provider/keybase.rb
index 9680b90eedcd7e..8e51d714646497 100644
--- a/app/lib/proof_provider/keybase.rb
+++ b/app/lib/proof_provider/keybase.rb
@@ -2,7 +2,7 @@
class ProofProvider::Keybase
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
diff --git a/app/models/concerns/ldap_authenticable.rb b/app/models/concerns/ldap_authenticable.rb
index e1b5e3832b44e1..84ff84c4b05c85 100644
--- a/app/models/concerns/ldap_authenticable.rb
+++ b/app/models/concerns/ldap_authenticable.rb
@@ -6,6 +6,7 @@ module LdapAuthenticable
def ldap_setup(_attributes)
self.confirmed_at = Time.now.utc
self.admin = false
+ self.external = true
save!
end
diff --git a/app/models/concerns/omniauthable.rb b/app/models/concerns/omniauthable.rb
index 1b28b8162efddf..283033083959ca 100644
--- a/app/models/concerns/omniauthable.rb
+++ b/app/models/concerns/omniauthable.rb
@@ -66,6 +66,7 @@ def user_params_from_auth(auth)
email: email || "#{TEMP_EMAIL_PREFIX}-#{auth.uid}-#{auth.provider}.com",
password: Devise.friendly_token[0, 20],
agreement: true,
+ external: true,
account_attributes: {
username: ensure_unique_username(auth.uid),
display_name: display_name,
diff --git a/app/models/concerns/pam_authenticable.rb b/app/models/concerns/pam_authenticable.rb
index 2f651c1a359619..6169d4dfaa103e 100644
--- a/app/models/concerns/pam_authenticable.rb
+++ b/app/models/concerns/pam_authenticable.rb
@@ -34,6 +34,7 @@ def pam_setup(_attributes)
self.confirmed_at = Time.now.utc
self.admin = false
self.account = account
+ self.external = true
account.destroy! unless save
end
diff --git a/app/models/domain_block.rb b/app/models/domain_block.rb
index 069cda3673e6fc..0b12617c6cc8f2 100644
--- a/app/models/domain_block.rb
+++ b/app/models/domain_block.rb
@@ -29,4 +29,11 @@ class DomainBlock < ApplicationRecord
def self.blocked?(domain)
where(domain: domain, severity: :suspend).exists?
end
+
+ def stricter_than?(other_block)
+ return true if suspend?
+ return false if other_block.suspend? && (silence? || noop?)
+ return false if other_block.silence? && noop?
+ (reject_media || !other_block.reject_media) && (reject_reports || !other_block.reject_reports)
+ end
end
diff --git a/app/models/media_attachment.rb b/app/models/media_attachment.rb
index a57ba0b2ea0ed4..ab794faa055655 100644
--- a/app/models/media_attachment.rb
+++ b/app/models/media_attachment.rb
@@ -18,6 +18,7 @@
# account_id :bigint(8)
# description :text
# scheduled_status_id :bigint(8)
+# blurhash :string
#
class MediaAttachment < ApplicationRecord
@@ -32,6 +33,11 @@ class MediaAttachment < ApplicationRecord
VIDEO_MIME_TYPES = ['video/webm', 'video/mp4', 'video/quicktime'].freeze
VIDEO_CONVERTIBLE_MIME_TYPES = ['video/webm', 'video/quicktime'].freeze
+ BLURHASH_OPTIONS = {
+ x_comp: 4,
+ y_comp: 4,
+ }.freeze
+
IMAGE_STYLES = {
original: {
pixels: 1_638_400, # 1280x1280px
@@ -41,6 +47,7 @@ class MediaAttachment < ApplicationRecord
small: {
pixels: 160_000, # 400x400px
file_geometry_parser: FastGeometryParser,
+ blurhash: BLURHASH_OPTIONS,
},
}.freeze
@@ -53,6 +60,8 @@ class MediaAttachment < ApplicationRecord
},
format: 'png',
time: 0,
+ file_geometry_parser: FastGeometryParser,
+ blurhash: BLURHASH_OPTIONS,
},
}.freeze
@@ -166,11 +175,11 @@ def file_styles(f)
def file_processors(f)
if f.file_content_type == 'image/gif'
- [:gif_transcoder]
+ [:gif_transcoder, :blurhash_transcoder]
elsif VIDEO_MIME_TYPES.include? f.file_content_type
- [:video_transcoder]
+ [:video_transcoder, :blurhash_transcoder]
else
- [:lazy_thumbnail]
+ [:lazy_thumbnail, :blurhash_transcoder]
end
end
end
diff --git a/app/models/user.rb b/app/models/user.rb
index 135baae122b42e..bce28aa5fb456b 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -78,7 +78,7 @@ class User < ApplicationRecord
accepts_nested_attributes_for :invite_request, reject_if: ->(attributes) { attributes['text'].blank? }
validates :locale, inclusion: I18n.available_locales.map(&:to_s), if: :locale?
- validates_with BlacklistedEmailValidator, if: :email_changed?
+ validates_with BlacklistedEmailValidator, on: :create
validates_with EmailMxValidator, if: :validate_email_dns?
validates :agreement, acceptance: { allow_nil: false, accept: [true, 'true', '1'] }, on: :create
@@ -107,13 +107,14 @@ class User < ApplicationRecord
:expand_spoilers, :default_language, :aggregate_reblogs, :show_application, to: :settings, prefix: :setting, allow_nil: false
attr_reader :invite_code
+ attr_writer :external
def confirmed?
confirmed_at.present?
end
def invited?
- invite_id.present?
+ invite_id.present? && invite.valid_for_use?
end
def disable!
@@ -273,13 +274,17 @@ def send_devise_notification(notification, *args)
private
def set_approved
- self.approved = open_registrations? || invited?
+ self.approved = open_registrations? || invited? || external?
end
def open_registrations?
Setting.registrations_mode == 'open'
end
+ def external?
+ !!@external
+ end
+
def sanitize_languages
return if chosen_languages.nil?
chosen_languages.reject!(&:blank?)
diff --git a/app/serializers/activitypub/note_serializer.rb b/app/serializers/activitypub/note_serializer.rb
index d11cfa59aee7e7..67f596e78a6504 100644
--- a/app/serializers/activitypub/note_serializer.rb
+++ b/app/serializers/activitypub/note_serializer.rb
@@ -2,7 +2,7 @@
class ActivityPub::NoteSerializer < ActivityPub::Serializer
context_extensions :atom_uri, :conversation, :sensitive,
- :hashtag, :emoji, :focal_point
+ :hashtag, :emoji, :focal_point, :blurhash
attributes :id, :type, :summary,
:in_reply_to, :published, :url,
@@ -153,7 +153,7 @@ def poll_and_expired?
class MediaAttachmentSerializer < ActivityPub::Serializer
include RoutingHelper
- attributes :type, :media_type, :url, :name
+ attributes :type, :media_type, :url, :name, :blurhash
attribute :focal_point, if: :focal_point?
def type
diff --git a/app/serializers/initial_state_serializer.rb b/app/serializers/initial_state_serializer.rb
index a7a3d770ce6eb2..0c9fc625f47905 100644
--- a/app/serializers/initial_state_serializer.rb
+++ b/app/serializers/initial_state_serializer.rb
@@ -14,6 +14,8 @@ def meta
domain: Rails.configuration.x.local_domain,
admin: object.admin&.id&.to_s,
search_enabled: Chewy.enabled?,
+ repository: Mastodon::Version.repository,
+ source_url: Mastodon::Version.source_url,
version: Mastodon::Version.to_s,
invites_enabled: Setting.min_invite_role == 'user',
mascot: instance_presenter.mascot&.file&.url,
diff --git a/app/serializers/rest/media_attachment_serializer.rb b/app/serializers/rest/media_attachment_serializer.rb
index 51011788bae1a7..1b3498ea4ebc1a 100644
--- a/app/serializers/rest/media_attachment_serializer.rb
+++ b/app/serializers/rest/media_attachment_serializer.rb
@@ -5,7 +5,7 @@ class REST::MediaAttachmentSerializer < ActiveModel::Serializer
attributes :id, :type, :url, :preview_url,
:remote_url, :text_url, :meta,
- :description
+ :description, :blurhash
def id
object.id.to_s
diff --git a/app/services/block_service.rb b/app/services/block_service.rb
index 140b238df3e418..10ed470e0a3e43 100644
--- a/app/services/block_service.rb
+++ b/app/services/block_service.rb
@@ -6,6 +6,7 @@ def call(account, target_account)
UnfollowService.new.call(account, target_account) if account.following?(target_account)
UnfollowService.new.call(target_account, account) if target_account.following?(account)
+ RejectFollowService.new.call(account, target_account) if target_account.requested?(account)
block = account.block!(target_account)
diff --git a/app/services/fetch_link_card_service.rb b/app/services/fetch_link_card_service.rb
index 7979c312e5d771..494aaed759c389 100644
--- a/app/services/fetch_link_card_service.rb
+++ b/app/services/fetch_link_card_service.rb
@@ -165,7 +165,7 @@ def attempt_opengraph
end
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
def lock_options
diff --git a/app/validators/blacklisted_email_validator.rb b/app/validators/blacklisted_email_validator.rb
index a2061fdd311069..a288c20ef4bfaa 100644
--- a/app/validators/blacklisted_email_validator.rb
+++ b/app/validators/blacklisted_email_validator.rb
@@ -2,7 +2,10 @@
class BlacklistedEmailValidator < ActiveModel::Validator
def validate(user)
+ return if user.invited?
+
@email = user.email
+
user.errors.add(:email, I18n.t('users.invalid_email')) if blocked_email?
end
@@ -13,7 +16,7 @@ def blocked_email?
end
def on_blacklist?
- return true if EmailDomainBlock.block?(@email)
+ return true if EmailDomainBlock.block?(@email)
return false if Rails.configuration.x.email_domains_blacklist.blank?
domains = Rails.configuration.x.email_domains_blacklist.gsub('.', '\.')
diff --git a/app/views/accounts/_header.html.haml b/app/views/accounts/_header.html.haml
index 370e7e470f50dc..4ef9f94787e2b1 100644
--- a/app/views/accounts/_header.html.haml
+++ b/app/views/accounts/_header.html.haml
@@ -3,7 +3,7 @@
= image_tag (current_account&.user&.setting_auto_play_gif ? account.header_original_url : account.header_static_url), class: 'parallax'
.public-account-header__bar
= 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__name
%h1
diff --git a/app/views/auth/registrations/new.html.haml b/app/views/auth/registrations/new.html.haml
index bd6e3a13f754c2..b4a7cced55c69d 100644
--- a/app/views/auth/registrations/new.html.haml
+++ b/app/views/auth/registrations/new.html.haml
@@ -36,6 +36,6 @@
= f.input :agreement, as: :boolean, wrapper: :with_label, label: t('auth.checkbox_agreement_html', rules_path: about_more_path, terms_path: terms_path)
.actions
- = f.button :button, sign_up_message, type: :submit
+ = f.button :button, @invite.present? ? t('auth.register') : sign_up_message, type: :submit
.form-footer= render 'auth/shared/links'
diff --git a/app/views/stream_entries/_detailed_status.html.haml b/app/views/stream_entries/_detailed_status.html.haml
index 4459581d94c6d1..23f2920d89c860 100644
--- a/app/views/stream_entries/_detailed_status.html.haml
+++ b/app/views/stream_entries/_detailed_status.html.haml
@@ -28,7 +28,7 @@
- elsif !status.media_attachments.empty?
- if status.media_attachments.first.video?
- video = status.media_attachments.first
- = react_component :video, src: video.file.url(:original), preview: video.file.url(:small), sensitive: !current_account&.user&.show_all_media? && status.sensitive? || current_account&.user&.hide_all_media?, width: 670, height: 380, detailed: true, inline: true, alt: video.description do
+ = react_component :video, src: video.file.url(:original), preview: video.file.url(:small), blurhash: video.blurhash, sensitive: !current_account&.user&.show_all_media? && status.sensitive? || current_account&.user&.hide_all_media?, width: 670, height: 380, detailed: true, inline: true, alt: video.description do
= render partial: 'stream_entries/attachment_list', locals: { attachments: status.media_attachments }
- else
= react_component :media_gallery, height: 380, sensitive: !current_account&.user&.show_all_media? && status.sensitive? || current_account&.user&.hide_all_media?, standalone: true, 'autoPlayGif': current_account&.user&.setting_auto_play_gif || autoplay, 'reduceMotion': current_account&.user&.setting_reduce_motion, media: status.media_attachments.map { |a| ActiveModelSerializers::SerializableResource.new(a, serializer: REST::MediaAttachmentSerializer).as_json } do
diff --git a/app/views/stream_entries/_simple_status.html.haml b/app/views/stream_entries/_simple_status.html.haml
index ba22c5340741c0..0df7497e10b6d6 100644
--- a/app/views/stream_entries/_simple_status.html.haml
+++ b/app/views/stream_entries/_simple_status.html.haml
@@ -32,7 +32,7 @@
- elsif !status.media_attachments.empty?
- if status.media_attachments.first.video?
- video = status.media_attachments.first
- = react_component :video, src: video.file.url(:original), preview: video.file.url(:small), sensitive: !current_account&.user&.show_all_media? && status.sensitive? || current_account&.user&.hide_all_media?, width: 610, height: 343, inline: true, alt: video.description do
+ = react_component :video, src: video.file.url(:original), preview: video.file.url(:small), blurhash: video.blurhash, sensitive: !current_account&.user&.show_all_media? && status.sensitive? || current_account&.user&.hide_all_media?, width: 610, height: 343, inline: true, alt: video.description do
= render partial: 'stream_entries/attachment_list', locals: { attachments: status.media_attachments }
- else
= react_component :media_gallery, height: 343, sensitive: !current_account&.user&.show_all_media? && status.sensitive? || current_account&.user&.hide_all_media?, 'autoPlayGif': current_account&.user&.setting_auto_play_gif || autoplay, media: status.media_attachments.map { |a| ActiveModelSerializers::SerializableResource.new(a, serializer: REST::MediaAttachmentSerializer).as_json } do
diff --git a/app/workers/activitypub/processing_worker.rb b/app/workers/activitypub/processing_worker.rb
index a3abe72cf66eed..05139f616db968 100644
--- a/app/workers/activitypub/processing_worker.rb
+++ b/app/workers/activitypub/processing_worker.rb
@@ -7,5 +7,7 @@ class ActivityPub::ProcessingWorker
def perform(account_id, body, delivered_to_account_id = nil)
ActivityPub::ProcessCollectionService.new.call(body, Account.find(account_id), override_timestamps: true, delivered_to_account_id: delivered_to_account_id, delivery: true)
+ rescue ActiveRecord::RecordInvalid => e
+ Rails.logger.debug "Error processing incoming ActivityPub object: #{e}"
end
end
diff --git a/config/initializers/rack_attack_logging.rb b/config/initializers/rack_attack_logging.rb
index 2ddbfb99ce8c7a..c30bd8a6431419 100644
--- a/config/initializers/rack_attack_logging.rb
+++ b/config/initializers/rack_attack_logging.rb
@@ -1,4 +1,6 @@
-ActiveSupport::Notifications.subscribe('rack.attack') do |_name, _start, _finish, _request_id, req|
+ActiveSupport::Notifications.subscribe(/rack_attack/) do |_name, _start, _finish, _request_id, payload|
+ req = payload[:request]
+
next unless [:throttle, :blacklist].include? req.env['rack.attack.match_type']
Rails.logger.info("Rate limit hit (#{req.env['rack.attack.match_type']}): #{req.ip} #{req.request_method} #{req.fullpath}")
end
diff --git a/config/initializers/stoplight.rb b/config/initializers/stoplight.rb
index 1bd4ee6e7cdf0a..7384b2e9a6ba7d 100644
--- a/config/initializers/stoplight.rb
+++ b/config/initializers/stoplight.rb
@@ -1,3 +1,4 @@
require 'stoplight'
Stoplight::Light.default_data_store = Stoplight::DataStore::Redis.new(Redis.current)
+Stoplight::Light.default_notifiers = [Stoplight::Notifier::Logger.new(Rails.logger)]
diff --git a/config/locales/activerecord.pt-BR.yml b/config/locales/activerecord.pt-BR.yml
index ddea7bbb416cd9..85150c1e75a7fc 100644
--- a/config/locales/activerecord.pt-BR.yml
+++ b/config/locales/activerecord.pt-BR.yml
@@ -2,8 +2,9 @@
pt-BR:
activerecord:
attributes:
- status:
- owned_poll: enquete
+ poll:
+ expires_at: Expira em
+ options: Escolhas
errors:
models:
account:
diff --git a/config/locales/activerecord.sk.yml b/config/locales/activerecord.sk.yml
index 9d59edd5be1599..26f6c97377c874 100644
--- a/config/locales/activerecord.sk.yml
+++ b/config/locales/activerecord.sk.yml
@@ -3,7 +3,7 @@ sk:
activerecord:
attributes:
poll:
- expires_at: Uzávierka
+ expires_at: Trvá do
options: Voľby
status:
owned_poll: Anketa
diff --git a/config/locales/ca.yml b/config/locales/ca.yml
index 17a5d9d0ceff09..6169767daea2b5 100644
--- a/config/locales/ca.yml
+++ b/config/locales/ca.yml
@@ -68,6 +68,7 @@ ca:
admin: Administrador
bot: Bot
moderator: Moderador
+ unavailable: Perfil inaccessible
unfollow: Deixa de seguir
admin:
account_actions:
@@ -80,6 +81,7 @@ ca:
destroyed_msg: Nota de moderació destruïda amb èxit!
accounts:
approve: Aprova
+ approve_all: Aprova'ls tots
are_you_sure: N'estàs segur?
avatar: Avatar
by_domain: Domini
@@ -132,6 +134,7 @@ ca:
moderation_notes: Notes de moderació
most_recent_activity: Activitat 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
not_subscribed: No subscrit
outbox_url: URL de la bústia de sortida
@@ -144,6 +147,7 @@ ca:
push_subscription_expires: La subscripció PuSH expira
redownload: Actualitza el perfil
reject: Rebutja
+ reject_all: Rebutja'ls tots
remove_avatar: Eliminar avatar
remove_header: Treu la capçalera
resend_confirmation:
@@ -330,6 +334,8 @@ ca:
expired: Caducat
title: Filtre
title: Convida
+ pending_accounts:
+ title: Comptes pendents (%{count})
relays:
add_new: Afegiu un nou relay
delete: Esborra
@@ -854,18 +860,23 @@ ca:
revoke_success: S'ha revocat la sessió amb èxit
title: Sessions
settings:
+ account: Compte
+ account_settings: Ajustos del compte
+ appearance: Aparènça
authorized_apps: Aplicacions autoritzades
- back: Torna a l'inici
+ back: Torna a Mastodon
delete: Eliminació del compte
development: Desenvolupament
edit_profile: Editar perfil
- export: Exportar informació
+ export: Exportar dades
featured_tags: Etiquetes destacades
identity_proofs: Proves d'identitat
import: Importar
+ import_and_export: Importar i exportar
migrate: Migració del compte
notifications: Notificacions
preferences: Preferències
+ profile: Perfil
relationships: Seguits i seguidors
two_factor_authentication: Autenticació de dos factors
statuses:
@@ -1040,7 +1051,7 @@ ca:
welcome:
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.
- 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_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
diff --git a/config/locales/co.yml b/config/locales/co.yml
index 1b0d8ff6aa3658..8c1a13e54b56ee 100644
--- a/config/locales/co.yml
+++ b/config/locales/co.yml
@@ -269,6 +269,7 @@ co:
created_msg: U blucchime di u duminiu hè attivu
destroyed_msg: U blucchime di u duminiu ùn hè più attivu
domain: Duminiu
+ existing_domain_block_html: Avete digià impostu limite più strette nant'à %{name}, duvete
sbluccallu primu.
new:
create: Creà un blucchime
hint: U blucchime di duminiu ùn impedirà micca a creazione di conti indè a database, mà metudi di muderazione specifiche saranu applicati.
@@ -862,6 +863,7 @@ co:
settings:
account: Contu
account_settings: Parametri di u contu
+ appearance: Apparenza
authorized_apps: Applicazione auturizate
back: Ritornu nant’à Mastodon
delete: Suppressione di u contu
diff --git a/config/locales/cs.yml b/config/locales/cs.yml
index ca456b7efbfcfc..5d05a13d6857a8 100644
--- a/config/locales/cs.yml
+++ b/config/locales/cs.yml
@@ -273,6 +273,7 @@ cs:
created_msg: Blokace domény se právě vyřizuje
destroyed_msg: Blokace domény byla zrušena
domain: Doména
+ existing_domain_block_html: Pro účet %{name} jste již nastavil/a přísnější omezení, musíte jej nejdříve
odblokovat.
new:
create: Vytvořit blokaci
hint: Blokace domény nezakáže vytváření záznamů účtů v databázi, ale bude na tyto účty zpětně a automaticky aplikovat specifické metody moderování.
diff --git a/config/locales/devise.sk.yml b/config/locales/devise.sk.yml
index 0052bc0bcdc88f..5ce04ba7aa0e47 100644
--- a/config/locales/devise.sk.yml
+++ b/config/locales/devise.sk.yml
@@ -3,7 +3,7 @@ sk:
devise:
confirmations:
confirmed: Tvoja emailová adresa bola úspešne overená.
- send_instructions: O niekoľko minút obdržíš email s inštrukciami ako potvrdiť svoj účet. Prosím, skontroluj si aj zložku spam, ak sa k tebe toto potvrdenie nedostalo.
+ send_instructions: O niekoľko minút obdržíš email s pokynmi ako potvrdiť svoj účet. Prosím, skontroluj si aj zložku spam, ak sa k tebe toto potvrdenie nedostalo.
send_paranoid_instructions: Ak sa tvoja emailová adresa nachádza v našej databázi, o niekoľko minút obdržíš email s pokynmi ako potvrdiť svoj účet. Prosím, skontroluj aj zložku spam, ak sa k tebe toto potvrdenie nedostalo.
failure:
already_authenticated: Už si prihlásený/á.
@@ -11,27 +11,27 @@ sk:
invalid: Nesprávny %{authentication_keys}, alebo heslo.
last_attempt: Máš posledný pokus pred zamknutím tvojho účtu.
locked: Tvoj účet je zamknutý.
- not_found_in_database: Nesprávny %{authentication_keys} alebo heslo.
+ not_found_in_database: Nesprávny %{authentication_keys}, alebo heslo.
pending: Tvoj účet je stále prehodnocovaný.
- timeout: Vaša aktívna sezóna vypršala. Pre pokračovanie sa prosím znovu prihláste.
+ timeout: Tvoja aktívna sezóna vypršala. Pre pokračovanie sa prosím prihlás znovu.
unauthenticated: K pokračovaniu sa musíš zaregistrovať alebo prihlásiť.
unconfirmed: Pred pokračovaním musíš potvrdiť svoj email.
mailer:
confirmation_instructions:
- action: Potvŕď emailovú adresu
+ action: Potvrď emailovú adresu
action_with_app: Potvrď a vráť sa na %{app}
explanation: S touto emailovou adresou si si vytvoril/a účet na %{host}. Si iba jeden klik od jeho aktivácie. Pokiaľ si to ale nebol/a ty, prosím ignoruj tento email.
- extra_html: Prosím pozri sa aj na
pravidlá tohto servera, a
naše užívaťeľské podiemky.
- subject: 'Mastodon: Potvrdzovacie inštrukcie pre %{instance}'
+ extra_html: Prosím, pozri sa aj na
pravidlá tohto servera, a
naše užívaťeľské podiemky.
+ subject: 'Mastodon: Potvrdzovacie pokyny pre %{instance}'
title: Potvrď emailovú adresu
email_changed:
explanation: 'Emailová adresa tvojho účtu bude zmenená na:'
- extra: Pokiaľ si nezmenil/a svoj email, je pravdepodobné že niekto iný získal prístup k tvojmu účtu. Naliehavo preto prosím zmeň svoje heslo, alebo kontaktuj administrátora tohto serveru pokiaľ si vymknutý/á zo svojho účtu.
+ extra: Ak si nezmenil/a svoj email, je pravdepodobné, že niekto iný získal prístup k tvojmu účtu. Naliehavo preto prosím zmeň svoje heslo, alebo kontaktuj administrátora tohto serveru, pokiaľ si vymknutý/á zo svojho účtu.
subject: 'Mastodon: Emailová adresa bola zmenená'
title: Nová emailová adresa
password_change:
explanation: Heslo k tvojmu účtu bolo zmenené.
- extra: Ak si heslo nezmenil/a, je pravdepodobné že niekto iný získal prístup k tvojmu účtu. Naliehavo preto prosím zmeň svoje heslo, alebo kontaktuj administrátora tohto serveru pokiaľ si vymknutý/á zo svojho účtu.
+ extra: Ak si heslo nezmenil/a, je pravdepodobné, že niekto iný získal prístup k tvojmu účtu. Naliehavo preto prosím zmeň svoje heslo, alebo kontaktuj administrátora tohto serveru, pokiaľ si vymknutý/á zo svojho účtu.
subject: 'Mastodon: Heslo bolo zmenené'
title: Heslo bolo zmenené
reconfirmation_instructions:
@@ -42,17 +42,17 @@ sk:
reset_password_instructions:
action: Zmeň svoje heslo
explanation: Vyžiadal/a si si nové heslo pre svoj účet.
- extra: Pokiaľ si túto akciu nevyžiadal/a, prosím ignoruj tento email. Tvoje heslo nebude zmenené pokiaľ nepostúpiš na adresu uvedenú vyššie a vytvoríš si nové.
- subject: 'Mastodon: Inštrukcie pre obnovu hesla'
+ extra: Ak si túto akciu nevyžiadal/a, prosím ignoruj tento email. Tvoje heslo nebude zmenené pokiaľ nepostúpiš na adresu uvedenú vyššie a vytvoríš si nové.
+ subject: 'Mastodon: Pokyny pre obnovu hesla'
title: Nastav nové heslo
unlock_instructions:
- subject: 'Mastodon: Inštrukcie pre odomknutie účtu'
+ subject: 'Mastodon: Pokyny na odomknutie účtu'
omniauth_callbacks:
- failure: Nebolo možné ťa overiť z dôvodu,%{kind} že "%{reason}".
+ failure: Nebolo možné ťa overiť z %{kind}, lebo "%{reason}".
success: Úspešné overenie z účtu %{kind}.
passwords:
- no_token: Túto stránku nemôžete navštíviť pokiaľ neprichádzate z emailu s inštrukciami na obnovu hesla. Pokiaľ prichádzate z tohto emailu, prosím uistite sa že ste použili celú URL z emailu.
- send_instructions: Pokiaľ sa tvoja emailová adresa nachádza v databázi, tak o niekoľko minút obdržíš email s inštrukciami ako nastaviť nové heslo. Ak máš pocit, že si email neobdržal/a, prosím skontroluj aj svoju spam zložku.
+ no_token: Túto stránku nemôžeš navštíviť, ak neprichádzaš z emailu s pokynmi na obnovu hesla. Pokiaľ prichádzaš z tohto emailu, prosím uisti sa že si použil/a celú URL adresu z emailu.
+ send_instructions: Ak sa tvoja emailová adresa nachádza v databázi, tak o niekoľko minút obdržíš email s pokynmi ako nastaviť nové heslo. Ak máš pocit, že si email neobdržal/a, prosím skontroluj aj svoju spam zložku.
send_paranoid_instructions: Ak sa tvoja emailová adresa nachádza v databázi, za chvíľu obdržíš odkaz pre obnovu hesla na svoj email. Skontroluj ale prosím aj svoj spam, ak tento email nevidíš.
updated: Tvoje heslo bolo úspešne zmenené. Teraz si prihlásený/á.
updated_not_active: Tvoje heslo bolo úspešne zmenené.
@@ -66,9 +66,9 @@ sk:
update_needs_confirmation: Účet bol úspešne pozmenený, ale ešte potrebujeme overiť tvoju novú emailovú adresu. Pre overenie prosím klikni na link v správe ktorú si dostal/a na email. Takisto ale skontroluj aj svoju spam zložku, ak sa ti zdá, že si tento email nedostal/a.
updated: Tvoj účet bol úspešne aktualizovaný.
sessions:
- already_signed_out: Odhlásil/a si sa úspešné.
- signed_in: Prihlásil/a si sa úspešné.
- signed_out: Odhlásil/a si sa úspešné.
+ already_signed_out: Už si sa úspešne odhlásil/a.
+ signed_in: Prihlásil/a si sa úspešne.
+ signed_out: Odhlásil/a si sa úspešne.
unlocks:
send_instructions: O niekoľko minút obdržíš email s pokynmi, ako nastaviť nové heslo. Prosím, skontroluj ale aj svoju spam zložku, pokiaľ sa ti zdá, že si tento email nedostal/a.
send_paranoid_instructions: Ak tvoj účet existuje, o niekoľko minút obdržíš email s pokynmi ako si ho odomknúť. Prosím, skontroluj ale aj svoju spam zložku, pokiaľ sa ti zdá, že si tento email nedostal/a.
@@ -79,8 +79,8 @@ sk:
confirmation_period_expired: musí byť potvrdený do %{period}, prosím požiadaj o nový
expired: vypŕšal, prosím, vyžiadaj si nový
not_found: nenájdený
- not_locked: nebol uzamknutý
+ not_locked: nebol zamknutý
not_saved:
- few: "%{resource} nebol uložený kôli %{count} chybám:"
- one: "%{resource} nebol uložený kôli chybe:"
- other: "%{resource} nebol uložený kôli %{count} chybám:"
+ few: "%{resource} nebol uložený kvôli %{count} chybám:"
+ one: "%{resource} nebol uložený kvôli chybe:"
+ other: "%{resource} nebol uložený kvôli %{count} chybám:"
diff --git a/config/locales/en.yml b/config/locales/en.yml
index b9609eccb02dee..c4f0289d98339a 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -269,6 +269,7 @@ en:
created_msg: Domain block is now being processed
destroyed_msg: Domain block has been undone
domain: Domain
+ existing_domain_block_html: You have already imposed stricter limits on %{name}, you need to
unblock it first.
new:
create: Create block
hint: The domain block will not prevent creation of account entries in the database, but will retroactively and automatically apply specific moderation methods on those accounts.
diff --git a/config/locales/fr.yml b/config/locales/fr.yml
index a6c806de39a766..d588b239ffda88 100644
--- a/config/locales/fr.yml
+++ b/config/locales/fr.yml
@@ -260,10 +260,10 @@ fr:
title: Nouveau blocage de domaine
reject_media: Fichiers média rejetés
reject_media_hint: Supprime localement les fichiers média stockés et refuse d’en télécharger ultérieurement. Ne concerne pas les suspensions
- reject_reports: Rapports de rejet
- reject_reports_hint: Ignorez tous les rapports provenant de ce domaine. Sans objet pour les suspensions
+ reject_reports: Rejeter les signalements
+ reject_reports_hint: Ignorez tous les signalements provenant de ce domaine. Ne concerne pas les suspensions
rejecting_media: rejet des fichiers multimédia
- rejecting_reports: rejet de rapports
+ rejecting_reports: rejet des signalements
severity:
silence: silencié
suspend: suspendu
diff --git a/config/locales/nl.yml b/config/locales/nl.yml
index ae274ad702afba..e07e7b13361577 100644
--- a/config/locales/nl.yml
+++ b/config/locales/nl.yml
@@ -68,6 +68,7 @@ nl:
admin: Beheerder
bot: Bot
moderator: Moderator
+ unavailable: Profiel niet beschikbaar
unfollow: Ontvolgen
admin:
account_actions:
@@ -80,6 +81,7 @@ nl:
destroyed_msg: Verwijderen van opmerking voor moderatoren geslaagd!
accounts:
approve: Goedkeuren
+ approve_all: Alles goedkeuren
are_you_sure: Weet je het zeker?
avatar: Avatar
by_domain: Domein
@@ -132,6 +134,7 @@ nl:
moderation_notes: Opmerkingen voor moderatoren
most_recent_activity: Laatst actief
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
not_subscribed: Niet geabonneerd
outbox_url: Outbox-URL
@@ -144,6 +147,7 @@ nl:
push_subscription_expires: PuSH-abonnement verloopt op
redownload: Profiel vernieuwen
reject: Afkeuren
+ reject_all: Alles afkeuren
remove_avatar: Avatar verwijderen
remove_header: Omslagfoto verwijderen
resend_confirmation:
@@ -245,6 +249,7 @@ nl:
feature_profile_directory: Gebruikersgids
feature_registrations: Registraties
feature_relay: Federatierelay
+ feature_timeline_preview: Voorvertoning van tijdlijn
features: Functies
hidden_service: Federatie met verborgen diensten
open_reports: onopgeloste rapportages
@@ -329,6 +334,8 @@ nl:
expired: Verlopen
title: Filter
title: Uitnodigingen
+ pending_accounts:
+ title: Accounts in afwachting (%{count})
relays:
add_new: Nieuwe relayserver toevoegen
delete: Verwijderen
@@ -428,14 +435,14 @@ nl:
desc_html: Medewerkersbadge op profielpagina tonen
title: Medewerkersbadge tonen
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
<a>
en
<em>
.
- title: Omschrijving Mastodonserver
+ 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
<a>
en
<em>
.
+ title: Omschrijving Mastodonserver (API)
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
title: Uitgebreide omschrijving Mastodonserver
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.
- title: Korte omschrijving Mastodonserver
+ 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: Omschrijving Mastodonserver (website)
site_terms:
desc_html: Je kan hier jouw eigen privacybeleid, gebruiksvoorwaarden en ander juridisch jargon kwijt. Je kan HTML gebruiken
title: Aangepaste gebruiksvoorwaarden
@@ -585,6 +592,9 @@ nl:
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
Mastodon-app 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:
archive_takeout:
date: Datum
@@ -628,10 +638,13 @@ nl:
all: Alles
changes_saved_msg: Wijzigingen succesvol opgeslagen!
copy: Kopiëren
+ order_by: Sorteer op
save_changes: Wijzigingen opslaan
validation_errors:
one: Er is iets niet helemaal goed! Bekijk onderstaande fout
other: Er is iets niet helemaal goed! Bekijk onderstaande %{count} fouten
+ html_validator:
+ invalid_markup: 'bevat ongeldige HTML-opmaak: %{error}'
identity_proofs:
active: Actief
authorize: Ja, autoriseren
@@ -646,6 +659,8 @@ nl:
i_am_html: Ik ben %{username} op %{service}.
identity: Identiteit
inactive: Inactief
+ publicize_checkbox: 'En toot dit:'
+ publicize_toot: 'Het is bewezen! Ik ben %{username} op %{service}: %{url}'
status: Verificatiestatus
view_proof: Bekijk bewijs
imports:
@@ -768,6 +783,8 @@ nl:
relationships:
activity: Accountactiviteit
dormant: Sluimerend
+ last_active: Laatst actief
+ most_recent: Recentelijk gevolgd
moved: Verhuisd
mutual: Wederzijds
primary: Primair
@@ -843,6 +860,9 @@ nl:
revoke_success: Sessie succesvol ingetrokken
title: Sessies
settings:
+ account: Account
+ account_settings: Accountinstellingen
+ appearance: Uiterlijk
authorized_apps: Geautoriseerde apps
back: Terug naar Mastodon
delete: Account verwijderen
@@ -852,9 +872,11 @@ nl:
featured_tags: Uitgelichte hashtags
identity_proofs: Identiteitsbewijzen
import: Importeren
+ import_and_export: Importeren en exporteren
migrate: Accountmigratie
notifications: Meldingen
preferences: Voorkeuren
+ profile: Profiel
relationships: Volgers en gevolgden
two_factor_authentication: Tweestapsverificatie
statuses:
diff --git a/config/locales/pt-BR.yml b/config/locales/pt-BR.yml
index 2d117128877ecf..22a3918a196deb 100644
--- a/config/locales/pt-BR.yml
+++ b/config/locales/pt-BR.yml
@@ -68,6 +68,7 @@ pt-BR:
admin: Administrador
bot: Robô
moderator: Moderador
+ unavailable: Perfil indisponível
unfollow: Deixar de seguir
admin:
account_actions:
@@ -80,6 +81,7 @@ pt-BR:
destroyed_msg: Nota de moderação excluída com sucesso!
accounts:
approve: Aprovar
+ approve_all: Aprovar tudo
are_you_sure: Você tem certeza?
avatar: Avatar
by_domain: Domínio
@@ -132,6 +134,7 @@ pt-BR:
moderation_notes: Notas de moderação
most_recent_activity: Atividade mais recente
most_recent_ip: IP mais recente
+ no_account_selected: Nenhuma conta foi modificada, pois nenhuma conta foi selecionada
no_limits_imposed: Nenhum limite imposto
not_subscribed: Não está inscrito
outbox_url: URL da caixa de saída
@@ -144,6 +147,7 @@ pt-BR:
push_subscription_expires: Inscrição PuSH expira
redownload: Atualizar perfil
reject: Rejeitar
+ reject_all: Rejeitar tudo
remove_avatar: Remover avatar
remove_header: Remover cabeçalho
resend_confirmation:
@@ -330,6 +334,8 @@ pt-BR:
expired: Expirados
title: Filtro
title: Convites
+ pending_accounts:
+ title: Contas pendentes (%{count})
relays:
add_new: Adicionar novo repetidor
delete: Excluir
@@ -854,6 +860,9 @@ pt-BR:
revoke_success: Sessão revogada com sucesso
title: Sessões
settings:
+ account: Conta
+ account_settings: Configurações da conta
+ appearance: Aparência
authorized_apps: Apps autorizados
back: Voltar para o Mastodon
delete: Exclusão de conta
@@ -863,9 +872,11 @@ pt-BR:
featured_tags: Hashtags em destaque
identity_proofs: Provas de identidade
import: Importar
+ import_and_export: Importar e exportar
migrate: Migração de conta
notifications: Notificações
preferences: Preferências
+ profile: Perfil
relationships: Seguindo e seguidores
two_factor_authentication: Autenticação em dois passos
statuses:
diff --git a/config/locales/simple_form.nl.yml b/config/locales/simple_form.nl.yml
index 0d7d1a847dea86..09bd4e856a5cd7 100644
--- a/config/locales/simple_form.nl.yml
+++ b/config/locales/simple_form.nl.yml
@@ -41,6 +41,8 @@ nl:
name: 'Je wilt misschien een van deze gebruiken:'
imports:
data: CSV-bestand dat op een andere Mastodonserver werd geëxporteerd
+ invite_request:
+ text: Dit helpt ons om jouw aanvraag te beoordelen
sessions:
otp: 'Voer de tweestaps-aanmeldcode vanaf jouw mobiele telefoon in of gebruik een van jouw herstelcodes:'
user:
@@ -118,12 +120,15 @@ nl:
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_dm: Directe berichten van mensen die jij niet volgt blokkeren
+ invite_request:
+ text: Waarom wil jij je aanmelden?
notification_emails:
digest: Periodiek e-mails met een samenvatting versturen
favourite: Een e-mail versturen wanneer iemand jouw toot aan hun favorieten heeft toegevoegd
follow: Een e-mail versturen wanneer iemand jou volgt
follow_request: Een e-mail versturen wanneer iemand jou wil volgen
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
report: Verstuur een e-mail wanneer een nieuw rapportage is ingediend
'no': Nee
diff --git a/config/locales/simple_form.pl.yml b/config/locales/simple_form.pl.yml
index abc2c17a91e91a..e1cbee91c572ef 100644
--- a/config/locales/simple_form.pl.yml
+++ b/config/locales/simple_form.pl.yml
@@ -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_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_hide_all: Zawsze ukrywaj zawartość multimedialną
- setting_display_media_show_all: Zawsze pokazuj zawartość multimedialną jako wrażliwą
+ setting_display_media_hide_all: Zawsze oznaczaj 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_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
diff --git a/config/locales/simple_form.pt-BR.yml b/config/locales/simple_form.pt-BR.yml
index 6cd6c7c8541f32..734bd21d01311e 100644
--- a/config/locales/simple_form.pt-BR.yml
+++ b/config/locales/simple_form.pt-BR.yml
@@ -41,6 +41,8 @@ pt-BR:
name: 'Você pode querer usar um destes:'
imports:
data: Arquivo CSV exportado de outra instância do Mastodon
+ invite_request:
+ text: Isso vai nos ajudar a revisar sua aplicação
sessions:
otp: 'Insira o código de autenticação gerado pelo app no seu celular ou use um dos códigos de recuperação:'
user:
@@ -118,12 +120,15 @@ pt-BR:
must_be_follower: Bloquear notificações de não-seguidores
must_be_following: Bloquear notificações de pessoas que você não segue
must_be_following_dm: Bloquear mensagens diretas de pessoas que você não segue
+ invite_request:
+ text: Por que você quer se cadastrar?
notification_emails:
digest: Mandar e-mails com relatórios
favourite: Mandar um e-mail quando alguém favoritar suas postagens
follow: Mandar um e-mail quando alguém te seguir
follow_request: Mandar um e-maill quando alguém solicitar ser seu seguidor
mention: Mandar um e-mail quando alguém te mencionar
+ pending_account: Mandar um -mail quando uma nova conta precisar ser revisada
reblog: Mandar um e-mail quando alguém compartilhar suas postagens
report: Mandar um e-mail quando uma nova denúncia é submetida
'no': Não
diff --git a/config/locales/sk.yml b/config/locales/sk.yml
index bf7898ed74bd42..d859d16b1e1fb7 100644
--- a/config/locales/sk.yml
+++ b/config/locales/sk.yml
@@ -10,7 +10,7 @@ sk:
api: API
apps: Aplikácie
apps_platforms: Uživaj Mastodon z iOSu, Androidu a iných platforiem
- browse_directory: Prehľadávaj databázu profilov a filtruj ju podľa záujmov
+ browse_directory: Prehľadávaj databázu profilov, filtruj podľa záujmov
browse_public_posts: Prebádaj naživo prúd verejných príspevkov na Mastodone
contact: Kontakt
contact_missing: Nezadaný
@@ -20,9 +20,9 @@ sk:
extended_description_html: |
Pravidlá
Žiadne zatiaľ uvedené nie sú
- federation_hint_html: S účtom na %{instance} budeš môcť následovať ľúdí na hociakom inom Mastodon serveri, ale aj inde.
+ federation_hint_html: S účtom na %{instance} budeš môcť následovať ľúdí na hociakom Mastodon serveri, ale aj inde.
generic_description: "%{domain} je jeden server v sieti"
- get_apps: Vyskúšaj mobilnú aplikáciu
+ get_apps: Vyskúšaj aplikácie
hosted_on: Mastodon hostovaný na %{domain}
learn_more: Zisti viac
privacy_policy: Ustanovenia o súkromí
@@ -32,22 +32,22 @@ sk:
status_count_after:
few: príspevkov
one: príspevok
- other: príspevkov
+ other: príspevky
status_count_before: Ktorí napísali
tagline: Následuj kamarátov, a objavuj nových
terms: Podmienky užívania
user_count_after:
- few: užívatelia
+ few: užívateľov
one: užívateľ
- other: užívateľov
+ other: užívatelia
user_count_before: Domov pre
what_is_mastodon: Čo je Mastodon?
accounts:
choices_html: "%{name}vé voľby:"
- follow: Sleduj
+ follow: Následuj
followers:
- few: Sledovatelia
- one: Sledujúci
+ few: Sledovateľov
+ one: Sledovateľ
other: Sledovatelia
following: Sledovaní
joined: Pridal/a sa v %{date}
@@ -70,8 +70,9 @@ sk:
reserved_username: Prihlasovacie meno je rezervované
roles:
admin: Administrátor
- bot: Automat
+ bot: Bot
moderator: Moderátor
+ unavailable: Profil nieje dostupný
unfollow: Prestaň sledovať
admin:
account_actions:
@@ -84,12 +85,13 @@ sk:
destroyed_msg: Moderátorska poznámka bola úspešne zmazaná!
accounts:
approve: Schváľ
+ approve_all: Schváľ všetky
are_you_sure: Si si istý/á?
avatar: Maskot
by_domain: Doména
change_email:
- changed_msg: Email k tomuto účtu bol úspešne zmenený!
- current_email: Súčastný email
+ changed_msg: Email pre tento účet bol úspešne zmenený!
+ current_email: Súčasný email
label: Zmeň email
new_email: Nový email
submit: Zmeň email
@@ -97,37 +99,37 @@ sk:
confirm: Potvrď
confirmed: Potvrdený
confirming: Potvrdzujúci
- deleted: Zmazané
- demote: Degradovať
+ deleted: Vymazané
+ demote: Degraduj
disable: Zablokuj
disable_two_factor_authentication: Zakáž 2FA
disabled: Blokovaný
- display_name: Zobraziť meno
+ display_name: Ukáž meno
domain: Doména
edit: Uprav
email: Email
email_status: Stav emailu
- enable: Povoliť
+ enable: Povoľ
enabled: Povolený
- feed_url: URL časovej osi
+ feed_url: URL adresa časovej osi
followers: Sledujúci
- followers_url: URL sledujúcich
+ followers_url: URL adresa sledujúcich
follows: Sledovania
header: Hlavička
- inbox_url: URL prijatých správ
+ inbox_url: URL adresa prijatých správ
invited_by: Pozvaný/á užívateľom
- ip: IP
+ ip: IP adresa
joined: Pridal/a sa
location:
all: Všetko
local: Miestne
remote: Federované
- title: Lokácia
+ title: Umiestnenie
login_status: Stav prihlásenia
media_attachments: Prílohy
- memorialize: Zmeniť na "Navždy budeme spomínať"
+ memorialize: Zmeň na "Navždy budeme spomínať"
moderation:
- active: Aktívny
+ active: Aktívny/a
all: Všetko
pending: Čakajúci
silenced: Umlčané
@@ -135,21 +137,22 @@ sk:
title: Moderácia
moderation_notes: Moderátorské poznámky
most_recent_activity: Posledná aktivita
- most_recent_ip: Posledná IP
+ most_recent_ip: Posledná IP adresa
no_limits_imposed: Nie sú stanovené žiadné obmedzenia
not_subscribed: Neodoberá
outbox_url: URL poslaných
pending: Vyžaduje posúdenie
perform_full_suspension: Vylúč
- profile_url: URL profilu
- promote: Povýš
+ profile_url: URL adresa profilu
+ promote: Vyzdvihni
protocol: Protokol
- public: Verejná os
+ public: Verejná časová os
push_subscription_expires: PuSH odoberanie expiruje
redownload: Obnov profil
- reject: Odmietni
- remove_avatar: Odstrániť avatár
- remove_header: Odstráň hlavičku
+ reject: Zamietni
+ reject_all: Zamietni všetky
+ remove_avatar: Vymaž avatar
+ remove_header: Vymaž hlavičku
resend_confirmation:
already_confirmed: Tento užívateľ je už potvrdený
send: Odošli potvrdzovací email znovu
@@ -164,7 +167,7 @@ sk:
staff: Člen
user: Užívateľ
salmon_url: Salmon adresa
- search: Hľadať
+ search: Hľadaj
shared_inbox_url: URL zdieľanej schránky
show:
created_reports: Vytvorené hlásenia
@@ -172,15 +175,15 @@ sk:
silence: Stíš
silenced: Utíšený/é
statuses: Príspevky
- subscribe: Odoberať
+ subscribe: Odoberaj
suspended: Zablokovaní
title: Účty
unconfirmed_email: Nepotvrdený email
- undo_silenced: Zrušiť stíšenie
+ undo_silenced: Zruš stíšenie
undo_suspension: Zruš blokovanie
unsubscribe: Prestaň odoberať
username: Prezývka
- warn: Varovať
+ warn: Varuj
web: Web
action_logs:
actions:
@@ -227,7 +230,7 @@ sk:
disable: Zakázať
disabled_msg: Emoji bolo úspešne zakázané
emoji: Emotikony
- enable: Povoliť
+ enable: Povoľ
enabled_msg: Emoji bolo úspešne povolené
image_hint: PNG do 50KB
listed: V zozname
@@ -240,7 +243,7 @@ sk:
unlisted: Nie je na zozname
update_failed_msg: Nebolo možné aktualizovať toto emoji
updated_msg: Emoji bolo úspešne aktualizované!
- upload: Nahrať
+ upload: Nahraj
dashboard:
backlog: odložené aktivity
config: Nastavenia
@@ -249,10 +252,11 @@ sk:
feature_profile_directory: Katalóg profilov
feature_registrations: Registrácie
feature_relay: Federovací mostík
+ feature_timeline_preview: Náhľad časovej osi
features: Vymoženosti
hidden_service: Federácia so skrytými službami
open_reports: otvorené hlásenia
- recent_users: Nedávny užívatelia
+ recent_users: Nedávni užívatelia
search: Celofrázové vyhľadávanie
single_user_mode: Jednouživateľské rozhranie
software: Softvér
@@ -264,10 +268,11 @@ sk:
week_users_active: aktívni tento týždeň
week_users_new: užívateľov počas tohto týždňa
domain_blocks:
- add_new: Pridaj nové doménové blokovanie
- created_msg: Doména je v procese blokovania
+ add_new: Blokuj novú doménu
+ created_msg: Doména je v štádiu blokovania
destroyed_msg: Blokovanie domény bolo zrušené
domain: Doména
+ existing_domain_block_html: Pre účet %{name} si už nahodil/a přísnejšie obmedzenie, najskôr ho teda musíš
odblokovať.
new:
create: Vytvor blokovanie domény
hint: Blokovanie domény stále dovolí vytvárať nové účty v databázi, ale tieto budú spätne automaticky moderované.
@@ -284,7 +289,7 @@ sk:
rejecting_media: odmietanie médiálnych súborov
rejecting_reports: odmietané hlásenia
severity:
- silence: utíšené
+ silence: stíšený
suspend: vylúčený
show:
affected_accounts:
@@ -295,12 +300,12 @@ sk:
silence: Zruš stíšenie všetkých existujúcich účtov z tejto domény
suspend: Zruš suspendáciu všetkých existujúcich účtov z tejto domény
title: Zruš blokovanie domény %{domain}
- undo: Vrátiť späť
+ undo: Vráť späť
undo: Odvolaj blokovanie domény
email_domain_blocks:
add_new: Pridaj nový
created_msg: Emailová doména bola úspešne pridaná do zoznamu zakázaných
- delete: Zmazať
+ delete: Vymaž
destroyed_msg: Emailová doména bola úspešne vymazaná zo zoznamu zakázaných
domain: Doména
new:
@@ -328,15 +333,15 @@ sk:
total_reported: Nahlásenia o nich
total_storage: Mediálne prílohy
invites:
- deactivate_all: Pozastaviť všetky
+ deactivate_all: Pozastav všetky
filter:
all: Všetky
available: Dostupné
expired: Vypršalo
- title: Filtrovať
+ title: Filtruj
title: Pozvánky
relays:
- add_new: Pridaj novú priechodnú oporu
+ add_new: Pridaj nový federovací mostík
delete: Vymaž
description_html: "
Federovací mostík je prechodný server ktorý obmieňa veľké množstvá verejných príspevkov medzi tými servermi ktoré na od neho odoberajú, aj doňho prispievajú.
Môže to pomôcť malým a stredným instanciám objavovať federovaný obsah, čo inak vyžaduje aby miestni užívatelia ručne následovali iných ľudí zo vzdialených instancií."
disable: Pozastav
@@ -344,7 +349,7 @@ sk:
enable: Povoľ
enable_hint: Ak povolíš, tvoj server bude odoberať všetky verejné príspevky z tohto mostu, a začne posielať verejné príspevky tvojho servera na tento most.
enabled: Povolené
- inbox_url: URL mostu
+ inbox_url: URL adresa mostu
pending: Čakám na povolenie od prechodného mostu
save_and_enable: Uložiť a povoliť
setup: Nastav prepojenie s mostom
@@ -359,7 +364,7 @@ sk:
report: nahlás
action_taken_by: Zákrok vykonal/a
are_you_sure: Si si istý/á?
- assign_to_self: Priraď k sebe
+ assign_to_self: Priraď sebe
assigned: Priradený moderátor
comment:
none: Žiadne
@@ -379,7 +384,7 @@ sk:
resolved: Vyriešené
resolved_msg: Hlásenie úspešne vyriešené!
status: Stav
- title: Reporty
+ title: Hlásenia
unassign: Odobrať
unresolved: Nevyriešené
updated_at: Aktualizované
@@ -391,7 +396,7 @@ sk:
desc_html: Ak je prezývok viacero, každú oddeľte čiarkou. Možno zadať iba miestne, odomknuté účty. Pokiaľ necháte prázdne, je to pre všetkých miestnych administrátorov.
title: Štandardní následovníci nových užívateľov
contact_information:
- email: Pracovný e-mail
+ email: Pracovný email
username: Kontaktné užívateľské meno
custom_css:
desc_html: Uprav vzhľad pomocou CSS, ktoré je načítané na každej stránke
@@ -508,11 +513,13 @@ sk:
invalid_url: Zadaná URL adresa je nesprávna
regenerate_token: Znovu vygenerovať prístupový token
token_regenerated: Prístupový token bol úspešne vygenerovaný znova
- warning: Na tieto údaje dávajte ohromný pozor. Nikdy ich s nikým nezďieľajte!
- your_token: Váš prístupový token
+ warning: Na tieto údaje dávaj ohromný pozor. Nikdy ich s nikým nezďieľaj!
+ your_token: Tvoj prístupový token
auth:
+ apply_for_account: Vyžiadaj si pozvánku
change_password: Heslo
- confirm_email: Potvrdiť email
+ checkbox_agreement_html: Súhlasím s
pravidlami servera, aj s
prevoznými podmienkami
+ confirm_email: Potvrď email
delete_account: Vymaž účet
delete_account_html: Pokiaľ chceš svoj účet odtiaľto vymazať, môžeš tak
urobiť tu. Budeš požiadaný/á o potvrdenie tohto kroku.
didnt_get_confirmation: Neobdržal/a si kroky na potvrdenie?
@@ -521,16 +528,17 @@ sk:
login: Prihlás sa
logout: Odhlás sa
migrate_account: Presúvam sa na iný účet
- migrate_account_html: Pokiaľ si želáš presmerovať tento účet na nejaký iný, môžeš si to
nastaviť tu.
- or_log_in_with: Alebo prihlásiť z
+ migrate_account_html: Ak si želáš presmerovať tento účet na nejaký iný, môžeš si to
nastaviť tu.
+ or_log_in_with: Alebo prihlás s
providers:
cas: CAS
saml: SAML
register: Zaregistruj sa
- resend_confirmation: Poslať potvrdzujúce pokyny znovu
- reset_password: Resetovať heslo
+ resend_confirmation: Zašli potvrdzujúce pokyny znovu
+ reset_password: Obnov heslo
security: Zabezpečenie
- set_new_password: Nastaviť nové heslo
+ set_new_password: Nastav nové heslo
+ trouble_logging_in: Problém s prihlásením?
authorize_follow:
already_following: Tento účet už následuješ
error: Naneštastie nastala chyba pri hľadaní vzdialeného účtu
@@ -636,10 +644,10 @@ sk:
other: Niečo ešte stále nieje v poriadku! Prosím skontroluj všetky %{count} nižšie uvedené pochybenia
imports:
modes:
- merge: Spojiť dohromady
+ merge: Spoj dohromady
merge_long: Ponechaj existujúce záznamy a pridaj k nim nové
overwrite: Prepíš
- overwrite_long: Nahraď súčasné záznamy s novými
+ overwrite_long: Nahraď súčasné záznamy novými
preface: Môžeš nahrať dáta ktoré si exportoval/a z iného Mastodon serveru, ako sú napríklad zoznamy ľudí ktorých sleduješ, alebo blokuješ.
success: Tvoje dáta boli nahraté úspešne, a teraz budú spracované v danom čase
types:
@@ -647,10 +655,10 @@ sk:
domain_blocking: Zoznam blokovaných domén
following: Zoznam sledovaných
muting: Zoznam ignorovaných
- upload: Nahrať
+ upload: Nahraj
in_memoriam_html: V pamäti.
invites:
- delete: Deaktivovať
+ delete: Deaktivuj
expired: Neplatné
expires_in:
'1800': 30 minút
@@ -661,13 +669,13 @@ sk:
'86400': 1 deň
expires_in_prompt: Nikdy
generate: Vygeneruj
- invited_by: 'Bol/a si pozvan/á užívateľom:'
+ invited_by: 'Bol/a si pozvaný/á užívateľom:'
max_uses:
few: "%{count} použitia"
one: jedno použitie
other: "%{count} použití"
- max_uses_prompt: Bez limitov
- prompt: Vygeneruj a zdieľaj linky s ostatnými aby mali umožnený prístup k tomuto serveru
+ max_uses_prompt: Bez obmedzení
+ prompt: Vygeneruj a zdieľaj linky s ostatnými, aby mali umožnený prístup k tomuto serveru
table:
expires_at: Vyprší
uses: Používa
@@ -692,16 +700,16 @@ sk:
body: Tu nájdete krátky súhrn správ ktoré ste zmeškali od svojej poslednj návštevi od %{since}
mention: "%{name} ťa spomenul/a v:"
new_followers_summary:
- few: Taktiež, získal/a si %{count} nových následovníkov za tú dobu čo si bol/a preč. Yay!
- one: Taktiež, získal/a si jedného nového následovníka zatiaľ čo si bol/a preč. Yay!
- other: Taktiež, získal/a si %{count} nových následovníkov za tú dobu čo si bol/a preč. Yay!
+ few: Tiež si získal/a %{count} nových následovateľov za tú dobu čo si bol/a preč. Yay!
+ one: Tiež si získal/a jedného nového následovateľa zatiaľ čo si bol/a preč. Yay!
+ other: Tiež si získal/a %{count} nových následovateľov za tú dobu čo si bol/a preč. Yay!
subject:
few: "%{count} nové notifikácie od tvojej poslednej návštevy \U0001F418"
- one: "1 nová notifikácia od tvojej poslednej návštevy \U0001F418"
- other: "%{count} nových notifikácií od tvojej poslednej návštevy \U0001F418"
+ one: "1 nové oboznámenie od tvojej poslednej návštevy \U0001F418"
+ other: "%{count} nových oboznámení od tvojej poslednej návštevy \U0001F418"
title: Zatiaľ čo si bol/a preč…
favourite:
- body: 'Tvoj príspevok bol uložený medi obľúbené užívateľa %{name}:'
+ body: 'Tvoj príspevok bol uložený medzi obľúbené užívateľa %{name}:'
subject: "%{name} si obľúbil/a tvoj príspevok"
title: Nové obľúbené
follow:
@@ -712,16 +720,16 @@ sk:
action: Spravuj žiadosti o sledovanie
body: "%{name} žiada povolenie ťa následovať"
subject: "%{name} ťa žiadá o možnosť sledovania"
- title: Nová žiadosť o sledovanie
+ title: Nová žiadosť o následovanie
mention:
action: Odpovedať
body: "%{name} ťa spomenul/a v:"
subject: Bol/a si spomenutý/á užívateľom %{name}
title: Novo spomenutý/á
reblog:
- body: 'Tvoj príspevok bol pozdvihnutý užívateľom %{name}:'
- subject: "%{name} pozdvihli tvoj príspevok"
- title: Novo pozdvyhnuté
+ body: 'Tvoj príspevok bol vyzdvihnutý užívateľom %{name}:'
+ subject: "%{name} vyzdvihli tvoj príspevok"
+ title: Novo vyzdvyhnuté
number:
human:
decimal_units:
@@ -820,17 +828,23 @@ sk:
revoke_success: Sezóna úspešne zamietnutá
title: Sezóny
settings:
+ account: Účet
+ account_settings: Nastavenia účtu
+ appearance: Vzhľad
authorized_apps: Povolené aplikácie
back: Späť na Mastodon
delete: Vymazanie účtu
development: Vývoj
edit_profile: Uprav profil
- export: Exportovať dáta
- featured_tags: Popredne zvýraznené haštagy
- import: Importovať
- migrate: Presunutie účtu
- notifications: Oznámenia
+ export: Exportuj dáta
+ featured_tags: Zvýraznené haštagy
+ import: Importuj
+ import_and_export: Import a export
+ migrate: Presuň účet
+ notifications: Oboznámenia
preferences: Voľby
+ profile: Profil
+ relationships: Následovaní a následovatelia
two_factor_authentication: Dvoj-faktorové overenie
statuses:
attached:
@@ -846,9 +860,9 @@ sk:
boosted_from_html: Povýšené od %{acct_link}
content_warning: 'Varovanie o obsahu: %{warning}'
disallowed_hashtags:
- few: 'obsahoval nepovolené hashtagy: %{tags}'
- one: 'obsahoval nepovolený hashtag: %{tags}'
- other: 'obsahoval nepovolené hashtagy: %{tags}'
+ few: 'obsahoval nepovolené haštagy: %{tags}'
+ one: 'obsahoval nepovolený haštag: %{tags}'
+ other: 'obsahoval nepovolené haštagy: %{tags}'
language_detection: Zisti automaticky
open_in_web: Otvor v okne na webe
over_character_limit: limit %{max} znakov bol presiahnutý
@@ -856,7 +870,7 @@ sk:
limit: Už si si pripol ten najvyšší možný počet hlášok
ownership: Nieje možné pripnúť hlášku od niekoho iného
private: Neverejné príspevky nemôžu byť pripnuté
- reblog: Pozdvihnutie sa nedá pripnúť
+ reblog: Vyzdvihnutie sa nedá pripnúť
poll:
total_votes:
few: "%{count} hlas(y)ov"
@@ -874,14 +888,14 @@ sk:
unlisted: Nezaradené
unlisted_long: Všetci môžu vidieť, ale nieje zaradené do verejnej osi
stream_entries:
- pinned: Pripnutý toot
+ pinned: Pripnutý príspevok
reblogged: vyzdvihnutý
sensitive_content: Senzitívny obsah
terms:
body_html: |
Podmienky súkromia
-
Aké informácie zbierame?
+
Aké informácie sú zbierané?
- Základné informácie o účte: Ak sa na tomto serveri zaregistruješ, budeš môcť byť požiadaný/á zadať prezývku, emailovú adresu a heslo. Budeš tiež môcť zadať aj ďalšie profilové údaje, ako napríklad meno a životopis, a nahrať profilovú fotku aj obrázok v záhlaví. Tvoja prezývka, meno, životopis, profilová fotka a obrázok v záhlaví sú vždy zobrazené verejne.
- Príspevky, sledovania a iné verejné informácie:
@@ -973,7 +987,7 @@ sk:
invalid_otp_token: Neplatný kód pre dvojfaktorovú autentikáciu
otp_lost_help_html: Pokiaľ si stratil/a prístup k obom, môžeš dať vedieť %{email}
seamless_external_login: Si prihlásená/ý cez externú službu, takže nastavenia hesla a emailu ti niesú prístupné.
- signed_in_as: 'Prihlásený ako:'
+ signed_in_as: 'Prihlásená/ý ako:'
verification:
explanation_html: 'Môžeš sa overiť ako majiteľ odkazov v metadátach tvojho profilu. Na to musí ale odkazovaná stránka obsahovať odkaz späť na tvoj Mastodon profil. Tento spätný odkaz musí mať prívlastok
rel="me"
. Na texte odkazu nezáleží. Tu je príklad:'
verification: Overenie
diff --git a/db/migrate/20190420025523_add_blurhash_to_media_attachments.rb b/db/migrate/20190420025523_add_blurhash_to_media_attachments.rb
new file mode 100644
index 00000000000000..f2bbe0a856c18c
--- /dev/null
+++ b/db/migrate/20190420025523_add_blurhash_to_media_attachments.rb
@@ -0,0 +1,5 @@
+class AddBlurhashToMediaAttachments < ActiveRecord::Migration[5.2]
+ def change
+ add_column :media_attachments, :blurhash, :string
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 3060159d25d3b6..8613539d644e80 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 2019_04_09_054914) do
+ActiveRecord::Schema.define(version: 2019_04_20_025523) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -362,6 +362,7 @@
t.bigint "account_id"
t.text "description"
t.bigint "scheduled_status_id"
+ t.string "blurhash"
t.index ["account_id"], name: "index_media_attachments_on_account_id"
t.index ["scheduled_status_id"], name: "index_media_attachments_on_scheduled_status_id"
t.index ["shortcode"], name: "index_media_attachments_on_shortcode", unique: true
diff --git a/docker-compose.yml b/docker-compose.yml
index faa066149baf79..47662d470759e7 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -43,7 +43,7 @@ services:
- external_network
- internal_network
healthcheck:
- test: ["CMD-SHELL", "wget -q --spider --header 'x-forwarded-proto: https' --proxy off localhost:3000/api/v1/instance || exit 1"]
+ test: ["CMD-SHELL", "wget -q --spider --header 'x-forwarded-proto: https' --proxy=off localhost:3000/api/v1/instance || exit 1"]
ports:
- "127.0.0.1:3000:3000"
depends_on:
@@ -63,7 +63,7 @@ services:
- external_network
- internal_network
healthcheck:
- test: ["CMD-SHELL", "wget -q --spider --header 'x-forwarded-proto: https' --proxy off localhost:4000/api/v1/streaming/health || exit 1"]
+ test: ["CMD-SHELL", "wget -q --spider --header 'x-forwarded-proto: https' --proxy=off localhost:4000/api/v1/streaming/health || exit 1"]
ports:
- "127.0.0.1:4000:4000"
depends_on:
diff --git a/lib/cli.rb b/lib/cli.rb
index b56c6e76f5a1ec..5780e3e8734228 100644
--- a/lib/cli.rb
+++ b/lib/cli.rb
@@ -9,6 +9,7 @@
require_relative 'mastodon/settings_cli'
require_relative 'mastodon/statuses_cli'
require_relative 'mastodon/domains_cli'
+require_relative 'mastodon/cache_cli'
require_relative 'mastodon/version'
module Mastodon
@@ -41,6 +42,9 @@ def self.exit_on_failure?
desc 'domains SUBCOMMAND ...ARGS', 'Manage account domains'
subcommand 'domains', Mastodon::DomainsCLI
+ desc 'cache SUBCOMMAND ...ARGS', 'Manage cache'
+ subcommand 'cache', Mastodon::CacheCLI
+
option :dry_run, type: :boolean
desc 'self-destruct', 'Erase the server from the federation'
long_desc <<~LONG_DESC
diff --git a/lib/mastodon/accounts_cli.rb b/lib/mastodon/accounts_cli.rb
index 9dc84f1b5293e5..3131647f3565ba 100644
--- a/lib/mastodon/accounts_cli.rb
+++ b/lib/mastodon/accounts_cli.rb
@@ -73,7 +73,7 @@ def rotate(username = nil)
def create(username)
account = Account.new(username: username)
password = SecureRandom.hex
- user = User.new(email: options[:email], password: password, agreement: true, admin: options[:role] == 'admin', moderator: options[:role] == 'moderator', confirmed_at: options[:confirmed] ? Time.now.utc : nil)
+ user = User.new(email: options[:email], password: password, agreement: true, approved: true, admin: options[:role] == 'admin', moderator: options[:role] == 'moderator', confirmed_at: options[:confirmed] ? Time.now.utc : nil)
if options[:reattach]
account = Account.find_local(username) || Account.new(username: username)
@@ -115,6 +115,7 @@ def create(username)
option :enable, type: :boolean
option :disable, type: :boolean
option :disable_2fa, type: :boolean
+ option :approve, type: :boolean
desc 'modify USERNAME', 'Modify a user'
long_desc <<-LONG_DESC
Modify a user account.
@@ -128,6 +129,9 @@ def create(username)
With the --disable option, lock the user out of their account. The
--enable option is the opposite.
+ With the --approve option, the account will be approved, if it was
+ previously not due to not having open registrations.
+
With the --disable-2fa option, the two-factor authentication
requirement for the user can be removed.
LONG_DESC
@@ -147,6 +151,7 @@ def modify(username)
user.email = options[:email] if options[:email]
user.disabled = false if options[:enable]
user.disabled = true if options[:disable]
+ user.approved = true if options[:approve]
user.otp_required_for_login = false if options[:disable_2fa]
user.confirm if options[:confirm]
diff --git a/lib/mastodon/cache_cli.rb b/lib/mastodon/cache_cli.rb
new file mode 100644
index 00000000000000..e9b6667b3b610a
--- /dev/null
+++ b/lib/mastodon/cache_cli.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+require_relative '../../config/boot'
+require_relative '../../config/environment'
+require_relative 'cli_helper'
+
+module Mastodon
+ class CacheCLI < Thor
+ def self.exit_on_failure?
+ true
+ end
+
+ desc 'clear', 'Clear out the cache storage'
+ def clear
+ Rails.cache.clear
+ say('OK', :green)
+ end
+ end
+end
diff --git a/lib/mastodon/version.rb b/lib/mastodon/version.rb
index c7ccc5b86eb5ab..a63be018a561b0 100644
--- a/lib/mastodon/version.rb
+++ b/lib/mastodon/version.rb
@@ -13,7 +13,7 @@ def minor
end
def patch
- 0
+ 2
end
def pre
@@ -37,16 +37,16 @@ def to_s
end
def repository
- 'tootsuite/mastodon'
+ ENV.fetch('GITHUB_REPOSITORY') { 'tootsuite/mastodon' }
end
def source_base_url
- "https://github.com/#{repository}"
+ ENV.fetch('SOURCE_BASE_URL') { "https://github.com/#{repository}" }
end
# specify git tag or commit hash here
def source_tag
- nil
+ ENV.fetch('SOURCE_TAG') { nil }
end
def source_url
diff --git a/lib/paperclip/blurhash_transcoder.rb b/lib/paperclip/blurhash_transcoder.rb
new file mode 100644
index 00000000000000..08925a6dde01fd
--- /dev/null
+++ b/lib/paperclip/blurhash_transcoder.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module Paperclip
+ class BlurhashTranscoder < Paperclip::Processor
+ def make
+ return @file unless options[:style] == :small
+
+ pixels = convert(':source RGB:-', source: File.expand_path(@file.path)).unpack('C*')
+ geometry = options.fetch(:file_geometry_parser).from_file(@file)
+
+ attachment.instance.blurhash = Blurhash.encode(geometry.width, geometry.height, pixels, options[:blurhash] || {})
+
+ @file
+ end
+ end
+end
diff --git a/package.json b/package.json
index 63cfa25b80548b..67396ccc3790c2 100644
--- a/package.json
+++ b/package.json
@@ -78,6 +78,7 @@
"babel-plugin-react-intl": "^3.0.1",
"babel-plugin-transform-react-remove-prop-types": "^0.4.24",
"babel-runtime": "^6.26.0",
+ "blurhash": "^1.0.0",
"classnames": "^2.2.5",
"compression-webpack-plugin": "^2.0.0",
"cross-env": "^5.1.4",
diff --git a/public/robots.txt b/public/robots.txt
index d93648beee28c9..771bf2160b4e3b 100644
--- a/public/robots.txt
+++ b/public/robots.txt
@@ -2,3 +2,4 @@
User-agent: *
Disallow: /media_proxy/
+Disallow: /interact/
diff --git a/spec/controllers/admin/domain_blocks_controller_spec.rb b/spec/controllers/admin/domain_blocks_controller_spec.rb
index 129bf888370020..2a8675c21a8581 100644
--- a/spec/controllers/admin/domain_blocks_controller_spec.rb
+++ b/spec/controllers/admin/domain_blocks_controller_spec.rb
@@ -37,7 +37,7 @@
end
it 'renders new when failed to save' do
- Fabricate(:domain_block, domain: 'example.com')
+ Fabricate(:domain_block, domain: 'example.com', severity: 'suspend')
allow(DomainBlockWorker).to receive(:perform_async).and_return(true)
post :create, params: { domain_block: { domain: 'example.com', severity: 'silence' } }
@@ -45,6 +45,17 @@
expect(DomainBlockWorker).not_to have_received(:perform_async)
expect(response).to render_template :new
end
+
+ it 'allows upgrading a block' do
+ Fabricate(:domain_block, domain: 'example.com', severity: 'silence')
+ allow(DomainBlockWorker).to receive(:perform_async).and_return(true)
+
+ post :create, params: { domain_block: { domain: 'example.com', severity: 'silence', reject_media: true, reject_reports: true } }
+
+ expect(DomainBlockWorker).to have_received(:perform_async)
+ expect(flash[:notice]).to eq I18n.t('admin.domain_blocks.created_msg')
+ expect(response).to redirect_to(admin_instances_path(limited: '1'))
+ end
end
describe 'DELETE #destroy' do
diff --git a/spec/controllers/auth/registrations_controller_spec.rb b/spec/controllers/auth/registrations_controller_spec.rb
index 1095df034e886f..a4337039e154f6 100644
--- a/spec/controllers/auth/registrations_controller_spec.rb
+++ b/spec/controllers/auth/registrations_controller_spec.rb
@@ -107,6 +107,89 @@
end
end
+ context 'approval-based registrations without invite' do
+ around do |example|
+ registrations_mode = Setting.registrations_mode
+ example.run
+ Setting.registrations_mode = registrations_mode
+ end
+
+ subject do
+ Setting.registrations_mode = 'approved'
+ request.headers["Accept-Language"] = accept_language
+ post :create, params: { user: { account_attributes: { username: 'test' }, email: 'test@example.com', password: '12345678', password_confirmation: '12345678' } }
+ end
+
+ it 'redirects to login page' do
+ subject
+ expect(response).to redirect_to new_user_session_path
+ end
+
+ it 'creates user' do
+ subject
+ user = User.find_by(email: 'test@example.com')
+ expect(user).to_not be_nil
+ expect(user.locale).to eq(accept_language)
+ expect(user.approved).to eq(false)
+ end
+ end
+
+ context 'approval-based registrations with expired invite' do
+ around do |example|
+ registrations_mode = Setting.registrations_mode
+ example.run
+ Setting.registrations_mode = registrations_mode
+ end
+
+ subject do
+ Setting.registrations_mode = 'approved'
+ request.headers["Accept-Language"] = accept_language
+ invite = Fabricate(:invite, max_uses: nil, expires_at: 1.hour.ago)
+ post :create, params: { user: { account_attributes: { username: 'test' }, email: 'test@example.com', password: '12345678', password_confirmation: '12345678', 'invite_code': invite.code } }
+ end
+
+ it 'redirects to login page' do
+ subject
+ expect(response).to redirect_to new_user_session_path
+ end
+
+ it 'creates user' do
+ subject
+ user = User.find_by(email: 'test@example.com')
+ expect(user).to_not be_nil
+ expect(user.locale).to eq(accept_language)
+ expect(user.approved).to eq(false)
+ end
+ end
+
+ context 'approval-based registrations with valid invite' do
+ around do |example|
+ registrations_mode = Setting.registrations_mode
+ example.run
+ Setting.registrations_mode = registrations_mode
+ end
+
+ subject do
+ Setting.registrations_mode = 'approved'
+ request.headers["Accept-Language"] = accept_language
+ invite = Fabricate(:invite, max_uses: nil, expires_at: 1.hour.from_now)
+ post :create, params: { user: { account_attributes: { username: 'test' }, email: 'test@example.com', password: '12345678', password_confirmation: '12345678', 'invite_code': invite.code } }
+ end
+
+ it 'redirects to login page' do
+ subject
+ expect(response).to redirect_to new_user_session_path
+ end
+
+ it 'creates user' do
+ subject
+ user = User.find_by(email: 'test@example.com')
+ expect(user).to_not be_nil
+ expect(user.locale).to eq(accept_language)
+ expect(user.approved).to eq(true)
+ end
+ end
+
it 'does nothing if user already exists' do
Fabricate(:user, account: Fabricate(:account, username: 'test'))
subject
diff --git a/spec/models/domain_block_spec.rb b/spec/models/domain_block_spec.rb
index 89cadccfec2b33..0035fd0ffa0fbd 100644
--- a/spec/models/domain_block_spec.rb
+++ b/spec/models/domain_block_spec.rb
@@ -36,4 +36,35 @@
expect(DomainBlock.blocked?('domain')).to eq false
end
end
+
+ describe 'stricter_than?' do
+ it 'returns true if the new block has suspend severity while the old has lower severity' do
+ suspend = DomainBlock.new(domain: 'domain', severity: :suspend)
+ silence = DomainBlock.new(domain: 'domain', severity: :silence)
+ noop = DomainBlock.new(domain: 'domain', severity: :noop)
+ expect(suspend.stricter_than?(silence)).to be true
+ expect(suspend.stricter_than?(noop)).to be true
+ end
+
+ it 'returns false if the new block has lower severity than the old one' do
+ suspend = DomainBlock.new(domain: 'domain', severity: :suspend)
+ silence = DomainBlock.new(domain: 'domain', severity: :silence)
+ noop = DomainBlock.new(domain: 'domain', severity: :noop)
+ expect(silence.stricter_than?(suspend)).to be false
+ expect(noop.stricter_than?(suspend)).to be false
+ expect(noop.stricter_than?(silence)).to be false
+ end
+
+ it 'returns false if the new block does is less strict regarding reports' do
+ older = DomainBlock.new(domain: 'domain', severity: :silence, reject_reports: true)
+ newer = DomainBlock.new(domain: 'domain', severity: :silence, reject_reports: false)
+ expect(newer.stricter_than?(older)).to be false
+ end
+
+ it 'returns false if the new block does is less strict regarding media' do
+ older = DomainBlock.new(domain: 'domain', severity: :silence, reject_media: true)
+ newer = DomainBlock.new(domain: 'domain', severity: :silence, reject_media: false)
+ expect(newer.stricter_than?(older)).to be false
+ end
+ end
end
diff --git a/spec/validators/blacklisted_email_validator_spec.rb b/spec/validators/blacklisted_email_validator_spec.rb
index d2e442f4ab40bc..84b0107dd70bf9 100644
--- a/spec/validators/blacklisted_email_validator_spec.rb
+++ b/spec/validators/blacklisted_email_validator_spec.rb
@@ -8,6 +8,7 @@
let(:errors) { double(add: nil) }
before do
+ allow(user).to receive(:invited?) { false }
allow_any_instance_of(described_class).to receive(:blocked_email?) { blocked_email }
described_class.new.validate(user)
end
diff --git a/yarn.lock b/yarn.lock
index 9d7f0eccb550b8..329216cdb9afdd 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1743,6 +1743,11 @@ bluebird@^3.5.1, bluebird@^3.5.3:
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.3.tgz#7d01c6f9616c9a51ab0f8c549a79dfe6ec33efa7"
integrity sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==
+blurhash@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/blurhash/-/blurhash-1.0.0.tgz#9087bc5cc4d482f1305059d7410df4133adcab2e"
+ integrity sha512-x6fpZnd6AWde4U9m7xhUB44qIvGV4W6OdTAXGabYm4oZUOOGh5K1HAEoGAQn3iG4gbbPn9RSGce3VfNgGsX/Vw==
+
bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0:
version "4.11.8"
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f"