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": [ |   "plugins": [ | ||||||
|  |     "transform-react-jsx-source", | ||||||
|  |     "transform-react-jsx-self", | ||||||
|     "transform-decorators-legacy", |     "transform-decorators-legacy", | ||||||
|     "transform-object-rest-spread" |     "transform-object-rest-spread", | ||||||
|  |     [ | ||||||
|  |       "react-intl", | ||||||
|  |       { | ||||||
|  |         "messagesDir": "./build/messages" | ||||||
|  |       } | ||||||
|  |     ] | ||||||
|   ] |   ] | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										1
									
								
								.foreman
									
										
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1 @@ | ||||||
|  | procfile: Procfile.dev | ||||||
							
								
								
									
										4
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						|  | @ -22,7 +22,7 @@ public/assets | ||||||
| .env | .env | ||||||
| .env.production | .env.production | ||||||
| node_modules/ | node_modules/ | ||||||
| neo4j/ | build/ | ||||||
| 
 | 
 | ||||||
| # Ignore Vagrant files | # Ignore Vagrant files | ||||||
| .vagrant/ | .vagrant/ | ||||||
|  | @ -43,3 +43,5 @@ redis | ||||||
| # Ignore vim files | # Ignore vim files | ||||||
| *~ | *~ | ||||||
| *.swp | *.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 | language: ruby | ||||||
| cache: | cache: | ||||||
|   bundler: true |   bundler: true | ||||||
|   yarn: true |   yarn: false | ||||||
|   directories: |  | ||||||
|     - node_modules |  | ||||||
| dist: trusty | dist: trusty | ||||||
| sudo: false | sudo: false | ||||||
| 
 | 
 | ||||||
|  | @ -42,7 +40,8 @@ install: | ||||||
|   - yarn install |   - yarn install | ||||||
| 
 | 
 | ||||||
| before_script: | before_script: | ||||||
|   - bundle exec rails db:create db:migrate |   - bundle exec rails db:create db:schema:load | ||||||
|  |   - bundle exec rails assets:precompile | ||||||
| 
 | 
 | ||||||
| script: | script: | ||||||
|   - bundle exec rspec |   - bundle exec rspec | ||||||
|  |  | ||||||
							
								
								
									
										15
									
								
								Dockerfile
									
										
									
									
									
								
							
							
						
						|  | @ -10,8 +10,6 @@ EXPOSE 3000 4000 | ||||||
| 
 | 
 | ||||||
| WORKDIR /mastodon | WORKDIR /mastodon | ||||||
| 
 | 
 | ||||||
| COPY Gemfile Gemfile.lock package.json yarn.lock /mastodon/ |  | ||||||
| 
 |  | ||||||
| RUN echo "@edge https://nl.alpinelinux.org/alpine/edge/main" >> /etc/apk/repositories \ | RUN echo "@edge https://nl.alpinelinux.org/alpine/edge/main" >> /etc/apk/repositories \ | ||||||
|  && BUILD_DEPS=" \ |  && BUILD_DEPS=" \ | ||||||
|     postgresql-dev \ |     postgresql-dev \ | ||||||
|  | @ -23,6 +21,7 @@ RUN echo "@edge https://nl.alpinelinux.org/alpine/edge/main" >> /etc/apk/reposit | ||||||
|     $BUILD_DEPS \ |     $BUILD_DEPS \ | ||||||
|     nodejs@edge \ |     nodejs@edge \ | ||||||
|     nodejs-npm@edge \ |     nodejs-npm@edge \ | ||||||
|  |     git \ | ||||||
|     libpq \ |     libpq \ | ||||||
|     libxml2 \ |     libxml2 \ | ||||||
|     libxslt \ |     libxslt \ | ||||||
|  | @ -31,14 +30,14 @@ RUN echo "@edge https://nl.alpinelinux.org/alpine/edge/main" >> /etc/apk/reposit | ||||||
|     imagemagick@edge \ |     imagemagick@edge \ | ||||||
|     ca-certificates \ |     ca-certificates \ | ||||||
|  && npm install -g npm@3 && npm install -g yarn \ |  && 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 \ |  && update-ca-certificates \ | ||||||
|  && apk del $BUILD_DEPS \ |  | ||||||
|  && rm -rf /tmp/* /var/cache/apk/* |  && 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 | 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 'pkg-config' | ||||||
| 
 | 
 | ||||||
| gem 'rails', '~> 5.0.2' |  | ||||||
| gem 'sass-rails', '~> 5.0' |  | ||||||
| gem 'uglifier', '>= 1.3.0' |  | ||||||
| gem 'jquery-rails' |  | ||||||
| gem 'puma' | gem 'puma' | ||||||
|  | gem 'rails', '~> 5.0.2' | ||||||
|  | gem 'uglifier', '>= 1.3.0' | ||||||
| 
 | 
 | ||||||
| gem 'hamlit-rails' | gem 'hamlit-rails' | ||||||
| gem 'pg' | gem 'pg' | ||||||
| gem 'pghero' | gem 'pghero' | ||||||
| gem 'dotenv-rails' | gem 'dotenv-rails' | ||||||
| gem 'font-awesome-rails' |  | ||||||
| gem 'best_in_place', '~> 3.0.1' | gem 'best_in_place', '~> 3.0.1' | ||||||
| 
 | 
 | ||||||
|  | gem 'aws-sdk', '>= 2.0' | ||||||
| gem 'paperclip', '~> 5.1' | gem 'paperclip', '~> 5.1' | ||||||
| gem 'paperclip-av-transcoder' | gem 'paperclip-av-transcoder' | ||||||
| gem 'aws-sdk', '>= 2.0' |  | ||||||
| 
 | 
 | ||||||
| gem 'addressable' | gem 'addressable' | ||||||
| gem 'devise' | gem 'devise' | ||||||
|  | @ -58,18 +55,18 @@ gem 'sprockets-rails', require: 'sprockets/railtie' | ||||||
| gem 'statsd-instrument' | gem 'statsd-instrument' | ||||||
| gem 'twitter-text' | gem 'twitter-text' | ||||||
| gem 'tzinfo-data' | gem 'tzinfo-data' | ||||||
|  | gem 'webpacker', '~>1.2' | ||||||
| gem 'whatlanguage' | gem 'whatlanguage' | ||||||
| 
 | 
 | ||||||
|  | # For some reason the view specs start failing without this | ||||||
| gem 'react-rails' | gem 'react-rails' | ||||||
| gem 'browserify-rails' |  | ||||||
| gem 'autoprefixer-rails' |  | ||||||
| 
 | 
 | ||||||
| group :development, :test do | group :development, :test do | ||||||
|   gem 'rspec-rails' |  | ||||||
|   gem 'pry-rails' |  | ||||||
|   gem 'fuubar' |  | ||||||
|   gem 'fabrication' |   gem 'fabrication' | ||||||
|  |   gem 'fuubar' | ||||||
|   gem 'i18n-tasks', '~> 0.9.6' |   gem 'i18n-tasks', '~> 0.9.6' | ||||||
|  |   gem 'pry-rails' | ||||||
|  |   gem 'rspec-rails' | ||||||
| end | end | ||||||
| 
 | 
 | ||||||
| group :test do | group :test do | ||||||
|  | @ -83,24 +80,23 @@ group :test do | ||||||
| end | end | ||||||
| 
 | 
 | ||||||
| group :development do | 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 'active_record_query_trace' | ||||||
|   gem 'annotate' |   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', '3.8.0' | ||||||
|   gem 'capistrano-rails' |   gem 'capistrano-rails' | ||||||
|   gem 'capistrano-rbenv' |   gem 'capistrano-rbenv' | ||||||
|   gem 'capistrano-yarn' |   gem 'capistrano-yarn' | ||||||
|   gem 'capistrano-faster-assets', '~> 1.0' |  | ||||||
| end | end | ||||||
| 
 | 
 | ||||||
| group :production do | group :production do | ||||||
|  |   gem 'lograge' | ||||||
|   gem 'rails_12factor' |   gem 'rails_12factor' | ||||||
|   gem 'redis-rails' |   gem 'redis-rails' | ||||||
|   gem 'lograge' |  | ||||||
| end | end | ||||||
|  |  | ||||||
							
								
								
									
										43
									
								
								Gemfile.lock
									
										
									
									
									
								
							
							
						
						|  | @ -43,15 +43,13 @@ GEM | ||||||
|       public_suffix (~> 2.0, >= 2.0.2) |       public_suffix (~> 2.0, >= 2.0.2) | ||||||
|     airbrussh (1.2.0) |     airbrussh (1.2.0) | ||||||
|       sshkit (>= 1.6.1, != 1.7.0) |       sshkit (>= 1.6.1, != 1.7.0) | ||||||
|     annotate (2.7.1) |     annotate (2.6.5) | ||||||
|       activerecord (>= 3.2, < 6.0) |       activerecord (>= 2.3.0) | ||||||
|       rake (>= 10.4, < 12.0) |       rake (>= 0.8.7) | ||||||
|     arel (7.1.4) |     arel (7.1.4) | ||||||
|     ast (2.3.0) |     ast (2.3.0) | ||||||
|     attr_encrypted (3.0.3) |     attr_encrypted (3.0.3) | ||||||
|       encryptor (~> 3.0.0) |       encryptor (~> 3.0.0) | ||||||
|     autoprefixer-rails (6.7.7.2) |  | ||||||
|       execjs |  | ||||||
|     av (0.9.0) |     av (0.9.0) | ||||||
|       cocaine (~> 0.5.3) |       cocaine (~> 0.5.3) | ||||||
|     aws-sdk (2.9.12) |     aws-sdk (2.9.12) | ||||||
|  | @ -76,10 +74,6 @@ GEM | ||||||
|       rack (>= 0.9.0) |       rack (>= 0.9.0) | ||||||
|     binding_of_caller (0.7.2) |     binding_of_caller (0.7.2) | ||||||
|       debug_inspector (>= 0.0.1) |       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) |     builder (3.2.3) | ||||||
|     bullet (5.5.1) |     bullet (5.5.1) | ||||||
|       activesupport (>= 3.0.0) |       activesupport (>= 3.0.0) | ||||||
|  | @ -92,8 +86,6 @@ GEM | ||||||
|     capistrano-bundler (1.2.0) |     capistrano-bundler (1.2.0) | ||||||
|       capistrano (~> 3.1) |       capistrano (~> 3.1) | ||||||
|       sshkit (~> 1.2) |       sshkit (~> 1.2) | ||||||
|     capistrano-faster-assets (1.0.2) |  | ||||||
|       capistrano (>= 3.1) |  | ||||||
|     capistrano-rails (1.2.3) |     capistrano-rails (1.2.3) | ||||||
|       capistrano (~> 3.1) |       capistrano (~> 3.1) | ||||||
|       capistrano-bundler (~> 1.1) |       capistrano-bundler (~> 1.1) | ||||||
|  | @ -161,8 +153,6 @@ GEM | ||||||
|     faker (1.7.3) |     faker (1.7.3) | ||||||
|       i18n (~> 0.5) |       i18n (~> 0.5) | ||||||
|     fast_blank (1.0.0) |     fast_blank (1.0.0) | ||||||
|     font-awesome-rails (4.7.0.1) |  | ||||||
|       railties (>= 3.2, < 5.1) |  | ||||||
|     fuubar (2.2.0) |     fuubar (2.2.0) | ||||||
|       rspec-core (~> 3.0) |       rspec-core (~> 3.0) | ||||||
|       ruby-progressbar (~> 1.4) |       ruby-progressbar (~> 1.4) | ||||||
|  | @ -210,10 +200,6 @@ GEM | ||||||
|       rainbow (~> 2.2) |       rainbow (~> 2.2) | ||||||
|       terminal-table (>= 1.5.1) |       terminal-table (>= 1.5.1) | ||||||
|     jmespath (1.3.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) |     json (2.1.0) | ||||||
|     kaminari (1.0.1) |     kaminari (1.0.1) | ||||||
|       activesupport (>= 4.1.0) |       activesupport (>= 4.1.0) | ||||||
|  | @ -257,6 +243,7 @@ GEM | ||||||
|     mimemagic (0.3.2) |     mimemagic (0.3.2) | ||||||
|     mini_portile2 (2.1.0) |     mini_portile2 (2.1.0) | ||||||
|     minitest (5.10.1) |     minitest (5.10.1) | ||||||
|  |     multi_json (1.12.1) | ||||||
|     net-scp (1.2.1) |     net-scp (1.2.1) | ||||||
|       net-ssh (>= 2.6.5) |       net-ssh (>= 2.6.5) | ||||||
|     net-ssh (4.1.0) |     net-ssh (4.1.0) | ||||||
|  | @ -348,8 +335,8 @@ GEM | ||||||
|       thor (>= 0.18.1, < 2.0) |       thor (>= 0.18.1, < 2.0) | ||||||
|     rainbow (2.2.2) |     rainbow (2.2.2) | ||||||
|       rake |       rake | ||||||
|     rake (11.3.0) |     rake (12.0.0) | ||||||
|     react-rails (1.11.0) |     react-rails (2.1.0) | ||||||
|       babel-transpiler (>= 0.7.0) |       babel-transpiler (>= 0.7.0) | ||||||
|       connection_pool |       connection_pool | ||||||
|       execjs |       execjs | ||||||
|  | @ -410,13 +397,6 @@ GEM | ||||||
|       crass (~> 1.0.2) |       crass (~> 1.0.2) | ||||||
|       nokogiri (>= 1.4.4) |       nokogiri (>= 1.4.4) | ||||||
|       nokogumbo (~> 1.4.1) |       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) |     sidekiq (4.2.10) | ||||||
|       concurrent-ruby (~> 1.0) |       concurrent-ruby (~> 1.0) | ||||||
|       connection_pool (~> 2.2, >= 2.2.0) |       connection_pool (~> 2.2, >= 2.2.0) | ||||||
|  | @ -473,6 +453,10 @@ GEM | ||||||
|       addressable (>= 2.3.6) |       addressable (>= 2.3.6) | ||||||
|       crack (>= 0.3.2) |       crack (>= 0.3.2) | ||||||
|       hashdiff |       hashdiff | ||||||
|  |     webpacker (1.2) | ||||||
|  |       activesupport (>= 4.2) | ||||||
|  |       multi_json (~> 1.2) | ||||||
|  |       railties (>= 4.2) | ||||||
|     websocket-driver (0.6.5) |     websocket-driver (0.6.5) | ||||||
|       websocket-extensions (>= 0.1.0) |       websocket-extensions (>= 0.1.0) | ||||||
|     websocket-extensions (0.1.2) |     websocket-extensions (0.1.2) | ||||||
|  | @ -487,15 +471,12 @@ DEPENDENCIES | ||||||
|   active_record_query_trace |   active_record_query_trace | ||||||
|   addressable |   addressable | ||||||
|   annotate |   annotate | ||||||
|   autoprefixer-rails |  | ||||||
|   aws-sdk (>= 2.0) |   aws-sdk (>= 2.0) | ||||||
|   best_in_place (~> 3.0.1) |   best_in_place (~> 3.0.1) | ||||||
|   better_errors |   better_errors | ||||||
|   binding_of_caller |   binding_of_caller | ||||||
|   browserify-rails |  | ||||||
|   bullet |   bullet | ||||||
|   capistrano (= 3.8.0) |   capistrano (= 3.8.0) | ||||||
|   capistrano-faster-assets (~> 1.0) |  | ||||||
|   capistrano-rails |   capistrano-rails | ||||||
|   capistrano-rbenv |   capistrano-rbenv | ||||||
|   capistrano-yarn |   capistrano-yarn | ||||||
|  | @ -507,7 +488,6 @@ DEPENDENCIES | ||||||
|   fabrication |   fabrication | ||||||
|   faker |   faker | ||||||
|   fast_blank |   fast_blank | ||||||
|   font-awesome-rails |  | ||||||
|   fuubar |   fuubar | ||||||
|   goldfinger |   goldfinger | ||||||
|   hamlit-rails |   hamlit-rails | ||||||
|  | @ -517,7 +497,6 @@ DEPENDENCIES | ||||||
|   http_accept_language |   http_accept_language | ||||||
|   httplog |   httplog | ||||||
|   i18n-tasks (~> 0.9.6) |   i18n-tasks (~> 0.9.6) | ||||||
|   jquery-rails |  | ||||||
|   kaminari |   kaminari | ||||||
|   letter_opener |   letter_opener | ||||||
|   letter_opener_web |   letter_opener_web | ||||||
|  | @ -554,7 +533,6 @@ DEPENDENCIES | ||||||
|   rubocop (= 0.46.0) |   rubocop (= 0.46.0) | ||||||
|   ruby-oembed |   ruby-oembed | ||||||
|   sanitize |   sanitize | ||||||
|   sass-rails (~> 5.0) |  | ||||||
|   sidekiq |   sidekiq | ||||||
|   sidekiq-unique-jobs |   sidekiq-unique-jobs | ||||||
|   simple-navigation |   simple-navigation | ||||||
|  | @ -566,6 +544,7 @@ DEPENDENCIES | ||||||
|   tzinfo-data |   tzinfo-data | ||||||
|   uglifier (>= 1.3.0) |   uglifier (>= 1.3.0) | ||||||
|   webmock |   webmock | ||||||
|  |   webpacker (~> 1.2) | ||||||
|   whatlanguage |   whatlanguage | ||||||
| 
 | 
 | ||||||
| RUBY VERSION | 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 |   end | ||||||
| 
 | 
 | ||||||
|   def add_rtl_body_class(other_classes) |   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 |     other_classes | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|  | @ -22,4 +22,8 @@ module ApplicationHelper | ||||||
|   def title |   def title | ||||||
|     Rails.env.production? ? site_title : "#{site_title} (Dev)" |     Rails.env.production? ? site_title : "#{site_title} (Dev)" | ||||||
|   end |   end | ||||||
|  | 
 | ||||||
|  |   def fa_icon(icon) | ||||||
|  |     content_tag(:i, nil, class: 'fa ' + icon.split(' ').map { |cl| "fa-#{cl}" }.join(' ')) | ||||||
|  |   end | ||||||
| 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 ImmutablePropTypes from 'react-immutable-proptypes'; | ||||||
| import PropTypes from 'prop-types'; | import PropTypes from 'prop-types'; | ||||||
| import Avatar from './avatar'; | import Avatar from './avatar'; | ||||||
|  | @ -5,6 +6,7 @@ import DisplayName from './display_name'; | ||||||
| import Permalink from './permalink'; | import Permalink from './permalink'; | ||||||
| import IconButton from './icon_button'; | import IconButton from './icon_button'; | ||||||
| import { defineMessages, injectIntl } from 'react-intl'; | import { defineMessages, injectIntl } from 'react-intl'; | ||||||
|  | import ImmutablePureComponent from 'react-immutable-pure-component'; | ||||||
| 
 | 
 | ||||||
| const messages = defineMessages({ | const messages = defineMessages({ | ||||||
|   follow: { id: 'account.follow', defaultMessage: 'Follow' }, |   follow: { id: 'account.follow', defaultMessage: 'Follow' }, | ||||||
|  | @ -14,7 +16,7 @@ const messages = defineMessages({ | ||||||
|   unmute: { id: 'account.unmute', defaultMessage: 'Unmute @{name}' } |   unmute: { id: 'account.unmute', defaultMessage: 'Unmute @{name}' } | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| class Account extends React.PureComponent { | class Account extends ImmutablePureComponent { | ||||||
| 
 | 
 | ||||||
|   constructor (props, context) { |   constructor (props, context) { | ||||||
|     super(props, context); |     super(props, context); | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | import React from 'react'; | ||||||
| import ImmutablePropTypes from 'react-immutable-proptypes'; | import ImmutablePropTypes from 'react-immutable-proptypes'; | ||||||
| 
 | 
 | ||||||
| const filename = url => url.split('/').pop().split('#')[0].split('?')[0]; | 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 AutosuggestAccountContainer from '../features/compose/containers/autosuggest_account_container'; | ||||||
| import ImmutablePropTypes from 'react-immutable-proptypes'; | import ImmutablePropTypes from 'react-immutable-proptypes'; | ||||||
| import PropTypes from 'prop-types'; | import PropTypes from 'prop-types'; | ||||||
| import { isRtl } from '../rtl'; | import { isRtl } from '../rtl'; | ||||||
|  | import ImmutablePureComponent from 'react-immutable-pure-component'; | ||||||
| 
 | 
 | ||||||
| const textAtCursorMatchesToken = (str, caretPosition) => { | const textAtCursorMatchesToken = (str, caretPosition) => { | ||||||
|   let word; |   let word; | ||||||
|  | @ -28,7 +30,7 @@ const textAtCursorMatchesToken = (str, caretPosition) => { | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| class AutosuggestTextarea extends React.Component { | class AutosuggestTextarea extends ImmutablePureComponent { | ||||||
| 
 | 
 | ||||||
|   constructor (props, context) { |   constructor (props, context) { | ||||||
|     super(props, context); |     super(props, context); | ||||||
|  | @ -1,21 +1,26 @@ | ||||||
|  | import React from 'react'; | ||||||
| import PropTypes from 'prop-types'; | import PropTypes from 'prop-types'; | ||||||
| 
 | 
 | ||||||
| class Avatar extends React.PureComponent { | class Avatar extends React.PureComponent { | ||||||
| 
 | 
 | ||||||
|   constructor (props, context) { |   constructor (props, context) { | ||||||
|     super(props, context); |     super(props, context); | ||||||
|  | 
 | ||||||
|     this.state = { |     this.state = { | ||||||
|       hovering: false |       hovering: false | ||||||
|     }; |     }; | ||||||
|  | 
 | ||||||
|     this.handleMouseEnter = this.handleMouseEnter.bind(this); |     this.handleMouseEnter = this.handleMouseEnter.bind(this); | ||||||
|     this.handleMouseLeave = this.handleMouseLeave.bind(this); |     this.handleMouseLeave = this.handleMouseLeave.bind(this); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   handleMouseEnter () { |   handleMouseEnter () { | ||||||
|  |     if (this.props.animate) return; | ||||||
|     this.setState({ hovering: true }); |     this.setState({ hovering: true }); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   handleMouseLeave () { |   handleMouseLeave () { | ||||||
|  |     if (this.props.animate) return; | ||||||
|     this.setState({ hovering: false }); |     this.setState({ hovering: false }); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | import React from 'react'; | ||||||
| import PropTypes from 'prop-types'; | import PropTypes from 'prop-types'; | ||||||
| 
 | 
 | ||||||
| class Button extends React.PureComponent { | class Button extends React.PureComponent { | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | import React from 'react'; | ||||||
| import { Motion, spring } from 'react-motion'; | import { Motion, spring } from 'react-motion'; | ||||||
| import PropTypes from 'prop-types'; | import PropTypes from 'prop-types'; | ||||||
| 
 | 
 | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | import React from 'react'; | ||||||
| import { FormattedMessage } from 'react-intl'; | import { FormattedMessage } from 'react-intl'; | ||||||
| import PropTypes from 'prop-types'; | import PropTypes from 'prop-types'; | ||||||
| 
 | 
 | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | import React from 'react'; | ||||||
| import { FormattedMessage } from 'react-intl'; | import { FormattedMessage } from 'react-intl'; | ||||||
| import PropTypes from 'prop-types'; | import PropTypes from 'prop-types'; | ||||||
| 
 | 
 | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | import React from 'react'; | ||||||
| import { Motion, spring } from 'react-motion'; | import { Motion, spring } from 'react-motion'; | ||||||
| import PropTypes from 'prop-types'; | import PropTypes from 'prop-types'; | ||||||
| 
 | 
 | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | import React from 'react'; | ||||||
| import ImmutablePropTypes from 'react-immutable-proptypes'; | import ImmutablePropTypes from 'react-immutable-proptypes'; | ||||||
| import escapeTextContentForBrowser from 'escape-html'; | import escapeTextContentForBrowser from 'escape-html'; | ||||||
| import emojify from '../emoji'; | import emojify from '../emoji'; | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | import React from 'react'; | ||||||
| import Dropdown, { DropdownTrigger, DropdownContent } from 'react-simple-dropdown'; | import Dropdown, { DropdownTrigger, DropdownContent } from 'react-simple-dropdown'; | ||||||
| import PropTypes from 'prop-types'; | import PropTypes from 'prop-types'; | ||||||
| 
 | 
 | ||||||