diff --git a/app/assets/javascripts/components/containers/mastodon.jsx b/app/assets/javascripts/components/containers/mastodon.jsx index 00f20074d91..fea8b159498 100644 --- a/app/assets/javascripts/components/containers/mastodon.jsx +++ b/app/assets/javascripts/components/containers/mastodon.jsx @@ -48,6 +48,8 @@ import hu from 'react-intl/locale-data/hu'; import uk from 'react-intl/locale-data/uk'; import fi from 'react-intl/locale-data/fi'; import eo from 'react-intl/locale-data/eo'; +import ru from 'react-intl/locale-data/ru'; + import getMessagesForLocale from '../locales'; import { hydrateStore } from '../actions/store'; import createStream from '../stream'; @@ -60,7 +62,9 @@ const browserHistory = useRouterHistory(createBrowserHistory)({ basename: '/web' }); -addLocaleData([...en, ...de, ...es, ...fr, ...pt, ...hu, ...uk, ...fi, ...eo]); + +addLocaleData([...en, ...de, ...es, ...fr, ...pt, ...hu, ...uk, ...fi, ...eo, ...ru]); + const Mastodon = React.createClass({ diff --git a/app/assets/javascripts/components/locales/index.jsx b/app/assets/javascripts/components/locales/index.jsx index 1e7b8b548e2..f9e1fe5bd4e 100644 --- a/app/assets/javascripts/components/locales/index.jsx +++ b/app/assets/javascripts/components/locales/index.jsx @@ -7,6 +7,8 @@ import pt from './pt'; import uk from './uk'; import fi from './fi'; import eo from './eo'; +import ru from './ru'; + const locales = { en, @@ -17,7 +19,9 @@ const locales = { pt, uk, fi, - eo + eo, + ru + }; export default function getMessagesForLocale (locale) { diff --git a/app/assets/javascripts/components/locales/ru.jsx b/app/assets/javascripts/components/locales/ru.jsx new file mode 100644 index 00000000000..e109005a7ce --- /dev/null +++ b/app/assets/javascripts/components/locales/ru.jsx @@ -0,0 +1,68 @@ +const ru = { + "column_back_button.label": "Назад", + "lightbox.close": "Закрыть", + "loading_indicator.label": "Загрузка...", + "status.mention": "Упомянуть @{name}", + "status.delete": "Удалить", + "status.reply": "Ответить", + "status.reblog": "Продвинуть", + "status.favourite": "Нравится", + "status.reblogged_by": "{name} продвинул(а)", + "status.sensitive_warning": "Чувствительный контент", + "status.sensitive_toggle": "Нажмите для просмотра", + "video_player.toggle_sound": "Вкл./выкл. звук", + "account.mention": "Упомянуть @{name}", + "account.edit_profile": "Изменить профиль", + "account.unblock": "Разблокировать @{name}", + "account.unfollow": "Отписаться", + "account.block": "Блокировать @{name}", + "account.follow": "Подписаться", + "account.posts": "Посты", + "account.follows": "Подписки", + "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}.", + "column.home": "Главная", + "column.community": "Локальная лента", + "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 {этому серверу} other {этим серверам}}? Приватность постов работает только на узлах Mastodon. Если {domains} {domainsCount, plural, one {не является узлом Mastodon} other {не являются узлами Mastodon}}, приватность поста не будет указана, и он может оказаться продвинут или иным образом показан не обозначенным Вами пользователям.", + "compose_form.unlisted": "Не отображать в публичных лентах", + "navigation_bar.edit_profile": "Изменить профиль", + "navigation_bar.preferences": "Опции", + "navigation_bar.community_timeline": "Локальная лента", + "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 ru; diff --git a/app/helpers/settings_helper.rb b/app/helpers/settings_helper.rb index 74dc0e11d76..327ca4e9894 100644 --- a/app/helpers/settings_helper.rb +++ b/app/helpers/settings_helper.rb @@ -5,13 +5,15 @@ module SettingsHelper en: 'English', de: 'Deutsch', es: 'Español', + eo: 'Esperanto', pt: 'Português', fr: 'Français', hu: 'Magyar', uk: 'Українська', 'zh-CN': '简体中文', fi: 'Suomi', - eo: 'Esperanto', + ru: 'Русский', + }.freeze def human_locale(locale) diff --git a/config/application.rb b/config/application.rb index 9a5c0d0d3fe..dc937ca0eb0 100644 --- a/config/application.rb +++ b/config/application.rb @@ -24,7 +24,9 @@ module Mastodon # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] - config.i18n.available_locales = [:en, :de, :es, :pt, :fr, :hu, :uk, 'zh-CN', :fi, :eo] + + config.i18n.available_locales = [:en, :de, :es, :pt, :fr, :hu, :uk, 'zh-CN', :fi, :eo, :ru] + config.i18n.default_locale = :en # config.paths.add File.join('app', 'api'), glob: File.join('**', '*.rb') diff --git a/config/locales/devise.ru.yml b/config/locales/devise.ru.yml new file mode 100644 index 00000000000..f829f9d8e25 --- /dev/null +++ b/config/locales/devise.ru.yml @@ -0,0 +1,61 @@ +--- +ru: + devise: + confirmations: + confirmed: Ваш адрес e-mail был успешно подтвержден. + send_instructions: Вы получите e-mail с инструкцией по подтверждению Вашего адреса e-mail в течение нескольких минут. + send_paranoid_instructions: Если Ваш адрес e-mail есть в нашей базе данных, вы получите e-mail с инструкцией по подтверждению Вашего адреса в течение нескольких минут. + failure: + already_authenticated: Вы уже авторизованы. + inactive: Ваш аккаунт еще не активирован. + invalid: Неверно введены %{authentication_keys} или пароль. + last_attempt: У Вас есть последняя попытка, после чего вход будет заблокирован. + locked: Ваш аккаунт заблокирован. + not_found_in_database: Неверно введены %{authentication_keys} или пароль. + timeout: Ваша сессия истекла. Пожалуйста, войдите снова, чтобы продолжить. + unauthenticated: Вам необходимо войти или зарегистрироваться. + unconfirmed: Вам необходимо подтвердить ваш адрес e-mail для продолжения. + mailer: + confirmation_instructions: + subject: 'Mastodon: Инструкция по подтверждению' + password_change: + subject: 'Mastodon: Пароль изменен' + reset_password_instructions: + subject: 'Mastodon: Инструкция по сбросу пароля' + unlock_instructions: + subject: 'Mastodon: Инструкция по разблокировке' + omniauth_callbacks: + failure: Не получилось аутентифицировать Вас с помощью %{kind} по следующей причине - "%{reason}". + success: Аутентификация с помощью аккаунта %{kind} прошла успешно. + passwords: + no_token: Вы можете получить доступ к этой странице, только перейдя по ссылке в e-mail для сброса пароля. Если Вы действительно перешли по такой ссылке, пожалуйста, удостоверьтесь, что ссылка была введена полностью и без изменений. + send_instructions: Вы получите e-mail с инструкцией по сбросу пароля в течение нескольких минут. + send_paranoid_instructions: Если Ваш адрес e-mail есть в нашей базе данных, Вы получите e-mail со ссылкой для сброса пароля в течение нескольких минут. + updated: Ваш пароль был успешно изменен. Вход выполнен. + updated_not_active: Ваш пароль был успешно изменен. + registrations: + destroyed: До свидания! Ваш аккаунт был успешно удален. Мы надеемся скоро увидеть Вас снова. + signed_up: Добро пожаловать! Вы успешно зарегистрировались. + signed_up_but_inactive: Вы успешно зарегистрировались. Тем не менее, мы не можем авторизовать Вас, поскольку Ваш аккаунт еще не активирован. + signed_up_but_locked: Вы успешно зарегистрировались. Тем не менее, мы не можем авторизовать Вас, поскольку Ваш аккаунт заблокирован. + signed_up_but_unconfirmed: Сообщение со ссылкой для подтверждения было выслано на Ваш адрес e-mail. Пожалуйста, пройдите по ссылке для активации Вашего аккаунта. + update_needs_confirmation: Вы успешно обновили Ваш аккаунт, но нам нужно подтвердить ваш новый адрес e-mail. Пожалуйста, проверьте почту и пройдите по ссылке для подтверждения Вашего нового адреса. + updated: Ваш аккаунт был успешно обновлен. + sessions: + already_signed_out: Выход прошел успешно. + signed_in: Вход прошел успешно. + signed_out: Выход прошел успешно. + unlocks: + send_instructions: Вы получите e-mail с инструкцией по разблокировке Вашего аккаунта в течение нескольких минут. + send_paranoid_instructions: Если Ваш аккаунт существует, Вы получите e-mail с инструкцией по его разблокировке в течение нескольких минут. + unlocked: Ваш аккаунт был успешно разблокирован. пожалуйста, войдите для продолжения. + errors: + messages: + already_confirmed: уже подтвержден, пожалуйста, попробуйте войти + confirmation_period_expired: не был подтвержден в течение %{period}, пожалуйста, запросите новый + expired: истек, пожалуйста, запросите новый + not_found: не найден + not_locked: не был заблокирован + not_saved: + one: '1 ошибка помешала сохранению этого %{resource}:' + other: "%{count} ошибки помешали сохранению этого %{resource}:" diff --git a/config/locales/doorkeeper.ru.yml b/config/locales/doorkeeper.ru.yml new file mode 100644 index 00000000000..8862936dc2e --- /dev/null +++ b/config/locales/doorkeeper.ru.yml @@ -0,0 +1,113 @@ +--- +ru: + 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: Callback URL + name: Название + new: Новое Приложение + title: Ваши приложения + new: + title: Новое Приложение + show: + actions: Действия + application_id: Id приложения + callback_urls: Callback urls + 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: Поток с предоставлением клиенту пароля завершился неудачей, поскольку параметр 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: Поиск владельца ресурса завершился неудачей, поскольку параметр 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: отправлять за Вас посты diff --git a/config/locales/ru.yml b/config/locales/ru.yml new file mode 100644 index 00000000000..e5a9c0958c0 --- /dev/null +++ b/config/locales/ru.yml @@ -0,0 +1,165 @@ +--- +ru: + about: + about_mastodon: Mastodon - это свободная социальная сеть с открытым исходным кодом. Как децентрализованная альтернатива коммерческим платформам, Mastodon предотвращает риск монополизации Вашего общения одной компанией. Выберите сервер, которому Вы доверяете — что бы Вы ни выбрали, Вы сможете общаться со всеми остальными. Любой может запустить свой собственный узел Mastodon и участвовать в социальной сети совершенно бесшовно. + 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: '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: 'Вы (%{self}) запросили подписку:' + 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: Что-то здесь не так! Пожалуйста, прочитайте о %{count} ошибках ниже + imports: + preface: Вы можете загрузить некоторые данные, например, списки людей, на которых Вы подписаны или которых блокируете, в Ваш аккаунт на этом узле из файлов, экспортированных с другого узла. + success: Ваши данные были успешно загружены и будут обработаны с должной скоростью + types: + blocking: Список блокируемых + following: Список подписок + upload: Загрузить + landing_strip_html: %{name} - пользователь на %{domain}. Вы можете подписаться на него/нее и общаться с ним/ней, если у Вас есть аккаунт на любом узле общей сети. Если у Вас его нет, вы можете зарегистрироваться здесь. + 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: Введите username@domain, откуда Вы хотите подписаться + missing_resource: Поиск требуемого перенаправления URL для Вашего аккаунта завершился неудачей + proceed: Продолжить подписку + prompt: 'Вы ходите подписаться на:' + settings: + authorized_apps: Авторизованные приложения + back: Назад в Mastodon + edit_profile: Изменить профиль + export: Экспорт данных + import: Импорт + preferences: Настройки + settings: Опции + two_factor_auth: Двухфакторная аутентификация + statuses: + open_in_web: Открыть в WWW + over_character_limit: превышен лимит символов (%{max}) + show_more: Подробнее + visibilities: + private: Показывать только подписчикам + public: Публичный + unlisted: Публичный, но без отображения в публичных лентах + stream_entries: + click_to_show: Показать + reblogged: продвинул(а) + sensitive_content: Чувствительный контент + time: + formats: + default: "%b %d, %Y, %H:%M" + two_factor_auth: + description_html: При включении двухфакторной аутентификации, вход потребует от Вас использования Вашего телефона, который сгенерирует входные токены. + disable: Отключить + enable: Включить + instructions_html: "Отсканируйте этот QR-код с помощью Google Authenticator или другого подобного приложения на Вашем телефоне. С этого момента приложение будет генерировать токены, которые будет необходимо ввести для входа." + plaintext_secret_html: 'Секрет открытым текстом: %{secret}' + warning: Если сейчас у Вас не получается настроить аутентификатор, нажмите "отключить", иначе Вы не сможете войти! + users: + invalid_email: Введенный e-mail неверен + invalid_otp_token: Введен неверный код + will_paginate: + page_gap: "…" diff --git a/config/locales/simple_form.ru.yml b/config/locales/simple_form.ru.yml new file mode 100644 index 00000000000..6f4873bfd2d --- /dev/null +++ b/config/locales/simple_form.ru.yml @@ -0,0 +1,46 @@ +--- +ru: + simple_form: + hints: + defaults: + avatar: PNG, GIF или JPG. Максимально 2MB. Будет уменьшено до 120x120px + display_name: Максимально 30 символов + header: PNG, GIF или JPG. Максимально 2MB. Будет уменьшено до 700x335px + 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: Присылать дайджест по e-mail + favourite: Уведомлять по e-mail, когда кому-то нравится Ваш статус + follow: Уведомлять по e-mail, когда кто-то подписался на Вас + follow_request: Уведомлять по e-mail, когда кто-то запрашивает разрешение на подписку + mention: Уведомлять по e-mail, когда кто-то упомянул Вас + reblog: Уведомлять по e-mail, когда кто-то продвинул Ваш статус + 'no': 'Нет' + required: + mark: "*" + text: обязательно + 'yes': 'Да'