Replace sprockets/browserify with Webpack (#2617)
* Replace browserify with webpack * Add react-intl-translations-manager * Do not minify in development, add offline-plugin for ServiceWorker background cache updates * Adjust tests and dependencies * Fix production deployments * Fix tests * More optimizations * Improve travis cache for npm stuff * Re-run travis * Add back support for custom.scss as before * Remove offline-plugin and babili * Fix issue with Immutable.List().unshift(...values) not working as expected * Make travis load schema instead of running all migrations in sequence * Fix missing React import in WarningContainer. Optimize rendering performance by using ImmutablePureComponent instead of React.PureComponent. ImmutablePureComponent uses Immutable.is() to compare props. Replace dynamic callback bindings in <UI /> * Add react definitions to places that use JSX * Add Procfile.dev for running rails, webpack and streaming API at the same time
							
								
								
									
										22
									
								
								.babelrc
									
									
									
									
									
								
							
							
						
						| @@ -1,7 +1,25 @@ | ||||
| { | ||||
|   "presets": ["es2015", "react"], | ||||
|   "presets": [ | ||||
|     "es2015", | ||||
|     "react", | ||||
|     [ | ||||
|       "env", | ||||
|       { | ||||
|         "loose": true, | ||||
|         "modules": false | ||||
|       } | ||||
|     ] | ||||
|   ], | ||||
|   "plugins": [ | ||||
|     "transform-react-jsx-source", | ||||
|     "transform-react-jsx-self", | ||||
|     "transform-decorators-legacy", | ||||
|     "transform-object-rest-spread" | ||||
|     "transform-object-rest-spread", | ||||
|     [ | ||||
|       "react-intl", | ||||
|       { | ||||
|         "messagesDir": "./build/messages" | ||||
|       } | ||||
|     ] | ||||
|   ] | ||||
| } | ||||
|   | ||||
							
								
								
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						| @@ -22,7 +22,7 @@ public/assets | ||||
| .env | ||||
| .env.production | ||||
| node_modules/ | ||||
| neo4j/ | ||||
| build/ | ||||
|  | ||||
| # Ignore Vagrant files | ||||
| .vagrant/ | ||||
| @@ -43,3 +43,5 @@ redis | ||||
| # Ignore vim files | ||||
| *~ | ||||
| *.swp | ||||
| /public/packs | ||||
| /node_modules | ||||
|   | ||||
							
								
								
									
										4
									
								
								.postcssrc.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,4 @@ | ||||
| plugins: | ||||
|   postcss-smart-import: {} | ||||
|   precss: {} | ||||
|   autoprefixer: {} | ||||
| @@ -1,9 +1,7 @@ | ||||
| language: ruby | ||||
| cache: | ||||
|   bundler: true | ||||
|   yarn: true | ||||
|   directories: | ||||
|     - node_modules | ||||
|   yarn: false | ||||
| dist: trusty | ||||
| sudo: false | ||||
|  | ||||
| @@ -42,7 +40,8 @@ install: | ||||
|   - yarn install | ||||
|  | ||||
| before_script: | ||||
|   - bundle exec rails db:create db:migrate | ||||
|   - bundle exec rails db:create db:schema:load | ||||
|   - bundle exec rails assets:precompile | ||||
|  | ||||
| script: | ||||
|   - bundle exec rspec | ||||
|   | ||||
							
								
								
									
										15
									
								
								Dockerfile
									
									
									
									
									
								
							
							
						
						| @@ -10,8 +10,6 @@ EXPOSE 3000 4000 | ||||
|  | ||||
| WORKDIR /mastodon | ||||
|  | ||||
| COPY Gemfile Gemfile.lock package.json yarn.lock /mastodon/ | ||||
|  | ||||
| RUN echo "@edge https://nl.alpinelinux.org/alpine/edge/main" >> /etc/apk/repositories \ | ||||
|  && BUILD_DEPS=" \ | ||||
|     postgresql-dev \ | ||||
| @@ -23,6 +21,7 @@ RUN echo "@edge https://nl.alpinelinux.org/alpine/edge/main" >> /etc/apk/reposit | ||||
|     $BUILD_DEPS \ | ||||
|     nodejs@edge \ | ||||
|     nodejs-npm@edge \ | ||||
|     git \ | ||||
|     libpq \ | ||||
|     libxml2 \ | ||||
|     libxslt \ | ||||
| @@ -31,14 +30,14 @@ RUN echo "@edge https://nl.alpinelinux.org/alpine/edge/main" >> /etc/apk/reposit | ||||
|     imagemagick@edge \ | ||||
|     ca-certificates \ | ||||
|  && npm install -g npm@3 && npm install -g yarn \ | ||||
|  && bundle install --deployment --without test development \ | ||||
|  && yarn --ignore-optional \ | ||||
|  && yarn cache clean \ | ||||
|  && npm -g cache clean \ | ||||
|  && update-ca-certificates \ | ||||
|  && apk del $BUILD_DEPS \ | ||||
|  && rm -rf /tmp/* /var/cache/apk/* | ||||
|  | ||||
| COPY Gemfile Gemfile.lock package.json yarn.lock /mastodon/ | ||||
|  | ||||
| RUN bundle install --deployment --without test development \ | ||||
|  && yarn --ignore-optional --pure-lockfile | ||||
|  | ||||
| COPY . /mastodon | ||||
|  | ||||
| VOLUME /mastodon/public/system /mastodon/public/assets | ||||
| VOLUME /mastodon/public/system /mastodon/public/assets /mastodon/public/packs | ||||
|   | ||||
							
								
								
									
										34
									
								
								Gemfile
									
									
									
									
									
								
							
							
						
						| @@ -5,22 +5,19 @@ ruby '>= 2.3.0', '< 2.5.0' | ||||
|  | ||||
| gem 'pkg-config' | ||||
|  | ||||
| gem 'rails', '~> 5.0.2' | ||||
| gem 'sass-rails', '~> 5.0' | ||||
| gem 'uglifier', '>= 1.3.0' | ||||
| gem 'jquery-rails' | ||||
| gem 'puma' | ||||
| gem 'rails', '~> 5.0.2' | ||||
| gem 'uglifier', '>= 1.3.0' | ||||
|  | ||||
| gem 'hamlit-rails' | ||||
| gem 'pg' | ||||
| gem 'pghero' | ||||
| gem 'dotenv-rails' | ||||
| gem 'font-awesome-rails' | ||||
| gem 'best_in_place', '~> 3.0.1' | ||||
|  | ||||
| gem 'aws-sdk', '>= 2.0' | ||||
| gem 'paperclip', '~> 5.1' | ||||
| gem 'paperclip-av-transcoder' | ||||
| gem 'aws-sdk', '>= 2.0' | ||||
|  | ||||
| gem 'addressable' | ||||
| gem 'devise' | ||||
| @@ -58,18 +55,18 @@ gem 'sprockets-rails', require: 'sprockets/railtie' | ||||
| gem 'statsd-instrument' | ||||
| gem 'twitter-text' | ||||
| gem 'tzinfo-data' | ||||
| gem 'webpacker', '~>1.2' | ||||
| gem 'whatlanguage' | ||||
|  | ||||
| # For some reason the view specs start failing without this | ||||
| gem 'react-rails' | ||||
| gem 'browserify-rails' | ||||
| gem 'autoprefixer-rails' | ||||
|  | ||||
| group :development, :test do | ||||
|   gem 'rspec-rails' | ||||
|   gem 'pry-rails' | ||||
|   gem 'fuubar' | ||||
|   gem 'fabrication' | ||||
|   gem 'fuubar' | ||||
|   gem 'i18n-tasks', '~> 0.9.6' | ||||
|   gem 'pry-rails' | ||||
|   gem 'rspec-rails' | ||||
| end | ||||
|  | ||||
| group :test do | ||||
| @@ -83,24 +80,23 @@ group :test do | ||||
| end | ||||
|  | ||||
| group :development do | ||||
|   gem 'rubocop', '0.46.0', require: false | ||||
|   gem 'better_errors' | ||||
|   gem 'binding_of_caller' | ||||
|   gem 'letter_opener' | ||||
|   gem 'letter_opener_web' | ||||
|   gem 'bullet' | ||||
|   gem 'active_record_query_trace' | ||||
|   gem 'annotate' | ||||
|   gem 'better_errors' | ||||
|   gem 'binding_of_caller' | ||||
|   gem 'bullet' | ||||
|   gem 'letter_opener' | ||||
|   gem 'letter_opener_web' | ||||
|   gem 'rubocop', '0.46.0', require: false | ||||
|  | ||||
|   gem 'capistrano', '3.8.0' | ||||
|   gem 'capistrano-rails' | ||||
|   gem 'capistrano-rbenv' | ||||
|   gem 'capistrano-yarn' | ||||
|   gem 'capistrano-faster-assets', '~> 1.0' | ||||
| end | ||||
|  | ||||
| group :production do | ||||
|   gem 'lograge' | ||||
|   gem 'rails_12factor' | ||||
|   gem 'redis-rails' | ||||
|   gem 'lograge' | ||||
| end | ||||
|   | ||||
							
								
								
									
										43
									
								
								Gemfile.lock
									
									
									
									
									
								
							
							
						
						| @@ -43,15 +43,13 @@ GEM | ||||
|       public_suffix (~> 2.0, >= 2.0.2) | ||||
|     airbrussh (1.2.0) | ||||
|       sshkit (>= 1.6.1, != 1.7.0) | ||||
|     annotate (2.7.1) | ||||
|       activerecord (>= 3.2, < 6.0) | ||||
|       rake (>= 10.4, < 12.0) | ||||
|     annotate (2.6.5) | ||||
|       activerecord (>= 2.3.0) | ||||
|       rake (>= 0.8.7) | ||||
|     arel (7.1.4) | ||||
|     ast (2.3.0) | ||||
|     attr_encrypted (3.0.3) | ||||
|       encryptor (~> 3.0.0) | ||||
|     autoprefixer-rails (6.7.7.2) | ||||
|       execjs | ||||
|     av (0.9.0) | ||||
|       cocaine (~> 0.5.3) | ||||
|     aws-sdk (2.9.12) | ||||
| @@ -76,10 +74,6 @@ GEM | ||||
|       rack (>= 0.9.0) | ||||
|     binding_of_caller (0.7.2) | ||||
|       debug_inspector (>= 0.0.1) | ||||
|     browserify-rails (4.1.0) | ||||
|       addressable (>= 2.4.0) | ||||
|       railties (>= 4.0.0, < 5.1) | ||||
|       sprockets (>= 3.6.0) | ||||
|     builder (3.2.3) | ||||
|     bullet (5.5.1) | ||||
|       activesupport (>= 3.0.0) | ||||
| @@ -92,8 +86,6 @@ GEM | ||||
|     capistrano-bundler (1.2.0) | ||||
|       capistrano (~> 3.1) | ||||
|       sshkit (~> 1.2) | ||||
|     capistrano-faster-assets (1.0.2) | ||||
|       capistrano (>= 3.1) | ||||
|     capistrano-rails (1.2.3) | ||||
|       capistrano (~> 3.1) | ||||
|       capistrano-bundler (~> 1.1) | ||||
| @@ -161,8 +153,6 @@ GEM | ||||
|     faker (1.7.3) | ||||
|       i18n (~> 0.5) | ||||
|     fast_blank (1.0.0) | ||||
|     font-awesome-rails (4.7.0.1) | ||||
|       railties (>= 3.2, < 5.1) | ||||
|     fuubar (2.2.0) | ||||
|       rspec-core (~> 3.0) | ||||
|       ruby-progressbar (~> 1.4) | ||||
| @@ -210,10 +200,6 @@ GEM | ||||
|       rainbow (~> 2.2) | ||||
|       terminal-table (>= 1.5.1) | ||||
|     jmespath (1.3.1) | ||||
|     jquery-rails (4.3.1) | ||||
|       rails-dom-testing (>= 1, < 3) | ||||
|       railties (>= 4.2.0) | ||||
|       thor (>= 0.14, < 2.0) | ||||
|     json (2.1.0) | ||||
|     kaminari (1.0.1) | ||||
|       activesupport (>= 4.1.0) | ||||
| @@ -257,6 +243,7 @@ GEM | ||||
|     mimemagic (0.3.2) | ||||
|     mini_portile2 (2.1.0) | ||||
|     minitest (5.10.1) | ||||
|     multi_json (1.12.1) | ||||
|     net-scp (1.2.1) | ||||
|       net-ssh (>= 2.6.5) | ||||
|     net-ssh (4.1.0) | ||||
| @@ -348,8 +335,8 @@ GEM | ||||
|       thor (>= 0.18.1, < 2.0) | ||||
|     rainbow (2.2.2) | ||||
|       rake | ||||
|     rake (11.3.0) | ||||
|     react-rails (1.11.0) | ||||
|     rake (12.0.0) | ||||
|     react-rails (2.1.0) | ||||
|       babel-transpiler (>= 0.7.0) | ||||
|       connection_pool | ||||
|       execjs | ||||
| @@ -410,13 +397,6 @@ GEM | ||||
|       crass (~> 1.0.2) | ||||
|       nokogiri (>= 1.4.4) | ||||
|       nokogumbo (~> 1.4.1) | ||||
|     sass (3.4.23) | ||||
|     sass-rails (5.0.6) | ||||
|       railties (>= 4.0.0, < 6) | ||||
|       sass (~> 3.1) | ||||
|       sprockets (>= 2.8, < 4.0) | ||||
|       sprockets-rails (>= 2.0, < 4.0) | ||||
|       tilt (>= 1.1, < 3) | ||||
|     sidekiq (4.2.10) | ||||
|       concurrent-ruby (~> 1.0) | ||||
|       connection_pool (~> 2.2, >= 2.2.0) | ||||
| @@ -473,6 +453,10 @@ GEM | ||||
|       addressable (>= 2.3.6) | ||||
|       crack (>= 0.3.2) | ||||
|       hashdiff | ||||
|     webpacker (1.2) | ||||
|       activesupport (>= 4.2) | ||||
|       multi_json (~> 1.2) | ||||
|       railties (>= 4.2) | ||||
|     websocket-driver (0.6.5) | ||||
|       websocket-extensions (>= 0.1.0) | ||||
|     websocket-extensions (0.1.2) | ||||
| @@ -487,15 +471,12 @@ DEPENDENCIES | ||||
|   active_record_query_trace | ||||
|   addressable | ||||
|   annotate | ||||
|   autoprefixer-rails | ||||
|   aws-sdk (>= 2.0) | ||||
|   best_in_place (~> 3.0.1) | ||||
|   better_errors | ||||
|   binding_of_caller | ||||
|   browserify-rails | ||||
|   bullet | ||||
|   capistrano (= 3.8.0) | ||||
|   capistrano-faster-assets (~> 1.0) | ||||
|   capistrano-rails | ||||
|   capistrano-rbenv | ||||
|   capistrano-yarn | ||||
| @@ -507,7 +488,6 @@ DEPENDENCIES | ||||
|   fabrication | ||||
|   faker | ||||
|   fast_blank | ||||
|   font-awesome-rails | ||||
|   fuubar | ||||
|   goldfinger | ||||
|   hamlit-rails | ||||
| @@ -517,7 +497,6 @@ DEPENDENCIES | ||||
|   http_accept_language | ||||
|   httplog | ||||
|   i18n-tasks (~> 0.9.6) | ||||
|   jquery-rails | ||||
|   kaminari | ||||
|   letter_opener | ||||
|   letter_opener_web | ||||
| @@ -554,7 +533,6 @@ DEPENDENCIES | ||||
|   rubocop (= 0.46.0) | ||||
|   ruby-oembed | ||||
|   sanitize | ||||
|   sass-rails (~> 5.0) | ||||
|   sidekiq | ||||
|   sidekiq-unique-jobs | ||||
|   simple-navigation | ||||
| @@ -566,6 +544,7 @@ DEPENDENCIES | ||||
|   tzinfo-data | ||||
|   uglifier (>= 1.3.0) | ||||
|   webmock | ||||
|   webpacker (~> 1.2) | ||||
|   whatlanguage | ||||
|  | ||||
| RUBY VERSION | ||||
|   | ||||
							
								
								
									
										3
									
								
								Procfile.dev
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,3 @@ | ||||
| web: bundle exec rails s -p 3000 | ||||
| stream: yarn run start | ||||
| webpack: ./bin/webpack-dev-server | ||||
| @@ -1,15 +0,0 @@ | ||||
| // This is a manifest file that'll be compiled into application.js, which will include all the files | ||||
| // listed below. | ||||
| // | ||||
| // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts, | ||||
| // or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path. | ||||
| // | ||||
| // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the | ||||
| // compiled file. | ||||
| // | ||||
| // Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details | ||||
| // about supported directives. | ||||
| // | ||||
| //= require jquery2 | ||||
| //= require jquery_ujs | ||||
| //= require components | ||||
| @@ -1,9 +0,0 @@ | ||||
| //= require jquery2 | ||||
| //= require jquery_ujs | ||||
| //= require extras | ||||
| //= require best_in_place | ||||
| //= require local_time | ||||
|  | ||||
| $(function () { | ||||
|   $(".best_in_place").best_in_place(); | ||||
| }); | ||||
| @@ -1,15 +0,0 @@ | ||||
| //= require_self | ||||
| //= require react_ujs | ||||
|  | ||||
| window.React    = require('react'); | ||||
| window.ReactDOM = require('react-dom'); | ||||
| window.Perf     = require('react-addons-perf'); | ||||
|  | ||||
| if (!window.Intl) { | ||||
|   require('intl'); | ||||
|   require('intl/locale-data/jsonp/en.js'); | ||||
| } | ||||
|  | ||||
| //= require_tree ./components | ||||
|  | ||||
| window.Mastodon = require('./components/containers/mastodon'); | ||||
| @@ -1,16 +0,0 @@ | ||||
| import Avatar from '../../../components/avatar'; | ||||
| import DisplayName from '../../../components/display_name'; | ||||
| import ImmutablePropTypes from 'react-immutable-proptypes'; | ||||
|  | ||||
| const AutosuggestAccount = ({ account }) => ( | ||||
|   <div className='autosuggest-account'> | ||||
|     <div className='autosuggest-account-icon'><Avatar src={account.get('avatar')} staticSrc={account.get('avatar_static')} size={18} /></div> | ||||
|     <DisplayName account={account} /> | ||||
|   </div> | ||||
| ); | ||||
|  | ||||
| AutosuggestAccount.propTypes = { | ||||
|   account: ImmutablePropTypes.map.isRequired | ||||
| }; | ||||
|  | ||||
| export default AutosuggestAccount; | ||||
| @@ -1,15 +0,0 @@ | ||||
| import { FormattedMessage } from 'react-intl'; | ||||
| import DisplayName from '../../../components/display_name'; | ||||
| import ImmutablePropTypes from 'react-immutable-proptypes'; | ||||
|  | ||||
| const AutosuggestStatus = ({ status }) => ( | ||||
|   <div className='autosuggest-status'> | ||||
|     <FormattedMessage id='search.status_by' defaultMessage='Status by {name}' values={{ name: <strong>@{status.getIn(['account', 'acct'])}</strong> }} /> | ||||
|   </div> | ||||
| ); | ||||
|  | ||||
| AutosuggestStatus.propTypes = { | ||||
|   status: ImmutablePropTypes.map.isRequired | ||||
| }; | ||||
|  | ||||
| export default AutosuggestStatus; | ||||
| @@ -1,44 +0,0 @@ | ||||
| import PropTypes from 'prop-types'; | ||||
| import ImmutablePropTypes from 'react-immutable-proptypes'; | ||||
| import Permalink from '../../../components/permalink'; | ||||
| import Avatar from '../../../components/avatar'; | ||||
| import DisplayName from '../../../components/display_name'; | ||||
| import emojify from '../../../emoji'; | ||||
| import IconButton from '../../../components/icon_button'; | ||||
| import { defineMessages, injectIntl } from 'react-intl'; | ||||
|  | ||||
| const messages = defineMessages({ | ||||
|   authorize: { id: 'follow_request.authorize', defaultMessage: 'Authorize' }, | ||||
|   reject: { id: 'follow_request.reject', defaultMessage: 'Reject' } | ||||
| }); | ||||
|  | ||||
| const AccountAuthorize = ({ intl, account, onAuthorize, onReject }) => { | ||||
|   const content = { __html: emojify(account.get('note')) }; | ||||
|  | ||||
|   return ( | ||||
|     <div className='account-authorize__wrapper'> | ||||
|       <div className='account-authorize'> | ||||
|         <Permalink href={account.get('url')} to={`/accounts/${account.get('id')}`} className='detailed-status__display-name'> | ||||
|           <div className='account-authorize__avatar'><Avatar src={account.get('avatar')} staticSrc={account.get('avatar_static')} size={48} /></div> | ||||
|           <DisplayName account={account} /> | ||||
|         </Permalink> | ||||
|  | ||||
|         <div className='account__header__content' dangerouslySetInnerHTML={content} /> | ||||
|       </div> | ||||
|  | ||||
|       <div className='account--panel'> | ||||
|         <div className='account--panel__button'><IconButton title={intl.formatMessage(messages.authorize)} icon='check' onClick={onAuthorize} /></div> | ||||
|         <div className='account--panel__button'><IconButton title={intl.formatMessage(messages.reject)} icon='times' onClick={onReject} /></div> | ||||
|       </div> | ||||
|     </div> | ||||
|   ) | ||||
| }; | ||||
|  | ||||
| AccountAuthorize.propTypes = { | ||||
|   account: ImmutablePropTypes.map.isRequired, | ||||
|   onAuthorize: PropTypes.func.isRequired, | ||||
|   onReject: PropTypes.func.isRequired, | ||||
|   intl: PropTypes.object.isRequired | ||||
| }; | ||||
|  | ||||
| export default injectIntl(AccountAuthorize); | ||||
| @@ -1,66 +0,0 @@ | ||||
| import Column from '../ui/components/column'; | ||||
| import ColumnLink from '../ui/components/column_link'; | ||||
| import ColumnSubheading from '../ui/components/column_subheading'; | ||||
| import { Link } from 'react-router'; | ||||
| import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; | ||||
| import { connect } from 'react-redux'; | ||||
| import PropTypes from 'prop-types'; | ||||
| 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: 'Federated timeline' }, | ||||
|   navigation_subheading: { id: 'column_subheading.navigation', defaultMessage: 'Navigation'}, | ||||
|   settings_subheading: { id: 'column_subheading.settings', defaultMessage: 'Settings'}, | ||||
|   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: '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' } | ||||
| }); | ||||
|  | ||||
| const mapStateToProps = state => ({ | ||||
|   me: state.getIn(['accounts', state.getIn(['meta', 'me'])]) | ||||
| }); | ||||
|  | ||||
| const GettingStarted = ({ intl, me }) => { | ||||
|   let followRequests = ''; | ||||
|  | ||||
|   if (me.get('locked')) { | ||||
|     followRequests = <ColumnLink icon='users' text={intl.formatMessage(messages.follow_requests)} to='/follow_requests' />; | ||||
|   } | ||||
|  | ||||
|   return ( | ||||
|     <Column icon='asterisk' heading={intl.formatMessage(messages.heading)} hideHeadingOnMobile={true}> | ||||
|       <div className='getting-started__wrapper'> | ||||
|         <ColumnSubheading text={intl.formatMessage(messages.navigation_subheading)}/> | ||||
|         <ColumnLink icon='users' hideOnMobile={true} text={intl.formatMessage(messages.community_timeline)} to='/timelines/public/local' /> | ||||
|         <ColumnLink icon='globe' hideOnMobile={true} text={intl.formatMessage(messages.public_timeline)} to='/timelines/public' /> | ||||
|         <ColumnLink icon='star' text={intl.formatMessage(messages.favourites)} to='/favourites' /> | ||||
|         {followRequests} | ||||
|         <ColumnLink icon='volume-off' text={intl.formatMessage(messages.mutes)} to='/mutes' /> | ||||
|         <ColumnLink icon='ban' text={intl.formatMessage(messages.blocks)} to='/blocks' /> | ||||
|         <ColumnSubheading text={intl.formatMessage(messages.settings_subheading)}/> | ||||
|         <ColumnLink icon='book' text={intl.formatMessage(messages.info)} href='/about/more' /> | ||||
|         <ColumnLink icon='cog' text={intl.formatMessage(messages.preferences)} href='/settings/preferences' /> | ||||
|         <ColumnLink icon='sign-out' text={intl.formatMessage(messages.sign_out)} href='/auth/sign_out' method='delete' /> | ||||
|       </div> | ||||
|  | ||||
|       <div className='scrollable optionally-scrollable' style={{ display: 'flex', flexDirection: 'column' }}> | ||||
|         <div className='static-content getting-started'> | ||||
|           <p><FormattedMessage id='getting_started.open_source_notice' defaultMessage='Mastodon is open source software. You can contribute or report issues on GitHub at {github}. {apps}.' values={{ github: <a href="https://github.com/tootsuite/mastodon" target="_blank">tootsuite/mastodon</a>, apps: <a href="https://github.com/tootsuite/documentation/blob/master/Using-Mastodon/Apps.md" target="_blank"><FormattedMessage id='getting_started.apps' defaultMessage='Various apps are available' /></a> }} /></p> | ||||
|         </div> | ||||
|       </div> | ||||
|     </Column> | ||||
|   ); | ||||
| }; | ||||
|  | ||||
| GettingStarted.propTypes = { | ||||
|   intl: PropTypes.object.isRequired, | ||||
|   me: ImmutablePropTypes.map.isRequired | ||||
| }; | ||||
|  | ||||
| export default connect(mapStateToProps)(injectIntl(GettingStarted)); | ||||
| @@ -1,68 +0,0 @@ | ||||
| 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 bg; | ||||
| @@ -1,68 +0,0 @@ | ||||
| const eo = { | ||||
|   "column_back_button.label": "Reveni", | ||||
|   "lightbox.close": "Fermi", | ||||
|   "loading_indicator.label": "Ŝarĝanta...", | ||||
|   "status.mention": "Mencii @{name}", | ||||
|   "status.delete": "Forigi", | ||||
|   "status.reply": "Respondi", | ||||
|   "status.reblog": "Diskonigi", | ||||
|   "status.favourite": "Favori", | ||||
|   "status.reblogged_by": "{name} diskonigita", | ||||
|   "status.sensitive_warning": "Tikla enhavo", | ||||
|   "status.sensitive_toggle": "Alklaki por vidi", | ||||
|   "video_player.toggle_sound": "Aktivigi sonojn", | ||||
|   "account.mention": "Mencii @{name}", | ||||
|   "account.edit_profile": "Redakti la profilon", | ||||
|   "account.unblock": "Malbloki @{name}", | ||||
|   "account.unfollow": "Malsekvi", | ||||
|   "account.block": "Bloki @{name}", | ||||
|   "account.follow": "Sekvi", | ||||
|   "account.posts": "Mesaĝoj", | ||||
|   "account.follows": "Sekvatoj", | ||||
|   "account.followers": "Sekvantoj", | ||||
|   "account.follows_you": "Sekvas vin", | ||||
|   "account.requested": "Atendas aprobon", | ||||
|   "getting_started.heading": "Por komenci", | ||||
|   "getting_started.about_addressing": "Vi povas sekvi homojn se vi konas la uzantnomon kaj domajnon tajpinte retpoŝtecan adreson en la serĉilon.", | ||||
|   "getting_started.about_shortcuts": "Se la celita uzanto troviĝas en la sama domajno de vi, uzi nur la uzantnomon sufiĉos. La sama regulo validas por mencii aliajn uzantojn en mesaĝo.", | ||||
|   "getting_started.open_source_notice": "Mastodon estas malfermitkoda programo. Vi povas kontribui aŭ raporti problemojn en github je {github}. {apps}.", | ||||
|   "column.home": "Hejmo", | ||||
|   "column.community": "Loka tempolinio", | ||||
|   "column.public": "Fratara tempolinio", | ||||
|   "column.notifications": "Sciigoj", | ||||
|   "tabs_bar.compose": "Ekskribi", | ||||
|   "tabs_bar.home": "Hejmo", | ||||
|   "tabs_bar.mentions": "Sciigoj", | ||||
|   "tabs_bar.public": "Fratara tempolinio", | ||||
|   "tabs_bar.notifications": "Sciigoj", | ||||
|   "compose_form.placeholder": "Pri kio vi pensas?", | ||||
|   "compose_form.publish": "Hup", | ||||
|   "compose_form.sensitive": "Marki ke la enhavo estas tikla", | ||||
|   "compose_form.spoiler": "Kaŝi la tekston malantaŭ averto", | ||||
|   "compose_form.private": "Marki ke la enhavo estas privata", | ||||
|   "compose_form.privacy_disclaimer": "Via privata mesaĝo estos sendita nur al menciitaj uzantoj en {domains}. Ĉu vi fidas {domainsCount, plural, one {tiun servilon} other {tiujn servilojn}}? Mesaĝa privateco funkcias nur en aperaĵoj de Mastodon. Se {domains} {domainsCount, plural, one {ne estas aperaĵo de Mastodon} other {ne estas aperaĵoj de Mastodon}}, estos neniu indiko ke via mesaĝo estas privata, kaj ĝi povus esti diskonigita aŭ videbligita al necelitaj ricevantoj.", | ||||
|   "compose_form.unlisted": "Ne afiŝi en publikaj tempolinioj", | ||||
|   "navigation_bar.edit_profile": "Redakti la profilon", | ||||
|   "navigation_bar.preferences": "Preferoj", | ||||
|   "navigation_bar.community_timeline": "Loka tempolinio", | ||||
|   "navigation_bar.public_timeline": "Fratara tempolinio", | ||||
|   "navigation_bar.logout": "Elsaluti", | ||||
|   "reply_indicator.cancel": "Rezigni", | ||||
|   "search.placeholder": "Serĉi", | ||||
|   "search.account": "Konto", | ||||
|   "search.hashtag": "Kradvorto", | ||||
|   "upload_button.label": "Aldoni enhavaĵon", | ||||
|   "upload_form.undo": "Malfari", | ||||
|   "notification.follow": "{name} sekvis vin", | ||||
|   "notification.favourite": "{name} favoris vian mesaĝon", | ||||
|   "notification.reblog": "{name} diskonigis vian mesaĝon", | ||||
|   "notification.mention": "{name} menciis vin", | ||||
|   "notifications.column_settings.alert": "Retumilaj atentigoj", | ||||
|   "notifications.column_settings.show": "Montri en kolono", | ||||
|   "notifications.column_settings.follow": "Novaj sekvantoj:", | ||||
|   "notifications.column_settings.favourite": "Favoroj:", | ||||
|   "notifications.column_settings.mention": "Mencioj:", | ||||
|   "notifications.column_settings.reblog": "Diskonigoj:", | ||||
| }; | ||||
|  | ||||
| export default eo; | ||||
| @@ -1,93 +0,0 @@ | ||||
| const es = { | ||||
|   "column_back_button.label": "Atrás", | ||||
|   "lightbox.close": "Cerrar", | ||||
|   "loading_indicator.label": "Cargando...", | ||||
|   "status.mention": "Mencionar", | ||||
|   "status.delete": "Borrar", | ||||
|   "status.reply": "Responder", | ||||
|   "status.reblog": "Retoot", | ||||
|   "status.favourite": "Favorito", | ||||
|   "status.reblogged_by": "Retooteado por {name}", | ||||
|   "status.sensitive_warning": "Contenido sensible", | ||||
|   "status.sensitive_toggle": "Click para ver", | ||||
|   "status.show_more": "Mostrar más", | ||||
|   "status.show_less": "Mostrar menos", | ||||
|   "status.open": "Expandir estado", | ||||
|   "status.report": "Reportar", | ||||
|   "video_player.toggle_sound": "Act/Desac. sonido", | ||||
|   "account.mention": "Mencionar", | ||||
|   "account.edit_profile": "Editar perfil", | ||||
|   "account.unblock": "Desbloquear", | ||||
|   "account.unfollow": "Dejar de seguir", | ||||
|   "account.mute": "Silenciar", | ||||
|   "account.block": "Bloquear", | ||||
|   "account.follow": "Seguir", | ||||
|   "account.posts": "Publicaciones", | ||||
|   "account.follows": "Seguir", | ||||
|   "account.followers": "Seguidores", | ||||
|   "account.follows_you": "Te sigue", | ||||
|   "account.requested": "Esperando aprobación", | ||||
|   "getting_started.heading": "Primeros pasos", | ||||
|   "getting_started.about_addressing": "Puedes seguir a gente si conoces su nombre de usuario y el dominio en el que están registrados, introduciendo algo similar a una dirección de correo electrónico en el formulario en la parte superior de la barra lateral.", | ||||
|   "getting_started.about_shortcuts": "Si el usuario que buscas está en el mismo dominio que tú, simplemente funcionará introduciendo el nombre de usuario. La misma regla se aplica para mencionar a usuarios.", | ||||
|   "getting_started.open_source_notice": "Mastodon es software libre. Puedes contribuir o reportar errores en {github}. {apps}.", | ||||
|   "column.home": "Inicio", | ||||
|   "column.community": "Historia local", | ||||
|   "column.public": "Historia federada", | ||||
|   "column.notifications": "Notificaciones", | ||||
|   "column.blocks": "Usuarios bloqueados", | ||||
|   "column.favourites": "Favoritos", | ||||
|   "column.follow_requests": "Solicitudes para seguirte", | ||||
|   "column.mutes": "Usuarios silenciados", | ||||
|   "tabs_bar.compose": "Redactar", | ||||
|   "tabs_bar.home": "Inicio", | ||||
|   "tabs_bar.mentions": "Menciones", | ||||
|   "tabs_bar.public": "Público", | ||||
|   "tabs_bar.notifications": "Notificaciones", | ||||
|   "compose_form.placeholder": "¿En qué estás pensando?", | ||||
|   "compose_form.publish": "Tootear", | ||||
|   "compose_form.sensitive": "Marcar contenido como sensible", | ||||
|   "compose_form.spoiler": "Ocultar texto tras advertencia", | ||||
|   "compose_form.spoiler_placeholder": "Advertencia de contenido", | ||||
|   "composer_form.private": "Marcar como privado", | ||||
|   "composer_form.privacy_disclaimer": "Tu estado se mostrará a los usuarios mencionados en {domains}. Tu estado podrá ser visto en otras instancias, quizás no quieras que tu estado sea visto por otros usuarios.", | ||||
|   "compose_form.unlisted": "No mostrar en la historia federada", | ||||
|   "navigation_bar.edit_profile": "Editar perfil", | ||||
|   "navigation_bar.preferences": "Preferencias", | ||||
|   "navigation_bar.community_timeline": "Historia local", | ||||
|   "navigation_bar.public_timeline": "Historia federada", | ||||
|   "navigation_bar.favourites": "Favoritos", | ||||
|   "navigation_bar.blocks": "Usuarios bloqueados", | ||||
|   "navigation_bar.info": "Información adicional", | ||||
|   "navigation_bar.logout": "Cerrar sesión", | ||||
|   "navigation_bar.follow_requests": "Solicitudes para seguirte", | ||||
|   "navigation_bar.mutes": "Usuarios silenciados", | ||||
|   "reply_indicator.cancel": "Cancelar", | ||||
|   "search.placeholder": "Buscar", | ||||
|   "search.account": "Cuenta", | ||||
|   "search.hashtag": "Etiqueta", | ||||
|   "upload_button.label": "Subir multimedia", | ||||
|   "upload_form.undo": "Deshacer", | ||||
|   "notification.follow": "{name} te empezó a seguir", | ||||
|   "notification.favourite": "{name} marcó tu estado como favorito", | ||||
|   "notification.reblog": "{name} ha retooteado tu estado", | ||||
|   "notification.mention": "{name} te ha mencionado", | ||||
|   "notifications.column_settings.alert": "Notificaciones de escritorio", | ||||
|   "notifications.column_settings.show": "Mostrar en columna", | ||||
|   "notifications.column_settings.follow": "Nuevos seguidores:", | ||||
|   "notifications.column_settings.favourite": "Favoritos:", | ||||
|   "notifications.column_settings.mention": "Menciones:", | ||||
|   "notifications.column_settings.reblog": "Retoots:", | ||||
|   "emoji_button.label": "Insertar emoji", | ||||
|   "privacy.public.short": "Público", | ||||
|   "privacy.public.long": "Mostrar en la historia federada", | ||||
|   "privacy.unlisted.short": "Sin federar", | ||||
|   "privacy.unlisted.long": "No mostrar en la historia federada", | ||||
|   "privacy.private.short": "Privado", | ||||
|   "privacy.private.long": "Sólo mostrar a seguidores", | ||||
|   "privacy.direct.short": "Directo", | ||||
|   "privacy.direct.long": "Sólo mostrar a los usuarios mencionados", | ||||
|   "privacy.change": "Ajustar privacidad" | ||||
| }; | ||||
|  | ||||
| export default es; | ||||
| @@ -1,68 +0,0 @@ | ||||
| const fi = { | ||||
|   "column_back_button.label": "Takaisin", | ||||
|   "lightbox.close": "Sulje", | ||||
|   "loading_indicator.label": "Ladataan...", | ||||
|   "status.mention": "Mainitse @{name}", | ||||
|   "status.delete": "Poista", | ||||
|   "status.reply": "Vastaa", | ||||
|   "status.reblog": "Buustaa", | ||||
|   "status.favourite": "Tykkää", | ||||
|   "status.reblogged_by": "{name} buustasi", | ||||
|   "status.sensitive_warning": "Arkaluontoista sisältöä", | ||||
|   "status.sensitive_toggle": "Klikkaa nähdäksesi", | ||||
|   "video_player.toggle_sound": "Äänet päälle/pois", | ||||
|   "account.mention": "Mainitse @{name}", | ||||
|   "account.edit_profile": "Muokkaa", | ||||
|   "account.unblock": "Salli @{name}", | ||||
|   "account.unfollow": "Lopeta seuraaminen", | ||||
|   "account.block": "Estä @{name}", | ||||
|   "account.follow": "Seuraa", | ||||
|   "account.posts": "Postit", | ||||
|   "account.follows": "Seuraa", | ||||
|   "account.followers": "Seuraajia", | ||||
|   "account.follows_you": "Seuraa sinua", | ||||
|   "account.requested": "Odottaa hyväksyntää", | ||||
|   "getting_started.heading": "Aloitus", | ||||
|   "getting_started.about_addressing": "Voit seurata ihmisiä jos tiedät heidän käyttäjänimensä ja domainin missä he ovat syöttämällä e-mail-esque osoitteen Etsi kenttään.", | ||||
|   "getting_started.about_shortcuts": "Jos etsimäsi henkilö on samassa domainissa kuin sinä, pelkkä käyttäjänimi kelpaa. Sama pätee kun mainitset ihmisiä statuksessasi", | ||||
|   "getting_started.open_source_notice": "Mastodon Mastodon on avoimen lähdekoodin ohjelma. Voit avustaa tai raportoida ongelmia GitHub palvelussa {github}. {apps}.", | ||||
|   "column.home": "Koti", | ||||
|   "column.community": "Paikallinen aikajana", | ||||
|   "column.public": "Yleinen aikajana", | ||||
|   "column.notifications": "Ilmoitukset", | ||||
|   "tabs_bar.compose": "Luo", | ||||
|   "tabs_bar.home": "Koti", | ||||
|   "tabs_bar.mentions": "Maininnat", | ||||
|   "tabs_bar.public": "Yleinen aikajana", | ||||
|   "tabs_bar.notifications": "Ilmoitukset", | ||||
|   "compose_form.placeholder": "Mitä sinulla on mielessä?", | ||||
|   "compose_form.publish": "Toot", | ||||
|   "compose_form.sensitive": "Merkitse media herkäksi", | ||||
|   "compose_form.spoiler": "Piiloita teksti varoituksen taakse", | ||||
|   "compose_form.private": "Merkitse yksityiseksi", | ||||
|   "compose_form.privacy_disclaimer": "Sinun yksityinen status toimitetaan mainitsemallesi käyttäjille domaineissa {domains}. Luotatko {domainsCount, plural, one {tähän palvelimeen} other {näihin palvelimiin}}? Postauksen yksityisyys toimii van Mastodon palvelimilla. Jos {domains} {domainsCount, plural, one {ei ole Mastodon palvelin} other {eivät ole Mastodon palvelin}}, viestiin ei tule Yksityinen-merkintää, ja sitä voidaan boostata tai muuten tehdä näkyväksi muille vastaanottajille.", | ||||
|   "compose_form.unlisted": "Älä näytä yleisillä aikajanoilla", | ||||
|   "navigation_bar.edit_profile": "Muokkaa profiilia", | ||||
|   "navigation_bar.preferences": "Ominaisuudet", | ||||
|   "navigation_bar.community_timeline": "Paikallinen aikajana", | ||||
|   "navigation_bar.public_timeline": "Yleinen aikajana", | ||||
|   "navigation_bar.logout": "Kirjaudu ulos", | ||||
|   "reply_indicator.cancel": "Peruuta", | ||||
|   "search.placeholder": "Hae", | ||||
|   "search.account": "Tili", | ||||
|   "search.hashtag": "Hashtag", | ||||
|   "upload_button.label": "Lisää mediaa", | ||||
|   "upload_form.undo": "Peru", | ||||
|   "notification.follow": "{name} seurasi sinua", | ||||
|   "notification.favourite": "{name} tykkäsi statuksestasi", | ||||
|   "notification.reblog": "{name} buustasi statustasi", | ||||
|   "notification.mention": "{name} mainitsi sinut", | ||||
|   "notifications.column_settings.alert": "Työpöytä ilmoitukset", | ||||
|   "notifications.column_settings.show": "Näytä sarakkeessa", | ||||
|   "notifications.column_settings.follow": "Uusia seuraajia:", | ||||
|   "notifications.column_settings.favourite": "Tykkäyksiä:", | ||||
|   "notifications.column_settings.mention": "Mainintoja:", | ||||
|   "notifications.column_settings.reblog": "Buusteja:", | ||||
| }; | ||||
|  | ||||
| export default fi; | ||||
| @@ -1,57 +0,0 @@ | ||||
| const hu = { | ||||
|   "column_back_button.label": "Vissza", | ||||
|   "lightbox.close": "Bezárás", | ||||
|   "loading_indicator.label": "Betöltés...", | ||||
|   "status.mention": "Említés", | ||||
|   "status.delete": "Törlés", | ||||
|   "status.reply": "Válasz", | ||||
|   "status.reblog": "Reblog", | ||||
|   "status.favourite": "Kedvenc", | ||||
|   "status.reblogged_by": "{name} reblogolta", | ||||
|   "status.sensitive_warning": "Érzékeny tartalom", | ||||
|   "status.sensitive_toggle": "Katt a megtekintéshez", | ||||
|   "video_player.toggle_sound": "Hang kapcsolása", | ||||
|   "account.mention": "Említés", | ||||
|   "account.edit_profile": "Profil szerkesztése", | ||||
|   "account.unblock": "Blokkolás levétele", | ||||
|   "account.unfollow": "Követés abbahagyása", | ||||
|   "account.block": "Blokkolás", | ||||
|   "account.follow": "Követés", | ||||
|   "account.posts": "Posts", | ||||
|   "account.follows": "Követve", | ||||
|   "account.followers": "Követők", | ||||
|   "account.follows_you": "Követnek téged", | ||||
|   "getting_started.heading": "Első lépések", | ||||
|   "getting_started.about_addressing": "Követhetsz embereket felhasználónevük és a doménjük ismeretében, amennyiben megadod ezt az e-mail-szerű címet az oldalsáv tetején lévő rubrikában.", | ||||
|   "getting_started.about_shortcuts": "Ha a célzott személy azonos doménen tartózkodik, a felhasználónév elegendő. Ugyanez érvényes mikor személyeket említesz az állapotokban.", | ||||
|   "getting_started.about_developer": "A projekt fejlesztője követhető, mint Gargron@mastodon.social", | ||||
|   "column.home": "Kezdőlap", | ||||
|   "column.mentions": "Említések", | ||||
|   "column.public": "Nyilvános", | ||||
|   "column.notifications": "Értesítések", | ||||
|   "tabs_bar.compose": "Összeállítás", | ||||
|   "tabs_bar.home": "Kezdőlap", | ||||
|   "tabs_bar.mentions": "Említések", | ||||
|   "tabs_bar.public": "Nyilvános", | ||||
|   "tabs_bar.notifications": "Notifications", | ||||
|   "compose_form.placeholder": "Mire gondolsz?", | ||||
|   "compose_form.publish": "Tülk!", | ||||
|   "compose_form.sensitive": "Tartalom érzékenynek jelölése", | ||||
|   "compose_form.unlisted": "Listázatlan mód", | ||||
|   "navigation_bar.edit_profile": "Profil szerkesztése", | ||||
|   "navigation_bar.preferences": "Beállítások", | ||||
|   "navigation_bar.public_timeline": "Nyilvános időfolyam", | ||||
|   "navigation_bar.logout": "Kijelentkezés", | ||||
|   "reply_indicator.cancel": "Mégsem", | ||||
|   "search.placeholder": "Keresés", | ||||
|   "search.account": "Fiók", | ||||
|   "search.hashtag": "Hashtag", | ||||
|   "upload_button.label": "Média hozzáadása", | ||||
|   "upload_form.undo": "Mégsem", | ||||
|   "notification.follow": "{name} követ téged", | ||||
|   "notification.favourite": "{name} kedvencnek jelölte az állapotod", | ||||
|   "notification.reblog": "{name} reblogolta az állapotod", | ||||
|   "notification.mention": "{name} megemlített" | ||||
| }; | ||||
|  | ||||
| export default hu; | ||||
| @@ -1,57 +0,0 @@ | ||||
| import ar from './ar'; | ||||
| import en from './en'; | ||||
| import de from './de'; | ||||
| import es from './es'; | ||||
| import fa from './fa'; | ||||
| import he from './he'; | ||||
| import hr from './hr'; | ||||
| import hu from './hu'; | ||||
| import io from './io'; | ||||
| import it from './it'; | ||||
| import fr from './fr'; | ||||
| import nl from './nl'; | ||||
| import no from './no'; | ||||
| import oc from './oc'; | ||||
| import pt from './pt'; | ||||
| import pt_br from './pt-br'; | ||||
| import uk from './uk'; | ||||
| import fi from './fi'; | ||||
| import eo from './eo'; | ||||
| import ru from './ru'; | ||||
| import ja from './ja'; | ||||
| import zh_hk from './zh-hk'; | ||||
| import zh_cn from './zh-cn'; | ||||
| import bg from './bg'; | ||||
| import id from './id'; | ||||
|  | ||||
| const locales = { | ||||
|   ar, | ||||
|   en, | ||||
|   de, | ||||
|   es, | ||||
|   fa, | ||||
|   he, | ||||
|   hr, | ||||
|   hu, | ||||
|   io, | ||||
|   it, | ||||
|   fr, | ||||
|   nl, | ||||
|   no, | ||||
|   oc, | ||||
|   pt, | ||||
|   'pt-BR': pt_br, | ||||
|   uk, | ||||
|   fi, | ||||
|   eo, | ||||
|   ru, | ||||
|   ja, | ||||
|   'zh-HK': zh_hk, | ||||
|   'zh-CN': zh_cn, | ||||
|   bg, | ||||
|   id, | ||||
| }; | ||||
|  | ||||
| export default function getMessagesForLocale (locale) { | ||||
|   return locales[locale]; | ||||
| }; | ||||
| @@ -1,57 +0,0 @@ | ||||
| const uk = { | ||||
|   "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": "Підписаний", | ||||
|   "getting_started.heading": "Ласкаво просимо", | ||||
|   "getting_started.about_addressing": "Ви можете підписуватись на людей, якщо ви знаєте їх ім'я користувача чи домен, шляхом введення email-подібної адреси у верхньому рядку бокової панелі.", | ||||
|   "getting_started.about_shortcuts": "Якщо користувач, якого ви шукаєте, знаходиться на тому ж домені, що й ви, можна просто ввести ім'я користувача. Це правило стосується й згадування людей у статусах.", | ||||
|   "getting_started.about_developer": "Розробник проекту знаходиться за адресою Gargron@mastodon.social", | ||||
|   "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.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} згадав(-ла) Вас" | ||||
| }; | ||||
|  | ||||
| export default uk; | ||||
| @@ -1,11 +0,0 @@ | ||||
| @font-face { | ||||
|   font-family: 'Montserrat'; | ||||
|   src: local('Montserrat'); | ||||
|   src: font-url('montserrat/Montserrat-Regular.eot'); | ||||
|   src: font-url('montserrat/Montserrat-Regular.eot?#iefix') format('embedded-opentype'), | ||||
|   font-url('montserrat/Montserrat-Regular.woff2') format('woff2'), | ||||
|   font-url('montserrat/Montserrat-Regular.woff') format('woff'), | ||||
|   font-url('montserrat/Montserrat-Regular.ttf') format('truetype'); | ||||
|   font-weight: 400; | ||||
|   font-style: normal; | ||||
| } | ||||
| @@ -1,12 +0,0 @@ | ||||
| @font-face { | ||||
|   font-family: 'Roboto Mono'; | ||||
|   src: local('Roboto Mono'); | ||||
|   src: font-url('roboto-mono/robotomono-regular-webfont.eot'); | ||||
|   src: font-url('roboto-mono/robotomono-regular-webfont.eot?#iefix') format('embedded-opentype'), | ||||
|   font-url('roboto-mono/robotomono-regular-webfont.woff2') format('woff2'), | ||||
|   font-url('roboto-mono/robotomono-regular-webfont.woff') format('woff'), | ||||
|   font-url('roboto-mono/robotomono-regular-webfont.ttf') format('truetype'), | ||||
|   font-url('roboto-mono/robotomono-regular-webfont.svg#roboto_monoregular') format('svg'); | ||||
|   font-weight: 400; | ||||
|   font-style: normal; | ||||
| } | ||||
| @@ -1,52 +0,0 @@ | ||||
| @font-face { | ||||
|   font-family: 'Roboto'; | ||||
|   src: local('Roboto'); | ||||
|   src: font-url('roboto/roboto-italic-webfont.eot'); | ||||
|   src: font-url('roboto/roboto-italic-webfont.eot?#iefix') format('embedded-opentype'), | ||||
|     font-url('roboto/roboto-italic-webfont.woff2') format('woff2'), | ||||
|     font-url('roboto/roboto-italic-webfont.woff') format('woff'), | ||||
|     font-url('roboto/roboto-italic-webfont.ttf') format('truetype'), | ||||
|     font-url('roboto/roboto-italic-webfont.svg#roboto-italic-webfont') format('svg'); | ||||
|   font-weight: normal; | ||||
|   font-style: italic; | ||||
| } | ||||
|  | ||||
| @font-face { | ||||
|   font-family: 'Roboto'; | ||||
|   src: local('Roboto'); | ||||
|   src: font-url('roboto/roboto-bold-webfont.eot'); | ||||
|   src: local('Roboto bold'), local('roboto-bold'), | ||||
|     font-url('roboto/roboto-bold-webfont.eot?#iefix') format('embedded-opentype'), | ||||
|     font-url('roboto/roboto-bold-webfont.woff2') format('woff2'), | ||||
|     font-url('roboto/roboto-bold-webfont.woff') format('woff'), | ||||
|     font-url('roboto/roboto-bold-webfont.ttf') format('truetype'), | ||||
|     font-url('roboto/roboto-bold-webfont.svg#roboto-bold-webfont') format('svg'); | ||||
|   font-weight: bold; | ||||
|   font-style: normal; | ||||
| } | ||||
|  | ||||
| @font-face { | ||||
|   font-family: 'Roboto'; | ||||
|   src: local('Roboto'); | ||||
|   src: font-url('roboto/roboto-medium-webfont.eot'); | ||||
|   src: font-url('roboto/roboto-medium-webfont.eot?#iefix') format('embedded-opentype'), | ||||
|     font-url('roboto/roboto-medium-webfont.woff2') format('woff2'), | ||||
|     font-url('roboto/roboto-medium-webfont.woff') format('woff'), | ||||
|     font-url('roboto/roboto-medium-webfont.ttf') format('truetype'), | ||||
|     font-url('roboto/roboto-medium-webfont.svg#roboto-medium-webfont') format('svg'); | ||||
|   font-weight: 500; | ||||
|   font-style: normal; | ||||
| } | ||||
|  | ||||
| @font-face { | ||||
|   font-family: 'Roboto'; | ||||
|   src: local('Roboto'); | ||||
|   src: font-url('roboto/roboto-regular-webfont.eot'); | ||||
|   src: font-url('roboto/roboto-regular-webfont.eot?#iefix') format('embedded-opentype'), | ||||
|     font-url('roboto/roboto-regular-webfont.woff2') format('woff2'), | ||||
|     font-url('roboto/roboto-regular-webfont.woff') format('woff'), | ||||
|     font-url('roboto/roboto-regular-webfont.ttf') format('truetype'), | ||||
|     font-url('roboto/roboto-regular-webfont.svg#roboto-regular-webfont') format('svg'); | ||||
|   font-weight: normal; | ||||
|   font-style: normal; | ||||
| } | ||||
| @@ -10,7 +10,7 @@ module ApplicationHelper | ||||
|   end | ||||
|  | ||||
|   def add_rtl_body_class(other_classes) | ||||
|     other_classes = "#{other_classes} rtl" if [:ar, :fa].include?(I18n.locale) | ||||
|     other_classes = "#{other_classes} rtl" if [:ar, :fa, :he].include?(I18n.locale) | ||||
|     other_classes | ||||
|   end | ||||
|  | ||||
| @@ -22,4 +22,8 @@ module ApplicationHelper | ||||
|   def title | ||||
|     Rails.env.production? ? site_title : "#{site_title} (Dev)" | ||||
|   end | ||||
|  | ||||
|   def fa_icon(icon) | ||||
|     content_tag(:i, nil, class: 'fa ' + icon.split(' ').map { |cl| "fa-#{cl}" }.join(' ')) | ||||
|   end | ||||
| end | ||||
|   | ||||
| Before Width: | Height: | Size: 339 KiB After Width: | Height: | Size: 339 KiB | 
| Before Width: | Height: | Size: 1.5 MiB After Width: | Height: | Size: 1.5 MiB | 
| Before Width: | Height: | Size: 1.5 MiB After Width: | Height: | Size: 1.5 MiB | 
| Before Width: | Height: | Size: 1.5 MiB After Width: | Height: | Size: 1.5 MiB | 
| Before Width: | Height: | Size: 1.4 MiB After Width: | Height: | Size: 1.4 MiB | 
| Before Width: | Height: | Size: 258 KiB After Width: | Height: | Size: 258 KiB | 
| Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB | 
| Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB | 
| Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 59 KiB | 
| Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 7.6 KiB | 
| Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB | 
| Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB | 
| Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB | 
| Before Width: | Height: | Size: 131 KiB After Width: | Height: | Size: 131 KiB | 
| Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB | 
| Before Width: | Height: | Size: 244 KiB After Width: | Height: | Size: 244 KiB | 
| Before Width: | Height: | Size: 174 B After Width: | Height: | Size: 174 B | 
							
								
								
									
										0
									
								
								app/javascript/mastodon/.gitkeep
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -1,3 +1,4 @@ | ||||
| import React from 'react'; | ||||
| import ImmutablePropTypes from 'react-immutable-proptypes'; | ||||
| import PropTypes from 'prop-types'; | ||||
| import Avatar from './avatar'; | ||||
| @@ -5,6 +6,7 @@ import DisplayName from './display_name'; | ||||
| import Permalink from './permalink'; | ||||
| import IconButton from './icon_button'; | ||||
| import { defineMessages, injectIntl } from 'react-intl'; | ||||
| import ImmutablePureComponent from 'react-immutable-pure-component'; | ||||
| 
 | ||||
| const messages = defineMessages({ | ||||
|   follow: { id: 'account.follow', defaultMessage: 'Follow' }, | ||||
| @@ -14,7 +16,7 @@ const messages = defineMessages({ | ||||
|   unmute: { id: 'account.unmute', defaultMessage: 'Unmute @{name}' } | ||||
| }); | ||||
| 
 | ||||
| class Account extends React.PureComponent { | ||||
| class Account extends ImmutablePureComponent { | ||||
| 
 | ||||
|   constructor (props, context) { | ||||
|     super(props, context); | ||||
| @@ -1,3 +1,4 @@ | ||||
| import React from 'react'; | ||||
| import ImmutablePropTypes from 'react-immutable-proptypes'; | ||||
| 
 | ||||
| const filename = url => url.split('/').pop().split('#')[0].split('?')[0]; | ||||
| @@ -1,7 +1,9 @@ | ||||
| import React from 'react'; | ||||
| import AutosuggestAccountContainer from '../features/compose/containers/autosuggest_account_container'; | ||||
| import ImmutablePropTypes from 'react-immutable-proptypes'; | ||||
| import PropTypes from 'prop-types'; | ||||
| import { isRtl } from '../rtl'; | ||||
| import ImmutablePureComponent from 'react-immutable-pure-component'; | ||||
| 
 | ||||
| const textAtCursorMatchesToken = (str, caretPosition) => { | ||||
|   let word; | ||||
| @@ -28,7 +30,7 @@ const textAtCursorMatchesToken = (str, caretPosition) => { | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| class AutosuggestTextarea extends React.Component { | ||||
| class AutosuggestTextarea extends ImmutablePureComponent { | ||||
| 
 | ||||
|   constructor (props, context) { | ||||
|     super(props, context); | ||||
| @@ -1,21 +1,26 @@ | ||||
| import React from 'react'; | ||||
| import PropTypes from 'prop-types'; | ||||
| 
 | ||||
| class Avatar extends React.PureComponent { | ||||
| 
 | ||||
|   constructor (props, context) { | ||||
|     super(props, context); | ||||
| 
 | ||||
|     this.state = { | ||||
|       hovering: false | ||||
|     }; | ||||
| 
 | ||||
|     this.handleMouseEnter = this.handleMouseEnter.bind(this); | ||||
|     this.handleMouseLeave = this.handleMouseLeave.bind(this); | ||||
|   } | ||||
| 
 | ||||
|   handleMouseEnter () { | ||||
|     if (this.props.animate) return; | ||||
|     this.setState({ hovering: true }); | ||||
|   } | ||||
| 
 | ||||
|   handleMouseLeave () { | ||||
|     if (this.props.animate) return; | ||||
|     this.setState({ hovering: false }); | ||||
|   } | ||||
| 
 | ||||
| @@ -1,3 +1,4 @@ | ||||
| import React from 'react'; | ||||
| import PropTypes from 'prop-types'; | ||||
| 
 | ||||
| class Button extends React.PureComponent { | ||||
| @@ -1,3 +1,4 @@ | ||||
| import React from 'react'; | ||||
| import { Motion, spring } from 'react-motion'; | ||||
| import PropTypes from 'prop-types'; | ||||
| 
 | ||||
| @@ -1,3 +1,4 @@ | ||||
| import React from 'react'; | ||||
| import { FormattedMessage } from 'react-intl'; | ||||
| import PropTypes from 'prop-types'; | ||||
| 
 | ||||
| @@ -1,3 +1,4 @@ | ||||
| import React from 'react'; | ||||
| import { FormattedMessage } from 'react-intl'; | ||||
| import PropTypes from 'prop-types'; | ||||
| 
 | ||||
| @@ -1,3 +1,4 @@ | ||||
| import React from 'react'; | ||||
| import { Motion, spring } from 'react-motion'; | ||||
| import PropTypes from 'prop-types'; | ||||
| 
 | ||||
| @@ -1,3 +1,4 @@ | ||||
| import React from 'react'; | ||||
| import ImmutablePropTypes from 'react-immutable-proptypes'; | ||||
| import escapeTextContentForBrowser from 'escape-html'; | ||||
| import emojify from '../emoji'; | ||||
| @@ -1,3 +1,4 @@ | ||||
| import React from 'react'; | ||||
| import Dropdown, { DropdownTrigger, DropdownContent } from 'react-simple-dropdown'; | ||||
| import PropTypes from 'prop-types'; | ||||
| 
 | ||||