Merge branch 'master' into master
This commit is contained in:
commit
1a12fd14d4
|
@ -52,8 +52,8 @@ import no from 'react-intl/locale-data/no';
|
|||
import ru from 'react-intl/locale-data/ru';
|
||||
import uk from 'react-intl/locale-data/uk';
|
||||
import zh from 'react-intl/locale-data/zh';
|
||||
import bg from 'react-intl/locale-data/bg';
|
||||
import { localeData as zh_hk } from '../locales/zh-hk';
|
||||
|
||||
import getMessagesForLocale from '../locales';
|
||||
import { hydrateStore } from '../actions/store';
|
||||
import createStream from '../stream';
|
||||
|
@ -66,7 +66,6 @@ const browserHistory = useRouterHistory(createBrowserHistory)({
|
|||
basename: '/web'
|
||||
});
|
||||
|
||||
|
||||
addLocaleData([
|
||||
...en,
|
||||
...de,
|
||||
|
@ -82,9 +81,9 @@ addLocaleData([
|
|||
...uk,
|
||||
...zh,
|
||||
...zh_hk,
|
||||
...bg,
|
||||
]);
|
||||
|
||||
|
||||
const Mastodon = React.createClass({
|
||||
|
||||
propTypes: {
|
||||
|
|
|
@ -14,7 +14,7 @@ import ColumnBackButtonSlim from '../../components/column_back_button_slim';
|
|||
import createStream from '../../stream';
|
||||
|
||||
const messages = defineMessages({
|
||||
title: { id: 'column.community', defaultMessage: 'Local' }
|
||||
title: { id: 'column.community', defaultMessage: 'Local timeline' }
|
||||
});
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
|
|
|
@ -19,7 +19,7 @@ import TextIconButton from './text_icon_button';
|
|||
const messages = defineMessages({
|
||||
placeholder: { id: 'compose_form.placeholder', defaultMessage: 'What is on your mind?' },
|
||||
spoiler_placeholder: { id: 'compose_form.spoiler_placeholder', defaultMessage: 'Content warning' },
|
||||
publish: { id: 'compose_form.publish', defaultMessage: 'Publish' }
|
||||
publish: { id: 'compose_form.publish', defaultMessage: 'Toot' }
|
||||
});
|
||||
|
||||
const ComposeForm = React.createClass({
|
||||
|
|
|
@ -12,7 +12,7 @@ import SearchResultsContainer from './containers/search_results_container';
|
|||
|
||||
const messages = defineMessages({
|
||||
start: { id: 'getting_started.heading', defaultMessage: 'Getting started' },
|
||||
public: { id: 'navigation_bar.public_timeline', defaultMessage: 'Whole Known Network' },
|
||||
public: { id: 'navigation_bar.public_timeline', defaultMessage: 'Federated timeline' },
|
||||
community: { id: 'navigation_bar.community_timeline', defaultMessage: 'Local timeline' },
|
||||
preferences: { id: 'navigation_bar.preferences', defaultMessage: 'Preferences' },
|
||||
logout: { id: 'navigation_bar.logout', defaultMessage: 'Logout' }
|
||||
|
|
|
@ -7,11 +7,11 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
|
|||
|
||||
const messages = defineMessages({
|
||||
heading: { id: 'getting_started.heading', defaultMessage: 'Getting started' },
|
||||
public_timeline: { id: 'navigation_bar.public_timeline', defaultMessage: 'Whole Known Network' },
|
||||
public_timeline: { id: 'navigation_bar.public_timeline', defaultMessage: 'Federated timeline' },
|
||||
community_timeline: { id: 'navigation_bar.community_timeline', defaultMessage: 'Local timeline' },
|
||||
preferences: { id: 'navigation_bar.preferences', defaultMessage: 'Preferences' },
|
||||
follow_requests: { id: 'navigation_bar.follow_requests', defaultMessage: 'Follow requests' },
|
||||
sign_out: { id: 'navigation_bar.logout', defaultMessage: 'Sign out' },
|
||||
sign_out: { id: 'navigation_bar.logout', defaultMessage: 'Logout' },
|
||||
favourites: { id: 'navigation_bar.favourites', defaultMessage: 'Favourites' },
|
||||
blocks: { id: 'navigation_bar.blocks', defaultMessage: 'Blocked users' },
|
||||
info: { id: 'navigation_bar.info', defaultMessage: 'Extended information' }
|
||||
|
|
|
@ -14,7 +14,7 @@ import ColumnBackButtonSlim from '../../components/column_back_button_slim';
|
|||
import createStream from '../../stream';
|
||||
|
||||
const messages = defineMessages({
|
||||
title: { id: 'column.public', defaultMessage: 'Whole Known Network' }
|
||||
title: { id: 'column.public', defaultMessage: 'Federated timeline' }
|
||||
});
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
|
|
68
app/assets/javascripts/components/locales/bg.jsx
Normal file
68
app/assets/javascripts/components/locales/bg.jsx
Normal file
|
@ -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 = {
|
||||
"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.disclaimer": "This user is from another instance. This number may be larger.",
|
||||
"account.edit_profile": "Edit profile",
|
||||
"account.follow": "Follow",
|
||||
"account.posts": "Posts",
|
||||
"account.follows": "Follows",
|
||||
"account.followers": "Followers",
|
||||
"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",
|
||||
"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.public": "Federated timeline",
|
||||
"column.favourites": "Favourites",
|
||||
"column.follow_requests": "Follow requests",
|
||||
"column.home": "Home",
|
||||
"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.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.sensitive": "Mark media as sensitive",
|
||||
"compose_form.spoiler_placeholder": "Content 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",
|
||||
"navigation_bar.edit_profile": "Edit profile",
|
||||
"navigation_bar.preferences": "Preferences",
|
||||
"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.public_timeline": "Federated timeline",
|
||||
"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",
|
||||
"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",
|
||||
"navigation_bar.preferences": "Preferences",
|
||||
"navigation_bar.public_timeline": "Federated timeline",
|
||||
"notification.favourite": "{name} favourited your status",
|
||||
"notification.follow": "{name} followed you",
|
||||
"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.show": "Show in column",
|
||||
"notifications.column_settings.follow": "New followers:",
|
||||
"notifications.column_settings.favourite": "Favourites:",
|
||||
"notifications.column_settings.follow": "New followers:",
|
||||
"notifications.column_settings.mention": "Mentions:",
|
||||
"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;
|
||||
|
|
|
@ -11,7 +11,7 @@ import eo from './eo';
|
|||
import ru from './ru';
|
||||
import ja from './ja';
|
||||
import zh_hk from './zh-hk';
|
||||
|
||||
import bg from './bg';
|
||||
|
||||
const locales = {
|
||||
en,
|
||||
|
@ -27,6 +27,7 @@ const locales = {
|
|||
ru,
|
||||
ja,
|
||||
'zh-HK': zh_hk,
|
||||
bg,
|
||||
};
|
||||
|
||||
export default function getMessagesForLocale (locale) {
|
||||
|
|
|
@ -39,8 +39,8 @@ const ja = {
|
|||
"tabs_bar.compose": "投稿",
|
||||
"tabs_bar.home": "ホーム",
|
||||
"tabs_bar.mentions": "返信",
|
||||
"tabs_bar.local_timeline": "ローカルTL",
|
||||
"tabs_bar.federated_timeline": "連合TL",
|
||||
"tabs_bar.local_timeline": "ローカル",
|
||||
"tabs_bar.federated_timeline": "連合",
|
||||
"tabs_bar.notifications": "通知",
|
||||
"compose_form.placeholder": "今なにしてる?",
|
||||
"compose_form.publish": "トゥート",
|
||||
|
|
|
@ -14,59 +14,115 @@ const pt = {
|
|||
"status.show_less": "Mostrar menos",
|
||||
"status.open": "Expandir",
|
||||
"status.report": "Reportar @{name}",
|
||||
"status.load_more": "Carregar mais",
|
||||
"status.media_hidden": "Media escondida",
|
||||
"video_player.toggle_sound": "Ligar/Desligar som",
|
||||
"video_player.toggle_visible": "Ligar/Desligar vídeo",
|
||||
"account.mention": "Mencionar @{name}",
|
||||
"account.edit_profile": "Editar perfil",
|
||||
"account.unblock": "Não bloquear @{name}",
|
||||
"account.unfollow": "Não seguir",
|
||||
"account.block": "Bloquear @{name}",
|
||||
"account.mute": "Mute",
|
||||
"account.unmute": "Remover Mute",
|
||||
"account.follow": "Seguir",
|
||||
"account.posts": "Posts",
|
||||
"account.follows": "Segue",
|
||||
"account.followers": "Seguidores",
|
||||
"account.follows_you": "É teu seguidor",
|
||||
"account.requested": "A aguardar aprovação",
|
||||
"account.report": "Denunciar",
|
||||
"account.disclaimer": "Essa conta está localizado em outra instância. Os nomes podem ser maiores.",
|
||||
"getting_started.heading": "Primeiros passos",
|
||||
"getting_started.about_addressing": "Podes seguir pessoas se sabes o nome de usuário deles e o domínio em que estão colocando um endereço similar a e-mail no campo no topo da barra lateral.",
|
||||
"getting_started.about_shortcuts": "Se o usuário alvo está no mesmo domínio, só o nome funcionará. A mesma regra se aplica a mencionar pessoas nas postagens.",
|
||||
"getting_started.about_developer": "Pode seguir o developer deste projecto em Gargron@mastodon.social",
|
||||
"getting_started.open_source_notice": "Mastodon é software de fonte aberta. Podes contribuir ou repostar problemas no GitHub do projecto: {github}. {apps}.",
|
||||
"column.home": "Home",
|
||||
"column.community": "Local",
|
||||
"column.public": "Público",
|
||||
"column.public": "Global",
|
||||
"column.notifications": "Notificações",
|
||||
"column.blocks": "Utilizadores Bloqueados",
|
||||
"column.favourites": "Favoritos",
|
||||
"column.follow_requests": "Seguidores Pendentes",
|
||||
"empty_column.notifications": "Não tens notificações. Interage com outros utilizadores para iniciar uma conversa.",
|
||||
"empty_column.public": "Não há nada aqui! Escreve algo publicamente ou segue outros utilizadores para ver aqui os conteúdos públicos.",
|
||||
"empty_column.home": "Ainda não segues qualquer utilizador. Visita {public} ou utiliza a pesquisa para procurar outros utilizadores.",
|
||||
"empty_column.home.public_timeline": "global",
|
||||
"empty_column.community": "Ainda não existem conteúdo local para mostrar!",
|
||||
"empty_column.hashtag": "Não existe qualquer conteúdo com essa hashtag",
|
||||
"tabs_bar.compose": "Criar",
|
||||
"tabs_bar.home": "Home",
|
||||
"tabs_bar.mentions": "Menções",
|
||||
"tabs_bar.public": "Público",
|
||||
"tabs_bar.notifications": "Notificações",
|
||||
"tabs_bar.local_timeline": "Local",
|
||||
"tabs_bar.federated_timeline": "Global",
|
||||
"compose_form.placeholder": "Em que estás a pensar?",
|
||||
"compose_form.publish": "Publicar",
|
||||
"compose_form.sensitive": "Media com conteúdo sensível",
|
||||
"compose_form.sensitive": "Marcar media como conteúdo sensível",
|
||||
"compose_form.spoiler": "Esconder texto com aviso",
|
||||
"compose_form.spoiler_placeholder": "Aviso",
|
||||
"compose_form.private": "Tornar privado",
|
||||
"compose_form.privacy_disclaimer": "O teu conteúdo privado vai ser partilhado com os utilizadores do {domains}. Confias {domainsCount, plural, one {neste servidor} other {nestes servidores}}? A privacidade só funciona em instâncias do Mastodon. Se {domains} {domainsCount, plural, one {não é uma instância} other {não são instâncias}}, não existem indicadores da privacidade da tua partilha, e podem ser partilhados com outros.",
|
||||
"compose_form.unlisted": "Não mostrar na listagem pública",
|
||||
"emoji_button.label": "Inserir Emoji",
|
||||
"navigation_bar.edit_profile": "Editar perfil",
|
||||
"navigation_bar.preferences": "Preferências",
|
||||
"navigation_bar.community_timeline": "Local",
|
||||
"navigation_bar.public_timeline": "Público",
|
||||
"navigation_bar.public_timeline": "Global",
|
||||
"navigation_bar.blocks": "Utilizadores bloqueados",
|
||||
"navigation_bar.favourites": "Favoritos",
|
||||
"navigation_bar.info": "Mais informações",
|
||||
"navigation_bar.logout": "Sair",
|
||||
"navigation_bar.follow_requests": "Seguidores pendentes",
|
||||
"reply_indicator.cancel": "Cancelar",
|
||||
"search.placeholder": "Pesquisar",
|
||||
"search.account": "Conta",
|
||||
"search.hashtag": "Hashtag",
|
||||
"search_results.total": "{count} {count, plural, one {resultado} other {resultados}}",
|
||||
"search.status_by": "Post de {name}",
|
||||
"upload_button.label": "Adicionar media",
|
||||
"upload_form.undo": "Anular",
|
||||
"upload_progress.label": "A gravar…",
|
||||
"upload_area.title": "Arraste e solte para enviar",
|
||||
"notification.follow": "{name} seguiu-te",
|
||||
"notification.favourite": "{name} adicionou o teu post aos favoritos",
|
||||
"notification.reblog": "{name} partilhou o teu post",
|
||||
"notification.mention": "{name} mencionou-te",
|
||||
"notifications.column_settings.alert": "Notificações no computador",
|
||||
"notifications.column_settings.show": "Mostrar nas colunas",
|
||||
"notifications.column_settings.sound": "Reproduzir som",
|
||||
"notifications.column_settings.follow": "Novos seguidores:",
|
||||
"notifications.column_settings.favourite": "Favoritos:",
|
||||
"notifications.column_settings.mention": "Menções:",
|
||||
"notifications.column_settings.reblog": "Partilhas:",
|
||||
"notifications.clear": "Limpar notificações",
|
||||
"notifications.clear_confirmation": "Queres mesmo limpar todas as notificações?",
|
||||
"notifications.settings": "Parâmetros da lista de Notificações",
|
||||
"privacy.public.short": "Público",
|
||||
"privacy.public.long": "Publicar em todos os feeds",
|
||||
"privacy.unlisted.short": "Não listar",
|
||||
"privacy.unlisted.long": "Não publicar nos feeds públicos",
|
||||
"privacy.private.short": "Privado",
|
||||
"privacy.private.long": "Apenas para os seguidores",
|
||||
"privacy.direct.short": "Directo",
|
||||
"privacy.direct.long": "Apenas para utilizadores mencionados",
|
||||
"privacy.change": "Ajustar a privacidade da mensagem",
|
||||
"media_gallery.toggle_visible": "Modificar a visibilidade",
|
||||
"missing_indicator.label": "Não encontrado",
|
||||
"follow_request.authorize": "Autorizar",
|
||||
"follow_request.reject": "Rejeitar",
|
||||
"home.settings": "Parâmetros da coluna Home",
|
||||
"home.column_settings.basic": "Básico",
|
||||
"home.column_settings.show_reblogs": "Mostrar as partilhas",
|
||||
"home.column_settings.show_replies": "Mostrar as respostas",
|
||||
"home.column_settings.advanced": "Avançadas",
|
||||
"home.column_settings.filter_regex": "Filtrar com uma expressão regular",
|
||||
"report.heading": "Nova denuncia",
|
||||
"report.placeholder": "Comentários adicionais",
|
||||
"report.submit": "Enviar",
|
||||
"report.target": "Denunciar"
|
||||
};
|
||||
|
||||
export default pt;
|
||||
|
|
|
@ -10,22 +10,29 @@ const ru = {
|
|||
"status.reblogged_by": "{name} продвинул(а)",
|
||||
"status.sensitive_warning": "Чувствительный контент",
|
||||
"status.sensitive_toggle": "Нажмите для просмотра",
|
||||
"status.show_more": "Развернуть",
|
||||
"status.show_less": "Свернуть",
|
||||
"status.open": "Развернуть статус",
|
||||
"status.report": "Пожаловаться",
|
||||
"status.load_more": "Показать еще",
|
||||
"video_player.toggle_sound": "Вкл./выкл. звук",
|
||||
"account.mention": "Упомянуть @{name}",
|
||||
"account.mention": "Упомянуть",
|
||||
"account.edit_profile": "Изменить профиль",
|
||||
"account.unblock": "Разблокировать @{name}",
|
||||
"account.unblock": "Разблокировать",
|
||||
"account.unfollow": "Отписаться",
|
||||
"account.block": "Блокировать @{name}",
|
||||
"account.block": "Блокировать",
|
||||
"account.mute": "Заглушить",
|
||||
"account.follow": "Подписаться",
|
||||
"account.posts": "Посты",
|
||||
"account.follows": "Подписки",
|
||||
"account.followers": "Подписчики",
|
||||
"account.followers": "Подписаны",
|
||||
"account.follows_you": "Подписан(а) на Вас",
|
||||
"account.requested": "Ожидает подтверждения",
|
||||
"getting_started.heading": "Добро пожаловать",
|
||||
"getting_started.about_addressing": "Вы можете подписаться на человека, зная имя пользователя и домен, на котором он находится, введя e-mail-подобный адрес в форму поиска.",
|
||||
"getting_started.about_shortcuts": "Если пользователь находится на одном с Вами домене, можно использовать только имя. То же правило применимо к упоминанию пользователей в статусах.",
|
||||
"getting_started.open_source_notice": "Mastodon - программа с открытым исходным кодом. Вы можете помочь проекту или сообщить о проблемах на GitHub по адресу {github}. {apps}.",
|
||||
"getting_started.apps": "Доступны различные приложения.",
|
||||
"column.home": "Главная",
|
||||
"column.community": "Локальная лента",
|
||||
"column.public": "Глобальная лента",
|
||||
|
@ -36,7 +43,7 @@ const ru = {
|
|||
"tabs_bar.public": "Глобальная лента",
|
||||
"tabs_bar.notifications": "Уведомления",
|
||||
"compose_form.placeholder": "О чем Вы думаете?",
|
||||
"compose_form.publish": "Протрубить",
|
||||
"compose_form.publish": "Трубить",
|
||||
"compose_form.sensitive": "Отметить как чувствительный контент",
|
||||
"compose_form.spoiler": "Скрыть текст за предупреждением",
|
||||
"compose_form.private": "Отметить как приватное",
|
||||
|
@ -47,6 +54,9 @@ const ru = {
|
|||
"navigation_bar.community_timeline": "Локальная лента",
|
||||
"navigation_bar.public_timeline": "Глобальная лента",
|
||||
"navigation_bar.logout": "Выйти",
|
||||
"navigation_bar.info": "Об узле",
|
||||
"navigation_bar.favourites": "Понравившееся",
|
||||
"navigation_bar.blocks": "Список блокировки",
|
||||
"reply_indicator.cancel": "Отмена",
|
||||
"search.placeholder": "Поиск",
|
||||
"search.account": "Аккаунт",
|
||||
|
@ -57,12 +67,35 @@ const ru = {
|
|||
"notification.favourite": "{name} понравился Ваш статус",
|
||||
"notification.reblog": "{name} продвинул(а) Ваш статус",
|
||||
"notification.mention": "{name} упомянул(а) Вас",
|
||||
"home.settings": "Настройки колонки",
|
||||
"home.column_settings.basic": "Основные",
|
||||
"home.column_settings.advanced": "Дополнительные",
|
||||
"home.column_settings.filter_regex": "Отфильтровать регулярным выражением",
|
||||
"home.column_settings.show_replies": "Показывать продвижения",
|
||||
"home.column_settings.show_replies": "Показывать ответы",
|
||||
"notifications.clear": "Очистить уведомления",
|
||||
"notifications.settings": "Настройки колонки",
|
||||
"notifications.column_settings.alert": "Десктопные уведомления",
|
||||
"notifications.column_settings.show": "Показывать в колонке",
|
||||
"notifications.column_settings.follow": "Новые подписчики:",
|
||||
"notifications.column_settings.favourite": "Нравится:",
|
||||
"notifications.column_settings.mention": "Упоминания:",
|
||||
"notifications.column_settings.reblog": "Продвижения:",
|
||||
"notifications.column_settings.sound": "Проигрывать звук",
|
||||
"empty_column.notifications": "У Вас еще нет уведомлений. Заведите знакомство с другими пользователями, чтобы начать разговор.",
|
||||
"empty_column.hashtag": "Статусов с таким хэштегом еще не существует.",
|
||||
"empty_column.community": "Локальная лента пуста. Напишите что-нибудь, чтобы разогреть народ!",
|
||||
"empty_column.public": "Здесь ничего нет! Опубликуйте что-нибудь или подпишитесь на пользователей с других узлов, чтобы заполнить ленту.",
|
||||
"empty_column.home": "Пока Вы ни на кого не подписаны. Полистайте {public} или используйте поиск, чтобы освоиться и завести новые знакомства.",
|
||||
"empty_column.home.public_timeline": "публичные ленты",
|
||||
"privacy.public.short": "Публичный",
|
||||
"privacy.public.long": "Показать в публичных лентах",
|
||||
"privacy.unlisted.short": "Скрытый",
|
||||
"privacy.unlisted.long": "Не показывать в лентах",
|
||||
"privacy.private.short": "Приватный",
|
||||
"privacy.private.long": "Показать только подписчикам",
|
||||
"privacy.direct.short": "Направленный",
|
||||
"privacy.direct.long": "Показать только упомянутым",
|
||||
};
|
||||
|
||||
export default ru;
|
||||
|
|
|
@ -88,7 +88,7 @@ code {
|
|||
}
|
||||
}
|
||||
|
||||
input[type=text], input[type=email], input[type=password], textarea {
|
||||
input[type=text], input[type=number], input[type=email], input[type=password], textarea {
|
||||
background: transparent;
|
||||
box-sizing: border-box;
|
||||
border: 0;
|
||||
|
|
|
@ -2,49 +2,29 @@
|
|||
|
||||
module Admin
|
||||
class AccountsController < BaseController
|
||||
before_action :set_account, except: :index
|
||||
|
||||
def index
|
||||
@accounts = Account.alphabetic.page(params[:page])
|
||||
|
||||
@accounts = @accounts.local if params[:local].present?
|
||||
@accounts = @accounts.remote if params[:remote].present?
|
||||
@accounts = @accounts.where(domain: params[:by_domain]) if params[:by_domain].present?
|
||||
@accounts = @accounts.silenced if params[:silenced].present?
|
||||
@accounts = @accounts.recent if params[:recent].present?
|
||||
@accounts = @accounts.suspended if params[:suspended].present?
|
||||
@accounts = filtered_accounts.page(params[:page])
|
||||
end
|
||||
|
||||
def show; end
|
||||
|
||||
def suspend
|
||||
Admin::SuspensionWorker.perform_async(@account.id)
|
||||
redirect_to admin_accounts_path
|
||||
end
|
||||
|
||||
def unsuspend
|
||||
@account.update(suspended: false)
|
||||
redirect_to admin_accounts_path
|
||||
end
|
||||
|
||||
def silence
|
||||
@account.update(silenced: true)
|
||||
redirect_to admin_accounts_path
|
||||
end
|
||||
|
||||
def unsilence
|
||||
@account.update(silenced: false)
|
||||
redirect_to admin_accounts_path
|
||||
def show
|
||||
@account = Account.find(params[:id])
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_account
|
||||
@account = Account.find(params[:id])
|
||||
def filtered_accounts
|
||||
AccountFilter.new(filter_params).results
|
||||
end
|
||||
|
||||
def account_params
|
||||
params.require(:account).permit(:silenced, :suspended)
|
||||
def filter_params
|
||||
params.permit(
|
||||
:local,
|
||||
:remote,
|
||||
:by_domain,
|
||||
:silenced,
|
||||
:recent,
|
||||
:suspended
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
23
app/controllers/admin/silences_controller.rb
Normal file
23
app/controllers/admin/silences_controller.rb
Normal file
|
@ -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
|
23
app/controllers/admin/suspensions_controller.rb
Normal file
23
app/controllers/admin/suspensions_controller.rb
Normal file
|
@ -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
|
|
@ -6,7 +6,7 @@ module Settings
|
|||
before_action :authenticate_user!
|
||||
|
||||
def index
|
||||
export_data = Export.new(export_accounts).to_csv
|
||||
@export = Export.new(current_account)
|
||||
|
||||
respond_to do |format|
|
||||
format.csv { send_data export_data, filename: export_filename }
|
||||
|
|
|
@ -5,8 +5,8 @@ module Settings
|
|||
class BlockedAccountsController < BaseController
|
||||
private
|
||||
|
||||
def export_accounts
|
||||
current_account.blocking
|
||||
def export_data
|
||||
@export.to_blocked_accounts_csv
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,8 +5,8 @@ module Settings
|
|||
class FollowingAccountsController < BaseController
|
||||
private
|
||||
|
||||
def export_accounts
|
||||
current_account.following
|
||||
def export_data
|
||||
@export.to_following_accounts_csv
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,8 +5,8 @@ module Settings
|
|||
class MutedAccountsController < BaseController
|
||||
private
|
||||
|
||||
def export_accounts
|
||||
current_account.muting
|
||||
def export_data
|
||||
@export.to_muted_accounts_csv
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,9 +6,6 @@ class Settings::ExportsController < ApplicationController
|
|||
before_action :authenticate_user!
|
||||
|
||||
def show
|
||||
@total_storage = current_account.media_attachments.sum(:file_file_size)
|
||||
@total_follows = current_account.following.count
|
||||
@total_blocks = current_account.blocking.count
|
||||
@total_mutes = current_account.muting.count
|
||||
@export = Export.new(current_account)
|
||||
end
|
||||
end
|
||||
|
|
13
app/controllers/well_known/host_meta_controller.rb
Normal file
13
app/controllers/well_known/host_meta_controller.rb
Normal file
|
@ -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
|
43
app/controllers/well_known/webfinger_controller.rb
Normal file
43
app/controllers/well_known/webfinger_controller.rb
Normal file
|
@ -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
|
|
@ -16,6 +16,7 @@ module SettingsHelper
|
|||
ja: '日本語',
|
||||
'zh-CN': '简体中文',
|
||||
'zh-HK': '繁體中文(香港)',
|
||||
bg: 'Български',
|
||||
}.freeze
|
||||
|
||||
def human_locale(locale)
|
||||
|
|
36
app/models/account_filter.rb
Normal file
36
app/models/account_filter.rb
Normal file
|
@ -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
|
|
@ -2,13 +2,43 @@
|
|||
require 'csv'
|
||||
|
||||
class Export
|
||||
attr_reader :accounts
|
||||
attr_reader :account
|
||||
|
||||
def initialize(accounts)
|
||||
@accounts = accounts
|
||||
def initialize(account)
|
||||
@account = account
|
||||
end
|
||||
|
||||
def to_csv
|
||||
def to_blocked_accounts_csv
|
||||
to_csv account.blocking
|
||||
end
|
||||
|
||||
def to_muted_accounts_csv
|
||||
to_csv account.muting
|
||||
end
|
||||
|
||||
def to_following_accounts_csv
|
||||
to_csv account.following
|
||||
end
|
||||
|
||||
def total_storage
|
||||
account.media_attachments.sum(:file_file_size)
|
||||
end
|
||||
|
||||
def total_follows
|
||||
account.following.count
|
||||
end
|
||||
|
||||
def total_blocks
|
||||
account.blocking.count
|
||||
end
|
||||
|
||||
def total_mutes
|
||||
account.muting.count
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def to_csv(accounts)
|
||||
CSV.generate do |csv|
|
||||
accounts.each do |account|
|
||||
csv << [(account.local? ? account.local_username_and_domain : account.acct)]
|
||||
|
|
|
@ -62,11 +62,11 @@
|
|||
= number_to_human_size @account.media_attachments.sum('file_file_size')
|
||||
|
||||
- if @account.silenced?
|
||||
= link_to 'Undo silence', unsilence_admin_account_path(@account.id), method: :post, class: 'button'
|
||||
= link_to 'Undo silence', admin_account_silence_path(@account.id), method: :delete, class: 'button'
|
||||
- else
|
||||
= link_to 'Silence', silence_admin_account_path(@account.id), method: :post, class: 'button'
|
||||
= link_to 'Silence', admin_account_silence_path(@account.id), method: :post, class: 'button'
|
||||
|
||||
- if @account.suspended?
|
||||
= link_to 'Undo suspension', unsuspend_admin_account_path(@account.id), method: :post, class: 'button'
|
||||
= link_to 'Undo suspension', admin_account_suspension_path(@account.id), method: :delete, class: 'button'
|
||||
- else
|
||||
= link_to 'Perform full suspension', suspend_admin_account_path(@account.id), method: :post, data: { confirm: 'Are you sure?' }, class: 'button'
|
||||
= link_to 'Perform full suspension', admin_account_suspension_path(@account.id), method: :post, data: { confirm: 'Are you sure?' }, class: 'button'
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
= t('auth.login')
|
||||
|
||||
= simple_form_for(resource, as: resource_name, url: session_path(resource_name), method: :post) do |f|
|
||||
= f.input :otp_attempt, placeholder: t('simple_form.labels.defaults.otp_attempt'), input_html: { 'aria-label' => t('simple_form.labels.defaults.otp_attempt') }, required: true, autofocus: true, autocomplete: 'off'
|
||||
= f.input :otp_attempt, type: :number, placeholder: t('simple_form.labels.defaults.otp_attempt'), input_html: { 'aria-label' => t('simple_form.labels.defaults.otp_attempt') }, required: true, autofocus: true, autocomplete: 'off'
|
||||
|
||||
.actions
|
||||
= f.button :button, t('auth.login'), type: :submit
|
||||
|
|
|
@ -5,17 +5,17 @@
|
|||
%tbody
|
||||
%tr
|
||||
%th= t('exports.storage')
|
||||
%td= number_to_human_size @total_storage
|
||||
%td= number_to_human_size @export.total_storage
|
||||
%td
|
||||
%tr
|
||||
%th= t('exports.follows')
|
||||
%td= @total_follows
|
||||
%td= @export.total_follows
|
||||
%td= table_link_to 'download', t('exports.csv'), settings_exports_follows_path(format: :csv)
|
||||
%tr
|
||||
%th= t('exports.blocks')
|
||||
%td= @total_blocks
|
||||
%td= @export.total_blocks
|
||||
%td= table_link_to 'download', t('exports.csv'), settings_exports_blocks_path(format: :csv)
|
||||
%tr
|
||||
%th= t('exports.mutes')
|
||||
%td= @total_mutes
|
||||
%td= @export.total_mutes
|
||||
%td= table_link_to 'download', t('exports.csv'), settings_exports_mutes_path(format: :csv)
|
||||
|
|
|
@ -27,6 +27,7 @@ module Mastodon
|
|||
|
||||
config.i18n.available_locales = [
|
||||
:en,
|
||||
:bg,
|
||||
:de,
|
||||
:eo,
|
||||
:es,
|
||||
|
|
169
config/locales/bg.yml
Normal file
169
config/locales/bg.yml
Normal file
|
@ -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: Не мога да прикача видеоклип към публикация, която вече съдържа изображения
|
61
config/locales/devise.bg.yml
Normal file
61
config/locales/devise.bg.yml
Normal file
|
@ -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} да бъде записан:"
|
113
config/locales/doorkeeper.bg.yml
Normal file
113
config/locales/doorkeeper.bg.yml
Normal file
|
@ -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: публикуването от твое име
|
|
@ -25,7 +25,7 @@ ja:
|
|||
confirmations:
|
||||
destroy: 本当に削除しますか?
|
||||
edit:
|
||||
title: アプリケーションの編集
|
||||
title: アプリの編集
|
||||
form:
|
||||
error: フォームにエラーが無いか確認してください。
|
||||
help:
|
||||
|
@ -35,17 +35,17 @@ ja:
|
|||
index:
|
||||
callback_url: コールバックURL
|
||||
name: 名前
|
||||
new: 新規アプリケーション
|
||||
title: あなたのアプリケーション
|
||||
new: 新規アプリ
|
||||
title: アプリ
|
||||
new:
|
||||
title: 新規アプリケーション
|
||||
title: 新規アプリ
|
||||
show:
|
||||
actions: アクション
|
||||
application_id: アクションId
|
||||
callback_urls: コールバックurl
|
||||
scopes: アクセス権
|
||||
secret: 非公開
|
||||
title: 'アプリケーション: %{name}'
|
||||
title: 'アプリ: %{name}'
|
||||
authorizations:
|
||||
buttons:
|
||||
authorize: 承認
|
||||
|
@ -53,8 +53,8 @@ ja:
|
|||
error:
|
||||
title: エラーが発生しました。
|
||||
new:
|
||||
able_to: このアプリケーションは以下のことができます
|
||||
prompt: アプリケーション %{client_name} があなたのアカウントへのアクセスを要求しています。
|
||||
able_to: このアプリは以下のことができます
|
||||
prompt: アプリ %{client_name} があなたのアカウントへのアクセスを要求しています。
|
||||
title: 認証が必要です。
|
||||
show:
|
||||
title: 認証コード
|
||||
|
@ -68,7 +68,7 @@ ja:
|
|||
created_at: 許可した日時
|
||||
date_format: "%Y年%m月%d日 %H時%M分%S秒"
|
||||
scopes: アクセス権
|
||||
title: 認証済みアプリケーション
|
||||
title: 認証済みアプリ
|
||||
errors:
|
||||
messages:
|
||||
access_denied: リソースの所有者または認証サーバーが要求を拒否しました。
|
||||
|
@ -92,22 +92,22 @@ ja:
|
|||
flash:
|
||||
applications:
|
||||
create:
|
||||
notice: アプリケーションが作成されました。
|
||||
notice: アプリが作成されました。
|
||||
destroy:
|
||||
notice: アプリケーションが削除されました。
|
||||
notice: アプリが削除されました。
|
||||
update:
|
||||
notice: アプリケーションが更新されました。
|
||||
notice: アプリが更新されました。
|
||||
authorized_applications:
|
||||
destroy:
|
||||
notice: アプリケーションが取り消されました。
|
||||
notice: アプリが取り消されました。
|
||||
layouts:
|
||||
admin:
|
||||
nav:
|
||||
applications: アプリケーション
|
||||
applications: アプリ
|
||||
oauth2_provider: OAuth2プロバイダー
|
||||
application:
|
||||
title: OAuth認証が必要です。
|
||||
title: OAuth認証
|
||||
scopes:
|
||||
follow: アカウントのフォロー, ブロック, ブロック解除, フォロー解除
|
||||
read: アカウントへのデータの読み取り
|
||||
write: アカウントからの投稿の書き込み
|
||||
read: アカウントからのデータの読み取り
|
||||
write: アカウントへのデータの書き込み
|
||||
|
|
|
@ -46,7 +46,7 @@ ja:
|
|||
applications:
|
||||
invalid_url: URLが無効です
|
||||
auth:
|
||||
change_password: 資格情報
|
||||
change_password: ログイン情報
|
||||
didnt_get_confirmation: 確認メールを受信できませんか?
|
||||
forgot_password: パスワードをお忘れですか?
|
||||
login: ログイン
|
||||
|
|
|
@ -9,7 +9,7 @@ ru:
|
|||
contact: Связаться
|
||||
description_headline: Что такое %{domain}?
|
||||
domain_count_after: другими узлами
|
||||
domain_count_before: Связывается с
|
||||
domain_count_before: Связан с
|
||||
features:
|
||||
api: Открытый API для приложений и сервисов
|
||||
blocks: Продвинутые инструменты блокирования и глушения
|
||||
|
@ -25,7 +25,7 @@ ru:
|
|||
other_instances: Другие узлы
|
||||
source_code: Исходный код
|
||||
status_count_after: статусов
|
||||
status_count_before: Автор
|
||||
status_count_before: Опубликовано
|
||||
terms: Условия
|
||||
user_count_after: пользователей
|
||||
user_count_before: Здесь живет
|
||||
|
@ -42,7 +42,7 @@ ru:
|
|||
application_mailer:
|
||||
settings: 'Изменить настройки e-mail: %{link}'
|
||||
signature: Уведомления Mastodon от %{instance}
|
||||
view: 'View:'
|
||||
view: 'Просмотр:'
|
||||
applications:
|
||||
invalid_url: Введенный URL неверен
|
||||
auth:
|
||||
|
@ -126,7 +126,7 @@ ru:
|
|||
acct: Введите username@domain, откуда Вы хотите подписаться
|
||||
missing_resource: Поиск требуемого перенаправления URL для Вашего аккаунта завершился неудачей
|
||||
proceed: Продолжить подписку
|
||||
prompt: 'Вы ходите подписаться на:'
|
||||
prompt: 'Вы хотите подписаться на:'
|
||||
settings:
|
||||
authorized_apps: Авторизованные приложения
|
||||
back: Назад в Mastodon
|
||||
|
@ -142,8 +142,8 @@ ru:
|
|||
show_more: Подробнее
|
||||
visibilities:
|
||||
private: Показывать только подписчикам
|
||||
public: Публичный
|
||||
unlisted: Публичный, но без отображения в публичных лентах
|
||||
public: Показывать всем
|
||||
unlisted: Показывать всем, но не отображать в публичных лентах
|
||||
stream_entries:
|
||||
click_to_show: Показать
|
||||
reblogged: продвинул(а)
|
||||
|
@ -156,8 +156,13 @@ ru:
|
|||
disable: Отключить
|
||||
enable: Включить
|
||||
instructions_html: "<strong>Отсканируйте этот QR-код с помощью Google Authenticator или другого подобного приложения на Вашем телефоне</strong>. С этого момента приложение будет генерировать токены, которые будет необходимо ввести для входа."
|
||||
manual_instructions: 'Если Вы не можете отсканировать QR-код и хотите ввести его вручную, секрет представлен здесь открытым текстом:'
|
||||
plaintext_secret_html: 'Секрет открытым текстом: <samp>%{secret}</samp>'
|
||||
warning: Если сейчас у Вас не получается настроить аутентификатор, нажмите "отключить", иначе Вы не сможете войти!
|
||||
code_hint: 'Для подтверждения введите код, сгенерированный приложением аутентификатора'
|
||||
setup: Настроить
|
||||
warning: 'Если сейчас у Вас не получается настроить аутентификатор, нажмите "отключить", иначе Вы не сможете войти!'
|
||||
users:
|
||||
invalid_email: Введенный e-mail неверен
|
||||
invalid_otp_token: Введен неверный код
|
||||
will_paginate:
|
||||
page_gap: "…"
|
||||
|
|
46
config/locales/simple_form.bg.yml
Normal file
46
config/locales/simple_form.bg.yml
Normal file
|
@ -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': 'Да'
|
|
@ -26,7 +26,7 @@ ru:
|
|||
note: О Вас
|
||||
otp_attempt: Двухфакторный код
|
||||
password: Пароль
|
||||
setting_default_privacy: Приватность постов
|
||||
setting_default_privacy: Видимость постов
|
||||
type: Тип импорта
|
||||
username: Имя пользователя
|
||||
interactions:
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'sidekiq/web'
|
||||
|
@ -14,8 +15,8 @@ Rails.application.routes.draw do
|
|||
controllers authorizations: 'oauth/authorizations', authorized_applications: 'oauth/authorized_applications'
|
||||
end
|
||||
|
||||
get '.well-known/host-meta', to: 'xrd#host_meta', as: :host_meta
|
||||
get '.well-known/webfinger', to: 'xrd#webfinger', as: :webfinger, defaults: { format: 'json' }
|
||||
get '.well-known/host-meta', to: 'well_known/host_meta#show', as: :host_meta, defaults: { format: 'xml' }
|
||||
get '.well-known/webfinger', to: 'well_known/webfinger#show', as: :webfinger, defaults: { format: 'json' }
|
||||
|
||||
devise_for :users, path: 'auth', controllers: {
|
||||
sessions: 'auth/sessions',
|
||||
|
@ -89,12 +90,8 @@ Rails.application.routes.draw do
|
|||
end
|
||||
|
||||
resources :accounts, only: [:index, :show] do
|
||||
member do
|
||||
post :silence
|
||||
post :unsilence
|
||||
post :suspend
|
||||
post :unsuspend
|
||||
end
|
||||
resource :silence, only: [:create, :destroy]
|
||||
resource :suspension, only: [:create, :destroy]
|
||||
end
|
||||
end
|
||||
|
||||
|
|
24
spec/controllers/admin/silences_controller_spec.rb
Normal file
24
spec/controllers/admin/silences_controller_spec.rb
Normal file
|
@ -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
|
24
spec/controllers/admin/suspensions_controller_spec.rb
Normal file
24
spec/controllers/admin/suspensions_controller_spec.rb
Normal file
|
@ -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
|
|
@ -1,6 +1,8 @@
|
|||
require 'rails_helper'
|
||||
|
||||
describe Settings::ExportsController do
|
||||
render_views
|
||||
|
||||
before do
|
||||
sign_in Fabricate(:user), scope: :user
|
||||
end
|
||||
|
@ -8,6 +10,7 @@ describe Settings::ExportsController do
|
|||
describe 'GET #show' do
|
||||
it 'returns http success' do
|
||||
get :show
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
end
|
||||
end
|
||||
|
|
13
spec/controllers/well_known/host_meta_controller_spec.rb
Normal file
13
spec/controllers/well_known/host_meta_controller_spec.rb
Normal file
|
@ -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
|
21
spec/controllers/well_known/webfinger_controller_spec.rb
Normal file
21
spec/controllers/well_known/webfinger_controller_spec.rb
Normal file
|
@ -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
|
31
spec/models/account_filter_spec.rb
Normal file
31
spec/models/account_filter_spec.rb
Normal file
|
@ -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
|
12
spec/requests/host_meta_request_spec.rb
Normal file
12
spec/requests/host_meta_request_spec.rb
Normal file
|
@ -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
|
15
spec/routing/well_known_routes_spec.rb
Normal file
15
spec/routing/well_known_routes_spec.rb
Normal file
|
@ -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
|
Reference in a new issue