@ -0,0 +1,68 @@ | |||||
const bg = { | |||||
"column_back_button.label": "Назад", | |||||
"lightbox.close": "Затвори", | |||||
"loading_indicator.label": "Зареждане...", | |||||
"status.mention": "Споменаване", | |||||
"status.delete": "Изтриване", | |||||
"status.reply": "Отговор", | |||||
"status.reblog": "Споделяне", | |||||
"status.favourite": "Предпочитани", | |||||
"status.reblogged_by": "{name} сподели", | |||||
"status.sensitive_warning": "Деликатно съдържание", | |||||
"status.sensitive_toggle": "Покажи", | |||||
"video_player.toggle_sound": "Звук", | |||||
"account.mention": "Споменаване", | |||||
"account.edit_profile": "Редактирай профила си", | |||||
"account.unblock": "Не блокирай", | |||||
"account.unfollow": "Не следвай", | |||||
"account.block": "Блокирай", | |||||
"account.follow": "Последвай", | |||||
"account.posts": "Публикации", | |||||
"account.follows": "Следвам", | |||||
"account.followers": "Последователи", | |||||
"account.follows_you": "Твой последовател", | |||||
"account.requested": "В очакване на одобрение", | |||||
"getting_started.heading": "Първи стъпки", | |||||
"getting_started.about_addressing": "Можеш да последваш потребител, ако знаеш потребителското му име и домейна, на който се намира, като в полето за търсене ги въведеш по този начин: име@домейн", | |||||
"getting_started.about_shortcuts": "Ако с търсения потребител се намирате на един и същ домейн, достатъчно е да въведеш само името. Същото важи и за споменаване на хора в публикации.", | |||||
"getting_started.about_developer": "Можеш да потърсиш разработчика на този проект като: Gargron@mastodon.social", | |||||
"getting_started.open_source_notice": "Mastodon е софтуер с отворен код. Можеш да помогнеш или да докладваш за проблеми в Github: {github}.", | |||||
"column.home": "Начало", | |||||
"column.mentions": "Споменавания", | |||||
"column.public": "Публичен канал", | |||||
"column.notifications": "Известия", | |||||
"tabs_bar.compose": "Съставяне", | |||||
"tabs_bar.home": "Начало", | |||||
"tabs_bar.mentions": "Споменавания", | |||||
"tabs_bar.public": "Публичен канал", | |||||
"tabs_bar.notifications": "Известия", | |||||
"compose_form.placeholder": "Какво си мислиш?", | |||||
"compose_form.publish": "Раздумай", | |||||
"compose_form.sensitive": "Отбележи съдържанието като деликатно", | |||||
"compose_form.spoiler": "Скрий текста зад предупреждение", | |||||
"compose_form.private": "Отбележи като поверително", | |||||
"compose_form.privacy_disclaimer": "Поверителни публикации ще бъдат изпратени до споменатите потребители на {domains}. Доверяваш ли се на {domainsCount, plural, one {that server} other {those servers}}, че няма да издаде твоята публикация?", | |||||
"compose_form.unlisted": "Не показвай в публичния канал", | |||||
"navigation_bar.edit_profile": "Редактирай профил", | |||||
"navigation_bar.preferences": "Предпочитания", | |||||
"navigation_bar.public_timeline": "Публичен канал", | |||||
"navigation_bar.logout": "Излизане", | |||||
"reply_indicator.cancel": "Отказ", | |||||
"search.placeholder": "Търсене", | |||||
"search.account": "Акаунт", | |||||
"search.hashtag": "Хаштаг", | |||||
"upload_button.label": "Добави медия", | |||||
"upload_form.undo": "Отмяна", | |||||
"notification.follow": "{name} те последва", | |||||
"notification.favourite": "{name} хареса твоята публикация", | |||||
"notification.reblog": "{name} сподели твоята публикация", | |||||
"notification.mention": "{name} те спомена", | |||||
"notifications.column_settings.alert": "Десктоп известия", | |||||
"notifications.column_settings.show": "Покажи в колона", | |||||
"notifications.column_settings.follow": "Нови последователи:", | |||||
"notifications.column_settings.favourite": "Предпочитани:", | |||||
"notifications.column_settings.mention": "Споменавания:", | |||||
"notifications.column_settings.reblog": "Споделяния:", | |||||
}; | |||||
export default en; |
@ -1,72 +1,129 @@ | |||||
/** | |||||
* Note for Contributors: | |||||
* This file (en.jsx) serve as a template for other languages. | |||||
* To make other contributors' life easier, please REMEMBER: | |||||
* 1. to add your new string here; and | |||||
* 2. to remove old strings that are no longer needed; and | |||||
* 3. to sort the strings by the key. | |||||
* Thanks! | |||||
*/ | |||||
const en = { | const en = { | ||||
"column_back_button.label": "Back", | |||||
"lightbox.close": "Close", | |||||
"loading_indicator.label": "Loading...", | |||||
"status.mention": "Mention @{name}", | |||||
"status.delete": "Delete", | |||||
"status.reply": "Reply", | |||||
"status.reblog": "Boost", | |||||
"status.favourite": "Favourite", | |||||
"status.reblogged_by": "{name} boosted", | |||||
"status.sensitive_warning": "Sensitive content", | |||||
"status.sensitive_toggle": "Click to view", | |||||
"status.show_more": "Show more", | |||||
"status.show_less": "Show less", | |||||
"status.open": "Expand this status", | |||||
"status.report": "Report @{name}", | |||||
"video_player.toggle_sound": "Toggle sound", | |||||
"account.mention": "Mention @{name}", | |||||
"account.edit_profile": "Edit profile", | |||||
"account.unblock": "Unblock @{name}", | |||||
"account.unfollow": "Unfollow", | |||||
"account.block": "Block @{name}", | "account.block": "Block @{name}", | ||||
"account.disclaimer": "This user is from another instance. This number may be larger.", | |||||
"account.edit_profile": "Edit profile", | |||||
"account.follow": "Follow", | "account.follow": "Follow", | ||||
"account.posts": "Posts", | |||||
"account.follows": "Follows", | |||||
"account.followers": "Followers", | "account.followers": "Followers", | ||||
"account.follows_you": "Follows you", | "account.follows_you": "Follows you", | ||||
"account.follows": "Follows", | |||||
"account.mention": "Mention @{name}", | |||||
"account.mute": "Mute @{name}", | |||||
"account.posts": "Posts", | |||||
"account.report": "Report @{name}", | |||||
"account.requested": "Awaiting approval", | "account.requested": "Awaiting approval", | ||||
"getting_started.heading": "Getting started", | |||||
"getting_started.about_addressing": "You can follow people if you know their username and the domain they are on by entering an e-mail-esque address into the search form.", | |||||
"getting_started.about_shortcuts": "If the target user is on the same domain as you, just the username will work. The same rule applies to mentioning people in statuses.", | |||||
"getting_started.open_source_notice": "Mastodon is open source software. You can contribute or report issues on GitHub at {github}. {apps}.", | |||||
"column.home": "Home", | |||||
"account.unblock": "Unblock @{name}", | |||||
"account.unfollow": "Unfollow", | |||||
"account.unmute": "Unmute @{name}", | |||||
"boost_modal.combo": "You can press {combo} to skip this next time", | |||||
"column_back_button.label": "Back", | |||||
"column.blocks": "Blocked users", | |||||
"column.community": "Local timeline", | "column.community": "Local timeline", | ||||
"column.public": "Federated timeline", | |||||
"column.favourites": "Favourites", | |||||
"column.follow_requests": "Follow requests", | |||||
"column.home": "Home", | |||||
"column.notifications": "Notifications", | "column.notifications": "Notifications", | ||||
"tabs_bar.compose": "Compose", | |||||
"tabs_bar.home": "Home", | |||||
"tabs_bar.mentions": "Mentions", | |||||
"tabs_bar.public": "Federated timeline", | |||||
"tabs_bar.notifications": "Notifications", | |||||
"column.public": "Federated timeline", | |||||
"compose_form.placeholder": "What is on your mind?", | "compose_form.placeholder": "What is on your mind?", | ||||
"compose_form.privacy_disclaimer": "Your private status will be delivered to mentioned users on {domains}. Do you trust {domainsCount, plural, one {that server} other {those servers}}? Post privacy only works on Mastodon instances. If {domains} {domainsCount, plural, one {is not a Mastodon instance} other {are not Mastodon instances}}, there will be no indication that your post is private, and it may be boosted or otherwise made visible to unintended recipients.", | |||||
"compose_form.publish": "Toot", | "compose_form.publish": "Toot", | ||||
"compose_form.sensitive": "Mark media as sensitive", | "compose_form.sensitive": "Mark media as sensitive", | ||||
"compose_form.spoiler_placeholder": "Content warning", | |||||
"compose_form.spoiler": "Hide text behind warning", | "compose_form.spoiler": "Hide text behind warning", | ||||
"compose_form.private": "Mark as private", | |||||
"compose_form.privacy_disclaimer": "Your private status will be delivered to mentioned users on {domains}. Do you trust {domainsCount, plural, one {that server} other {those servers}}? Post privacy only works on Mastodon instances. If {domains} {domainsCount, plural, one {is not a Mastodon instance} other {are not Mastodon instances}}, there will be no indication that your post is private, and it may be boosted or otherwise made visible to unintended recipients.", | |||||
"compose_form.unlisted": "Do not display on public timelines", | |||||
"emoji_button.label": "Insert emoji", | |||||
"empty_column.community": "The local timeline is empty. Write something publicly to get the ball rolling!", | |||||
"empty_column.hashtag": "There is nothing in this hashtag yet.", | |||||
"empty_column.home.public_timeline": "the public timeline", | |||||
"empty_column.home": "You aren't following anyone yet. Visit {public} or use search to get started and meet other users.", | |||||
"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 instances to fill it up", | |||||
"follow_request.authorize": "Authorize", | |||||
"follow_request.reject": "Rejec", | |||||
"getting_started.apps": "Various apps are available", | |||||
"getting_started.heading": "Getting started", | |||||
"getting_started.open_source_notice": "Mastodon is open source software. You can contribute or report issues on GitHub at {github}. {apps}.", | |||||
"home.column_settings.advanced": "Advanced", | |||||
"home.column_settings.basic": "Basic", | |||||
"home.column_settings.filter_regex": "Filter out by regular expressions", | |||||
"home.column_settings.show_reblogs": "Show boosts", | |||||
"home.column_settings.show_replies": "Show replies", | |||||
"home.settings": "Column settings", | |||||
"lightbox.close": "Close", | |||||
"loading_indicator.label": "Loading...", | |||||
"media_gallery.toggle_visible": "Toggle visibility", | |||||
"missing_indicator.label": "Not found", | |||||
"navigation_bar.blocks": "Blocked users", | |||||
"navigation_bar.community_timeline": "Local timeline", | |||||
"navigation_bar.edit_profile": "Edit profile", | "navigation_bar.edit_profile": "Edit profile", | ||||
"navigation_bar.favourites": "Favourites", | |||||
"navigation_bar.follow_requests": "Follow requests", | |||||
"navigation_bar.info": "Extended information", | |||||
"navigation_bar.logout": "Logout", | |||||
"navigation_bar.preferences": "Preferences", | "navigation_bar.preferences": "Preferences", | ||||
"navigation_bar.community_timeline": "Local timeline", | |||||
"navigation_bar.public_timeline": "Federated timeline", | "navigation_bar.public_timeline": "Federated timeline", | ||||
"navigation_bar.logout": "Logout", | |||||
"reply_indicator.cancel": "Cancel", | |||||
"search.placeholder": "Search", | |||||
"search.account": "Account", | |||||
"search.hashtag": "Hashtag", | |||||
"upload_button.label": "Add media", | |||||
"upload_form.undo": "Undo", | |||||
"notification.follow": "{name} followed you", | |||||
"notification.favourite": "{name} favourited your status", | "notification.favourite": "{name} favourited your status", | ||||
"notification.follow": "{name} followed you", | |||||
"notification.reblog": "{name} boosted your status", | "notification.reblog": "{name} boosted your status", | ||||
"notification.mention": "{name} mentioned you", | |||||
"notifications.clear_confirmation": "Are you sure you want to clear all your notifications?", | |||||
"notifications.clear": "Clear notifications", | |||||
"notifications.column_settings.alert": "Desktop notifications", | "notifications.column_settings.alert": "Desktop notifications", | ||||
"notifications.column_settings.show": "Show in column", | |||||
"notifications.column_settings.follow": "New followers:", | |||||
"notifications.column_settings.favourite": "Favourites:", | "notifications.column_settings.favourite": "Favourites:", | ||||
"notifications.column_settings.follow": "New followers:", | |||||
"notifications.column_settings.mention": "Mentions:", | "notifications.column_settings.mention": "Mentions:", | ||||
"notifications.column_settings.reblog": "Boosts:", | "notifications.column_settings.reblog": "Boosts:", | ||||
"notifications.column_settings.show": "Show in column", | |||||
"notifications.column_settings.sound": "Play sound", | |||||
"notifications.settings": "Column settings", | |||||
"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": "Private", | |||||
"privacy.public.long": "Post to public timelines", | |||||
"privacy.public.short": "Public", | |||||
"privacy.unlisted.long": "Do not show in public timelines", | |||||
"privacy.unlisted.short": "Unlisted", | |||||
"reply_indicator.cancel": "Cancel", | |||||
"report.heading": "New report", | |||||
"report.placeholder": "Additional comments", | |||||
"report.submit": "Submit", | |||||
"report.target": "Reporting", | |||||
"search_results.total": "{count} {count, plural, one {result} other {results}}", | |||||
"search.placeholder": "Search", | |||||
"search.status_by": "Status by {name}", | |||||
"status.delete": "Delete", | |||||
"status.favourite": "Favourite", | |||||
"status.load_more": "Load more", | |||||
"status.media_hidden": "Media hidden", | |||||
"status.mention": "Mention @{name}", | |||||
"status.open": "Expand this status", | |||||
"status.reblog": "Boost", | |||||
"status.reblogged_by": "{name} boosted", | |||||
"status.reply": "Reply", | |||||
"status.report": "Report @{name}", | |||||
"status.sensitive_toggle": "Click to view", | |||||
"status.sensitive_warning": "Sensitive content", | |||||
"status.show_less": "Show less", | |||||
"status.show_more": "Show more", | |||||
"tabs_bar.compose": "Compose", | |||||
"tabs_bar.federated_timeline": "Federated", | |||||
"tabs_bar.home": "Home", | |||||
"tabs_bar.local_timeline": "Local", | |||||
"tabs_bar.notifications": "Notifications", | |||||
"upload_area.title": "Drag & drop to upload", | |||||
"upload_button.label": "Add media", | |||||
"upload_form.undo": "Undo", | |||||
"upload_progress.label": "Uploading...", | |||||
"video_player.toggle_sound": "Toggle sound", | |||||
"video_player.toggle_visible": "Toggle visibility", | |||||
}; | }; | ||||
export default en; | export default en; |
@ -0,0 +1,23 @@ | |||||
# frozen_string_literal: true | |||||
module Admin | |||||
class SilencesController < BaseController | |||||
before_action :set_account | |||||
def create | |||||
@account.update(silenced: true) | |||||
redirect_to admin_accounts_path | |||||
end | |||||
def destroy | |||||
@account.update(silenced: false) | |||||
redirect_to admin_accounts_path | |||||
end | |||||
private | |||||
def set_account | |||||
@account = Account.find(params[:account_id]) | |||||
end | |||||
end | |||||
end |
@ -0,0 +1,23 @@ | |||||
# frozen_string_literal: true | |||||
module Admin | |||||
class SuspensionsController < BaseController | |||||
before_action :set_account | |||||
def create | |||||
Admin::SuspensionWorker.perform_async(@account.id) | |||||
redirect_to admin_accounts_path | |||||
end | |||||
def destroy | |||||
@account.update(suspended: false) | |||||
redirect_to admin_accounts_path | |||||
end | |||||
private | |||||
def set_account | |||||
@account = Account.find(params[:account_id]) | |||||
end | |||||
end | |||||
end |
@ -0,0 +1,13 @@ | |||||
# frozen_string_literal: true | |||||
module WellKnown | |||||
class HostMetaController < ApplicationController | |||||
def show | |||||
@webfinger_template = "#{webfinger_url}?resource={uri}" | |||||
respond_to do |format| | |||||
format.xml { render content_type: 'application/xrd+xml' } | |||||
end | |||||
end | |||||
end | |||||
end |
@ -0,0 +1,43 @@ | |||||
# frozen_string_literal: true | |||||
module WellKnown | |||||
class WebfingerController < ApplicationController | |||||
def show | |||||
@account = Account.find_local!(username_from_resource) | |||||
@canonical_account_uri = @account.to_webfinger_s | |||||
@magic_key = pem_to_magic_key(@account.keypair.public_key) | |||||
respond_to do |format| | |||||
format.xml { render content_type: 'application/xrd+xml' } | |||||
format.json { render content_type: 'application/jrd+json' } | |||||
end | |||||
rescue ActiveRecord::RecordNotFound | |||||
head 404 | |||||
end | |||||
private | |||||
def username_from_resource | |||||
WebfingerResource.new(resource_param).username | |||||
end | |||||
def pem_to_magic_key(public_key) | |||||
modulus, exponent = [public_key.n, public_key.e].map do |component| | |||||
result = [] | |||||
until component.zero? | |||||
result << [component % 256].pack('C') | |||||
component >>= 8 | |||||
end | |||||
result.reverse.join | |||||
end | |||||
(['RSA'] + [modulus, exponent].map { |n| Base64.urlsafe_encode64(n) }).join('.') | |||||
end | |||||
def resource_param | |||||
params.require(:resource) | |||||
end | |||||
end | |||||
end |
@ -1,55 +0,0 @@ | |||||
# frozen_string_literal: true | |||||
class XrdController < ApplicationController | |||||
before_action :set_default_format_xml, only: :host_meta | |||||
def host_meta | |||||
@webfinger_template = "#{webfinger_url}?resource={uri}" | |||||
respond_to do |format| | |||||
format.xml { render content_type: 'application/xrd+xml' } | |||||
end | |||||
end | |||||
def webfinger | |||||
@account = Account.find_local!(username_from_resource) | |||||
@canonical_account_uri = @account.to_webfinger_s | |||||
@magic_key = pem_to_magic_key(@account.keypair.public_key) | |||||
respond_to do |format| | |||||
format.xml { render content_type: 'application/xrd+xml' } | |||||
format.json { render content_type: 'application/jrd+json' } | |||||
end | |||||
rescue ActiveRecord::RecordNotFound | |||||
head 404 | |||||
end | |||||
private | |||||
def set_default_format_xml | |||||
request.format = 'xml' if request.headers['HTTP_ACCEPT'].nil? && params[:format].nil? | |||||
end | |||||
def username_from_resource | |||||
WebfingerResource.new(resource_param).username | |||||
end | |||||
def pem_to_magic_key(public_key) | |||||
modulus, exponent = [public_key.n, public_key.e].map do |component| | |||||
result = [] | |||||
until component.zero? | |||||
result << [component % 256].pack('C') | |||||
component >>= 8 | |||||
end | |||||
result.reverse.join | |||||
end | |||||
(['RSA'] + [modulus, exponent].map { |n| Base64.urlsafe_encode64(n) }).join('.') | |||||
end | |||||
def resource_param | |||||
params.require(:resource) | |||||
end | |||||
end |
@ -0,0 +1,36 @@ | |||||
# frozen_string_literal: true | |||||
class AccountFilter | |||||
attr_reader :params | |||||
def initialize(params) | |||||
@params = params | |||||
end | |||||
def results | |||||
scope = Account.alphabetic | |||||
params.each do |key, value| | |||||
scope = scope.merge scope_for(key, value) | |||||
end | |||||
scope | |||||
end | |||||
def scope_for(key, value) | |||||
case key | |||||
when /local/ | |||||
Account.local | |||||
when /remote/ | |||||
Account.remote | |||||
when /by_domain/ | |||||
Account.where(domain: value) | |||||
when /silenced/ | |||||
Account.silenced | |||||
when /recent/ | |||||
Account.recent | |||||
when /suspended/ | |||||
Account.suspended | |||||
else | |||||
raise "Unknown filter: #{key}" | |||||
end | |||||
end | |||||
end |
@ -0,0 +1,169 @@ | |||||
--- | |||||
bg: | |||||
about: | |||||
about_mastodon: Mastodon е <em>безплатен</em> сървър с <em>отворен код</em> за социални мрежи. Като <em>децентрализирана</em> алтернатива на комерсиалните платформи, той позволява избягването на риска от монополизация на твоята комуникация от единични компании. Изберете си сървър, на който се доверявате, и ще можете да контактувате с всички останали. Всеки може да пусне Mastodon и лесно да вземе участие в <em>социалната мрежа</em>. | |||||
about_this: За тази инстанция | |||||
apps: Приложения | |||||
business_email: 'Служебен e-mail:' | |||||
closed_registrations: В момента регистрациите за тази инстанция са затворени. | |||||
contact: За контакти | |||||
description_headline: Какво е %{domain}? | |||||
domain_count_after: други инстанции | |||||
domain_count_before: Свързани към | |||||
features: | |||||
api: Отворено API за приложения и услуги | |||||
blocks: Богат на инструменти за блокиране и заглушаване | |||||
characters: Публикации от 500 символа | |||||
chronology: Публикациите се показват хронологично | |||||
ethics: 'Етичен дизайн: без реклами и проследяване' | |||||
gifv: GIFV комплекти и кратки видео клипове | |||||
privacy: Настройване на поверителността за всяка публикация | |||||
public: Публични канали | |||||
features_headline: Какво откроява Mastodon | |||||
get_started: Първи стъпки | |||||
links: Връзки | |||||
other_instances: Други инстанции | |||||
source_code: Програмен код | |||||
status_count_after: публикации | |||||
status_count_before: Написали | |||||
terms: Условия | |||||
user_count_after: потребители | |||||
user_count_before: Дом на | |||||
accounts: | |||||
follow: Последвай | |||||
followers: Последователи | |||||
following: Следва | |||||
nothing_here: Тук няма никого! | |||||
people_followed_by: Хора, които %{name} следва | |||||
people_who_follow: Хора, които следват %{name} | |||||
posts: Публикации | |||||
remote_follow: Последвай | |||||
unfollow: Не следвай | |||||
application_mailer: | |||||
settings: 'Промяна на предпочитанията за e-mail: %{link}' | |||||
signature: Mastodon известия от %{instance} | |||||
view: 'Преглед:' | |||||
applications: | |||||
invalid_url: Предоставеният URL е невалиден | |||||
auth: | |||||
change_password: Идентификационни данни | |||||
didnt_get_confirmation: Не получих инструкции за потвърждение | |||||
forgot_password: Забравих си паролата | |||||
login: Влизане | |||||
logout: Излизане | |||||
register: Регистрация | |||||
resend_confirmation: Изпрати отново инструкции за потвърждение | |||||
reset_password: Подновяване на паролата | |||||
set_new_password: Задай нова парола | |||||
authorize_follow: | |||||
error: Възникна грешка в откриването на потребителя | |||||
follow: Последвай | |||||
prompt_html: '(<strong>%{self}</strong>), молбата ти беше изпратена до:' | |||||
title: Последвай %{acct} | |||||
datetime: | |||||
distance_in_words: | |||||
about_x_hours: "%{count} ч." | |||||
about_x_months: "%{count} м." | |||||
about_x_years: "%{count} г." | |||||
almost_x_years: "%{count} г." | |||||
half_a_minute: Току-що | |||||
less_than_x_minutes: "%{count} мин." | |||||
less_than_x_seconds: Току-що | |||||
over_x_years: "%{count} г." | |||||
x_days: "%{count} дни" | |||||
x_minutes: "%{count} мин." | |||||
x_months: "%{count} м." | |||||
x_seconds: "%{count} сек." | |||||
exports: | |||||
blocks: Вашите блокирания | |||||
csv: CSV | |||||
follows: Вашите следвания | |||||
storage: Съхранение на мултимедия | |||||
generic: | |||||
changes_saved_msg: Успешно запазване на промените! | |||||
powered_by: поддържано от %{link} | |||||
save_changes: Запази промените | |||||
validation_errors: | |||||
one: Нещо все още не е наред! Моля, прегледай грешката по-долу | |||||
other: Нещо все още не е наред! Моля, прегледай грешките по-долу | |||||
imports: | |||||
preface: Можеш да импортираш някои данни, като например всички хора, които следваш или блокираш в акаунта си на тази инстанция, от файлове, създадени чрез експорт в друга инстанция. | |||||
success: Твоите данни бяха успешно качени и ще бъдат обработени впоследствие. | |||||
types: | |||||
blocking: Списък на блокираните | |||||
following: Списък на последователите | |||||
upload: Качване | |||||
landing_strip_html: <strong>%{name}</strong> е потребител от <strong>%{domain}</strong>. Можеш да ги следваш, или да контактуваш с тях, ако имаш акаунт където и да е из федерираната вселена на Mastodon. Ако нямаш акаунт, можеш да си <a href="%{sign_up_path}">създадеш ето тук</a>. | |||||
notification_mailer: | |||||
digest: | |||||
body: 'Ето кратко резюме на нещата, които се случиха от последното ти посещение в %{instance} на %{since}:' | |||||
mention: "%{name} те спомена в:" | |||||
new_followers_summary: | |||||
one: Имаш един нов последовател! Ура! | |||||
other: Имаш %{count} нови последователи! Изумително! | |||||
subject: | |||||
one: "1 ново известие от последното ти посещение \U0001F418" | |||||
other: "%{count} нови известия от последното ти посещение \U0001F418" | |||||
favourite: | |||||
body: 'Публикацията ти беше харесана от %{name}:' | |||||
subject: "%{name} хареса твоята публикация" | |||||
follow: | |||||
body: "%{name} те последва!" | |||||
subject: "%{name} те последва" | |||||
follow_request: | |||||
body: "%{name} помоли за разрешение да те последва" | |||||
subject: 'Чакащ последовател: %{name}' | |||||
mention: | |||||
body: '%{name} те спомена в:' | |||||
subject: '%{name} те спомена' | |||||
reblog: | |||||
body: 'Твоята публикация беше споделена от %{name}:' | |||||
subject: "%{name} сподели публикацията ти" | |||||
pagination: | |||||
next: Напред | |||||
prev: Назад | |||||
remote_follow: | |||||
acct: Въведи потребителско_име@домейн, от които искаш да следваш | |||||
missing_resource: Неуспешно търсене на нужния URL за пренасочване за твоя акаунт | |||||
proceed: Започни следване | |||||
prompt: 'Ще последваш:' | |||||
settings: | |||||
authorized_apps: Упълномощени приложения | |||||
back: Обратно към Mastodon | |||||
edit_profile: Редактирай профила си | |||||
export: Експортиране на данни | |||||
import: Импортиране | |||||
preferences: Предпочитания | |||||
settings: Настройки | |||||
two_factor_auth: Двустепенно удостоверяване | |||||
statuses: | |||||
open_in_web: Отвори в уеб | |||||
over_character_limit: прехвърлен лимит от %{max} символа | |||||
show_more: Покажи повече | |||||
visibilities: | |||||
private: Покажи само на последователите си | |||||
public: Публично | |||||
unlisted: Публично, но не показвай в публичния канал | |||||
stream_entries: | |||||
click_to_show: Покажи | |||||
reblogged: споделено | |||||
sensitive_content: Деликатно съдържание | |||||
time: | |||||
formats: | |||||
default: "%d %b, %Y, %H:%M" | |||||
two_factor_auth: | |||||
description_html: При активация на <strong>двустепенно удостоверяване</strong>, за да влезеш в приложението, ще трябва да използваш телефона си. През него ще се генерира код, който да въвеждаш при влизане. | |||||
disable: Деактивирай | |||||
enable: Активирай | |||||
instructions_html: "<strong>Сканирай този QR код с Google Authenticator или подобно приложение от своя телефон</strong>. Oтсега нататък, това приложение ще генерира код, който ще трябва да въвеждаш при всяко влизане." | |||||
plaintext_secret_html: "Тайна в обикновен текст: <samp>%{secret}</samp>" | |||||
warning: Ако не можеш да настроиш приложението за удостверяване сега, избери "Деактивирай". В противен случай, няма да можеш да влезеш в акаунта си. | |||||
users: | |||||
invalid_email: E-mail адресът е невалиден | |||||
invalid_otp_token: Невалиден код | |||||
will_paginate: | |||||
page_gap: "…" | |||||
media_attachments: | |||||
validations: | |||||
too_many: Не мога да прикача повече от 4 файла | |||||
images_and_video: Не мога да прикача видеоклип към публикация, която вече съдържа изображения |
@ -0,0 +1,61 @@ | |||||
--- | |||||
bg: | |||||
devise: | |||||
confirmations: | |||||
confirmed: Твоят профил беше успешно потвърден. Влизането в профила е успешно. | |||||
send_instructions: Ще получиш писмо с инструкции как да потвърдиш своя профил до няколко минути. | |||||
send_paranoid_instructions: Ако твоят имейл адрес съществува в базата ни, ще получиш там инструкции как да потвърдиш своя профил. | |||||
failure: | |||||
already_authenticated: Вече си вътре в профила си. | |||||
inactive: Профилът ти все още не е активиран. | |||||
invalid: Невалиден имейл адрес или парола. | |||||
last_attempt: Разполагаш с още един опит преди профилът ти да бъде заключен. | |||||
locked: Профилът ти е заключен. | |||||
not_found_in_database: "Невалидни стойности за %{authentication_keys} или парола." | |||||
timeout: Сесията ти изтече, моля влез отново, за да продължиш. | |||||
unauthenticated: Преди да продължиш, трябва да влезеш в профила си или да се регистрираш. | |||||
unconfirmed: Преди да продължиш, трябва да потвърдиш регистрацията си. | |||||
mailer: | |||||
confirmation_instructions: | |||||
subject: 'Mastodon: Инструкции за потвърждаване' | |||||
password_change: | |||||
subject: 'Mastodon: Паролата е променена' | |||||
reset_password_instructions: | |||||
subject: 'Инструкции за смяна на паролата' | |||||
unlock_instructions: | |||||
subject: 'Инструкции за отключване' | |||||
omniauth_callbacks: | |||||
failure: "Не успяхме да те упълномощим чрез %{kind}, защото \"%{reason}\"." | |||||
success: "Успешно упълномощаване чрез %{kind} профил." | |||||
passwords: | |||||
no_token: Може да достъпваш тази страница само от имейл за промяна на паролата. Ако тази страница е отворена от такъв имейл, увери се, че използваш целия URL-адрес, който сме ти изпратили. | |||||
send_instructions: Ще получиш писмо с инструкции как да промениш паролата си до няколко минути. | |||||
send_paranoid_instructions: Ако твоят имейл адрес съществува в базата ни, ще получиш там инструкции за промяна на своята парола. | |||||
updated: Паролата ти беше променена успешно. Влизането в профила е успешно. | |||||
updated_not_active: Паролата ти беше променена успешно. | |||||
registrations: | |||||
destroyed: Довиждане! Твоят профил беше успешно изтрит. Надяваме се скоро да те видим отново. | |||||
signed_up: Привет! Регистрирацията ти е успешна. | |||||
signed_up_but_inactive: Регистрирацията ти е успешна. Въпреки това, не можеш да влезеш в профила си, защото той все още не е потвърден. | |||||
signed_up_but_locked: Регистрирацията ти е успешна. Въпреки това, не можеш да влезеш в профила си, защото той е заключен. | |||||
signed_up_but_unconfirmed: Писмо с връзка за потвърждаване на профила ти беше изпратено на твоя имейл адрес. Моля, отвори връзката, за да активираш своя профил. | |||||
update_needs_confirmation: Профилът ти е успешно променен, но ние трябва да проверим твоя нов имейл адрес. Моля, провери пощата си и отвори връзката за потвърждаване на новия адрес. | |||||
updated: Профилът ти е успешно променен. | |||||
sessions: | |||||
already_signed_out: Успешно излизане от профила. | |||||
signed_in: Успешно влизане. | |||||
signed_out: Успешно излизане. | |||||
unlocks: | |||||
send_instructions: Ще получиш писмо с инструкции как да отключиш профила си до няколко минути. | |||||
send_paranoid_instructions: Ако твоят профил съществува в базата ни, на своя имейл адрес ще получиш инструкции за отключването му до няколко минути. | |||||
unlocked: Твоят профил беше отключен успешно. За да продължиш, влез в него. | |||||
errors: | |||||
messages: | |||||
already_confirmed: е вече потвърден, моля опитай да влезеш в профила си с него | |||||
confirmation_period_expired: "трябва да се потвърди в рамките на %{period}, моля направи нова заявка за потвърждение" | |||||
expired: е изтекъл, моля заяви нов | |||||
not_found: не е намерен | |||||
not_locked: не бе заключен | |||||
not_saved: | |||||
one: "Една грешка попречи този %{resource} да бъде записан:" | |||||
other: "%{count} грешки попречиха този %{resource} да бъде записан:" |
@ -0,0 +1,113 @@ | |||||
--- | |||||
bg: | |||||
activerecord: | |||||
attributes: | |||||
doorkeeper/application: | |||||
name: Име | |||||
redirect_uri: URI за пренасочване | |||||
errors: | |||||
models: | |||||
doorkeeper/application: | |||||
attributes: | |||||
redirect_uri: | |||||
fragment_present: не може да съдържа фрагмент. | |||||
invalid_uri: трябва да е валидно URI. | |||||
relative_uri: трябва да е абсолютно URI. | |||||
secured_uri: трябва да е HTTPS/SSL URI. | |||||
doorkeeper: | |||||
applications: | |||||
buttons: | |||||
authorize: Упълномощаване | |||||
cancel: Отказ | |||||
destroy: Унищожаване | |||||
edit: Редакция | |||||
submit: Изпращане | |||||
confirmations: | |||||
destroy: Потвърждаваш ли изтриването? | |||||
edit: | |||||
title: Редактиране на приложението | |||||
form: | |||||
error: О, не! Провери формата за възможни грешки | |||||
help: | |||||
native_redirect_uri: Изполвай %{native_redirect_uri} за локални тестове | |||||
redirect_uri: Използвай един ред за всяко URI | |||||
scopes: Разделяй диапазоните с интервал. Остави празно, за да използваш диапазона по подразбиране. | |||||
index: | |||||
callback_url: URL за обратно повикване | |||||
name: Име | |||||
new: Ново приложение | |||||
title: Твоите приложения | |||||
new: | |||||
title: Ново приложение | |||||
show: | |||||
actions: Действия | |||||
application_id: Идентификатор на приложението | |||||
callback_urls: URL-и за обратно повикване | |||||
scopes: Диапазони | |||||
secret: Тайна | |||||
title: 'Приложение: %{name}' | |||||
authorizations: | |||||
buttons: | |||||
authorize: Упълномощаване | |||||
deny: Отказ | |||||
error: | |||||
title: Възникна грешка | |||||
new: | |||||
able_to: Ще е възможно | |||||
prompt: Приложението %{client_name} заявява достъп до твоя акаунт | |||||
title: Изисква се упълномощаване | |||||
show: | |||||
title: Код за упълномощаване | |||||
authorized_applications: | |||||
buttons: | |||||
revoke: Отмяна | |||||
confirmations: | |||||
revoke: Потвърждаваш ли отмяната? | |||||
index: | |||||
application: Приложение | |||||
created_at: Създадено на | |||||
date_format: "%Y-%m-%d %H:%M:%S" | |||||
scopes: Диапазони | |||||
title: Твоите упълномощени приложения | |||||
errors: | |||||
messages: | |||||
access_denied: Заявката беше отказана от собственика на ресурса или от сървъра за упълномощаване. | |||||
credential_flow_not_configured: Resource Owner Password Credentials предизвика грешка, заради това, че настройките за Doorkeeper.configure.resource_owner_from_credentials липсват. | |||||
invalid_client: Удостоверяването на клиента предизвика грешка, поради непознат клиент, липсващо клиентско удостоверяване, или заради това, че методът на удостоверяване не се поддържа. | |||||
invalid_grant: Предоставеното удостоверение за достъп е невалидно, изтекло, отхвърлено, не съвпада с пренасочващото URI, използвано в заявката за удостоверение, или е бил издадено от друг клиент. | |||||
invalid_redirect_uri: Наличното пренасочващо URI е невалидно. | |||||
invalid_request: Заявката е с липсващ задължителен параметър, включва стойност на параметъра, която не се поддържа, или е изкривена по друг начин. | |||||
invalid_resource_owner: Предоставените идентификационни данни на притежателя на ресурса са невалидни, или притежателят не може да бъде намерен. | |||||
invalid_scope: Заявеният диапазон е невалиден, неизвестен или изкривен. | |||||
invalid_token: | |||||
expired: Маркерът за достъп изтече | |||||
revoked: Маркерът за достъп беше отхвърлен | |||||
unknown: Маркерът за достъп е невалиден | |||||
resource_owner_authenticator_not_configured: Намирането на Resource Owner се провали поради липса на конфигурация на Doorkeeper.configure.resource_owner_authenticator. | |||||
server_error: Сървърът за удостоверяване попадна на неочаквано условие, което предотврати изпълнението на заявката. | |||||
temporarily_unavailable: Сървърът за удостоверяване не може да се справи със заявката в момента поради временно претоварване или профилактика на сървъра. | |||||
unauthorized_client: Клиентът не е удостоверен да изпълни заявката по този начин. | |||||
unsupported_grant_type: Типът на удостоврението за достъп не се поддържа от сървъра за удостоверяване. | |||||
unsupported_response_type: Удостоверяващият сървър не поддържа този тип отговор. | |||||
flash: | |||||
applications: | |||||
create: | |||||
notice: Приложението е създадено. | |||||
destroy: | |||||
notice: Приложението е изтрито. | |||||
update: | |||||
notice: Приложението е обновено. | |||||
authorized_applications: | |||||
destroy: | |||||
notice: Приложението е отказано. | |||||
layouts: | |||||
admin: | |||||
nav: | |||||
applications: Приложения | |||||
oauth2_provider: OAuth2 доставчик | |||||
application: | |||||
title: Нужно е упълномощаване по OAuth | |||||
scopes: | |||||
follow: следването, блокирането, деблокирането и отмяната на следването на акаунтите | |||||
read: четенето на данните от твоя акаунт | |||||
write: публикуването от твое име |
@ -0,0 +1,46 @@ | |||||
--- | |||||
bg: | |||||
simple_form: | |||||
hints: | |||||
defaults: | |||||
avatar: PNG, GIF или JPG. До 2MB. Ще бъде смалена до 120x120 пиксела | |||||
display_name: До 30 символа | |||||
header: PNG, GIF или JPG. До 2MB. Ще бъде смалена до 700x335 пиксела | |||||
locked: Изисква ръчно одобрение на последователите. По подразбиране, публикациите са достъпни само до последователи. | |||||
note: До 160 символа | |||||
imports: | |||||
data: CSV файл, експортиран от друга инстанция на Mastodon | |||||
labels: | |||||
defaults: | |||||
avatar: Аватар | |||||
confirm_new_password: Потвърди новата парола | |||||
confirm_password: Потвърди паролата | |||||
current_password: Текуща парола | |||||
data: Данни | |||||
display_name: Показвано име | |||||
email: E-mail адрес | |||||
header: Заглавен ред | |||||
locale: Език | |||||
locked: Направи акаунта поверителен | |||||
new_password: Нова парола | |||||
note: Био | |||||
otp_attempt: Двустепенен код | |||||
password: Парола | |||||
setting_default_privacy: Поверителност на публикациите | |||||
type: Тип на импортиране | |||||
username: Потребителско име | |||||
interactions: | |||||
must_be_follower: Блокирай известия от не-последователи | |||||
must_be_following: Блокирай известия от хора, които не следваш | |||||
notification_emails: | |||||
digest: Изпращай извлечения на съобщенията | |||||
favourite: Изпращай e-mail, когато някой хареса твоя публикация | |||||
follow: Изпращай e-mail, когато някой те последва | |||||
follow_request: Изпращай e-mail, когато някой пожелае да те последва | |||||
mention: Изпращай e-mail, когато някой те спомене | |||||
reblog: Изпращай e-mail, когато някой сподели твоя публикация | |||||
'no': 'Не' | |||||
required: | |||||
mark: "*" | |||||
text: задължително | |||||
'yes': 'Да' |
@ -0,0 +1,24 @@ | |||||
require 'rails_helper' | |||||
describe Admin::SilencesController do | |||||
let(:account) { Fabricate(:account) } | |||||
before do | |||||
sign_in Fabricate(:user, admin: true), scope: :user | |||||
end | |||||
describe 'POST #create' do | |||||
it 'redirects to admin accounts page' do | |||||
post :create, params: { account_id: account.id } | |||||
expect(response).to redirect_to(admin_accounts_path) | |||||
end | |||||
end | |||||
describe 'DELETE #destroy' do | |||||
it 'redirects to admin accounts page' do | |||||
delete :destroy, params: { account_id: account.id } | |||||
expect(response).to redirect_to(admin_accounts_path) | |||||
end | |||||
end | |||||
end |
@ -0,0 +1,24 @@ | |||||
require 'rails_helper' | |||||
describe Admin::SuspensionsController do | |||||
let(:account) { Fabricate(:account) } | |||||
before do | |||||
sign_in Fabricate(:user, admin: true), scope: :user | |||||
end | |||||
describe 'POST #create' do | |||||
it 'redirects to admin accounts page' do | |||||
post :create, params: { account_id: account.id } | |||||
expect(response).to redirect_to(admin_accounts_path) | |||||
end | |||||
end | |||||
describe 'DELETE #destroy' do | |||||
it 'redirects to admin accounts page' do | |||||
delete :destroy, params: { account_id: account.id } | |||||
expect(response).to redirect_to(admin_accounts_path) | |||||
end | |||||
end | |||||
end |
@ -0,0 +1,13 @@ | |||||
require 'rails_helper' | |||||
describe WellKnown::HostMetaController, type: :controller do | |||||
render_views | |||||
describe 'GET #show' do | |||||
it 'returns http success' do | |||||
get :show, format: :xml | |||||
expect(response).to have_http_status(:success) | |||||
end | |||||
end | |||||
end |
@ -0,0 +1,21 @@ | |||||
require 'rails_helper' | |||||
describe WellKnown::WebfingerController, type: :controller do | |||||
render_views | |||||
describe 'GET #show' do | |||||
let(:alice) { Fabricate(:account, username: 'alice') } | |||||
it 'returns http success when account can be found' do | |||||
get :show, params: { resource: alice.to_webfinger_s }, format: :json | |||||
expect(response).to have_http_status(:success) | |||||
end | |||||
it 'returns http not found when account cannot be found' do | |||||
get :show, params: { resource: 'acct:not@existing.com' }, format: :json | |||||
expect(response).to have_http_status(:not_found) | |||||
end | |||||
end | |||||
end |
@ -1,26 +0,0 @@ | |||||
require 'rails_helper' | |||||
RSpec.describe XrdController, type: :controller do | |||||
render_views | |||||
describe 'GET #host_meta' do | |||||
it 'returns http success' do | |||||
get :host_meta | |||||
expect(response).to have_http_status(:success) | |||||
end | |||||
end | |||||
describe 'GET #webfinger' do | |||||
let(:alice) { Fabricate(:account, username: 'alice') } | |||||
it 'returns http success when account can be found' do | |||||
get :webfinger, params: { resource: alice.to_webfinger_s }, format: :json | |||||
expect(response).to have_http_status(:success) | |||||
end | |||||
it 'returns http not found when account cannot be found' do | |||||
get :webfinger, params: { resource: 'acct:not@existing.com' }, format: :json | |||||
expect(response).to have_http_status(:not_found) | |||||
end | |||||
end | |||||
end |
@ -0,0 +1,31 @@ | |||||
require 'rails_helper' | |||||
describe AccountFilter do | |||||
describe 'with empty params' do | |||||
it 'defaults to alphabetic account list' do | |||||
filter = AccountFilter.new({}) | |||||
expect(filter.results).to eq Account.alphabetic | |||||
end | |||||
end | |||||
describe 'with invalid params' do | |||||
it 'raises with key error' do | |||||
filter = AccountFilter.new(wrong: true) | |||||
expect { filter.results }.to raise_error(/wrong/) | |||||
end | |||||
end | |||||
describe 'with valid params' do | |||||
it 'combines filters on Account' do | |||||
filter = AccountFilter.new(by_domain: 'test.com', silenced: true) | |||||
allow(Account).to receive(:where).and_return(Account.none) | |||||
allow(Account).to receive(:silenced).and_return(Account.none) | |||||
filter.results | |||||
expect(Account).to have_received(:where).with(domain: 'test.com') | |||||
expect(Account).to have_received(:silenced) | |||||
end | |||||
end | |||||
end |
@ -0,0 +1,12 @@ | |||||
require "rails_helper" | |||||
describe "The host_meta route" do | |||||
describe "requested without accepts headers" do | |||||
it "returns an xml response" do | |||||
get host_meta_url | |||||
expect(response).to have_http_status(:success) | |||||
expect(response.content_type).to eq "application/xrd+xml" | |||||
end | |||||
end | |||||
end |
@ -0,0 +1,15 @@ | |||||
require 'rails_helper' | |||||
describe 'the host-meta route' do | |||||
it 'routes to correct place with xml format' do | |||||
expect(get('/.well-known/host-meta')). | |||||
to route_to('well_known/host_meta#show', format: 'xml') | |||||
end | |||||
end | |||||
describe 'the webfinger route' do | |||||
it 'routes to correct place with json format' do | |||||
expect(get('/.well-known/webfinger')). | |||||
to route_to('well_known/webfinger#show', format: 'json') | |||||
end | |||||
end |