From 5aae6384ffc306d87ba153f99080db9d232d8832 Mon Sep 17 00:00:00 2001 From: Takayuki KUSANO Date: Sat, 15 Apr 2017 02:09:52 +0900 Subject: [PATCH 01/49] Fix Japanese translation for remote_follow (#1771) Current remote_follow.acct translation inappropriate. Users may input their own acccount. So fix the wording. --- config/locales/ja.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/locales/ja.yml b/config/locales/ja.yml index c1df73b7..39709589 100644 --- a/config/locales/ja.yml +++ b/config/locales/ja.yml @@ -157,7 +157,7 @@ ja: prev: 前 truncate: "…" remote_follow: - acct: フォローしたい人の ユーザー名@ドメイン を入力してください + acct: あなたの ユーザー名@ドメイン を入力してください missing_resource: リダイレクト先が見つかりませんでした proceed: フォローする prompt: 'フォローしようとしています:' From 1616cf98a1f9e87956ce03f82d5e6167c66d5dd5 Mon Sep 17 00:00:00 2001 From: Kazuhiro NISHIYAMA Date: Sat, 15 Apr 2017 02:10:12 +0900 Subject: [PATCH 02/49] Add missing Japanese translations (#1785) --- config/locales/ja.yml | 83 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 82 insertions(+), 1 deletion(-) diff --git a/config/locales/ja.yml b/config/locales/ja.yml index 39709589..91fda77c 100644 --- a/config/locales/ja.yml +++ b/config/locales/ja.yml @@ -40,6 +40,83 @@ ja: remote_follow: リモートフォロー unfollow: フォロー解除 admin: + accounts: + are_you_sure: 本当に実行しますか? + display_name: 表示名 + domain: ドメイン + edit: 編集 + email: E-mail + feed_url: Feed URL + followers: フォロワー数 + follows: フォロー数 + location: + all: すべて + local: ローカル + remote: リモート + title: ロケーション + media_attachments: 添付されたメディア + moderation: + all: すべて + silenced: サイレンス中 + suspended: 停止中 + title: モデレーション + most_recent_activity: 直近の活動 + most_recent_ip: 直近のIP + not_subscribed: 購読していない + order: + alphabetic: アルファベット順 + most_recent: 直近の活動順 + title: 順序 + perform_full_suspension: 完全に活動停止させる + profile_url: プロフィールURL + public: パブリック + push_subscription_expires: PuSH購読期限切れ + salmon_url: Salmon URL + silence: サイレンス + statuses: トゥート数 + title: アカウント + undo_silenced: サイレンスから戻す + undo_suspension: 停止から戻す + username: ユーザー名 + web: Web + domain_block: + add_new: 新規追加 + domain: ドメイン + new: + create: ブロックを作成 + hint: ドメインブロックはデータベース中のアカウント項目の作成を妨げませんが、遡って自動的に指定されたモデレーションをそれらのアカウントに適用します。 + severity: + desc_html: "サイレンスはアカウントのトゥートをフォローしていない人から隠します。停止はそのアカウントのコンテンツ、メディア、プロフィールデータをすべて削除します。" + silence: サイレンス + suspend: 停止 + title: 新規ドメインブロック + severity: 深刻度 + title: ドメインブロック + pubsubhubbub: + callback_url: コールバックURL + confirmed: 確認済み + expires_in: 期限 + last_delivery: 最終配送 + title: PubSubHubbub + topic: トピック + reports: + comment: + label: コメント + none: なし + delete: 削除 + id: ID + mark_as_resolved: 解決済みとしてマーク + report: 'レポート#%{id}' + reported_account: 報告対象アカウント + reported_by: 報告者 + resolved: 解決済み + silence_account: アカウントをサイレンス + status: ステータス + suspend_account: アカウントを停止 + target: ターゲット + title: レポート + unresolved: 未解決 + view: 表示 settings: click_to_edit: クリックして編集 contact_information: @@ -47,19 +124,23 @@ ja: label: 連絡先情報 username: ユーザー名を入力 registrations: + closed_message: + desc_html: 新規登録を停止しているときにフロントページに表示されます。
HTMLタグが利用可能です。 + title: 新規登録停止時のメッセージ open: disabled: 無効 enabled: 有効 title: 新規登録を受け付ける setting: 設定 site_description: - desc_html: トップページへの表示と meta タグに使用されます。
HTMLタグ、特に<a> and <em>が利用可能です。 + desc_html: トップページへの表示と meta タグに使用されます。
HTMLタグ、特に<a><em>が利用可能です。 title: サイトの説明文 site_description_extended: desc_html: インスタンスについてのページに表示されます。
HTMLタグが利用可能です。 title: サイトの詳細な説明 site_title: サイトのタイトル title: サイト設定 + title: 管理 application_mailer: settings: 'メール設定の変更: %{link}' signature: Mastodon %{instance} インスタンスからの通知 From 66ea015a017d97ecbd18eb850a033ca0c32e7957 Mon Sep 17 00:00:00 2001 From: Kazuhiro NISHIYAMA Date: Sat, 15 Apr 2017 02:10:38 +0900 Subject: [PATCH 03/49] Remove current directory from PATH (#1779) --- Vagrantfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Vagrantfile b/Vagrantfile index 90f60464..66892e44 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -43,7 +43,7 @@ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build -export PATH="$HOME/.rbenv/bin::$PATH" +export PATH="$HOME/.rbenv/bin:$PATH" eval "$(rbenv init -)" cd /vagrant From f5cd1383231af6922dbab4f54b7d29eacfec9d9e Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Fri, 14 Apr 2017 19:12:39 -0400 Subject: [PATCH 04/49] Improve i18n chooser (#1804) * Add locale spec with failing locale plus region check * Use a more accurate locale when supplied by browser headers Previously we were using a matching option which would use the first locale available which matched the locale portion, even if a region was specified. This changes to first try to find an exact match, and then fall back to the region, and then fall back to the default. * Clean up default_locale method --- app/controllers/concerns/localized.rb | 6 +++++- spec/requests/localization_spec.rb | 31 +++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 spec/requests/localization_spec.rb diff --git a/app/controllers/concerns/localized.rb b/app/controllers/concerns/localized.rb index 22bb5b21..d9a7a722 100644 --- a/app/controllers/concerns/localized.rb +++ b/app/controllers/concerns/localized.rb @@ -27,7 +27,11 @@ module Localized def default_locale ENV.fetch('DEFAULT_LOCALE') { - http_accept_language.compatible_language_from(I18n.available_locales) || I18n.default_locale + user_supplied_locale || I18n.default_locale } end + + def user_supplied_locale + http_accept_language.language_region_compatible_from(I18n.available_locales) + end end diff --git a/spec/requests/localization_spec.rb b/spec/requests/localization_spec.rb new file mode 100644 index 00000000..d1b7bdc1 --- /dev/null +++ b/spec/requests/localization_spec.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +require 'rails_helper' + +describe 'Localization' do + it 'uses a specific region when provided' do + headers = { 'Accept-Language' => 'zh-HK' } + + get "/about", headers: headers + expect(response.body).to include( + I18n.t('about.about_mastodon', locale: 'zh-HK') + ) + end + + it 'falls back to a locale when region missing' do + headers = { 'Accept-Language' => 'es-FAKE' } + + get "/about", headers: headers + expect(response.body).to include( + I18n.t('about.about_mastodon', locale: 'es') + ) + end + it 'falls back to english when locale is missing' do + headers = { 'Accept-Language' => '12-FAKE' } + + get "/about", headers: headers + expect(response.body).to include( + I18n.t('about.about_mastodon', locale: 'en') + ) + end +end From 92cd207c5083e60074e0ce123bb5b848a58e7417 Mon Sep 17 00:00:00 2001 From: Chad Pytel Date: Fri, 14 Apr 2017 19:21:02 -0400 Subject: [PATCH 05/49] Introduce capybara and first feature spec (#1801) This commit introduces Capybara and the first feature spec. I focused on coverage for log in for the first feature spec because that would have prevented 624a9a7136159d460228a0c2f5df18a9ead3b7f2 causing #1236. --- Gemfile | 1 + Gemfile.lock | 10 ++++++++++ spec/features/log_in_spec.rb | 16 ++++++++++++++++ spec/rails_helper.rb | 6 ++++++ 4 files changed, 33 insertions(+) create mode 100644 spec/features/log_in_spec.rb diff --git a/Gemfile b/Gemfile index 3f80e92e..d1a1e323 100644 --- a/Gemfile +++ b/Gemfile @@ -70,6 +70,7 @@ group :development, :test do end group :test do + gem 'capybara' gem 'faker' gem 'rails-controller-testing' gem 'rspec-sidekiq' diff --git a/Gemfile.lock b/Gemfile.lock index 2618f47f..430e2044 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -99,6 +99,13 @@ GEM sshkit (~> 1.3) capistrano-yarn (2.0.2) capistrano (~> 3.0) + capybara (2.13.0) + addressable + mime-types (>= 1.16) + nokogiri (>= 1.3.3) + rack (>= 1.0.0) + rack-test (>= 0.5.4) + xpath (~> 2.0) chunky_png (1.3.8) climate_control (0.1.0) cocaine (0.5.8) @@ -446,6 +453,8 @@ GEM websocket-driver (0.6.5) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.2) + xpath (2.0.0) + nokogiri (~> 1.3) PLATFORMS ruby @@ -465,6 +474,7 @@ DEPENDENCIES capistrano-rails capistrano-rbenv capistrano-yarn + capybara coffee-rails (~> 4.1.0) devise devise-two-factor diff --git a/spec/features/log_in_spec.rb b/spec/features/log_in_spec.rb new file mode 100644 index 00000000..4a634f6b --- /dev/null +++ b/spec/features/log_in_spec.rb @@ -0,0 +1,16 @@ +require "rails_helper" + +feature "Log in" do + scenario "A valid email and password user is able to log in" do + email = "test@example.com" + password = "password" + Fabricate(:user, email: email, password: password) + + visit new_user_session_path + fill_in "user_email", with: email + fill_in "user_password", with: password + click_on "Log in" + + expect(page).to have_css "div.app-holder[data-react-class=Mastodon]" + end +end diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index faac9698..536c5a77 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -7,6 +7,7 @@ require 'spec_helper' require 'rspec/rails' require 'webmock/rspec' require 'paperclip/matchers' +require 'capybara/rspec' Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f } @@ -24,6 +25,11 @@ RSpec.configure do |config| config.include Devise::Test::ControllerHelpers, type: :controller config.include Devise::TestHelpers, type: :view config.include Paperclip::Shoulda::Matchers + + config.before :each, type: :feature do + https = ENV['LOCAL_HTTPS'] == 'true' + Capybara.app_host = "http#{https ? 's' : ''}://#{ENV.fetch('LOCAL_DOMAIN')}" + end end RSpec::Sidekiq.configure do |config| From fe8dd58bc1548b59741d30d9b3ce46f08b6afcd8 Mon Sep 17 00:00:00 2001 From: Patrick Figel Date: Sat, 15 Apr 2017 01:23:49 +0200 Subject: [PATCH 06/49] Add list of muted user to UI and Getting Started (#1799) Add the same UI that already exists for blocked users for muted ones and add it to the "Getting Started" menu. --- .../javascripts/components/actions/mutes.jsx | 82 +++++++++++++++++++ .../components/components/account.jsx | 13 ++- .../components/containers/mastodon.jsx | 2 + .../features/getting_started/index.jsx | 2 + .../components/features/mutes/index.jsx | 68 +++++++++++++++ .../javascripts/components/locales/en.jsx | 2 + .../components/reducers/accounts.jsx | 6 ++ .../components/reducers/user_lists.jsx | 11 ++- 8 files changed, 183 insertions(+), 3 deletions(-) create mode 100644 app/assets/javascripts/components/actions/mutes.jsx create mode 100644 app/assets/javascripts/components/features/mutes/index.jsx diff --git a/app/assets/javascripts/components/actions/mutes.jsx b/app/assets/javascripts/components/actions/mutes.jsx new file mode 100644 index 00000000..82482159 --- /dev/null +++ b/app/assets/javascripts/components/actions/mutes.jsx @@ -0,0 +1,82 @@ +import api, { getLinks } from '../api' +import { fetchRelationships } from './accounts'; + +export const MUTES_FETCH_REQUEST = 'MUTES_FETCH_REQUEST'; +export const MUTES_FETCH_SUCCESS = 'MUTES_FETCH_SUCCESS'; +export const MUTES_FETCH_FAIL = 'MUTES_FETCH_FAIL'; + +export const MUTES_EXPAND_REQUEST = 'MUTES_EXPAND_REQUEST'; +export const MUTES_EXPAND_SUCCESS = 'MUTES_EXPAND_SUCCESS'; +export const MUTES_EXPAND_FAIL = 'MUTES_EXPAND_FAIL'; + +export function fetchMutes() { + return (dispatch, getState) => { + dispatch(fetchMutesRequest()); + + api(getState).get('/api/v1/mutes').then(response => { + const next = getLinks(response).refs.find(link => link.rel === 'next'); + dispatch(fetchMutesSuccess(response.data, next ? next.uri : null)); + dispatch(fetchRelationships(response.data.map(item => item.id))); + }).catch(error => dispatch(fetchMutesFail(error))); + }; +}; + +export function fetchMutesRequest() { + return { + type: MUTES_FETCH_REQUEST + }; +}; + +export function fetchMutesSuccess(accounts, next) { + return { + type: MUTES_FETCH_SUCCESS, + accounts, + next + }; +}; + +export function fetchMutesFail(error) { + return { + type: MUTES_FETCH_FAIL, + error + }; +}; + +export function expandMutes() { + return (dispatch, getState) => { + const url = getState().getIn(['user_lists', 'mutes', 'next']); + + if (url === null) { + return; + } + + dispatch(expandMutesRequest()); + + api(getState).get(url).then(response => { + const next = getLinks(response).refs.find(link => link.rel === 'next'); + dispatch(expandMutesSuccess(response.data, next ? next.uri : null)); + dispatch(fetchRelationships(response.data.map(item => item.id))); + }).catch(error => dispatch(expandMutesFail(error))); + }; +}; + +export function expandMutesRequest() { + return { + type: MUTES_EXPAND_REQUEST + }; +}; + +export function expandMutesSuccess(accounts, next) { + return { + type: MUTES_EXPAND_SUCCESS, + accounts, + next + }; +}; + +export function expandMutesFail(error) { + return { + type: MUTES_EXPAND_FAIL, + error + }; +}; diff --git a/app/assets/javascripts/components/components/account.jsx b/app/assets/javascripts/components/components/account.jsx index 8ce9b192..6fda5915 100644 --- a/app/assets/javascripts/components/components/account.jsx +++ b/app/assets/javascripts/components/components/account.jsx @@ -10,7 +10,8 @@ const messages = defineMessages({ follow: { id: 'account.follow', defaultMessage: 'Follow' }, unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' }, requested: { id: 'account.requested', defaultMessage: 'Awaiting approval' }, - unblock: { id: 'account.unblock', defaultMessage: 'Unblock' } + unblock: { id: 'account.unblock', defaultMessage: 'Unblock' }, + unmute: { id: 'account.unmute', defaultMessage: 'Unmute' } }); const buttonsStyle = { @@ -25,6 +26,7 @@ const Account = React.createClass({ me: React.PropTypes.number.isRequired, onFollow: React.PropTypes.func.isRequired, onBlock: React.PropTypes.func.isRequired, + onMute: React.PropTypes.func.isRequired, intl: React.PropTypes.object.isRequired }, @@ -38,6 +40,10 @@ const Account = React.createClass({ this.props.onBlock(this.props.account); }, + handleMute () { + this.props.onMute(this.props.account); + }, + render () { const { account, me, intl } = this.props; @@ -51,11 +57,14 @@ const Account = React.createClass({ const following = account.getIn(['relationship', 'following']); const requested = account.getIn(['relationship', 'requested']); const blocking = account.getIn(['relationship', 'blocking']); + const muting = account.getIn(['relationship', 'muting']); if (requested) { buttons = } else if (blocking) { - buttons = ; + buttons = ; + } else if (muting) { + buttons = ; } else { buttons = ; } diff --git a/app/assets/javascripts/components/containers/mastodon.jsx b/app/assets/javascripts/components/containers/mastodon.jsx index 5cd72782..f1038bbe 100644 --- a/app/assets/javascripts/components/containers/mastodon.jsx +++ b/app/assets/javascripts/components/containers/mastodon.jsx @@ -37,6 +37,7 @@ import FollowRequests from '../features/follow_requests'; import GenericNotFound from '../features/generic_not_found'; import FavouritedStatuses from '../features/favourited_statuses'; import Blocks from '../features/blocks'; +import Mutes from '../features/mutes'; import Report from '../features/report'; import { IntlProvider, addLocaleData } from 'react-intl'; import en from 'react-intl/locale-data/en'; @@ -171,6 +172,7 @@ const Mastodon = React.createClass({ + diff --git a/app/assets/javascripts/components/features/getting_started/index.jsx b/app/assets/javascripts/components/features/getting_started/index.jsx index 05bfcc22..6167d7cf 100644 --- a/app/assets/javascripts/components/features/getting_started/index.jsx +++ b/app/assets/javascripts/components/features/getting_started/index.jsx @@ -14,6 +14,7 @@ const messages = defineMessages({ sign_out: { id: 'navigation_bar.logout', defaultMessage: 'Logout' }, favourites: { id: 'navigation_bar.favourites', defaultMessage: 'Favourites' }, blocks: { id: 'navigation_bar.blocks', defaultMessage: 'Blocked users' }, + mutes: { id: 'navigation_bar.mutes', defaultMessage: 'Muted users' }, info: { id: 'navigation_bar.info', defaultMessage: 'Extended information' } }); @@ -37,6 +38,7 @@ const GettingStarted = ({ intl, me }) => { {followRequests} + diff --git a/app/assets/javascripts/components/features/mutes/index.jsx b/app/assets/javascripts/components/features/mutes/index.jsx new file mode 100644 index 00000000..698b5408 --- /dev/null +++ b/app/assets/javascripts/components/features/mutes/index.jsx @@ -0,0 +1,68 @@ +import { connect } from 'react-redux'; +import PureRenderMixin from 'react-addons-pure-render-mixin'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import LoadingIndicator from '../../components/loading_indicator'; +import { ScrollContainer } from 'react-router-scroll'; +import Column from '../ui/components/column'; +import ColumnBackButtonSlim from '../../components/column_back_button_slim'; +import AccountContainer from '../../containers/account_container'; +import { fetchMutes, expandMutes } from '../../actions/mutes'; +import { defineMessages, injectIntl } from 'react-intl'; + +const messages = defineMessages({ + heading: { id: 'column.mutes', defaultMessage: 'Muted users' } +}); + +const mapStateToProps = state => ({ + accountIds: state.getIn(['user_lists', 'mutes', 'items']) +}); + +const Mutes = React.createClass({ + propTypes: { + params: React.PropTypes.object.isRequired, + dispatch: React.PropTypes.func.isRequired, + accountIds: ImmutablePropTypes.list, + intl: React.PropTypes.object.isRequired + }, + + mixins: [PureRenderMixin], + + componentWillMount () { + this.props.dispatch(fetchMutes()); + }, + + handleScroll (e) { + const { scrollTop, scrollHeight, clientHeight } = e.target; + + if (scrollTop === scrollHeight - clientHeight) { + this.props.dispatch(expandMutes()); + } + }, + + render () { + const { intl, accountIds } = this.props; + + if (!accountIds) { + return ( + + + + ); + } + + return ( + + + +
+ {accountIds.map(id => + + )} +
+
+
+ ); + } +}); + +export default connect(mapStateToProps)(injectIntl(Mutes)); diff --git a/app/assets/javascripts/components/locales/en.jsx b/app/assets/javascripts/components/locales/en.jsx index 47e23d98..5dccb807 100644 --- a/app/assets/javascripts/components/locales/en.jsx +++ b/app/assets/javascripts/components/locales/en.jsx @@ -31,6 +31,7 @@ const en = { "column.favourites": "Favourites", "column.follow_requests": "Follow requests", "column.home": "Home", + "column.mutes": "Muted users", "column.notifications": "Notifications", "column.public": "Federated timeline", "compose_form.placeholder": "What is on your mind?", @@ -68,6 +69,7 @@ const en = { "navigation_bar.follow_requests": "Follow requests", "navigation_bar.info": "Extended information", "navigation_bar.logout": "Logout", + "navigation_bar.mutes": "Muted users", "navigation_bar.preferences": "Preferences", "navigation_bar.public_timeline": "Federated timeline", "notification.favourite": "{name} favourited your status", diff --git a/app/assets/javascripts/components/reducers/accounts.jsx b/app/assets/javascripts/components/reducers/accounts.jsx index df944009..60d283b0 100644 --- a/app/assets/javascripts/components/reducers/accounts.jsx +++ b/app/assets/javascripts/components/reducers/accounts.jsx @@ -15,6 +15,10 @@ import { BLOCKS_FETCH_SUCCESS, BLOCKS_EXPAND_SUCCESS } from '../actions/blocks'; +import { + MUTES_FETCH_SUCCESS, + MUTES_EXPAND_SUCCESS +} from '../actions/mutes'; import { COMPOSE_SUGGESTIONS_READY } from '../actions/compose'; import { REBLOG_SUCCESS, @@ -94,6 +98,8 @@ export default function accounts(state = initialState, action) { case FOLLOW_REQUESTS_EXPAND_SUCCESS: case BLOCKS_FETCH_SUCCESS: case BLOCKS_EXPAND_SUCCESS: + case MUTES_FETCH_SUCCESS: + case MUTES_EXPAND_SUCCESS: return normalizeAccounts(state, action.accounts); case NOTIFICATIONS_REFRESH_SUCCESS: case NOTIFICATIONS_EXPAND_SUCCESS: diff --git a/app/assets/javascripts/components/reducers/user_lists.jsx b/app/assets/javascripts/components/reducers/user_lists.jsx index 8c9a3d3a..7f55c364 100644 --- a/app/assets/javascripts/components/reducers/user_lists.jsx +++ b/app/assets/javascripts/components/reducers/user_lists.jsx @@ -16,6 +16,10 @@ import { BLOCKS_FETCH_SUCCESS, BLOCKS_EXPAND_SUCCESS } from '../actions/blocks'; +import { + MUTES_FETCH_SUCCESS, + MUTES_EXPAND_SUCCESS +} from '../actions/mutes'; import Immutable from 'immutable'; const initialState = Immutable.Map({ @@ -24,7 +28,8 @@ const initialState = Immutable.Map({ reblogged_by: Immutable.Map(), favourited_by: Immutable.Map(), follow_requests: Immutable.Map(), - blocks: Immutable.Map() + blocks: Immutable.Map(), + mutes: Immutable.Map() }); const normalizeList = (state, type, id, accounts, next) => { @@ -65,6 +70,10 @@ export default function userLists(state = initialState, action) { return state.setIn(['blocks', 'items'], Immutable.List(action.accounts.map(item => item.id))).setIn(['blocks', 'next'], action.next); case BLOCKS_EXPAND_SUCCESS: return state.updateIn(['blocks', 'items'], list => list.push(...action.accounts.map(item => item.id))).setIn(['blocks', 'next'], action.next); + case MUTES_FETCH_SUCCESS: + return state.setIn(['mutes', 'items'], Immutable.List(action.accounts.map(item => item.id))).setIn(['mutes', 'next'], action.next); + case MUTES_EXPAND_SUCCESS: + return state.updateIn(['mutes', 'items'], list => list.push(...action.accounts.map(item => item.id))).setIn(['mutes', 'next'], action.next); default: return state; } From 8482f67cafabbd747126238c03853f251e0dce56 Mon Sep 17 00:00:00 2001 From: Alex Dunn Date: Fri, 14 Apr 2017 17:05:41 -0700 Subject: [PATCH 07/49] update Node to 6.x LTS (#1228) The 4.x branch [entered maintenance](https://github.com/nodejs/LTS#lts-schedule1) on 1 April. --- .nvmrc | 2 +- .travis.yml | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/.nvmrc b/.nvmrc index f0e13c50..1e8b3149 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -6.7.0 +6 diff --git a/.travis.yml b/.travis.yml index a9824ccf..45a71d83 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,8 +5,6 @@ notifications: email: false env: - matrix: - - TRAVIS_NODE_VERSION="4" global: - LOCAL_DOMAIN=cb6e6126.ngrok.io - LOCAL_HTTPS=true @@ -28,8 +26,7 @@ before_install: - sudo apt-get -qq update - sudo apt-get -qq install g++-4.8 install: - - nvm install $TRAVIS_NODE_VERSION - - npm install -g npm@3 + - nvm install - npm install -g yarn - bundle install - yarn install From 5ab0ffc6c8ae37d95b559ed0a9f2b926490e1d59 Mon Sep 17 00:00:00 2001 From: Valentin Lorentz Date: Sat, 15 Apr 2017 02:07:21 +0200 Subject: [PATCH 08/49] Custom Paperclip path. (#778) * Custom Paperclip path. * Document PAPERCLIP_ROOT. * Add PAPERCLIP_ROOT_URL (and rename PAPERCLIP_ROOT to PAPERCLIP_ROOT_PATH). --- .env.production.sample | 4 ++++ config/initializers/paperclip.rb | 3 +++ 2 files changed, 7 insertions(+) diff --git a/.env.production.sample b/.env.production.sample index 7c82c014..fd2f7116 100644 --- a/.env.production.sample +++ b/.env.production.sample @@ -41,6 +41,10 @@ SMTP_FROM_ADDRESS=notifications@example.com #SMTP_ENABLE_STARTTLS_AUTO=true +# Optional user upload path and URL (images, avatars). Default is :rails_root/public/system. If you set this variable, you are responsible for making your HTTP server (eg. nginx) serve these files. +# PAPERCLIP_ROOT_PATH=/var/lib/mastodon/public-system +# PAPERCLIP_ROOT_URL=/system + # Optional asset host for multi-server setups # CDN_HOST=assets.example.com diff --git a/config/initializers/paperclip.rb b/config/initializers/paperclip.rb index c58f1b06..202c102c 100644 --- a/config/initializers/paperclip.rb +++ b/config/initializers/paperclip.rb @@ -38,4 +38,7 @@ if ENV['S3_ENABLED'] == 'true' Paperclip::Attachment.default_options[:url] = ':s3_alias_url' Paperclip::Attachment.default_options[:s3_host_alias] = ENV['S3_CLOUDFRONT_HOST'] end +else + Paperclip::Attachment.default_options[:path] = (ENV['PAPERCLIP_ROOT_PATH'] || ':rails_root/public/system') + '/:class/:attachment/:id_partition/:style/:filename' + Paperclip::Attachment.default_options[:url] = (ENV['PAPERCLIP_ROOT_URL'] || '/system') + '/:class/:attachment/:id_partition/:style/:filename' end From 0d2910478a6b1659f4c40e64cf28cf2e64dfb01e Mon Sep 17 00:00:00 2001 From: Pierre Ozoux Date: Sat, 15 Apr 2017 01:07:59 +0100 Subject: [PATCH 09/49] Use image too in docker-compose (#1109) * Use image too in docker-compose It is possible with version 2 of compose to use both `build` and `image` * Update docker-compose.yml --- docker-compose.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docker-compose.yml b/docker-compose.yml index 910bf8cf..81c6fe98 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -18,6 +18,7 @@ services: web: restart: always build: . + image: gargron/mastodon env_file: .env.production command: bundle exec rails s -p 3000 -b '0.0.0.0' ports: @@ -32,6 +33,7 @@ services: streaming: restart: always build: . + image: gargron/mastodon env_file: .env.production command: npm run start ports: @@ -43,6 +45,7 @@ services: sidekiq: restart: always build: . + image: gargron/mastodon env_file: .env.production command: bundle exec sidekiq -q default -q mailers -q pull -q push depends_on: From a9529d3b4b057eeb3b47943b271ad6605e22732d Mon Sep 17 00:00:00 2001 From: ThibG Date: Sat, 15 Apr 2017 02:15:46 +0200 Subject: [PATCH 10/49] Allow running mastodon on a different domain as the one used for identifying users (#1267) * Allow running mastodon on a different domain as the one used for identifying users * Alter documentation of WEB_DOMAIN to make clear it shouldn't be used unless the admin knows what they are doing * Compare to web_domain instead of local_domain when dealing with feeds/API * Correctly identify mentions to local accounts Mentions URLs point to the person's web profile, i.e., the user page served on WEB_DOMAIN. --- .env.production.sample | 4 ++++ app/controllers/api/push_controller.rb | 2 +- app/lib/tag_manager.rb | 4 ++++ app/services/process_feed_service.rb | 2 +- config/initializers/ostatus.rb | 8 +++++--- 5 files changed, 15 insertions(+), 5 deletions(-) diff --git a/.env.production.sample b/.env.production.sample index fd2f7116..1125eedb 100644 --- a/.env.production.sample +++ b/.env.production.sample @@ -11,6 +11,10 @@ DB_PORT=5432 LOCAL_DOMAIN=example.com LOCAL_HTTPS=true +# Use this only if you need to run mastodon on a different domain than the one used for federation. +# Do not use this unless you know exactly what you are doing. +# WEB_DOMAIN=mastodon.example.com + # Application secrets # Generate each with the `rake secret` task (`docker-compose run --rm web rake secret` if you use docker compose) PAPERCLIP_SECRET= diff --git a/app/controllers/api/push_controller.rb b/app/controllers/api/push_controller.rb index 78d4e36e..f2ddfd96 100644 --- a/app/controllers/api/push_controller.rb +++ b/app/controllers/api/push_controller.rb @@ -30,7 +30,7 @@ class Api::PushController < ApiController params = Rails.application.routes.recognize_path(uri.path) domain = uri.host + (uri.port ? ":#{uri.port}" : '') - return unless TagManager.instance.local_domain?(domain) && params[:controller] == 'accounts' && params[:action] == 'show' && params[:format] == 'atom' + return unless TagManager.instance.web_domain?(domain) && params[:controller] == 'accounts' && params[:action] == 'show' && params[:format] == 'atom' Account.find_local(params[:username]) end diff --git a/app/lib/tag_manager.rb b/app/lib/tag_manager.rb index 07b2fb91..f26c943d 100644 --- a/app/lib/tag_manager.rb +++ b/app/lib/tag_manager.rb @@ -56,6 +56,10 @@ class TagManager id.start_with?("tag:#{Rails.configuration.x.local_domain}") end + def web_domain?(domain) + domain.nil? || domain.gsub(/[\/]/, '').casecmp(Rails.configuration.x.web_domain).zero? + end + def local_domain?(domain) domain.nil? || domain.gsub(/[\/]/, '').casecmp(Rails.configuration.x.local_domain).zero? end diff --git a/app/services/process_feed_service.rb b/app/services/process_feed_service.rb index a2def453..321f53f2 100644 --- a/app/services/process_feed_service.rb +++ b/app/services/process_feed_service.rb @@ -163,7 +163,7 @@ class ProcessFeedService < BaseService url = Addressable::URI.parse(link['href']) - mentioned_account = if TagManager.instance.local_domain?(url.host) + mentioned_account = if TagManager.instance.web_domain?(url.host) Account.find_local(url.path.gsub('/users/', '')) else Account.find_by(url: link['href']) || FetchRemoteAccountService.new.call(link['href']) diff --git a/config/initializers/ostatus.rb b/config/initializers/ostatus.rb index fb0b8b7f..155d0a9f 100644 --- a/config/initializers/ostatus.rb +++ b/config/initializers/ostatus.rb @@ -2,18 +2,20 @@ port = ENV.fetch('PORT') { 3000 } host = ENV.fetch('LOCAL_DOMAIN') { "localhost:#{port}" } +web_host = ENV.fetch('WEB_DOMAIN') { host } https = ENV['LOCAL_HTTPS'] == 'true' Rails.application.configure do config.x.local_domain = host + config.x.web_domain = web_host config.x.use_https = https config.x.use_s3 = ENV['S3_ENABLED'] == 'true' - config.action_mailer.default_url_options = { host: host, protocol: https ? 'https://' : 'http://', trailing_slash: false } + config.action_mailer.default_url_options = { host: web_host, protocol: https ? 'https://' : 'http://', trailing_slash: false } config.x.streaming_api_base_url = 'http://localhost:4000' if Rails.env.production? - config.action_cable.allowed_request_origins = ["http#{https ? 's' : ''}://#{host}"] - config.x.streaming_api_base_url = ENV.fetch('STREAMING_API_BASE_URL') { "http#{https ? 's' : ''}://#{host}" } + config.action_cable.allowed_request_origins = ["http#{https ? 's' : ''}://#{web_host}"] + config.x.streaming_api_base_url = ENV.fetch('STREAMING_API_BASE_URL') { "http#{https ? 's' : ''}://#{web_host}" } end end From 7609593e4833e32064313148c616053022274408 Mon Sep 17 00:00:00 2001 From: Les Orchard Date: Fri, 14 Apr 2017 20:21:13 -0400 Subject: [PATCH 11/49] Add REDIS_DB env variable to configure Redis database (#1366) --- .env.production.sample | 1 + config/environments/production.rb | 4 +++- config/initializers/sidekiq.rb | 5 +++-- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/.env.production.sample b/.env.production.sample index 1125eedb..9011dc21 100644 --- a/.env.production.sample +++ b/.env.production.sample @@ -1,6 +1,7 @@ # Service dependencies REDIS_HOST=redis REDIS_PORT=6379 +# REDIS_DB=0 DB_HOST=db DB_USER=postgres DB_NAME=postgres diff --git a/config/environments/production.rb b/config/environments/production.rb index 0f107654..80021287 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -55,6 +55,8 @@ Rails.application.configure do ENV['REDIS_HOST'] = redis_url.host ENV['REDIS_PORT'] = redis_url.port.to_s ENV['REDIS_PASSWORD'] = redis_url.password + db_num = redis_url.path[1..-1] + ENV['REDIS_DB'] = db_num if db_num.present? end # Use a different cache store in production. @@ -62,7 +64,7 @@ Rails.application.configure do host: ENV.fetch('REDIS_HOST') { 'localhost' }, port: ENV.fetch('REDIS_PORT') { 6379 }, password: ENV.fetch('REDIS_PASSWORD') { false }, - db: 0, + db: ENV.fetch('REDIS_DB') { 0 }, namespace: 'cache', expires_in: 10.minutes, } diff --git a/config/initializers/sidekiq.rb b/config/initializers/sidekiq.rb index ecdd07b0..8ae3bd5a 100644 --- a/config/initializers/sidekiq.rb +++ b/config/initializers/sidekiq.rb @@ -1,11 +1,12 @@ host = ENV.fetch('REDIS_HOST') { 'localhost' } port = ENV.fetch('REDIS_PORT') { 6379 } password = ENV.fetch('REDIS_PASSWORD') { false } +db = ENV.fetch('REDIS_DB') { 0 } Sidekiq.configure_server do |config| - config.redis = { host: host, port: port, password: password} + config.redis = { host: host, port: port, db: db, password: password } end Sidekiq.configure_client do |config| - config.redis = { host: host, port: port, password: password } + config.redis = { host: host, port: port, db: db, password: password } end From ade004b5ee8dbd3bb7286eba7bab599f848985b4 Mon Sep 17 00:00:00 2001 From: rysiekpl Date: Sat, 15 Apr 2017 02:22:46 +0200 Subject: [PATCH 12/49] Polish translation (needs more love though) (#807) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Polish translation (needs more love though) * Polish translation bugfix * bugfix for new colon-containing texts * another bugfix. yaml is evil * minor fix * fixing issues pointed out by reviewers * Uwierzytelnianie dwustopniowe -> dwuetapowe, as suggested by a reviewer * Etyczny dizajn zbyt sarkastyczny, to będą założenia --- config/locales/devise.pl.yml | 61 +++++++++++ config/locales/doorkeeper.pl.yml | 113 ++++++++++++++++++++ config/locales/pl.yml | 164 ++++++++++++++++++++++++++++++ config/locales/simple_form.pl.yml | 46 +++++++++ 4 files changed, 384 insertions(+) create mode 100644 config/locales/devise.pl.yml create mode 100644 config/locales/doorkeeper.pl.yml create mode 100644 config/locales/pl.yml create mode 100644 config/locales/simple_form.pl.yml diff --git a/config/locales/devise.pl.yml b/config/locales/devise.pl.yml new file mode 100644 index 00000000..d4ee1b6a --- /dev/null +++ b/config/locales/devise.pl.yml @@ -0,0 +1,61 @@ +--- +pl: + devise: + confirmations: + confirmed: Twój adres e-mail został poprawnie zweryfikowany. + send_instructions: W ciągu kilku minut otrzymasz wiadomosć e-mail z instrukcją jak potwierdzić Twój adres e-mail. + send_paranoid_instructions: Jeśli Twój adres e-mail już istnieje w naszej bazie danych, w ciągu kilku minut otrzymasz wiadomość e-mail z instrukcją jak potwierdzić Twój adres e-mail. + failure: + already_authenticated: Jesteś już zalogowany/zalogowana. + inactive: Twoje konto nie zostało jeszcze aktywowane. + invalid: Błędne %{authentication_keys} lub hasło. + last_attempt: Masz jeszcze jedną próbę; Twoje konto zostanie zablokowane jeśli się nie powiedzie. + locked: Twoje konto zostało zablokowane. + not_found_in_database: Błędne %{authentication_keys} lub hasło. + timeout: Twoja sesja wygasła. Zaloguj się ponownie aby kontynuować.. + unauthenticated: Zapisz się lub zaloguj aby kontynuować. + unconfirmed: Zweryfikuj adres e-mail aby kontynuować. + mailer: + confirmation_instructions: + subject: 'Mastodon: Instrukcje weryfikacji adresu e-mail' + password_change: + subject: 'Mastodon: Hasło zmienione' + reset_password_instructions: + subject: 'Mastodon: Instrukcje ustawienia nowego hasła' + unlock_instructions: + subject: 'Mastodon: Instrukcje odblokowania konta' + omniauth_callbacks: + failure: 'Uwierzytelnienie przez %{kind} nie powiodło się, ponieważ: "%{reason}".' + success: Uwierzytelnienie przez %{kind} powiodło się. + passwords: + no_token: Dostęp do tej strony możliwy jest wyłącznie za pomocą odnośnika z e-maila z instrukcjami ustawienia nowego hasła. Jeśli skorzystałeś/aś z takiego odnośnika, upewnij się, że został wykorzystany/skopiowany cały odnośnik. + send_instructions: W ciągu kilku minut otrzymasz wiadomość e-mail z instrukcją ustawienia nowego hasła. + send_paranoid_instructions: Jeśli Twój adres e-mail już istnieje w naszej bazie danych, w ciągu kilku minut otrzymasz wiadomość e-mail zawierającą odnośnik pozwalający na ustawienie nowego hasła. + updated: Twoje hasło zostało zmienione. Jesteś zalogowany/a. + updated_not_active: Twoje hasło zostało zmienione. + registrations: + destroyed: Twoje konto zostało anulowane. Mamy jednak nadzieję, że do nas wrócisz. Do zobaczenia! + signed_up: Twoje konto zostało utworzone. Witamy! + signed_up_but_inactive: Twoje konto zostało utworzone. Nie mogliśmy Cię jednak zalogować, ponieważ konto nie zostało jeszcze aktywowane. + signed_up_but_locked: Twoje konto zostało utworzone. Nie mogliśmy Cię jednak zalogować, ponieważ konto jest zablokowane. + signed_up_but_unconfirmed: Na Twój adres e-mail została wysłana wiadomosć z odnośnikiem potwierdzającym. Kliknij w odnośnik aby aktywować konto. + update_needs_confirmation: Konto zostało zaktualizowane, musimy jednak zweryfikować Twój nowy adres e-mail. Została na niego wysłana wiadomość z odnośnikiem potwierdzającym. + updated: Konto zostało zaktualizowane. + sessions: + already_signed_out: Zostałeś/aś wylogowany/a. + signed_in: Zostałeś/aś zalogowany/a. + signed_out: Zostałeś/aś wylogowany/a. + unlocks: + send_instructions: W ciągu kilku minut otrzymasz wiadomość e-mail z instrukcjami odblokowania konta. + send_paranoid_instructions: Jeśli Twoje konto istnieje, instrukcje odblokowania go otrzymasz w wiadomości e-mail w ciągu kilku minut. + unlocked: Twoje konto zostało odblokowane. Zaloguj się aby kontynuować. + errors: + messages: + already_confirmed: był już potwierdzony, spróbuj się zalogować + confirmation_period_expired: musi być potwierdzony w ciągu %{period}, poproś o nowe potwierdzenie + expired: wygasło, poproś o nowe + not_found: nie znaleziono + not_locked: było zablokowane + not_saved: + one: '1 błąd uniemożliwił zapisanie zasobu %{resource}:' + other: "Błędy (%{count}) uniemożliwiły zapisanie zasobu %{resource}:" diff --git a/config/locales/doorkeeper.pl.yml b/config/locales/doorkeeper.pl.yml new file mode 100644 index 00000000..8103c456 --- /dev/null +++ b/config/locales/doorkeeper.pl.yml @@ -0,0 +1,113 @@ +--- +pl: + activerecord: + attributes: + doorkeeper/application: + name: Nazwa + redirect_uri: URI przekierowania + errors: + models: + doorkeeper/application: + attributes: + redirect_uri: + fragment_present: nie może zawierać fragmentu. + invalid_uri: musi być poprawnym adresem URI. + relative_uri: musi być bezwzględnym adresem URI. + secured_uri: musi być bezpiecznym (HTTPS/TLS) adresem URI. + doorkeeper: + applications: + buttons: + authorize: Autoryzuj + cancel: Anuluj + destroy: Usuń + edit: Edytuj + submit: Wyślij + confirmations: + destroy: Czy na pewno? + edit: + title: Edytuj aplikację + form: + error: Ups! Sprawdź, czy formularz nie zawiera błędów + help: + native_redirect_uri: Użyj %{native_redirect_uri} do lokalnych testów + redirect_uri: Jeden adres na linię tekstu + scopes: Rozdziel zakresy (scopes) spacjami. Zostaw puste aby użyć domyślnych zakresów. + index: + callback_url: URL wywołania zwrotnego (callback) + name: Nazwa + new: Nowa aplikacja + title: Twoje aplikacje + new: + title: Nowa aplikacja + show: + actions: Akcje + application_id: ID Aplikacji + callback_urls: Adresy wywołań zwrotnych + scopes: Zakresy (scopes) + secret: Sekret + title: 'Aplikacja: %{name}' + authorizations: + buttons: + authorize: Autoryzuj + deny: Odmów + error: + title: Wystapił błąd + new: + able_to: Będzie w stanie + prompt: Aplikacja %{client_name} prosi o dostęp do Twojego konta + title: Wymagana jest autoryzacja + show: + title: Kod autoryzacji + authorized_applications: + buttons: + revoke: Unieważnij + confirmations: + revoke: Czy na pewno? + index: + application: Aplikacja + created_at: Autoryzowana + date_format: "%d.%m.%Y %H:%M:%S" + scopes: Zakresy + title: Twoje autoryzowane aplikacje + errors: + messages: + access_denied: Właściciel zasobu lub serwer autoryzujący odrzuciły żądanie. + credential_flow_not_configured: Ścieżka "Resource Owner Password Credentials" zakończyła się błędem, ponieważ Doorkeeper.configure.resource_owner_from_credentials nie jest skonfigurowany. + invalid_client: Autoryzacja klienta nie powiodła się z powodu nieznanego klienta, braku uwierzytelnienia klienta, lub niewspieranej metody uwierzytelniania. + invalid_grant: Grant uwierzytelnienia jest niepoprawny, przeterminowany, unieważniony, nie pasuje do URI przekierowwania użytego w żądaniu uwierzytelnienia, lub został wystawiony przez innego klienta. + invalid_redirect_uri: URI przekierowania jest nieprawidłowy. + invalid_request: 'Żądanie jest nieprawidłowe: brakujący parametr, niewspierana wartość parametru, lub inny błąd.' + invalid_resource_owner: Dostarczone dane uwierzytelniające właściciela zasobu są niepoprawne, lub właściciel zasobu nie może zostać znaleziony. + invalid_scope: Zakres żądania jest niepoprawny, nieznany, lub błędnie zbudowany. + invalid_token: + expired: Token dostępowy wygasł + revoked: Token dostępowy został unieważniony + unknown: Token dostępowy jest błędny + resource_owner_authenticator_not_configured: Wyszukiwanie właściciela zasobu nie powiodło się, ponieważ Doorkeeper.configure.resource_owner_authenticator jest nieskonfigurowany. + server_error: Serwer uwierzytelniający napotkał niespodziewane warunki, które uniemożliwiły obsłużenie żądania. + temporarily_unavailable: Serwer uwierzytelniający nie jest obecnie w stanie obsłużyć żądania z powodu tymczasowego przeciążenia lub prac konserwacyjnych. + unauthorized_client: Klient nie jest uprawniony do wykonania tego żądania przy pomocy tej metody. + unsupported_grant_type: Ten typ grantu uwierzytelniającego nie jest wspierany przez serwer uwierzytelniający. + unsupported_response_type: Serwer uwierzytelniający nie wspiera tego typu odpowiedzi. + flash: + applications: + create: + notice: Aplikacja utworzona. + destroy: + notice: Aplikacja usunięta. + update: + notice: Aplikacja zaktualizowana. + authorized_applications: + destroy: + notice: Aplikacja unieważniona. + layouts: + admin: + nav: + applications: Aplikacje + oauth2_provider: Dostawca OAuth2 + application: + title: Uwierzytelnienie OAuth jest wymagane + scopes: + follow: śledzenie, blokowanie, usuwanie blokady, anulowanie śledzenia kont + read: dostęp do odczytu danych konta + write: publikowanie postów w Twoim imieniu diff --git a/config/locales/pl.yml b/config/locales/pl.yml new file mode 100644 index 00000000..3c4c98bc --- /dev/null +++ b/config/locales/pl.yml @@ -0,0 +1,164 @@ +--- +pl: + about: + about_mastodon: Mastodon jest wolną i otwartą siecią społecznościową, zdecentralizowaną alternatywą dla zamkniętych, komercyjnych platform. Pozwala uniknąć ryzyka monopolizacji Twojej komunikacji przez jedną korporację. Wybierz serwer, któremu ufasz — nie ograniczy to Twoich możliwości komunikacji z innymi osobami w sieci. Każdy może też uruchomić własną instancję Mastodona i dołączyć do reszty tej sieci społecznościowej. + about_this: O tej instancji + apps: Aplikacje + business_email: 'Służbowy adres e-mail:' + contact: Kontakt + description_headline: Czym jest %{domain}? + domain_count_after: inne instancje + domain_count_before: Połączone z + features: + api: Otwarte API dla aplikacji i usług + blocks: Rozbudowane narzędzia blokowania i wyciszania + characters: 500 znaków na wpis + chronology: Chronologiczny porządek wyświetlania + ethics: 'Etyczne założenia: bez reklam, bez śledzenia' + gifv: obsługa GIFV i krótkich wideo + privacy: Precyzyjne ustawienia widoczności poszczególnych postów + public: Publiczne osie czasu + features_headline: Co wyróżnia Mastodona + get_started: Rozpocznijmy! + links: Odnośniki + other_instances: Inne instancje + source_code: Kod źródłowy + status_count_after: wpisów + status_count_before: Kto jest autorem + terms: Regulamin + user_count_after: tootujących + user_count_before: Dom dla + accounts: + follow: Śledź + followers: Śledzących + following: Śledzi + nothing_here: Niczego tu nie ma! + people_followed_by: Konta śledzone przez %{name} + people_who_follow: Osoby, które śledzą konto %{name} + posts: Wpisy + remote_follow: Zdalne śledzenie + unfollow: Przestań śledzić + application_mailer: + settings: 'Zmień ustawienia powiadamiania: %{link}' + signature: Powiadomienie Mastodona, wysłane przez %{instance} + view: 'Zobacz:' + applications: + invalid_url: Ten URL jest nieprawidłowy + auth: + change_password: Uwierzytelnienie + didnt_get_confirmation: Nie otrzymałeś instrukcji weryfikacji? + forgot_password: Zapomniane hasło + login: Zaloguj się + logout: Wyloguj się + register: Rejestracja + resend_confirmation: Ponownie prześlij instrukcje weryfikacji + reset_password: Zresetuj hasło + set_new_password: Ustaw nowe hasło + authorize_follow: + error: Niestety, podczas sprawdzania zdalnego konta wystąpił błąd + follow: Śledź + prompt_html: 'Ty (%{self}) chcesz śledzić:' + title: Śledź %{acct} + datetime: + distance_in_words: + about_x_hours: "%{count}h" + about_x_months: "%{count} miesięcy" + about_x_years: "%{count} lat" + almost_x_years: "%{count} lat" + half_a_minute: Przed chwilą + less_than_x_minutes: "%{count}min" + less_than_x_seconds: Przed chwilą + over_x_years: "%{count} lat" + x_days: "%{count} dni" + x_minutes: "%{count}min" + x_months: "%{count} miesięcy" + x_seconds: "%{count}s" + exports: + blocks: Blokujesz + csv: CSV + follows: Śledzisz + storage: Media storage + generic: + changes_saved_msg: Ustawienia zapisane! + powered_by: uruchomione na %{link} + save_changes: Zapisz zmiany + validation_errors: + one: Coś jest wciąż nie tak! Przyjrzyj się błędowi poniżej + other: Coś jest wciąż nie tak! Przejrzyj błędy (%{count}) poniżej + imports: + preface: Możesz zaimportować pewne dane (jak dane kont, które śledzisz lub blokujesz) do swojego konta na tym serwerze, korzystająć z danych wyeksportowanych z innego serwera. + success: Twoje dane zostały załadowane i zostaną niebawem przetworzone + types: + blocking: Lista blokowanych + following: Lista śledzonych + upload: Załaduj + landing_strip_html: %{name} ma konto na %{domain}. Możesz je śledzić i wejść z nim w interakcję jeśli masz konto gdziekolwiek w Fediwersie. Jeśli jeszcze go nie masz, możesz stworzyć konto. + notification_mailer: + digest: + body: 'Oto krótkie podsumowanie co Cię ominęło na %{instance} od Twojej ostatniej wizyty (%{since}):' + mention: "%{name} wspomniał o Tobie w:" + new_followers_summary: + one: Śledzi Cię nowa osoba! Gratulacje! + other: Kilka (%{count}) nowych osób Cię śledzi! Wspaniale! + subject: + one: "1 nowe powiadomienie od Twojej ostatniej wizyty \U0001F418" + other: "%{count} nowych powiadomień od Twojej ostatniej wizyty \U0001F418" + favourite: + body: 'Twój wpis został polubiony przez %{name}:' + subject: "%{name} lubi Twój wpis" + follow: + body: "%{name} Cię śledzi!" + subject: "%{name} Cię śledzi" + follow_request: + body: "%{name} poprosił o możliwość śledzenia Cię" + subject: 'Prośba o możliwość śledzenia: %{name}' + mention: + body: '%{name} wspomniał Cię w:' + subject: '%{name} Cię wspomniał' + reblog: + body: 'Twój wpis został podbity przez %{name}:' + subject: "Twój wpis został podbity przez %{name}" + pagination: + next: Następna + prev: Poprzednia + remote_follow: + acct: Podaj swój adres (nazwa@domena), z którego chcesz śledzić + missing_resource: Nie udało się znaleźć adresu przekierowania z Twojej domeny + proceed: Śledź + prompt: 'Śledzony będzie:' + settings: + authorized_apps: Uwierzytelnione aplikacje + back: Powrót do Mastodona + edit_profile: Edytuj profil + export: Exportuj dane + import: Importuj dane + preferences: Preferencje + settings: Ustawienia + two_factor_auth: Uwierzytelnianie dwuetapowe + statuses: + open_in_web: Otwórz w przeglądarce + over_character_limit: limit %{max} znaków przekroczony + show_more: Pokaż więcej + visibilities: + private: Tylko dla śledzących + public: Publiczny + unlisted: Publiczny, ale nie wyświetlaj na publicznych osiach czasu + stream_entries: + click_to_show: Kliknij aby pokazać + reblogged: podbity + sensitive_content: Wrażliwa treść + time: + formats: + default: "%b %d, %Y, %H:%M" + two_factor_auth: + description_html: Jeśli włączysz uwierzytelnianie dwustopniowe, logowanie się będzie wymagało podania tokenu wyświetlonego na Twoim telefone. + disable: Wyłącz + enable: Włącz + instructions_html: "Zeskanuj ten kod QR na swoim urządzeniu za pomocą Google Authenticator, FreeOTP lub podobnej aplikacji. Od teraz będzie ona generowała kody wymagane przy logowaniu." + plaintext_secret_html: 'Sekret: %{secret}' + warning: Jeśli nie jesteś w stanie skonfigurować aplikacji uwierzytelniania dwustopniowego w tej chwili, wyłącz uwierzytelnianie dwustopniowe. W przeciwnym wypadku nie będziesz się w stanie zalogować! + users: + invalid_email: Adres e-mail jest niepoprawny + invalid_otp_token: Kod uwierzytelniający jest niepoprawny + will_paginate: + page_gap: "…" diff --git a/config/locales/simple_form.pl.yml b/config/locales/simple_form.pl.yml new file mode 100644 index 00000000..19121c4d --- /dev/null +++ b/config/locales/simple_form.pl.yml @@ -0,0 +1,46 @@ +--- +pl: + simple_form: + hints: + defaults: + avatar: PNG, GIF lub JPG. Najwyżej 2MB. Zostanie zmniejszone do 120x120px + display_name: Najwyżej 30 znaków + header: PNG, GIF lub JPG. Najwyżej 2MB. Zostanie zmniejszone do 700x335px + locked: Śledzenie Cię wymaga Twojego potwierdzenia; Twoje wpisy są domyślnie widoczne tylko dla śledzących Cię. + note: Najwyżej 160 znaków + imports: + data: Plik CSV wyeksportowany z innej instancji Mastodona + labels: + defaults: + avatar: Awatar + confirm_new_password: Potwierdź nowe hasło + confirm_password: Potwierdź hasło + current_password: Obecne hasło + data: Dane + display_name: Widoczna nazwa + email: Adres e-mail + header: Nagłówek + locale: Język + locked: Ustaw konto jako prywatne + new_password: Nowe hasło + note: Biogram + otp_attempt: Kod uwierzytelnienia dwustopniowego + password: Hasło + setting_default_privacy: Widoczność posta + type: Typ importu + username: Nazwa użytkownika + interactions: + must_be_follower: Zablokuj powiadomienia od osób, które Cię nie śledzą + must_be_following: Zablokuj powiadomienia od osób, których nie śledzisz + notification_emails: + digest: Wysyłaj podsumowania e-mailem + favourite: Powiadom mnie e-mailem gdy ktoś polubi mój status. + follow: Powiadom mnie e-mailem gdy ktoś zacznie mnie śledzić. + follow_request: Powiadom mnie e-mailem gdy ktoś poprosi o pozwolenie śledzenia mnie. + mention: Powiadom mnie e-mailem gdy ktoś mnie wspomni. + reblog: Powiadom mnie e-mailem gdy ktoś podbije mój status. + 'no': 'Nie' + required: + mark: "*" + text: pole wymagane + 'yes': 'Tak' From 0655f16cc1f97f63e792e8c6463d50493e1deb69 Mon Sep 17 00:00:00 2001 From: Alex Dunn Date: Fri, 14 Apr 2017 17:29:32 -0700 Subject: [PATCH 13/49] [css] reduce spacing between text elements on about pages (#1510) --- app/assets/stylesheets/about.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/about.scss b/app/assets/stylesheets/about.scss index 8bf950d4..4bd4c26d 100644 --- a/app/assets/stylesheets/about.scss +++ b/app/assets/stylesheets/about.scss @@ -64,7 +64,7 @@ p, li { font: 16px/28px 'Montserrat', sans-serif; font-weight: 400; - margin-bottom: 26px; + margin-bottom: 12px; a { color: $color4; @@ -352,7 +352,7 @@ } } } - + @media screen and (max-width: 625px) { .mascot { display: none; From 619817d29e928bfac8eae50cfb6be93c5657e24c Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Fri, 14 Apr 2017 20:30:55 -0400 Subject: [PATCH 14/49] Remove unused will_paginate.page_gap key from i18n (#1815) This value was changed recently, and every locale which had it set was using the same value as the default. This value is still the default in the new location. --- config/locales/bg.yml | 2 -- config/locales/en.yml | 2 -- config/locales/fr.yml | 2 -- config/locales/hr.yml | 2 -- config/locales/ja.yml | 2 -- config/locales/nl.yml | 2 -- config/locales/ru.yml | 2 -- 7 files changed, 14 deletions(-) diff --git a/config/locales/bg.yml b/config/locales/bg.yml index bceb66ca..e0e60adf 100644 --- a/config/locales/bg.yml +++ b/config/locales/bg.yml @@ -165,5 +165,3 @@ bg: users: invalid_email: E-mail адресът е невалиден invalid_otp_token: Невалиден код - will_paginate: - page_gap: "…" diff --git a/config/locales/en.yml b/config/locales/en.yml index 9c270892..e2f18739 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -298,5 +298,3 @@ en: users: invalid_email: The e-mail address is invalid invalid_otp_token: Invalid two-factor code - will_paginate: - page_gap: "…" diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 9e590f10..754eabb9 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -293,5 +293,3 @@ fr: users: invalid_email: L'adresse courriel est invalide invalid_otp_token: Le code d'authentification à deux facteurs est invalide - will_paginate: - page_gap: "…" diff --git a/config/locales/hr.yml b/config/locales/hr.yml index 64b1ae2c..f6e6ed44 100644 --- a/config/locales/hr.yml +++ b/config/locales/hr.yml @@ -161,5 +161,3 @@ hr: users: invalid_email: E-mail adresa nije valjana invalid_otp_token: Nevaljani dvo-faktorski kod - will_paginate: - page_gap: "…" diff --git a/config/locales/ja.yml b/config/locales/ja.yml index 91fda77c..3e78e567 100644 --- a/config/locales/ja.yml +++ b/config/locales/ja.yml @@ -298,5 +298,3 @@ ja: users: invalid_email: メールアドレスが無効です invalid_otp_token: 二段階認証コードが間違っています - will_paginate: - page_gap: "…" diff --git a/config/locales/nl.yml b/config/locales/nl.yml index 22fed228..c81c6ac2 100644 --- a/config/locales/nl.yml +++ b/config/locales/nl.yml @@ -161,5 +161,3 @@ nl: users: invalid_email: Het e-mailadres is ongeldig invalid_otp_token: Ongeldige twe-factor code - will_paginate: - page_gap: "…" diff --git a/config/locales/ru.yml b/config/locales/ru.yml index ca73dd45..4c8cb6a4 100644 --- a/config/locales/ru.yml +++ b/config/locales/ru.yml @@ -164,5 +164,3 @@ ru: users: invalid_email: Введенный e-mail неверен invalid_otp_token: Введен неверный код - will_paginate: - page_gap: "…" From 9240ca6cefdec25574f329b70438c4fa4571a1e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dar=C3=ADo=20Here=C3=B1=C3=BA?= Date: Fri, 14 Apr 2017 21:31:16 -0300 Subject: [PATCH 15/49] Mispelling & minor fixes (#1814) --- config/locales/doorkeeper.es.yml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/config/locales/doorkeeper.es.yml b/config/locales/doorkeeper.es.yml index 74360371..f3efb230 100644 --- a/config/locales/doorkeeper.es.yml +++ b/config/locales/doorkeeper.es.yml @@ -41,7 +41,7 @@ es: title: Nueva aplicación show: actions: Acciones - application_id: Id de aplicación + application_id: Id de la aplicación callback_urls: Callback urls scopes: Ámbitos secret: Secreto @@ -49,12 +49,12 @@ es: authorizations: buttons: authorize: Autorizar - deny: Denegar + deny: Desautorizar error: title: Ha ocurrido un error new: able_to: Será capaz de - prompt: La aplicación %{client_name} solicita acceder a su cuenta + prompt: La aplicación %{client_name} solicita tener acceso a su cuenta title: Se requiere autorización show: title: Código de autorización @@ -72,16 +72,16 @@ es: messages: access_denied: El propietario del recurso o servidor de autorización denegó la petición. credential_flow_not_configured: Las credenciales de contraseña del propietario del recurso falló debido a que Doorkeeper.configure.resource_owner_from_credentials está sin configurar. - invalid_client: La autentificación del cliente falló debido a un cliente desconocido, no hay incluido autentificación del cliente, o método de autentificación no confirmado. - invalid_grant: La concesión de autorización ofrecida es inválida, expiró, se revocó, no coincide con la URI de redirección utilizada en la petición de autorización, o fue emitida para otro cliente. + invalid_client: La autentificación del cliente falló debido o a que es un cliente desconocido o no está incluída la autentificación del cliente o el método de autentificación no está confirmado. + invalid_grant: La concesión de autorización ofrecida es inválida, venció, se revocó, no coincide con la URI de redirección utilizada en la petición de autorización, o fue emitida para otro cliente. invalid_redirect_uri: La URI de redirección incluida no es válida. - invalid_request: En la petición falta un parámetro necesario, incluye un valor de parámetro no soportado o tiene otro tipo de formato incorrecto. - invalid_resource_owner: Las credeciales del propietario del recurso proporcionado no son válidas, o el propietario del recurso no puede ser encontrado + invalid_request: En la petición falta un parámetro necesario o incluye un valor de parámetro no soportado o tiene otro tipo de formato incorrecto. + invalid_resource_owner: Las credenciales del propietario del recurso proporcionado no son válidas, o el propietario del recurso no puede ser encontrado. invalid_scope: El ámbito pedido es inválido, desconocido o erróneo. invalid_token: - expired: El identificador de acceso expiró - revoked: El identificador de acceso fue revocado - unknown: El identificador de acceso es inválido + expired: El identificador de acceso finalizó. + revoked: El identificador de acceso fue revocado. + unknown: El identificador de acceso es inválido. resource_owner_authenticator_not_configured: El propietario del recurso falló debido a que Doorkeeper.configure.resource_owner_authenticator está sin configurar. server_error: El servidor de la autorización entontró una condición inesperada que le impidió cumplir con la solicitud. temporarily_unavailable: El servidor de la autorización es actualmente incapaz de manejar la petición debido a una sobrecarga temporal o un trabajo de mantenimiento del servidor. From ef879a88393598f5dd83a2ced6dfadbebe888203 Mon Sep 17 00:00:00 2001 From: Joachim Viide Date: Sat, 15 Apr 2017 03:32:42 +0300 Subject: [PATCH 16/49] Send initial state in a